Перейти на главную страничку сайта (список статей, файлы для скачивания)

ФОРУМ (здесь можно обсудить эту статью, а также саму программу AutoHotkey и проблемы её использования)

Проект перевода документации AutoHotkey: перечень переведённых статей и статей в работе.

Как передавать скрипту параметры командной строки

Автор статьи - Androgen Belkin


Здесь я изложу несколько способов передачи скрипту каких-нибудь параметров. Справка AutoHotkey на эту тему, на мой взгляд, вопиюще скупа. Оговорюсь, что предлагаемые ниже варианты - не полноценные скрипты, а, скорее, идеи. Но опираться на них и использовать в качестве шаблончиков вполне можно.

В качестве введения: обычно, программа считается продвинутой, если может использоваться с параметрами командной строки. И чем больше параметров может принять такая прога, тем она продвинутей. (Скажем, консольная версия всем известного RAR'а имеет больше ста (!) команд и ключей). И, конечно, чем больше параметров какой-нибудь проги может использовать юзер, тем, (обычно) продвинутей юзер этой самой проги. А всякий, кто способен написать скрипт, если уж не супер-мега-продвинутый (где-то есть и такие), то, как минимум - "непростой". Больше того, скриптописатель уже даже вроде и программер (а некоторые - и безо всякого "вроде"), а скрипты - уже программы. Вот и научим наши программы принимать всякие параметры.

Зачем и когда это может понадобиться? Вот несколько примеров:

Ну, и т.д.

Внимание: Как известно, AutoHotkey распространяется в виде архива (zip), и в виде инсталлятора (ехе). Если вы использовали не инсталлятор, а zip-архив, и просто связали файлы с расширением *.ahk с AutoHotkey.exe, то в реестре у вас будет функционально урезанная команда на исполнение скрипта. Такая команда не позволяет скрипту принимать параметры непосредственно. Т.е. если вы захотите передать скрипту параметры, то перед полным путем к скрипту, должны будете указать полный путь к AutoHotkey.exe. Примерно так:

"C:\Program Files\AutoHotkey\AutoHotkey.exe" "D:\AHK\Param2Script.ahk" /orange /apple /test

Чтобы иметь возможность передавать скрипту параметры напрямую, без указания полного пути к AutoHotkey.exe (как это и описано далее), нужно либо использовать стандартный инсталлятор, либо воспользоваться вот этой статьей. Там подробно рассмотрена разница между zip и ехе версиями, и приведен скрипт, исправляющий эту проблему.

Итак, прежде чем мы перейдем к различным вариантам передачи параметров скрипту, определимся с терминами. Как указано в справке AutoHotkey, "ПАРАМЕТРАМИ может быть любая строка, которую мы передаем скрипту" (даже самая бессмысленная). Разделителем параметров считается, как обычно, пробел. Такой подход вряд ли можно назвать инструментальным, поэтому, я предлагаю ввести дополнительные понятия и инструменты, которые и составят синтаксис параметров командной строки. Итак, внутри ПАРАМЕТРОВ могут быть:

КЛЮЧИ - модификаторы, изменяющие поведение скрипта;

ИМЕНА - имена передаваемых скрипту для обработки файлов/папок, могут содержать полный или относительный путь.

Разумеется, этот синтаксис условен, и конечно, вы вольны изобрести свой собственный синтаксис.

Далее, обращаю ваше особое внимание на то, что в AutoHotkey синтаксис обработки принимаемых скриптом параметров отличается от синтаксиса, принятого для других команд и операций. Я их оформил в виде примечаний, чтобы на них легче было ссылаться:

Возможно, это просто глюк AutoHotkey, а может где-то в справке так и написано, просто я не нашел, а может и вовсе я что-то не так понял. Однако в таком виде все работает. Альтернативой указанному использованию параметров в выражениях является присвоение содержимого "числовых" переменных, обычной "буквенной" переменной, и использование в выражениях уже этой переменной. Так получится чуть длиннее, но зато сохранится привычный синтаксис.

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

Ну, поехали. Вот мы запускаем скрипт с ключами. В зависимости от их наличия скрипт будет выполнять разные действия. Это может выглядеть так (пути, как всегда, указываете свои):

"D:\AHK\Param2Script.ahk" /orange /apple /test

или так

"D:\AHK\Param2Script.ahk" -orange -apple –test

или даже так

"D:\AHK\Param2Script.ahk" /orange /apple –test

Слова orange, apple и test - ключи. Теперь нам нужно эти ключи извлечь. Сначала простой вариант. Я использовал идею, взятую у чела с ником Ace_NoOne из его скриптика "processing command line parameters" (http://autohotkey.com/forum/viewtopic.php?p=44748). Его скрипт я немного модернизировал, расширив извлечение ключей.

; Поиск в параметрах ключей (модификаторов действий скрипта)
If 0 > 0 ; если параметры есть (см. Примечание 1 выше. Будет верным написать и так If %0% > 0), то...
{
    Loop, %0% ; обработать все переданные параметры
    {
        Param := %A_Index% ; получаем значение текущего параметра (см. Примечание 2 и 3)
        ; берем 1-й символ параметра (проверяем наличие ключа)
        StringLeft, Switch_Pointer, Param, 1
        ; если параметр начинается с "-" или с "/" (указатели на ключ), то...
        If ( Switch_Pointer = "-" OR Switch_Pointer = "/" )
        {
            ; берем остальную часть строки (получаем сам ключ)
            StringMid, Switch, Param, 2, StrLen( Param )
            ; (ВНИМАНИЕ: укажите здесь желаемое имя ключа) если ключ имеет нужное имя, то...
            If Switch = orange
                ; назначаем любую переменную, в которой будет указано, что параметр получен
                Switch1 := Switch
            ; (ВНИМАНИЕ: укажите здесь желаемое имя ключа) если ключ имеет нужное имя, то...
            If Switch = apple
                ; назначаем любую переменную, в которой будет указано, что параметр получен
                Switch2 := Switch
            ; и т.д.
        }
    }
}
 
; Обработка полученных ключей
If Switch1 ; если ключ был получен, то...
    MsgBox, Скрипт запущен с ключом Switch1 = "%Switch1%"
If Switch2 ; если ключ был получен, то...
    MsgBox, Скрипт запущен с ключом Switch2 = "%Switch2%"

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

; Задаем список допустимых ключей
pSwitches = orange,apple,test ; (без пробелов после запятой)
 
; Поиск в параметрах ключей (модификаторов действий скрипта)
If 0 > 0 ; если параметры есть (см. Примечание 1), то...
{
    Loop, %0% ; обработать все переданные параметры
    {
        ; получаем значение текущего параметра (см. Примечание 2 и 3)
        Param := %A_Index%
        ; берем 1-й символ параметра (проверяем наличие ключа)
        StringLeft, Switch_Pointer, Param, 1
        ; если параметр начинается с "-" или с "/" (указатели на ключ), то...
        If ( Switch_Pointer = "-" OR Switch_Pointer = "/" )
        {
            ; берем остальную часть строки (получаем сам ключ)
            StringMid, Switch, Param, 2, StrLen( Param )
            Loop, parse, pSwitches, `, ; просматриваем список допустимых ключей
            {
                ; если полученный ключ имеет имя из списка, то...
                If Switch = %A_LoopField%
                {
                    Switch_Count += 1 ; увеличиваем счетчик ключей
                    ; запоминаем номер ключа и его содержимое (в массив)
                    Switch%Switch_Count% := A_LoopField
                }
            }
        }
    }
}
 
; Извлекаем результаты (из массива)
Loop %Switch_Count%
{
    Switch_Val := Switch%A_Index% ; вносим содержимое ключа в переменную
    MsgBox, Скрипт запущен с ключом Switch%A_Index% = "%Switch_Val%"  
}

Теперь изменим предыдущий вариант так, чтобы в качестве параметров можно было получать не только ключи, но и имена файлов/папок. Сама командная строка, содержащая и ключи, и имена, может выглядеть так (пути, имеющие пробелы, нужно заключать в кавычки):

"D:\AHK\Param2Script.ahk" /orange "D:\AutoGeneral\Нужный файл.txt" "D:\Рабочая папка"

Итак, обрабатываем полученные параметры:

; Задаем список допустимых ключей
pSwitches = orange,apple,test ; (без пробелов после запятой)
 
; Поиск в параметрах ключей (модификаторов действий скрипта)
If 0 > 0 ; если параметры есть (см. Примечание 1), то...
{
    Loop, %0% ; обработать все переданные параметры
    {
        ; получаем значение текущего параметра (см. Примечание 2 и 3)
        Param := %A_Index%
        ; берем 1-й символ параметра (проверяем наличие ключа)
        StringLeft, Switch_Pointer, Param, 1
        ; если параметр начинается с "-" или с "/" (указатели на ключ), то...
        If ( Switch_Pointer = "-" OR Switch_Pointer = "/" )
        {
            ; берем остальную часть строки (получаем сам ключ)
            StringMid, Switch, Param, 2, StrLen( Param )
            Loop, parse, pSwitches, `, ; просматриваем список допустимых ключей
            {
                ; если полученный ключ имеет имя из списка, то...
                If Switch = %A_LoopField%
                {
                    Switch_Count += 1 ; подсчитываем количество ключей
                    ; запоминаем номер ключа и его содержимое (в массив)
                    Switch%Switch_Count% := A_LoopField
                }
            }
        }
        ; если параметр не ключ, значит он - имя файла/папки
        ; (что не обязательно верно, но проверить это можно позже)
        Else
        {
            Name_Count += 1 ; подсчитываем количество полученных имен
            Name%Name_Count% := Param ; запоминаем полученное имя в массив              
        }
    }
}
 
; Извлекаем результаты (из массива)
Loop %Switch_Count%
{
    Switch_Val := Switch%A_Index% ; вносим содержимое ключа в переменную
    MsgBox, Скрипт запущен с ключом Switch%A_Index% = "%Switch_Val%"  
}
 
Loop %Name_Count%
{
    Name_Val := Name%A_Index% ; вносим содержимое ключа в переменную
    MsgBox, Получено имя Name%A_Index% = "%Name_Val%"  
}

Этот вариант вполне рабочий. Думаю, нет нужды упоминать, что вместо MsgBox'ов можно и нужно использовать то, что вы хотите, чтобы скрипт делал.

А вот – как можно использовать передаваемые скрипту параметры в Total Commander'е. Чтобы передать скрипту в качестве параметров файлы/папки, выделенные в ТС, есть простой способ. Пишем следующий, с позволения сказать, скрипт:

; читаем созданный TC'ром временный список выделенных файлов/папок
FileRead, Temp_List, %1%
; показываем результаты (или делаем всякие действия)
MsgBox, Временный список:`n%1%`n`nВыделенные файлы/папки:`n%Temp_List%

Сохраняем его. Создаем для него кнопку на панели инструментов, или команду в меню "Запуск". В параметрах кнопки (или команды) указываем %L. Нажимаем кнопку - видим результат. Вообще, можно использовать следующие параметры:

На всякий случай расскажу, как создать кнопку. Это легко: просто перетаскиваем скрипт на панель инструментов TC. Если хочется поместить кнопку в то место панели инструментов, где уже есть другие кнопки, то нужно просто удерживать клавишу "SHIFT". Затем по созданной кнопке нужно кликнуть правой мышью, и в контекстном меню выбрать пункт "Изменить…" (или как он там называется в вашем переводе). Появится меню настройки кнопки. Нас интересует второе сверху текстовое поле, называющееся "Параметры". В него выбранные параметры и нужно вписывать.

А вот, к примеру, хотите вы скопировать в буфер длинные имена, включая полный путь. В ТС есть специальная команда для этого (cm_CopyFullNamesToClip). Однако если копируемое имя – имя папки, то такое имя будет заканчиваться бэкслэшем. Иногда это не удобно. А если вы захотите копировать не длинные, а короткие имена, то и команды такой нет. Сделать нужное можно таким скриптом:

Loop, read, %1% ; обработать временный список файлов/папок, созданный ТС
{
    Current_String = %A_LoopReadLine% ; вносим текущую строку из списка в переменную
    StringRight, Right_Simbol, Current_String, 1 ; получить последний символ в строке
    If Right_Simbol = \ ; если последний символ "\" (полученное имя - папка), то...
        If ( %2% = TrimSlash OR  %2% = ts ) ; (см. Примечание 4) если указано, 
        ; ... что нужно отрезать финальные бэкслэши из имени папки, то...
            StringTrimRight, Current_String, Current_String, 1 ; отрезать последний символ из строки
    If My_List = ; если список еще пуст, то...
        My_List = %Current_String% ; ВНЕСТИ имя файла/папки в общий список имен
    Else ; если список УЖЕ НЕ пуст, то...
        My_List = %My_List%`n%Current_String% ; ДОБАВИТЬ имя файла/папки в общий список имен
}
clipboard = %My_List% ; вставить полученный список в буфер

Создаем для него кнопку на панели ТС, а в указанное поле "Параметры" пишем "%l ts" или "%l TrimSlash" (без кавычек), что будет означать, что нам нужны короткие имена с путем и не нужны финальные бэкслэши в именах папок. Теперь выделяем какие-нибудь файлы/папки и нажимаем кнопку. Выбранные имена оказываются в буфере. Разумеется, вместо %l (короткие имена) можно указать любые другие параметры из приведенного выше списка. Вообще говоря, этот скрипт можно улучшить (удобнить), но здесь не форум по Total Commander'у, поэтому воздержусь, несмотря на мою любовь к ТС.

Вот, коротенько, и все. Надеюсь, написанное вам пригодится. Будут идеи, замечания, вопросы - делитесь, излагайте, задавайте на форуме.

Удачи, здоровья и творческих узбеков.

Перейти на главную страничку сайта (список статей, файлы для скачивания)

© 2007 http://www.script-coding.com При любом использовании материалов сайта обязательна ссылка на него как на источник информации, а также сохранение целостности и авторства материалов.