====== Бета-функционал ====== В процессе тестирования весь бета-функционал будет временно собран на этой странице. После окончания тестирования соответствующие разделы переедут на свои места. Некоторые страницы, на которые есть ссылки, могут еще не существовать. ====== Критические изменения ====== В целом, совместимость со старыми скриптами сохраняется, но некоторые изменения в новой версии могут вызвать неработоспособность скрипта: - Строки без кавычек в условиях и выражениях теперь не разрешены по умолчанию. - Убрана команда AutorunBlockUnload. - Убран старый синтаксис FileExists в условиях. - Убрана директива AutorunAllowWriteEnv. - Убрана директива AutorunLoadInSubrocess за отсутствием реальной необходимости. Просьба внимательно прочитать раздел по переходу на новую версию. ===== Как перейти на новую версию ===== **1. Строки без кавычек в условиях и выражениях теперь не разрешены по умолчанию.** Рекомендуется прочитать раздел [[syntax|Синтаксис]] для понимания различий двух видов синтаксиса в Autorun и причин их существования. Можно просто включить [[directives|директиву]] LegacyExpressions, но рекомендуется внести изменения для поддержки актуального режима работы. Необходимо, чтобы все строки в выражениях (в том числе вычисляемых строках) были в кавычках - двойных или одинарных. Некоторые примеры: Было: if %MYVAR% = text then Стало: if MYVAR = "text" then или if %MYVAR% = "text" then Было: if not FileExist(%COMMANDER_PATH%\NoClose.exe) then Стало: if not FileExist("%COMMANDER_PATH%\NoClose.exe") then или if not FileExist(%COMMANDER_PATH% & "\NoClose.exe") then Было: if IniRead(%COMMANDER_INI%, Configuration, LanguageIni) then Стало: if IniRead(%COMMANDER_INI%, "Configuration", "LanguageIni") then или if IniRead(%COMMANDER_INI%, 'Configuration', 'LanguageIni') then Было: %"IniRead(%COMMANDER_INI%, Configuration, LanguageIni)" Стало: %"IniRead(%COMMANDER_INI%, 'Configuration', 'LanguageIni')" или %'IniRead(%COMMANDER_INI%, "Configuration", "LanguageIni")' **2. Убрана команда AutorunBlockUnload** Необходимо внести следующие изменения: Было: AutorunBlockUnload(Yes) Стало: Pragma AutorunBlockUnload **3. Убран командный синтаксис FileExist/ProcessExist в условиях.** Необходимо внести следующие изменения: Было: If FileExist "file" Then Стало: If FileExist("file") Then **4. Убрана директива AutorunAllowWriteEnv** К сожалению, нет другого варианта, кроме как переписать код или использовать старую версию. Работа этой директивы неприменима в новой версии. ====== Синтаксис ====== ===== Командный синтаксис ===== В ранних версиях Autorun, до момента, когда появились условия, использовался только один вид синтаксиса --- командный. Этот вид синтаксиса широко используется для передачи приложению параметров в командной строке и обычно включает в себя список параметров, следующих один за другим, и переключателей, которые могут располагаться в произвольном порядке (в Autorun переключатели должны располагаться до параметров). В примере ниже будет запущена 64-битная версия Total Commander в свернутом состоянии: ShellExec /SW_MINIMIZE "%COMMANDER_PATH%\Totalcmd64.exe" Этот вид синтаксиса использует разделение параметров пробелами, если в тексте параметра содержится пробел --- то параметр берется в кавычки. Также текст параметров может содержать переменные Autorun или переменные окружения, в примере выше %COMMANDER_PATH% --- это переменная окружения, содержащая путь к Total Commander. К плюсам такого синтаксиса можно отнести простоту записи и обработки параметров, возможность в относительно компактной записи реализовывать сложную логику. Но есть и минусы. Если команда должна возвращать значение, такая запись становится неудобной. Также практически невозможно использовать команды напрямую в выражениях (в частности в условиях). Важная особенность записи команд в этом синтаксисе: вычисляемые строки в параметрах выполняются //после// входа в команду. В функциональном синтаксисе выражения в параметрах выполняются //перед// входом в функцию. ===== Функциональный синтаксис ===== Функциональный синтаксис призван решить недостатки командного. Такой способ записи (с вариациями) широко используется в большинстве языков программирования. Пример: p = StrPos("abcdefgh", "cd") В результате в переменную "p" будет записан результат выполнения функции 3 --- позиция подстроки. Функциональный синтаксис удобен для использования в выражениях: в операциях присваивания, условиях, определениях функций. Например: if StrPos("abcdefgh", "cd") = 3 then MsgBox("Yes") В этом коде, если позиция подстроки равна 3, то вызывается команда MsgBox, выдающая сообщение. В отличие от командного синтаксиса использовать переменные прямо в тексте здесь нельзя. Переменная находится в выражении отдельно, что нужно делать с ее значением определяется стоящими рядом операторами: a = 1 b = a + 1 --> b = 2, сложение b = a & 1 --> b = 11, конкатенация (соединение двух строк) ===== Интерпретация функционального синтаксиса ===== Исторически сложилось, что сначала в выражениях строки были "нестрогие", т.е. допускалось написание строк без обрамляющих кавычек (аналогично командному синтаксису). К сожалению, желание сохранить полную совместимость на том этапе привело к проблемам в настоящем и мешало дальнейшему развитию. Поэтому при написании актуальной версии было принято решение поменять настройки интерпретации выражений, но оставить возможность использовать предыдущий вариант как опцию. Интерпретация определяется [[directives|директивой]] LegacyExpressions. При ее наличии будет использоваться старая интерпретация. Различия между актуальной и старой реализацией следующие: Актуальная: - Все строки должны быть кавычках (любых из двух типов) - Переменные в выражениях используются без символов %, но могут быть и заключены в них. - При использовании в выражении отсутствующей переменной выдается ошибка. - Нет неоднозначностей в выражениях. Предыдущая: - Строки могут быть в кавычках (любых из двух типов), либо без кавычек, но только если строка не содержит пробелов и разделителей. - Переменные должны быть заключены в %%. - В случае отсутствия переменной возвращается само имя переменной, ошибок не выдаётся. - Возможны неоднозначности в выражениях, что может привести к сложнодиагностируемым ошибкам. Хотя в целом скрипты будут работоспособны в обоих вариантах, настоятельно рекомендуется использовать актуальный вариант, так как он исключает возможные неопределенности в интерпретации строк и выдает сообщения об ошибках с переменными, что упрощает отладку. Некоторые примеры работы двух интерпретаций: Актуальный a = "zxc" -- ок c = %a% -- ок, присвоит значение a c = a -- ок, присвоит значение a b = StrLen("qwerty") -- ок b = StrLen(%a%) -- ок b = StrLen(a) -- ок b = StrLen(a & "qwerty") -- ок Старый a = "zxc asd" -- ок a = zxc -- ок c = %a% -- ок, присвоит значение a c = a -- ок, присвоит строку "a" b = StrLen(qwerty) -- ок b = StrLen("qwerty") -- ок b = StrLen(%a%) -- ок b = StrLen(a) -- ок, вернет "1", длину строки "a" b = StrLen("qwerty asdf") -- кавычки обязательны, т.к. пробел b = StrLen("qw(er)ty,asdf") -- кавычки обязательны, т.к. в строке есть разделители ",()" b = StrLen(%a% & qwerty) -- ок Пример неоднозначности: While %h% > 0 h = %h% - 1 Wend --> при отсутствии объявленной переменной произойдет немедленный выход из цикла, т.к. будет возвращено "%h%" - строка, которая не приводится к числу, следовательно = 0 ====== Основы ====== Длинные строки могут быть разделены на несколько строк. Для этого используется комбинация пробела с символом подчеркивания " _": MsgBox("Text", _ "Title") При слиянии строк комбинация " _" (в том числе пробел) убирается. ====== Директивы ====== Pragma Include Загружает дополнительный файл со скриптом в формате Autorun. Это может быть библиотека нужных пользовательских функций, или основной скрипт Autorun, вынесенный в другое место. Путь может быть относительным каталога Autorun, в нем также могут использоваться переменные окружения (но не внутренние переменные!). Обратите внимание, что загрузка происходит на этапе препроцессинга, а значит, условия здесь еще не работают. Pragma IncludeOnce Директива может находиться в начале подключаемого файла (в основном скрипте смысла не имеет). Сообщает препроцессору, что содержимое файла должно быть вставлено только один раз, что помогает избежать дублирования определения функций. Если директива отсутствует, содержимое файла будет вставлено столько раз, сколько будет встречена директива Include с именем этого файла. ----- ====== Циклы ====== В Autorun реализовано два типа циклов. ===== For .. Next ===== Простой цикл с предварительно заданными условиями. Шаг по умолчанию равен 1. Шаг может быть отрицательным. For var = To [Step ] ... Next **Пример** For var = 1 To 4 MsgBox(var) --> 1 --> 2 --> 3 --> 4 Next ===== While.. Wend ===== Цикл по условию. Выполняется, пока условие истинно. While ... Wend **Пример** var = 3 While var > 0 MsgBox(var) --> 3 --> 2 --> 1 var = var - 1 Next В циклах могут быть использованы ключевые слова Break и Continue для управления потоком выполнения. var = 3 While True var = var + 1 If var < 10 Then Continue Break Next var --> 10 :!: Внимание! Не создавайте пустых циклов и долго выполняющихся циклов без использования задержки. Это может привести к повышенной нагрузке на процессор. ----- ====== Переменные ====== Переменные в Autorun могут быть глобальные и локальные. Локальные переменные имеют смысл только внутри функций. Global [Const] Var1 [= expr] [, Var2 [= expr] .. [, VarN [= expr]] Local [Const] Var1 [= expr] [, Var2 [= expr] .. [, VarN [= expr]] Const Var1 [= expr] [, Var2 [= expr] .. [, VarN [= expr]] **Global** - переменная будет глобальной. В основном теле скрипта может быть опущена, т.к. в нем переменные всегда глобальные. В функции принудительно устанавливает глобальный диапазон действия переменной. Если переменной с таким именем еще не было в глобальном диапазоне, то она создается, если была - устанавливается новое значение. **Local** - переменная будет локальной. В основном теле скрипта смысла не имеет. В функции принудительно устанавливает локальный диапазон действия переменной, что позволяет перекрыть глобальную переменную с тем же именем. **Const** - переменная будет константой. В основном имеет смысл использовать совместно с Global и/или в основном теле скрипта, поскольку значение локальной переменной исчезает при выходе из функции. После первичного создания переменной значение константы изменить нельзя. Также возможно задавать переменные без предварительного определения: Var1 = expr Var2 = expr Если ключевые слова не заданы, то правила следующие: при присваивании переменной в функции, если переменная с тем же именем существует в глобальном диапазоне, то значение присваивается ей. Если не существует, то создается локальная переменная. var1 = 1 var2 = 1 MyFunc() Func MyFunc() Local var1 = 123 var2 = 123 Global var3 = 123 var4 = 123 Local var5 = 123 EndFunc var1 --> 1 var2 --> 123 var3 --> 123 var4 --> undefined var5 --> undefined ----- ====== Функции ====== Пользовательские функции задаются с помощью ключевых слов Func с последующим именем функции и списком параметров в скобках, и EndFunc. Параметры разделяются запятой. Вызов функции производится по имени аналогично вызову любой встроенной функции или команды. Если имя вызываемой функции неизвестно на этапе запуска, вызов можно производить с помощью функции Call или Eval. В функциях могут быть заданы 4 вида формальных параметров: * Простой параметр * Параметр "по ссылке" * Параметр со значением по умолчанию * Открытый список параметров === Простой параметр === Простой параметр задается просто именем переменной. Значение актуального параметра будет вычисляться перед передачей в функцию. MyFunc(123+456) Func MyFunc(var) MsgBox(var) --> 579 EndFunc === Параметр "по ссылке" === Этот тип параметра дает возможность функции возвращать назад измененный параметр. Это удобно использовать, чтобы уменьшить число глобальных переменных, что в свою очередь уменьшает число возможных ошибок. Этот параметр задается просто именем переменной. Но значение актуального параметра должно также быть переменной, иначе будет выдано сообщение об ошибке. Значение актуальной переменной будет вычисляться перед передачей в функцию, и функция может его изменить. a = 1 MsgBox(a) --> 1 MyFunc(a) Func MyFunc(ByRef var) MsgBox(var) --> 1 var = 123 EndFunc MsgBox(a) --> 123 === Параметр со значением по умолчанию === Этот параметр задается именем переменной с присвоением значения по умолчанию. Это позволяет опускать при вызове функции часть параметров. Параметры этого типа должны идти после параметров двух предыдущих типов, но перед открытым списком параметров. Если актуальный параметр будет задан, то переменной будет присвоено его значение, если опущен - будет присвоено значение по умолчанию. MyFunc("text") MyFunc("text", "My title") Func MyFunc(var1, var2 = "Default title") MsgBox(var1) --> text MsgBox(var2) --> Default title --> My title EndFunc === Открытый список параметров === Параметр задается специальным значением "..." и позволяет задавать неограниченный список входных параметров. Этот параметр должен находиться в самом конце списка формальных параметров, всё что после него будет проигнорировано. Получение параметра производится с помощью функции Args: MyFunc(123, 456, 789) Func MyFunc(...) For i = 1 To Args() MsgBox(Args(i), i) --> 123 --> 456 --> 789 Next EndFunc Выход из функции производится по достижении ее конца, либо путем использования ключевого слова Return с возвращаемым значением. Если выход из функции происходит без посредства Return, возвращаемое значение --- пустая строка. r = MyFunc(1) r --> Positive Func MyFunc(var) If var > 0 Then Return "Positive" ElseIf var < 0 Then Return "Negative" Else Return "Zero" EndIf EndFunc ----- ====== Args ====== Функция предназначена для получения параметров функции, переданных открытым списком. Args([индекс]) **Параметры** |< 100% 15% >| |индекс|Индекс получаемого параметра. Начинается с 1. Если опущен, возвращается число переданных параметров.| ----- ====== Call ====== Call FuncName [ Param1 [ Param2 .. [ ParamN]]] Call("FuncName" [, Param1 [, Param2, .. [, ParamN]]]) **Параметры** |< 100% 15% >| |FuncName|Имя вызываемой функции.| |Param|Имя вызываемой функции.| **Возвращаемое значение** Значение, возвращаемое функцией, имя которой задано первым параметром (только в функциональной записи). **Пример** a = "MsgBox" Call(a, "Text", "Title") **Примечания** Используйте эту функцию только при необходимости вызова функции или команды, имя которой нужно передавать в переменной (т.е. на этапе написания скрипта не определено, какую именно функцию нужно будет запускать). В остальных случаях предпочтительнее прямой вызов функции. ----- ====== Eval ====== Вычисляет выражение, заданное строкой. Eval "expression" Eval("expression") **Параметры** |< 100% 15% >| |"expression"|Строка с вычисляемым выражением.| **Возвращаемое значение** Значение, полученное в результате вычисления заданного строкой выражения (только в функциональной записи). **Пример** a = 4 Eval("1+2+3+a") -- > 10 **Примечания** Функция также может выполнять другие функции, заданные в строке. Используйте эту функцию только при необходимости вычисления выражения, заданного строкой. В остальных случаях предпочтительнее прямая запись выражения.