+-----------------------------------------------------------------------------+
| Описание языка плагинов для программы VISG ( visual and smart GUI builder ) |
| К версии:      0.95                                                         |
| Версия файла:  1.00 ( 9 марта 2008 )                                        |
+-----------------------------------------------------------------------------+

+-----------------------------------------------------------------------------+
| Введение                                                                    |
+-----------------------------------------------------------------------------+

Вся основная функциональность визуального редактора графического интерфейса
пользователя VISG реализована с помощью плагинов (автоматически подключаемых
внешних файлов).

Есть плагины для описания контролов (элементов управления), плагины для
описания окон, плагины для генерации кода, плагины с внутренними данными и
плагины для дополнительной функциональности (к примеру, клонирование внешних
окон тоже реализовано через специальный плагин).

Все плагины это текстовые файлы в двух возможных кодировках: ANSI или Unicode.
Программа сама распознает формат файла (к слову, она это делает по первым двум
байтам файла - для Unicode используются стандартная сигнатура FEFFh).

Поскольку плагины это обычные текстовые файлы, то любой желающий пользователь
может их изменять и тем самым настраивать поведение программы под себя.

+-----------------------------------------------------------------------------+
| Кратко про язык написания плагинов                                          |
+-----------------------------------------------------------------------------+

VISG содержит в себе специальный интерпретатор языка написания плагинов.

Язык плагинов специально разработан для удобства написания генераторов кода
("генератор кода" - это плагин для генерации исходника).

Скрипт на этом языке может оперировать строковыми переменными и списками
из строковых значений. Работа с числами также возможна с помощью специальной
команды вычисления математических выражений (на данный момент поддерживается
32-битная целочисленная арифметика, так как необходимости в вещественных
числах, либо числах с большей разрядностью пока не было).

В языке есть обычный набор операций: циклы, условные операторы, рекурсия.

Скорость выполнения инструкций на данный момент приемлемая для текущих задач.

Интерпретатор не чувствителен к регистру символов, так что IF и if и If - это
одно и то же. При поиске переменных также не учитывается регистр.

При использовании чисел, поддерживается десятичная форма числа, восьмеричная
( 0число ) и шестнадцатиричная ( 0xчисло, 0Xчисло ). Также есть возможность
указывать непосредственно впереди числа его знак ( + или - ).

При указании размеров и координат, поддерживаются диалоговые единицы
длины (dlu). Для этого нужно за числом (непосредственно или через пробел)
указать слово "dlu" (буквы могут иметь любой регистр). Система сама
переконвертирует заданное число в пикселы.

+-----------------------------------------------------------------------------+
| Общий вид и расположение файла-плагина                                      |
+-----------------------------------------------------------------------------+

Файл с плагином должен иметь расширение "vsg" и находиться в директории
visg/plugins. Исключение составляют несколько специальных плагинов, которые
находятся прямо в директории visg.

Пользовательские плагины автоматически подключаются из директории visg/plugins
во время загрузки программы.

Плагин может состоять из нескольких файлов. В этом случае, главный файл
находится в visg/plugins, а включаемые в него файлы - в одной из вложенных
директорий (можно создавать свои вложенные директории без ограничений;
дополнительные файлы подключаются специальной командой).

+-----------------------------------------------------------------------------+
| Общая внутренняя структура файла-плагина                                    |
+-----------------------------------------------------------------------------+

Есть два вида строк в файле-плагине: командная строка и просто строка.

Строки с командами начинаются с символа "процент" (%). После него
непосредственно идет команда, а затем, через пробельные символы, - список
параметров к команде.

Для удобства форматирования кода, строка с командой может начинаться с
символа "%." (процент с точкой без пробелов между ними). Это укажет
интерпретатору пропустить после точки все пробельные символы до имени команды.
Это позволяет делать отступы и формировать удобночитаемый код.

"Просто строки" это текст, который будет копироваться во внешний файл в
процессе генерации исходника, либо игнорироваться для других операций.

