Double Commander

2.15. Scripting Lua

Contenuto

1. Introduzione
2. Librerie dinamiche richieste (DLL)
3. Librerie di funzioni di Double Commander
3.1. Libreria DC
3.1.1. Esempio di utilizzo di DC.ExecuteCommand
3.2. Libreria di sistema
3.2.1. Dettagli sul valore restituito da SysUtils.FileGetAttr
3.2.2. Esempio di utilizzo di SysUtils.FileGetAttr
3.2.3. Esempio di utilizzo di FindFirst, FindNext e FindClose
3.3. Libreria degli appunti
3.3.1. Esempio di utilizzo della libreria degli appunti
3.4. Libreria dei dialoghi
3.4.1. Pulsanti visualizzati in Dialogs.MessageBox
3.4.2. Stili di finestra per Dialogs.MessageBox
3.4.3. Pulsante attivo predefinito di Dialogs.MessageBox
3.4.4. Valore restituito da Dialogs.MessageBox
3.4.5. Esempio di utilizzo di Dialogs.MessageBox
3.4.6. Esempio di utilizzo di Dialogs.InputQuery
3.5. Libreria UTF-8
3.6. Libreria dei caratteri
3.7. Libreria del sistema operativo
4. Indice

1. Introduzione

Per informazioni dettagliate sul linguaggio di programmazione Lua, visitare il sito ufficiale di Lua.

Double Commander consente di eseguire script Lua tramite il comando cm_ExecuteScript.
I parametri degli script devono essere passati così come sono, senza necessità di escape (senza virgolette o barre rovesciate "\\"), a tale scopo è consigliabile utilizzare la variabile %"0: ad esempio, per il file sotto il cursore utilizzare %"0%p0 anziché %p0, e per la cartella corrente %"0%D anziché %D. In caso contrario, se Double Commander aggiungesse automaticamente le virgolette, esse verrebbero passate come parte del parametro, e si dovrebbe gestirne la presenza nello script.
Per ottenere un elenco di tutti i file selezionati, è possibile ricorrere alle variabili di sistema (come %LU, %FU o %RU) oppure a comandi interni (quali cm_SaveSelectionToFile, cm_SaveFileDetailsToFile, cm_CopyFullNamesToClip o cm_CopyFileDetailsToClip). Ad esempio, se si utilizza la variabile %p, Double Commander passerà l'elenco dei nomi di tutti i file selezionati in un'unica riga di testo, separati da spazi.

Inoltre, è possibile sviluppare plugin di contenuto (WDX) tramite script Lua; alcuni esempi pratici sono disponibili nella cartella dell'applicazione (plugins/wdx/scripts). Sul wiki del progetto è presente una pagina dedicata allo sviluppo dei plugin. Limitazioni: sono supportati esclusivamente i seguenti tipi di dati:

L'elenco sopra riporta i nomi definiti nei file header (.h); negli script Lua è necessario fare riferimento ai rispettivi valori numerici indicati tra parentesi.


Informazioni sulla codifica del testo

Tutte le funzioni aggiuntive descritte di seguito accettano parametri stringa in formato codificato UTF-8 e restituiscono stringhe con la medesima codifica (ad eccezione della funzione LazUtf8.ConvertEncoding).

Alcune funzioni delle librerie standard di Lua sono state sostituite da equivalenti di Double Commander o di Free Pascal/Lazarus (oppure ne sono state create di nuove) per garantire il supporto nativo alla codifica UTF-8.

Nello sviluppo di plugin, è altrettanto necessario utilizzare la codifica UTF-8 per tutti i dati di tipo testo (ft_multiplechoice, ft_string e ft_fulltext).

Si consiglia di salvare i file di script utilizzando la codifica UTF-8 senza firma BOM.


Note importanti

L'automazione tramite Lua offre ampie potenzialità, ma in determinati contesti richiede attenzione ad alcuni dettagli implementativi. Di seguito sono raccolte alcune raccomandazioni utili.

1. Se sono attive le opzioni di aggiornamento automatico e di caricamento dell'elenco file in un thread separato, le funzioni di rinfresco operano in modalità asincrona. Poiché lo script viene eseguito nel thread principale (UI thread) di Double Commander, questa concorrenza potrebbe influenzare l'esecuzione in rari casi. Ad esempio, la chiamata consecutiva di comandi di navigazione potrebbe non produrre l'effetto sperato (specialmente con cartelle molto grandi o dischi lenti); in tali circostanze si consiglia di disabilitare il caricamento in thread separato o cercare percorsi alternativi.

Se lo script crea nuovi file o ne rinomina di esistenti nel pannello corrente e successivamente esegue operazioni aggiuntive (come la selezione o lo spostamento del cursore), in alcuni casi queste potrebbero fallire poiché l'elenco non è ancora aggiornato. È necessario chiamare preventivamente il comando cm_Refresh. Nelle condizioni descritte, anche cm_Refresh verrà eseguito in modo asincrono e Double Commander potrebbe non avere il tempo di ricostruire interamente l'elenco prima che lo script proceda.

Poiché l'aggiornamento automatico e il caricamento asincrono sono funzioni comode per l'utente, un metodo empirico e stabile per consentire a Double Commander di completare l'operazione consiste nel restituire momentaneamente il controllo al programma con una breve pausa:

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

2. La funzione io.open di Lua fa affidamento sulla funzione standard C fopen: in modalità testo, questa funzione effettua la conversione automatica delle interruzioni di riga (CRLF, LF o CR) in fase di lettura e scrittura, il che può produrre risultati imprevisti. Se si lavora con file aventi terminatori di riga diversi o se si sviluppano script multi-piattaforma, è essenziale tenerne conto, o più semplicemente forzare l'uso della modalità binaria.

