Double Commander

2.15. Lua 脚本

内容

1. 介绍
2. 所需 DLL
3. Double Commander 函数库
3.1. DC 库
3.1.1. DC.ExecuteCommand 使用示例
3.2. 系统库
3.2.1. SysUtils.FileGetAttr 返回值详情
3.2.2. SysUtils.FileGetAttr 使用示例
3.2.3. 使用 FindFirst、FindNext 和 FindClose 的示例
3.3. 剪贴板库
3.3.1. 剪贴板库使用示例
3.4. 对话框库
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. 字符库
3.7. 操作系统库
4. 索引

1. 介绍

有关 Lua 脚本编程语言的详细信息,请访问 Lua 网站

Double Commander 可以通过 cm_ExecuteScript 命令执行 Lua 脚本。
脚本参数必须按原样传递,无需转义(无需引号或“\”),为此我们需要使用 %"0 变量:例如,对于光标下的文件使用 %"0%p0 而不是 %p0,对于当前目录使用 %"0%D 而不是 %D。否则,如果 Double Commander 自动添加引号,它们将作为参数的一部分传递,您将不得不考虑这一点。
要获取所有选定文件的列表,我们可以使用 变量%LU%FU%RU)或内部命令(cm_SaveSelectionToFilecm_SaveFileDetailsToFilecm_CopyFullNamesToClipcm_CopyFileDetailsToClip)。 例如,我们可以使用 %p:在这种情况下,Double Commander 将在一行中传递所有选定文件的名称,用空格分隔名称。

也可以使用 Lua 脚本编写内容插件,示例可以在程序文件夹中找到(plugins/wdx/scripts)。 Wiki 上有一个专门用于编写插件的页面。 限制:仅支持以下数据类型

上面的列表包含头文件中的名称,在 Lua 脚本中我们必须使用括号中指定的数值。


关于文本编码

下面描述的所有附加函数都接受 UTF-8 编码的字符串参数并返回此编码的字符串(LazUtf8.ConvertEncoding 函数除外)。

一些标准 Lua 库中的函数已被 Double Commander 或 Free Pascal/Lazarus 的函数替换(或编写了新函数),这提供了 UTF-8 支持。

编写插件时,我们也应该对文本数据使用 UTF-8(ft_multiplechoiceft_stringft_fulltext)。

保存脚本时,请使用不带 BOM 的 UTF-8 编码。


注意事项

使用 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 DLL 文件,Double Commander 支持 5.1 - 5.4 版本。

我们可以使用来自 LuaJIT 项目 的 DLL 文件。LuaJIT 结合了一个用汇编编写的高速解释器和一个先进的 JIT 编译器。此外,我们还获得了 FFI 库,它允许从纯 Lua 代码中调用外部 C 函数和使用 C 数据结构。

Windows 版本的 DC 默认包含 Lua DLL(在 DC 0.9.7 及更高版本中来自 LuaJIT 项目),在其他情况下,我们可以通过包管理器查找和安装它,或者自行编译。如果我们使用的是 64 位版本的 DC,则 DLL 也必须是 64 位版本。

默认情况下,DC 会在其目录和系统目录中查找名为 lua5.1.dll(Windows)、liblua5.1.so.0(Unix 或 GNU/Linux)或 liblua5.1.dylib(macOS)的文件。我们可以在 要使用的 Lua 库文件 参数中更改文件名(和路径)。

3. Double Commander 函数库

Double Commander 为我们的 Lua 脚本提供了一些函数库。

以下是这些库的列表。

库列表
库名称脚本名称简要描述
DCDouble Commander 特定函数
SysUtils各种系统函数
Clipbrd提供外部剪贴板功能
Dialogs与用户交互
LazUtf8UTF-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 是实际的内部命令名称。

我们可以提供命令支持的任意数量的 Param... 参数。

除了内部命令之外,在脚本中我们还可以使用特殊命令 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. 系统库

该库包含各种系统函数。

它在 SysUtils 表中提供了所有函数。

系统库
函数名称描述

SysUtils.Sleep(iMilliseconds)

暂停脚本执行指定的毫秒数 iMilliseconds
指定的时间过后,脚本执行将继续。

SysUtils.GetTickCount()

返回一个递增的时钟滴答计数。它可用于时间测量,但不应假设滴答之间的间隔。

