This page couldn't be found. Please note, that the site is undergoing testing at present, so pages may be missing/moved.
Binary packages are available on the GitHub releases page.
Alternatively, you can install lite-xl from your distribution's package manager. These packages are maintained by the community and may be outdated.
choco install lite-xl # chocolatey scoop bucket add extras && scoop install lite-xl # scoop sudo port install lite-xl # macports yay -S lite-xl # or your favorite AUR helper nix-env -i lite-xl # nixos sudo dnf copr enable sentry/lite && sudo dnf install lite-xl # fedora (copr)
Source code is available on GitHub, by downloading zip or tar archives, or directly via git:
git clone https://github.com/lite-xl/lite-xl.git
Name | Contributions |
---|---|
rxi | Original development of lite editor. |
Francesco | Creator of lite-xl fork from rxi/lite. |
Takase | NagView and X Window database resource query for Xft.dpi setting. |
Nils Kvist | Popup window replacement with CommandView dialog. |
liquidev | Tab style and animations improvements. |
Adam | Multi-language syntax highlighting and many other improvements. |
Cukmekerb | Syntax highlighting improvements. |
Janis-Leuenberger | Add keymap bindings help file and macOS testing. |
Mat Mariani | Help for macOS port. Some resources taken from mathewmariani/lite-macos. |
daubaris | Initial implementation of Xft.dpi query using xrdb command. |
Robert Štojs | Continuos integration configuration. |
Currently, Lite XL offers a lot of features out of the box.
We currently support Windows, Linux and MacOS (with Retina display support).
We are currently around 3MB in size and takes about 10MB in RAM (can be lower). No Electron / WebView involved. The whole thing is just Lua running on a rendering engine.
While the editor is minimal by default, it is very extensible using Lua. In fact, a lot of features are provided by plugins. For example, VSC-like intellisense
The editor looks good in screen of any sizes. Some other options are also configurable, such as hinting and antialiasing.
You can now place multiple cursors by ctrl
+ lclick
on lines or ctrl
+ shift
+ up
or ctrl
+ shift
+ down
.
Here are some features that aren't implemented with the rationales behind it. Some of these may be implemented via plugins. We encourage you to give it a shot.
tl;dr - franko stated that he isn't considering using OpenGL due to the skills and work involved.
Hardware acceleration was brought up in this discussion. Takase had made 2 attempts at this - at first using NanoVG and then forcing SDL to use GPU rendering. In both attempts, the performance gains at best is negligible, while at worst its completely unusable. Right now, we decided to focus on optimizing the software renderer and various part of Lua code.
This is painful because various systems has their own mechanism of managing fonts. For now, users can use the fontconfig plugin. Fontconfig is widely available on Linux and installable on MacOS, while Windows builds are available. In the future, we might consider adding API to read font metadata, allowing us to write a fontconfig alternative in Lua. (no promises here)
Our path handling code can only handle POSIX and Windows paths. We also aren't sure how Lite XL will behave in these scenarios.
This is by far the hardest to achieve. Lite XL has no intention to link to any widget toolkits (Qt and GTK) which are required for these features. An alternative approach is to create our own IPC mechanism, but that's reinventing the wheel.
A terminal is complex to implement. There are projects that can be ported to Lua, such as xterm.js. If someone is interested, they can do so.
Check out the LSP plugin.
Work is being done on lite-xl-terminal and lite-xl-tmt. Both plugins has their own supported features and bugs so you should try both out and see which one works for you.
In your user config (the cog icon in the file tree):
config.tab_type = "soft" -- soft for spaces, hard for real tabs (\t) config.indent_size = 4 -- 4 spaces
local keymap = require "core.keymap" keymap.add { ["ctrl+escape"] = "core:quit" }
-- the second parameter lets you override commands for certain keys -- in this case it maps it to nothing keymap.add({ ["ctrl+escape"] = {} }, true)
You can search for commands in the command palette.
For each command, replace the spaces in the right side with dashes.
For example: Core: Find Command
→ core:find-command
Lua 5.2.4. There's some activity around using LuaJIT instead (which is 5.1) but it can provide some Lua 5.2 compatibility.
You need to vibe.
Just in case you don't want to comb through our plugin repository, these are a list of plugins that just makes Lite XL a lot more pleasant.
Plugin | Use case |
---|---|
autoinsert | Automatically insert closing brackets and quotes |
bracketmatch | Highlight matching brackets |
ephemeral_tabs | Ephemeral tabs (previewing files without creating multiple tabs) |
gitdiff_highlight | Git diff gutter |
linecopypaste | Copy/Paste lines when nothing is selected |
lint+ | Linter support |
minimap | Minimap |
selectionhighlight | Highlight code that matches the selection |
lite-xl-discord | Discord rich presence |
You can get more info in the Features page.
Keymaps on different operating systems have the same functionality, just bound slightly differently in order to conform to normal expectations for that operating system.
Currently, there are only two operating system layouts. MacOS, and everything else.
Key Combination | Actions |
---|---|
alt +1 |
root:switch-to-tab-1 |
alt +2 |
root:switch-to-tab-2 |
alt +3 |
root:switch-to-tab-3 |
alt +4 |
root:switch-to-tab-4 |
alt +5 |
root:switch-to-tab-5 |
alt +6 |
root:switch-to-tab-6 |
alt +7 |
root:switch-to-tab-7 |
alt +8 |
root:switch-to-tab-8 |
alt +9 |
root:switch-to-tab-9 |
alt +i |
root:switch-to-up |
alt +j |
root:switch-to-left |
alt +k |
root:switch-to-down |
alt +l |
root:switch-to-right |
alt +return |
core:toggle-fullscreen |
alt +shift +i |
root:split-up |
alt +shift +j |
root:split-left |
alt +shift +k |
root:split-down |
alt +shift +l |
root:split-right |
ctrl +/ |
doc:toggle-line-comments |
ctrl +1lclick |
doc:split-cursor |
ctrl +[ |
doc:move-to-previous-block-start |
ctrl +] |
doc:move-to-next-block-end |
ctrl +a |
doc:select-all |
ctrl +backspace |
doc:delete-to-previous-word-start |
ctrl +c |
doc:copy |
ctrl +d |
doc:select-word |
ctrl +d |
find-replace:select-add-next |
ctrl +delete |
doc:delete-to-next-word-end |
ctrl +down |
doc:move-lines-down |
ctrl +end |
doc:move-to-end-of-doc |
ctrl +f3 |
find-replace:select-next |
ctrl +f |
find-replace:find |
ctrl +g |
doc:go-to-line |
ctrl +home |
doc:move-to-start-of-doc |
ctrl +i |
find-replace:toggle-sensitivity |
ctrl +insert |
doc:copy |
ctrl +j |
doc:join-lines |
ctrl +l |
doc:select-lines |
ctrl +left |
doc:move-to-previous-word-start |
ctrl +n |
core:new-doc |
ctrl +o |
core:open-file |
ctrl +p |
core:find-file |
ctrl +pagedown |
root:move-tab-right |
ctrl +pageup |
root:move-tab-left |
ctrl +r |
find-replace:replace |
ctrl +return |
doc:newline-below |
ctrl +right |
doc:move-to-next-word-end |
ctrl +s |
doc:save |
ctrl +shift +[ |
doc:select-to-previous-block-start |
ctrl +shift +] |
doc:select-to-next-block-end |
ctrl +shift +backspace |
doc:delete-to-previous-word-start |
ctrl +shift +c |
core:change-project-folder |
ctrl +shift +d |
doc:duplicate-lines |
ctrl +shift +delete |
doc:delete-to-next-word-end |
ctrl +shift +down |
doc:create-cursor-next-line |
ctrl +shift +end |
doc:select-to-end-of-doc |
ctrl +shift +f3 |
find-replace:select-previous |
ctrl +shift +home |
doc:select-to-start-of-doc |
ctrl +shift +i |
find-replace:toggle-regex |
ctrl +shift +k |
doc:delete-lines |
ctrl +shift +l |
doc:select-word |
ctrl +shift +l |
find-replace:select-add-all |
ctrl +shift +left |
doc:select-to-previous-word-start |
ctrl +shift +o |
core:open-project-folder |
ctrl +shift +p |
core:find-command |
ctrl +shift +return |
doc:newline-above |
ctrl +shift +right |
doc:select-to-next-word-end |
ctrl +shift +s |
doc:save-as |
ctrl +shift +tab |
root:switch-to-previous-tab |
ctrl +shift +up |
doc:create-cursor-previous-line |
ctrl +tab |
root:switch-to-next-tab |
ctrl +up |
doc:move-lines-up |
ctrl +v |
doc:paste |
ctrl +w |
root:close |
ctrl +x |
doc:cut |
ctrl +y |
doc:redo |
ctrl +z |
doc:undo |
f11 |
core:toggle-fullscreen |
f3 |
find-replace:repeat-find |
shift +f3 |
find-replace:previous-find |
Lite XL is a lightweight text editor written mostly in Lua — it aims to provide something practical, pretty, small and fast, implemented as simply as possible; easy to modify and extend, or to use without doing either.
Lite XL is based on the Lite editor and provide some enhancements while remaining generally compatible with it.
Lite XL works using a project directory — this is the directory where your project's code and other data resides.
To open a specific project directory the directory name can be passed
as a command-line argument (.
can be passed to use the current directory)
or the directory can be dragged onto either the executable or a running instance.
Once started the project directory can be changed using the command
core:change-project-folder
. The command will close all the documents
currently opened and switch to the new project directory.
If you want to open a project directory in a new window the command
core:open-project-folder
will open a new editor window with the selected
project directory.
The main way of opening files in Lite XL is through the core:find-file
command
— this provides a fuzzy finder over all of the project's files and can be
opened using the ctrl
+p
shortcut by default.
Commands can be run using keyboard shortcuts, or by using the core:find-command
command bound to ctrl
+shift
+p
by default. For example, pressing
the above combination and typing newdoc
then pressing return
would open a new document. The current keyboard shortcut for a command
can be seen to the right of the command name on the command finder, thus to find
the shortcut for a command ctrl
+shift
+p
can be pressed
and the command name typed.
Lite XL uses standard systems user directories; the user data can be found in
$HOME/.config/lite-xl
on Linux and macOS.
On Windows, the variable $USERPROFILE
will be used instead of
$HOME
.
Lite XL can be configured through use of the user module. The user module can be used for changing options in the config module, adding additional key bindings, loading custom color themes, modifying the style or changing any other part of the editor to your personal preference.
The user module is loaded when the application starts, after the plugins have been loaded.
The user module can be modified by running the core:open-user-module
command
or otherwise directly opening the $HOME/.config/lite-xl/init.lua
file.
On Windows, the variable $USERPROFILE
will be used instead of
$HOME
.
tl;dr:
C:\Users\(username)\.config\lite-xl\init.lua
/Users/(usernmame)/.config/lite-xl/init.lua
/home/(username)/.config/lite-xl/init.lua
These aren't the exact location, but it gives you an idea where to find.
Please note that Lite XL differs from the standard Lite editor for the location of the user's module.
The project module is an optional module which is loaded from the current project's directory when Lite XL is started. Project modules can be useful for things like adding custom commands for project-specific build systems, or loading project-specific plugins.
The project module is loaded when the application starts, after both the plugins and user module have been loaded.
The project module can be edited by running the core:open-project-module
command — if the module does not exist for the current project when the
command is run it will be created.
In addition to the project directories it is possible to add other directories
using the command core:add-directory
.
Once added a directory it will be shown in the tree-view on the left side and
the additional files will be reachable using the ctrl
+p
command (find file).
The additonal files will be also visible when searching across the project.
The additional directories can be removed using the command core:remove-directory
.
When you will open again Lite XL on the same project folder the application will remember your workspace including the additonal project directories.
Since version 1.15 Lite XL does not need a workspace plugin as it is now bundled with the editor.
Using the command files:create-directory
or control-click in a directory in the
tree-view to create a new empty subdirectory.
Commands are used both through the command finder (ctrl
+shift
+p
) and
by Lite XL's keyboard shortcut system. Commands consist of 3 components:
namespace:action-name
, for
example: doc:select-all
Commands can be added using the command.add
function provided by the
core.command
module:
local core = require "core" local command = require "core.command" command.add("core.docview", { ["doc:save"] = function() core.active_view.doc:save() core.log("Saved '%s', core.active_view.doc.filename) end })
Commands can be performed programatically (eg. from another command or by your
user module) by calling the command.perform
function after requiring the
command
module:
local command = require "core.command" command.perform "core:quit"
All keyboard shortcuts are handled by the core.keymap
module.
A key binding maps a "stroke" (eg. ctrl
+q
) to one or more commands
(eg. core:quit
). When the shortcut is pressed Lite XL will iterate each command
assigned to that key and run the predicate function for that command — if the
predicate passes it stops iterating and runs the command.
An example of where this used is the default binding of the tab
key:
["tab"] = { "command:complete", "doc:indent" },
When tab is pressed the command:complete
command is attempted which will only
succeed if the command-input at the bottom of the window is active. Otherwise
the doc:indent
command is attempted which will only succeed if we have a
document as our active view.
A new mapping can be added by your user module as follows:
local keymap = require "core.keymap" keymap.add { ["ctrl+q"] = "core:quit" }
A list of default mappings can be viewed here.
There are a few global variables set by the editor. These variables are available everywhere and shouldn't be overwritten.
ARGS
: command-line arguments. argv[1]
is the program name, argv[2]
is the 1st parameter, ...PLATFORM
: Output from SDL_GetPlatform()
. Can be Windows
, Mac OS X
, Linux
, iOS
and Android
.SCALE
: Font scale. Usually 1, but can be higher on HiDPI systems.EXEFILE
: An absolute path to the executable.EXEDIR
: The executable directory. DO NOT WRITE TO THIS DIRECTORY.VERSION
: lite-xl version.MOD_VERSION
: mod-version used in plugins. This is usually incremented when there are API changes.PATHSEP
: Path seperator. \
(Windows) or /
(Other OSes)DATADIR
: The data directory, where the Lua part of lite-xl resides. DO NOT WRITE TO THIS DIRECTORY.USERDIR
: User configuration directory.
USERDIR
should be used instead ofDATADIR
when configuring the editor becauseDATADIR
might not be writable. (for example, if the editor is installed in/usr
,DATADIR
will be/usr/share/lite-xl
!)USERDIR
on the other hand should always be writable for the user, and allows multiple users to customize their own editor.
Plugins in Lite XL are normal lua modules and are treated as such — no complicated plugin manager is provided, and, once a plugin is loaded, it is never expected be to have to unload itself.
To install a plugin simply drop it in the plugins
directory in the user
module directory.
When Lite XL starts it will first load the plugins included in the data directory
and will then loads the plugins located in the user module directory.
To uninstall a plugin the plugin file can be deleted — any plugin (including those included with the default installation) can be deleted to remove its functionality.
If you want to load a plugin only under a certain circumstance (for example,
only on a given project) the plugin can be placed somewhere other than the
plugins
directory so that it is not automatically loaded. The plugin can
then be loaded manually as needed by using the require
function.
Plugins can be downloaded from the plugins repository.
If you modifies the user configuration file or some of the Lua implementation files
you may restart the editor using the command core:restart
.
All the application will be restarting by keeping the window that is already in use.
Colors themes in Lite XL are lua modules which overwrite the color fields of
Lite XL's core.style
module.
Pre-defined color methods are located in the colors
folder in the data directory.
Additional color themes can be installed in the user's directory in a folder named
colors
.
A color theme can be set by requiring it in your user module:
core.reload_module "colors.winter"
In the Lite editor the function require
is used instead of core.reload_module
.
In Lite XL core.reload_module
should be used to ensure that the color module
is actually reloaded when saving the user's configuration file.
Color themes can be downloaded from the color themes repository. They are included with Lite XL release packages.
Once you have downloaded the source code, you can build Lite XL yourself using Meson.
In addition, the build-packages.sh
script can be used to compile Lite XL and
create an OS-specific package for Linux, Windows or macOS.
The following libraries are required:
The following libraries are optional:
If they are not found, they will be downloaded and compiled by Meson. Otherwise, if they are present, they will be used to compile Lite XL.
If you compile Lite XL yourself,
it is recommended to use the script build-packages.sh
:
bash build-packages.sh -h
The script will run Meson and create a tar compressed archive with the application or, for Windows, a zip file. Lite XL can be easily installed by unpacking the archive in any directory of your choice.
On Windows two packages will be created, one called "portable" using the "data" folder next to the executable and the other one using a unix-like file layout. Both packages works correctly. The one with unix-like file layout is meant for people using a unix-like shell and the command line.
Please note that there aren't any hard-coded directories in the executable, so that the package can be extracted and used in any directory.
When performing the meson setup
command you may enable the -Dportable=true
option to specify whether files should be installed as in a portable application.
If portable
is enabled, Lite XL is built to use a data
directory placed next
to the executable.
Otherwise, Lite XL will use unix-like directory locations.
In this case, the data
directory will be $prefix/share/lite-xl
and the executable will be located in $prefix/bin
.
$prefix
is determined when the application starts as a directory such that
$prefix/bin
corresponds to the location of the executable.
The user
directory does not depend on the portable
option and will always be
$HOME/.config/lite-xl
.
$HOME
is determined from the corresponding environment variable.
As a special case on Windows the variable $USERPROFILE
will be used instead.
On Debian-based systems the required libraries and Meson can be installed using the following commands:
# To install the required libraries: sudo apt install libfreetype6-dev libsdl2-dev # To install Meson: sudo apt install meson # or pip3 install --user meson
To build Lite XL with Meson the commands below can be used:
meson setup --buildtype=release --prefix <prefix> build meson compile -C build DESTDIR="$(pwd)/lite-xl" meson install --skip-subprojects -C build
where <prefix>
depends on the OS you are using:
- on Linux is /usr
- on macOS application bundle can be "/Lite XL.app"
If you are using a version of Meson below 0.54 you need to use diffent commands to compile and install:
meson setup --buildtype=release build ninja -C build ninja -C build install
macOS is fully supported and a notarized app disk image is provided in the release page. In addition the application can be compiled using the generic instructions given above.
The build environment chosen for Lite XL on Windows is MSYS2. Follow the install instructions in the link.
MinGW 64-bit
or MinGW 32-bit
shell from the start menu.pacman -Syu
pacman -S \ ${MINGW_PACKAGE_PREFIX}-freetype \ ${MINGW_PACKAGE_PREFIX}-gcc \ ${MINGW_PACKAGE_PREFIX}-ninja \ ${MINGW_PACKAGE_PREFIX}-pcre2 \ ${MINGW_PACKAGE_PREFIX}-pkg-config \ ${MINGW_PACKAGE_PREFIX}-python-pip \ ${MINGW_PACKAGE_PREFIX}-SDL2 pip3 install meson
${MINGW_PACKAGE_PREFIX}
expands either to mingw-w64-i686
or mingw-w64-x86_64
depending if the current shell is 32 or 64 bit.
Keymaps on different operating systems have the same functionality, just bound slightly differently in order to conform to normal expectations for that operating system.
Currently, there are only two operating system layouts. MacOS, and everything else.
Key Combination | Actions |
---|---|
cmd +/ |
doc:toggle-line-comments |
cmd +1 |
root:switch-to-tab-1 |
cmd +2 |
root:switch-to-tab-2 |
cmd +3 |
root:switch-to-tab-3 |
cmd +4 |
root:switch-to-tab-4 |
cmd +5 |
root:switch-to-tab-5 |
cmd +6 |
root:switch-to-tab-6 |
cmd +7 |
root:switch-to-tab-7 |
cmd +8 |
root:switch-to-tab-8 |
cmd +9 |
root:switch-to-tab-9 |
cmd +[ |
doc:move-to-previous-block-start |
cmd +] |
doc:move-to-next-block-end |
cmd +a |
doc:select-all |
cmd +backspace |
doc:delete-to-start-of-indentation |
cmd +c |
doc:copy |
cmd +ctrl +i |
root:switch-to-up |
cmd +ctrl +j |
root:switch-to-left |
cmd +ctrl +k |
root:switch-to-down |
cmd +ctrl +l |
root:switch-to-right |
cmd +ctrl +return |
core:toggle-fullscreen |
cmd +ctrl +shift +i |
root:split-up |
cmd +ctrl +shift +j |
root:split-left |
cmd +ctrl +shift +k |
root:split-down |
cmd +ctrl +shift +l |
root:split-right |
cmd +d |
doc:select-word |
cmd +d |
find-replace:select-add-next |
cmd +delete |
doc:delete-to-end-of-line |
cmd +down |
doc:move-to-end-of-doc |
cmd +f3 |
find-replace:select-next |
cmd +f |
find-replace:find |
cmd +g |
doc:go-to-line |
cmd +j |
doc:join-lines |
cmd +l |
doc:select-lines |
cmd +left |
doc:move-to-start-of-indentation |
cmd +n |
core:new-doc |
cmd +o |
core:open-file |
cmd +option +down |
doc:create-cursor-next-line |
cmd +option +up |
doc:create-cursor-previous-line |
cmd +p |
core:find-file |
cmd +pagedown |
root:move-tab-right |
cmd +pageup |
root:move-tab-left |
cmd +r |
find-replace:replace |
cmd +return |
doc:newline-below |
cmd +right |
doc:move-to-end-of-line |
cmd +s |
doc:save |
cmd +shift +[ |
doc:select-to-previous-block-start |
cmd +shift +] |
doc:select-to-next-block-end |
cmd +shift +backspace |
doc:delete-to-previous-word-start |
cmd +shift +c |
core:change-project-folder |
cmd +shift +d |
doc:duplicate-lines |
cmd +shift +delete |
doc:delete-to-next-word-end |
cmd +shift +down |
doc:select-to-end-of-doc |
cmd +shift +k |
doc:delete-lines |
cmd +shift +l |
doc:select-word |
cmd +shift +l |
find-replace:select-add-all |
cmd +shift +left |
doc:select-to-start-of-indentation |
cmd +shift +o |
core:open-project-folder |
cmd +shift +p |
core:find-command |
cmd +shift +return |
doc:newline-above |
cmd +shift +right |
doc:select-to-end-of-line |
cmd +shift +s |
doc:save-as |
cmd +shift +up |
doc:select-to-start-of-doc |
cmd +up |
doc:move-to-start-of-doc |
cmd +v |
doc:paste |
cmd +w |
root:close-or-quit |
cmd +x |
doc:cut |
cmd +y |
doc:redo |
cmd +z |
doc:undo |
ctrl +1lclick |
doc:split-cursor |
ctrl +insert |
doc:copy |
ctrl +shift +tab |
root:switch-to-previous-tab |
ctrl +tab |
root:switch-to-next-tab |
f3 |
find-replace:repeat-find |
option +backspace |
doc:delete-to-previous-word-start |
option +delete |
doc:delete-to-next-word-end |
option +down |
doc:move-lines-down |
option +left |
doc:move-to-previous-word-start |
option +right |
doc:move-to-next-word-end |
option +shift +left |
doc:select-to-previous-word-start |
option +shift +right |
doc:select-to-next-word-end |
option +up |
doc:move-lines-up |
shift +f3 |
find-replace:previous-find |
A lightweight, simple, fast, feature-filled, and extremely extensible text editor written in C, and Lua, adapted from lite.
Here we provide some resources and explanation to some API and aspects of Lite XL. For API docs, it's available in the repo Thus, we'll not explain everything, only the more important and frequently used features.
Built-in APIs:
Lite XL provides a process API to launch external applications. This API is meant to replace
lua's io.popen
and lite's pipe-to-a-file approach.
Advantages of this API includes:
process.start()
may throw errors if it cannot run the program.process.read*
and process.write
functions may throw errors if
To start a process, use process.start(args, options)
.
Here are some of the more useful arguments.
args
: The executable and any arguments, eg: { "sh", "-c", "echo hello world" }
options
: Options for process.start()
env
: A key-value table containing the env. Note that if this is provided,
environment variables will not be inherited.stdin
: Specify where to redirect stdinstdout
: Specify where to redirect stdoutstderr
: Specify where to redirect stderrfor options.std{in,out,err}
, valid values are:
process.REDIRECT_PIPE
(Make it available to subprocess API for reading / writing)process.REDIRECT_DISCARD
(Discard the output. Use this to prevent buffering)process.REDIRECT_STDOUT
(stderr
only, for redirecting stderr
to stdout
)To read from stdout
or stderr
of a process, use process:read_stdout()
and
process:read_stderr()
respectively.
You can specify a numeric argument to them, which will change the size of internal buffer used to read the output.
Alternatively, you could use process:read()
with process.STREAM_STDERR
and process.STREAM_STDOUT
.
Example:
local proc = process.start { "sh", "-c", "echo hello world!" } -- do not use `while proc:running()` if you care about output. -- The process could die and leave data in the buffer -- You should just read until `proc:read_stdout()` returns nil while true do local rdbuf = proc:read_stdout() if not rdbuf then break end -- yay, output end
You can use process:write(data)
to write a string to stdin
.
process:running()
returns a boolean to indicate whether if the process is running.process:wait(time)
also does the same thing, but you specify how long it should wait (or 0 to return immediately).process:terminate()
sends SIGTERM (or Windows equivalent) to the process.process:kill()
sends SIGKILL (or Windows equivalent) to the progress.
Use this only if process:terminate()
cannot kill the process, as it can cause issues.process:pid()
returns the PID of the process.
There are no guarantees for this PID to be correct if the process terminated early.process:returncode()
returns the exit code of the process, if anyprocess:close_stream()
closes stdin
, stdout
or stderr
stream of the process.This is where Lite XL's lua code interact with its underlying C engine. Some of the functions here will be omitted because they're not useful for plugins.
system.set_clipboard(text)
sets the clipboard content.system.get_clipboard()
retrieves the content of the clipboard.system.list_dir(dir)
returns a list of filenames in a directory.system.rmdir(dir)
removes a directory. Use this instead of os.remove()
.
The directory must be empty.system.chdir(dir)
changes the current working directory (like cd
).system.mkdir(dir)
creates a new directory.
It does not recursively create directories.system.absolute_path(path)
resolves the path components (.. and .
) to an absolute path.system.get_file_info(path)
returns info about a path.
modified
: last modification time of the file in seconds since UNIX epoch.size
: file size in bytes.type
: Path type ("file"
or "dir"
).system.get_time()
returns time in seconds (as floating point number) since Lite XL started.
Use this instead of os.time()
for higher precision timers.system.sleep(time)
sleeps for time
in milliseconds.
Do not use this. Write asynchronous code.system.set_window_opacity(o)
sets the window opacity from 0 to 1.system.set_window_title(title)
sets the window title.system.set_window_mode(mode)
sets window mode:
"normal"
: also known as "restored" on Windows."maximized"
: Maximize the window."minimized"
: Minimize the window."fullscreen"
: Fullscreensystem.set_window_bordered(bordered)
enables or disable window border (decoration).system.set_window_hit_test(height, control_width, resize_border)
sets window hit test (used for
config.borderless
to make custom drawn border interactable).
height
: height of the title bar.controls_width
: Not too sure about this, but it should be the size of the title bar controls
(Maximize, Minimize and Normal buttons on the right).
It seems to be fixed at the right side of the title bar.resize_border
: Number of pixels reserved for resizing the window.
(setting this to a large value means that you can resize the window way easier)system.get_window_size()
gets the window size.system.set_window_size(w, h, x, y)
sets the window size (and also position).system.window_has_focus()
checks whether the window is in focus.system.show_fatal_error(title, msg)
shows an system error message box.
Use nagview whenever possible.system.exec(command)
runs a command. Use the Process API instead of this.system.fuzzy_match(haystack, needle, file)
generates a score depends on how close the needle
matches the haystack.
file
: match backwards (more accurate for filename matching).This API provides PCRE regular expressions for those who needs more power in matching text. This API written in C and Lua.
Use regex.compile(pattern, options)
to compile a regex.
pattern
: The regex patternoptions
: regex modifiers as a string, eg "im"
"i"
: Case-insensitive search"m"
: Multiline search"s"
: Match all characters with dot (.
), including newlines.regex:cmatch(str, offset, options)
low-level matching function
str
: The string to match againstoffset
: Where to start matchingoptions
: A bit field of optionsregex.ANCHORED
: Only match from the start of the stringregex.ENDANCHORED
: Only match from the end of the stringregex.NOTBOL
: String is not beginning of lineregex.NOTEOL
: String is not the end of lineregex.NOTEMPTY
: Do not match an empty stringregex.NOTEMPTY_ATSTART
: Do not match empty string at the startNote: regex:cmatch()
returns wrong indexes (currently at version 2.0.2).
The end index returned by regex:cmatch()
is always off by 1 (-1 to get the actual end index).
All the functions below can be in 2 forms:
- regex:fn(...)
where regex
is the compiled regex instance
- regex.fn(pattern, ...)
where pattern
is a pattern string to be compiled and used directly.
We will only document the first form.
regex:match(str, offset, options)
high level matching function. This function accepts
the same arguments as regex:cmatch()
regex:gsub(str, replacement)
replaces matches in str
with replacement
.
Capture groups are identified with \0
to \9
, this might change in the future.Simple is a very basic plugin written with the intention of introducing developers who are new to Lite XL to the process of writing plugins for the editor.
The plugin displays a message (that is taken as input from the user) at the top right corner of the editor window. It also allows the user to toggle the visibility of the message.
If you come from other programming languages, take a look at Lua cheatsheet. If you're new to programming, you can read this.
The code contains comments detailing what most (if not all) of the code in the file does.
-- mod-version:2 -- lite-xl 2.0 -- you MUST put mod-version:x on the first line of your plugin -- mod-version usually maps to lite-xl releases (eg. mod-version: 2 == lite-xl 2.0) -- lite-xl won't load the plugin if the mod-version mismatches ----------------------------------------------------------------------- -- NAME : Simple -- DESCRIPTION: A simple guide on how to make your first Lite XL plugin -- AUTHOR : Ashwin Godbole (aelobdog) -- GOALS : To render some text inside the editor ----------------------------------------------------------------------- -- Disclaimer : -- I am not a lua developer, and my knowledge about writing plugins for -- Lite XL is very limited. This file serves the purpose of helping the -- reader get started with plugin development for Lite XL, and therefore -- demonstrates only some very basic features. For more complex plugin -- development, be sure to check out the source code of some other -- plugins after going through this file. ----------------------------------------------------------------------- -- Before we start writing any code for the plugin, we must import the -- required modules from the "core" package. -- the "core" module local core = require "core" -- the "command" module will help us register commands for our plugin. local command = require "core.command" -- the "style" module will allow us to use styling options local style = require "core.style" -- the "config" module will be used to store certain things like colors -- and functions local config = require "core.config" -- the "keymap" module will allow us to set keybindings for our commands local keymap = require "core.keymap" -- since we wants to modify RootView, we'll need to require it first local RootView = require "core.rootview" ----------------------------------------------------------------------- -- per-plugin config must stay in config.plugins.(plugin name) config.plugins.simple = {} -- colors are just three or four comma separated values (RGBA) (range 0 - 255) -- put inside of '{ }'. We will add our color to the config module. config.plugins.simple.text_color = {200, 140, 220} -- or use `{ common.color "#C88CDC" }` ----------------------------------------------------------------------- -- Let's create a function to calculate the coordinates of our text. -- While we're at it, let's add out function to the `config` module. -- We'll take the message we want to display as the argument to the -- function to determine the x and y coordinates of the text. function config.plugins.simple.get_text_coordinates(message) -- For this plugin, we want to display the text on the top right -- corner of the screen. For this, we need to know the editor's width -- and height. -- The current font's size can be obtained from the "style" module. -- The editor's dimensions can be obtained by -- 1. WIDTH : core.root_view.size.x -- 2. HEIGHT : core.root_view.size.y local message_width = style.code_font:get_width(message.." ") local font_height = style.code_font:get_size() local x = core.root_view.size.x - message_width local y = font_height / 2 return x, y end ----------------------------------------------------------------------- -- Let's now get to actually drawing the text inside the editor. -- In order to "inject" our own code to draw text, -- we'll need to save the original draw function -- We'll save `RootView.draw` to a variable we call `parent_draw` local parent_draw = RootView.draw -- Now let's overload the original definition of `draw` in RootView -- by redefining the function. function RootView:draw() -- We call the parent's function to keep the editor functional... -- obviously we must still draw all the other stuff ! -- So we call the `parent_draw` function before doing anything else. parent_draw(self) -- we'll add an option to toggle the message on and off. let's use a -- boolean variable to keep track of whether we want to display the -- message or not. if config.plugins.simple.show_my_message then -- We'll be getting the message to display as input from the user -- later. We'll store that user input in `config.plugins.simple.hw_message`. -- (NOTE: this variable does not come in-built in lite-xl; -- it is a variable that we will define later.) -- let's store the value of config.plugins.simple.hw_message in a local variable -- `message` in case config.plugins.simple.hw_message we set the message to -- "message not set yet!" local message if config.plugins.simple.hw_message then message = config.plugins.simple.hw_message else message = "Message not set yet !" end -- let's get the coordinates for our text local x, y = config.plugins.simple.get_text_coordinates(message) -- let's finally draw the text to the window ! -- the draw_text function from `renderer` is an important function -- as it is used to display any and all text inside of the editor -- window renderer.draw_text(style.code_font, message, x, y, config.plugins.simple.text_color) end end ----------------------------------------------------------------------- -- Let's allow the user to turn the message on and off -- we'll write a function to flip our "show" boolean variable. local function toggle_helloworld() config.plugins.simple.show_my_message = not config.plugins.simple.show_my_message end ----------------------------------------------------------------------- -- Finally, let's add the toggle function to the command list so that -- we can call it from the C-S-p command panel. Let's add one command -- to toggle the visibility of the message on and off and one to get -- the user's message and then display it. command.add(nil, { -- Toggle the visibility of the message ["simple:toggle"] = toggle_helloworld, -- Set and show the message -- This is the way to get user input through the command bar. -- `core.command_view:enter` takes 2 arguments: -- * the prompt to display before taking input -- * a function that takes the "input" as its argument -- (NOTE: here the variable we are reading input into is `text`) ["simple:setshow"] = function() core.command_view:enter("Test to display", function(text) config.plugins.simple.hw_message = text config.plugins.simple.show_my_message = true end) end } ----------------------------------------------------------------------- -- Just for fun, let's assign our commands their own keybindings. -- Here, we assign the keybinding the same string(its name) as the one -- that we set while creating the command keymap.add { ["alt+s"] = "simple:setshow", ["alt+t"] = "simple:toggle", }
Syntax highlighting plugins for Lite XL are Lua files. These define some patterns or regular expressions that match different parts of a given language, assigning token types to each match. These different token types are then given different colors by your chosen color scheme.
Like other plugins, syntax definitions are sourced from the following folders, in order:
/usr/share/lite-xl/plugins/
$HOME/.config/lite-xl/plugins/
NOTE: The exact location of these folders will depend on your OS and installation method. For example, on Windows, the variable $USERPROFILE
will be used instead of $HOME
.
The user module folder for Lite XL can generally be found in these places on different OSes:
C:\Users\(username)\.config\lite-xl
/Users/(usernmame)/.config/lite-xl
/home/(username)/.config/lite-xl
So, to create a new syntax definition on Linux, you can just create a .lua
file in your $HOME/.config/lite-xl/plugins/
folder.
The supported syntax token types, defined by lite-xl/core/style.lua
, are:
In your syntax highlighting plugin, you write patterns to match parts of the language syntax, assigning these token types to matches. You don't have to use them all - just use as many as you need for your language.
Let's walk through an example syntax definition and see how this works.
This is a small, simple example of a syntax definition. It's intended to highlight SSH Config files and looks like this:
-- mod-version:2 -- lite-xl 2.0 local syntax = require "core.syntax" syntax.add { files = { "sshd?/?_?config$" }, comment = '#', patterns = { { pattern = "#.*\n", type = "comment" }, { pattern = "%d+", type = "number" }, { pattern = "[%a_][%w_]*", type = "symbol" }, { pattern = "@", type = "operator" }, }, symbols = { -- ssh config ["Host"] = "function", ["ProxyCommand"] = "function", ["HostName"] = "keyword", ["IdentityFile"] = "keyword", ... -- sshd config ["Subsystem"] = "keyword2", -- Literals ["yes"] = "literal", ["no"] = "literal", ["any"] = "literal", ["ask"] = "literal", }, }
Let's take each section in turn and see how it works.
The first line is a Lua comment & tells Lite XL which version this plugin requires. The second imports the core.syntax
module
for us to use:
-- mod-version:2 -- lite-xl 2.0 local syntax = require "core.syntax"
We then add a syntax definition to lite, using syntax.add {...}
. The contents of this definition are covered next.
The files
property tells Lite XL which files this syntax should be used for. This is a Lua pattern that matches against the full path of the file being opened. For example, to match against Markdown files - with either a .md
or a .markdown
extension,
you could do this:
files = { "%.md$", "%.markdown$" },
In our original example, we match against the end of the path rather than the extension, because SSH config files don't have extensions - and we don't want to match all config
files. We expect the path for SSH config files to look something like one of these:
~/.ssh/config
/etc/ssh/ssh_config
/etc/ssh/sshd_config
This pattern matches paths that look like that:
files = { "sshd?/?_?config$" },
The comment property doesn't define which parts of the syntax are comments - see Patterns for that, below. This property tells Lite XL which character to insert at the start of selected lines when you press ctrl+/
.
A given piece of text can only match one pattern. Once Lite XL decides that a piece of text matches a pattern, it will assign that token type to that piece and move on. Patterns are tested in the order that they are written in the syntax definition, so the first match will win.
Each pattern takes one of the following forms:
{ pattern = "#.*\n", type = "comment" },
This form matches the line against the pattern and if it matches, assigns the matching text to the given token type
- comment
, in this case.
{ pattern = { "%[", "%]" }, type = "keyword" },
This form has two patterns - one that matches against the start of the range and one that matches against the end. Everything between the start and the end will be assigned the given token type
.
{ pattern = { '"', '"', '\' }, type = "string" },
This is the same as the previous form, but with an extra, third parameter.
The 3rd part, the '\'
part in this example, specifies the character that allows escaping the closing match.
For more on Lua Patterns, see: Lua Pattern Reference
If you need to use PCRE Regular Expressions, instead of Lua Patterns, you can use the regex
keyword here, instead of pattern
.
The symbols section allows you to assign token types to particular keywords or strings - usually reserved words in the language you are highlighting.
For example this highlights Host
using the function
token type, HostName
as a keyword
and yes
, no
, any
& ask
as a literal
:
["Host"] = "function", ["HostName"] = "keyword", ["yes"] = "literal", ["no"] = "literal", ["any"] = "literal", ["ask"] = "literal",
To test your new syntax highlighting you need to do two things:
To reload the core, you can either restart Lite XL, or reload the core from the command palette, without needing to restart.
To do this, type ctrl+shit+p
to show the command palette, then select Core: Restart
(or type crr
or something similar to match it), then press Enter. You will need to restart the core after any changes you make to the syntax highlighting definition.
lite-xl does not provide a convenient way to use fonts on the system. There is literally _different APIs for the each platforms we support (Windows, Linux and Mac). This is where fontconfig comes to our rescue. fontconfig is installable on a lot of OSes.
lite-xl has a fontconfig plugin that we can use to find system fonts.
mingw-w64-fontconfig provides a build that can be used directly on Windows. Download the file, extract it to somewhere and (optionally) add it to the PATH.
Check your distro-specific instructions.
# ubuntu / debian apt install fontconfig # arch pacman -Su fontconfig # fedora dnf install fontconfig ...
brew install fontconfig
local fontconfig = require "plugins.fontconfig" fontconfig.use { font = { name = "sans", size = 13 * SCALE }, code_font = { name = "monospace", size = 13 * SCALE } }
"sans"
and "monospace"
can be any fontconfig syntax. (check "Font Names")
Note that the font might not load immediately (because we need to wait for fc-match
to return.
If you want that, replace fontconfig.use
with fontconfig.use_blocking
. Doing this will force
lite-xl to wait for fc-match
, which can be much slower.