Обычная строка может содержать в себе места для вставки значений переменных.
Для этого имя переменной обрамляется одинарными символами процента
(%имя_переменной%). Если же необходима просто вставка символа "процент", то
нужно его продублировать (%%).

Обычная строка может также начинаться с символа "процент" как и командная в
следующих двух случаях:

(1) если нужно использовать значение переменной прямо в начале строки, тогда
нужно написать два символа процента, а затем имя переменной, и завершить имя
еще одним символом процента (%%имя_переменной%)

(2) если обычная строка должна начинаться с символа процент, то следует
поставить вначале строки три символа процента (%%%), которые будут заменены
на один символ "процент" в процессе выполнения скрипта.

Поддерживаются также комментарии. Они начинаются с процента, затем идет
минимум один пробельный символ-разделитель (пробел, табуляция), а затем уже
сам текст комментария до конца строки. Многострочных комментариев нет.

+-----------------------------------------------------------------------------+
| Переменные                                                                  |
+-----------------------------------------------------------------------------+

Имя переменной может быть произвольным. Разрешены любые символы, кроме "%".
Регистр символов в именах переменных не учитывается.

Переменная может иметь одновременно два значения: строковое и списковое.

При создании, переменная инициализирована пустым значением. Все переменные
глобальные, но у скрипта есть возможность задать локальные переменные,
изменения которых не повлияют на глобальные переменные с теми же именами.

