20 марта в 17:30

Ненормальное программирование: макрос-интерпретатор в Notepad++

swap


Обмен значений. Исходный текст и текст после 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, только вынесенный в отдельную подпрограмму. Конструкция [[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="&gt;" />
            <Action type="1" message="2170" wParam="0" lParam="0" sParam="&gt;" />
            <Action type="1" message="2170" wParam="0" lParam="0" sParam="&gt;" />
            <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="&gt;&gt;&gt;" />
            <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="&gt;&gt;&gt;" />
            <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="&gt;&gt;&gt;" />
            <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="&gt;&gt;&gt;" />
            <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="&gt;" />
            <Action type="1" message="2170" wParam="0" lParam="0" sParam="&gt;" />
            <Action type="1" message="2170" wParam="0" lParam="0" sParam="&gt;" />
            <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="&gt;&gt;&gt;" />
            <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="&gt;&gt;&gt;" />
            <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="&gt;&gt;&gt;" />
            <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="&gt;&gt;&gt;" />
            <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="&gt;&gt;&gt;" />
            <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="&gt;&gt;&gt;" />
            <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="&gt;&gt;&gt;" />
            <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="&gt;&gt;&gt;" />
            <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="&gt;&gt;&gt;" />
            <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="&gt;&gt;&gt;" />
            <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="&gt;&gt;&gt;" />
            <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="&gt;" />
            <Action type="1" message="2170" wParam="0" lParam="0" sParam="&gt;" />
            <Action type="1" message="2170" wParam="0" lParam="0" sParam="&gt;" />
            <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="&gt;&gt;&gt;" />
            <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="&gt;&gt;&gt;" />
            <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="&gt;&gt;&gt;" />
            <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="&gt;&gt;&gt;" />
            <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="&gt;" />
            <Action type="1" message="2170" wParam="0" lParam="0" sParam="&gt;" />
            <Action type="1" message="2170" wParam="0" lParam="0" sParam="&gt;" />
            <Action type="3" message="1700" wParam="0" lParam="0" sParam="" />
            <Action type="3" message="1601" wParam="0" lParam="0" sParam="&gt;&gt;&gt;" />
            <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="&gt;&gt;&gt;" />
            <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.


Заключение


Была мысль создать стек, чтобы отойти от глобальных переменных. Тогда бы появилась возможность реализации рекурсии, например. Но не вижу особого смысла, ведь тут самым интересным было исследовать возможность такого программирования. И вы не представляете, как я был рад, когда заработали первые простые примеры.

Филипп Володин @Fil
карма
424,6
рейтинг 0,1
Пользователь
Похожие публикации
Самое читаемое Разработка

Комментарии (9)

  • +2
    После таких статей реально понимаешь, насколько программирование в наш век пиара, маркетинга, понтов и пафоса может оставаться хобби и кто-то с удовольствием посвящает ему свободное время Вопрос — это так в вашем случае (хобби) или все же программирование это основной источник дохода?)
    • +2

      Эта статья, конечно, баловство, примерно как запустить Doom на микроволновке :) Но это потому что очень интересно сделать что-то нестандартное, то что мало кто делал. Но программирование как хобби есть у многих профессиональных программистов, ведь таким образом можно заниматься очень увлекательными вещами, которые на работе скорее всего делать не придется. Кто-то пишет компилятор с нуля вместо готовых анализаторов, другой ОС просто так, или свою реализацию сортировки вместо библиотечной и т. д.
      Я программист C++.

      • 0
        Пару лет назад я нечаянно в одном из своих пет проектов превратил JSON в скриптовый язык. Теперь вот ваша статья мотивирует меня написать по этому поводу статью.
        • 0
          превратил JSON в скриптовый язык

          Я тоже чуть не превратил, только потом решил задачу по другому и забил на эту тему.

          Может, и мне написать, как я в nodejs превратил разбор аргументов командной строки в форт-подобного монстра?..
          • 0
            Пишите, почитаем.
          • 0
            На чём только форто-подобного не делали…
            и на bash и на PostScript, не считая разных языков программирования :)

            P.S. Некоторые статьи Форт тематики появлятся и сейчас на хабре
            https://habrahabr.ru/post/324108/
            • 0
              Ну, у меня не было цели создавать Форт. Я им вдохновлялся, но за сходством не гнался. Использовал идеи стека для данных и определения одних команд через другие (причем, второе — скорее для фана). В остальном — писалось под задачу. Даже синтаксис не чисто постфиксный — он всё-таки заточен под разбор аргументов.
  • +1
    Не могу понять, это после наркотиков или вместо? :-D
    • 0
      … я знал, что когда-нибудь мы перейдём и на эту дрянь (с)
      Я совместил в ОДНОМ файле скрипты для bash(linux), bat(win), powershell(win). И все работают. Скажите, это можно вылечить? или я уже прочно «на игле»? :-)

Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.