3. Nei sistemi operativi Linux e Unix-like, all'interno del dialogo delle proprietà dei file, la funzione ContentGetValue viene richiamata impostando il flag CONTENT_DELAYIFSLOW (come quarto parametro, con valore pari a 1) per prevenire rallentamenti nell'apertura della finestra: se il recupero dei dati è particolarmente lento, è possibile restituire semplicemente nil per quel campo o per l'intero plugin verificando la presenza del suddetto flag.

4. Se il plugin deve restituire una stringa vuota, passare il valore nil risulta più efficiente rispetto alla stringa vuota "".

2. Librerie dinamiche richieste (DLL)

Per poter interpretare ed eseguire gli script Lua, Double Commander richiede la presenza della libreria dinamica di Lua; sono supportate le versioni da 5.1 a 5.4.

È possibile utilizzare le librerie derivanti dal progetto LuaJIT. LuaJIT combina un interprete ad alte prestazioni scritto in assembly con un compilatore JIT avanzato. Inoltre, fornisce l'accesso alla libreria FFI, che consente di invocare funzioni C esterne e di utilizzare strutture dati C direttamente da codice Lua.

La versione per Windows di Double Commander include già la libreria di Lua preinstallata (basata su LuaJIT a partire da DC 0.9.7); su altre piattaforme è possibile installarla tramite il gestore dei pacchetti di sistema o compilarla autonomamente. Se si utilizza la versione a 64 bit di Double Commander, anche la libreria dinamica deve essere compilata per architetture a 64 bit.

Per impostazione predefinita, DC ricerca la libreria all'interno della propria cartella e nei percorsi di sistema cercando i file lua5.1.dll (in Windows), liblua5.1.so.0 (in Linux e sistemi Unix-like) o liblua5.1.dylib (in macOS). È possibile modificare il nome del file e il relativo percorso impostando il parametro Libreria di runtime Lua da utilizzare nelle opzioni.

3. Librerie di funzioni di Double Commander

Double Commander espone diverse librerie di funzioni pronte all'uso per gli script Lua.

Di seguito viene riportato l'elenco delle librerie disponibili:

Elenco delle librerie
Nome libreriaNome nello scriptDescrizione
DCFunzioni specifiche di Double Commander
SysUtilsFunzioni di utilità e interazione con il sistema
ClipbrdFunzioni per interagire con gli appunti di sistema
DialogsFunzioni per l'interazione con l'utente tramite finestre di dialogo
LazUtf8Funzioni per la gestione di stringhe con codifica UTF-8
CharFunzioni per l'analisi delle proprietà dei caratteri Unicode
osFunzioni di sistema fornite dal sistema operativo

3.1. Libreria DC

Questa libreria racchiude le funzioni native specifiche di Double Commander.

Tutte le funzioni sono esposte all'interno della tabella globale DC.

Libreria DC
Nome funzioneDescrizione

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

Scrive un messaggio all'interno della finestra del registro (log):

  • sMessage : il testo del messaggio da visualizzare.
  • iMsgType : il tipo di messaggio: 0 - informativo, 1 - successo, 2 - errore.
  • bForce : valore booleano; se impostato su true, forza la visualizzazione della finestra del registro qualora fosse nascosta.
  • bLogFile : valore booleano; se impostato su true, scrive il messaggio anche all'interno del file di registro su disco.

iPanel = DC.CurrentPanel()

Restituisce il pannello attivo corrente: 0 se il pannello attivo è quello sinistro, 1 se è quello destro.

DC.CurrentPanel(iPanel)

Imposta il pannello attivo corrente: iPanel deve essere 0 per il pannello sinistro e 1 per il pannello destro.

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

Consente allo script di invocare uno dei comandi interni di Double Commander.

sCommand rappresenta il nome del comando interno da eseguire.

È possibile passare un numero variabile di parametri Param... accettati dal comando specifico.

In aggiunta ai comandi interni standard, è possibile utilizzare il comando speciale cm_ExecuteToolBarItem, che consente di azionare un pulsante della barra degli strumenti specificandone l'identificatore univoco (questa funzionalità permette, ad esempio, di associare scorciatoie da tastiera ai pulsanti). Il comando si utilizza in modo del tutto analogo a un normale comando interno ed accetta i seguenti parametri:

Parametro Valore Descrizione
ToolBarID TfrmOptionsToolbar Pulsanti della barra degli strumenti principale
TfrmOptionsToolbarMiddle Pulsanti della barra degli strumenti centrale
(assente) Pulsanti della barra degli strumenti principale
ToolItemID Identificatore L'identificatore univoco del pulsante

L'identificatore univoco è memorizzato all'interno del tag ID. Ci sono diversi modi per recuperarlo: esaminando il file di configurazione doublecmd.xml, i file di backup delle barre degli strumenti, oppure copiando semplicemente il pulsante negli appunti e incollandone il codice XML in un editor di testo.

Nota: questi identificatori vengono generati automaticamente e potrebbero differire tra diverse installazioni del programma; se necessario, è comunque possibile assegnare manualmente un valore personalizzato.

3.1.1. Esempio di utilizzo di DC.ExecuteCommand

In questo esempio viene illustrato un semplice script che esegue in sequenza le seguenti operazioni:

  1. Sposta il focus sul pannello destro;
  2. Chiude tutte le schede aperte al suo interno;
  3. Cambia percorso selezionando una cartella specifica;
  4. Sposta il focus sul pannello sinistro;
  5. Chiude tutte le schede aperte;
  6. Cambia percorso selezionando una cartella specifica;
  7. Apre una nuova scheda;
  8. Cambia percorso selezionando una cartella specifica.
