Double Commander

2.15. Scripts Lua

Contenido

1. Introducción
2. DLL requerida
3. Bibliotecas de funciones de Double Commander
3.1. Biblioteca DC
3.1.1. Ejemplo de uso de DC.ExecuteCommand
3.2. Biblioteca del sistema
3.2.1. Detalles del valor devuelto por SysUtils.FileGetAttr
3.2.2. Ejemplo de uso de SysUtils.FileGetAttr
3.2.3. Ejemplo usando FindFirst, FindNext y FindClose
3.3. Biblioteca del portapapeles
3.3.1. Ejemplo de uso de la biblioteca del portapapeles
3.4. Biblioteca de diálogos
3.4.1. Botones mostrados en Dialogs.MessageBox
3.4.2. Estilo de ventana de Dialogs.MessageBox
3.4.3. Botón activo predeterminado de Dialogs.MessageBox
3.4.4. Valor devuelto de Dialogs.MessageBox
3.4.5. Ejemplo de uso de Dialogs.MessageBox
3.4.6. Ejemplo de uso de Dialogs.InputQuery
3.5. Biblioteca UTF-8
3.6. Biblioteca de caracteres
3.7. Biblioteca del sistema operativo
4. Índice

1. Introducción

Para obtener información detallada sobre el lenguaje de programación de scripts Lua, visite el sitio web de Lua.