bExists = SysUtils.FileExists(sFileName)

检查文件系统中是否存在特定文件。

如果磁盘上存在名为 sFileName 的文件,则在 bExists 中返回值 true,否则返回 false

bExists = SysUtils.DirectoryExists(sDirectory)

检查 sDirectory 是否存在于文件系统中且确实是一个目录。

如果是这样,函数将在 bExists 中返回值 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 : 文件的时间戳(自 1970 年 1 月 1 日以来的秒数)。

Result, FindData = SysUtils.FindNext(Handle)

通过重用先前返回的 Handle,查找由 FindFirst 发起的搜索序列的下一个匹配项。

如果找到文件或目录,返回的 Result 将非空,否则为 nil

SysUtils.FindFirst 相同的注意事项也适用于此处。

备注:最后一次 SysUtils.FindNext 调用必须始终跟随一个使用相同 HandleSysUtils.FindClose 调用。否则将导致内存泄漏。

SysUtils.FindClose(Handle)

结束一系列 SysUtils.FindFirst/SysUtils.FindNext 调用。

释放这些调用使用的任何内存。

绝对有必要进行此调用,否则可能导致内存泄漏。

bResult = SysUtils.CreateDirectory(sDirectory)

创建一系列目录,sDirectory 是目录的完整路径。

如果 sDirectory 已存在或成功创建,则返回 true。如果创建任何部分失败,则返回 false

bResult = SysUtils.CreateHardLink(sFileName, sLinkName)

为文件 sFileName 创建硬链接 sLinkName

如果成功则返回 true,否则返回 false

bResult = SysUtils.CreateSymbolicLink(sFileName, sLinkName)

为文件或目录 sFileName 创建符号链接 sLinkName

如果成功则返回 true,否则返回 false

sTarget = SysUtils.ReadSymbolicLink(sLinkName, bRecursive)

读取符号链接 sLinkName 的目标。

如果 bRecursivetrue 且链接指向另一个链接,则递归解析直到找到一个有效的非链接文件名。

返回符号链接 sLinkName 指向的路径,或者在链接无效或指向的文件不存在且 bRecursivetrue 时返回空字符串。

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 基础目录的目录。

如果 sFileNamesBaseDirectory 包含相同的值,函数将返回空字符串("")。如果无法获取带有相对路径的文件名,函数将返回 sFileName 的值。

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

如果 sFileName 与传递的掩码 sMask 匹配,则返回 true

iMaskOptions(可选参数,默认为 0)设置为以下值的总和:

