Lua скрипт: Гайд по использованию Lua-скриптов в Redis

Содержание

Гайд по использованию Lua-скриптов в Redis

Что такое язык Lua?

Язык программирования Lua появился в 1993 году. По своей структуре он является компактным языком программирования, который можно встраивать практически в любое приложение — от World of Warcraft до веб-сервера Nginx. Ну и конечно же, в Redis, о котором далее и пойдёт речь.

Благодаря Lua в Redis возможно встраивать собственные скриптовые расширения для базы данных. Вызов скриптов выглядит следующим образом:

> EVAL 'local val="Hello Compose" return val' 0
"Hello Compose"

Далее сам Lua-скрипт:

local val="Hello Compose"
return val

Что более важно, вы можете запускать скрипты в качестве «умных транзакций». Это позволяет обрабатывать ошибки в рантайме, не останавливая приложение. Безусловно, то, насколько «умными» будут эти транзакции, зависит целиком и полностью от вас.

Ключи и аргументы

Для обращения к скрипту неплохо бы было передать ему ключи и аргументы.

Например, как в нижеприведённом коде:

> EVAL 'local val="Hello Compose" return val' 0

В конце EVAL мы видим ноль — это количество ключей, переданных скрипту. Но если вместо ноля написать 2 foo bar fizz buzzthen, первые два элемента foo и bar будут переданы в качестве ключей, а fizz и buzz — в качестве аргументов.

Ключи доступны Lua-скрипту в таблице KEYS. Таблица в Lua — это ассоциативный массив, который также используется в качестве массива из одного элемента. Если помимо ключей используются аргументы, они будут доступны в таблице ARGV, например:

return ARGV[1]..' '..KEYS[1]

В Lua .. используется в качестве оператора объединения, так что здесь в качестве возвращаемого значения мы получаем аргумент, привязанный к пробелу, и название ключа, которое было передано в качестве аргумента:

> EVAL "return ARGV[1]. .' '..KEYS[1]" 1 name:first "Hello"
"Hello name:first"

Никакой магии в KEYS, это просто строка, так что нам по-прежнему нужно получить их значение.

Что касается вызова Redis из Lua, можно использовать функцию redis.call(). Например:

> EVAL 'return ARGV[1].." "..redis.call("get",KEYS[1])' 1 name:first "Hello"
"Hello Brian"

Прим. автора Если в процессе объединения вы получаете ошибку «attempt to concatenate a boolean value» (попытка объединения значений булевого типа), скорее всего name:first не было присвоено какое-либо значение.

Таким образом, скрипт взял параметр, нашёл значение ключа и вернул в качестве вывода созданную строку.

Однако помимо EVAL есть и другой способ передать скрипт на сервер. Например, используя аргументы команды redis-cli. Попробуем написать чуть более сложный скрипт:

lua
local name=redis.call("get", KEYS[1])
local greet=ARGV[1]
local result=greet. ." "..name
return result

Сохраним его как longhello.lua и выполним в командной строке:

$ redis-cli -h aws-us-east-1-portal.15.dblayer.com -p 11260 -a secret  --eval longhello.lua name:first , Hello
"Hello Brian"

Итак, мы запускаем redis-cli, добавляем параметры -h, -p и -a для связи с базой данных. Затем идёт --eval

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

Сложные скрипты

Следующий случай наглядно демонстрирует, как Lua решает одну небольшую проблему. Допустим, разные пользователи или разработчики увеличивают счётчики в большой структуре данных. Например, region:one увеличивает count:emea, count:usa, count:atlantic, в то время как region:two затрагивает лишь count:usa. Эти счётчики могут быть добавлены позже, но вдруг вам важно убедиться, что добавятся они все разом? Самое время вспомнить про «умные транзакции».

Добавим все наши регионы в список:

> rpush region:one count:emea count:usa count:atlantic
(integer) 3
> rpush region:two "count:usa"
(integer) 1

Создадим локальную переменную:

local count=0

Начнём с переменной-счётчика — он будет считать все операции по увеличению наших округов.

local broadcast=redis.call("lrange", KEYS[1], 0,-1)

Теперь запросим у Redis все значения списка, относящиеся к первому ключу.

for _,key in ipairs(broadcast) do

Здесь мы запустили цикл, в котором функция ipairs() просмотрит каждую задействованную Lua-таблицу и передаст из неё ключ.

redis.call("INCR",key)
count=count+1
end
return count

С каждым вызовом мы увеличиваем указанный ключ, а заодно и наш счётчик.

После окончания цикла мы получаем конечное число итераций. Сохраним итоговый скрипт и запустим его на сервере:

$ redis-cli -h aws-us-east-1-portal.15.dblayer.com -p 11260 -a secret --eval broadcast.lua region:one
(integer) 3

В таблице будут содержаться следующие значения:

> mget count:usa count:atlantic count:emea

1) "1"

2) "1"

3) "1"

Значения для region.two:

$ redis-cli -h aws-us-east-1-portal.15.dblayer.com -p 11260 -a secret --eval broadcast.lua region:two
(integer) 1
> mget count:usa count:atlantic count:emea
1) "2"
2) "1"
3) "1"

Но что, если бы во время выполнения скрипта произошла ошибка? Он просто продолжил бы выполняться, игнорируя её. Для вывода деталей ошибки следует использовать

redis.pcall().

Кэширование скриптов

Для того чтобы не загружать скрипт каждый раз перед выполнением, можно использовать команду SCRIPT LOAD для загрузки скрипта в кэш. Рассмотрим пример использования из командной строки:

$ redis-cli -h aws-us-east-1-portal.15.dblayer.com -p 11260 -a secret SCRIPT LOAD "$(cat broadcast.lua)"
"84ffc8b6e4b45af697cfc5cd83894417b7946cc1"

Здесь $(cat broadcast.lua) превращает наш скрипт в аргумент. А шестнадцатеричное число ниже — SHA1-подпись нашего скрипта. Её можно использовать для его последующего вызова командой EVALSHA:

> EVALSHA 84ffc8b6e4b45af697cfc5cd83894417b7946cc1 1 region:one
(integer) 3

Также есть команды для проверки наличия скрипта на сервере и его удаления —

SCRIPT EXISTS и SCRIPT FLUSH соответственно.

Не всё так просто

После довольно небольшого промежутка времени (по умолчанию — 5 секунд) Lua-скрипты начнут выдавать ошибки в ответ на запросы — в таком случае возможно только «убить» скрипт командой KILL SCRIPT либо выключить сервер командой SHUTDOWN NOSAVE. С другой стороны, 5 секунд — очень щедрое ограничение, ведь ваши скрипты должны выполняться буквально в течение миллисекунд. И на это есть очень веская причина: во время выполнения ваших скриптов все остальные процессы приостанавливаются.

Заключение

Итак, в этой статье мы рассмотрели примеры написания простых и сложных Lua-скриптов, их вызов из Redis, а также запись и хранение на сервере.

Перевод статьи «A Speed Guide To Redis Lua Scripting»

Гайд — Написание Lua скриптов для MoonLoader | BLASTHACK


Данная тема посвящена нюансам и особенностям разработки Lua скриптов для MoonLoader.

Список вопросов:
Начало разработки.
Взаимодействие с игроками.
Работа с переменными.
Работа с командами.



Начало разработки.
Каждый Lua скрипт при запуске создает поток «main» который и является основным местом работы со скриптом.
Сразу обговорим — скрипт «жив» пока «жив» поток main(), поэтому если мы хотим продолжать работать со скриптом после запуска — будем держать поток активным:
function main() -- Объявляем поток main() wait(-1) -- Устанавливаем бесконечное ожидание end -- закрываем функцию

Запускаем скрипт — работает!
Что ж, поставим себе цель — при запуске выводить сообщение «Привет мир» в чат.
Что нам для этого нужно?
Заходим на WIKI (Раздел «Функции» moonloader`a) и ищем функции чата — Поиск -> «Chat». Видим функцию sampAddChatMessage(message, color) — то что надо.
Вставляем:
function main()
    sampAddChatMessage("Привет мир!", 0xFFFFFFFF) -- Выводим сообщение в чат
    wait(-1) -- Устанавливаем бесконечное ожидание
end
Запускаем скрипт — ошибка?
(error) test.lua: opcode '0AF8' call caused an unhandled exception
Бежим на WIKI (Опять раздел «Функции» moonloader`a) и в поиск вводим наш опкод «0AF8».
Находим нашу функцию sampAddChatMessage()
Что это значит? Дело в том что нельзя вызывать функции для работы с SA:MP пока сам SA:MP не готов. Что делать? Добавим перед выводом сообщения такой код:
if not isSampfuncsLoaded() or not isSampLoaded() then -- Если SF или SA:MP не загружены
    return -- Завершаем работу скрипта
end
while not isSampAvailable() do -- Ждём пока функция isSampAvailable() вернет true
    wait(0) -- Устанавливаем минимальное ожидание, что бы наша игра не зависла
    -- значение 0 говорит что мы ждём следующий кадр (Frame)
end
Теперь наш скрипт будет ждать пока самп полностью не загрузится и продолжит выполнение кода.

Что такое wait() и с чем его едят?
Wait позволяет ставить поток в режим ожидания на указанное количество мили-секунд (ms)
Wait нельзя в CallBack-функциях, это приведет к ошибке, а в последствии и смерти, скрипта.
Почему мы ставим 0? Потому-что это минимальная задержка.

Подведем краткий итог кода:

function main()
    if not isSampfuncsLoaded() or not isSampLoaded() then
        return
    end
    while not isSampAvailable() do
        wait(0)
    end
    sampAddChatMessage("Привет мир!", 0xFFFFFFFF)
    wait(-1)
end
Теперь при входе в игру / перезапуске скрипта в чат будет выводиться сообщение «Привет мир».
К списку вопросов

Взаимодействие с игроками
Перейдем к примерам посложнее — попробуем получить ник, ид и счет игрока в которого мы прицелились.
Цель поставили, какие нам нужны средства?
Опять бежим к WIKI, всё в тот же раздел функций и ищем функции связанные с целями, Поиск -> Target.
Смотрим в списке есть getCharPlayerIsTargeting(ped).
Она возвращает 2 значения — result, ped.
Первое значение — возвращает результат проверки на целится ли указанный Ped в кого-либо.
Второе — если указанный Ped целится — возвращает саму цель.
Как нам это использовать? Всё просто, уберем бесконечное ожидание и будем проверять значение result.
function main()
    if not isSampfuncsLoaded() or not isSampLoaded() then
        return
    end
    while not isSampAvailable() do
        wait(0)
    end
    sampAddChatMessage("Привет мир!", 0xFFFFFFFF)
    while true do -- Создаем бесконечный цикл, вместо бесконечного ожидания
        wait(0) -- Опять таки чтобы наша игра не зависла, ждем след кадр
        local result, ped = getCharPlayerIsTargeting(PLAYER_HANDLE) -- Каждый кадр получаем данные функции, PLAYER_HANDLE - возвращает ваш Handle
        if result then -- Если result вернет true
            print("True!") -- Выведем сообщение в лог / консоль
        end
    end
end
Что мы можем с этим делать? Теперь если мы целимся в кого-либо, мы увидим сообщения в moonloader. log об этом. Мы получили Ped игрока в которого мы целимся. Давайте используем эту информацию.
function main()
    if not isSampfuncsLoaded() or not isSampLoaded() then
        return
    end
    while not isSampAvailable() do
        wait(0)
    end
    sampAddChatMessage("Привет мир!", 0xFFFFFFFF)
    while true do
        wait(0)
        local result, ped = getCharPlayerIsTargeting(playerPed)
        if result then
            local result2, id = sampGetPlayerIdByCharHandle(ped) -- Попробуем получить ID игрока по его Ped
            if result2 then -- Если получилось
                local nickname = sampGetPlayerNickname(id) -- Запишем его ник
                local score = sampGetPlayerScore(id) -- и счет
                sampAddChatMessage(string.format("%s[%d] имеет счет %d", nickname, id, score), -1) -- И выведем это в чат
            end
        end
    end
end
К списку вопросов

Работа с переменными
Что у нас получилось? Мы будем получать кучу сообщений в чат о игрока по пока целимся в кого-либо, но как убрать этот флуд?
Давайте создадим переменную перед main(), например targeting, и присвоим ей значение false.
И задействуем её в коде
local targeting = false -- Создаем булевую переменную
function main()
    if not isSampfuncsLoaded() or not isSampLoaded() then
        return
    end
    while not isSampAvailable() do
        wait(0)
    end
    sampAddChatMessage("Привет мир!", 0xFFFFFFFF)
    while true do
        wait(0)
        local result, ped = getCharPlayerIsTargeting(playerPed)
        if result and not targeting then -- Если мы целимся, но ранее ни в кого не целились
            local result2, id = sampGetPlayerIdByCharHandle(ped)
            if result2 then
                local nickname = sampGetPlayerNickname(id)
                local score = sampGetPlayerScore(id)
                sampAddChatMessage(string.format("%s[%d] имеет счет %d", nickname, id, score), -1)
                targeting = true -- запишем что мы целимся в кого либо и наше условие выше станет ложным
            end
        elseif not result and targeting then -- Если условие обратное - скажем скрипту что мы не целимся
            targeting = false
        end
    end
end
Отлично, теперь если мы целимся в игрока — получаем одно сообщение, меняем цель или заново целимся в того же игрока — снова получим о нём информацию.
К списку вопросов

Работа с командами.
Уже лучше, давайте теперь работаем с командами.
Уберем лишний код и оставим следующее:
function main()
    if not isSampfuncsLoaded() or not isSampLoaded() then
        return
    end
    while not isSampAvailable() do
        wait(0)
    end
    while true do
        wait(0)
    end
end

Как добавить команду? Давайте опять порыщем на WIKI, Поиск -> Command
Нашли sampRegisterChatCommand(command, callback)? Отлично, можно уже приступать.
Зарегистрируем нашу команду, например «toster»:
function main()
    if not isSampfuncsLoaded() or not isSampLoaded() then
        return
    end
    while not isSampAvailable() do
        wait(0)
    end

    sampRegisterChatCommand("toster", tosterCallBack) -- Регистрируем ДО бесконечного цикла. 
    -- Первый параметр - команда, без слэша.
    -- Второй - функция-callback которая будет вызваться если будет введена команда.

    wait(-1) -- Уберем бесконечный цикл, он тут вовсе не нужен, но нам же нужно чтобы скрипт работал
end

function tosterCallBack(params)
    sampAddChatMessage("Дзынь!", -1)
end
Теперь при вводе команды «/toster» мы увидим в чате сообщение. Успех? Но как например вывести свой текст в чат? Легко!
sampAddChatMessage(params, -1)
Теперь мы выводим весь текст после команды «/toster» в чат. Например: /toster Привет жалкий мирок!

Помните я говорил что нельзя использовать wait() внутри callback-функций, это всё еще так, но есть тут одна хитрость!