Double Commander puede ejecutar scripts Lua mediante el comando cm_ExecuteScript.
Los parámetros del script deben pasarse tal cual, sin escape (sin comillas o "\"), para ello necesitamos usar la variable %"0: por ejemplo, para el archivo bajo el cursor use %"0%p0 en lugar de %p0, para el directorio actual use %"0%D en lugar de %D. De lo contrario, si Double Commander agrega automáticamente comillas, estas se pasarán como parte del parámetro y tendrá que tener esto en cuenta.
Para obtener una lista de todos los archivos seleccionados, podemos usar variables (%LU, %FU o %RU) o comandos internos (cm_SaveSelectionToFile, cm_SaveFileDetailsToFile, cm_CopyFullNamesToClip o cm_CopyFileDetailsToClip). Por ejemplo, podemos usar %p: en este caso, Double Commander pasará todos los nombres de archivos seleccionados en una línea, separando los nombres con espacios.

También es posible escribir plugins de contenido usando scripts Lua, los ejemplos se pueden encontrar en la carpeta del programa (plugins/wdx/scripts). Hay una página dedicada a la escritura de plugins en la Wiki. Restricción: solo se admiten los siguientes tipos de datos

La lista anterior contiene nombres del archivo de encabezado, en scripts Lua debemos usar los valores numéricos especificados entre paréntesis.


Acerca de la codificación de texto

Todas las funciones adicionales descritas a continuación aceptan parámetros de cadena codificados en UTF-8 y devuelven cadenas en esta codificación (excepto la función LazUtf8.ConvertEncoding).

Algunas funciones en bibliotecas estándar de Lua han sido reemplazadas por funciones de Double Commander o Free Pascal/Lazarus (o se han escrito nuevas funciones), lo que proporciona soporte UTF-8.

Al escribir plugins, también deberíamos usar UTF-8 para datos de texto (ft_multiplechoice, ft_string y ft_fulltext).

Al guardar scripts, utilice la codificación UTF-8 sin BOM.


Notas importantes

El uso de Lua para automatización tiene grandes posibilidades, pero en ciertas situaciones puede ser necesario prestar atención a algunos detalles. Intentemos recopilar estos contenidos en esta subsección.

1. Si las opciones actualización automática y cargar lista de archivos en un hilo separado están habilitadas, la función de actualización trabajará de forma asíncrona. Al mismo tiempo, los scripts se ejecutan en el hilo principal de Double Commander, por lo que en ciertos casos todo esto puede afectar la ejecución de sus scripts. Por ejemplo, a veces la ejecución consecutiva de comandos de navegación puede no funcionar (por ejemplo, directorios grandes, discos lentos), en este caso, intente deshabilitar cargar lista de archivos en un hilo separado o busque soluciones alternativas.

Si su script crea nuevos archivos o renombra archivos existentes en el panel actual, pero luego no finaliza y ejecuta algunas operaciones adicionales (por ejemplo, seleccionar archivos o mover el cursor), en ciertos casos estas operaciones no tendrán efecto: no todos los archivos pueden haber estado ya en el panel, primero necesita llamar al comando cm_Refresh. Bajo las condiciones mencionadas, cm_Refresh también se ejecutará de forma asíncrona, y Double Commander puede no tener tiempo para actualizar completamente la lista de archivos después de sus cambios.

La actualización automática y cargar la lista de archivos en un hilo separado son funciones convenientes del administrador de archivos, por lo tanto, a través de experimentación se encontró un método estable de trabajo, que es devolver temporalmente el control al programa y permitir que la lista de archivos se actualice completamente:

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

2. La función Lua io.open usa la función estándar C fopen: en modo texto, esta función puede convertir tipos de fin de línea (CRLF, LF o CR) al leer y escribir, lo que podría causar resultados inesperados. Si encuentra archivos con diferentes tipos de fin de línea o está escribiendo scripts multiplataforma, debe considerar esto, o más prácticamente, priorizar el uso del modo binario.

3. En Linux y otros sistemas operativos tipo Unix, para el cuadro de diálogo de propiedades de archivo, se llama a la función ContentGetValue con la bandera CONTENT_DELAYIFSLOW (cuarto parámetro, valor 1), esto evita retrasos al abrir la ventana: si la recuperación de datos es lenta, podemos excluir estos datos simplemente agregando una verificación del valor de la bandera y devolviendo nil para esos campos o plugins.

4. Si el plugin debería devolver una cadena vacía, pasar nil es más rápido que pasar "".

2. DLL requerida

Para poder interpretar archivos de script Lua, necesitamos un archivo DLL de Lua. Double Commander soporta las versiones 5.1 a 5.4.

Podemos utilizar el archivo DLL del proyecto LuaJIT. LuaJIT combina un intérprete de alta velocidad escrito en ensamblador con un compilador avanzado JIT. Además, obtenemos la biblioteca FFI, que permite llamar funciones externas en C y usar estructuras de datos en C desde código Lua puro.

La versión de Windows de DC incluye por defecto la DLL de Lua (en DC 0.9.7 y versiones posteriores proviene del proyecto LuaJIT). En otros casos, podemos buscar e instalarla mediante un gestor de paquetes o compilarla nosotros mismos. Si utilizamos la versión de 64 bits de DC, entonces la DLL también debe ser de 64 bits.

Por defecto, DC busca un archivo llamado lua5.1.dll (Windows), liblua5.1.so.0 (Unix o GNU/Linux) o liblua5.1.dylib (macOS) en su propio directorio y en los directorios del sistema. Podemos cambiar el nombre del archivo (y la ruta) en el parámetro Archivo de biblioteca Lua a usar.

3. Bibliotecas de funciones de Double Commander

Double Commander proporciona algunas bibliotecas de funciones para nuestros scripts Lua.

A continuación se muestra la lista de estas bibliotecas.

Lista de bibliotecas
Nombre de la bibliotecaNombre en scriptDescripción breve
DCFunciones específicas de Double Commander
SysUtilsVarias funciones del sistema
ClipbrdProporciona funcionalidad del portapapeles externo
DialogsInteracción con el usuario
LazUtf8Funciones de cadenas UTF-8
CharObtener información de caracteres
osFunciones relacionadas con el sistema operativo

3.1. Biblioteca DC

Esta biblioteca contiene funciones específicas de Double Commander.

Proporciona todas las funciones en la tabla DC.

Biblioteca DC
Nombre de la funciónDescripción

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

Escribe un mensaje en la ventana de registro:

  • sMessage : Texto del mensaje.
  • iMsgType : Tipo de mensaje: 0 - Información, 1 - Éxito, 2 - Error.
  • bForce : Valor booleano. Si es verdadero, mostrará la ventana de registro incluso cuando esté oculta.
  • bLogFile : Valor booleano. Si es verdadero, también escribirá el mensaje en el archivo de registro.

iPanel = DC.CurrentPanel()

Obtiene el panel activo: devuelve 0 si el panel izquierdo está activo, de lo contrario devuelve 1.

DC.CurrentPanel(iPanel)

Establece el panel activo: iPanel igual a 0 para el panel izquierdo, igual a 1 para el panel derecho.

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

Permite que el script invoque comandos internos de Double Commander.

sCommand es el nombre real del comando interno.

Podemos proporcionar cualquier cantidad de parámetros Param... que admita el comando.

Además de los comandos internos, en los scripts también podemos usar el comando especial cm_ExecuteToolBarItem, que permite invocar botones de la barra de herramientas mediante identificadores (en el programa, esta función proporciona la capacidad de usar atajos de teclado para los botones de la barra de herramientas). El uso de este comando es similar al de los comandos internos normales (ver ejemplo a continuación) y tiene los siguientes parámetros:

Parámetro Valor Descripción
ToolBarID TfrmOptionsToolbar Botón de la barra de herramientas principal
TfrmOptionsToolbarMiddle Botón de la barra de herramientas central
(no existe) Botón de la barra de herramientas principal
ToolItemID Identificador Identificador único del botón

Los identificadores únicos se almacenan en la etiqueta ID. Tenemos varias formas de obtenerlo: podemos encontrar el botón en el archivo doublecmd.xml o en los archivos de copia de seguridad de la barra de herramientas, o simplemente copiar el botón al portapapeles y pegar su código en un editor de texto.

Nota: Los identificadores se generan automáticamente y no tienen por qué coincidir con los identificadores de botones similares en otra copia del programa, pero si es necesario, podemos establecer manualmente nuestros propios valores.

3.1.1. Ejemplo de uso de DC.ExecuteCommand

En este ejemplo, escribimos un script simple que realizará las siguientes acciones:

  1. Enfocar el panel derecho
  2. Cerrar todas las pestañas abiertas
  3. Cambiar a una carpeta específica
  4. Enfocar el panel izquierdo
  5. Cerrar todas las pestañas abiertas
  6. Cambiar a una carpeta específica
  7. Abrir una nueva pestaña
  8. Cambiar a una carpeta específica
-- 1. Enfocar el panel derecho.
DC.ExecuteCommand("cm_FocusSwap", "side=right")

-- 2. Cerrar todas las pestañas.
DC.ExecuteCommand("cm_CloseAllTabs")

-- 3. Cambiar a un directorio específico.
DC.ExecuteCommand("cm_ChangeDir", "E:\\FakeKey\\Documents\\Music")

-- 4. Enfocar el panel izquierdo.
DC.ExecuteCommand("cm_FocusSwap", "side=left")

-- 5. Cerrar todas las pestañas.
DC.ExecuteCommand("cm_CloseAllTabs")

-- 6. Cambiar a un directorio específico.
DC.ExecuteCommand("cm_ChangeDir", "C:\\Users\\Public\\Music")

-- 7. Abrir una nueva pestaña.
DC.ExecuteCommand("cm_NewTab")

-- 8. Cambiar a un directorio específico.
DC.ExecuteCommand("cm_ChangeDir", "E:\\VirtualMachines\\ShareFolder")

Usando el comando interno cm_ExecuteScript, podemos configurar un botón de la barra de herramientas para ejecutar nuestro script.

Supongamos que este archivo de script es E:\scripts\lua\music.lua, podemos configurar el botón de la siguiente manera:

Invocar script Lua desde la barra de herramientas

Además, también podemos usar el editor interno de Double Commander para editar scripts. Si el nombre del archivo tiene la extensión .lua, el editor interno lo reconocerá y proporcionará resaltado de sintaxis para el lenguaje Lua:

Resaltado de sintaxis Lua en el editor interno

3.2. Biblioteca del sistema

Esta biblioteca contiene varias funciones del sistema.

Proporciona todas las funciones en la tabla SysUtils.

Biblioteca del sistema
Nombre de la funciónDescripción

SysUtils.Sleep(iMilliseconds)

Pausa la ejecución del script durante iMilliseconds milisegundos especificados.
Después del tiempo especificado, la ejecución del script continuará.

SysUtils.GetTickCount()

Devuelve un conteo incremental de tics del reloj. Se puede usar para medir el tiempo, pero no se debe asumir el intervalo entre tics.

bExists = SysUtils.FileExists(sFileName)

Verifica si existe un archivo específico en el sistema de archivos.

Si existe un archivo llamado sFileName en el disco, devuelve el valor true en bExists; de lo contrario, devuelve false.

bExists = SysUtils.DirectoryExists(sDirectory)

Verifica si sDirectory existe en el sistema de archivos y es realmente un directorio.

Si es así, la función devuelve el valor true en bExists; de lo contrario, devuelve false.

iAttr = SysUtils.FileGetAttr(sFileName)

Devuelve la configuración de atributos del archivo sFileName en iAttr.

Para obtener una descripción detallada del valor devuelto, consulte aquí.

Handle, FindData = SysUtils.FindFirst(sPath)

Busca archivos que coincidan con sPath, generalmente usando comodines.

Si no se encuentra ningún archivo, Handle será nil.

Cuando se encuentra al menos un elemento, el Handle devuelto se puede usar en llamadas posteriores a SysUtils.FindNext para buscar otras coincidencias del mismo patrón.

La tabla FindData contiene información sobre el archivo o directorio encontrado.

Los campos de la tabla FindData son los siguientes:

  • Name : Nombre del archivo (sin incluir la ruta).
  • Attr : Atributos del archivo (para más detalles, consulte aquí).
  • Size : Tamaño del archivo en bytes.
  • Time : Marca de tiempo del archivo (segundos desde el 1 de enero de 1970).

Result, FindData = SysUtils.FindNext(Handle)

Busca el siguiente elemento coincidente en la secuencia de búsqueda iniciada por FindFirst, reutilizando el Handle previamente devuelto.

Si se encuentra un archivo o directorio, el Result devuelto no será nulo; de lo contrario, será nil.

Las mismas consideraciones que para SysUtils.FindFirst también se aplican aquí.

Nota: La última llamada a SysUtils.FindNext siempre debe ir seguida de una llamada a SysUtils.FindClose usando el mismo Handle. De lo contrario, provocará una pérdida de memoria.

SysUtils.FindClose(Handle)

Finaliza una serie de llamadas a SysUtils.FindFirst/SysUtils.FindNext.

Libera cualquier memoria utilizada por estas llamadas.

Es absolutamente necesario realizar esta llamada; de lo contrario, podría causar una pérdida de memoria.

bResult = SysUtils.CreateDirectory(sDirectory)

Crea una serie de directorios. sDirectory es la ruta completa del directorio.

Devuelve true si sDirectory ya existe o se crea correctamente. Devuelve false si falla la creación de alguna parte.

bResult = SysUtils.CreateHardLink(sFileName, sLinkName)

Crea un enlace duro sLinkName para el archivo sFileName.

Devuelve true si tiene éxito; de lo contrario, devuelve false.

bResult = SysUtils.CreateSymbolicLink(sFileName, sLinkName)

Crea un enlace simbólico sLinkName para el archivo o directorio sFileName.

Devuelve true si tiene éxito; de lo contrario, devuelve false.

sTarget = SysUtils.ReadSymbolicLink(sLinkName, bRecursive)

Lee el destino del enlace simbólico sLinkName.

Si bRecursive es true y el enlace apunta a otro enlace, se resuelve recursivamente hasta encontrar un nombre de archivo válido que no sea un enlace.

Devuelve la ruta a la que apunta el enlace simbólico sLinkName, o una cadena vacía si el enlace no es válido o el archivo al que apunta no existe y bRecursive es true.

sName = SysUtils.ExtractFileName(sFileName)

Extrae la parte del nombre del archivo de un nombre de archivo con ruta completa.

El nombre del archivo consiste en todos los caracteres después del último carácter separador de directorio ("/" o "\") o de la letra de unidad.

sExt = SysUtils.ExtractFileExt(sFileName)

Devuelve la extensión del nombre del archivo (todos los caracteres después del último "." (punto), incluyendo el carácter ".").

sPath = SysUtils.ExtractFilePath(sFileName)

Extrae la ruta (incluyendo la letra de unidad) del nombre del archivo.

La ruta consiste en todos los caracteres antes del último carácter separador de directorio ("/" o "\"), incluyendo el propio separador de directorio.

sDir = SysUtils.ExtractFileDir(sFileName)

Extrae solo la parte del directorio de sFileName, incluyendo la letra de unidad.

El nombre del directorio no tiene un separador de directorio final, a diferencia de SysUtils.ExtractFilePath.

sDrive = SysUtils.ExtractFileDrive(sFileName)

Extrae la parte de la unidad del nombre del archivo.

Tenga en cuenta que algunos sistemas operativos no admiten letras de unidad.

sName = SysUtils.GetAbsolutePath(sFileName, sBaseDirectory)

Devuelve la ruta absoluta (completa) de un archivo:

  • sFileName : Nombre del archivo con una ruta relativa.
  • sBaseDirectory : Directorio que se utilizará como directorio base para sFileName.

Si no se puede obtener la ruta absoluta, la función devolverá el valor de sFileName.

sName = SysUtils.GetRelativePath(sFileName, sBaseDirectory)

Devuelve el nombre del archivo relativo al directorio especificado:

  • sFileName : Nombre del archivo completo (absoluto).
  • sBaseDirectory : Directorio que se utilizará como directorio base para sFileName.

Si sFileName y sBaseDirectory contienen el mismo valor, la función devolverá una cadena vacía (""). Si no se puede obtener un nombre de archivo con una ruta relativa, la función devolverá el valor de sFileName.

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

Devuelve true si sFileName coincide con la máscara sMask proporcionada.

iMaskOptions (parámetro opcional, por defecto 0) se establece como la suma de los siguientes valores:

Valor Descripción
1
Distingue mayúsculas de minúsculas
2
Ignora signos diacríticos y ligaduras
4
Filtro estilo Windows: "*.*" también coincide con archivos sin extensión, etc.
8
Habilita soporte para pinyin (usará el archivo pinyin.tbl)

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

Devuelve true si sFileName coincide con al menos una de las máscaras en sMaskList separadas por sSeparator (por defecto ";").

sSeparator e iMaskOptions (ver arriba) son parámetros opcionales.

sTempFileName = SysUtils.GetTempName()

Devolverá un nombre de archivo que se utilizará como nombre de archivo temporal (en el directorio de archivos temporales del sistema), similar a la función os.tmpname, pero el archivo se creará en un subdirectorio que se eliminará automáticamente cuando se cierre Double Commander.
Si la función no puede crear un nombre único, devolverá una cadena vacía.

SysUtils.PathDelim

Carácter utilizado por el sistema operativo actual para separar nombres de directorios en rutas completas de archivos.

En sistemas Unix/Linux, el separador de directorios será "/", mientras que en Windows será "\".

3.2.1. Detalles del valor devuelto por SysUtils.FileGetAttr

FileGetAttr devuelve la configuración de atributos del archivo sFileName.

Los atributos son una combinación OR de las siguientes constantes:

Constantes utilizadas en el valor devuelto por SysUtils.FileGetAttr
ValorSignificado
0x00000001
faReadOnly
El archivo es de solo lectura.
0x00000002
faHidden
El archivo está oculto.
En Unix/Linux, esto significa que el nombre del archivo comienza con un punto.
0x00000004
faSysFile
El archivo es un archivo del sistema.
En Unix/Linux, esto significa que el archivo es un dispositivo de caracteres o bloques, o una tubería nombrada (FIFO).
0x00000008
faVolumeId
Etiqueta de volumen.
Solo se aplica a sistemas de archivos FAT (no VFAT o FAT32) en DOS/Windows.
0x00000010
faDirectory
El archivo es un directorio.
0x00000020
faArchive
El archivo ha sido archivado.
No es posible en Unix/Linux.
0x00000400
faSymLink
El archivo es un enlace simbólico.
Nota: Si ocurre un error, se devolverá -1.

Vea el ejemplo en la siguiente sección.

3.2.2. Ejemplo de uso de SysUtils.FileGetAttr

El siguiente script es un ejemplo del uso de SysUtils.FileGetAttr.

Cuando detecta que el argumento es un directorio, abre una nueva pestaña en el panel activo y cambia a ese directorio.

local params = {...}
local iAttr

if #params == 1 then -- ¿Recibimos al menos un parámetro?
  iAttr = SysUtils.FileGetAttr(params[1])
  if iAttr > 0 then -- ¿Obtuvimos un atributo válido?
    if math.floor(iAttr / 0x00000010) % 2 ~= 0 then
      -- ¿Está establecido el cuarto bit? Entonces es un directorio.
      DC.ExecuteCommand("cm_NewTab")
      DC.ExecuteCommand("cm_ChangeDir", params[1])
    end
  end
end

En el ejemplo anterior, params[1] es el primer argumento pasado al script.

Cuando se utiliza el comando interno cm_ExecuteScript, será el primer argumento pasado después del nombre del archivo de script.

Por lo tanto, en nuestro ejemplo, podemos configurar un botón de la barra de herramientas como sigue:

Uso de parámetros con cm_ExecuteScript

En este ejemplo, el parámetro %"0%p se pasará al script. Esto representará el nombre del archivo del elemento seleccionado en el panel activo actual sin comillas.

3.2.3. Ejemplo usando FindFirst, FindNext y FindClose

En el siguiente ejemplo de script, escanearemos el contenido del directorio recibido como parámetro y almacenaremos los datos resultantes en un archivo de texto cuyo nombre se pasa como segundo parámetro.

Esto nos dará una buena comprensión del uso de FindFirst, FindNext y FindClose.

local params = {...}

if #params == 2 then -- ¿Recibimos dos parámetros?
  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

En el ejemplo anterior, necesitamos pasar dos argumentos al script:

  1. params[1] - El directorio cuyo contenido queremos
  2. params[2] - El nombre del archivo de salida donde almacenar los resultados

Por lo tanto, es fácil configurar un botón de la barra de herramientas usando el comando interno cm_ExecuteScript y pasarle los parámetros.

Uso de parámetros con cm_ExecuteScript

En este ejemplo, el parámetro %"0%Ds se pasará como primer argumento al script. Esto representará el directorio mostrado en el panel activo sin comillas.

3.3. Biblioteca del portapapeles

Double Commander puede proporcionar funcionalidad de portapapeles externo para nuestros scripts Lua.

La siguiente tabla muestra las funciones relacionadas:

Biblioteca del portapapeles
Nombre de la funciónDescripción

Clipbrd.Clear()

Borra el contenido del portapapeles.

sVar = Clipbrd.GetAsText()

Obtiene el contenido textual actual del portapapeles y lo asigna a sVar. Si el portapapeles no contiene texto, la función devolverá una cadena vacía.

Clipbrd.SetAsText(sVar)

Almacena el contenido textual de sVar en el portapapeles.

Clipbrd.SetAsHtml(sHtml)

Agrega texto en formato HTML sHtml al portapapeles (formato de portapapeles CF_HTML).

Este contenido será insertado en aplicaciones que soporten este formato de portapapeles, como MS Word, LO Writer, etc.

Es correcto usar tanto Clipbrd.SetAsText como Clipbrd.SetAsHtml para almacenar datos. Cuando peguemos, la aplicación usará el mejor formato que soporte.

Por ejemplo, podríamos tener lo siguiente:

  • Clipbrd.SetAsText("¡Bienvenido a Double Commander!")
  • Clipbrd.SetAsHtml("¡Bienvenido a <b>Double Commander</b>!"))

Si cambiamos a Notepad e intentamos pegar algo, se pegará en texto plano el mensaje copiado con Clipbrd.SetAsText. Pero si cambiamos a Microsoft Word y pegamos algo, se pegará el segundo, es decir, Double Commander en negrita, porque Microsoft Word reconoce y soporta ese tipo de contenido del portapapeles.

3.3.1. Ejemplo de uso de la biblioteca del portapapeles

El siguiente ejemplo utiliza tres funciones relacionadas con el portapapeles: Clear, GetAsText y SetAsText.

Este es un script relativamente largo, pero combina muy bien algunas de las funciones vistas anteriormente.

Se asume que nuestro panel activo está actualmente ubicado en un directorio que contiene muchos archivos de texto fuente.

También se asume que actualmente tenemos una palabra en el portapapeles y que recibirá la carpeta activa actual como único parámetro.

El script escaneará los archivos del nivel del directorio actual y leerá su contenido uno por uno para detectar líneas de texto que contengan la palabra del portapapeles.

Luego, los nombres de archivo que contengan al menos una línea con esa palabra se colocarán en el portapapeles.

Posteriormente, el script utilizará el comando interno cm_LoadSelectionFromClip para seleccionar los archivos que contengan dicha palabra.

Además, al final, volveremos a colocar la palabra original que necesitábamos buscar en el portapapeles.

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 -- ¿Recibimos un parámetro?
  sSearchString = Clipbrd.GetAsText() -- Obtener la expresión a buscar.
  Clipbrd.Clear() -- Asegurarnos de que el portapapeles esté vacío.
  DC.ExecuteCommand("cm_MarkUnmarkAll") -- Asegurarnos de que nada esté seleccionado.

  -- Escaneemos uno por uno todos los archivos del directorio.
  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 -- ¿Obtuvimos un atributo válido?
        -- ¡Necesitamos archivos, no directorios!
        if math.floor(iAttr / 0x00000010) % 2 == 0 then

          -- Ahora leamos el archivo línea por línea hasta el final o hasta encontrarlo.
          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

  -- ¡Si encontramos algo, seleccionémoslo!
  if sFileToSelect ~= "" then
    Clipbrd.SetAsText(sFileToSelect)
    DC.ExecuteCommand("cm_LoadSelectionFromClip")
  end

  Clipbrd.SetAsText(sSearchString) -- Restaurar el contenido del portapapeles.
end

3.4. Biblioteca de diálogos

Esta biblioteca permite que nuestros scripts interactúen con el usuario, mostrando mensajes, solicitando respuestas, etc.

La siguiente tabla enumera las funciones relacionadas:

Biblioteca de diálogos
Nombre de la funciónDescripción

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

Muestra un cuadro de mensaje que solicita al usuario hacer clic en un botón, el cual será devuelto por la función:

  • sMessage: Texto dentro del cuadro de mensaje.
  • sTitle: Título del cuadro de mensaje.
  • iFlags: Valor de constantes combinadas con OR bit a bit, utilizado para determinar los botones mostrados, el estilo de ventana y el botón predeterminado. Consulte las tablas siguientes para conocer los botones mostrados, el estilo de ventana o el botón predeterminado.
  • iButton: Valor devuelto que representa el botón presionado por el usuario (consulte esta tabla).

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

Muestra un cuadro de solicitud donde el usuario puede introducir una cadena de texto:

  • sTitle: Título del cuadro de solicitud.
  • sMessage: Texto dentro del cuadro de solicitud.
  • bMask: Valor booleano, si es verdadero mostrará asteriscos para ocultar los caracteres.
  • sDefault: Texto sugerido por defecto que el usuario puede modificar según sea necesario.
  • bResult: Valor booleano devuelto que indica si el usuario realmente introdujo algún contenido.
  • sAnswer: Cadena devuelta cuando el usuario introduce contenido y hace clic en Aceptar.

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

Muestra un cuadro de diálogo que permite al usuario seleccionar un elemento de una lista:

  • sTitle: Título del cuadro de diálogo.
  • sMessage: Texto dentro del cuadro de diálogo.
  • aItems: Una tabla Lua donde cada elemento debe ser una cadena de texto.
  • sDefault: Elemento seleccionado por defecto en la lista.
  • sItem: Devuelve el elemento seleccionado como una cadena, o nil si se cancela el diálogo.
  • iItem: Índice del elemento seleccionado (contando desde 1, siguiendo la convención de tablas Lua).

3.4.1. Botones mostrados en Dialogs.MessageBox

Los botones mostrados por la función Dialogs.MessageBox están controlados por los siguientes valores constantes combinados con OR bit a bit:

Constantes ButFlags para mostrar botones en Dialogs.MessageBox
Valor de la constanteBotones mostrados, de izquierda a derecha
0x0000
MB_OK
Botón OK
0x0001
MB_OKCANCEL
Botón OK Botón CANCEL
0x0002
MB_ABORTRETRYIGNORE
Botón ABORT Botón RETRY Botón IGNORE
0x0003
MB_YESNOCANCEL
Botón YES Botón NO Botón CANCEL
0x0004
MB_YESNO
Botón YES Botón NO
0x0005
MB_RETRYCANCEL
Botón RETRY Botón CANCEL

3.4.2. Estilo de ventana de Dialogs.MessageBox

El estilo de ventana mostrado por la función Dialogs.MessageBox está controlado por los siguientes valores constantes combinados con OR bit a bit:

Constantes ButFlags para iconos y estilos de Dialogs.MessageBox
Valor de la constanteEstilo de ventana
0x0040
MB_ICONINFORMATION
Icono INFORMATION Ventana de información
0x0030
MB_ICONWARNING
Icono WARNING Ventana de advertencia
0x0020
MB_ICONQUESTION
Icono QUESTION Ventana de confirmación
0x0010
MB_ICONERROR
Icono ERROR Ventana de error

3.4.3. Botón activo predeterminado de Dialogs.MessageBox

El botón activo predeterminado mostrado por la función Dialogs.MessageBox está controlado por los siguientes valores constantes combinados con OR bit a bit:

Constantes ButFlags para botón predeterminado de Dialogs.MessageBox
Valor de la constanteBotón predeterminado
0x0000
MB_DEFBUTTON1
Predeterminado es el primer botón de la izquierda
0x0100
MB_DEFBUTTON2
Predeterminado es el segundo botón de la izquierda
0x0200
MB_DEFBUTTON3
Predeterminado es el tercer botón de la izquierda

3.4.4. Valor devuelto de Dialogs.MessageBox

El número devuelto por la función Dialogs.MessageBox representa el botón presionado por el usuario, como se muestra a continuación:

Valores ButPressed devueltos cuando se presiona un botón en Dialogs.MessageBox
Valor de la constanteBotón presionado
0x0000
mrNone
No se presionó ningún botón
0x0001
mrOK
Resultado OK
0x0002
mrCancel
Resultado CANCEL
0x0003
mrAbort
Resultado ABORT
0x0004
mrRetry
Resultado RETRY
0x0005
mrIgnore
Resultado IGNORE
0x0006
mrYes
Resultado YES
0x0007
mrNo
Resultado NO

Nota: Si se presiona la "x" en la esquina superior derecha o se cierra la ventana con Esc, se devolverá el valor del botón "Cancelar".

3.4.5. Ejemplo de uso de Dialogs.MessageBox

A continuación se muestra un pequeño script usando Dialogs.MessageBox y la ventana resultante que se mostrará:

-- Botones mostrados
MB_OK = 0x0000
MB_OKCANCEL = 0x0001
MB_ABORTRETRYIGNORE = 0x0002
MB_YESNOCANCEL = 0x0003
MB_YESNO = 0x0004
MB_RETRYCANCEL = 0x0005

-- Estilo de ventana
MB_ICONINFORMATION = 0x0040
MB_ICONWARNING = 0x0030
MB_ICONQUESTION = 0x0020
MB_ICONERROR = 0x0010

-- Botón predeterminado
MB_DEFBUTTON1 = 0x0000
MB_DEFBUTTON2 = 0x0100
MB_DEFBUTTON3 = 0x0200

-- Devolución del botón presionado
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("¿Desea salir?", "Pregunta", iFlags)

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

Ejemplo de uso de Dialogs.MessageBox

3.4.6. Ejemplo de uso de Dialogs.InputQuery

A continuación se muestra un pequeño script usando Dialogs.InputQuery y la ventana resultante que se mostrará:

bResult, sAnswer = Dialogs.InputQuery("Autenticación", "Por favor ingrese su nombre:", false, "Juan")

if bResult == true then
  Dialogs.MessageBox("¡Hola " .. sAnswer .. "!", "¡Bienvenido!", 0x0040)
end

Ejemplo de uso de Dialogs.InputQuery

3.5. Biblioteca UTF-8

Esta biblioteca proporciona soporte básico para la codificación UTF-8.

Proporciona todas las funciones en la tabla LazUtf8.

Biblioteca UTF-8
Nombre de la funciónDescripción

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

Busca una subcadena en una cadena comenzando desde una posición especificada. La búsqueda distingue entre mayúsculas y minúsculas.

Devuelve la posición de la primera aparición de la subcadena SearchText en la cadena SourceText, comenzando la búsqueda desde la posición Offset (por defecto 1).

Si SearchText no aparece en SourceText después del Offset dado, devuelve cero.

LazUtf8.Next(String)

Una función iteradora que devuelve el siguiente carácter en String junto con su posición inicial en bytes en cada llamada.

Ejemplo:

-- Imprimir pares de valores en formato "posición : carácter"
for iPos, sChar in LazUtf8.Next(String) do
  DC.LogWrite(iPos .. " : " .. sChar)
end

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

Copia una parte de una cadena.

Copy devuelve una cadena que es una copia de iCount caracteres de String comenzando desde la posición iIndex.

Si iCount es mayor que la longitud de la cadena String, el resultado se truncará. Si iIndex es mayor que la longitud de la cadena String, devuelve una cadena vacía.

iResult = LazUtf8.Length(String)

Devuelve el número de caracteres UTF-8 en una cadena.

sResult = LazUtf8.UpperCase(String)

Toma una cadena y devuelve una copia de esa cadena con todas las letras minúsculas cambiadas a mayúsculas.

sResult = LazUtf8.LowerCase(String)

Toma una cadena y devuelve una copia de esa cadena con todas las letras mayúsculas cambiadas a minúsculas.

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

Convierte la codificación de String de FromEnc a ToEnc.

Lista de valores de codificación admitidos:

  • Codificación del sistema predeterminada (depende de la configuración regional del sistema): "default".
  • Codificación ANSI (Windows) predeterminada (depende de la configuración regional del sistema): "ansi".
  • Codificación OEM (DOS) predeterminada (depende de la configuración regional del sistema): "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".
  • Otros: "macintosh", "koi8r", "koi8u", "koi8ru".
Significado de codificaciones especiales (ejemplos).

En Windows (inglés o ruso):
  • "default" - cp1252 o cp1251
  • "ansi" - cp1252 o cp1251
  • "oem" - cp850 o cp866
En Linux (inglés o ruso):
  • "default" - utf8
  • "ansi" - cp1252 o cp1251
  • "oem" - cp850 o cp866

sEnc = LazUtf8.DetectEncoding(String)

Devuelve el valor de codificación del texto transmitido.
La lista de codificaciones admitidas es similar a las utilizadas en la función LazUtf8.ConvertEncoding.

3.6. Biblioteca de caracteres

Esta biblioteca contiene funciones para verificar si un carácter pertenece a una categoría Unicode específica y para obtener la categoría de un carácter.

Lista de funciones disponibles en esta biblioteca:

Biblioteca de caracteres
Nombre de la funciónDescripción

iResult = Char.GetUnicodeCategory(Character)

Devuelve la categoría Unicode del carácter Character, uno de los siguientes valores:

ValorDescripción
  Letras:
0Mayúscula (Lu)
1Minúscula (Ll)
2Título (Lt)
3Modificadora (Lm)
4Otra letra (Lo)
  Marcas:
5No espaciadora (Mn)
6Espaciadora combinante (Mc)
7Adjunta (Me)
  Números:
8Dígito decimal (Nd)
9Número letra (Nl)
10Otro número (No)
  Puntuación:
11Conector (Pc)
12Guión (Pd)
13Apertura (Ps)
14Cierre (Pe)
15Inicial (Pi)
16Final (Pf)
17Otra puntuación (Po)
  Símbolos:
18Matemático (Sm)
19Moneda (Sc)
20Modificador (Sk)
21Otro símbolo (So)
  Separadores:
22Espacio (Zs)
23Línea (Zl)
24Párrafo (Zp)
  Otros:
25Control (Cc)
26Formato (Cf)
27Subrogado (Cs)
28Privado (Co)
29Sin asignar (Cn)

bResult = Char.IsDigit(Character)

Devuelve true si el carácter Character está en la categoría Nd.

bResult = Char.IsLetter(Character)

Devuelve true si el carácter Character está en las categorías Lu, Ll, Lt, Lm o Lo.

bResult = Char.IsLetterOrDigit(Character)

Devuelve true si el carácter Character está en las categorías Lu, Ll, Lt, Lm, Lo, Nd o Nl.

bResult = Char.IsLower(Character)

Devuelve true si el carácter Character está en la categoría Ll.

bResult = Char.IsUpper(Character)

Devuelve true si el carácter Character está en la categoría Lu.

Además, estas funciones admiten el uso de dos parámetros: podemos especificar una cadena y la posición de un carácter en esa cadena en lugar de un solo carácter.

3.7. Biblioteca del sistema operativo

Esta biblioteca contiene funciones relacionadas con el sistema operativo en el que se ejecuta Double Commander.

A continuación se muestra la lista de funciones disponibles en esta biblioteca:

Biblioteca del sistema operativo
Nombre de la funciónDescripción

iResultCode = os.execute(sCommand)

Ejecutará sCommand como si se ingresara en la línea de comandos y devolverá el código de resultado de la operación.

sCommand puede ser:

  • Comando de terminal, por ejemplo os.execute("dir > all.txt")
  • Archivo ejecutable, por ejemplo os.execute("C:\\Windows\\System32\\calc.exe")
  • Archivo ejecutable con parámetros:
    os.execute("C:\\Utils\\fsum.exe -md5 test.bin > md5.txt")

sTempFileName = os.tmpname()

Devolverá un nombre de archivo que se utilizará como nombre de archivo temporal (en el directorio de archivos temporales del sistema).
Si la función no puede crear un nombre único, devolverá una cadena vacía.

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

Eliminará el archivo o directorio denominado sFileName.

Si tiene éxito, la función devuelve true.

Si falla, la función devuelve tres cosas:

  1. nil indicando fallo
  2. sError como descripción del mensaje de error
  3. iError como número de código de error

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

Renombrará el archivo sOldName con el nuevo nombre sNewName.

Nota: ¡Si ya existe un archivo llamado sNewName, será reemplazado!

Si tiene éxito, la función devuelve true.

Si falla, la función devuelve tres cosas:

  1. nil indicando fallo
  2. sError como descripción del mensaje de error
  3. iError como número de código de error

Value = os.getenv(VariableName)

Devolverá el Value de la variable VariableName pasada en el argumento.
Si no existe una variable con ese nombre, devolverá nil.

os.setenv(VariableName, Value)

Añade o modifica la variable de entorno VariableName. Si hay un error, la función devuelve -1.

os.unsetenv(VariableName)

Elimina la variable de entorno VariableName. Si hay un error, la función devuelve -1.

4. Índice

Biblioteca DC

DC.CurrentPanel
DC.ExecuteCommand
DC.LogWrite


Biblioteca del sistema

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


Biblioteca del portapapeles

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


Biblioteca de diálogos

Dialogs.InputListBox
Dialogs.InputQuery
Dialogs.MessageBox


Biblioteca UTF-8

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


Biblioteca de caracteres

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


Biblioteca del sistema operativo

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


Valid HTML 4.0 Transitional CSS Valid!