-- 1. Sposta il focus sul pannello destro.
DC.ExecuteCommand("cm_FocusSwap", "side=right")
 
-- 2. Chiude tutte le schede.
DC.ExecuteCommand("cm_CloseAllTabs")
 
-- 3. Passa alla cartella specificata.
DC.ExecuteCommand("cm_ChangeDir", "E:\\FakeKey\\Documents\\Music")
 
-- 4. Sposta il focus sul pannello sinistro.
DC.ExecuteCommand("cm_FocusSwap", "side=left")
 
-- 5. Chiude tutte le schede.
DC.ExecuteCommand("cm_CloseAllTabs")
 
-- 6. Passa alla cartella specificata.
DC.ExecuteCommand("cm_ChangeDir", "C:\\Users\\Public\\Music")
 
-- 7. Apre una nuova scheda.
DC.ExecuteCommand("cm_NewTab")
 
-- 8. Passa alla cartella specificata.
DC.ExecuteCommand("cm_ChangeDir", "E:\\VirtualMachines\\ShareFolder")

Utilizzando il comando interno cm_ExecuteScript, è possibile configurare un pulsante sulla barra degli strumenti per l'esecuzione del nostro script.

Ipotizzando che il file di script sia salvato in E:\scripts\lua\music.lua, il pulsante può essere configurato come segue:

Esecuzione dello script Lua dalla barra dei pulsanti

È inoltre possibile utilizzare il visualizzatore/editor interno di Double Commander per modificare lo script. Se il file presenta l'estensione .lua, l'editor ne riconoscerà il tipo abilitando l'evidenziazione sintattica nativa per il linguaggio Lua:

Evidenziazione della sintassi Lua nell'editor interno

3.2. Libreria di sistema

Questa libreria racchiude varie funzioni di interazione con il sistema operativo.

Tutte le funzioni sono accessibili tramite la tabella SysUtils.

Libreria di sistema
Nome funzioneDescrizione

SysUtils.Sleep(iMilliseconds)

Sospende l'esecuzione dello script per la durata specificata in millisecondi (iMilliseconds). Trascorso tale intervallo, lo script riprende regolarmente.

SysUtils.GetTickCount()

Restituisce il valore incrementale dei cicli di clock del sistema. È utile per effettuare misurazioni temporali di precisione, ma non si deve fare affidamento su una durata fissa tra i singoli tick.

bExists = SysUtils.FileExists(sFileName)

Verifica l'effettiva presenza di un file nel file system.

Restituisce true in bExists se il file sFileName esiste sul disco, in caso contrario restituisce false.

bExists = SysUtils.DirectoryExists(sDirectory)

Verifica se il percorso sDirectory esiste nel file system ed è effettivamente una cartella (directory).

In caso positivo, restituisce true in bExists, altrimenti restituisce false.

iAttr = SysUtils.FileGetAttr(sFileName)

Restituisce in iAttr la maschera degli attributi del file sFileName.

Per spiegazioni dettagliate sui valori restituiti si veda la sezione dedicata.

Handle, FindData = SysUtils.FindFirst(sPath)

Avvia la ricerca di file che corrispondono al criterio specificato in sPath (solitamente contenente caratteri jolly).

Se non viene trovata alcuna corrispondenza, Handle assume il valore nil.

Se viene trovato almeno un elemento, l'oggetto Handle restituito deve essere riutilizzato nelle chiamate successive a SysUtils.FindNext per continuare la ricerca.

La tabella FindData racchiude le informazioni relative al file o alla cartella individuata.

La tabella FindData espone i seguenti campi:

  • Name : il solo nome del file (escluso il percorso);
  • Attr : gli attributi del file (per dettagli vedere qui);
  • Size : la dimensione del file espressa in byte;
  • Time : la data e ora dell'ultima modifica (espressa in timestamp Unix, secondi trascorsi dal 1° gennaio 1970).

Result, FindData = SysUtils.FindNext(Handle)

Consente di cercare l'elemento successivo nella sequenza di ricerca avviata con FindFirst, riutilizzando lo specifico Handle.

Restituisce un valore non nullo in Result se viene individuato un altro elemento, altrimenti restituisce nil.

Si applicano le medesime considerazioni descritte per SysUtils.FindFirst.

Nota: l'ultimo ciclo di chiamate a SysUtils.FindNext deve necessariamente concludersi con l'invocazione di SysUtils.FindClose sullo stesso oggetto Handle. La mancata chiusura provocherà una perdita di memoria (memory leak).

SysUtils.FindClose(Handle)

Conclude la sequenza di ricerca avviata con SysUtils.FindFirst e SysUtils.FindNext.

Rilascia le risorse di sistema e la memoria allocate per la ricerca.

Questa chiamata è fondamentale e obbligatoria per prevenire perdite di memoria.

bResult = SysUtils.CreateDirectory(sDirectory)

Crea la cartella o la struttura di cartelle specificata nel percorso assoluto sDirectory.

Restituisce true se la cartella esiste già o viene creata con successo. Restituisce false qualora fallisca la creazione di una qualsiasi delle sottocartelle.

bResult = SysUtils.CreateHardLink(sFileName, sLinkName)

Crea un collegamento fisico (hard link) denominato sLinkName per il file d'origine sFileName.

Restituisce true in caso di successo, altrimenti false.

bResult = SysUtils.CreateSymbolicLink(sFileName, sLinkName)