function tosterCallBack()
    sampAddChatMessage("Дзынь!", -1)
    lua_thread. create(function() -- Создаем новый поток
        wait(5000) -- Ждём 5 секунд
        sampAddChatMessage("Тоже дзынь, но на 5 секунд позже!", -1) -- Выводим текст в чат
    end) -- Тут наш поток умирает :(
end
К списку вопросов
На сегодня всё, теперь вы чертовы волшебники, поняв как всё работает, можно приступать к изучению примеров Lua скриптов!

Тема будет дополняться по мере изучения популярных вопросов по Lua скриптингу.

Спойлер: Хейтерам

Я понимаю что вы невъебенные мастера луа скриптинга, но это тема не для вас

DC — Скрипты Lua

Double Commander может выполнять скрипты Lua с помощью команды cm_ExecuteScript.

Эта возможность добавлена в версии 0.8.

Также на языке Lua возможно писать контентные (или информационные) плагины (WDX-плагины).

Более подробную информацию о языке программирования Lua можно найти на официальном веб-сайте Lua.

(наверх)

Чтобы использовать скрипты Lua, нам требуется интерпретатор Lua версии 5.1 или выше, DLL-файл должен лежать рядом с исполняемым файлом Double Commander или в системной папке.

По умолчанию DC ищет файл с именем lua5.1.dll (Windows), liblua5.1.so.0 (Unix или GNU/Linux) или liblua5.1.dylib (Mac OS). Мы можем вручную изменить имя файла в параметре <PathToLibrary>.

Мы можем использовать DLL-файл проекта LuaJIT. LuaJIT сочетает в себе высокоскоростной интерпретатор, написанный на ассемблере, и JIT-компилятор. Также мы получаем библиотеку FFI: с её помощью в скриптах можно будет вызывать внешние функции C и использовать структуры данных C. DLL для Windows: 32-битная или 64-битная.

Если мы используем 64-битную версию DC, то DLL-файл также должен быть 64-битным.

Дистрибутивы DC для Windows включают в себя DLL-файл Lua (в DC 0. 9.7 и новее из проекта LuaJIT), в иных случаях мы можем найти и установить его с помощью менеджера пакетов или скомпилировать.

(наверх)

Double Commander предлагает несколько библиотек функций для скриптов Lua, список представлен ниже.

(наверх)

Эта библиотека содержит особые функции Double Commander, все функции представлены в таблице DC.

Библиотека DC
ФункцияОписание

DC.LogWrite

DC.LogWrite(Message, MsgType, bForce, bLogFile)

Пишет сообщение в окно протокола.

Описание:

  • Message : Текст сообщения.
  • MsgType : Тип сообщения: 0 — информационное, 1 — успешная операция, 2 — ошибка.
  • bForce : Логическое (булево) значение, если true, то показать окно протокола (если оно скрыто).
  • bLogFile : Логическое (булево) значение, если true, то сообщение будет записано и в файл протокола.

DC.CurrentPanel

iPanel = DC.CurrentPanel()

Получить активную панель: возвращает 0, если активна левая панель, или 1, если правая.

DC.CurrentPanel(iPanel)

Сделать активной: левую панель, если iPanel равно 0, или правую, если равно 1.

DC.ExecuteCommand

DC.ExecuteCommand(Command, Param1, Param2,…,ParamX)

Вызывает внутреннюю команду Double Commander Command с параметрами Param1..ParamX.

Мы можем подставить столько Param…, сколько поддерживает команда Command.

(наверх)

В этом примере мы написали простой скрипт, который сделает следующее:

  1. перенесёт фокус на правую панель
  2. закроет все открытые вкладки
  3. перейдёт в указанную папку
  4. перенесёт фокус на левую панель
  5. закроет все открытые вкладки
  6. перейдёт в указанный каталог
  7. откроет новую вкладку
  8. перейдёт в указанный каталог
-- 1.  Перенести фокус на правую панель.
DC.ExecuteCommand("cm_FocusSwap", "side=right")

-- 2. Закрыть все вкладки.
DC.ExecuteCommand("cm_CloseAllTabs")

-- 3. Перейти в указанный каталог.
DC.ExecuteCommand("cm_ChangeDir", "e:\\FakeKey\\Documents\\Music")

-- 4. Перенести фокус на левую панель.
DC.ExecuteCommand("cm_FocusSwap", "side=left")

-- 5. Закрыть все вкладки.
DC.ExecuteCommand("cm_CloseAllTabs")

-- 6. Перейти в указанный каталог.
DC.ExecuteCommand("cm_ChangeDir", "C:\\Users\\Public\\Music")

-- 7. Открыть новую вкладку.
DC.ExecuteCommand("cm_NewTab")

-- 8. Перейти в указанный каталог.
DC.ExecuteCommand("cm_ChangeDir", "e:\\VirtualMachines\\ShareFolder")

Для выполнения нашего скрипта мы можем создать кнопку на панели инструментов с внутренней командой cm_ExecuteScript.

Предположим, наш скрипт e:\scripts\lua\music.lua, мы могли бы настроить эту кнопку следующим образом:

Кроме того, для редактирования наших скриптов мы можем использовать внутренний редактор Double Commander.

Если файл имеет расширение .lua, то он будет распознан внутренним редактором и открыт с подсветкой синтаксиса, специфичного для языка Lua:

(наверх)

Эта библиотека содержит различные системные функции, все они представлены в таблице SysUtils.

Библиотека System
ФункцияОписание

SysUtils.Sleep

SysUtils.Sleep(Milliseconds)

Приостанавливает выполнение скрипта на указанное количество миллисекунд (Milliseconds), выполнение сценария будет продолжено после истечения указанного времени.

SysUtils.GetTickCount

SysUtils.GetTickCount()

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

SysUtils.FileExists

bFlagExists = SysUtils.FileExists(FileName)

Проверяет, существует ли в файловой системе определённый файл.

FileExists возвращает true, если файл с именем FileName существует на диске, и false в противном случае.

SysUtils.DirectoryExists

bFlagExists = SysUtils.DirectoryExists(Directory)

Проверяет существование Directory в файловой системе и что это действительно каталог.

Если это так, то функция возвращает true, иначе возвращает false.

SysUtils.FileGetAttr

Attr = SysUtils.FileGetAttr(FileName)

Возвращает в Attr атрибуты файла FileName.

Подробное описание возвращаемого значения смотрите здесь.

SysUtils.FindFirst

Handle, FindData = SysUtils.FindFirst(Path)

Ищет файлы, совпадающие с Path (можно использовать маски).

Если файл не найден, Handle будет равно nil.

В случае успеха функция вернёт дескриптор поиска Handle для последующих вызовов SysUtils.FindNext и поиска других совпадений с паттерном.

Таблица FindData содержит информацию о найденном файле или каталоге.

Поля таблицы FindData:

  • Name : Имя файла (без пути).
  • Attr : Атрибуты файла (подробнее смотрите здесь).
  • Size : Размер файла в байтах.
  • Time : Отметка времени файла (в формате POSIX, так называемое Unix-время: количество секунд, прошедших с 1 января 1970 г. )

SysUtils.FindNext

Result, FindData = SysUtils.FindNext(Handle)

Находит следующее вхождение поиска, инициированного FindFirst, Handle — дескриптор поиска, возвращённый функцией FindFirst.

В случае успеха функция вернёт Result не равный nil и таблицу FindData, содержащую информацию о найденном файле или каталоге.

Замечание: За последним вызовом SysUtils.FindNext всегда должен следовать вызов SysUtils.FindClose с тем же Handle. Несоблюдение этого приведёт к утечке памяти.

SysUtils.FindClose

SysUtils.FindClose(Handle)

Завершает серию вызовов SysUtils.FindFirst/SysUtils.FindNext и освобождает использованную память.

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

SysUtils.CreateHardLink

bResult = SysUtils.CreateHardLink(Path, LinkName)

Создаёт жёсткую ссылку LinkName на файл Path.

Возвращет true в случае успеха, иначе возвращает false.

SysUtils.CreateSymbolicLink

bResult = SysUtils.CreateSymbolicLink(Path, LinkName)

Создаёт символьную ссылку LinkName на файл Path.

Возвращет true в случае успеха, иначе возвращает false.

SysUtils.ReadSymbolicLink

sTarget = SysUtils.ReadSymbolicLink(LinkName, Recursive)

Читает имя файла, на который указывает символьная ссылка LinkName.

Если Recursive равно true и ссылка указывает на ссылку, то она разрешается рекурсивно до тех пор, пока не будет найдено допустимое имя файла, не являющееся ссылкой.

Возвращает путь, на который указывает символьная ссылка LinkName или пустую строку, если ссылка недействительна или файл, на который она указывает, не существует и значение Recursive равно true.

SysUtils.PathDelim

SysUtils.PathDelim

Позволяет получить от DC разделитель пути в системе.

В системах Unix/Linux это будет » / » и » \ » в Windows.

SysUtils.ExtractFileName

sName = SysUtils.ExtractFileName(FileName)

Возвращает имя файла из полного (имя+путь) имени файла.

Имя файла содержит все символы после последнего символа разделителя каталогов («/» или «\») или буквы диска.

SysUtils.ExtractFilePath

sPath = SysUtils.ExtractFilePath(FileName)

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

Путь содержит все символы до последнего символа разделителя каталогов («/» или «\»), включая сам разделитель каталогов.

SysUtils.ExtractFileDir

sDir = SysUtils.ExtractFileDir(FileName)

Возвращает только каталог из FileName, включая букву диска.

Результат НЕ содержит разделитель каталогов в конце, в отличие от SysUtils.ExtractFilePath.

SysUtils.ExtractFileDrive

sDrive = SysUtils.ExtractFileDrive(FileName)

Возвращает диск из полного имени файла.

Обратите внимание, некоторые операционные системы не поддерживают буквы дисков.

SysUtils.ExtractFileExt

sExt = SysUtils.ExtractFileExt(FileName)

Возвращает расширение файла (все символы после последней точки, включая сам символ «.»).

SysUtils.CreateDirectory

bResult = SysUtils.CreateDirectory(Directory)

Создаёт цепочку каталогов, Directory — полный путь каталога.

Возвращает true, если Directory уже существует или был успешно создан, или false, если не удалось создать какую-либо часть пути.

(наверх)

FileGetAttr возвращает атрибуты FileName в виде ИЛИ-совокупности следующих констант:

Константы, используемые в возвращаемом значении SysUtils. FileGetAttr
ЗначениеОписание

0x00000001
faReadOnly

Файл только для чтения.

0x00000002
faHidden

Скрытый файл.
В Unix/Linux это значит, что имя файла начинается с точки.

0x00000004
faSysFile

Системный файл.
В Unix/Linux это может быть символьное или блочное физическое устройство, именованный канал (FIFO).

0x00000008
faVolumeId

Метка тома (означает, что файл содержит идентификатор (ID) тома).
Только для DOS/Windows 9x на обычной файловой системе FAT (не VFAT или FAT32).

0x00000010
faDirectory

Каталог.

0x00000020
faArchive

Архивный.
Не используется в Unix/Linux.

0x00000400
faSymLink

Символьная ссылка.
Примечание: В случае ошибки функция возвращает -1.

Смотрите пример в следующей секции.

(наверх)

Пример скрипта ниже использует SysUtils.FileGetAttr.

Если параметр окажется каталогом, то скрипт откроет его в новой вкладке активной панели и переключится на неё.

local params = {...}
local myfileattr

if #params == 1 then -- Мы получили один параметр?
  myfileattr = SysUtils.FileGetAttr(params[1])
  if myfileattr > 0 then -- Получили значение атрибута?
    if math.floor(myfileattr / 0x00000010) % 2 ~= 0 then
      -- 0x00000010 присутствует? Тогда это каталог.
      DC.ExecuteCommand("cm_NewTab")
      DC.ExecuteCommand("cm_ChangeDir", params[1])
    end
  end
end

В приведённом выше примере param[1] является первым параметром, переданным скрипту.

При использовании внутренней команды cm_ExecuteScript это будет первый параметр, переданный после имени файла скрипта.

Итак, в нашем примере мы можем создать на панели инструментов кнопку, как показано ниже:

В этом примере скрипту будет передан параметр %»0%p: имя выделенного в активной панели файла или папки, без кавычек.

(наверх)

В следующем примере мы просканируем содержимое каталога, переданного первым параметром, и сохраним полученные данные в текстовый файл с именем, переданным вторым параметром.

Это даст нам хорошее представление об использовании FindFirst, FindNext и FindClose.

local params = {...}

if #params == 2 then -- У нас есть два параметра?
  local Result = nil
  local OutputFile = nil

  OutputFile = io.output(params[2])

  local Handle,FindData = SysUtils.FindFirst(params[1] .. "\\*")
  if Handle ~= nil then
    repeat
      io. write(FindData.Name .. "\r")
      io.write(FindData.Size .. "\r")
      io.write("---------------\r")

      Result,FindData = SysUtils.FindNext(Handle)
    until Result == nil

    SysUtils.FindClose(Handle)
    io.close(OutputFile)
  end
end

В приведённом выше примере нам нужно передать скрипту два параметра:

  1. param[1] — каталог, содержимое которого мы хотим получить
  2. param[2] — имя файла для сохранения результата работы скрипта

Настраиваем кнопку на панели инструментов с внутренней командой cm_ExecuteScript и передаём параметрами всё необходимое:

В этом примере скрипту в качестве первого параметра будет передано %»0%Ds: имя каталога активной панели, без кавычек.

(наверх)

Double Commander предоставляет скриптам Lua библиотеку функций для работы с буфером обмена.

Библиотека Clipboard
ФункцияОписание

Clipbrd. Clear

Clipbrd.Clear()

Очищает содержимое буфера обмена.

Clipbrd.GetAsText

StringVar = Clipbrd.GetAsText()

Получает содержимое буфера обмена как строку StringVar.

Clipbrd.SetAsText

Clipbrd.SetAsText(StringVar)

Помещает в буфер обмена строку текста StringVar.

Clipbrd.SetAsHtml

Clipbrd.SetAsHtml(Html)

Добавляет в буфер обмена текст Html в формате HTML (формат буфера обмена CF_HTML).

Содержимое может быть вставлено в приложения, поддерживающие этот формат буфера обмена, такие как MS Word, LO Writer и другие.

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

Например, у нас может быть следующее:

  • Clipbrd.SetAsText("Добро пожаловать в Double Commander!")
  • Clipbrd.SetAsHtml("Добро пожаловать в <b>Double Commander</b>!")

Если мы запустим Блокнот и попытаемся вставить текст из буфера обмена, то будет вставлен текст, скопированный с помощью Clipbrd.SetAsText. Но если мы перейдём к Microsoft Word, то будет вставлена строка с выделенным жирным шрифтом Double Commander, потому что Microsoft Word распознаёт и поддерживает этот формат буфера обмена.

(наверх)

В следующем примере используются три функции, связанные с буфером обмена: Clear, GetAsText и SetAsText.

Это относительно большой скрипт, но было бы неплохо собрать вместе несколько функций, с которыми мы познакомились ранее.

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

Также предполагается, что в настоящее время в буфере обмена одно слово и что скрипт в качестве единственного параметра получит текущий каталог активной панели.

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

Затем имена файлов, которые содержат это словом, будут скопированы в буфер обмена.

Далее скрипт вызовет внутреннюю команду cm_LoadSelectionFromClip и все эти файлы будут выделены.

Кроме того, в конце вернём обратно в буфер обмена слово, которое мы искали.

local params = {...}
local Result = nil
local myfileattr
local bFound = false
local sCompleteFilename = ""
local InputFile = nil
local line = ""
local iPosS
local iPosE
local sFileToSelect = ""
local sSearchString = ""

if #params == 1 then -- Мы получили наш параметр?
  sSearchString = Clipbrd. GetAsText() -- Получаем выражение для поиска.
  Clipbrd.Clear() -- Очищаем буфер обмена.
  DC.ExecuteCommand("cm_MarkUnmarkAll") -- Убедимся, что ничего не выделено.

  -- Начинаем сканировать все файлы нашего каталога один за другим.
  local Handle,FindData = SysUtils.FindFirst(params[1] .. "\\*")
  if Handle ~= nil then
    repeat
      sCompleteFilename = params[1] .. "\\" .. FindData.Name
      myfileattr = SysUtils.FileGetAttr(sCompleteFilename)
      if myfileattr > 0 then -- Получили значение атрибута?
        -- Нам нужен файл, не каталог!
        if math.floor(myfileattr / 0x00000010) % 2 == 0 then

          -- Начинаем читать файл построчно, до конца файла ИЛИ до совпадения.
          InputFile = io.open(sCompleteFilename, "r")
          bFound = false

          while bFound == false do
            line = InputFile:read()
            if line == nil then break end
            iPosS, iPosE = string.find(line, sSearchString)
            if iPosS ~= nil then bFound = true end
          end

          if bFound == true then
            sFileToSelect = sFileToSelect . . FindData.Name .. "\n"
          end

          io.close(InputFile)
        end
      end
      Result,FindData = SysUtils.FindNext(Handle)
    until Result == nil

    SysUtils.FindClose(Handle)
  end

  -- Если что-то нашли, то выделяем!
  if sFileToSelect ~= "" then
    Clipbrd.SetAsText(sFileToSelect)
    DC.ExecuteCommand("cm_LoadSelectionFromClip")
  end

  Clipbrd.SetAsText(sSearchString) -- Восстанавливаем содержимое буфера обмена.
end

(наверх)

Эта библиотека позволяет нашим скриптам взаимодействовать с пользователем, показывая сообщения, выдавая запросы и т.д.

Библиотека Dialogs
ФункцияОписание

Dialogs.MessageBox

ButPressed = Dialogs.MessageBox(Message, Title, ButFlags)

Показывает окно сообщения, функция вернёт нажатую пользователем кнопку.

Описание:

  • Message : Сообщение окна.
  • Title : Текст в заголовке окна.
  • ButFlags : Сумма констант, задающих отображаемые кнопки, стиль окна и кнопку по умолчанию. Смотрите ниже таблицы с кнопками, стилями и кнопкой по умолчанию.
  • ButPressed : Возвращаемое значение, указывающее нажатую кнопку (смотрите эту таблицу).

Dialogs.InputQuery

bAck, sAnswer = Dialogs.InputQuery(Title, Msg, bMask, sDefault)

Показывает диалоговое окно с полем ввода текста.

Описание:

  • Title : Текст в заголовке окна.
  • Msg : Сообщение окна.
  • bMask : Логическое (булево) значение, если true, то вводимый текст будет скрываться «звёздочками».
  • sDefault : Текст, который будет отображаться в строке ввода при появлении окна.
  • bAck : Возвращаемое логическое (булево) значение, указывающее, ввёл ли что-то пользователь или нет.
  • sAnswer : Возвращаемая строка, если пользователь что-то ввёл, а затем нажал ОК.

Dialogs.InputListBox

sAnswer = Dialogs.InputListBox(Title, Msg, Items, sDefault)

Показывает диалоговое окно с возможностью выбора из списка элементов.

Описание:

  • Title : Текст в заголовке окна.
  • Msg : Сообщение окна.
  • Items : Таблица Lua, каждый элемент таблицы должен быть строкой.
  • sDefault : Пункт списка, выделенный по умолчанию.
  • sAnswer : Возвращаемая строка с выбранным пунктом или nil в случае отмены.

(наверх)

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

(наверх)

Стиль окна Dialogs.MessageBox задаётся одним из следующих значений:

Константы, задающие значок и стиль окна Dialogs.MessageBox
Значение константыСтиль окна

0x0040
MB_ICONINFORMATION

Информационное окно

0x0030
MB_ICONWARNING

Окно предупреждения

0x0020
MB_ICONQUESTION

Окно подтверждения

0x0010
MB_ICONERROR

Окно ошибки

(наверх)

Кнопка по умолчанию (активная) в Dialogs.MessageBox задаётся одним из следующих значений:

Константы, задающие кнопку по умолчанию в Dialogs. MessageBox
Значение константыКнопка по умолчанию

0x0000
MB_DEFBUTTON1

Первая кнопка слева

0x0100
MB_DEFBUTTON2

Вторая кнопка слева

0x0200
MB_DEFBUTTON3

Третья кнопка слева

(наверх)

Число, возвращаемое функцией Dialogs.MessageBox, указывает на кнопку, которую нажал пользователь, и может быть одним из следующих:

Возвращаемое значение Dialogs.MessageBox
Значение константыНажатая кнопка

0x0000
mrNone

Кнопка не нажата

0x0001
mrOK

0x0002
mrCancel

0x0003
mrAbort

0x0004
mrRetry

0x0005
mrIgnore

0x0006
mrYes

0x0007
mrNo

Примечание: Если закрыть окно, нажав крестик «x» в углу окна или клавишу Esc, то функция вернёт 0x0002, как нажатие кнопки Отмена.

(наверх)

Маленький скрипт, использующий Dialogs.MessageBox:

-- Отображаемые кнопки
MB_OK = 0x0000
MB_OKCANCEL = 0x0001
MB_ABORTRETRYIGNORE = 0x0002
MB_YESNOCANCEL = 0x0003
MB_YESNO = 0x0004
MB_RETRYCANCEL = 0x0005

-- Стиль окна
MB_ICONINFORMATION = 0x0040
MB_ICONWARNING = 0x0030
MB_ICONQUESTION = 0x0020
MB_ICONERROR = 0x0010

-- Кнопка по умолчанию
MB_DEFBUTTON1 = 0x0000
MB_DEFBUTTON2 = 0x0100
MB_DEFBUTTON3 = 0x0200

-- Возвращаемое значение
mrNone = 0x0000
mrOK = 0x0001
mrCancel = 0x0002
mrAbort = 0x0003
mrRetry = 0x0004
mrIgnore = 0x0005
mrYes = 0x0006
mrNo = 0x0007

ButFlags = MB_YESNO + MB_ICONQUESTION + MB_DEFBUTTON2
ButPressed = Dialogs.MessageBox("Хотите завершить?", "Вопрос", ButFlags)

if ButPressed == mrYes then
  DC.ExecuteCommand("cm_Exit")
end

(наверх)

Маленький скрипт, использующий Dialogs.InputQuery:

bAck, sAnswer = Dialogs. InputQuery("Идентификация", "Введите ваше имя:", false, "Иван")

if bAck == true then
  Dialogs.MessageBox("Привет, " .. sAnswer .. "!", "Добро пожаловать!", 0x0040)
end

(наверх)

Эта библиотека обеспечивает базовую поддержку кодировки UTF-8.

Все функции представлены в таблице LazUtf8.

Библиотека UTF-8
ФункцияОписание

LazUtf8.Pos

Result = LazUtf8.Pos(SearchText, SourceText, Offset)

Поиск подстроки в строке, начиная с определённой позиции. Поиск чувствителен к регистру.

Возвращает позицию первого вхождения подстроки SearchText в строке SourceText, поиск начинается с позиции Offset (по умолчанию 1).

Если в SourceText не найдено совпадение с SearchText после заданного Offset, то функция возвращает ноль.

LazUtf8.Copy

Result = LazUtf8.Copy(Source, Index, Count)

Копирует (извлекает) часть строки.

Функция возвращает Count символов из строки Source, начиная с позиции Index.

Если Count больше длины строки Source, то результат усекается. Если Index больше длины строки Source, то возвращается пустая строка.

LazUtf8.Length

Result = LazUtf8.Length(String)

Возвращает количество символов в строке с учётом кодировки UTF-8.

LazUtf8.UpperCase

Result = LazUtf8.UpperCase(String)

Возвращает строку, в которой все буквы в нижнем регистре (строчные) заменены на буквы в верхнем регистре (прописные или заглавные).

LazUtf8.LowerCase

Result = LazUtf8.LowerCase(String)

Возвращает строку, в которой все буквы в верхнем регистре (прописные или заглавные) заменены на буквы в нижнем регистре (строчные).

LazUtf8.ConvertEncoding

Result = LazUtf8.ConvertEncoding(String, FromEnc, ToEnc)

Конвертирует кодировку String из FromEnc в ToEnc.

Список поддерживаемых значений кодировок:

  • Системная кодировка по умолчанию (зависит от локали): «default».
  • Кодировка ANSI (Windows) по умолчанию (зависит от локали): «ansi».
  • Кодировка OEM (DOS) по умолчанию (зависит от локали): «oem».
  • Юникод: «utf8», «utf8bom», «ucs2le», «ucs2be».
  • ANSI (Windows): «cp1250», «cp1251», «cp1252», «cp1253», «cp1254», «cp1255», «cp1256», «cp1257», «cp1258».
  • OEM (DOS): «cp437», «cp850», «cp852», «cp866», «cp874», «cp932», «cp936», «cp949», «cp950».
  • ISO 8859: «iso88591», «iso88592», «iso885915».
  • Другие: «macintosh», «koi8».
Специальные значения кодировок (примеры).

В Windows с русской локалью:

  • «default» — cp1251
  • «ansi» — cp1251
  • «oem» — cp866
В Linux с русской локалью:
  • «default» — utf8
  • «ansi» — cp1251
  • «oem» — cp866

(наверх)

Эта библиотека содержит функции, связанные с операционной системой, в которой запущен Double Commander.

Список доступных функций:

Библиотека OS
ФункцияОписание

os. execute

resultcode = os.execute(command)

Выполнить command, аналогично введённой в командной строке, будет возвращён код завершения.

command может быть:

  • Команда терминала, например, os.execute("dir > all.txt")
  • Исполняемый файл, например, os.execute("C:\\Windows\\System32\\calc.exe")
  • Исполняемый файл с параметрами:
    os.execute("C:\\Utils\\fsum.exe -md5 test.bin > md5.txt")

os.tmpname

tempfilename = os.tmpname()

Возвращает строку с именем файла, который может быть использован в качестве временного файла.

os.remove

bresult, errorstr, errorno = os.remove(filename)

Удалить файл с именем filename.

Если удалось, функция вернёт true.

Если не удалось, функция вернёт:

  1. nil как индикатор неудачи
  2. errorstr с описанием ошибки
  3. errorno в виде кода ошибки (число)

os.rename

bresult, errorstr, errorno = os.rename(nameS, nameD)

Переименовать файл nameS в nameD.

Если удалось, функция вернёт true.

Если не удалось, функция вернёт:

  1. nil как индикатор неудачи
  2. errorstr с описанием ошибки
  3. errorno в виде кода ошибки (число)

os.getenv

value = os.getenv(variablename)

Получить в value значение переменной окружения variablename.
Если переменная не существует, то функция вернёт nil.

(наверх)


Lua-скрипты: примеры, как установить и запустить

Lua не является интерпретированным языком и генерирует байт-код из другой программы, например, Java. Эта программа работает на виртуальной машине Lua VM. Большинство таких устройств называются стеками, но Lua отличается тем, что она основана на регистрах и является одной из первых широко используемых VM в игровой сфере.

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

Коротко про Луа

Lua — это простой в освоении и быстрый скриптовый язык с синтаксисом типа pascal. Это позволяет начинающим программистам писать свои собственные программы. Он используется во многих играх и приложениях для расширения существующей функциональности и программирования пользовательских последовательностей. В интернете есть много обучающих программ, которые помогают работать на этом языке, в том числе много информации можно найти на домашней странице Lua.

Этот язык программирования был создан в Бразилии в 1993 году программистами Роберто Иерусальшимом, Луисом Энрике де Фигеиредо и Вальдемаром Целесом в университете Рио-де-Жанейро, где по-прежнему находится офис «LabLua». Название происходит от португальского, что в переводе значит — луна. Одним из предшественников был язык SOL (Simple Object Language). Поскольку имя Lua является существительным, а не аббревиатурой, оно не должно писаться, как LUA, а именно как Lua.

Это гибкий язык, он используется на нескольких направлениях:

  • Википедия применяет Lua для сценариев шаблонов.
  • Медиаплеер VLC работает со сценариями Lua-скриптов для quik.
  • Lua используется в промышленных приложениях, таких как Adobe Lightroom.
  • Программы для встроенных систем, таких как промежуточное ПО Ginga для цифрового телевидения.
  • Игры — язык является ведущим для сценариев в играх, например, используется при создании World of Warcraft и Angry Birds.
  • Каждому доступно попробовать применения кода онлайн в Lua Demo с интересным способом изучения и использованием игрового движка.
  • Функционал этой программы можно использовать в LÖVE, Defold и, конечно же, в Pico-8.

    Основы синтаксиса

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

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

    Переменные могут содержать любую последовательность цифр, букв и подчеркиваний, но они не должны начинаться с числа. Null представляет ключевое слово, когда переменные не определены. Необъявленные неотличимы от объявленных переменных, которые не имеют значения. Примеры скриптов Lua:

    Блоки кода и операторы if

    Блоки определяются определенными ключевыми словами, после чего следует «end». Условия в if операторах должны сопровождаться ключевиками «then». If заявления используют «elseif», а не «else if». Можно создать новую пустую область с «do…end» блоком.

    Lua использует особый тип данных, называемый таблицей, предназначенный для целей создания массивов, словарей, хеш-карт, объектов других языков. Таблицы — это просто список пар «ключ-значение», которыми может быть любой тип данных, даже другие таблицы. Можно использовать логическое значение в качестве ключа. Поскольку Lua динамически типизируется, можно иметь любую смесь типов данных в обоих ключах и значениях по выбору пользователя, с которые нужно определиться перед тем, как устанавливать Lua скрипты.

    Значения таблиц могут быть определены как внутри, так и отдельно. Обычно есть два способа получить и установить их значения, синтаксис «точка», например, «myTable.a», и синтаксис скобки, например, «myTable[«a»]». При использовании строковых ключей можно использовать только синтаксис точек и нельзя применять его, если строка начинается с числа.

    Каждое значение в таблице учитывается, nil — если оно не установлено. Это означает, что невозможно определить, объявлено ли значение в таблице или это просто нуль, если оно никогда не было определено раньше. Это означает, что если ключи в таблице указаны и установлены на нуль, это не будет иметь никакого эффекта, вернее, оно будет таким, каким было бы в случае, если бы их и не определяли вовсе. В Lua таблицы с числовыми ключами начинаются с индекса 1, а не 0. Это то, что вызывает большую головную боль для программистов. Можно разделить встроенные элементы таблицы запятой или точкой с запятой.

    Сложный тип данных

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

    Цифры в Lua используют только в одном виде — своего собственного числа. Нет таких типов, как int, float, long, double и других, как в прочих языках и это надо учитывать перед тем, как устанавливать Lua-скрипты. Технически все значения в Lua представляют собой числа с плавающей запятой.

    Lua имеет только «=» оператор для определения и увеличения. В нем нет «+=», «-=», «++» или чего-нибудь еще. Оператором конкатенации является «…». Можно применять эту операцию на строках и номерах без проблем. Однако нельзя объединять другие типы данных — логические или табличные. Можно получить длину таблицы или строки с «#» оператором и это работает только для массивов с числовыми индексами. Например, код не будет работать с таблицами, которые имеют строковые индексы.

    Циклические типы Loops

    Существует четыре типа циклов Loop, что в переводе означает петля или виток.

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

    Numeric for loop (цифровой). Цикл применяет переменную local для своей области и увеличивает или уменьшает ее. Пользователь объявляет и определяет переменную, которую нужно использовать и за которой следует значение цели.

    Generic for loop (генерируемый) — использует функцию итератора. Она вызывается повторением каждого цикла и возвращает значения, которые будут применены в ней.

    Pairs (пары) является функцией итератора в глобальном масштабе. Она принимает таблицу в качестве аргумента, возвращает индекс и значение каждой переменной в таблице. Код будет перебирать даже ненулевые индексы. У нее есть «брат» — «ipairs», который делает точно то же самое, за исключением того, что работает только с числовыми индексами и останавливается, когда достигается значения nil.

    Repeat loop (повторение) похож на while, за исключением того, что проверка условий проводится в конце блока, а не в начале. Перед тем как открыть lua скрипт нужно учитывать, что код внутри будет запускаться не менее одного раза. Цикл повторения обычно избегают в разработке этого языка, поскольку его прецедент ограничен и трудно читаем из-за того, что не использует стандартный do..end синтаксис.

    Метод функций

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

    Существует два способа определения функции в Lua. Первое объявление является глобальным, так как не существует локального ключевого слова. Как правило, глобальные функции считаются приемлемыми. Тем не менее пользователь все равно может сделать их локальными, если нужно, поставив «local» фронт. Можно также объявить переменные до того, как определить функции, которые все равно похожи на любой другой тип данных. Можно передать их, назначить переменными или принять столько аргументов, сколько нужно, с помощью синтаксиса «…». Фактическим объектом «…» является «tuple» (кортеж), поэтому нужно окружить его фигурными скобками, чтобы превратить данные в таблицу.

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

    Глобальное пространство имен

    «Луа» предоставляет несколько таблиц в глобальном пространстве имен, которые содержат вспомогательные функции, такие как «string», «table» и «math». Таким образом, пользователь никогда не должен указывать какую-либо переменную из названных, поскольку они будут перераспределять массивы, содержащие полезные функции.

    Существуют две таблицы, которые совместно используются всеми сценариями на сервере или клиенте (но не для обоих) — это «_G» и «shared». Первая — поистине глобальная, реализуемая через отдельные скрипты, поэтому, если нужно получить или установить значения из нее, используют «_G.something».

    «Strings» (Струны) — этой функцией Lua может несколькими способами определить строковый литерал и многострочные данные, используя двойные квадратные скобки. И также можно поместить любое количество знаков равенства (=) между квадратными скобками ([===[ … ]===]). Они сбалансированы, могут включать в себя последовательности внутри, как ]]. Lua также имеет собственный набор встроенных функций манипуляции строками и собственную, вытесненную версию регулярных выражений, называемых строковыми шаблонами.

    Игровой лунный сценарий

    Это очень простые первые шаги по написанию программы, но они являются хорошими отправными точками для взлома скриптов Garry Mod 10 Lua. Первый шаг — создают фактический файл сценария Lua. Открывают текст или редактор — блокнот будет отлично работать для этой цели. Далее сохраняют этот файл, прописывая, как на рисунке.

    Где:

    • <Steamname> — имя пользователя паролей.
    • <Garry’s Mod Install location> — каталог Steam для Garry’s Mod.

    Место установки по умолчанию для Lua-скриптов для garry s mod обычно «C:Program FilesSteamsteamapps\garrysmod», но может отличаться на компьютере — «autorunclient». Любые файлы сценариев, помещенные в этот каталог, будут запускаться при запуске Lua на клиенте, например, когда начнется новая игра или пользователь присоединяется к серверу. Далее создают файл типа Hello World, добавляя к нему сценарий lua mod скриптов. Это самый простой вариант.

    Это может казаться немного запутанным сразу. Скрипт выдает содержимое таблицы (какие массивы или списки вызываются) и перехватывает данные до команды консоли, чтобы подтвердить, что требуется определить функцию, которая которая не принимает никаких параметров и не возвращает значения, но обязательно устанавливает «конец» в конце своих команд.

    Функции — это модульные фрагменты кода, которые можно использовать несколько раз. В этом примере показано, как запустить скрипт Lua. Здесь создан список строк, но пользователь также может вставлять и другие объекты. Таблицы являются ассоциативными или хешированными. Это означает, что каждый элемент в списке может ссылаться на ключ.

    Эти команды распечатывают все элементы в таблице, а структура называется циклом. Обращают внимание на команду пары «myTable», которая запускается один раз для каждого элемента и возвращает пары ключ/значение для значений в списке.

    Значение — это элемент в таблице, а ключ — это просто способ ссылки на него. Этот пример показывает, как выводить текстовые и значения переменных с той же командой печати. Переменные «ключ» и «значение» устанавливаются в цикле выше. Обращают внимание на «…» между строками и переменными. Символ «…» — оператор конкатенации Lua. Это говорит языку, что нужно склеить два элемента вместе и рассматривать их как одну текстовую строку «.concommand.Add»:

    • my_test_function;
    • myTestFunction.

    Запись создает консольную команду, которая запускает только что инициированную функцию. Первым ее параметром является имя команды управления, в этом случае: «my_test_function». Это то, что пользователь вводит в консоль мод Garry для запуска скрипта.

    Второй параметр — это функция для запуска, в этом случае: myTestFunction. Этот файл впоследствии потребуется сохранить. Далее тестируют скрипт, запускают Garry’s Mod и новую игру. После этого открывают консоль, используя тильду (~). Если она не появляется, тогда нужно ее включить, вводя «my_test_function» в строку в нижней части панели. После запуска начнется автоматическое заполнение экрана с именем команды, нажимают Enter, чтобы ее запустить.

    Возможности Lua-Quick-Try-Out

    Эта консоль предназначена для прямого ввода кода Lua (например, команда команды Lua (8 + 9) сразу выводит результат 17).

    Ее функции:

  • Основное окно для исходного кода с функциями его сохранения и загрузки.
  • Отладчик сценария с точками останова, одноступенчатое выполнение и вид переменной.
  • Функции для создания таблиц.
  • Функции для создания диаграмм.
  • Функции для создания графических изображений.
  • Функции для создания векторных графиков.
  • Онлайн-помощь для создания функций Lua.
  • Точки консоли останова могут быть установлены щелчком рядом с номером строки. Если режим отладки включен, вид переменной будет виден в правой части главного окна. Ее размер можно изменить, перетаскивая левую границу. Различные параметры режима отладки «вкл.» или «выкл.» сохраняются и восстанавливаются, когда он включен или отключен. Можно применять колесико мыши для изменения видимого размера диаграмм и графики. Правую кнопку мыши можно использовать, чтобы открыть контекстное меню для диаграмм с функциями их масштабирования.

    SAMP Lua-скрипты — это библиотека lua для MoonLoader, которая добавляет некоторые команды, чтобы упростить модификацию SA: MP,SAMP. Events дает возможность обрабатывать SA: MP входящие и исходящие низкоуровневые сетевые пакеты очень простым способом. Можно переписать данные, установив все аргументы в таблице в правильном порядке или можно прервать обработку любых пакетов, вернув false, которая предотвращает изменение пользователем позиции игрока.Перед тем как установить Lua-скрипт samp, можно добавить собственный обработчик пакетов.

    Дистрибутив Lua-WoW

    Так называется дистрибутив исходного кода Lua, модифицированный для соответствия среде аддонов World of Warcraft.

    Его данные:

  • Администраторы: morlando.
  • Пользователи: morlando.
  • Лицензия: MIT / X.
  • Язык: c, lua 5.
  • Метки: переводчики, средства тестирования.
  • Операционные системы: macros, windows, os independent.
  • Эта версия языка настроена на соответствие среде Lua World of Warcraft. Все параметры совместимости 5.0-5.1 отключены, кроме openlib. Библиотека битлиба работает. Некоторые wow Lua скрипты — специфичные, Lua-библиотечные функции реализованы.

    Программой предоставляются глобальные псевдонимы для функций «Lua.string.format», они могут использовать выбор аргументов из Lua 4.0. Двоичные файлы Windows, включенные в эту загрузку, статически связаны для производительности. Они могут работать не так, как ожидалось пользователем, при использовании с некоторыми сторонними пакетами.

    История версий:

  • V1.12 — добавлен скраб, tostringall, проект Visual Studio обновлен до Visual Studio 2008 Visual C ++. Runtime теперь статически связана, что должно устранить некоторые проблемы, связанные с lua-wow при определенных установках Windows.
  • Lua скрипты v34 c — добавлено strrelpace (string.replace, wow.strreplace).
  • V1.10.1 — добавлен msvcr80.dll в проект windows.
  • V1.10 — реорганизованные файлы readme. Переименованные проекты msvc и имена выхода exe. Проект msvc включает в себя значок и ресурсы Lua для исполняемых файлов.
  • V1.9 — добавлены глобальные версии тригонометрических функций. Программа правильно используют градусы .strsplit, напечатает соответствующее сообщение об ошибке, если оно переполнит стек, что теперь уже невозможно практически с помощью strjoin.
  • V1.8 – обновленная совместимость 5.0 openlib, поскольку WoW не использует libs в любом случае.
  • V1.7 — изменено GCPAUSE до 110 на WoW 2.1. Устранено несколько разных предупреждений компилятора.
  • V1.6.1 — добавлен #define LUA_LIB для lwowlib & lbitlib для исправления проблем компиляции в Lua скриптах для самп.
  • V1.6 — обновлен битлиб до последней версии. Теперь он корректно использует 32-битные целые числа, как WoW. Глобальные псевдонимы для функций bitlib и table.setn были удалены, поскольку они не существуют в WoW.
  • V1.5.1 — игнорирует знак порядка байтов UTF-8.
  • V1.5 — добавлен debugstack, сделаны некоторые небольшие оптимизации и упрощения кода.
  • V1.4 — добавлен выбор аргумента в string.format.
  • V1.3.1 — исправлена проблема с Makefile.
  • V1.3 — добавлены специфичные функции, глобальные псевдонимы, css Lua скрипты.
  • V1.2 — этот пакет теперь можно использовать в качестве замены для стандартного дистрибутива источника Lua: проект MSVC, включая предварительно скомпилированные двоичные файлы Windows, теперь находятся в подкаталоге msvc, остальная структура каталогов не затронута.
  • V1.1 — добавлен BitLib. Оптимизированный размер файла Luac.exe. Включает в себя тестовые программы.
  • Игровой движок Pico-8

    Pico-8 — это фантастическая программа, которая эмулирует полную игровую консоль с ограниченными 8-битными спецификациями. Она имеет все необходимые инструменты для программирования на языке Lua. Причина, по которой пользователи выбирают Pico-8, заключается в том, что ее можно использовать прямо из коробки, без необходимости настройки или внешних редакторов, все инструменты включены в пакет Lua-скриптов для самп, а обучение довольно простое.

    Порядок работы:

  • Обычно принято называть первую программу, которую создают на новом языке, программой «Hello world», но для языка программирования Lua набирают «Hello Lua».
  • Скачивают Pico-8.
  • Устанавливают и запускают.
  • После загрузки поступит приглашение «>».
  • Чтобы получить обзор возможных команд, нажимают ESC.Теперь, когда редактор открыт, вводят коды, указанные на рисунке выше.
  • Нажимают ESC еще раз, чтобы вернуться к приглашению, вводят CLS, а потом RUN.
  • Получают первую программу Lua на Pico-8.
  • Для сохранения скрипта используют команду SAVE: SAVE HELLOLUA.
  • Если нужно поработать с программой, можно применить функцию BTN (), которая обеспечивает реагирование на нажатия клавиш.
  • Чтобы иметь больше графических возможностей, используют две специальные функции обратного вызова, называемые UPDATE и _DRAW.Следующая программа позволяет перемещать круг с помощью клавиш курсора.
  • Нажимают ESC, чтобы перейти к редактору кода, вводят или копируют и вставляют код, как на рисунке ниже.
  • Нажимают escape, чтобы вернуться в консоль, и вводят RUN.
  • Pico-8 предназначена только для отображения символов верхнего регистра, поэтому можно просто набирать шрифт, нет необходимости использовать Shift или Caps-lock. Редактор также имеет синтаксическую раскраску для кода. Если посмотреть в верхнем правом углу редактора, можно увидеть несколько значков. Это встроенные инструменты для создания спрайтов, карт, звуков и музыки. Этот пример довольно простой, но дает представление о редакторе и языке.

    Чтобы исследовать более интересные примеры, можно перейти в каталог DEMOS. Для этого вводят: INSTALL_DEMOS. После открывается каталог DEMOS с несколькими примерами программ для изучения. Одним из главных преимуществ Lua является его простота. Некоторые компании используют этот язык исключительно из-за этого, поскольку думают, что их сотрудники смогут работать лучше.

    Некоторые очень простые языки, такие как Bash или Batch, не будут достаточно сильными, чтобы выполнять требуемые задачи, но Lua является одновременно мощной и простой программой. Другим важным преимуществом Lua скриптов для css v34 является их способность внедряться, что признается одной из важнейших характеристик этого продукта на протяжении всего этапа его развития. Такие игры, как World of Warcraft или ROBLOX, имеют возможность встраивать Lua в свое приложение.

    Подключение к КВИКу | jato

    Подключение Jatotrader© к КВИКу через луа-скрипт.

    Пошаговая инструкция.

    ВНИМАНИЕ! С настоящего момента Jatotrader можно подключать к терминалу КВИК версии 8 и выше. Поддержка подключения к КВИКу ниже версии 8 осуществляться не будет.

    Новый луа-скрипт, называется QuikLuaJatoConnector. lua.  Со старым скриптом QuikLuaJATOFastest.lua программа больше не работает!

    Установка коннектора JatoTrader-КВИК

    В главном меню программы JatoTrader© нажмите кнопку «Настройки соединения».

    (1) В окне настроек задайте путь к КВИКу через который вы будете совершать торговые операции. Обратите внимание, что последним символом в имени пути должен быть обратный слэш «\» . Например: C:\Open_Broker_QUIK\.

    (3) В полях «AccountT+» и «Client code T+» введите соответствующие значения номера счета и кода клиента, которые можно определить через окно ручного ввода заявки в КВИКе, выбрав в качестве инструмента на ММВБ, например, обыкновенные акции Сбербанка (если вы не собираетесь торговать акциями, то эти поля можно  оставить пустыми):

     

    (2) Ту же процедуру повторите для счета и кода клиента на FORTS («Account FUT» и «Client code FUT»), выбрав в качестве инструмента, например, фьючерсный контракт на индекс РТС.

    Если в поле «Торговый счет» терминала КВИК нет никакого значения, то убедитесь, что торговые счета были выбраны в основном меню КВИКа: «Система»—>»Настройки»—>»Основные настройки»—>»Настройка счетов».

    (4) В нижней части окна «Настроек соединения» в разделе  «Подключение по умолчанию» выберите «КВИК» и нажмите кнопку «Сохранить» . Если вы все сделали правильно появится сообщение:

    Примечание: Если вы желаете установить коннектор вручную, то просто скопируйте содержимое папки \Jatotrader\QUIK8 (а не саму папку!) в папку КВИКа.

     

    Настройка КВИКа для подключения к JatoTrader©

    Запустите КВИК и установите соединение с сервером брокера. Платформа JatoTrader© использует для каждого инструмента тиковые данные и данные биржевого стакана. В КВИКе нужно открыть: «Таблицу обезличенных

     сделок», а также биржевые стаканы, которые нужно передавать в JatoTrader©.

    Чтобы открыть «Таблицу всех сделок» в главном меню КВИКа выберите пункты «Создать окно»—>«Таблица обезличенных сделок». В появившемся окне нажмите кнопку «Да». В таблицу добавьте нужные вам инструменты для анализа и торговли (правая кнопка мыши на таблице, пункт «Редактировать таблицу»). Таблица обезличенных сделок(тиковые данные) в КВИКе выглядит примерно так:

    Если после описанных выше действий «Таблица всех сделок» оказалась пуста, вам следует связаться с вашим брокером и попросить включить трансляцию тиковых данных.

    Если вы не используете в своей работе биржевые стаканы, то для увеличения быстродействия их можно не открывать. Для трансляции биржевых стаканов в JatoTrader© просто откройте в КВИКе нужные «стаканы» 

    через главное меню «Создать окно»—>»Котировки…» 

    Загрузите в КВИК луа-скрипт. В главном меню КВИКа выберите пункт «Сервисы»—>«Луа скрипты». В появившемся окне «Доступные скрипты» нажмите кнопку «Добавить».  Выберите скрипт QuikLuaJatoConnector. lua (после установки коннектора он будет в папке КВИКа, если его там нет, поищите его в папке \Jatotrader\QUIK8, он идет в комплекте поставки).

    Запустите луа-скрипт и дождитесь загрузки данных в Jatotrader. Теперь все готово к успешной работе.

     

    Возможные проблемы при подключении к КВИКу

    1. При запуске луа скрипта QuikLuaJatoConnector.lua в КВИКе появляется сообщение об ошибке:

    Причина: в папке КВИКа отсутствуют необходимые библиотеки.

    Скопируйте содержимое папки \Jatotrader\QUIK8 (а не саму папку!) в папку КВИКа и запустите луа-скрипт снова.

    2. При запуске луа скрипта QuikLuaJatoConnector.lua в КВИКе появляется сообщение об ошибке:

    Причина: КВИК старой версии (ниже 8-й). Обновите КВИК до версии 8.5.2 или выше.

    4. При запуске луа-скрипта в КВИКе (окно «Доступные скрипты») соединение с JatoTrader© не устанавливается, КВИК выдает ошибку:

    Причина: не запущен JatoTrader©.  Запустите  JatoTrader© и повторите попытку.

     

    Lua-скрипт с таймером для тренировок — RCPilots

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

    Как известно, многие гонки дронов проводятся по системе MultiGP: за отведённое время пилотам нужно пролететь как можно больше кругов по трассе. Данный скрипт воспроизводит стартовый и финишный сигналы и предупреждение о скором окончании вылета.

    Как это работает: 

    • Пилот, полностью готовый к вылету, щёлкает тумблером.
    • Через случайный промежуток времени от 2 до 5 секунд раздаётся стартовый сигнал.
    • За 10 секунд до окончания вылета звучит предупредительный сигнал.
    • По истечении двух минут скрипт сигнализирует о завершении вылета.

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

     

     

    Как установить:

    • Скачать архив из гитхаба: https://github.com/alexeystn/droneracing-timer-lua-script/archive/master.zip
    • Поместить содержимое папки /TELEMETRY/ из архива в папку /SCRIPTS/TELEMETRY/ на SD-карте в вашем Таранисе: файл ‘race.lua’ и папку с четырьмя звуками.
    • Назначить на один из экранов телеметрии скрипт ‘race’. Можно сделать как с аппы, так и через Companion.
    • Теперь скрипт можно запустить с главного экрана долгим нажатием кнопки ‘Page’.

    Скрипт тестировался на Таранисе Q X7 с OpenTX 2.2.2, но также должен работать и на X9 и X-Lite. Если у вас возникнут проблемы на данных передатчиках, не стесняйтесь сообщить мне об этом.

    Приятных полётов и продуктивных тренировок!

    Автор — Алексей Станкевич. https://t.me/AlexeyStn

    Garry’s Mod: LUA скрипты

    Старая, но прекрасно выполняющая свои функции разработка неизвестного мне автора.

    Данная статья предполагает, что вы играете на сервере, где разрешены кастомные скрипты.

    VAC-бан исключён, если на сервере разрешены кастомные скрипты, и вы смогли загрузить его командой, не используя обход.

    noclip.lua нужно положить в папку, с расположением: ..Steam/steamApps/common/Garry’s mod/garrysmod/lua

    Команда загрузки скрипта: lua_openscript_cl noclip.lua

    Активация меню — Insert.

    Функции:

    [spoiler]

    MAIN-CONFIG — Главная отличительная черта данного скрипта — возможность сохранить все изменения в отдельный файл для каждого сервера, в названии файла название сервера. Файлов можно сохранить неограниченное количество, но при списке больше 50 файлов — иногда происходит баг при загрузке, и меню не закрывается, от чего игра становится невозможно — не создавайте слишком много сейвов. В меню можно перезагрузить сам скрипт, можно выключить его (panic key — кнопка disable справа вверху в окне чита.

    Aimbot — гибкий в настройке автоприцел, способный стрелять по частям тела, наводиться лишь по тем кто находится в поле зрения — и наоборот, по тем кто находится за стенами. Присутствует FOV и эффект смягчения наведения для тех, кто предпочитает «сильно не палиться».

    ESP — Гибкий в настройке ESP (Впрочем, тут почти во всём гибкая настройка)
    Возможность включить фильтр отрисовки; Друзья, Враги, Команда(те, у кого такой же скин), NPC, Наблюдатели. 
    Возможность выбрать элементы для отображения: Ник, здоровье, оружие, дистанция, здоровье(шкала), команда(цвет), коробка(квадрат/3D прямоугольник).
    Возможность включить отрисовку entity, список которых составляется вручную, так же поддерживается коробка

    Misc — Возможность выбрать для отображения в небольшом окне слева вверху админов и наблюдателей.

    Манипулятор временем позволяет ускорить игровое время, но это не дает спидхака, и не ускоряет получение зарплаты/возрождение, поскольку работает лишь у хоста сервера.

    Не до конца понятно, зачем эта функция была добавлена.

    ENTS[/color — Управление списком интересных вам  entity сервера с функцией обновления спика, очищения списка, сохранения набора entity в отдельный файл (не путать с config — это отдельное меню и отдельные файлы, которые не видны из других менеджеров сохранения)

    FRIENDS — Список друзей составленный по SteamId с отображением ников. После составления его можно переключить в список врагов. Внимание — если нажать Friends is enemy до составления списка — вы не сможете переместить человека ни в список друзей, ни в список врагов — почему-то свитчер перестает работать в этом случае. Составляйте заранее.

    CAMS — Функция, в честь которой назван сам скрипт. Позволяет открепить камеру от пользователя, имитируя вид от третьего лица (консольный thirdperson), либо вовсе открепить от игрока и летать ей по карте. Она проходит стены и дает весьма не слабый потенциал для вора на Dark RP, трейтора в TTT или убийцы в Murder. Регулятор скорости полёта камеры прилагается.

    Почти бесполезные функции, но всё же присутствующие и требующие описания.

    bhop, который не дает бонуса скорости почти нигде. Тем не менее, присутствуют функции движения боком для более успешной распрыжки, автоматических стрейфов, движения со скоростью прыжка, автоматического прыжка и движения по углам поворота — «W only». Данная функция поворачивает ваш скин под углами, позволяющая прыгать назад, смотря вперед, при этом чтобы вас все видели, будто вы прыгаете нормально — смотря туда, куда прыгая. Удобно при побеге.

    Spam — функция спама сообщениями. С настраиваемой задержкой и обходом защиты от однотипных сообщений. Просто и со вкусом.

    Test 10 и 11 — тестовые функции, которые пока не реализованы. Пустые окна.

    [/spoiler]

    Искренне надеюсь что тут работают коды и я не зря их писал.

    Lua: около

    Lua — мощный, эффективный, легкий встраиваемый язык сценариев. Он поддерживает процедурное программирование, объектно-ориентированного программирования, функциональное программирование, программирование, управляемое данными, и описание данных.

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

    Lua разработан, внедрен и поддерживается а команда в PUC-Rio, Папский католический университет Рио-де-Жанейро в Бразилии. Луа родился и вырос в Текграф, ранее Группа компьютерной графики PUC-Rio. Lua теперь находится по адресу LabLua, лаборатория Департамент компьютерных наук PUC-Rio.

    «Луа» (произносится ЛОО-ах ) означает «Луна» на португальском языке. Таким образом, это не акроним и не аббревиатура, а существительное. В частности, «Луа» — это имя, название луны Земли и название языка.Как и большинство имен, его следует писать строчными буквами с заглавной буквы, то есть «Lua». Пожалуйста, не пишите это как «LUA», что одновременно уродливо и сбивает с толку, потому что тогда это становится аббревиатурой с участием разные значения для разных людей. Так что пишите «Lua» правильно!

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

    Ты можешь лично познакомиться с частью сообщества Lua, посетив а Мастерская Lua.

    Присоединяйтесь к нам на Lua Workshop 2021, состоится во Фрайбурге в октябре.

    Вы можете помочь поддержать проект Lua от покупка книги опубликовано Lua.org и по делать пожертвование.

    Вы также можете помочь распространить информацию о Lua, купив продукты Lua. в Zazzle.

    Lua — проверенный и надежный язык.

    Lua использовался в многие промышленные применения (например., Adobe Photoshop Lightroom), с упором на встроенные системы (е.г., то Джинга промежуточное ПО для цифрового ТВ в Бразилии) и игры (например., World of Warcraft и Angry Birds). Lua в настоящее время ведущий скриптовый язык в играх. Lua имеет твердую справочное руководство и здесь несколько книг об этом. Несколько версии Lua были выпущены и используются в реальные приложения с момента создания в 1993 году. Lua представлен в HOPL III, Третья конференция ACM SIGPLAN по истории языков программирования, в 2007. Lua выиграл Премия Front Line Awards 2011 от Журнал разработчиков игр.

    Lua быстрый

    Lua имеет заслуженную репутацию за производительность. Утверждать, что он «такой же быстрый, как Lua», — это стремление других языков сценариев. Несколько тестов показывают Lua как самый быстрый язык в области интерпретируемых языков сценариев. Lua быстр не только в отлаженных программах тестирования, но и в реальной жизни тоже. Значительная часть больших приложений написана на Lua.

    Если вам нужно еще больше скорости, попробуйте LuaJIT, независимая реализация Lua с использованием оперативного компилятора.

    Lua переносной

    Lua распространяется в небольшом пакете и строит из коробки на всех платформах, которые имеют стандартный компилятор C. Lua работает на всех разновидностях Unix и Windows, на мобильных устройствах (под управлением Android, iOS, BREW, Symbian, Windows Phone), на встроенных микропроцессорах (таких как ARM и Rabbit, для таких приложений, как Lego MindStorms), на мэйнфреймах IBM и т. д.

    По определенным причинам, по которым Lua является хорошим выбором также для устройств с ограничениями, читать это резюме пользователя Mike Pall.Также плакат созданный Тиммом Мллером.

    Lua встраиваемый

    Lua — это быстрый языковой движок с небольшими размерами, который вы можете легко встроить в свое приложение. Lua имеет простой и хорошо документированный API что обеспечивает тесную интеграцию с кодом, написанным на других языках. Lua легко расширить библиотеками, написанными на других языках. С помощью Lua также легко расширять программы, написанные на других языках. Lua использовался для расширения программ, написанных не только на C и C ++, но также в Java, C #, Smalltalk, Fortran, Ada, Erlang, и даже на других языках сценариев, такие как Perl и Ruby.

    Lua мощный (но простой)

    Фундаментальная концепция дизайна Lua — это: предоставить мета-механизмы для реализации функций, вместо того, чтобы предоставлять множество функций прямо на языке. Например, хотя Lua не является чистым объектно-ориентированным языком, он предоставляет мета-механизмы для реализации классов и наследования. Мета-механизмы Lua обеспечивают экономию концепций и сохраняют небольшой размер языка, позволяя расширить семантику нетрадиционными способами.

    Lua маленький

    Добавление Lua в приложение его не раздувает. В tarball для Lua 5.4.2, который содержит исходный код и документацию, занимает 346K в сжатом виде и 1,3M в несжатом. Источник содержит около 29000 строк C. Под 64-битным Linux интерпретатор Lua, построенный со всеми стандартными библиотеками Lua, занимает 278K а библиотека Lua занимает 465 КБ.

    Lua бесплатно

    Lua — бесплатное программное обеспечение с открытым исходным кодом, распространяется под очень либеральная лицензия (известная лицензия MIT).Его можно использовать в любых целях, в том числе в коммерческих, абсолютно бесплатно. Только скачать его и использовать.

    Сценарии Lua — Rainmeter


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

    Сценарий относится к набору функций Lua, связанных с мерой сценария.Эти функции могут выполняться при загрузке скина, при обновлении или по команде.

    На этой странице подробно описаны модификации Rainmeter и новые функции, которые были добавлены во встроенную среду Lua Rainmeter. Дополнительная документация для самого Lua доступна по адресу:

    Остальная часть этой страницы предполагает базовые знания языка Lua.

    Мера сценария

    Показатель сценария используется для загрузки сценария Lua из файла и взаимодействия со сценарием.Файл сценария должен быть текстовым и обычно имеет расширение .lua .

    Как и меры плагина, каждая мера скрипта создает отдельный экземпляр своего скрипта. Это означает, что скин может иметь любое количество загружаемых одновременно сценариев — даже из одного файла сценария. (Порядок выполнения скриптов определяется порядком измерений.) «Глобальные» переменные не используются совместно между экземплярами.

     [MeasureName] 
    Measure = Script
    ScriptFile = MyScript.lua

    Опции

    В дополнение к общим параметрам измерения и ScriptFile сценарии также допускают параметры, определяемые пользователем. Эти параметры могут иметь любое имя и значение и могут быть изменены с помощью! SetOption. Сценарий может читать и использовать собственные значения параметров с помощью объектных функций SELF. Это позволяет использовать один и тот же файл сценария с разными параметрами в зависимости от контекста.

     [MeasureName] 
    Measure = Script
    ScriptFile = MyScript.lua
    MyOption = Привет, мир!

    Динамические переменные

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

    ! CommandMeasure

    Команда! CommandMeasure bang может использоваться для выполнения кода Lua в контексте конкретного экземпляра скрипта:

    ! CommandMeasure «MyScriptMeasure» «MyFunction ()»

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

    ! CommandMeasure "MyScriptMeasure" "a = b; print (SKIN: ParseFormula ('(2 + 2)'))"

    Все операторы должны передаваться как один параметр в bang. Поскольку одинарные кавычки ( ') и двойные кавычки ( ") являются допустимыми контейнерами строк в Lua, в то время как в Rainmeter распознаются только двойные кавычки, при передаче строк с помощью! CommandMeasure.

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

    Инициализировать

    Если функция Initialize определена в каком-либо скрипте, функция вызывается один раз (без параметров) при активации или обновлении темы оформления.Это происходит, даже если мера скрипта отключена. Если файл сценария изменяется с помощью команды! SetOption, также вызывается функция Initialize нового сценария.

     function Initialize () 
    MyVariable = 'Привет, мир!'
    конец

    Действия, необходимые для «настройки» сценария, такие как объявление глобальных переменных, должны выполняться в функции Initialize.

    Использование dofile

    Функцию dofile можно использовать для включения библиотек или других фрагментов кода Lua.Вы должны указать полный путь к dofile, используя синтаксис dofile ('C: \ PathToDoFile \ SomeLua.lua') . Используйте функцию GetVariable, если вы хотите использовать ярлык переменной # @ # для папки @Resources для текущей конфигурации, или MakePathAbsolute, если вы хотите, чтобы файл .lua располагался относительно текущей папки скинов.

     функция Initialize () 
    dofile (SKIN: GetVariable ('@') .. 'MyDoFiles \\ toolkit.lua')
    dofile (SKIN: MakePathAbsolute ('toolkit.lua'))
    end

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

    Обновление

    Если функция Update определена в любом скрипте, функция вызывается (без параметров) всякий раз, когда обновляется мера скрипта. Мера скрипта обычно реагирует на параметр Disabled, параметр UpdateDivider и все удары измерения.

     Обновление функции () 
    MyVariable = 'Hello, world!'
    return MyVariable
    end

    Возвращаемое значение функции обновления определяет, какие значения предоставляются мерой сценария.Строки и числа в Lua аналогичны строковым значениям и числовым значениям в мерах Rainmeter. Примеры:

    • return
      Предоставляет 0 как числовое значение и » (пробел) как строковое значение. То же самое верно, если не указано return .

    • return 99
      return '99'
      В любом случае предоставляет 99 как числовое значение и ’99’ как строковое значение.

    • return 'Девяносто девять'
      Предоставляет 0 как числовое значение (поскольку строка не может быть преобразована в число) и ‘Девяносто девять’ как строковое значение.

    Значения, предоставленные мерой сценария, можно использовать так же, как и другие значения меры. (Примечание : значения обновляются только при обновлении самой меры. Вызов Update () в Lua не обновляет значения меры.)

    Журнал

    ошибок Lua регистрируется в окне «О программе».Функцию печати также можно использовать для записи строк в журнал. Это может обеспечить полезную обратную связь при написании или устранении неполадок скрипта.

    print ('Текущее значение MyVariable:' .. MyVariable)

    Функции

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

    СКИН объект

    Объект SKIN создается автоматически.

    GetMeasure Параметр: MeasureName

    Создает дескриптор для именованной меры. Возвращает nil , если мера не найдена.

    Пример: MyMeasure = SKIN: GetMeasure ('MeasureName')

    GetMeter Параметр: MeterName

    Создает объект ручки для названного счетчика.Возвращает nil , если счетчик не найден.

    Пример: MyMeter = SKIN: GetMeter ('MeterName')

    GetVariable Параметр: Имя переменной , по умолчанию

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

    Пример: MyVariable = SKIN: GetVariable ('VariableName', 'n / a')

    GetX

    Возвращает текущую позицию X окна скина в виде числа.

    Пример: MyX = ​​SKIN: GetX ()

    GetY

    Возвращает текущую позицию Y окна скина в виде числа.

    Пример: MyY = SKIN: GetY ()

    GetW

    Возвращает текущий размер окна скина в виде числа.

    Пример: MyW = SKIN: GetW ()

    GetH

    Возвращает текущий размер H окна скина в виде числа.

    Пример: MyH = SKIN: GetH ()

    MoveWindow Параметры: X , Y

    Перемещает окно скина в положение экрана, определяемое целочисленными параметрами X и Y .

    Пример: SKIN: MoveWindow (200,100)

    FadeWindow Параметры: от , до

    Уменьшает непрозрачность окна обложки от начального целочисленного значения до конечного целочисленного значения.Допустимые значения от 255 (непрозрачный) до 0 (прозрачный). Обратите внимание, что мышь не будет обнаружена с непрозрачностью 0 в окне скина.

    Скорость затухания контролируется настройкой FadeDuration для кожи.

    Пример: СКИН: FadeWindow (255,100)

    Bang Параметры: BangName , BangArg1, BangArg2, BangArgN

    Выполняет удар. Удар будет выполнен Rainmeter, когда управление будет возвращено из скрипта.

    Каждый параметр взрыва — это отдельный параметр в функции.

    Пример:

     someVar = 12 
    SKIN: Bang ('! SetOption', 'MeterName', 'Text', 'Hello, world!')
    SKIN: Bang ('! SetOption', 'MeterName', 'FontSize', someVar)
    SKIN: Bang ('! UpdateMeter', 'MeterName')
    SKIN: Bang ('! Redraw')

    Примечание: ! Delay bang в Rainmeter не поддерживается в Lua.

    MakePathAbsolute Параметр: Файл / папка

    Преобразует относительный путь к файлу в полный путь к файлу.Путь будет относиться к папке со скинами.

    Пример: MyPath = SKIN: MakePathAbsolute ('MyImage.png')

    ReplaceVariables Параметр: Строка

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

    Пример: MyString = SKIN: ReplaceVariables ('Значение MyVariable - # MyVariable #.')

    ParseFormula Параметр: FormulaString

    Если заданная строка является допустимой формулой, вычисляет формулу и возвращает результат в виде числа. В противном случае возвращает ноль . Это может использовать математические функции в Rainmeter, которые не могут быть встроены в Lua. Помните, что формулы в Rainmeter должны быть полностью заключены в (круглые скобки).

     numToRound = 239.78 
    roundedNum = SKIN: ParseFormula ('(Round (' .. numToRound .. '))')

    Измерение объекта

    Объект Measure создается с помощью GetMeasure. Он создает дескриптор определенной меры в скине, которую затем можно использовать со следующими функциями для воздействия на меру.

    Пример: MyMeasure = SKIN: GetMeasure ('MeasureName')

    GetValue

    Возвращает текущее числовое значение меры.

    Пример: MyMeasureValue = MyMeasure: GetValue ()

    GetStringValue

    Возвращает текущее строковое значение меры.

    Пример: MyMeasureValue = MyMeasure: GetStringValue ()

    GetOption Параметры: Имя опции , по умолчанию

    Возвращает текущее значение указанной опции в виде строки.Если параметр не существует, возвращает заданное значение по умолчанию или '' , если значение по умолчанию не задано.

    Пример: MyGroup = MyMeasure: GetOption ('Группа', 'Нет')

    GetNumberOption Параметры: OptionName , по умолчанию

    Возвращает текущее значение названной опции в виде числа. Если параметр не существует или не является допустимым числом или формулой, возвращает заданное значение по умолчанию или 0 , если значение по умолчанию не задано.

    Пример: MyUpdateDivider = MyMeasure: GetNumberOption ('UpdateDivider', 1)

    GetName

    Возвращает имя меры в виде строки.

    Пример: MyMeasureName = MyMeasure: GetName ()

    GetMinValue

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

    Пример: MyMeasureMin = MyMeasure: GetMinValue ()

    GetMaxValue

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

    Пример: MyMeasureMax = MyMeasure: GetMaxValue ()

    GetRelativeValue

    Возвращает текущее числовое процентное значение меры в виде числа с масштабированием от 0,0 до 1,0 . Результат будет основан на текущих определенных или производных MinValue и MaxValue меры.

    Пример: MyMeasureValue = MyMeasure: GetRelativeValue ()

    GetValueRange

    Возвращает текущий диапазон значений меры в виде числа.Результат будет основан на текущих определенных или производных MinValue и MaxValue меры, и будет разницей между ними.

    Пример: MyMeasureRange = MyMeasure: GetValueRange ()

    Отключить

    Отключает меру.

    Пример: MyMeasure: Disable ()

    Включить

    Включает измерение.

    Пример: MyMeasure: Enable ()

    SELF объект

    Объект SELF создается автоматически. SELF — это объект меры, связанный с текущей мерой скрипта. Все функции объекта измерения действительны для SELF .

    MyScriptMeasureName = SELF: GetName ()

    Метр объекта

    Объект Meter создается с помощью GetMeter. Он создает ручку для конкретного измерителя в коже, которую затем можно использовать со следующими функциями для воздействия на измеритель.

    Пример: MyMeter = SKIN: GetMeter ('MeterName')

    GetOption Параметры: Имя опции , по умолчанию

    Возвращает текущее значение указанной опции в виде строки.Если параметр не существует, возвращает заданное значение по умолчанию или '' , если значение по умолчанию не задано.

    Пример: MySolidColor = MyMeter: GetOption ('SolidColor', '000000')

    GetName

    Возвращает имя счетчика в виде строки.

    Пример: MyMeterName = MyMeter: GetName ()

    GetX Параметры: Абсолютный

    Возвращает текущую позицию X измерителя в виде числа.Если необязательный параметр Absolute равен true , возвращает абсолютное (или «реальное») положение X, которое может отличаться от заданного параметра на измерителе.

    Пример: MyX = ​​MyMeter: GetX ()

    GetY Параметры: Абсолютный

    Возвращает текущую позицию Y измерителя в виде числа. Если необязательный параметр Absolute равен true , возвращает абсолютное (или «реальное») положение Y, которое может отличаться от заданного параметра на измерителе.

    Пример: MyY = MyMeter: GetY ()

    GetW

    Возвращает текущую «реальную» ширину счетчика в виде числа.

    Пример: MyW = MyMeter: GetW ()

    GetH

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

    Пример: MyH = MyMeter: GetH ()

    Набор X

    Устанавливает положение X измерителя.

    Пример: MyMeter: SetX ()

    КОМПЛЕКТ

    Устанавливает положение Y измерителя.

    Пример: MyMeter: SetY ()

    НАБОР

    Устанавливает ширину измерителя.

    Пример: MyMeter: SetW ()

    НАБОР

    Устанавливает высоту измерителя.

    Пример: MyMeter: SetH ()

    Скрыть

    Скрывает счетчик.

    Пример: MyMeter: Hide ()

    Показать

    Показывает счетчик.

    Пример: MyMeter: Show ()

    Ограничения

    Следующие функции Lua в настоящее время недоступны в Rainmeter:

    • Внешние скомпилированные библиотеки, такие как LuaCURL.
    • требует , os.exit , os.setlocale , io.popen и collectgarbage функции .

    Устаревшие функции

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

    • PROPERTIES = {...}
      Эта таблица ранее использовалась для чтения параметров в мере скрипта. Вместо этого используйте:
      SELF: GetOption ('MyOption') или SELF: GetNumberOption ('MyOption')

    • MyMeter: SetText ('... ')
      Эта функция использовалась для изменения текста счетчика строк. Вместо этого используйте:
      SKIN: Bang ('! SetOption', 'MeterName', 'Text', '...')

    • функция GetStringValue ()
      Эта функция использовалась для установки значения меры скрипта. Вместо этого используйте:
      function Update () ... return ... end

    Создание веб-скриптов с помощью Lua

    Введение

    CGILua использует Lua как серверный скрипт. язык для создания динамических веб-страниц.Оба чистые Скрипты Lua и Страницы Lua (LP) поддерживаются CGILua. Сценарий Lua — это, по сути, программа Lua, которая создает все содержимое веб-страницу и возвращает ее клиенту. Страница Lua — это обычная текст разметки (HTML, XML и т. д.), который встраивает код Lua с помощью специальных теги. Эти теги обрабатываются CGILua, и результирующая страница возвращается в клиент.

    Lua Scripts и Lua Pages одинаково просты в использовании, и выбор одного из них в основном зависит от характеристик результирующей страницы.Хотя Lua Страницы более удобны для разделения логики и формата, скрипты Lua больше подходят для создания более простых по структуре страниц, но требуют более значительной внутренней обработки.

    Позволяя смешивать эти два метода, CGILua предоставляет веб-приложения разработчики с большой гибкостью, когда присутствуют оба требования. Для подробное описание обоих методов написания сценариев и несколько примеров их использование см. Скрипты Lua и Страницы Lua.

    Архитектура

    Архитектура CGILua разделена на два уровня. Нижний уровень представлен серверным API (SAPI), а на более высоком уровне представлен самим API CGILua. SAPI — это интерфейс между веб-сервером и CGILua API, поэтому его необходимо реализовать для каждого веб-сервера и запустить используемый метод.

    Лаунчер отвечает за взаимодействие CGILua и веб-сервера, реализация SAPI, например, с использованием ISAPI в IIS или mod_lua в Apache.Эталонная реализация пусковых установок CGILua: Кеплер.

    CGILua API реализован с использованием только SAPI и полностью переносим. над различными программами запуска и поддерживающими их веб-серверами. Таким образом, любой скрипт Lua или Lua Page может использоваться любым лаунчером.

    Жизненный цикл запроса

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

    1. Добавьте обработчики по умолчанию, такие как LuaScripts и Lua Pages, а также форматы файлов commom.
    2. Выполните файл config.lua , позволяющий настроить следующие шаги.
    3. Создайте таблицы cgilua.POST и cgilua.QUERY (обработка данных POST и QUERY).
    4. Перейти в каталог пользовательских сценариев.
    5. Выполняет зарегистрированные функции открытия .
    6. Выполнить запрошенный сценарий в правильной среде.
    7. Выполняет зарегистрированные функции закрыть .
    8. Вернуться в исходный каталог

    Редактируя файл config.lua , можно настроить поведение CGILua. Типичное использование — регистрация функций открыть и закрыть . чтобы изменить поведение обработки запроса. С помощью этой настройки можно реализовать новые функции, такие как управление сеансами и каталоги частных библиотек, как показано в разделе Конфигурация или даже внедрение нового абстракции для всего образа жизни CGILua, такие как MVC-frameworks, такие как Orbit.

    Установка

    CGILua следует за модель упаковки для Lua 5.1, поэтому он должен быть «установлен» в вашем package.path .

    Вы также можете установить CGILua, используя LuaRocks:

    luarocks установить cgilua
     

    Конфигурация

    Дистрибутив Kepler для CGILua 5.1 предлагает один файл конфигурации с именем config.lua . Этот файл можно использовать для изменения поведения CGILua по умолчанию, и он находится в каталоге конфигурации Kepler.

    Некоторые из вариантов использования настройки config.lua :

    Обработчики скриптов
    Обработчик отвечает за ответ на запрос. Вы можете добавить новые обработчики CGILua, используя cgilua.addscripthandler (см. также cgilua.buildplainhandler и cgilua.buildprocesshandler для функций, которые создают простые обработчики).
    Размеры данных POST
    Вы можете изменить ограничения размера данных POST, используя cgilua.setmaxinput и cgilua.setmaxfilesize .
    Функции открытия и закрытия
    Вы можете добавить свои функции в жизненный цикл CGILua, используя cgilua.addopenfunction и cgilua.addclosefunction . Эти функции выполняются непосредственно до и сразу после выполнения скрипта, даже при возникновении ошибки в обработке скрипта.

    В частности, функции открытия и закрытия полезны для разных вещей.Далее показаны некоторые примеры использования таких функций в файле config.lua .

    Предыдущие версии CGILua загружали файл env.lua из каталог скрипта перед его обработкой. Чтобы эмулировать это с помощью CGILua 5.1, вы можете используйте что-то вроде:

    cgilua.addopenfunction (функция ()
       cgilua.doif ("env.lua")
    конец)
     

    Если каждому сценарию необходимо загрузить модуль (например, библиотеку сеансов), вы можете сделать:

    требуется ("cgilua.session")
    cgilua.session.setsessiondir (CGILUA_TMP)
    cgilua.addopenfunction (cgilua.session.open)
    cgilua.addclosefunction (cgilua.session.close)
     

    Обратите внимание на , что функция cgilua.addopenfunction необходимо использовать для вызова cgilua.session.open , потому что эта функция необходимо изменить таблицу cgi (см. раздел Получение параметров для получения дополнительной информации об этой специальной таблице) который еще не доступен во время выполнения config.lua файл (см. Жизненный цикл запроса).

    Когда одни скрипты могут использовать библиотеку, а другие нет, вы можете определить «разрешающую» функцию (которая должна вызываться в самое начало каждого скрипта, который должен использовать сеансы):

    требуется ("cgilua.session")
    cgilua.session.setsessiondir (CGILUA_TMP)
    cgilua.enablesession = функция ()
       cgilua.session.open ()
       cgilua.addclosefunction (cgilua.session.close)
    конец
     

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

    local app_lib_dir = {
       ["/ виртуальный / путь /"] = "/ абсолютный / путь / библиотека /",
    }
    локальный пакет = пакет
    cgilua.addopenfunction (функция ()
       локальное приложение = app_lib_dir [cgilua.script_vdir]
       если приложение то
          package.path = app .. '/ ?. lua' .. ';' .. package.path
       конец
    конец)
     

    Скрипты Lua

    Сценарии Lua — это текстовые файлы, содержащие действительный код Lua.Этот стиль использования принимает более «сырую» форму веб-программирования, когда программа отвечает за на всю генерацию получившейся страницы. Скрипты Lua имеют значение по умолчанию .lua расширение.

    Для создания действительного веб-документа (HTML, XML, WML, CSS и т. Д.) Lua Script должен следовать ожидаемому порядку HTTP, чтобы произвести свой вывод, сначала отправив правильные заголовки, а затем отправка фактическое содержание документа.

    CGILua предлагает некоторые функции для облегчения этих задач, например cgilua.htmlheader в создать заголовок для HTML-документа и cgilua.put для отправки документа содержимое (или его часть).

    Например, документ HTML, в котором отображается предложение «Hello World!» мочь может быть сгенерирован с помощью следующего Lua Script:

    cgilua.htmlheader ()
    cgilua.put ([[
    
    
       Привет, мир 
    
    
       Привет, мир! 
    
    ]])
     

    Следует отметить, что в приведенном выше примере создается «фиксированная» страница: даже хотя страница создается во время выполнения, «переменной» нет Информация.Это означает, что тот же самый документ может быть создан напрямую с помощью простого статического файла HTML. Однако скрипты Lua становятся особенно полезными когда документ содержит заранее неизвестную информацию или изменяется согласно переданным параметрам, и необходимо сформировать «динамическую» страницу.

    Можно показать еще один простой пример, на этот раз с использованием структуры управления Lua, переменные и оператор конкатенации:

    cgilua.htmlheader ()
    
    если cgilua.QUERY.language == 'english', тогда
       приветствие = 'Hello World!'
    elseif cgilua.QUERY.language == 'португальский', затем
       приветствие = 'Olá Mundo!'
    еще
       приветствие = '[неизвестный язык]'
    конец
    
    cgilua.put ('')
    cgilua.put ('<заголовок>')
    cgilua.put ('' ..greeting .. '')
    cgilua.put ('')
    cgilua.put ('<тело>')
    cgilua.put ('' ..приветствие .. '')
    cgilua.put ('')
    cgilua.put ('')
     

    В приведенном выше примере использование cgilua.QUERY.language означает что язык был передан в Lua Script как Параметр CGILua, полученный из URL-адреса, используемого для его активации (через GET).Если бы вы использовали форму, параметр был бы доступен в cgilua.POST язык . CGILua автоматически декодирует такие Параметры QUERY и POST, чтобы вы могли использовать их по своему желанию Сценарии Lua и страницы Lua.

    Страниц Lua

    Страница Lua — это текстовый файл шаблона, который будет обрабатываться CGILua. до того, как HTTP-сервер отправит его клиенту. CGILua не обрабатывать сам текст, но ищите специальные разметки, включающие Lua код в файл.После того, как все эти разметки будут обработаны и объединены с файл шаблона, результаты отправляются клиенту.

    Страницы Lua имеют расширение по умолчанию .lp . Они попроще способ сделать страницу динамической, потому что нет необходимости отправлять заголовки HTTP. Обычно страницы Lua представляют собой HTML-страницы, поэтому CGILua автоматически отправляет заголовок HTML.

    Поскольку иногда существуют некоторые ограничения на использование заголовков HTTP сценарий Lua должен использоваться вместо страницы Lua.

    Основные разметки страницы Lua:

    фрагмент ?>
    Обрабатывает и объединяет результаты выполнения фрагмента Lua , где разметка находится в шаблоне. Альтернативная форма <% chunk %> также можно использовать.
    выражение ?>
    Обрабатывает и объединяет оценку Lua выражения , где разметка находится в шаблоне.Альтернативная форма <% = выражение %> также можно использовать.

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

    Второй пример из предыдущего раздела можно написать с использованием Страница Lua нравится:

    
    
    
       <% = welcome%> 
    
    
       <% = welcome%> 
    
    
     

    Теги HTML и теги Lua Page можно свободно смешивать. Однако, как и на других языков шаблонов, рекомендуется не использовать явные Логика Lua по шаблонам.Рекомендуемый подход — использовать только вызовы функций, которые возвращают контент. фрагменты, поэтому в этом примере, предполагая, что функция getGreeting был определен в файле functions.lua следующим образом:

    функция getGreeting ()
       местное приветствие
       если cgilua.QUERY.language == 'english', тогда
          приветствие = 'Hello World!'
       elseif cgilua.QUERY.language == 'португальский' тогда
          приветствие = 'Olá Mundo!'
       еще
          приветствие = '[неизвестный язык]'
       конец
       ответное приветствие
    конец
     

    страницу Lua можно переписать как:

    
    
       <% = getGreeting ()%> 
    
    
       <% = getGreeting ()%> 
    
    
     

    Еще одна интересная особенность Lua Pages — это смешение Lua и HTML. Очень обычно иметь список значений в таблице, перебирать список и показать элементы на странице.

    Сценарий Lua может сделать это с помощью цикла вроде:

    cgilua.put ("
      ") для i, элемент в ipairs (список) делать cgilua.положить ("
    • " ..item .. "
    • ") конец cgilua.put ("
    ")

    Эквивалентный цикл в Lua Page будет:

      <% for i, элемент в ipairs (list) do%>
    • <% = item%>
    • <% конец%>

    Параметры приема: таблицы QUERY и POST

    CGILua предлагает оба типа параметров запроса (строки QUERY и данные POST) в cgilua.QUERY и cgilua.Таблицы ГОСТ .

    Обычно все типы параметров доступны в виде строк. Если значение параметр — это число, он будет преобразован в его строковое представление.

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

    имя файла
    имя файла, указанное клиентом.
    px
    размер файла в байтах.
    файл
    — дескриптор временного файла. Файл необходимо скопировать потому что CGILua удалит его после завершения скрипта.

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

    Диспетчерская

    Если вы хотите использовать более сложные URL-адреса, дистрибутив Kepler включает сценарий диспетчеризации называется app.lua , который можно использовать для обработки URL-адресов в формате ... / app.lua / app_name / path_info стандартным способом. Говорят, что URL-адреса в этом формате относятся к приложениям CGILua, которые заключаются в стандартной загрузке последовательность для веб-приложений с использованием CGILua и app.lua в качестве их диспетчера:

    • есть app_name как начало path_info
    • есть файл init.lua в CGILUA_APPS / имя_приложения
    • изменяет текущий каталог на CGILUA_APPS / имя_приложения
    • устанавливает cgilua.app_name в app_name
    • добавляет CGILUA_APPS / имя_приложения / lua в начало пакета .путь
    • выполняет init.lua

    Приложениям CGILua обычно необходимо отправлять свои действия, используя оставшийся path_info , и для этого они могут использовать cgilua.dispatcher в качестве вспомогательной библиотеки. В приведенном ниже примере он используется для отправки URL-адресов, следуйте соглашению, аналогичному Rails. Предположим, что это init.lua файл в каталоге CGILUA_APPS / blog :

    требуют ("cgilua.диспетчер »)
    return cgilua.dispatcher.route {"/ $ controller / $ action / $ ID", handle, "rails"}
     

    В этом примере URL-адреса типа ... / app.lua / blog / post / edit / 2 приведут к дескриптору функции называется как

    handle ({controller = "post", action = "edit",})
     

    затем функция handle решит, как действовать, в зависимости от полученных параметров и сгенерирует соответствующий ответ с использованием функций CGILua или механизма шаблонов, такого как Lua Pages или Cosmo.

    Обратите внимание, что этот пример не включает обработку ошибок для недопустимых URL-адресов или значений по умолчанию.

    Аутентификация

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

    Первый — это сценарий контроллера, который отвечает за централизацию управления аутентификацией пользователей. и решение, следует ли продолжать работу приложения в зависимости от того, вошел ли пользователь в систему или нет.Пример такого Контроллером будет сценарий диспетчера app.lua , распространяемый с Kepler. Как и большинство контроллеров будет делать, он проверяет наличие аутентифицированного пользователя и перенаправляет на скрипт проверки, когда это не удается:

    - проверяет наличие аутентифицированных пользователей
    если не cgilua.authentication.username (), то
       cgilua.redirect (cgilua.authentication.checkURL ())
    еще
       - продолжает поток заявок
    конец
     

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

    Второй участник механизма аутентификации — это скрипт проверки. Этот скрипт должен запрашивать пользователя учетные данные, проверьте их с помощью соответствующего метода и перенаправьте обратно на исходный URL-адрес, если пользователь успешно прошел аутентифицирован.

    Одним из простых примеров такого сценария проверки является тот, который находится в /examples/check.lua в CGILua CVS, но обычно скрипт проверки, реализованный в CGILua, будет делать следующее:

    - Пример проверки скрипта
    - Предполагается, что форма входа будет использовать два поля: имя пользователя и пароль.
    
    локальное имя пользователя = cgilua.POST.username
    локальный проход = cgilua.POST.pass
    локальный журнал, ошибка, logoutURL
    
    если cgilua.authentication то
       зарегистрирован, err = cgilua.authentication.check (имя пользователя, пароль)
       username = cgilua.authentication.username () или ""
       logoutURL = cgilua.authentication.logoutURL ()
    еще
       logged = false
       err = "Аутентификация не настроена!"
       имя пользователя = ""
    конец
    
    если зарегистрирован и имя пользователя, то
       - возвращается в приложение
       cgilua.redirect (cgilua.authentication.refURL ())
    еще
       err = err или ""
       - отображает форму входа, которая подчиняется этому же скрипту
       cgilua.htmlheader ()
       cgilua.lp.include ("login.lp", {
          logged = зарегистрировано, errorMsg = err, username = username,
          cgilua = cgilua, logoutURL = logoutURL
       })
    конец
     

    Форма входа в систему для этого примера может быть установлена ​​по адресу /examples/login.lp в CGILua CVS и состоит из:

    <%, если зарегистрирован, то%>
    

    Пользователь <% = username%> вошел в систему

    Выйти <% else%>

    <% = errorMsg%>

    Имя пользователя:
    Пароль:
    <% конец%>

    Наконец, третий участник процесса аутентификации — это файл конфигурации.Этот файл используется для установить метод аутентификации и другие детали. Каждый метод имеет свой набор параметров и определяет проверяет обратный вызов , используемый CGILua в процессе аутентификации. См. /examples/authentication_conf.lua для примеров конфигурации с использованием базы данных, LDAP и веб-сервера. методы аутентификации.

    Обработка ошибок

    В CGILua есть три функции для обработки ошибок:

    Функция cgilua.seterrorhandler определяет обработчик ошибок , функцию, вызываемую Lua, когда ошибка только что произошло.Обработчик ошибок имеет доступ к стеку выполнения до error генерируется, поэтому он может создать сообщение об ошибке, используя информацию стека. Lua также предоставляет для этого функцию: debug.traceback .

    Функция cgilua.seterroroutput определяет функцию, которая решает, что делать с сообщением об ошибке. Это могло бы быть отправлено в браузер клиента, записано в файл журнала или отправлено по электронной почте адрес (с помощью LuaSocket или LuaLogging например).

    Функция cgilua.журнал ошибок предоставляется для записи непосредственно в файл журнала ошибок HTTP-сервера.

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

    local ip = cgilua.servervariable "REMOTE_ADDR"
    local developers_machines = {
       ["192.168.0.20"] = правда,
       ["192.168.0.27"] = правда,
       ["192.168.0.30"] = правда,
    }
    почта (а) местной службы
       требуется "cgilua.сериализовать "
       требуется "socket.smtp"
       - Создайте сообщение
       local msg = {}
       table.insert (сообщение, tostring (s))
       - Пытается получить REFERER URL
       table.insert (msg, tostring (cgilua.servervariable "HTTP_REFERER"))
       table.insert (msg, cgilua.servervariable "SERVER_NAME" ..
          cgilua.servervariable "SCRIPT_NAME")
       - Параметры CGI
       table.insert (сообщение, "CGI")
       cgilua.serialize (cgi, функция (ы) table.insert (msg, s) end)
       table.insert (сообщение, tostring (os.date ()))
       table.insert (сообщение, строка (IP))
       Таблица.insert (msg, "Cookies:")
       table.insert (msg, tostring (cgilua.servervariable "HTTP_COOKIE" или "no cookies"))
       - Форматирует сообщение согласно LuaSocket-2.0b3
       local source = socket.smtp.message {
          headers = {subject = "Ошибка сценария",},
          body = table.concat (msg, '\ n'),
       }
       - отправляет сообщение
       local r, e = socket.smtp.send {
          from = "[email protected]",
          rcpt = "[email protected]",
          source = источник,
       }
    конец
    если developers_machines [ip], то
       - Обработка ошибок разработчика: написать на дисплей
       cgilua.seterroroutput (функция (сообщение)
          cgilua.errorlog (сообщение)
          cgilua.errorlog (cgilua.servervariable "REMOTE_ADDR")
          cgilua.errorlog (os.date ())
          cgilua.htmlheader ()
          msg = string.gsub (string.gsub (msg, «\ n», «
    \ n»), «\ t», «») cgilua.put (сообщение) конец) еще - Обработка ошибок пользователя: показывает стандартную страницу и отправляет электронное письмо на адрес - разработчик cgilua.seterroroutput (функция (и) cgilua.htmlheader () cgilua.put "

    Произошла ошибка

    \ n" cgilua.поставить "Ответственный информируется". почта (а) конец) конец

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

    Lua Power control язык программирования и сценариев.

    Настройте свой контроллер питания с помощью простых и мощных сценариев Lua.

    Обновлено 24.11.2020

    Расширенное управление питанием — сценарии Lua

    Сам по себе выключатель питания не очень умен. Добавьте настраиваемую функциональность с помощью встроенного простой язык сценариев Lua. Это действительно просто. Опыт программирования не требуется. Попробуйте!

    Требования к оборудованию

    На этой странице описан язык сценариев на основе Lua, используемый в продуктах DLI с Wi-Fi. Если вы используете продукт без опции Wi-Fi, ищите здесь BASIC справочник по сценариям.

    Ввод скриптов

    Сначала просмотрите этот веб-сайт, чтобы получить краткий обзор Язык Lua. Войдите в систему как администратор и используйте функцию сценариев. Щелкните ссылку Сценарии слева. Просмотрите эти образцы сценариев, чтобы start:

    Пример — включение и выключение освещения (реле) по расписанию рабочего дня. Теперь включает альтернативный пример, управляемый событиями.
    Пример — Ежедневно включайте и выключайте розетку. Теперь включает альтернативный пример, управляемый событиями.
    Пример. Включите знак в рабочие дни, кроме праздников.

    Здесь есть несколько дополнительных примеров пользовательских сценариев.

     - [[Это образец / тестовый набор скриптов для контроллеров DLI. 
     Реализация сценария изменилась и больше не совместима
    со старой реализацией BASIC. Наиболее важные изменения: 
     - Теперь на основе Lua.
    - Больше никаких номеров строк, блоков кода, определяемых функциями.
    - Большинство функций ON, OFF и т. Д. Сохранены как устаревшие функции, которые можно вызывать как
     например, ВКЛ (2345), ВКЛ ("2345") или ВКЛ "2345", на ваш выбор.
     Выполнение по-прежнему основано на потоках. Теперь темы более заметны и
    управляемый. Попробуйте запустить несколько, и вы увидите, что они появятся в
    список.
    ]] - 
     функция turn_outlets_on ()
        ВКЛ (1)
        ВКЛ (2)
        ВКЛ (3)
        ВКЛ (4)
        ВКЛ (5)
        ВКЛ (6)
        ВКЛ (7)
        ВКЛ (8)
    конец 
     функция turn_outlets_off ()
        ВЫКЛ (12345678)
    конец 
     - Надеюсь, это пока что знакомо.
    - Отступы полезны, но не обязательны:
    функция toggle_stuff_and_log ()
    ЖУРНАЛ "ЕДИНЫЙ"
    ВКЛ (1)
    ВЫКЛ (1)
    ЖУРНАЛ "Два"
    ВКЛ (2)
    ВЫКЛ (2)
    ЖУРНАЛ "Готово"
    конец 
     функция do_some_lua_stuff ()
    для i = 1,8 do
    если i> 4, то ВЫКЛ (i) иначе ВКЛ (i) конец
    конец
    конец 
     функция test_display ()
    ДИСПЛЕЙ "\ 1Процент %% \ v"
    ДИСПЛЕЙ "\ 2Backslash \\\ v" 
     - Эти индикаторы мощности относятся только к EPCR5 и EPCR6
    ДИСПЛЕЙ "\ 1% a \ v" - текущая шина A
    ДИСПЛЕЙ «\ 2% A \ v» - напряжение шины A
    ДИСПЛЕЙ "\ 1% b \ v" - текущая шина B
    ДИСПЛЕЙ "\ 2% B \ v" - напряжение шины B 
     ДИСПЛЕЙ "\ 1% o \ v" - Состояние розеток в виде "12456" (отображаются ВКЛ.)
    ДИСПЛЕЙ "\ 1% O \ v" - Состояние розеток в виде "++ - +++ -" 
     ДИСПЛЕЙ "\ 1% n \ v" - Серийный номер
    ДИСПЛЕЙ "\ 2% f \ v" - Версия прошивки 
     ДИСПЛЕЙ "\ f" - Очистить экран, первая строка намеренно пуста
    ДИСПЛЕЙ "\ 2% d \ v" - Системное время / дата 
     ДИСПЛЕЙ "\ 1% M \ v" - MAC-адрес контроллера питания
    ДИСПЛЕЙ "\ 2% i \ v" - IP-адрес контроллера питания 
     DISPLAY "\ 1% m \ v" - маска IP сети
    ДИСПЛЕЙ "\ 2% g \ v" - IP-шлюз
    конец 
     - [[Некоторые дополнительные скрипты, которые могут быть полезны.wait_until используется и требуется для многих из них. 
    - Функция wait_until является встроенной, но показана здесь для справки и в качестве примера
    - локальные функции и переменные должны быть объявлены перед их использованием - локальные функции не будут отображаться в окне выбора веб-интерфейса и не могут использоваться извне - Прошивка версии 1.7.x представила новую систему событий, которая может использоваться вместо функции wait_until и имеет больше возможностей. ]] -
    - Поменять местами выходы 7 и 8 функция flip_flop_7_8 () если (выход [7].состояние == вкл), затем выход [7] .off () выход [8] .on () еще выход [7] .on () выход [8] .off () конец end

    - Ежедневно в 1:00 ч. функция cycle_outlet_daily () в то время как правда wait_until ({час = 1, мин = 0}) выход [2] .cycle () delay (60) - запретить запуск более одного раза за одну минуту конец конец

     - Цикличность выхода в воскресенье утром в 2:00. 
    - В функции wait_until, указанной ниже, wday - день недели, воскресенье = 1
    функция cycle_outlet_weekly () в то время как правда wait_until ({wday = 1, hour = 2, min = 0}) розетка [2].цикл () delay (60) - запретить запуск более одного раза за одну минуту конец конец
     - переключать розетку 5 каждые 15 минут в час
    - В этом примере используется подход, основанный на событиях.
    функция output_5_toggle_schedule ()
      для i, t данные в event.stream (event.local_time ({min = 15})) делают
        если выход [5] .state == on то
          выход [5] .off ()
        еще
          выход [5] .on ()
        конец
        log.notice («Выход 5 был переключен»)
      конец
    конец
     
     - возвращает истину, если это выходной день
    выходные местные функции (day_of_week)
    return day_of_week == 7 или day_of_week == 1
    конец 
     - возвращает истину, если это будний день
    локальная функция будний день (day_of_week)
    return day_of_week1
    конец 
     - Включите переключатели 1-5 утром в будние дни
    функция turn_on_lights_weekdays ()
    в то время как правда
    wait_until ({wday = будний день, час = 8, min = 0})
    для i = 1,5 сделать
    розетка [i].на()
    конец
    delay (120) - запретить запуск более одного раза в минуту
    конец
    конец 
     - Выключать переключатели 1-5 в будние дни вечером
    функция turn_off_lights_weekday_evenings ()
    в то время как правда
    wait_until ({wday = будний день, час = 17, мин = 30})
    для i = 1,5 сделать
    выход [i] .off ()
    конец
    delay (120) - запретить запуск более одного раза в минуту
    конец
    конец 
     - Объедините минуты и часы, чтобы получить общее количество минут
    локальная функция get_minutes (часы, минуты)
    возврат (часы * 60) + минуты
    конец 
     - Проверяет, есть ли время между двумя другими
    локальная функция is__time_between (start_h, start_m, stop_h, stop_m, test_h, test_m)
    - добавить 24 часа, если нерабочие часы
    if (stop_h - если конечные часы увеличились, текущий час также должен увеличиться
    test_h = test_h + 24
    конец
    конец
    - Минуты в течение дня
    локальный start_t_val = get_minutes (start_h, start_m)
    местный stop_t_val = get_minutes (stop_h, stop_m)
    локальный cur_t_val = get_minutes (test_h, test_m)
    return (cur_t_val> = start_t_val и cur_t_val
    
     
     - Проверьте, не находится ли сейчас между временем начала и окончания
    локальная функция is_now_between (start_h, start_m, stop_h, stop_m)
    местное время = os.дата ("* т")
    return is__time_between (start_h, start_m, stop_h, stop_m, time.hour, time.min)
    конец 
     - Запланируйте включение с 8:30 до 17:15 и наблюдайте между ними.
    - Ограничение здесь в том, что это расписание не может быть изменено, если этот сценарий не остановлен.
    функция schedule_switch_one ()
    в то время как правда
    если (is_now_between (8,30,17,15)), то
    if (output [1] .state == off) то
    выход [1] .on ()
    конец
    еще
    если (выход [1].состояние == вкл), затем
    выход [1] .off ()
    конец
    конец
    delay (1) - Не перегружайте процессор, иначе система убьет его
    конец
    конец 
     - Здесь мы используем wait_until, чтобы выключить розетку 4 в полночь.
    функция turn_off_light_at_midnight ()
    wait_until ({час = 0, мин = 0})
    ВЫКЛ (4)
    конец 
     - Вот пример функции с циклами. wait_until засыпает до указанного времени
    - *** ПРИМЕЧАНИЕ: вам не нужно добавлять эту функцию, чтобы использовать ее.Он встроен в сервер сценариев.
    - * параметры wait_until *
    - day - число месяца, начиная с 1
    - month - месяц, январь = 1
    - year - год, с веком
    - wday - день недели, воскресенье = 1
    - yday - день года, 1 января = 1
    - час - час
    - min - минута
    - сек - второй
    - ** Не рекомендуется выполнять точное совпадение по секундам, так как задержки внутренних операций 
    - могут быть больше 1 секунды.- ****************************** функция wait_until (условия) повторение местное ок = правда местная дата = os.date ("* t") для k, v в парах (условиях) делаем если type (v) == "функция", то ok = v (дата [k]) еще ок = дата [k] == v конец если не хорошо то перерыв конец конец если не хорошо то задержка (1) конец пока хорошо конец
    - EPCR5 - только EPCR7 - Записывать некоторые показания счетчиков в системный журнал функция log_meter_readings ()
    LOG («Старый стиль ведения журнала») ЖУРНАЛ (строка.формат ("Напряжение шины A:% g, ток шины A:% g", meter.buses [1] .voltage, meter.buses [1] .current)) LOG (string.format ("Напряжение шины B:% g, ток шины B:% g", meter.buses [2] .voltage, meter.buses [2] .current))
     log.info («Это новый формат ведения журнала») 
    , если (meter.bus [1] .voltage> 95 и meter.bus [1] .voltage <130), то
    log.notice ("Напряжение шины A:% g, ток шины A:% g", meter.buses [1] .voltage, meter.bus [1] .current)
    еще
    log.warning ("Предупреждение! Напряжение на шине А:% g, ток на шине А:% g", meter.шины [1]. напряжение, счетчик. шины [1]. ток)
    конец 
    , если (шины счетчика [2]. Напряжение> 100), то
    log.info ("Напряжение шины B:% g, ток шины B:% g", meter.buses [2] .voltage, meter.bus [2] .current)
    еще
    log.warning ("Предупреждение о низком напряжении - Напряжение шины B:% g, ток шины B:% g", meter.buses [2] .voltage, meter.buses [2] .current)
    конец 
    , если (шины счетчика [2]. Напряжение> 120), то
    log.notice ("Напряжение шины B:% g, ток шины B:% g", meter.bus [2] .voltage, meter.автобусы [2]. ток)
    еще
    log.warning ("Напряжение на шине B:% g, ток на шине B:% g", meter.bus [2] .voltage, meter.buses [2] .current)
    конец
    конец 
     - Обратный цикл - включите, затем выключите
    - Помните, что скорость «включения» между переключателями ограничена «задержкой последовательности включения» на странице настройки.
    - Эта функция может быть вызвана со страницы автозапуска, и переключатели будут переданы.
    функция reverse_cycle (selected_relays)
    count = #selected_relays
    для i = 1 счет делать
    розетка [selected_relays [i]].на()
    конец
      
    delay (15) - Время задержки включения в секундах
      
    для i = 1 счет делать
    розетка [selected_relays [i]]. off ()
    конец
    конец 

    У вас есть умный сценарий или уникальный способ использования коммутатора? Дайте нам знать!

    [email protected]

    Создание сценариев на стороне сервера с помощью Lua - документация Orthanc Book

    Начиная с выпуска 0.5.2, Orthanc поддерживает сценарии на стороне сервера через Lua язык сценариев.Благодаря этой важной функции Orthanc можно настроить к конкретным медицинским рабочим процессам без привлечения внешних сценарий. Эта страница обобщает возможности серверной части Orthanc. сценарии.

    В исходном коде доступно множество других примеров.

    Более выразительная альтернатива сценариям Lua предоставляется Плагины Python.

    Пользовательский сценарий Lua может быть установлен либо конфигурацией файл или загрузив его через REST API.

    Чтобы установить его с помощью файла конфигурации методом , вам просто нужно укажите путь к файлу, содержащему скрипт Lua, в LuaScripts переменная.Список путей, разделенных запятыми, может быть указан для установки нескольких скриптов.

    Чтобы загрузить скрипт, хранящийся в файле « script.lua », через REST API , используйте следующую команду:

     $ curl -X POST http: // localhost: 8042 / tools / execute-script --data-binary @ script.lua
     

    Обратите внимание на то, что в отличие от установленных скриптов из конфигурационного файла скрипты, установленные через REST API не являются постоянными: они удаляются после перезапуска Orthanc, что делает их полезными для прототипирования скриптов.Вы также можете интерпретировать одна команда Lua через REST API:

     $ curl -X POST http: // localhost: 8042 / tools / execute-script --data-binary "print (42)"
     

    Примечание: Параметр --data-binary cURL используется вместо - данные для предотвращения интерпретации символов новой строки cURL, обязательно для правильной оценки возможных комментариев внутри скрипта Lua.

    Обратные вызовы для реакции на события

    Движок Lua Orthanc вызывает следующие обратные вызовы, которые срабатывают при различных событиях.Вот общие события :

    • function Initialize () : вызывается сразу после запуска сервера Orthanc.
    • function Finalize () : Вызывается непосредственно перед остановкой сервера Orthanc.

    Некоторые события, связанные с разрешениями позволяют фильтровать входящие запросы:

    • функция ReceivedInstanceFilter (dicom, origin, info) : Вызывается для известно, должен ли входящий экземпляр DICOM быть принято.См. Этот раздел. происхождение Параметр документируется отдельно. Информация Параметр содержит дополнительную информацию и был добавлен в Orthanc 1.6.1.
    • функция IncomingHttpRequestFilter (метод, uri, ip, имя пользователя, httpHeaders) : Вызывается, чтобы узнать, должен ли REST-запрос быть принято. См. Этот раздел.

    Некоторые события , связанные с заданием, позволяют реагировать на завершение / сбой задания:

    • функция OnJobSubmitted (jobId) : Вызывается при отправке нового задания.Обратите внимание, что это не означает, что выполнение задания началось.
    • функция OnJobFailure (jobId) : Вызывается при сбое задания.
    • функция OnJobSuccess (jobId) : Вызывается при успешном завершении задания.

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

    • функция OnStoredInstance (instanceId, теги, метаданные, происхождение) : Вызывается всякий раз, когда новый экземпляр сохраняется в Orthanc.Это особенно полезно для автоматической маршрутизации изображений DICOM. происхождение Параметр документируется отдельно.
    • функция OnStablePatient (идентификатор пациента, теги, метаданные) : Вызвано всякий раз, когда пациент не получил новый экземпляр для определенного количество времени (см. опцию StableAge в Файл конфигурации). Предоставляется идентификатор пациента вместе с ее DICOM. теги и ее метаданные.
    • функция OnStableSeries (seriesId, теги, метаданные) : вызвано каждый раз, когда серия не получила новых экземпляров для определенного количество времени.
    • функция OnStableStudy (studyId, теги, метаданные) : Вызван всякий раз, когда исследование не получило новых экземпляров для определенного количество времени.
    • функция IncomingFindRequestFilter (источник, происхождение) : Вызывается всякий раз, когда Orthanc получает входящий запрос C-Find через DICOM протокол. Это позволяет проверять содержимое запроса C-Find, и, возможно, модифицировать его, если для какого-то производителя нужен патч. А доступен образец сценария.

    Доступны некоторые другие события, связанные с ресурсами :

    • функция OnDeletedPatient (PatientId) : вызывается, когда у пациента был удален из базы данных Orthanc (новое в Orthanc 1.6.0).
    • функция OnDeletedStudy (studyId) : вызывается, когда исследование было удален из базы данных Orthanc (новый в Orthanc 1.6.0).
    • функция OnDeletedSeries (seriesId) : вызывается, когда серия был удален из базы данных Orthanc (новое в Orthanc 1.6.0).
    • функция OnDeletedInstance (instanceId) : вызывается, когда экземпляр был удален из базы данных Orthanc (новое в Orthanc 1.6.0).
    • функция OnUpdatedPatient (PatientId) : вызывается, когда некоторые метаданные или какая-то привязанность, связанная с данным пациентом, была обновлено (новое в Orthanc 1.6.0).
    • функция OnUpdatedStudy (studyId) : вызывается, когда некоторые метаданные или некоторые приложения, связанные с данным исследованием, были обновлены (новое в Orthanc 1.6.0).
    • функция OnUpdatedSeries (seriesId) : вызывается, когда некоторые метаданные или какое-то приложение, связанное с данной серией, было обновлено (новое в Orthanc 1.6.0).
    • функция OnUpdatedInstance (instanceId) : вызывается, когда некоторые метаданные или какое-либо вложение, связанное с данным экземпляром, имеет было обновлено (новое в Orthanc 1.6.0).

    Кроме того, в версиях Orthanc <= 1.8.2, когда DICOM согласовывается для C-Store SCP, несколько обратных вызовов последовательно вызывается, чтобы указать, какие синтаксисы передачи принят в ассоциацию. Эти обратные вызовы перечислены в этом образец сценария. Эти обратные вызовы были удалены в Orthanc 1.9.0.

    Примечание: Все эти обратные вызовы гарантированно будут вызваны в взаимное исключение . Это означает, что сценарии Lua в Orthanc не поддерживают какой-либо параллелизм.

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

    Вызов REST API Orthanc

    скриптов Lua имеют полный доступ к REST API Orthanc через следующие функции:

    • RestApiGet (uri, встроенный, заголовки)
    • RestApiPost (uri, тело, встроенный, заголовки)
    • RestApiPut (uri, тело, встроенный, заголовки)
    • RestApiDelete (uri, встроенный, заголовки)

    Вот описание параметров:

    • uri указывает ресурс, к которому осуществляется доступ (е.г. / экземпляры ). Он не должен включать схему URL (протокол), имя хоста или порт.
    • В контексте запроса POST или PUT тело представляет собой строку содержащий тело запроса (например, {"Keep": "StudyDate"} ). Эта строка часто соответствует в версию таблицы Lua в формате JSON. DumpJson () функция (см. ниже) очень полезна для преобразования из таблицу Lua в простую строку.
    • builtin - необязательное логическое значение, указывающее, запрос предназначен только для встроенного REST API Orthanc (если установлено значение true ) или полный REST API после заражения плагинами (если установлено значение ложно ).
    • заголовки - необязательный аргумент и был добавлен в выпуске 1.5.7. Это позволяет предоставить конечной точке REST API заголовки HTTP.

    Например:

     RestApiPost ('/ instance / 5af318ac-78fb-47ff-b0b0-0df18b0588e0 / anonymize', '{}')
     

    Функции общего назначения

    Движок Lua Orthanc содержит несколько вспомогательных функции:

    • PrintRecursive (v) рекурсивно печатает содержимое таблицы Lua в файл журнала Orthanc.
    • ParseJson (s) преобразует строку, закодированную в формате JSON, в таблицу Lua.
    • DumpJson (v, keepStrings) кодирует таблицу Lua как строку JSON. Установка необязательного аргумента keepStrings (доступно из выпуск 0.9.5) до true предотвращает автоматическое преобразование строки в целые числа.
    • GetOrthancConfiguration () возвращает таблицу Lua, содержащую содержимое файлов конфигурации Ортханк.

    Подобно функциям для вызова REST API Orthanc, несколько функций доступны для создания общего HTTP запросов к Web-сервисам:

    • HttpGet (URL, заголовки)
    • HttpPost (URL, тело, заголовки)
    • HttpPut (URL, тело, заголовки)
    • HttpDelete (URL, заголовки)
    • SetHttpCredentials (имя пользователя, пароль) можно использовать для настройки Учетные данные HTTP.

    Заголовки Аргумент является необязательным и был добавлен в выпуске 1.2.1. Это позволяет установить заголовки HTTP для запроса клиента HTTP.

    Пример:

     локальный предварительный просмотр = RestApiGet ('/ instance /' .. instanceId .. '/ preview')
    локальные заголовки = {
       ["content-type"] = "изображение / png",
    }
    HttpPost ("http: // localhost / my-web-service / instance-preview", предварительный просмотр, заголовки)
     

    Происхождение экземпляров

    Каждый раз, когда Ортханк решает, следует ли сохранить новый экземпляр (ср.обратный вызов ReceivedInstanceFilter () ), или всякий раз, когда он фактически сохранил новый экземпляр (см. OnStoredInstance callback) предоставляется параметр origin . Этот параметр является Таблица Lua, которая описывает из из какой подсистемы Orthanc создан новый экземпляр.

    Возможны 4 подсистемы, которые можно выделить в соответствии с к значению происхождения ["RequestOrigin"] :

    • RestApi : экземпляр исходит из некоторого HTTP-запроса к REST API.В этом случае поля RemoteIp и Имя пользователя являются доступно в происхождения . Они соответственно описывают IP-адрес клиента HTTP и имя пользователя, которое использовалось для HTTP аутентификация (как определено в RegisteredUsers переменная конфигурации).
    • DicomProtocol : экземпляр происходит из C-Store DICOM. Поля RemoteIp , RemoteAet и CalledAet соответственно укажите IP-адрес DICOM SCU (клиента), название объекта приложения клиента DICOM SCU и название объекта приложения сервера Orthanc SCP.В CalledAet можно использовать для расширенных сценариев автоматической маршрутизации, когда один экземпляр Orthanc действует как прокси для нескольких клиентов DICOM SCU.
    • Lua : экземпляр происходит из сценария Lua.
    • Плагины : экземпляр происходит из плагина.

    Сценарии Lua могут использоваться для управления доступом к различным URI REST API. Каждый раз при получении входящего HTTP-запроса IncomingHttpRequestFilter () Вызывается функция Lua.Доступ к ресурс предоставляется тогда и только тогда, когда этот сценарий обратного вызова возвращает правда .

    Этот механизм может использоваться для реализации детального контроля доступа списки. Вот это пример Lua-скрипта, который ограничивает запросы POST, PUT и DELETE пользователю с именем «admin»:

     функция IncomingHttpRequestFilter (метод, uri, ip, имя пользователя, httpHeaders)
       - Разрешить запросы GET только для пользователей без прав администратора
    
      если method == 'GET', то
          вернуть истину
       elseif username == 'admin' тогда
          вернуть истину
       еще
          вернуть ложь
       конец
    конец
     

    Вот описание аргументов этого обратного вызова Lua:

    • метод : метод HTTP (GET, POST, PUT или DELETE).
    • uri : путь к ресурсу (например, / tools / generate-uid ).
    • ip : IP-адрес хоста, отправившего HTTP-запрос (например, 127.0.0.1 ).
    • имя пользователя : если базовая аутентификация HTTP включена в файл конфигурации, имя пользователя, который выдал HTTP-запрос (как определено в RegisteredUsers переменная конфигурации). Если аутентификация отключена, это аргумент установлен в пустую строку.
    • httpHeaders : HTTP-заголовки входящего запроса. Эта Аргумент доступен начиная с Orthanc 1.0.1. Это полезно, если аутентификация должна осуществляться с помощью токенов, например против LDAP или сервер OAuth3.

    запросов C-Find иногда интерпретируются по-разному на разных серверах DICOM (например, подстановочный знак * , как сообщили пользователи), а иногда модальность запроса может устанавливать неожиданные теги DICOM (см. этот пример из реальной жизни).В такие ситуации можно динамически исправлять входящие или исходящие запросы C-Find с использованием сценария Lua.

    Очистка входящих запросов C-Find может быть выполнена путем реализации IncomingFindRequestFilter (query, origin) callback, который вызывается всякий раз, когда Orthanc C-Find SCP запрашивает удалённую модальность. Для Например, вот сценарий Lua для удаления указанного частного тега по некоторым производителям:

     функция IncomingFindRequestFilter (запрос, источник)
      - Сначала отобразите содержимое запроса C-Find
      PrintRecursive (запрос)
      PrintRecursive (происхождение)
    
      - Удалите из запроса тег "PrivateCreator".
      локальный v = запрос
      v ['5555,0010'] = ноль
    
      вернуть v
    конец
     

    Аргумент origin содержит информацию о том, какая модальность выдал запрос.

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

    Также обратите внимание, что обратный вызов IncomingFindRequestFilter не применяется к Запросы C-Find, ориентированные на рабочие списки модальности. Начиная с Orthanc 1.4.2, соответствующий IncomingWorklistRequestFilter Обратный вызов может использоваться для очистки Запросы C-FIND к рабочим спискам:

     функция IncomingWorklistRequestFilter (запрос, источник)
      PrintRecursive (запрос)
      PrintRecursive (происхождение)
    
      - Реализует то же поведение, что и FilterIssuerAet.
      - опция плагина примерного рабочего списка
      запрос ['0040,0100'] [1] ['0040,0001'] = origin ['RemoteAet']
    
      ответ на запрос
    конец
     

    Аналогично обратный вызов OutgoingFindRequestFilter (запрос, модальность) вызывается всякий раз, когда Orthanc действует как SCU C-Find, что дает возможность динамически исправлять исходящие запросы C-Find до того, как они фактически отправляются запрашиваемой модальности.Например, вот пример обратного вызова Lua, который заменил бы подстановочные знаки звездочки (например, * ) пустой строкой для любого запроса / извлечения, выданного Orthanc (включая из Orthanc Explorer):

     функция OutgoingFindRequestFilter (запрос, модальность)
      для ключа значение в парах (запрос) делать
        если значение == '*' тогда
          запрос [ключ] = ""
        конец
      конец
    
      ответ на запрос
    конец
     

    Сценарии с Lua

    Storyboard Lua API (Lua API) дает разработчикам доступ к Engine через Lua скриптовый интерфейс.Этот API представляет собой библиотеку функций, которые позволяют взаимодействовать с Движок, манипулируя данными и работая с событиями и компонентами пользовательского интерфейса. С помощью Storyboard Lua API разработчики могут:

    Каждой функции Lua, вызываемой из Storyboard, передаются два аргумента:

    script_function_name (table mapargs, string allargs)

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

    В таблице контекста всегда доступны следующие ключи:

    context_app

    Контекст приложения текущего действия

    context_screen

    Контекст экрана текущего действия (текущий экран)

    context_layer

    Контекст уровня текущего действия (текущий уровень)

    context_control

    Контекст управления текущего действия (текущий элемент управления)

    context_row

    Если context_control - таблица, то это индекс строки текущей ячейки

    context_col

    Если context_control является таблицей, то это индекс столбца текущей ячейки

    context_target

    Текущий контекст (приложение, экран, уровень или элемент управления) что мероприятие было нацелено at

    context_event

    Имя события, вызвавшего действие

    context_event_data

    Указатель на таблицу lua, содержащую любые данные события.Данные события разные для каждого события и определяется в определении события.

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

    Пример использования контекстных данных:

    функция get_context (mapargs, stringargs)
      print ("вызвано событием:" ..mapargs.context_event)
      print ("событие было нацелено:" ..mapargs [mapargs.context_target])
      print ("строковые аргументы:", строковые аргументы)
    конец
                 

    Передача дополнительных параметров функциям lua

    Действия Lua идентифицируются с использованием типа действия Lua и установки конкретных Функция Lua и дополнительные параметры (если требуются) в аргументах действия.Любые дополнительные параметры будут переданы напрямую в функцию Lua через первый аргумент (таблица lua), и к данным можно получить доступ, используя имя параметра в качестве таблица index.

    функция my_lua_func (mapargs, allargs)
      локальный параметр1 = mapargs.paramter1
      print ("my_lua_func был передан:" .. paramter1)
    конец
                 

    Storyboard Интеграция с Lua

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

    Полный Lua API можно найти в разделе Storyboard Lua API этого документ.

    Среда выполнения Lua

    Плагин Lua Storyboard Engine предоставляет немного другую среду выполнения по сравнению с обычным выполнением сценария Lua.

    Обычно один сценарий Lua служит отправной точкой для выполнения сценария и всех другие сценарии будут включены с использованием объявления Lua require () . Плагин Storyboard Lua обеспечивает несколько иное поведение загрузки, поскольку он предварительно загружает все сценарии Lua, содержащиеся в каталоге сценариев во время инициализации движка.Эта инициализация будет включать выполнение любых элементов скрипта, не содержащихся в функциональных блоках. Поскольку порядок загрузки нескольких файлов не указан, скрипты, требующие инициализации в зависимости от порядка должен добавить действие обратного вызова Lua к событию запуска приложения (gre.init).

    Помимо загрузки всех файлов сценариев в сценарии , плагин Lua изменяет переменную package.path и ;; путь поиска по умолчанию для автоматического поиска в каталоге скриптов.

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

    print ("Базовый каталог скрипта:" .. tostring (gre.SCRIPT_ROOT))
    - Ищите дополнительные файлы модулей в каталоге scripts / modules
    пакет.path = package.path .. ";" .. gre.SCRIPT_ROOT .. "/modules/?.lua"
     

    Lua - Fluent Bit: официальное руководство

    Фильтр Lua позволяет изменять входящие записи с помощью пользовательских сценариев Lua.

    Из-за необходимости иметь гибкий механизм фильтрации, теперь можно расширить возможности Fluent Bit, написав простые фильтры с использованием языка программирования Lua. Фильтр на основе Lua состоит из двух шагов:

    • Настройка фильтра в основной конфигурации

    • Подготовка сценария Lua, который будет использоваться фильтром

    Плагин поддерживает следующие параметры конфигурации:

    В порядке для тестирования фильтра вы можете запустить плагин из командной строки или через файл конфигурации.В следующих примерах для приема данных используется плагин фиктивного ввода, вызывается фильтр Lua с помощью сценария test.lua и вызывается функция cb_print (), которая выводит только ту же информацию на стандартный вывод:

    Из командной строки вы можете использовать следующие параметры:

     

    $ fluent-bit -i dummy -F lua -p script = test.lua -p call = cb_print -m '*' -o null

    В основном файле конфигурации добавьте следующий ввод , Фильтр и Вывод разделов:

     

    [INPUT]

    Имя фиктивного

    [ФИЛЬТР]

    Имя lua

    Match *

    script test.lua

    call cb_print

    [OUTPUT]

    Name null

    Match *

    Жизненный цикл фильтра состоит из следующих шагов:

    • После сопоставления тегов с помощью filter_lua он может обрабатывать или обходить запись.

    • Если filter_lua принимает запись, он вызовет функцию, определенную в свойстве call , которое в основном является именем функции, определенной в сценарии Lua .

    • Вызов функции Lua, передающей каждую запись в формате JSON.

    • По возвращении подтвердите возвращаемое значение и выполните некоторые действия (описанные выше)

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

     

    function cb_print ( tag, timestamp, record)

    код возврата, временная метка, запись

    конец

    Каждый обратный вызов должен возвращать три значения:

    Функциональные примеры этого интерфейса см.

    Добавить комментарий

    Ваш адрес email не будет опубликован. Обязательные поля помечены *

    Theme: Overlay by Kaira Extra Text
    Cape Town, South Africa