Double Commander

2.15. Скрипты Lua

Содержание

1. Введение
2. Необходимая DLL
3. Библиотеки функций Double Commander
3.1. Библиотека DC
3.1.1. Пример с DC.ExecuteCommand
3.2. Библиотека System
3.2.1. Описание возвращаемого значения SysUtils.FileGetAttr
3.2.2. Пример с SysUtils.FileGetAttr
3.2.3. Пример использования FindFirst, FindNext и FindClose
3.3. Библиотека Clipboard
3.3.1. Пример работы с буфером обмена
3.4. Библиотека Dialogs
3.4.1. Кнопки Dialogs.MessageBox
3.4.2. Стиль окна Dialogs.MessageBox
3.4.3. Кнопка по умолчанию в Dialogs.MessageBox
3.4.4. Возвращаемое значение Dialogs.MessageBox
3.4.5. Пример использования Dialogs.MessageBox
3.4.6. Пример использования Dialogs.InputQuery
3.5. Библиотека UTF-8
3.6. Библиотека Char
3.7. Библиотека OS
4. Индекс

1. Введение

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

Double Commander может выполнять скрипты Lua с помощью команды cm_ExecuteScript.
Параметры скриптов должны передаваться как есть, без экранирования (без кавычек или "\"), для этого необходимо использовать переменную %"0: например, %"0%p0 для файла под курсором вместо %p0 или %"0%D для текущего каталога вместо %D. В противном случае, если Double Commander автоматически добавит кавычки, они будут переданы как часть параметра и вам придётся их учитывать.
Для получения списка всех выделенных файлов мы можем использовать переменные (%LU, %FU или %RU) или внутренние команды (cm_SaveSelectionToFile, cm_SaveFileDetailsToFile, cm_CopyFullNamesToClip или cm_CopyFileDetailsToClip). Мы можем использовать, например, %p: в этом случае Double Commander передаст имена всех выделенных файлов одной строкой, разделяя имена пробелом.

Также на языке Lua можно писать информационные плагины, примеры можно найти в папке программы (plugins/wdx/scripts). В Вики есть страница, посвящённая написанию плагинов. Ограничения: поддерживаются только следующие типы данных

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


О кодировке текста

Все дополнительные функции, описанные ниже, принимают строковые параметры в кодировке UTF-8 и возвращают строки в этой кодировке (за исключением функции LazUtf8.ConvertEncoding).

Часть функций из стандартных библиотек Lua заменены на функции из Double Commander или Free Pascal/Lazarus (или написаны новые), это обеспечивает поддержку UTF-8.

При написании плагинов мы также должны использовать UTF-8 для текстовых данных (ft_multiplechoice, ft_string и ft_fulltext).

При сохранении скриптов используйте кодировку UTF-8 без BOM.


Примечания

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

1. Если включено автообновление и опция Загружать список файлов в отдельном потоке, то функция обновления будет работать асинхронно. При этом скрипты выполняются в основном потоке Double Commander и поэтому в некоторых случаях всё это может отразиться на работе вашего скрипта. Например, иногда последовательное выполнение команд для навигации может не сработать (например, большие каталоги, медленный диск), в этом случае попробуйте отключить Загружать список файлов в отдельном потоке или поискать альтернативное решение.

Если ваш скрипт создаёт новые файлы в текущей панели или переименовывает существующие файлы, но после этого не завершается и выполняет некоторые дополнительные действия (например, выделение файов или перемещение курсора), то в некоторых случаях эти действия не будут иметь эффекта: ещё не все файлы могут быть в панели и вам потребуется предварительно вызвать команду cm_Refresh. При описываемых условиях cm_Refresh также будет выполняться асинхронно и Double Commander может не успеть полностью обновить список файлов после ваших изменений.

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

DC.ExecuteCommand("cm_Refresh")
i = 10
while i > 0 do
  SysUtils.Sleep(10)
  DC.ExecuteCommand("")
  i = i - 1
end

2. Функция Lua io.open использует стандартную функцию C fopen: в текстовом режиме эта функция может преобразовывать тип окончания строк (CRLF, LF или CR) при чтении и записи, что может привести к неожиданному результату. Если вам попадаются файлы с разным типом окончания строк или вы пишете кроссплатформенный скрипт, это необходимо учитывать или может быть практичнее отдать предпочтение бинарному режиму.

3. Для диалога свойств файла в Linux и других Unix-подобных операционных системах функция ContentGetValue вызывается с флагом CONTENT_DELAYIFSLOW (четвёртый параметр, значение равно 1), это позволяет избежать задержки открытия окна: если получение данных медленное, мы можем эти данные исключить, просто добавляем проверку значения флага и возвращаем nil для таких полей или плагина.

4. Если плагин должен вернуть пустую строку, то более быстрым будет передать nil вместо "".

2. Необходимая DLL

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

По умолчанию DC ищет файл с именем lua5.1.dll (Windows), liblua5.1.so.0 (Unix или GNU/Linux) или liblua5.1.dylib (macOS) в своём каталоге и в системном. Мы можем изменить имя файла (и путь) в параметре Библиотека Lua.

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

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

3. Библиотеки функций Double Commander

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

Список библиотек
БиблиотекаИмя функцииКраткое описание
DCСпецифические функции Double Commander
SysUtilsРазличные системные функции
ClipbrdРазличные функции для работы с буфером обмена
DialogsВзаимодействие с пользователем
LazUtf8Строковые функции для работы с UTF-8
CharПолучение информации о символах
osФункции, связанные с операционной системой

3.1. Библиотека DC

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

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

DC.LogWrite(sMessage, iMsgType, bForce, bLogFile)

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

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

iPanel = DC.CurrentPanel()

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

DC.CurrentPanel(iPanel)

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

DC.ExecuteCommand(sCommand, Param1, Param2,...,ParamX)

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

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

DC.GoToFile(Альфа-версия)

DC.GoToFile(sFileName, bActive)

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

bActive – это опциональный параметр: функция может работать в активной файловой панели (true) или неактивной (false). По умолчанию true.

DC.GetPluginField(Альфа-версия)

Result = DC.GetPluginField(sFileName, sPlugin, iField, iUnit)

Позволяет получить данные с помощью установленного информационного (или контентного) плагина (WDX):

  • sFileName : Полное (абсолютное) имя файла.
  • sPlugin : Имя плагина, как оно сохранено в соответствующем разделе настроек.
  • iField : Индекс поля плагина (отсчёт от 0).
  • iUnit : Индекс единицы измерения (отсчёт от 0); укажите 0, если отсутствует.
  • Result : Возвращаемое значение: целое число со знаком (включая время в формате Unix), число с плавающей запятой, логическое (булево) значение, текстовая строка или nil.
DC.ExpandVar(Альфа-версия)

sResult = DC.ExpandVar(String)

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

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

Параметр Значение Описание
ToolBarID TfrmOptionsToolbar кнопка основной панели инструментов
TfrmOptionsToolbarMiddle кнопка центральной панели инструментов
(отсутствует) кнопка основной панели инструментов
ToolItemID идентификатор уникальный идентификатор кнопки

Уникальный идентификатор хранится в теге ID и у нас есть несколько способов его получить: мы можем найти кнопку в файле doublecmd.xml, в файле резервной копии панели инструментов или просто скопировать кнопку в буфер обмена и вставить её код в текстовый редактор.

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

3.1.1. Пример с DC.ExecuteCommand

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

  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, мы можем настроить эту кнопку следующим образом:

Вызов скрипта Lua кнопкой панели инструментов

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

Подсветка синтаксиса Lua во встроенном редакторе

3.2. Библиотека System

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

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

SysUtils.Sleep(iMilliseconds)

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

SysUtils.GetTickCount()

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

bExists = SysUtils.FileExists(sFileName)

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

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

bExists = SysUtils.DirectoryExists(sDirectory)

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

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

iAttr = SysUtils.FileGetAttr(sFileName)

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

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

Handle, FindData = SysUtils.FindFirst(sPath)

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

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

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

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

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

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

Result, FindData = SysUtils.FindNext(Handle)

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

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

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

SysUtils.FindClose(Handle)

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

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

bResult = SysUtils.CreateDirectory(sDirectory)

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

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

SysUtils.RemoveDirectory(Альфа-версия)

bResult = SysUtils.RemoveDirectory(sDirectory)

Удалить каталог с именем sDirectory. Возвращает true в случае успеха, иначе возвращает false.

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

bResult = SysUtils.CreateHardLink(sFileName, sLinkName)

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

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

bResult = SysUtils.CreateSymbolicLink(sFileName, sLinkName)

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

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

sTarget = SysUtils.ReadSymbolicLink(sLinkName, bRecursive)

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

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

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

sName = SysUtils.ExtractFileName(sFileName)

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

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

sExt = SysUtils.ExtractFileExt(sFileName)

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

sPath = SysUtils.ExtractFilePath(sFileName)

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

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

sDir = SysUtils.ExtractFileDir(sFileName)

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

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

sDrive = SysUtils.ExtractFileDrive(sFileName)

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

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

sName = SysUtils.GetAbsolutePath(sFileName, sBaseDirectory)

Возвращает абсолютный (полный) путь к файлу:

  • sFileName : Имя файла с относительным путём.
  • sBaseDirectory : Каталог, который использовался как базовый каталог для sFileName.

Если не удалось получить абсолютный путь, функция вернёт значение sFileName.

sName = SysUtils.GetRelativePath(sFileName, sBaseDirectory)

Возвращает имя файла относительно указанного каталога:

  • sFileName : Полное (абсолютное) имя файла.
  • sBaseDirectory : Каталог, который будет использоваться как базовый каталог для sFileName.

Если sFileName и sBaseDirectory содержат одно и то же значение, функция вернёт пустую строку (""). Если не удалось получить имя файла с относительным путём, функция вернёт значение sFileName.

bResult = SysUtils.MatchesMask(sFileName, sMask, iMaskOptions)

Возвращает true, если sFileName совпадает с переданной маской sMask.

iMaskOptions (необязательный параметр, по умолчанию 0) задаётся как сумма следующих значений:

Значение Описание
1
с учётом регистра
2
игнорировать акценты и лигатуры
4
фильтр в стиле Windows: "*.*" также совпадает с файлами без расширения и т.д.
8
включить поддержку пиньинь (будет использоваться файл pinyin.tbl)

bResult = SysUtils.MatchesMaskList(sFileName, sMaskList, sSeparator, iMaskOptions)

Возвращает true, если sFileName совпадает с хотя бы одной из переданных масок sMaskList, разделённых sSeparator (по умолчанию ";").

sSeparator и iMaskOptions (см. выше) – необязательные параметры.

SysUtils.ExpandEnv(Альфа-версия)

sResult = SysUtils.ExpandEnv(String, bSpecial)

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

bSpecial – это опциональный параметр: если true, то также будут раскрыты псевдопеременные окружения (подробнее смотрите здесь). По умолчанию false.

sTempFileName = SysUtils.GetTempName()

Возвращает строку с именем файла, который может быть использован в качестве временного файла (в системном каталоге для временных файлов), подобно функции os.tmpname, но файл будет создан в подкаталоге, который автоматически удаляется при закрытии Double Commander.
Если функции не удалось создать уникальное имя, то она вернёт пустую строку.

SysUtils.GetFileProperty(Альфа-версия)

Result = SysUtils.GetFileProperty(sFileName, iValue)

Возвращает свойство файла, соответствующее iValue:

ЗначениеОписание
0Размер файла в байтах
1Строка атрибутов как в файловой панели (подробное описание строкового значения смотрите здесь)
2Группа владельца файла
3Владелец файла
4Дата модификации
5Дата создания
6Дата последнего доступа
7Дата изменения статуса
8Тип файла (как в Проводнике Windows или MIME-тип)
9Описание (комментарий) из descript.ion (подробнее смотрите здесь)

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

SysUtils.FileSetTime(Альфа-версия)

bResult = SysUtils.FileSetTime(sFileName, iModification, iCreation, iLastAccess)

Позволяет задать отметки времени (время в формате Unix) для sFileName: дата модификации, дата создания и дата последнего доступа. Укажите ноль для тех отметок времени, которые должны быть проигнорированы.

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

SysUtils.PathDelim

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

В системах Unix/Linux разделителем каталогов будет "/" и "\" в Windows.

3.2.1. Описание возвращаемого значения SysUtils.FileGetAttr

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

Константы, используемые в возвращаемом значении 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.

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

3.2.2. Пример с SysUtils.FileGetAttr

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

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

local params = {...}
local iAttr

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

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

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

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

Параметр с cm_ExecuteScript

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

3.2.3. Пример использования FindFirst, FindNext и FindClose

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

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

local params = {...}

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

  hOutputFile = 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(hOutputFile)
  end
end

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

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

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

Параметр с cm_ExecuteScript

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

3.3. Библиотека Clipboard

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

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

Clipbrd.Clear()

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

sVar = Clipbrd.GetAsText()

Получает содержимое буфера обмена как строку sVar. Если буфер обмена не содержит текст, то функция вернёт пустую строку.

Clipbrd.SetAsText(sVar)

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

Clipbrd.SetAsHtml(sHtml)

Добавляет в буфер обмена текст sHtml в формате 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 распознаёт и поддерживает этот формат буфера обмена.

3.3.1. Пример работы с буфером обмена

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

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

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

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

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

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

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

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

local params = {...}
local Result = nil
local iAttr
local bFound = false
local sCompleteFilename = ""
local hInputFile = nil
local sLine = ""
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
      iAttr = SysUtils.FileGetAttr(sCompleteFilename)
      if iAttr > 0 then -- Получили значение атрибута?
        -- Нам нужен файл, не каталог!
        if math.floor(iAttr / 0x00000010) % 2 == 0 then

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

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

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

          io.close(hInputFile)
        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

3.4. Библиотека Dialogs

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

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

iButton = Dialogs.MessageBox(sMessage, sTitle, iFlags)

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

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

bResult, sAnswer = Dialogs.InputQuery(sTitle, sMessage, bMask, sDefault)

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

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

sItem, iItem = Dialogs.InputListBox(sTitle, sMessage, aItems, sDefault)

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

  • sTitle : Текст в заголовке окна.
  • sMessage : Сообщение окна.
  • aItems : Таблица Lua, каждый элемент таблицы должен быть строкой.
  • sDefault : Пункт списка, выделенный по умолчанию.
  • sItem : Возвращаемая строка с выбранным пунктом или nil в случае отмены.
  • iItem : Индекс выделенного пункта (отсчёт от единицы, как принято в таблицах Lua).

3.4.1. Кнопки Dialogs.MessageBox

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

Константы для кнопок в Dialogs.MessageBox
Значение константыОтображаемые кнопки, слева направо
0x0000
MB_OK
Кнопка OK
0x0001
MB_OKCANCEL
Кнопка OK Кнопка ОТМЕНА
0x0002
MB_ABORTRETRYIGNORE
Кнопка ПРЕРВАТЬ Кнопка ПОВТОР Кнопка ПРОПУСТИТЬ
0x0003
MB_YESNOCANCEL
Кнопка ДА Кнопка НЕТ Кнопка ОТМЕНА
0x0004
MB_YESNO
Кнопка ДА Кнопка НЕТ
0x0005
MB_RETRYCANCEL
Кнопка ПОВТОР Кнопка ОТМЕНА

3.4.2. Стиль окна Dialogs.MessageBox

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

Константы, задающие значок и стиль окна Dialogs.MessageBox
Значение константыСтиль окна
0x0040
MB_ICONINFORMATION
Значок ИНФОРМАЦИЯ Информационное окно
0x0030
MB_ICONWARNING
Значок ПРЕДУПРЕЖДЕНИЕ Окно предупреждения
0x0020
MB_ICONQUESTION
Значок ВОПРОС Окно подтверждения
0x0010
MB_ICONERROR
Значок ОШИБКА Окно ошибки

3.4.3. Кнопка по умолчанию в Dialogs.MessageBox

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

Константы, задающие кнопку по умолчанию в Dialogs.MessageBox
Значение константыКнопка по умолчанию
0x0000
MB_DEFBUTTON1
Первая кнопка слева
0x0100
MB_DEFBUTTON2
Вторая кнопка слева
0x0200
MB_DEFBUTTON3
Третья кнопка слева

3.4.4. Возвращаемое значение Dialogs.MessageBox

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

Возвращаемое значение Dialogs.MessageBox
Значение константыНажатая кнопка
0x0000
mrNone
Кнопка не нажата
0x0001
mrOK
Результат: OK
0x0002
mrCancel
Результат: ОТМЕНА
0x0003
mrAbort
Результат: ПРЕРВАТЬ
0x0004
mrRetry
Результат: ПОВТОР
0x0005
mrIgnore
Результат: ПРОПУСТИТЬ
0x0006
mrYes
Результат: ДА
0x0007
mrNo
Результат: НЕТ

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

3.4.5. Пример использования Dialogs.MessageBox

Маленький скрипт, использующий 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

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

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

Пример использования Dialogs.MessageBox

3.4.6. Пример использования Dialogs.InputQuery

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

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

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

Пример использования Dialogs.InputQuery

3.5. Библиотека UTF-8

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

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

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

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

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

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

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

LazUtf8.Next(String)

Функция-итератор, которая при каждом вызове возвращает следующий символ в строке String и позицию начала этого символа (в байтах).

Пример:

-- Выведем пары значений в виде "позиция : символ"
for iPos, sChar in LazUtf8.Next(String) do
  DC.LogWrite(iPos .. " : " .. sChar)
end

sResult = LazUtf8.Copy(String, iIndex, iCount)

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

Функция возвращает iCount символов из строки String, начиная с позиции iIndex.

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

iResult = LazUtf8.Length(String)

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

sResult = LazUtf8.UpperCase(String)

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

sResult = LazUtf8.LowerCase(String)

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

sResult = 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" - cp1252 или cp1251
  • "ansi" - cp1252 или cp1251
  • "oem" - cp850 или cp866
В Linux (английкий или русский языки):
  • "default" - utf8
  • "ansi" - cp1252 или cp1251
  • "oem" - cp850 или cp866

sEnc = LazUtf8.DetectEncoding(String)

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

3.6. Библиотека Char

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

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

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

iResult = Char.GetUnicodeCategory(Character)

Возвращает категорию юникода символа Character, одно из следующих значений:

ЗначениеОписание
  Буква:
0Буква в верхнем регистре (Lu)
1Буква в нижнем регистре (Ll)
2Заглавная буква (Lt)
3Модификатор (Lm)
4Прочие буквы (Lo)
  Отметки:
5Символ нулевой ширины, указывающий на изменение базового символа (Mn)
6Символ ненулевой ширины, указывающий на изменение базового символа (Mc)
7Вложенный символ (Me)
  Цифра:
8Десятичная цифра (Nd)
9Цифра, обозначаемая буквами (Nl)
10Прочие цифры (No)
  Знак пунктуации:
11Соединитель (Pc)
12Тире (Pd)
13Открывающий знак пунктуации (скобки) (Ps)
14Закрывающий знак пунктуации (скобки) (Pe)
15Знак открывающей кавычки (Pi)
16Знак закрывающей кавычки (Pf)
17Прочие знаки пунктуации (Po)
  Символ:
18Математический символ (Sm)
19Денежная единица (Sc)
20Модификатор (Sk)
21Прочие символы (So)
  Разделитель:
22Пробел (Zs)
23Разделитель строк (Zl)
24Разделитель параграфов (Zp)
  Прочее:
25Управляющий символ (Cc)
26Символ форматирования (Cf)
27Символ-заместитель (суррогат) (Cs)
28Для частного использования (Co)
29Не определён (Cn)

bResult = Char.IsDigit(Character)

Возвращает true, если символ Character входит в категорию Nd.

bResult = Char.IsLetter(Character)

Возвращает true, если символ Character входит в категорию Lu, Ll, Lt, Lm или Lo.

bResult = Char.IsLetterOrDigit(Character)

Возвращает true, если символ Character входит в категорию Lu, Ll, Lt, Lm Lo, Nd или Nl.

bResult = Char.IsLower(Character)

Возвращает true, если символ Character входит в категорию Ll.

bResult = Char.IsUpper(Character)

Возвращает true, если символ Character входит в категорию Lu.

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

3.7. Библиотека OS

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

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

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

iResultCode = os.execute(sCommand)

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

sCommand может быть:

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

sTempFileName = os.tmpname()

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

bResult, sError, iError = os.remove(sFileName)

Удалить файл или каталог с именем sFileName.

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

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

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

bResult, sError, iError = os.rename(sOldName, sNewName)

Переименовать файл sOldName в sNewName.

Примечание: Если файл с именем sNewName уже существует, он будет заменён!

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

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

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

Value = os.getenv(VariableName)

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

os.setenv(VariableName, Value)

Добавить или изменить переменную окружения VariableName. В случае ошибки функция возвращает -1.

os.unsetenv(VariableName)

Удалить переменную окружения VariableName. В случае ошибки функция возвращает -1.

4. Индекс

Библиотека DC

DC.CurrentPanel
DC.ExecuteCommand
DC.ExpandVar
DC.GetPluginField
DC.GoToFile
DC.LogWrite


Библиотека System

SysUtils.CreateDirectory
SysUtils.CreateHardLink
SysUtils.CreateSymbolicLink
SysUtils.DirectoryExists
SysUtils.ExpandEnv
SysUtils.ExtractFileDir
SysUtils.ExtractFileDrive
SysUtils.ExtractFileExt
SysUtils.ExtractFileName
SysUtils.ExtractFilePath
SysUtils.FileExists
SysUtils.FileGetAttr
SysUtils.FileSetTime
SysUtils.FindClose
SysUtils.FindFirst
SysUtils.FindNext
SysUtils.GetAbsolutePath
SysUtils.GetFileProperty
SysUtils.GetRelativePath
SysUtils.GetTempName
SysUtils.GetTickCount
SysUtils.MatchesMask
SysUtils.MatchesMaskList
SysUtils.PathDelim
SysUtils.ReadSymbolicLink
SysUtils.RemoveDirectory
SysUtils.Sleep


Библиотека Clipboard

Clipbrd.Clear
Clipbrd.GetAsText
Clipbrd.SetAsHtml
Clipbrd.SetAsText


Библиотека Dialogs

Dialogs.InputListBox
Dialogs.InputQuery
Dialogs.MessageBox


Библиотека UTF-8

LazUtf8.ConvertEncoding
LazUtf8.Copy
LazUtf8.DetectEncoding
LazUtf8.Length
LazUtf8.LowerCase
LazUtf8.Next
LazUtf8.Pos
LazUtf8.UpperCase


Библиотека Char

Char.GetUnicodeCategory
Char.IsDigit
Char.IsLetter
Char.IsLetterOrDigit
Char.IsLower
Char.IsUpper


Библиотека OS

os.execute
os.getenv
os.remove
os.rename
os.setenv
os.tmpname
os.unsetenv


Valid HTML 4.0 Transitional CSS Valid!