LIL File Actions Documentation
LIL File Actions, or just lilfa, is a tool to
provide a simple GUI for running a command inside a folder that
contains a series of files. When lilfa runs it checks the current
folder and its parents for a LIL
script named fileacts.lil and runs it to populate
a list of files using the instructions in the script (alternatively
lilfa can run the script passed to it as the first parameter,
but the main use case is having it find the script automatically).
Common uses for this is to present list of files in the folder
to be viewed with a specific viewer or editor (e.g. all PDF files
in a directory) with folder-specific settings, run bytecode under
a VM, build source files for a project or even run custom maps
for a game. In fact, the examples at the bottom
of the page show exactly that.
Scripting
The script accepts all LIL commands (see LIL
documentation) as well as LILGUI commands (see LILGUI
documentation) which allows it to optionally show some custom
GUI controls for running the command. The example Quake script
at the bottom uses LILGUI commands to provide an option to run
the game in fullscreen and to optionally activate one of the two
official expansion packs for the game.
In addition to the above commands, the following lilfa-specific
commands are also provided:
Adding files
- add-files directory [mask] [deep]
Adds the files under the given directory to the file list,
optionally limiting the file selection with the given mask.
If deep is a non-zero, non-empty value then it also scans
the subdirectories of the given directory.
Example (will all all bmp files under the images
directory):
add-files images *.bmp
- add-dirs directory [deep]
Like add-files, but adds directories instead.
- add-file filename
Adds the given filename to the list. Note that lilfa doesn't
care if the file exists or not, so you can use anything as a
filename - you could even add "special" files and ignore
them later (though it is better to use LILGUI for special actions
instead).
Example:
add-file foo.bar
- remove-files mask
Removes the files from the file list that match the given mask.
This can be useful when you want to add all files in a folder,
but only ignore some.
Example (removes all files with the bak extension):
remove-files *.bak
Scanning files
- file-exists filename
Returns true if a file with the given filename exists.
Example:
if [file-exists "$fn"] { do something }
- directory-exists filename
Returns true if a directory with the given filename exists
- file-or-directory-exists filename
Returns true if a file or a directory with the given filename
exists
- for-each-file code
Run the given piece of code for each file in the file
list. The variables filename and display are
set to the filename as stored in the list and the text that is
displayed in the file listbox (initially both are the same).
You can change the value of those variables to change the actual
stored and displayed values.
Example (will cause the list to only show the file name
without any path):
for-each-file { set display [get-file-name $filename] }
Filename manipulation
- absolute-path filename
Returns the absolute path to the given filename.
Example:
msgbox [absolute-path somefile.txt]
- get-file-name filename
Returns the filename part of the given path (e.g. for c:\foo\bar\baz.txt
it will return baz.txt).
- get-file-name-without-extension filename
Returns the filename part of the given without its extension
(e.g. for c:\foo\bar\baz.txt it will return baz).
- get-path filename
Returns the directory path part of the given path (e.g. for c:\foo\bar\baz.txt
it will return c:\foo\bar).
- get-extension filename
Returns the extension of a filename or path (e.g. for c:\foo\bar\baz.txt
it will return txt).
- change-extension filename [newext]
Change the extension of the given filename or path to
newext or remove the extension if newext isn't
given or is empty.
Example (will return "foo.h"):
change-extension foo.c h
- matches-mask filename mask
Returns true if te given filename matches the given mask
Example (returns true if the file has the bak
extension):
matches-mask $file *.bak
Running commands
- set-command command
Set the command to be executed when the user clicks the Run
button (or presses Enter, or double clicks a file).
Example (inside the select function):
set-command "preview $filename"
- run-command command
Run the given command.
Example (will launch the Windows command shell and run
the "dir" command):
run-command "cmd /c dir"
- run-shown-command
Will run the command shown to the user (set via the set-command
above).
- enable-sorting [enable]
If enable is true (non-empty, non-zero) or if enable is not given,
it will enable sorting in the file list. Note that sorting is
enabled by default but applied the first time the GUI is shown.
If you call this to disable sorting you should do it either before
modifying the file list or after the final file list is filled.
Do not change this while modifying it.
Example (disables sorting):
enable-sorting 0
Multiple selection
- enable-multiple-selection [enable]
If enable is true (non-empty, non-zero) or if enable
is not given, it will enable allowing multiple selection in the
file list (via control click, shift click and drag select). If
this is enabled you can obtain the selected files via selected-files
and for-each-selected.
- for-each-selected code
Run the given piece of code for each selected file in
the file list. The filename variable is set to the filename
(not the displayed text, but the stored filename in the
file list) of each selection.
- selected-files [quotes]
Return the selected files as a space-separated list, optionally
in quotes. If the quotes parameter is not given, the files
are returned with double quotes so they can be passed directly
to a command. If the quotes parameter is a single character
then that character is used instead of the double quote one.
If the quotes parameter is more than a single character,
then the first character is placed at the left side of the filename
and the second character is placed at the right side of the filename.
Finally, if the quotes parameter is an empty string then
the filenames are returned without any quotes.
- Examples (assuming the three files first,
second and with spaces):
- selected-files
will return "first" "second" "with
spaces"
- selected-files +
will return +first+ +second+ +with spaces+
- selected-files {{}}
will return {first} {second} {with spaces} (this can be
used with LIL's list commands such as foreach)
- selected-files {}
will return first second with spaces
Misc
- set-caption caption
Set the caption of the lilfa window to the given one.
Example: set-caption "Choose a PDF to print"
- show-panel
Make the LILGUI panel at the right side of the lilfa window visible.
This must be called to show the LILGUI controls at the side.
Callbacks (or special user-defined functions)
Two functions can be defined that lilfa will call when the
selection changes and when the user clicks the Run button (or
presses Enter or double clicks a file name). These functions are:
- func select {filename} { ...
}
The select function is called with the filename that was selected
as its parameter when the user selects (or deselects, for multiple
selection) a file. This function should be defined and call the
set-command command to be used for launching or viewing the selected
file. By default (if this function is not defined) the command
is set as the filename itself. Note that if multiple selection
is enabled this will only contain a single file and you should
use get-selected-files or for-each-selected
instead to obtain all selected files.
Example (this will set the command to "notepad whatever
file was selected"):
func {filename} { set-command "notepad $filename" }
- func run {filename} { ... }
The run function is called with the filename that was selected
as its parameter when the user clicks the Run button (or presses
Enter or double clicks the file list). By default this function
is set to simply call run-shown-command, which should
be sufficient for most uses.
Examples
Duke Nukem 3D custom map launcher
The following code is a very simple fileacts.lil script
that can be placed inside a Duke Nukem 3D game installation with
the EDuke32 engine to launch
custom map files:
set-caption "Come Get Some Maps"
add-files . *.map
func select {filename} {
set-command "eduke32 -nologo -nosetup -map $filename"
}
Fossil Web UI repository launcher
The following code is a slightly more advanced fileacts.lil
script that can be placed inside a directory with Fossil repositories
(assuming they all use the .fossil file extension) to launch the
Web UI for the selected one. This script also shows how to use
the output of run-command to obtain additional information as
well as store external files (in this case, a temporary batch
file used to collect all names in a single call):
# Fancy caption
set-caption "Open Fossil Web UI"
# Scan all fossil files
add-files . *.fossil
# Create a temporary batch file to collect project names
set bat {@echo off}
for-each-file {
set bat $bat{
fossil info "}$filename{" | findstr /C:project-name
}
}
store fileacts.bat $bat
# Run and delete the batch file (its output is a project name per line)
set titles [run-command "cmd /c fileacts.bat && del fileacts.bat"]
set titles [split $titles "\n"]
# Go over all files again and set the display for each one
set i 0
for-each-file {
set display "[substr [index $titles $i] 14] (${filename})"
inc i
}
# Set the command when a file is select to launch Fossil's web UI
func select {filename} { set-command "fossil ui $filename" }
Quake 1 custom map launcher
The following code is a more advanced fileacts.lil
script that can be placed inside a Quake 1 game installation with
the Quakespasm
engine under Windows to launch custom maps (note, however, that
this is just an example - MiniQL
is a better launcher for this purpose) with custom GUI options
and nice file display:
# Fancy caption
set-caption "Run Custom Quake Map"
# Scan for single map files
add-files id1\maps *.map
add-files hipnotic\maps *.map
add-files rogue\maps *.map
# Scan for map packs with a start map
scan-dirs . {
if [file-exists "${filename}\\maps\\start.bsp"] {
add-file "start +game [get-filename $filename]"
}
}
# Prettify file display
for-each-file {
if [streq [substr $filename 0 12] {start +game }] {
set display "Game: [substr $filename 12]"
} {
set filename [get-filename $filename]
set filename [get-filename-without-extension $filename]
set display "Map: $filename"
}
}
# Variables used to build the command to run
set mapfile {}
set fullscreen 1
set game base
# This build the command based on the current selected file and options
func build-command {} {
local p
set p {}
if $fullscreen {
set p "$p -current"
} {
set p "$p -window -width 640 -height 480"
}
if not [streq $game base] { set p "$p -$game" }
set-command "quakespasm $p +map $mapfile"
}
# Show and create the control panel. The fullscreen and game variables
# are bound to the checkbox and radio buttons
show-panel
checkbox 'Fullscreen' fullscreen
radio 'Base' game base
radio 'Hipnotic' game hipnotic
radio 'Rogue' game rogue
# Called when the file selection changes
func select {fn} {
set mapfile $fn
build-command
}
# Watch the fullscreen and game variables (which are bound to the GUI
# controls) and call build-command if they get modified
watch fullscreen game { build-command }