Обмен значений. Исходный текст и текст после 1-го, 2-го и 3-го выполнения макроса. Далее будут примеры посложнее.
Идея приспособить макрос для примитивного программирования появлялась у меня несколько раз. То есть, сделать так, чтобы макрос при запуске "читал" строчку с операцией, интерпретировал ее, что-то делал с данными и переходил к следующей строчке.
На всякий случай напомню: макрос в Notepad++ и в других текстовых редакторах – записанная последовательность действий пользователя над текстом. Макрос можно запускать многократно для быстрого выполнения рутинных операций. Макрос "запоминает" нажатия клавиш и может воспроизводить, например, такие действия:
- Ввод и удаление символов
- Перемещение курсора
- Копирование и вставка
- Поиск в тексте
Сначала это казалось невозможным, ведь макрос слишком "глуп" и прямолинеен:
- Нельзя менять последовательность действий во время выполнения макроса.
- Искомая строка фиксирована — никакой вставки из буфера обмена.
- Нельзя выполнить действие переменное количество раз, а также пропустить действие в зависимости от какого-либо условия.
Для второго пункта нашлось решение – Search -> Find (Volatile) Next (Ctrl+Alt+F3)
. Эта операция ищет выделенное. Благодаря ей, можно совершать динамический переход, в зависимости от выделения. А вот первый пункт казалось невозможно обойти. Получалось, что никак не выполнить такой код:
a = 1
if что-то-там...
Макрос не сможет определить, что в первой строке нужно выполнить присваивание, а во второй совершить условный переход. А это значит, что нужно делать все в одной операции. Как-то так:
//Данные
a:0
//Код
a = 1 goto label1
label1: a = 2 goto label2
Чтобы перейти по метке, нужно использовать поиск выделенного. Но появилась такая проблема – как реализовать условный переход. Очевидно, нужно переходить всегда, но по изменяющимся меткам:
[a]:0
a = 1 goto label[a]
label1:
Значение переменной подставляется вместо [a]
, и получается label1, label2 или label_hello. Так как подстановка должна осуществляться всегда, то для безусловного перехода появилась служебная переменная [] с пустым значением:
[]:
[a]:0
a = 1 goto label1[]
label1: ...
Из-за того что пустое значение нельзя скопировать, пришлось во всех хранилищах переменных добавлять пробел после значения и удалять после подстановки. Неудобно, но не знаю, как сделать лучше. В конечном итоге, строка с операций приобрела следующий вид:
w: w[w]w = w[w[w]w]w w[w]w
Где w – \w*
в регулярном выражении, т. е. состоящее из буквенных и цифровых символов и знаков подчёркивания. Макрос 4 раза осуществляет подстановку переменных, сохраняет значение переменнной и совершает переход.
Принцип работы макроса
Рассмотрим простой пример.
label1: b[index] = [a[]] label2[]
label2:
[]:
[a]:Hello_world
[index]:2
[b2]:
Считаем, что курсор в начале первой строки. Регуляркой \w*\[\w*\]\w*
ищется и выделяется первое вхождение, у нас это b[index]
. Оно копируется и вставляется в конец строки после добавления >>>
:
label1: b[index] = [a[]] label2[]>>>b[index]
После \[\w*\]
добавляется двоеточие, и регуляркой выделяется [index]:
. Далее совершается поиск следующего такого вхождения. Если все корректно, то это место со значением переменной. Значение выделяется и копируется. Производится возврат путем поиска >>>
. Регуляркой находится [index]:
. Вместо этого выражения вставляется значение переменной. Все выражения "оборачивается" в квадратные скобки и к нему добавляется двоеточие для дальнейшего поиска получившегося имени переменной:
label1: b[index] = [a[]] label2[]>>>[b2]:
Дальше аналогично, но для выражения в правой части равенства осуществляется двойная подстановка.
(1) label1: b[index] = [a[]] label2[]>>>[b2]:>>>[a[]]
(2) label1: b[index] = [a[]] label2[]>>>[b2]:>>>[a]
(3) label1: b[index] = [a[]] label2[]>>>[b2]:>>>Hello_world
Запись значения переменной по тому же принципу. И, наконец, осуществляется подстановка для имени метки, и происходит переход по ней.
(1) label1: b[index] = [a[]] label2[]>>>label2[]
(1) label2:
(2) label1: b[index] = [a[]] label2[]>>>label2
(2) label2:
(3) label1: b[index] = [a[]] label2[]>>>label2
(3) >>>label2:
(4) label1: b[index] = [a[]] label2[]
(4) >>>label2:
(5) label1: b[index] = [a[]] label2[]
(5) label2:
Приходится отмечать маркером >>>
метку перехода, чтобы удалить "мусор" в конце строки.
Примеры
Hello, world!
Выполнение макроса зацикливается на первой строчке.
label: out[] = Hello_world[[]] label[]
[out]:Hello_world
[]:
Обмен значений (swap)
l1: t[]=[a[]] l2[]
l2: a[]=[b[]] l3[]
l3: b[]=[t[]] l1[]
[]:
[a]:World
[b]:Hello
[t]:
В начале и после трех запусков макроса:
Вызов подпрограммы
Тот же swap, только вынесенный в отдельную подпрограмму. Конструкция [[swap_var0]]
позволяет получить значение переменной, имя которой находится в swap_var0.
l1: swap_var0[] = a[[]] l2[] //Установка имени 1 переменной
l2: swap_var1[] = b[[]] l3[] //Установка имени 2 переменной
l3: swap_ret[] = l1[[]] swap[] //Установка метки возврата
//и переход в подпрограмму
[]:
[a]:Hello
[b]:World
##### Swap
[swap_var0]:
[swap_var1]:
[swap_ret]:
swap: _swap_temp[] = [[swap_var0]] _swap_2[]
-- private
_swap_2: [swap_var0] = [[swap_var1]] _swap_3[]
_swap_3: [swap_var1] = [_swap_temp[]] [swap_ret]
[_swap_temp]:
#####
Одноразрядный десятичный инкремент
l1: inc__var[] = a[[]] l2[]
l2: inc__ret[] = inc__begin[[]] inc__begin[]
[]:
[a]:0
##### Increment
[inc__var]:a
[inc__ret]:
inc__begin: _inc__val[] = [[inc__var]] _inc[]
-- private
_inc: [inc__var] = [_inc__map[_inc__val]] [inc__ret]
[_inc__val]:
[_inc__map0]:1
[_inc__map1]:2
[_inc__map2]:3
[_inc__map3]:4
[_inc__map4]:5
[_inc__map5]:6
[_inc__map6]:7
[_inc__map7]:8
[_inc__map8]:9
[_inc__map9]:0
#####
Трехразрядный десятичный инкремент
При инкрементации для переноса в старший разряд требуется отслеживать переполнение. Поэтому в подпрограмму инкрементации добавлен второй overflow-выход. Да, метки можно разместить в ряд.
l01: inc__var[] = a[[]] l02[]
l02: inc__ret[] = inc__begin[[]] l03[]
l03: inc__over_ret[] = l11[[]] inc__begin[]
l11: inc__var[] = b[[]] l12[]
l12: inc__ret[] = l01[[]] l13[]
l13: inc__over_ret[] = l21[[]] inc__begin[]
l21: inc__var[] = c[[]] l22[]
l22: inc__ret[] = l01[[]] l23[]
l23: inc__over_ret[] = l01[[]] inc__begin[]
[]:
[c]:0
[b]:0
[a]:0
##### Increment
[inc__var]:
[inc__ret]:
[inc__over_ret]:
inc__begin: _inc__val[] = [[inc__var]] _inc[]
-- private
_inc: [inc__var] = [_inc__map[_inc__val]] i[_inc__val]
i0:i1:i2:i3:i4:i5:i6:i7:i8: _inc__val[] = [_inc__val[]] [inc__ret]
i9: _inc__val[] = [_inc__val[]] [inc__over_ret]
[_inc__val]:
[_inc__map0]:1
[_inc__map1]:2
[_inc__map2]:3
[_inc__map3]:4
[_inc__map4]:5
[_inc__map5]:6
[_inc__map6]:7
[_inc__map7]:8
[_inc__map8]:9
[_inc__map9]:0
#####
Пузырьковая сортировка
И размер массива, и его возможные значения ограничены от 0 до 9. Работает долго, но сортирует. Можно запустить макрос многократно и задать 2000 итераций, тогда выполнение займет порядка минуты. Первоначальная реализация сравнения была очень медленной – каждое число декрементировалось до тех пор, пока одно из них не достигнет 0. Сейчас она некрасивая, но относительно быстрая.
s000: it_remain[] = 8[[]] s010[]
s010: index0[] = 8[[]] s020[]
s020: index1[] = 9[[]] s030[]
//Обмен значений, если первое больше
s030: swap_if__var0[] = array[index0[]] s040[]
s040: swap_if__var1[] = array[index1[]] s050[]
s050: swap_if__ret[] = s060[[]] swap_if__begin[]
//Декремент 1-го индекса
s060: dec__var[] = index1[[]] s070[]
s070: dec__ret[] = s100[[]] s080[]
s080: dec__zero_ret[] = s100[[]] dec__begin[]
//Декремент 2-го индекса
s100: dec__var[] = index0[[]] s110[]
s110: dec__ret[] = s030[[]] s120[]
s120: dec__zero_ret[] = s200[[]] dec__begin[]
//Декремент количества оставшихся прогонов
s200: dec__var[] = it_remain[[]] s210[]
s210: dec__ret[] = s010[[]] s220[]
s220: dec__zero_ret[] = finish[[]] dec__begin[]
[array0]:5
[array1]:3
[array2]:7
[array3]:3
[array4]:2
[array5]:3
[array6]:1
[array7]:2
[array8]:4
[array9]:1
[index0]:
[index1]:
[it_remain]:
##### special
[]:
[stub]:stub
[finished]:no
finish: finished[]=yes[[]] finish[]
#####
##### Swap if not less
[swap_if__var0]:
[swap_if__var1]:
[swap_if__ret]:
swap_if__begin: less__val0[] = [[swap_if__var0]] _swap_if1[]
-- private
_swap_if1: less__val1[] = [[swap_if__var1]] _swap_if2[]
_swap_if2: less__ret0[] = [swap_if__ret[]] _swap_if3[]
_swap_if3: less__ret1[] = _swap_if4[[]] less__begin[]
_swap_if4: _swap__tmp[] = [[swap_if__var0]] _swap_if5[]
_swap_if5: [swap_if__var0] = [[swap_if__var1]] _swap_if6[]
_swap_if6: [swap_if__var1] = [_swap__tmp[]] [swap_if__ret]
[_swap__tmp]:
#####
##### Less
[less__val0]:
[less__val1]:
[less__ret0]:
[less__ret1]:
less__begin: stub[] = [stub[]] _less__[less__val0]
-- private
_less__0: stub[] = [stub[]] s0[less__val1]
_less__1: stub[] = [stub[]] s1[less__val1]
_less__2: stub[] = [stub[]] s2[less__val1]
_less__3: stub[] = [stub[]] s3[less__val1]
_less__4: stub[] = [stub[]] s4[less__val1]
_less__5: stub[] = [stub[]] s5[less__val1]
_less__6: stub[] = [stub[]] s6[less__val1]
_less__7: stub[] = [stub[]] s7[less__val1]
_less__8: stub[] = [stub[]] s8[less__val1]
_less__9: stub[] = [stub[]] [less__ret1]
s01:s02:s03:s04:s05:s06:s07:s08:s09:s12: stub[] = [stub[]] [less__ret0]
s13:s14:s15:s16:s17:s18:s19:s23:s24:s25: stub[] = [stub[]] [less__ret0]
s26:s27:s28:s29:s34:s35:s36:s37:s38:s39: stub[] = [stub[]] [less__ret0]
s45:s46:s47:s48:s49:s56:s57:s58:s59:s67: stub[] = [stub[]] [less__ret0]
s68:s69:s78:s79:s89: stub[] = [stub[]] [less__ret0]
s00:s10:s11:s20:s21:s22:s30:s31:s32:s33: stub[] = [stub[]] [less__ret1]
s40:s41:s42:s43:s44:s50:s51:s52:s53:s54: stub[] = [stub[]] [less__ret1]
s55:s60:s61:s62:s63:s64:s65:s66:s70:s71: stub[] = [stub[]] [less__ret1]
s72:s73:s74:s75:s76:s77:s80:s81:s82:s83: stub[] = [stub[]] [less__ret1]
s84:s85:s86:s87:s88: stub[] = [stub[]] [less__ret1]
#####
##### Decrement
[dec__var]:
[dec__ret]:
[dec__zero_ret]:
dec__begin: _dec__val[] = [[dec__var]] d[_dec__val]
-- private
d1:d2:d3:d4:d5:d6:d7:d8:d9: [dec__var] = [_dec__map[_dec__val]] [dec__ret]
d0: [dec__var] = [_dec__map[_dec__val]] [dec__zero_ret]
[_dec__val]:
[_dec__map0]:9
[_dec__map1]:0
[_dec__map2]:1
[_dec__map3]:2
[_dec__map4]:3
[_dec__map5]:4
[_dec__map6]:5
[_dec__map7]:6
[_dec__map8]:7
[_dec__map9]:8
#####
Установка
Если вам вдруг захотелось попробовать, то в элемент <Macros>
файла %APPDATA%/Notepad++/shortcuts.xml
нужно вставить:
<Macro name="npplang" Ctrl="yes" Alt="yes" Shift="yes" Key="69">
<Action type="3" message="1700" wParam="0" lParam="0" sParam="" />
<Action type="3" message="1601" wParam="0" lParam="0" sParam="\w*\[\w*\]\w*" />
<Action type="3" message="1625" wParam="0" lParam="2" sParam="" />
<Action type="3" message="1702" wParam="0" lParam="768" sParam="" />
<Action type="3" message="1701" wParam="0" lParam="1" sParam="" />
<Action type="0" message="2178" wParam="0" lParam="0" sParam="" />
<Action type="0" message="2451" wParam="0" lParam="0" sParam="" />
<Action type="1" message="2170" wParam="0" lParam="0" sParam=">" />
<Action type="1" message="2170" wParam="0" lParam="0" sParam=">" />
<Action type="1" message="2170" wParam="0" lParam="0" sParam=">" />
<Action type="0" message="2179" wParam="0" lParam="0" sParam="" />
<Action type="3" message="1700" wParam="0" lParam="0" sParam="" />
<Action type="3" message="1601" wParam="0" lParam="0" sParam=">>>" />
<Action type="3" message="1625" wParam="0" lParam="0" sParam="" />
<Action type="3" message="1702" wParam="0" lParam="256" sParam="" />
<Action type="3" message="1701" wParam="0" lParam="1" sParam="" />
<Action type="3" message="1700" wParam="0" lParam="0" sParam="" />
<Action type="3" message="1601" wParam="0" lParam="0" sParam="\[\w*\]" />
<Action type="3" message="1625" wParam="0" lParam="2" sParam="" />
<Action type="3" message="1702" wParam="0" lParam="768" sParam="" />
<Action type="3" message="1701" wParam="0" lParam="1" sParam="" />
<Action type="0" message="2306" wParam="0" lParam="0" sParam="" />
<Action type="1" message="2170" wParam="0" lParam="0" sParam=":" />
<Action type="3" message="1700" wParam="0" lParam="0" sParam="" />
<Action type="3" message="1601" wParam="0" lParam="0" sParam=">>>" />
<Action type="3" message="1625" wParam="0" lParam="0" sParam="" />
<Action type="3" message="1702" wParam="0" lParam="256" sParam="" />
<Action type="3" message="1701" wParam="0" lParam="1" sParam="" />
<Action type="3" message="1700" wParam="0" lParam="0" sParam="" />
<Action type="3" message="1601" wParam="0" lParam="0" sParam="\[\w*\]:" />
<Action type="3" message="1625" wParam="0" lParam="2" sParam="" />
<Action type="3" message="1702" wParam="0" lParam="768" sParam="" />
<Action type="3" message="1701" wParam="0" lParam="1" sParam="" />
<Action type="2" message="0" wParam="43014" lParam="0" sParam="" />
<Action type="0" message="2306" wParam="0" lParam="0" sParam="" />
<Action type="0" message="2452" wParam="0" lParam="0" sParam="" />
<Action type="0" message="2178" wParam="0" lParam="0" sParam="" />
<Action type="3" message="1700" wParam="0" lParam="0" sParam="" />
<Action type="3" message="1601" wParam="0" lParam="0" sParam=">>>" />
<Action type="3" message="1625" wParam="0" lParam="0" sParam="" />
<Action type="3" message="1702" wParam="0" lParam="256" sParam="" />
<Action type="3" message="1701" wParam="0" lParam="1" sParam="" />
<Action type="3" message="1700" wParam="0" lParam="0" sParam="" />
<Action type="3" message="1601" wParam="0" lParam="0" sParam="\[\w*\]:" />
<Action type="3" message="1625" wParam="0" lParam="2" sParam="" />
<Action type="3" message="1702" wParam="0" lParam="768" sParam="" />
<Action type="3" message="1701" wParam="0" lParam="1" sParam="" />
<Action type="0" message="2179" wParam="0" lParam="0" sParam="" />
<Action type="0" message="2326" wParam="0" lParam="0" sParam="" />
<Action type="3" message="1700" wParam="0" lParam="0" sParam="" />
<Action type="3" message="1601" wParam="0" lParam="0" sParam=">>>" />
<Action type="3" message="1625" wParam="0" lParam="0" sParam="" />
<Action type="3" message="1702" wParam="0" lParam="256" sParam="" />
<Action type="3" message="1701" wParam="0" lParam="1" sParam="" />
<Action type="0" message="2306" wParam="0" lParam="0" sParam="" />
<Action type="1" message="2170" wParam="0" lParam="0" sParam="[" />
<Action type="0" message="2451" wParam="0" lParam="0" sParam="" />
<Action type="1" message="2170" wParam="0" lParam="0" sParam="]" />
<Action type="1" message="2170" wParam="0" lParam="0" sParam=":" />
<Action type="0" message="2453" wParam="0" lParam="0" sParam="" />
<Action type="3" message="1700" wParam="0" lParam="0" sParam="" />
<Action type="3" message="1601" wParam="0" lParam="0" sParam="\w*\[\w*\[\w*\]\w*\]\w*" />
<Action type="3" message="1625" wParam="0" lParam="2" sParam="" />
<Action type="3" message="1702" wParam="0" lParam="768" sParam="" />
<Action type="3" message="1701" wParam="0" lParam="1" sParam="" />
<Action type="0" message="2178" wParam="0" lParam="0" sParam="" />
<Action type="0" message="2451" wParam="0" lParam="0" sParam="" />
<Action type="1" message="2170" wParam="0" lParam="0" sParam=">" />
<Action type="1" message="2170" wParam="0" lParam="0" sParam=">" />
<Action type="1" message="2170" wParam="0" lParam="0" sParam=">" />
<Action type="0" message="2179" wParam="0" lParam="0" sParam="" />
<Action type="3" message="1700" wParam="0" lParam="0" sParam="" />
<Action type="3" message="1601" wParam="0" lParam="0" sParam=">>>" />
<Action type="3" message="1625" wParam="0" lParam="0" sParam="" />
<Action type="3" message="1702" wParam="0" lParam="256" sParam="" />
<Action type="3" message="1701" wParam="0" lParam="1" sParam="" />
<Action type="3" message="1700" wParam="0" lParam="0" sParam="" />
<Action type="3" message="1601" wParam="0" lParam="0" sParam="\[\w*\]" />
<Action type="3" message="1625" wParam="0" lParam="2" sParam="" />
<Action type="3" message="1702" wParam="0" lParam="768" sParam="" />
<Action type="3" message="1701" wParam="0" lParam="1" sParam="" />
<Action type="0" message="2306" wParam="0" lParam="0" sParam="" />
<Action type="1" message="2170" wParam="0" lParam="0" sParam=":" />
<Action type="3" message="1700" wParam="0" lParam="0" sParam="" />
<Action type="3" message="1601" wParam="0" lParam="0" sParam=">>>" />
<Action type="3" message="1625" wParam="0" lParam="0" sParam="" />
<Action type="3" message="1702" wParam="0" lParam="256" sParam="" />
<Action type="3" message="1701" wParam="0" lParam="1" sParam="" />
<Action type="3" message="1700" wParam="0" lParam="0" sParam="" />
<Action type="3" message="1601" wParam="0" lParam="0" sParam="\[\w*\]:" />
<Action type="3" message="1625" wParam="0" lParam="2" sParam="" />
<Action type="3" message="1702" wParam="0" lParam="768" sParam="" />
<Action type="3" message="1701" wParam="0" lParam="1" sParam="" />
<Action type="2" message="0" wParam="43014" lParam="0" sParam="" />
<Action type="0" message="2306" wParam="0" lParam="0" sParam="" />
<Action type="0" message="2452" wParam="0" lParam="0" sParam="" />
<Action type="0" message="2178" wParam="0" lParam="0" sParam="" />
<Action type="3" message="1700" wParam="0" lParam="0" sParam="" />
<Action type="3" message="1601" wParam="0" lParam="0" sParam=">>>" />
<Action type="3" message="1625" wParam="0" lParam="0" sParam="" />
<Action type="3" message="1702" wParam="0" lParam="256" sParam="" />
<Action type="3" message="1701" wParam="0" lParam="1" sParam="" />
<Action type="3" message="1700" wParam="0" lParam="0" sParam="" />
<Action type="3" message="1601" wParam="0" lParam="0" sParam="\[\w*\]:" />
<Action type="3" message="1625" wParam="0" lParam="2" sParam="" />
<Action type="3" message="1702" wParam="0" lParam="768" sParam="" />
<Action type="3" message="1701" wParam="0" lParam="1" sParam="" />
<Action type="0" message="2179" wParam="0" lParam="0" sParam="" />
<Action type="0" message="2326" wParam="0" lParam="0" sParam="" />
<Action type="3" message="1700" wParam="0" lParam="0" sParam="" />
<Action type="3" message="1601" wParam="0" lParam="0" sParam=">>>" />
<Action type="3" message="1625" wParam="0" lParam="0" sParam="" />
<Action type="3" message="1702" wParam="0" lParam="256" sParam="" />
<Action type="3" message="1701" wParam="0" lParam="1" sParam="" />
<Action type="3" message="1700" wParam="0" lParam="0" sParam="" />
<Action type="3" message="1601" wParam="0" lParam="0" sParam="\[\w*\]" />
<Action type="3" message="1625" wParam="0" lParam="2" sParam="" />
<Action type="3" message="1702" wParam="0" lParam="768" sParam="" />
<Action type="3" message="1701" wParam="0" lParam="1" sParam="" />
<Action type="0" message="2306" wParam="0" lParam="0" sParam="" />
<Action type="1" message="2170" wParam="0" lParam="0" sParam=":" />
<Action type="3" message="1700" wParam="0" lParam="0" sParam="" />
<Action type="3" message="1601" wParam="0" lParam="0" sParam=">>>" />
<Action type="3" message="1625" wParam="0" lParam="0" sParam="" />
<Action type="3" message="1702" wParam="0" lParam="256" sParam="" />
<Action type="3" message="1701" wParam="0" lParam="1" sParam="" />
<Action type="3" message="1700" wParam="0" lParam="0" sParam="" />
<Action type="3" message="1601" wParam="0" lParam="0" sParam="\[\w*\]:" />
<Action type="3" message="1625" wParam="0" lParam="2" sParam="" />
<Action type="3" message="1702" wParam="0" lParam="768" sParam="" />
<Action type="3" message="1701" wParam="0" lParam="1" sParam="" />
<Action type="2" message="0" wParam="43014" lParam="0" sParam="" />
<Action type="0" message="2306" wParam="0" lParam="0" sParam="" />
<Action type="0" message="2452" wParam="0" lParam="0" sParam="" />
<Action type="0" message="2178" wParam="0" lParam="0" sParam="" />
<Action type="3" message="1700" wParam="0" lParam="0" sParam="" />
<Action type="3" message="1601" wParam="0" lParam="0" sParam=">>>" />
<Action type="3" message="1625" wParam="0" lParam="0" sParam="" />
<Action type="3" message="1702" wParam="0" lParam="256" sParam="" />
<Action type="3" message="1701" wParam="0" lParam="1" sParam="" />
<Action type="3" message="1700" wParam="0" lParam="0" sParam="" />
<Action type="3" message="1601" wParam="0" lParam="0" sParam="\[\w*\]:" />
<Action type="3" message="1625" wParam="0" lParam="2" sParam="" />
<Action type="3" message="1702" wParam="0" lParam="768" sParam="" />
<Action type="3" message="1701" wParam="0" lParam="1" sParam="" />
<Action type="0" message="2179" wParam="0" lParam="0" sParam="" />
<Action type="0" message="2326" wParam="0" lParam="0" sParam="" />
<Action type="3" message="1700" wParam="0" lParam="0" sParam="" />
<Action type="3" message="1601" wParam="0" lParam="0" sParam=">>>" />
<Action type="3" message="1625" wParam="0" lParam="0" sParam="" />
<Action type="3" message="1702" wParam="0" lParam="256" sParam="" />
<Action type="3" message="1701" wParam="0" lParam="1" sParam="" />
<Action type="0" message="2306" wParam="0" lParam="0" sParam="" />
<Action type="0" message="2452" wParam="0" lParam="0" sParam="" />
<Action type="0" message="2178" wParam="0" lParam="0" sParam="" />
<Action type="3" message="1700" wParam="0" lParam="0" sParam="" />
<Action type="3" message="1601" wParam="0" lParam="0" sParam=">>>" />
<Action type="3" message="1625" wParam="0" lParam="0" sParam="" />
<Action type="3" message="1702" wParam="0" lParam="256" sParam="" />
<Action type="3" message="1701" wParam="0" lParam="1" sParam="" />
<Action type="3" message="1700" wParam="0" lParam="0" sParam="" />
<Action type="3" message="1601" wParam="0" lParam="0" sParam=">>>" />
<Action type="3" message="1625" wParam="0" lParam="0" sParam="" />
<Action type="3" message="1702" wParam="0" lParam="256" sParam="" />
<Action type="3" message="1701" wParam="0" lParam="1" sParam="" />
<Action type="3" message="1700" wParam="0" lParam="0" sParam="" />
<Action type="3" message="1601" wParam="0" lParam="0" sParam="\[\w*\]:" />
<Action type="3" message="1625" wParam="0" lParam="2" sParam="" />
<Action type="3" message="1702" wParam="0" lParam="768" sParam="" />
<Action type="3" message="1701" wParam="0" lParam="1" sParam="" />
<Action type="2" message="0" wParam="43014" lParam="0" sParam="" />
<Action type="0" message="2306" wParam="0" lParam="0" sParam="" />
<Action type="0" message="2452" wParam="0" lParam="0" sParam="" />
<Action type="0" message="2179" wParam="0" lParam="0" sParam="" />
<Action type="1" message="2170" wParam="0" lParam="0" sParam=" " />
<Action type="3" message="1700" wParam="0" lParam="0" sParam="" />
<Action type="3" message="1601" wParam="0" lParam="0" sParam=">>>" />
<Action type="3" message="1625" wParam="0" lParam="0" sParam="" />
<Action type="3" message="1702" wParam="0" lParam="256" sParam="" />
<Action type="3" message="1701" wParam="0" lParam="1" sParam="" />
<Action type="3" message="1700" wParam="0" lParam="0" sParam="" />
<Action type="3" message="1601" wParam="0" lParam="0" sParam=">>>" />
<Action type="3" message="1625" wParam="0" lParam="0" sParam="" />
<Action type="3" message="1702" wParam="0" lParam="256" sParam="" />
<Action type="3" message="1701" wParam="0" lParam="1" sParam="" />
<Action type="0" message="2304" wParam="0" lParam="0" sParam="" />
<Action type="0" message="2452" wParam="0" lParam="0" sParam="" />
<Action type="0" message="2180" wParam="0" lParam="0" sParam="" />
<Action type="0" message="2453" wParam="0" lParam="0" sParam="" />
<Action type="3" message="1700" wParam="0" lParam="0" sParam="" />
<Action type="3" message="1601" wParam="0" lParam="0" sParam="\w*\[\w*\]\w*" />
<Action type="3" message="1625" wParam="0" lParam="2" sParam="" />
<Action type="3" message="1702" wParam="0" lParam="768" sParam="" />
<Action type="3" message="1701" wParam="0" lParam="1" sParam="" />
<Action type="3" message="1700" wParam="0" lParam="0" sParam="" />
<Action type="3" message="1601" wParam="0" lParam="0" sParam="\w*\[\w*\]\w*" />
<Action type="3" message="1625" wParam="0" lParam="2" sParam="" />
<Action type="3" message="1702" wParam="0" lParam="768" sParam="" />
<Action type="3" message="1701" wParam="0" lParam="1" sParam="" />
<Action type="3" message="1700" wParam="0" lParam="0" sParam="" />
<Action type="3" message="1601" wParam="0" lParam="0" sParam="\w*\[\w*\]\w*" />
<Action type="3" message="1625" wParam="0" lParam="2" sParam="" />
<Action type="3" message="1702" wParam="0" lParam="768" sParam="" />
<Action type="3" message="1701" wParam="0" lParam="1" sParam="" />
<Action type="0" message="2178" wParam="0" lParam="0" sParam="" />
<Action type="0" message="2451" wParam="0" lParam="0" sParam="" />
<Action type="1" message="2170" wParam="0" lParam="0" sParam=">" />
<Action type="1" message="2170" wParam="0" lParam="0" sParam=">" />
<Action type="1" message="2170" wParam="0" lParam="0" sParam=">" />
<Action type="0" message="2179" wParam="0" lParam="0" sParam="" />
<Action type="3" message="1700" wParam="0" lParam="0" sParam="" />
<Action type="3" message="1601" wParam="0" lParam="0" sParam=">>>" />
<Action type="3" message="1625" wParam="0" lParam="0" sParam="" />
<Action type="3" message="1702" wParam="0" lParam="256" sParam="" />
<Action type="3" message="1701" wParam="0" lParam="1" sParam="" />
<Action type="3" message="1700" wParam="0" lParam="0" sParam="" />
<Action type="3" message="1601" wParam="0" lParam="0" sParam="\[\w*\]" />
<Action type="3" message="1625" wParam="0" lParam="2" sParam="" />
<Action type="3" message="1702" wParam="0" lParam="768" sParam="" />
<Action type="3" message="1701" wParam="0" lParam="1" sParam="" />
<Action type="0" message="2306" wParam="0" lParam="0" sParam="" />
<Action type="1" message="2170" wParam="0" lParam="0" sParam=":" />
<Action type="3" message="1700" wParam="0" lParam="0" sParam="" />
<Action type="3" message="1601" wParam="0" lParam="0" sParam=">>>" />
<Action type="3" message="1625" wParam="0" lParam="0" sParam="" />
<Action type="3" message="1702" wParam="0" lParam="256" sParam="" />
<Action type="3" message="1701" wParam="0" lParam="1" sParam="" />
<Action type="3" message="1700" wParam="0" lParam="0" sParam="" />
<Action type="3" message="1601" wParam="0" lParam="0" sParam="\[\w*\]:" />
<Action type="3" message="1625" wParam="0" lParam="2" sParam="" />
<Action type="3" message="1702" wParam="0" lParam="768" sParam="" />
<Action type="3" message="1701" wParam="0" lParam="1" sParam="" />
<Action type="2" message="0" wParam="43014" lParam="0" sParam="" />
<Action type="0" message="2306" wParam="0" lParam="0" sParam="" />
<Action type="0" message="2452" wParam="0" lParam="0" sParam="" />
<Action type="0" message="2178" wParam="0" lParam="0" sParam="" />
<Action type="3" message="1700" wParam="0" lParam="0" sParam="" />
<Action type="3" message="1601" wParam="0" lParam="0" sParam=">>>" />
<Action type="3" message="1625" wParam="0" lParam="0" sParam="" />
<Action type="3" message="1702" wParam="0" lParam="256" sParam="" />
<Action type="3" message="1701" wParam="0" lParam="1" sParam="" />
<Action type="3" message="1700" wParam="0" lParam="0" sParam="" />
<Action type="3" message="1601" wParam="0" lParam="0" sParam="\[\w*\]:" />
<Action type="3" message="1625" wParam="0" lParam="2" sParam="" />
<Action type="3" message="1702" wParam="0" lParam="768" sParam="" />
<Action type="3" message="1701" wParam="0" lParam="1" sParam="" />
<Action type="0" message="2179" wParam="0" lParam="0" sParam="" />
<Action type="0" message="2326" wParam="0" lParam="0" sParam="" />
<Action type="0" message="2451" wParam="0" lParam="0" sParam="" />
<Action type="1" message="2170" wParam="0" lParam="0" sParam=":" />
<Action type="3" message="1700" wParam="0" lParam="0" sParam="" />
<Action type="3" message="1601" wParam="0" lParam="0" sParam=">>>" />
<Action type="3" message="1625" wParam="0" lParam="0" sParam="" />
<Action type="3" message="1702" wParam="0" lParam="256" sParam="" />
<Action type="3" message="1701" wParam="0" lParam="1" sParam="" />
<Action type="0" message="2306" wParam="0" lParam="0" sParam="" />
<Action type="0" message="2452" wParam="0" lParam="0" sParam="" />
<Action type="2" message="0" wParam="43014" lParam="0" sParam="" />
<Action type="0" message="2304" wParam="0" lParam="0" sParam="" />
<Action type="1" message="2170" wParam="0" lParam="0" sParam=">" />
<Action type="1" message="2170" wParam="0" lParam="0" sParam=">" />
<Action type="1" message="2170" wParam="0" lParam="0" sParam=">" />
<Action type="3" message="1700" wParam="0" lParam="0" sParam="" />
<Action type="3" message="1601" wParam="0" lParam="0" sParam=">>>" />
<Action type="3" message="1625" wParam="0" lParam="0" sParam="" />
<Action type="3" message="1702" wParam="0" lParam="256" sParam="" />
<Action type="3" message="1701" wParam="0" lParam="1" sParam="" />
<Action type="0" message="2452" wParam="0" lParam="0" sParam="" />
<Action type="0" message="2180" wParam="0" lParam="0" sParam="" />
<Action type="3" message="1700" wParam="0" lParam="0" sParam="" />
<Action type="3" message="1601" wParam="0" lParam="0" sParam=">>>" />
<Action type="3" message="1625" wParam="0" lParam="0" sParam="" />
<Action type="3" message="1702" wParam="0" lParam="768" sParam="" />
<Action type="3" message="1701" wParam="0" lParam="1" sParam="" />
<Action type="0" message="2180" wParam="0" lParam="0" sParam="" />
</Macro>
Запуск макроса осуществляется нажатием Ctrl+Shift+Alt+E
.
Заключение
Была мысль создать стек, чтобы отойти от глобальных переменных. Тогда бы появилась возможность реализации рекурсии, например. Но не вижу особого смысла, ведь тут самым интересным было исследовать возможность такого программирования. И вы не представляете, как я был рад, когда заработали первые простые примеры.
Phizio
После таких статей реально понимаешь, насколько программирование в наш век пиара, маркетинга, понтов и пафоса может оставаться хобби и кто-то с удовольствием посвящает ему свободное время Вопрос — это так в вашем случае (хобби) или все же программирование это основной источник дохода?)
Fil
Эта статья, конечно, баловство, примерно как запустить Doom на микроволновке :) Но это потому что очень интересно сделать что-то нестандартное, то что мало кто делал. Но программирование как хобби есть у многих профессиональных программистов, ведь таким образом можно заниматься очень увлекательными вещами, которые на работе скорее всего делать не придется. Кто-то пишет компилятор с нуля вместо готовых анализаторов, другой ОС просто так, или свою реализацию сортировки вместо библиотечной и т. д.
Я программист C++.
MrShoor
Пару лет назад я нечаянно в одном из своих пет проектов превратил JSON в скриптовый язык. Теперь вот ваша статья мотивирует меня написать по этому поводу статью.
Zenitchik
Я тоже чуть не превратил, только потом решил задачу по другому и забил на эту тему.
Может, и мне написать, как я в nodejs превратил разбор аргументов командной строки в форт-подобного монстра?..
MaM
Пишите, почитаем.
FForth
На чём только форто-подобного не делали…
и на bash и на PostScript, не считая разных языков программирования :)
P.S. Некоторые статьи Форт тематики появлятся и сейчас на хабре
https://habrahabr.ru/post/324108/
Zenitchik
Ну, у меня не было цели создавать Форт. Я им вдохновлялся, но за сходством не гнался. Использовал идеи стека для данных и определения одних команд через другие (причем, второе — скорее для фана). В остальном — писалось под задачу. Даже синтаксис не чисто постфиксный — он всё-таки заточен под разбор аргументов.