Для обозначения/ограничения строковых значений используются кавычки (").

Существует несколько зарезервированных переменных общего назначения:

* nl            : символ конца строки ( 0Ah );
* cr            : 0Dh;
* tab           : символ горизонтальной табуляции;
* quo           : кавычка (");
* apo           : апостроф (');
* bsl           : обратный слэш (\);
* visg_version  : текущая версия программы VISG;
* c_lang        : текущий язык интерфейса программы;
* now           : текущее время и дата;
* this_file     : имя выходного файла;
* this_filename : имя выходного файла без расширения.

+-----------------------------------------------------------------------------+
| Команды                                                                     |
+-----------------------------------------------------------------------------+

Вот полный список встроенных команд скриптового языка программы VISG:

(1) % любой_текст_до_конца_строки

Однострочный комментарий. Многострочные комментарии не поддерживаются.
После знака процента должен быть минимум один пробел, либо табуляция.

(2) %code

Начало кода. Разрешает генерацию исходника со следующей строки. По-умолчанию,
при выполнении скрипта, генерация исходника во внешний файл запрещена. Чтобы
обозначить начало исходника с файле скрипта используется данная команда.

(3) %nocode

Конец кода. Используется для обозначения конца участка, на котором шла
генерация исходника. В пределах одного файла может быть сколько угодно
команд code и nocode.

(4) %set имя_переменной значение

Установить заданной переменной новое строковое значение. Если значение
не содержит пробельных символов, то его можно записать без кавычек ("). Иначе
их нужно использовать. Имя переменной также может быть в кавычках при 
необходимости.

(5) %setex имя_переменной выражение

Расширенная установка значения переменной. Ко второму аргументу применяется
операция "расширения" - раскрываются значения всех входящих в строку
переменных, имена которых были обрамлены знаками процента. Затем полученная
строка записывается в заданную переменную. При необходимости (в случае наличия
пробелов во втором аргументе) второй аргумент можно заключить в кавычки как и
для команды set.

Пример:

%set a hello
%set b " "
%setex c %a%%b%world!
% Теперь в переменной "c" содержится значение "hello world!".
% Либо вот тоже самое, но без переменной "b":
%setex c "%a% world!"

(6) %if выражение
    ...
    %end if

Условный блок. Если выражение истинно, то управление передается внутрь блока,
иначе - блок пропускается. Выражение может быть одним из следующих:

* any_window_exists

Истинно, если создано хотя бы одно пользовательское окно. Вместо этого
условия можно использовать переменную "w.count", которая хранит в себе
общее число пользовательских окон. Таким образом, можно использовать
условие "ifnot w.count == 0".

* child_class_exists имя_класса

Имеет смысл только внутри цикла "for each window". Истинно, если в текущем
окне существует хотя бы один контрол с заданным классом.

* имя_переменной == значение

Истинно, если значение переменной равно заданному.
Сравнение без учета регистра символов.

* имя_переменной1 = имя_переменной2

Истинно, если значения переменных равны друг другу.
Сравнение без учета регистра символов.

* имя_переменной like маска

Истинно, если значение заданной переменной подходит к заданной маске. Маска
это строка, в которой можно использовать специальные символы "?" и "*". Знак
вопроса обозначает один любой символ. Знак "звездочка" обозначает любое
количество любых символов, в том числе и отсутствие символов.

Пример:

%set str "hello world!"
% Условие будет выполнено:
%if str like "h?llo*"
%.  set flag 1
%end if

* имя_переменной1 in имя_переменной2

Истинно, если значение переменной1 можно найти в значении переменной2. То есть,
другими словами, это поиск подстроки - если значение переменной1 это подстрока
значения переменной2, то выражение истинно. Поиск происходит с учетом регистра.

Пример:

%set str "hello world!"
%set llo "llo"
% Условие будет выполнено:
%if llo in str
%.  set flag 1
%end if

* class_exists имя_класса

Выражение истинно, если заданный класс контрола существует хотя бы в одном
пользовательском окне. имя_класса может быть равно звездочке (*), в этом
случае это выражение будет истинно, если есть окно хотя бы с одним контролом.

* any_name_exists

Истинно, если есть хотя бы одно имя символьного идентификатора. Вместо этого
можно использовать переменную "n.count", которая хранит общее число уникальных
символьных идентификаторов. Соответственно,
можно использовать условие "ifnot n.count == 0".

(7) %ifnot выражение
    ...
    %end if

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

(8) %else
    ...
    %end else

Условный блок, использующий в качестве выражения инвертированное значение
последнего вычисленного выражения для команды if/ifnot. Можно использовать
как непосредственно после условного блока if/ifnot .. end if, так и через
несколько команд от него. Запоминается только одно значение выражения для
всех if/not, то есть вложенность тут не поддерживается. Поэтому надо быть
аккуратнее с применением else, чтобы не напутать в логике.

Пример:

% Классический if-then-else:
%set flag 1
%if flag == 1
%.  set flag#2 1
%end if
%else
%.  set flag#2 0
%end else

% А вот специфика:
%set flag 1
%if flag == 1
%.  if flag == 0
%.    set flag#2 0
%.  end if
%end if
%else
%.  set flag#2 "777"
%end else
% Первый if выполнится, затем не выполнится второй if.
% Поэтому запомненное значение логического выражения будет "ложь".
% Поэтому блок else будет выполнен и переменная "flag#2" получит значение 777.

(9) %for тип_цикла
    ...
    %end for

Цикл с предусловием. В начале каждой итерации цикла устанавливается набор
необходимых переменных, определяющих текущее состояние цикла и зависящий
от вида цикла. После последней итерации все эти переменные сохраняют свое
последнее значение, то есть их состояние определено и их можно использовать.
Тип цикла может быть одним из следующих:

* each window

Цикл по каждому пользовательскому окну. Тело цикла выполняется один раз для
каждого пользовательского окна. Общее число окон можно узнать, используя
переменную "w.count". В начале каждой итерации интерпретатор
устанавливает следующий набор переменных, определяющий свойства текущего окна:

  w.index       : индекс текущего окна ( от 0 до w.count-1 );
  w.id          : символьный идентификатор окна ( сейчас не используется );
  w.x           : координата x верхнего левого угла окна;
  w.x.dlu       : координата x в диалоговых единицах длины ( dlu );
  w.y           : координата y верхнего левого угла окна;
  w.y.dlu       : координата y в диалоговых единицах длины ( dlu );
  w.height      : высота окна;
  w.height.dlu  : высота окна в диалоговых единицах длины;
  w.width       : ширина окна;
  w.width.dlu   : ширина окна в диалоговых единицах длины;
  w.style       : целочисленный стиль окна;
  w.style.hex   : стиль окна в шестнадцатиричной форме ( заглавными буквами );
  w.exstyle     : расширенный стиль окна ( целое десятичное число );
  w.exstyle.hex : расширенный стиль окна в шестнадцатиричной форме;
  w.caption     : заголовок окна;
  c.count       : общее число дочерних контролов в окне.

Примечание: использование диалоговых единиц длины ( dlu ) позволяет
делать более переносимый код, так как эти единицы зависят от текущих настроек
системы ( шрифт и т.п. ).

* each control

Цикл по каждому вложенному элементу управления в текущем окне. Имеет смысл
только внутри цикла "for each window". Общее число контролов в окне хранится
в переменной "c.count". В начале каждой итерации устанавливается следующий
набор переменных, определяющих свойства текущего контрола:

  c.index       : индекс текущего контрола ( от 0 до c.count-1 );
  c.id          : символьный идентификатор;
  c.x           : координата x;
  c.x.dlu       : координата x в dlu;
  c.y           : координата y;
  c.y.dlu       : координата y в dlu;
  c.tab_x       : координата x относительно родительской вкладки;
  c.tab_x.dlu   : координата x относительно родительской вкладки в dlu;
  c.tab_y       : координата y относительно родительской вкладки;
  c.tab_y.dlu   : координата y относительно родительской вкладки в dlu;
  c.height      : высота контрола;
  c.height.dlu  : высота контрола в dlu;
  c.width       : ширина контрола;
  c.width.dlu   : ширина контрола в dlu;
  c.style       : целочисленный стиль контрола;
  c.style.hex   : стиль контрола в шестнадцатиричной форме;
  c.exstyle     : расширенный стиль контрола;
  c.exstyle.hex : расширенный стиль контрола в шестнадцатиричной форме;
  c.tab_id      : идентификатор вкладки, на который расположен контрол;
  c.caption     : надпись на контроле;
  c.class       : класс контрола;
  c.alias       : обобщенный символьный тип контрола;
  c.library     : имя библиотеки, которая нужна для данного контрола;
  c.ctltype     : символьный тип контрола;
  c.items       : yes/no - есть ли в контроле вложенные элементы;
  i.count       : число вложенных элементов в контроле.

Примечания:

  - если контрол находится непосредственно на самом окне, а не на вкладке,
    то tab_id = 0, tab_x = x, tab_y = y, tab_x.dlu = x.dlu, tab_y.dlu = y.dlu;

  - поскольку один класс контрола может на практике реализовывать очень разные
    виды контролов, то были введены дополнительные свойства alias и ctltype;

  - alias используется для формирования символьного имени контрола
    по-умолчанию. К примеру, это свойство равно "check" для флажка
    с автоматическим переключением и с ручным. Соответственно,
    идентификаторы для обоих типов контрола будут вида CHECK0, CHECK1 и т.д.;

  - ctltype введен, чтобы гарантированно отличать один вид контрола от другого.
    К примеру, для флажка с автопереключением он равен "checkbox", а для
    флажка с ручным переключением - "m_checkbox";

  - говоря тут о вложенных элементах контрола, имеются ввиду контролы со
    списками строк, контролы с вкладками и т.п. То есть, их вложенный
    элемент это строка текста или вкладка со своими собственными свойствами.

* each item

Цикл по каждому вложенному элементу контрола (вкладки, строки текста,
заголовки таблицы и т.п.). Общее число таких элементов содержится в переменной
"i.count". В начале каждой итерации устанавливается следующий набор переменных,
определяющих свойства текущего элемента:

  i.index     : индекс текущего элемента ( от 0 до i.count-1 );
  i.id        : уникальный целочисленный идентификатор;
  i.width     : ширина элемента в точках;
  i.width.dlu : ширина элемента в диалоговых единицах длины;
  i.caption   : текстовое содержимое.

Примечания:

  - идентификатор есть не у всех элементов. На данный момент, он актуален
    только для вкладок, так как к ним привязаны другие контролы, которые
    ссылаются на свою вкладку свойством "c.tab_id";

  - ширина элемента также актуальна далеко не для всех контролов. Она имеет
    смысл, к примеру, для столбцов таблицы, но не имеет смысла для списка
    строк.

* each name

Цикл по каждому уникальному символьному идентификатору. Общее число символьных
идентификаторов содержится в переменной "n.count". Этот цикл позволяет вставить
в конечную программу объявления всех уникальных символьных идентификаторов.
В начале каждой итерации интерпретатор устанавливает следующий набор
переменных, содержащих свойства текущего идентификатора:

  n.index   : индекс идентификатора ( от 0 до n.count-1 );
  n.caption : текстовое имя идентификатора.

Примечание: символьный идентификатор - это константа, содержащая целочисленный
идентификатор контрола. Скрипт генерации может сам определять какие именно
целочисленные значения получат эти константы. Кроме того, они могут быть
вообще не целочисленные, а такие, какие требует конечный язык программирования,
либо библиотека для создания GUI. Примеры идентификаторов: IDC_BUTTON1,
IDC_CHECK3, IDC_LIST0. По-умолчанию для каждого нового контрола формируется
уникальный в рамках текущего окна идентификатор на основе свойства "c.alias".

* each number имя_переменной

Обычный цикл со счетчиком. Изначально, число итераций содержится в заданной
переменной. Затем, при каждой итерации, значение в заданной переменной
уменьшается на единицу. По достижении нуля цикл прекращается. Таким образом
значение в заданной переменной изменяется от N до 1. Если в начале переменная
содержала в себе число меньше или равное нулю, либо вообще не число, то 
цикл не будет выполняться ни разу. В теле цикла разрешено менять значение
переменной-счетчика, тем самым увеличивая число итераций или уменьшая его.

(10) %break тип_прерывания необязательное_количество

Команда для прерывания исполнения скрипта или части скрипта в зависимости от
параметра "тип_прерывания":

* if     : завершает условный блок ( требуется количество );
* for    : завершает цикл ( требуется количество );
* script : завершает текущий скрипт/файл.

Примечания:

  - количество это число команд "end", которых надо пропустить.

  - если количество не задано или меньше либо равно нуля,
    то используется единица, таким образом будет пропущен один уровень;

  - на данный момент разницы в действии команды с параметрами if и for нет,
    то есть она просто пропустит заданное число команд "end". Однако
    рекомендуется указывать тип последнего end-а в качестве параметра.

Пример:

% ...
%for each item
%.  if i.index == 7
%     Следующая команда break пропустит всё оставшееся тело текущего условия
%     и текущего цикла, пропустив, таким образом, две команды end:
%.    break for 2
%     ...
%.  end if
%   ...
%end for
% Вот тут выполнение продолжится.
% ...

(11) %include имя_файла_без_расширения аргументы_к_скрипту

Команда для запуска файла-скрипта. Первым параметром должна получить
относительный путь к файлу, но без расширения. Расширение всегда
используется "vsg". Все остальные параметры рассматриваются как параметры к
запускаемому скрипту. Они будут помещены в соответствующие переменные: arg1,
arg2, ..., argN. После выполнения заданного скрипта выполнение текущего файла
продолжится. Эту команду можно рассматривать как вызов подпрограммы, код
которой содержится целиком во внешнем файле. При указании пути, вложенные
директории следует разделять знаком "/". Надо помнить, что поскольку все
переменные глобальные, то исполняемый файл сможет изменить значения любых
переменных, даже тех, которые объявлены локальными через команду "local".
Этой командой скрипт может вызывать сам себя, организуя, таким образом,
рекурсию. Глубина рекурсии ограничена только размером стека программы.

(12) %local имена_переменных

Специальная команда для объявления "локальных" переменных. Все переменные
в скриптах VISG по сути глобальные, но эта команда позволяет задать список
переменных, чьи значения будут сохранены, а затем, по выходу из текущего
скрипта, восстановлены. Таким образом, это будут почти что локальные
переменные, так как их изменение не повлияет на их глобальное значение после
того, как скрипт завершит работу. Надо помнить, что эти переменные могут
быть изменены вложенными скриптами, которые вызваны из текущего командой
"include", потому что для вложенных скриптов это глобальные переменные. Эту
команду можно вызывать сколько угодно раз и в любых местах одного файла.

(13) %debug сообщение имя_переменной

Команда предназначена для отладки сценариев. Она открывает текстовую консоль,
если необходимо, а затем выводит туда заданное сообщение и значение заданной
переменной. Затем переходит на новую строку.

(14) %length имя_переменной1 имя_переменной2

Команда помещает длину строкового значения переменной2 в переменную1.

(15) %uppercase имя_переменной

Команда приводит строковое значение заданной переменной к верхнему регистру.

(16) %lowercase имя_переменной

Команда приводит строковое значение заданной переменной к нижнему регистру.

(17) %replace что_ищем на_что_заменить где_искать

Команда для замены подстроки. Все три аргумента - имена переменных. Первый
аргумент задает подстроку для поиска. Второй - подстроку, на которую будет
заменена первая подстрока. А третий - имя переменной, где будет осуществляться
поиск подстроки и замена. Поиск происходит с учетом регистра символов.

(18) %eval имя_переменной строка_с_выражением

Специальная команда для вычисления математических выражений. Работает только
с целыми 32-битными числами со знаком. Вычисляет значение выражения,
переданного во втором аргументе, и заносит это значение в переменную, чье
имя указано в первом аргументе. Поддерживается шестнадцатиричная система
указания числа ( 0xчисло, 0Xчисло ), восьмеричная ( 0число ) и десятичная.
Доступны следующие операции:

* Высокий приоритет:
  - !  : побитовое НЕ;
  - () : скобки;

* Средний приоритет:
  - * : умножение;
  - / : деление;
  - \ : остаток от деления;
  - ^ : возведение в степень;
  - & : побитовое И;

* Низкий приоритет:
  - + : сложение;
  - - : вычитание;
  - > : больше ( при сравнении чисел: 0 - ложь, 1 - истина );
  - < : меньше;
  - = : равно;
  - | : побитовое ИЛИ;
  - ~ : побитовое ИСКЛЮЧАЮЩЕЕ ИЛИ.

Примечание: на данный момент, за отсутствием необходимости в отрицательных
числах, данная функция не понимает префиксной операции "минус", то есть
она непонимает прямого указания отрицательности числа. Вместо этой операции
следует использовать выражение "(0-число)", при необходимости.

(19) %style имя_константы целочисленное_значение

Специальная команда для объявления символического стиля контрола или окна.
Заодно устанавливает значение переменной "имя_константы" в заданное значение
"целочисленное_значение". Используется в плагинах, описывающих соответственно
контролы либо окна. В другого рода плагинах она не имеет смысла и выполняет
только установку значения заданной переменной "имя_константы".

(20) %exstyle имя_константы целочисленное_значение

Эта команда делает все то же самое, что и "style", но нужна для указания
расширенного стиля контролов и окон.

(21) %new тип_создаваемого_объекта

На данный момент нужна только для файлов проектов. Создает заданный вид объекта
( window - новое окно, control - новый контрол, item - новый элемент для
списков, вкладок, таблиц и т.п. ). В других скриптах смысла не имеет. Свойства
для создаваемого объекта получает из соответствующих переменных.

(22) %convert имя_переменной

Конвертирует значение заданной переменной и заносит результат в нее же. Нужна
для конвертации специальных символов. Преобразует следующий символы:

  - 0Ah -> "%NL%";
  - 0Dh -> "%CR%";
  - горизонтальная табуляция -> "%TAB%";
  - кавычка -> "%QUO%";
  - апостроф -> "%APO%";
  - обратный слэш -> "%BSL%".
  - процент -> "%%"

Смысл этой команды в том, чтобы сконвертировать сложный текст со специальными
символами в однострочное значение без этих символов. Есть также специальное
использование этой команды в генераторах исходника - переконвертация таких
специальных символов в символы, принятые в конечном языке программирования.
К примеру, если временно переопределить значение переменной "nl" в "\n",
а "cr" в "\r", то можно заменить все концы строк в заданном тексте на значения,
принятые в языках программирования C/C++. Либо можно переопределить эти
переменные пробелами, и тогда из многострочного текста можно сделать
однострочный для каких-то специальных целей, к примеру, для записи
в однострочный комментарий в исходном тексте генерируемой программы.

(23) %expand имя_переменной_назначения имя_исходной_переменной

Команда для "расширения" значения исходной переменной и записи этого значения
в переменную назначения. Под расширением понимается подстановка значений всех
переменных, входящих в заданную строку и обрамленных символами процента. Данная
команда очень похожа на "setex", но для "setex" второй аргумент должен быть
непосредственно строкой, а для "expand" - именем переменной. Эту команду удобно
использовать для конвертации аргументов, переданных сценарию через команду
"include", если конечно они должны быть сконвертированны. Имена переменных,
переданных этой команде, могут совпадать.

Пример:

% Файл a.vsg
% Выполняем сценарий b.vsg и передаем ему "сложный" аргумент:
%include b "hello%TAB%world!"
% ...

% Файл b.vsg
% Перед дальнейшим выполнением конвертируем значение 1го аргумента:
%expand arg1 arg1
% Теперь переменная "arg1" содержит текст с символом табуляции
% вместо переменной "tab".
% ...

(24) %exec выражение

Специальная команда для выполнения заданной строки как будто бы это обычная
строка скриптового файла, но выполняется эта строка после "расширения".
К примеру, таким образом можно устанавливать значение переменной, чье имя
не известно заранее, но известно имя другой переменной, где находится имя
первой переменной. Следует помнить, что к строке, полученной после расширения,
предъявляются все те же требования, что и к строке файла, то есть, если это
командная строка, то она должна начинаться с символа процента и имени команды
и т.д.

Пример:

%set var_name "dest_var"
%exec "%%set %var_name% %QUO%hello world!%QUO%"
% Теперь в переменной "dest_var" находится значение "hello world!".
% Символы процента продублированы, как это и положено,
% а кавычки заменены на переменные "quo".

(25) %list операция аргументы

Общая команда для работы со списками строк. Аргументы зависят от выбранной
операции. Операция может быть одной из следующих:

* nth переменная_назначения исходная_переменная переменная_с_индексом

Возвращает в переменную назначения элемент заданного списка. Индекс начинается
от нуля. Если заданного элемента списка не существует, то возвращается пустая
строка.

* add переменная_назначения строки

Добавляет к заданной переменной новые строковые элементы. Число добавляемых
элементов не ограничено. Каждый элемент должен быть строкой, имена переменных
тут не поддерживаются.

* length переменная_назначения исходная_переменная_со_списком

Вычисляет длину заданного списка и возвращает его в первую переменную.

* clear имена_переменных

Очищает списковые значения заданных переменных. Нужна потому, что команда
"set" не работает со списками и не может очистить списковое значение
заданной переменной.

+-----------------------------------------------------------------------------+
| Заключение                                                                  |
+-----------------------------------------------------------------------------+

При возникновении любых вопросов, которые не освещены в данном описании,
свяжитесь с автором через один из его сайтов:

  http://mrhx.clan.su/
  http://mrhx.ucoz.com/

+-----------------------------------------------------------------------------+
| (C) 2008 Alexander G. Karpov aka mrhx                                       |
+-----------------------------------------------------------------------------+