描述
1
区分大小写
2
忽略重音符号和连字
4
Windows 风格过滤器:“*.*”也匹配没有扩展名的文件等。
8
启用拼音支持(将使用文件 pinyin.tbl

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

如果 sFileName 与由 sSeparator(默认为“;”)分隔的传递掩码 sMaskList 中的至少一个匹配,则返回 true

sSeparatoriMaskOptions(见上文)是可选参数。

sTempFileName = SysUtils.GetTempName()

将返回一个用作临时文件名的文件名(在系统临时文件目录中),类似于 os.tmpname 函数,但文件将在 Double Commander 关闭时自动删除的子目录中创建。
如果函数无法创建唯一名称,它将返回空字符串。

SysUtils.PathDelim

当前操作系统用于分隔完整文件名中目录名的字符。

在 Unix/Linux 系统中,目录分隔符将是“/”,在 Windows 中将是“\”。

3.2.1. SysUtils.FileGetAttr 返回值详情

FileGetAttr 返回文件 sFileName 的属性设置。

属性是以下常量的 OR 组合:

SysUtils.FileGetAttr 返回值中使用的常量
含义
0x00000001
faReadOnly
文件是只读的。
0x00000002
faHidden
文件是隐藏的。
在 Unix/Linux 中,这意味着文件名以点开头。
0x00000004
faSysFile
文件是系统文件。
在 Unix/Linux 中,这意味着文件是字符或块设备,命名管道 (FIFO)。
0x00000008
faVolumeId
卷标。
仅适用于 DOS/Windows 上的普通 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
      -- 第4位被设置?所以它是一个目录。
      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 的示例

在以下脚本示例中,我们将扫描参数中接收的目录内容,并将结果数据存储到以第二个参数传递的文件名的文本文件中。

这将让我们很好地了解 FindFirstFindNextFindClose 的用法。

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. 剪贴板库

Double Commander 可以为我们的 Lua 脚本提供外部剪贴板功能。

下表给出了相关的函数:

剪贴板库
函数名描述

Clipbrd.Clear()

清除剪贴板的内容。

sVar = Clipbrd.GetAsText()

获取剪贴板的当前文本内容并将其分配给 sVar。如果剪贴板不包含文本,函数将返回一个空字符串。

Clipbrd.SetAsText(sVar)

在剪贴板中存储 sVar 的文本内容。

Clipbrd.SetAsHtml(sHtml)

将 html 格式的文本 sHtml 添加到剪贴板 (CF_HTML 剪贴板格式)。

这些内容将被插入到支持此剪贴板格式的应用程序中,如 MS Word、LO Writer 等。

使用 Clipbrd.SetAsTextClipbrd.SetAsHtml 存储数据都是正确的。当我们粘贴时,应用程序将使用它支持的最佳格式。

例如,我们可能有以下内容:

  • Clipbrd.SetAsText("欢迎使用 Double Commander!")
  • Clipbrd.SetAsHtml("欢迎使用 <b>Double Commander</b>!")

如果我们切换到记事本尝试粘贴某些内容,它将以纯文本形式粘贴我们用 Clipbrd.SetAsText 复制的消息。但如果我们切换到 Microsoft Word 并粘贴某些内容,它将粘贴第二个,即 Double Commander 以粗体显示的那个,因为 Microsoft Word 识别并支持该剪贴板内容类型。

3.3.1. 剪贴板库使用示例

以下示例使用了与剪贴板相关的三个函数:ClearGetAsTextSetAsText

这是一个相对较长的脚本,但它很好地将上面看到的一些函数组合在一起。

它假设我们的活动面板当前位于一个包含许多源文本文件的目录中。

它还假设我们当前在剪贴板中有一个单词,并且它将接收当前活动文件夹作为单个参数。

脚本将扫描当前目录级别的文件,并逐个读取它们的内容,以检测包含剪贴板中单词的文本行。

然后,包含至少一行该单词的文件名将被放置到剪贴板中。

然后,脚本将使用内部命令 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. 对话框库

该库允许我们的脚本与用户交互,显示消息、提示输入答案等。

下表列出了相关函数:

对话框库
函数名称描述

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:选中项目的索引(从 1 开始计数,符合 Lua 表的习惯)。

3.4.1. Dialogs.MessageBox 中显示的按钮

Dialogs.MessageBox 函数显示的按钮由以下常量的按位或值控制:

Dialogs.MessageBox 显示按钮的 ButFlags 常量
常量值显示的按钮,从左到右
0x0000
MB_OK
按钮 OK
0x0001
MB_OKCANCEL
按钮 OK 按钮 CANCEL
0x0002
MB_ABORTRETRYIGNORE
按钮 ABORT 按钮 RETRY 按钮 IGNORE
0x0003
MB_YESNOCANCEL
按钮 YES 按钮 NO 按钮 CANCEL
0x0004
MB_YESNO
按钮 YES 按钮 NO
0x0005
MB_RETRYCANCEL
按钮 RETRY 按钮 CANCEL

3.4.2. Dialogs.MessageBox 的窗口样式

Dialogs.MessageBox 函数显示的窗口样式由以下常量的按位或值控制:

Dialogs.MessageBox 图标和样式的 ButFlags 常量
常量值窗口样式
0x0040
MB_ICONINFORMATION
图标 INFORMATION 信息窗口
0x0030
MB_ICONWARNING
图标 WARNING 警告窗口
0x0020
MB_ICONQUESTION
图标 QUESTION 确认窗口
0x0010
MB_ICONERROR
图标 ERROR 错误窗口

3.4.3. Dialogs.MessageBox 的默认活动按钮

Dialogs.MessageBox 函数显示的默认活动按钮由以下常量的按位或值控制:

Dialogs.MessageBox 默认按钮的 ButFlags 常量
常量值默认按钮
0x0000
MB_DEFBUTTON1
默认为左侧第一个按钮
0x0100
MB_DEFBUTTON2
默认为左侧第二个按钮
0x0200
MB_DEFBUTTON3
默认为左侧第三个按钮

3.4.4. Dialogs.MessageBox 的返回值

Dialogs.MessageBox 函数返回的数字表示用户按下的按钮,如下所示:

Dialogs.MessageBox 按钮按下时返回的 ButPressed 值
常量值按下的按钮
0x0000
mrNone
未按下任何按钮
0x0001
mrOK
结果 OK
0x0002
mrCancel
结果 CANCEL
0x0003
mrAbort
结果 ABORT
0x0004
mrRetry
结果 RETRY
0x0005
mrIgnore
结果 IGNORE
0x0006
mrYes
结果 YES
0x0007
mrNo
结果 NO

注意:如果按下右上角的“x”或按 Esc 关闭窗口,则将返回“取消”按钮的值。

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)开始。

