Скрипты и скриптовый язык 1C:EDT CLI #
Cкрипт 1C:EDT CLI - это текстовый файл, содержащий инструкции скриптового языка 1C:EDT CLI (в простом случае — одну или несколько последовательных команд), который можно запустить с помощью аргумента командной строки -file
и в который можно передать аргументы, доступные из скрипта как переменные $1
, $2
и т.д. Обычно файлы скриптов имеют расширение .1cedtcli
.
В версии 1C:EDT 2024.2 появилась расширенная поддержка скриптов:
- Скрипты могут быть запущены как обычные команды CLI в интерактивном режиме или режиме
-command
. - Скрипты могут быть включены в поставку продукта.
- Команда
help
не делает различий между командами и скриптами: список выводимых команд содержит загруженные скрипты, можно получить справку по скрипту.
Таким образом стирается грань между понятиями “команда” и “скрипт”. Скрипты можно рассматривать как команды, которые проще реализовать и добавить в продукт.
Загрузка скриптов #
Поставляемые вместе с продуктом скрипты загружаются автоматически. Их список можно получить командой script
.
Загрузить внешние (не входящие в дистрибутив продукта) скрипты можно несколькими способами:
- Перечислить в переменной окружения
EDTCLI_SCRIPT_PATH
пути к папкам со скриптами (формат аналогичен переменнойPATH
). - Использовать команду
script --load
.
В обоих случаях из указанных папок будут загружены все файлы с расширением .1cedtcli
. Именем скрипта будет имя его файла без расширения. Имя файла не должно содержать специальных символов.
Для динамической верификации скриптов можно подключиться к точке расширенияcom.e1c.g5.v8.dt.cli.api.cliVerifier
классом, реализующим интерфейсcom.e1c.g5.v8.dt.cli.api.ICliVerifier
. Это позволит запрещать загрузку определенных скриптов. Верификация проводится как для поставляемых скриптов, так и для внешних.
Запуск скриптов #
Скрипты могут запускаться как обычные команды:
<имя скрипта> <аргумент1> <аргумент2> ...
Также с ними работает команда help
.
Пример: создадим файл hello.1cedtcli
со следующим содержимым:
# Скрипт приветствует пользователя.
#
# Использование:
# hello "имя"
# Аргументы:
# имя - имя пользователя. Если не задано, приветствует мир.
#
# Дополнительно скрипт распечатывает свое расположение.
name = мир
if { $1 } {
name = $1
}
echo Привет, $name!
echo Расположение скрипта: $0
Запустим 1C:EDT CLI в интерактивном режиме и загрузим его:
1C:EDT> script --load "C:\Users\test\cli-scripts\hello.1cedtcli"
hello
Вывод hello
выше означает, что скрипт успешно загружен. Теперь мы можем получить по нему справку
1C:EDT> help hello
Скрипт приветствует пользователя.
Использование:
hello "имя"
Аргументы:
имя - имя пользователя. Если не задано, приветствует мир.
Дополнительно скрипт распечатывает свое расположение.
…и запустить как обычную команду в интерактивной режиме
1C:EDT> hello
Привет, мир!
Расположение скрипта: C:\Users\test\cli-scripts\hello.1cedtcli
1C:EDT> hello Иван
Привет, Иван!
Расположение скрипта: C:\Users\test\cli-scripts\hello.1cedtcli
Если мы хотим использовать этот скрипт в режиме -command
, то нам нужно установить значение переменной окружения EDTCLI_SCRIPT_PATH=C:\Users\test\cli-scripts
. При указании папки будут загружены все скрипты из неё. Также можно:
- указать путь до файла - тогда будет загружен только этот скрипт;
- указать несколько путей через стандартный разделитель (для Windows это
;
, для Linux и Mac -:
).
Теперь мы можем запустить скрипт в режиме -command
:
$ 1cedtcli -data C:\Users\test\workspace -command hello Иван
Также при помощи команды script -c/--content
можно увидеть содержимое скрипта (его код).
Любой внешний (не входящий в дистрибутив) скрипт также можно запустить с помощью аргумента командной строки -file
, для этого не требуется прописывать его в переменной EDTCLI_SCRIPT_PATH
:
$ 1cedtcli -data C:\Users\test\workspace -file C:\Users\test\cli-scripts\hello.1cedtcli Иван
Скриптовый язык #
Комментарии #
Символ #
и остаток строки после него - это комментарий.
Если скрипт начинается с комментария, то этот комментарий трактуется как справка о скрипте, и он будет показан командой help
.
Литералы и переменные #
Поддерживаются следующие типы литералов:
- Строка:
"abcd"
, кавычки не обязательны. - Список:
[1 2 a b]
- Словарь:
[Jan=1 Feb=2 Mar=3]
- Замыкание:
{ echo hi $args }
(см. ниже).
Определить переменную можно так: a = test
. Получить значение переменной: $a
.
Команды могут возвращать произвольный объект Java в качестве результата, поэтому переменная может быть объектом любого класса Java.
Предопределенные переменные #
При выполнении скрипта следующие переменные определены автоматически.
$0
- путь до файла исполняемого скрипта. В случае поставляемого скрипта - это путь до ресурса (см. ниже раздел “Поставка скриптов”).$argc
- количество переданных аргументов.$1, $2, ...
- аргументы, переданные скрипту.
Последовательное исполнение команд, перенаправление вывода #
Чтобы последовательно выполнить несколько команд в одной строке, используйте ;
:
echo a; echo b
Поддерживается перенаправление вывода одной команды на ввод другой (pipes):
1C:EDT> platform-versions | grep 8.3.22
8.3.22
true
Вывод команды можно перенаправить в переменную с помощью скобок:
1C:EDT> q = (echo abcd)
abcd
1C:EDT> $q
abcd
Вывод команды можно перенаправить в файл с помощью >
:
1C:EDT> platform-versions > /home/test/platform-versions.txt
1C:EDT>
Замыкания #
Замыкание - блок кода, который может быть сохранен в переменную или передан как аргумент в команду для исполнения позднее. Оформляется фигурными скобками:
1C:EDT> hi-func = { echo Привет, $args! }
echo Привет, $args!
1C:EDT> hi-func Имярек
Привет, Имярек!
В интерактивном режиме замыкания могут быть только однострочными. В скриптах возможны многострочные замыкания. В этом случае открывающая фигурная скобка должна быть на той же строке:
# правильно
hi-func = {
echo Привет, $args!
echo Как дела?
}
# неправильно:
hi-func =
{
echo Привет, $args!
echo Как дела?
}
Управление ходом исполнения #
Команды управления ходом исполнения получают на вход замыкания, к ним применяются правила оформления замыканий. Например:
# правильно:
if { условие } {
действие
}
# неправильно:
if { условие }
{
действие
}
Ветвление #
if { условие } { действие, если условие истинно } { действие, если условие ложно }
Последний блок (else
) необязателен и может быть опущен.
В качестве условия может выступать результат выполнения команды/скрипта или значение переменной. Следующие значения считаются ложными:
null
false
(булево значение)0
(число)0
(строка)- пустая строка
- строка, состоящая из одних пробельных символов
- любая пустая коллекция.
Остальные значения считаются истинными.
Инвертировать условия можно командой not { условие }
.
Циклы #
while { условие } { действие, пока условие истинно }
until { условие } { действие, пока условие ложно }
Условие истинности такое же, как для ветвлений.
each $коллекция { действие }
Выполняет действие для каждого элемента коллекции. Текущий элемент доступен в переменной it
. См. пример ниже.
Работа с исключениями #
try { основное действие } { действие в случае исключения } { завершающее действие }
# аналогично первому варианту, но более читабельно:
try { основное действие } catch { действие в случае исключения } finally { завершающее действие }
Аналог try/catch/finally
в Java. Выполняется основное действие, если выпало исключение - то действие в случае исключения. Завершающее действие выполняется всегда.
Третий блок (finally
) не обязателен и может быть опущен.
Если нужно сделать try/finally
(без catch
), используйте следующую форму:
try { основное действие } finally { завершающее действие }
Бросить исключение:
throw строка/число/любой объект
Если выброшено исключение, оно будет доступно в переменной exception
. В переменной будет хранится объект исключения, у него можно вызвать методы, например, message
или printStackTrace
:
1C:EDT> throw "Произошла ошибка"
edtsh: Произошла ошибка
Введите '$exception printStackTrace' для получения детальной информации об ошибке.
1C:EDT> $exception message
Произошла ошибка
Успешное выполненные команды обнуляют переменную exception
. Если информация об исключении нужна позднее, сохраните его в другую переменную: handle_later = $exception
.
Служебные команды #
echo: вывод #
1C:EDT> echo Всем привет!
Всем привет!
grep: поиск #
1C:EDT> platform-versions | grep -q 8.3.24
true
Необязательные аргументы:
-i, --ignore-case
: игнорировать регистр символов-n, --line-number
: добавлять к каждой строке номер строки-q, --quiet, --silent
: подавить весь нормальный вывод-v, --invert-match
: выбирать несовпадающие строки (инверсия)
cat: чтение файлов #
cat /home/test/hello.txt
Выводит содержимое файла на консоль.
cd: текущая (рабочая) директория #
cd
cd /path/to/new/working/directory
Первый вариант выводит текущую рабочую директорию (относительно которой определяются все относительные пути). Второй вариант меняет текущую рабочую директорию на указанную.
env: переменные окружения #
env
env PATH
Первый вариант выводит список всех переменных окружения. Второй вариант выводит значение указанной переменной окружения.
Взаимодействие с Java #
Все переменные являются объектами Java определенных типов, и у них можно вызывать методы и считывать свойства. Синтаксис следующий:
$<имя переменной> <имя метода или свойства> [аргументы]
Например:
1C:EDT> a = [1 2 abcd]
1
2
abcd
1C:EDT> $a size
3
1C:EDT> $a get 2
abcd
1C:EDT>
В этом примере мы создали список из 3 элементов. Переменная a
после этого имеет тип java.util.List<Object>
. Далее мы вызываем метод size()
у этого объекта и получаем размер списка. После чего вызываем метод get(2)
, чтобы получить последний элемент.
Если у типа есть геттер (метод вида getSomething()
), то его можно вызвать как $a something
(без get
). Пример (см. пункт работы с исключениями):
$exception message
Здесь вызывается метод getMessage()
у объекта исключения.
Основные команды и скрипты #
Список основных команд и скриптов зависит от комплектации дистрибутива и постоянно растет. Получить актуальный список можно, набрав команду help
(без параметров).
1C:EDT> help
Доступные команды 1С:EDT CLI:
build
cd
clean-up-source
delete
exit
export
format-modules
help
import
install-platform-support
platform-versions
project
script
uninstall-platform-support
validate
lt:convert-language-project
lt:convert-languages
lt:export-translation-statistic
lt:generate-strings
lt:import-language-projects
lt:list-storages
lt:list-translation-providers
lt:synchronize
Чтобы получить справку по конкретной команде, введите ее имя после "help". Например: "help install-platform-support".
В этом списке нет служебных команд и команд управления ходом исполнения.
Поставка скриптов #
Чтобы включить скрипт в поставку продукта, нужно добавить файл скрипта в плагин и подключиться к точке расширения com.e1c.g5.v8.dt.cli.api.cliScript
, указав относительный путь до файла скрипта в атрибуте resource
элемента cliScript
:
|
|
Как и для команд, для скриптов можно указать пространство имён:
|
|
Тестирование скриптов #
Автоматическое тестирование поставляемых скриптов может быть реализовано через сервис com.e1c.g5.v8.dt.cli.api.ICliCommandExecutor
, аналогично тому, как реализуются интеграционные тесты для команд. Подробнее см.
здесь.
Примеры скриптов #
Пример 1 #
Пример выводит сообщение о том, поддерживается ли версия «1С:Предприятия» 8.3.22 данной средой разработки.
is22 = ( platform-versions | grep -q 8.3.22 )
if { $is22 } { echo 8.3.22 поддерживается } { echo 8.3.22 не поддерживается }
Вывод:
8.3.22 поддерживается
В первой строке создается переменная is22
, в которую записывается результат выполнения команды в скобках. В скобках команда platform-versions
выводит все поддерживаемые версии платформы, а ее вывод перенаправляется на вход команды grep
, которая ищет в нем строку 8.3.22
. Опция -q
означает, что команда grep
ничего не выводит, а просто возвращает true
или false
.
Во второй строке команда if
проверяет истинность значения переменной is22
, а команды echo
выводят соответствующие сообщения.
Пример 2 #
Пример выводит сообщение о том, поддерживается ли данной средой разработки каждая из перечисленных версий «1С:Предприятия».
isList = [8.3.21 8.3.22 9.3.23]
each $isList {
if { not { platform-versions | grep -q $it } } {
"$it не поддерживается"
} {
"$it поддерживается"
}
}
Вывод:
8.3.21 поддерживается
8.3.22 поддерживается
9.3.23 не поддерживается
В первой строке создается переменная-список интересующих версий. Во второй строке по каждой из этих версий команда if
проверяет, поддерживается эта версия, или нет, и выводит соответствующее сообщение.
Пример 3 #
Пример читает содержимое файла.
hellotxt = ( cat /home/test/hello.txt )
В первой строке команда cat
читает в переменную hellotxt
содержимое файла /home/test/hello.txt
.
Просмотр существующих скриптов #
Воспользуйтесь командой script
, чтобы получить список загруженных скриптов. Далее, вызовите команду script -c <script>
, чтобы изучить содержимое скрипта (его код):
script -c hello