Crea un collegamento simbolico (symlink) denominato sLinkName che punta al file o alla cartella sFileName.

Restituisce true in caso di successo, altrimenti false.

sTarget = SysUtils.ReadSymbolicLink(sLinkName, bRecursive)

Legge e restituisce la destinazione a cui punta il collegamento simbolico sLinkName.

Se il parametro bRecursive è impostato su true e il collegamento punta a un secondo collegamento simbolico, la risoluzione prosegue ricorsivamente fino a individuare il file o cartella reale di destinazione.

Restituisce il percorso puntato dal collegamento simbolico sLinkName, oppure una stringa vuota se il collegamento non è valido o se l'elemento di destinazione non esiste e il parametro bRecursive è impostato su true.

sName = SysUtils.ExtractFileName(sFileName)

Estrae unicamente il nome del file da un percorso assoluto.

Il nome del file corrisponde alla porzione di testo situata dopo l'ultimo separatore di cartella ("/" o "\") o dopo i due punti della lettera di unità.

sExt = SysUtils.ExtractFileExt(sFileName)

Restituisce l'estensione del file (ovvero tutti i caratteri a partire dall'ultimo punto ".", incluso quest'ultimo).

sPath = SysUtils.ExtractFilePath(sFileName)

Estrae il percorso delle cartelle (inclusa l'eventuale lettera di unità) da un percorso completo.

Il percorso corrisponde a tutto il testo precedente l'ultimo separatore di cartella ("/" o "\"), includendo il separatore stesso alla fine.

sDir = SysUtils.ExtractFileDir(sFileName)

Estrae la sola cartella di appartenenza del file sFileName, inclusa l'unità.

A differenza di SysUtils.ExtractFilePath, il valore restituito non include il separatore di cartella finale.

sDrive = SysUtils.ExtractFileDrive(sFileName)

Estrae la sola lettera dell'unità dal percorso del file.

Si fa presente che non tutti i sistemi operativi utilizzano il concetto di lettera di unità.

sName = SysUtils.GetAbsolutePath(sFileName, sBaseDirectory)

Restituisce il percorso assoluto (completo) di un file:

  • sFileName : il nome del file con percorso relativo;
  • sBaseDirectory : la cartella di base da utilizzare come riferimento per risolvere il percorso relativo.

Se non è possibile calcolare il percorso assoluto, la funzione restituisce il valore originale di sFileName.

sName = SysUtils.GetRelativePath(sFileName, sBaseDirectory)

Restituisce il percorso relativo del file rispetto alla cartella specificata:

  • sFileName : il percorso assoluto del file;
  • sBaseDirectory : la cartella di riferimento rispetto alla quale calcolare il percorso relativo.

Se i due percorsi coincidono, viene restituita una stringa vuota "". Se non è possibile calcolare il percorso relativo, viene restituito il valore originale di sFileName.

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

Restituisce true se il nome del file sFileName corrisponde alla maschera di filtro sMask.

Il parametro opzionale iMaskOptions (predefinito a 0) può essere la somma dei seguenti flag binari:

Valore Descrizione
1
Ricerca con distinzione tra maiuscole e minuscole
2
Ignora accenti e legature di caratteri
4
Filtro stile Windows (ad esempio la maschera "*.*" corrisponde anche a file senza estensione)
8
Abilita il supporto alla trascrizione Pinyin (utilizza il file pinyin.tbl)

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

Restituisce true se il nome del file corrisponde ad almeno una delle maschere presenti nell'elenco sMaskList, separate dal carattere sSeparator (predefinito a ";").

I parametri sSeparator e iMaskOptions sono opzionali.

sTempFileName = SysUtils.GetTempName()

Restituisce un nome di file univoco utilizzabile per file temporanei (all'interno della cartella temporanea di sistema). Risulta analogo alla funzione os.tmpname, con la differenza che il file verrà creato all'interno di una cartella temporanea dedicata che Double Commander provvederà a rimuovere automaticamente alla sua chiusura.
Se la funzione non riesce a generare un nome univoco, restituisce una stringa vuota.

SysUtils.PathDelim

Il carattere utilizzato dal sistema operativo corrente per separare le cartelle nei percorsi dei file.

Nei sistemi Unix/Linux corrisponde a "/", mentre in Windows corrisponde a "\".

3.2.1. Dettagli sul valore restituito da SysUtils.FileGetAttr

FileGetAttr restituisce lo stato degli attributi per il file sFileName.

La maschera degli attributi restituita è una combinazione logica OR dei seguenti valori costanti:

Costanti utilizzate nel valore restituito da SysUtils.FileGetAttr
ValoreSignificato
0x00000001
faReadOnly
Il file è impostato come sola lettura.
0x00000002
faHidden
Il file è nascosto.
Nei sistemi Unix/Linux, corrisponde a un nome file che inizia con un punto "."
0x00000004
faSysFile
Il file è un file di sistema.
Nei sistemi Unix/Linux, identifica file speciali quali dispositivi a blocchi o caratteri, o pipe con nome (FIFO).
0x00000008
faVolumeId
Etichetta del volume (Volume ID).
Disponibile solo per file system FAT classici (non VFAT o FAT32) sotto MS-DOS/Windows.
0x00000010
faDirectory
L'elemento è una cartella (directory).
0x00000020
faArchive
Il file presenta l'attributo archivio.
Non disponibile nei sistemi Unix/Linux.
0x00000400
faSymLink
L'elemento è un collegamento simbolico (symlink).
Nota: in caso di errore di lettura degli attributi, la funzione restituisce -1.

Si veda l'esempio pratico riportato nella sezione successiva.

3.2.2. Esempio di utilizzo di SysUtils.FileGetAttr

Lo script seguente illustra un esempio pratico di utilizzo di SysUtils.FileGetAttr.

Se il parametro ricevuto corrisponde a una cartella, lo script aprirà una nuova scheda nel pannello attivo e vi si sposterà all'interno.

local params = {...}
local iAttr
 
if #params == 1 then -- È stato passato almeno un parametro?
  iAttr = SysUtils.FileGetAttr(params[1])
  if iAttr > 0 then -- È stato recuperato un attributo valido?
    if math.floor(iAttr / 0x00000010) % 2 ~= 0 then
      -- Il quarto bit (0x10) è attivo? In tal caso è una cartella.
      DC.ExecuteCommand("cm_NewTab")
      DC.ExecuteCommand("cm_ChangeDir", params[1])
    end
  end
end

Nell'esempio sopra riportato, params[1] rappresenta il primo parametro passato allo script.

Quando si utilizza the comando interno cm_ExecuteScript, i parametri dello script vengono passati subito dopo il nome del file.

Di conseguenza, per questo esempio, è possibile configurare un pulsante sulla barra degli strumenti come segue:

Passaggio dei parametri con il comando cm_ExecuteScript

In questo esempio, viene passata allo script la variabile %"0%p. Essa rappresenta il nome del file dell'elemento attualmente selezionato nel pannello attivo, senza virgolette esterne.

3.2.3. Esempio di utilizzo di FindFirst, FindNext e FindClose

Nel seguente esempio pratico, lo script effettua la scansione di una cartella (ricevuta come primo parametro) e scrive l'elenco e le dimensioni degli elementi individuati in un file di testo (il cui nome è passato come secondo parametro).

Questo script illustra chiaramente l'uso corretto delle funzioni di scansione FindFirst, FindNext e FindClose.

local params = {...}
 
if #params == 2 then -- Sono stati passati entrambi i parametri richiesti?
  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

Nell'esempio sopra riportato, è necessario passare due parametri allo script:

  1. params[1] - la cartella di cui scansionare il contenuto;
  2. params[2] - il nome del file di testo in cui salvare i risultati.

È quindi molto semplice configurare un pulsante sulla barra degli strumenti che invoca il comando interno cm_ExecuteScript passando i relativi parametri.

Passaggio dei parametri con il comando cm_ExecuteScript

In questo esempio, viene passata come primo parametro la variabile %"0%Ds, che corrisponde al percorso della cartella correntemente aperta nel pannello attivo, senza virgolette.

3.3. Libreria degli appunti

Double Commander espone ai nostri script Lua alcune funzioni per interagire con gli appunti di sistema.

La tabella seguente riporta le funzioni disponibili nella libreria:

Libreria degli appunti
Nome funzioneDescrizione

Clipbrd.Clear()

Svuota completamente il contenuto degli appunti di sistema.

sVar = Clipbrd.GetAsText()

Recupera il testo attualmente memorizzato negli appunti e lo assegna alla variabile sVar. Se gli appunti non contengono testo, restituisce una stringa vuota.

Clipbrd.SetAsText(sVar)

Memorizza il testo contenuto in sVar all'interno degli appunti di sistema.

Clipbrd.SetAsHtml(sHtml)

Inserisce negli appunti il testo formattato in codice HTML sHtml (utilizzando il formato di sistema CF_HTML).

Questo contenuto potrà essere incollato direttamente all'interno di applicazioni in grado di interpretare la formattazione HTML, come Microsoft Word, LibreOffice Writer, ecc.

È una buona pratica registrare contemporaneamente i dati sia con Clipbrd.SetAsText che con Clipbrd.SetAsHtml. Al momento dell'incolla, l'applicazione ricevente utilizzerà automaticamente il formato migliore tra quelli disponibili.

Ad esempio, consideriamo il seguente codice:

  • Clipbrd.SetAsText("Benvenuti in Double Commander!")
  • Clipbrd.SetAsHtml("Benvenuti in <b>Double Commander</b>!")

Se proviamo a incollare il testo all'interno di Blocco Note, verrà incollata la stringa di testo semplice memorizzata con Clipbrd.SetAsText. Se invece incolliamo all'interno di Microsoft Word, verrà inserito il testo formattato con la parola Double Commander evidenziata in grassetto, poiché Word riconosce e supporta il formato HTML degli appunti.

3.3.1. Esempio di utilizzo della libreria degli appunti

Il seguente esempio pratico combina l'uso di tre funzioni della libreria: Clear, GetAsText e SetAsText.

Si tratta di uno script più strutturato, utile per comprendere come far cooperare diverse librerie tra di loro.

Lo script assume che il pannello attivo si trovi all'interno di una cartella contenente diversi file di testo.

Presuppone inoltre che negli appunti sia memorizzata una parola da cercare e che la cartella attiva venga passata allo script come parametro.

Lo script effettua la scansione di tutti i file presenti nella cartella e ne legge il contenuto riga per riga per verificare se vi sia presente la parola cercata.

I nomi dei file che contengono almeno una riga con la parola cercata vengono raccolti in un elenco e copiati negli appunti.

Successivamente, richiamando il comando interno cm_LoadSelectionFromClip, Double Commander selezionerà automaticamente tutti questi file nel pannello.

Infine, lo script provvederà a ripristinare la parola di ricerca originale negli appunti di sistema.

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 -- Il parametro richiesto è stato passato?
  sSearchString = Clipbrd.GetAsText() -- Recupera la parola chiave da cercare.
  Clipbrd.Clear() -- Pulisce temporaneamente gli appunti.
  DC.ExecuteCommand("cm_MarkUnmarkAll") -- Rimuove le selezioni correnti nel pannello.
 
  -- Inizia la scansione di tutti gli elementi della cartella.
  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 -- È stato recuperato un attributo valido?
        -- Considera solo i file ed esclude le cartelle!
        if math.floor(iAttr / 0x00000010) % 2 == 0 then
 
          -- Legge il file riga per riga fino alla fine o alla prima corrispondenza.
          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
 
  -- Se ci sono file corrispondenti, selezionali nel pannello!
  if sFileToSelect ~= "" then
    Clipbrd.SetAsText(sFileToSelect)
    DC.ExecuteCommand("cm_LoadSelectionFromClip")
  end
 
  Clipbrd.SetAsText(sSearchString) -- Ripristina la parola chiave originale negli appunti.
end

3.4. Libreria dei dialoghi

Questa libreria consente agli script di interagire direttamente con l'utente, mostrando messaggi, ponendo domande o richiedendo l'inserimento di dati.

La tabella seguente riporta l'elenco delle funzioni disponibili:

Libreria dei dialoghi
Nome funzioneDescrizione

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

Mostra una finestra di messaggio (popup) e attende che l'utente faccia clic su uno dei pulsanti, restituendo il codice del pulsante premuto:

  • sMessage:il testo da visualizzare all'interno del messaggio;
  • sTitle:il titolo della finestra di dialogo;
  • iFlags:combinazione di flag binari (valori costanti) per definire i pulsanti da mostrare, l'icona dello stile e il pulsante predefinito. Si rimanda alle tabelle per i dettagli sui pulsanti, gli stili icona o il pulsante attivo di default;
  • iButton:il codice numerico restituito che identifica il pulsante premuto dall'utente (si veda la tabella dei valori di ritorno).

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

Mostra una finestra di richiesta per l'inserimento di una stringa di testo:

  • sTitle:il titolo della finestra di richiesta;
  • sMessage:il testo o la domanda da mostrare all'utente;
  • bMask:valore booleano; se impostato su true, oscura i caratteri digitati visualizzando degli asterischi (utile per l'inserimento di password);
  • sDefault:un valore di testo predefinito che l'utente può eventualmente modificare;
  • bResult:restituisce un valore booleano che indica se l'utente ha confermato l'inserimento (premendo OK) o ha annullato;
  • sAnswer:restituisce il testo effettivamente digitato dall'utente.

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

Mostra un dialogo contenente un elenco dal quale l'utente può selezionare un elemento:

  • sTitle:il titolo della finestra di dialogo;
  • sMessage:il testo descrittivo da mostrare;
  • aItems:una tabella Lua in cui ogni elemento deve essere una stringa di testo (le voci dell'elenco);
  • sDefault:l'elemento dell'elenco da selezionare come predefinito;
  • sItem:restituisce l'elemento selezionato sotto forma di stringa, oppure nil se l'utente annulla il dialogo;
  • iItem:restituisce l'indice numerico dell'elemento selezionato (partendo da 1, in conformità con gli indici delle tabelle Lua).

3.4.1. Pulsanti visualizzati in Dialogs.MessageBox

I pulsanti mostrati dalla funzione Dialogs.MessageBox sono controllati dalla combinazione dei seguenti flag costanti:

Costanti ButFlags per i pulsanti di Dialogs.MessageBox
Costante e valorePulsanti visualizzati (da sinistra a destra)
0x0000
MB_OK
Pulsante OK
0x0001
MB_OKCANCEL
Pulsante OK Pulsante ANNULLA (Cancel)
0x0002
MB_ABORTRETRYIGNORE
Pulsante INTERROMPI (Abort) Pulsante RIPROVA (Retry) Pulsante IGNORA (Ignore)
0x0003
MB_YESNOCANCEL
Pulsante SÌ (Yes) Pulsante NO Pulsante ANNULLA (Cancel)
0x0004
MB_YESNO
Pulsante SÌ (Yes) Pulsante NO
0x0005
MB_RETRYCANCEL
Pulsante RIPROVA (Retry) Pulsante ANNULLA (Cancel)

3.4.2. Stili di finestra per Dialogs.MessageBox

L'icona e lo stile grafico della finestra di dialogo sono determinati dai seguenti flag costanti:

Costanti ButFlags per icone e stili di Dialogs.MessageBox
Costante e valoreStile della finestra
0x0040
MB_ICONINFORMATION
Icona INFORMAZIONE (Information) Finestra informativa
0x0030
MB_ICONWARNING
Icona AVVERTIMENTO (Warning) Finestra di avvertimento
0x0020
MB_ICONQUESTION
Icona DOMANDA (Question) Finestra di conferma/domanda
0x0010
MB_ICONERROR
Icona ERRORE (Error) Finestra di errore

3.4.3. Pulsante attivo predefinito di Dialogs.MessageBox

Il pulsante attivo di default all'apertura del dialogo è definito dai seguenti flag costanti:

Costanti ButFlags per il pulsante predefinito di Dialogs.MessageBox
Costante e valorePulsante predefinito
0x0000
MB_DEFBUTTON1
Il focus è impostato sul primo pulsante a sinistra.
0x0100
MB_DEFBUTTON2
Il focus è impostato sul secondo pulsante da sinistra.
0x0200
MB_DEFBUTTON3
Il focus è impostato sul terzo pulsante da sinistra.

3.4.4. Valore restituito da Dialogs.MessageBox

Il valore numerico restituito da Dialogs.MessageBox identifica il pulsante premuto dall'utente, come illustrato di seguito:

Valori di ritorno ButPressed per i pulsanti di Dialogs.MessageBox
Costante e valorePulsante premuto
0x0000
mrNone
Nessun pulsante premuto
0x0001
mrOK
Risultato OK
0x0002
mrCancel
Risultato ANNULLA (Cancel)
0x0003
mrAbort
Risultato INTERROMPI (Abort)
0x0004
mrRetry
Risultato RIPROVA (Retry)
0x0005
mrIgnore
Risultato IGNORA (Ignore)
0x0006
mrYes
Risultato SÌ (Yes)
0x0007
mrNo
Risultato NO

Nota: se l'utente chiude la finestra facendo clic sulla "x" in alto a destra o premendo il tasto Esc, viene restituito il codice corrispondente al pulsante "Annulla" (mrCancel).

3.4.5. Esempio di utilizzo di Dialogs.MessageBox

Di seguito viene riportato un breve script di esempio che utilizza la funzione Dialogs.MessageBox e la finestra grafica generata:

-- Pulsanti visualizzati
MB_OK = 0x0000
MB_OKCANCEL = 0x0001
MB_ABORTRETRYIGNORE = 0x0002
MB_YESNOCANCEL = 0x0003
MB_YESNO = 0x0004
MB_RETRYCANCEL = 0x0005
 
-- Stile della finestra
MB_ICONINFORMATION = 0x0040
MB_ICONWARNING = 0x0030
MB_ICONQUESTION = 0x0020
MB_ICONERROR = 0x0010
 
-- Pulsante predefinito
MB_DEFBUTTON1 = 0x0000
MB_DEFBUTTON2 = 0x0100
MB_DEFBUTTON3 = 0x0200
 
-- Pulsante premuto restituito
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("Vuoi uscire da Double Commander?", "Domanda", iFlags)
 
if iButton == mrYes then
  DC.ExecuteCommand("cm_Exit")
end

Esempio di utilizzo di Dialogs.MessageBox

3.4.6. Esempio di utilizzo di Dialogs.InputQuery

Il seguente esempio mostra l'uso della funzione Dialogs.InputQuery per richiedere dati all'utente:

bResult, sAnswer = Dialogs.InputQuery("Autenticazione", "Inserisci il tuo nome:", false, "John")
 
if bResult == true then
  Dialogs.MessageBox("Ciao " .. sAnswer .. "!", "Benvenuto!", 0x0040)
end

Esempio di utilizzo di Dialogs.InputQuery

3.5. Libreria UTF-8

Questa libreria fornisce il support essenziale alla gestione di testi con codifica UTF-8.

Le funzioni sono disponibili all'interno della tabella LazUtf8.

Libreria UTF-8
Nome funzioneDescrizione

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

Cerca la presenza di una sottostringa all'interno di una stringa a partire da una determinata posizione. La ricerca distingue tra lettere maiuscole e minuscole (case-sensitive).

Restituisce la posizione iniziale della prima occorrenza della sottostringa SearchText nella stringa SourceText, avviando la ricerca a partire dall'indice Offset (predefinito a 1).

Se la sottostringa non viene individuata oltre la posizione indicata, restituisce zero.

LazUtf8.Next(String)

Un iteratore che ad ogni chiamata restituisce il carattere successivo presente nella stringa String e la sua posizione di inizio espressa in byte.

Esempio:

-- Stampa le coppie "posizione : carattere"
for iPos, sChar in LazUtf8.Next(String) do
  DC.LogWrite(iPos .. " : " .. sChar)
end

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

Estrae e copia una porzione di testo da una stringa.

Restituisce una nuova stringa contenente un numero di caratteri pari a iCount estratti a partire dalla posizione iIndex della stringa String.

Se il numero di caratteri richiesti iCount supera la lunghezza residua della stringa, il risultato viene troncato alla fine della stringa stessa. Se iIndex è superiore alla lunghezza totale della stringa, viene restituita una stringa vuota.

iResult = LazUtf8.Length(String)

Restituisce il numero totale di caratteri UTF-8 contenuti nella stringa.

sResult = LazUtf8.UpperCase(String)

Accetta una stringa e ne restituisce una copia con tutti i caratteri minuscoli convertiti in lettere maiuscole.

sResult = LazUtf8.LowerCase(String)

Accetta una stringa e ne restituisce una copia con tutti i caratteri maiuscoli convertiti in lettere minuscole.

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

Converte la codifica della stringa String dal formato d'origine FromEnc al formato di destinazione ToEnc.

Elenco dei valori di codifica supportati:

  • Codifica di sistema predefinita (in base alle impostazioni locali): "default";
  • Codifica ANSI predefinita di Windows (in base alle impostazioni locali): "ansi";
  • Codifica OEM (DOS) predefinita (in base alle impostazioni locali): "oem";
  • Unicode: "utf8", "utf8bom", "ucs2le", "ucs2be";
  • ANSI di 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";
  • Altre codifiche: "macintosh", "koi8r", "koi8u", "koi8ru".
Significato delle codifiche speciali (esempi):

In Windows (in lingua inglese o russa):
  • "default" - cp1252 o cp1251
  • "ansi" - cp1252 o cp1251
  • "oem" - cp850 o cp866
In Linux (in lingua inglese o russa):
  • "default" - utf8
  • "ansi" - cp1252 o cp1251
  • "oem" - cp850 o cp866

sEnc = LazUtf8.DetectEncoding(String)

Analizza e restituisce il formato di codifica del testo passato come parametro.
L'elenco delle codifiche rilevabili corrisponde a quello supportato dalla funzione LazUtf8.ConvertEncoding.

3.6. Libreria dei caratteri

Questa libreria contiene funzioni utili a determinare se un carattere appartiene a una specifica classe Unicode e a leggerne la relativa categoria.

Elenco delle funzioni disponibili in questa libreria:

Libreria dei caratteri
Nome funzioneDescrizione

iResult = Char.GetUnicodeCategory(Character)

Restituisce la categoria Unicode del carattere Character come uno dei seguenti codici numerici:

ValoreDescrizione
  Lettere:
0Lettera maiuscola (Lu)
1Lettera minuscola (Ll)
2Lettera iniziale maiuscola / Titolo (Lt)
3Lettera modificatrice (Lm)
4Altra lettera (Lo)
  Segni combinatori (Mark):
5Segno non spaziatore (Mn)
6Segno combinatorio spaziatore (Mc)
7Segno racchiudente (Me)
  Numeri:
8Cifra decimale (Nd)
9Numero rappresentato da lettere (Nl)
10Altro tipo di numero (No)
  Punteggiatura:
11Punteggiatura di collegamento (Pc)
12Punteggiatura di trattino (Pd)
13Punteggiatura di apertura (Ps)
14Punteggiatura di chiusura (Pe)
15Virgoletta iniziale (Pi)
16Virgoletta finale (Pf)
17Altro tipo di punteggiatura (Po)
  Simboli:
18Simbolo matematico (Sm)
19Simbolo valutario (Sc)
20Simbolo modificatore (Sk)
21Altro tipo di simbolo (So)
  Separatori:
22Separatore di spazio (Zs)
23Separatore di riga (Zl)
24Separatore di paragrafo (Zp)
  Altri caratteri:
25Carattere di controllo (Cc)
26Carattere di formattazione (Cf)
27Surrogato (Cs)
28Uso privato (Co)
29Carattere non assegnato (Cn)

bResult = Char.IsDigit(Character)

Restituisce true se il carattere Character appartiene alla categoria Nd (cifra decimale).

bResult = Char.IsLetter(Character)

Restituisce true se il carattere Character appartiene a una delle categorie letterali (Lu, Ll, Lt, Lm o Lo).

bResult = Char.IsLetterOrDigit(Character)

Restituisce true se il carattere Character appartiene a una categoria alfanumerica (lettera o cifra: Lu, Ll, Lt, Lm, Lo, Nd o Nl).

bResult = Char.IsLower(Character)

Restituisce true se il carattere Character è una lettera minuscola (categoria Ll).

bResult = Char.IsUpper(Character)

Restituisce true se il carattere Character è una lettera maiuscola (categoria Lu).

In aggiunta, tutte queste funzioni supportano il passaggio di due parametri: anziché un singolo carattere, è possibile passare una stringa di testo e l'indice di posizione del carattere al suo interno.

3.7. Libreria del sistema operativo

Questa libreria racchiude funzioni strettamente legate all'interazione con il sistema operativo ospite.

Di seguito viene riportato l'elenco delle funzioni disponibili:

Libreria del sistema operativo
Nome funzioneDescrizione

iResultCode = os.execute(sCommand)

Esegue il comando sCommand passandolo alla shell di sistema (riga di comando) e restituisce il relativo codice di errore/stato dell'operazione.

sCommand può contenere:

  • comandi della shell di sistema, ad esempio: os.execute("dir > all.txt")
  • percorsi di file eseguibili, ad esempio: os.execute("C:\\Windows\\System32\\calc.exe")
  • eseguibili corredati di parametri aggiuntivi, ad esempio:
    os.execute("C:\\Utils\\fsum.exe -md5 test.bin > md5.txt")

sTempFileName = os.tmpname()

Restituisce un percorso valido che può essere utilizzato per creare un file temporaneo all'interno della cartella temporanea di sistema.
Se non è possibile generare un nome univoco, la funzione restituisce una stringa vuota.

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

Elimina dal disco il file o la cartella specificata in sFileName.

Restituisce true in caso di esecuzione corretta.

In caso di fallimento, restituisce tre distinti valori:

  1. nil per indicare l'errore;
  2. la stringa sError contenente la descrizione dell'errore;
  3. il valore numerico iError corrispondente al codice di errore del sistema operativo.

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

Rinomina il file o la cartella sOldName con il nuovo nome sNewName.

Attenzione: se nella destinazione è già presente un file con lo stesso nome sNewName, esso verrà sovrascritto senza preavviso!

Restituisce true in caso di esecuzione corretta.

In caso di fallimento, restituisce tre distinti valori:

  1. nil per indicare l'errore;
  2. la stringa sError contenente la descrizione dell'errore;
  3. il valore numerico iError corrispondente al codice di errore del sistema operativo.

Value = os.getenv(VariableName)

Restituisce il valore Value associato alla variabile d'ambiente VariableName specificata.
Se la variabile non esiste nel sistema, restituisce nil.

os.setenv(VariableName, Value)

Definisce o modifica la variabile d'ambiente VariableName impostandovi il valore Value. Restituisce -1 in caso di errore.

os.unsetenv(VariableName)

Rimuove la variabile d'ambiente VariableName dal sistema. Restituisce -1 in caso di errore.

4. Indice

Libreria DC

DC.CurrentPanel
DC.ExecuteCommand
DC.LogWrite


Libreria di 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


Libreria degli appunti

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


Libreria dei dialoghi

Dialogs.InputListBox
Dialogs.InputQuery
Dialogs.MessageBox


Libreria UTF-8

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


Libreria dei caratteri

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


Libreria del sistema operativo

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


Valid HTML 4.0 Transitional CSS Valid!