如果在给定的 Offset 之后 SearchText 未在 SourceText 中出现,则返回零。

LazUtf8.Next(String)

一个迭代器函数,每次调用时返回 String 中的下一个字符以及该字符开始位置(以字节为单位)。

示例:

-- 以 "位置 : 字符" 的形式打印值对
for iPos, sChar in LazUtf8.Next(String) do
  DC.LogWrite(iPos .. " : " .. sChar)
end

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

复制字符串的一部分。

Copy 返回一个字符串,该字符串是 String 中从位置 iIndex 开始的 iCount 个字符的副本。

如果 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"。
  • Unicode:"utf8"、"utf8bom"、"ucs2le"、"ucs2be"。
  • ANSI(Windows):"cp1250"、"cp1251"、"cp1252"、"cp1253"、"cp1254"、"cp1255"、"cp1256"、"cp1257"、"cp1258"。
  • OEM(DOS):"cp437"、"cp850"、"cp852"、"cp865"、"cp866"、"cp874"、"cp932"、"cp936"、"cp949"、"cp950"。
  • ISO 8859:"iso88591"、"iso88592"、"iso88593"、"iso88594"、"iso88595"、"iso88597"、"iso88599"、"iso885910"、"iso885913"、"iso885914"、"iso885915"、"iso885916"。
  • 其他:"macintosh"、"koi8r"、"koi8u"、"koi8ru"。
特殊编码的含义(示例)。

在 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. 字符库

该库包含用于检查字符是否属于特定 Unicode 类别的函数,以及获取字符类别的函数。

该库中可用函数的列表:

字符库
函数名称描述

iResult = Char.GetUnicodeCategory(Character)

返回字符 Character 的 Unicode 类别,以下值之一:

描述
  字母:
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)

如果 Character 字符在 Nd 类别中,则返回 true

bResult = Char.IsLetter(Character)

如果 Character 字符在 LuLlLtLmLo 类别中,则返回 true

bResult = Char.IsLetterOrDigit(Character)

如果 Character 字符在 LuLlLtLmLoNdNl 类别中,则返回 true

bResult = Char.IsLower(Character)

如果 Character 字符在 Ll 类别中,则返回 true

bResult = Char.IsUpper(Character)

如果 Character 字符在 Lu 类别中,则返回 true

此外,这些函数支持使用两个参数:我们可以指定一个字符串和该字符串中字符的位置,而不是单个字符。

3.7. 操作系统库

该库包含与 Double Commander 运行所在的操作系统相关的函数。

以下是该库中可用函数的列表:

操作系统库
函数名称描述

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)

将用新名称 sNewName 重命名文件 sOldName

注意:如果名为 sNewName 的文件已存在,它将被替换!

如果成功,函数返回 true

如果失败,函数返回三样东西:

  1. nil 表示失败
  2. sError 为错误消息描述
  3. iError 为错误代码编号

Value = os.getenv(VariableName)

将返回参数中传递的变量 VariableNameValue
如果不存在该名称的变量,它将返回 nil

os.setenv(VariableName, Value)

添加或更改 VariableName 环境变量。如果出现错误,函数返回 -1。

os.unsetenv(VariableName)

移除 VariableName 环境变量。如果出现错误,函数返回 -1。

4. 索引

DC 库

DC.CurrentPanel
DC.ExecuteCommand
DC.LogWrite


系统库

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


剪贴板库

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


对话框库

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.GetUnicodeCategory
Char.IsDigit
Char.IsLetter
Char.IsLetterOrDigit
Char.IsLower
Char.IsUpper


操作系统库

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


Valid HTML 4.0 Transitional CSS Valid!