轻量级 IDE:Lite XL

Lite XL 是一款使用 C 和 Lua 开发的开源文本编辑器。它的官网简介为:

A simple, fast, feature-filled and extremely extensible text editor written in C and Lua, adapted from lite.

它的 Windows 安装包大小仅为 2MB。在不加载插件的情况下,启动后占用内存只有 20MB 多。和 VSCode 动则几百 MB 的内存使用量相比,的确算得上轻量。虽然官方的自我定位是一款文本编辑器,不过在安装插件后可以作为一个简单的 IDE 使用。其生态位和 Sublime 类似,可以作为主力 IDE 的备胎。

本文仅介绍 Lite XL 在 Windows 平台上的安装和使用。

安装

官网提供 Windows 平台的安装包。也可以使用 WinGet 安装:

powershellwinget install LiteXLTeam.LiteXL

或者 Chocolatey 安装:

powershellchoco install lite-xl

特别要注意的是,如果使用 Scoop 安装,最好选择 versions/lite-xl-addons 包,而不是 extras/lite-xl。后者缺少一些组件,比如 2.1 版本后自带的 Settings GUI 插件。

powershellscoop install versions/lite-xl-addons

基本配置

在 Windows 平台上,Lite XL 会按如下顺序查找配置:

  1. 安装路径下的 \user 目录
  2. %LITE_USERDIR%
  3. %XDG_CONFIG_HOME%\lite-xl
  4. %USERPROFILE%\.config\lite-xl

如果要制作软件的便携版,可以将配置存放在软件根目录下。另外,可以将配置目录上传到 GitHub 或者云端,以便在不同设备上共享配置。

Lite XL 的配置文件是一组 Lua 脚本,用户的配置信息称为 User Module,它的入口是配置目录下的 init.lua 文件。在 Settings GUI 中修改的配置会保存在 user_settings.lua 文件中。

由于 Lite XL 的 GUI 使用 SDL2 绘制,并不使用系统字体,因此默认不支持显示中文。软件自带两款英文字体,用户界面使用 FiraSans 字体,编辑区文本使用 JetBrainsMono 字体。在使用 Lite XL 之前,必须先设置字体使其支持显示中文。

Interface Font

在 Lite XL 窗口中按下 Ctrl + Alt + p 打开 Settings GUI。在 Interface 小节中找到 Font 设置,点击下方的 按钮,打开「Font Selector」对话框,点击 按钮,在下方的 Select Font: 提示符右侧输入 yahei,在候选列表里选中「Microsoft YaHei Regular」,点击 按钮保存。

然后对 Editor 小节的 Font 设置进行同样的设置。

管理插件

插件存放在 DATADIR\plugins 和 USERDIR\plugins 目录下。其中 DATADIR 是软件安装路径下的 data 目录,USERDIR 是用户配置目录。可以在官方提供的插件仓库里找到需要安装的插件,手动下载并保存到插件目录中。

为了方便管理插件,可以安装 lpmMiq。前者是官方提供的插件管理命令行工具,后者是第三方开发的声明式插件管理器。

安装 lpm

lpm 可以通过 WinGet 安装:

powershellwinget install LiteXLTeam.LPM

或者 Scoop 安装:

powershellscoop install https://raw.githubusercontent.com/lite-xl/lite-xl-plugin-manager/refs/heads/master/lite-xl-plugin-manager.json

也可以直接下载 Windows 可执行文件:

Lite XL Plugin Managergithub.comA standalone binary that provides an easy way of installing, and uninstalling plugins from lite-xl.

将下载后的 lpm.x86_64-windows.exe 文件重命名为 lpm.exe,并保存到 PATH 路径下。

首先,安装插件管理器的图形界面:

powershelllpm install plugin_manager --assume-yes

也可以手动指定 lpm 的安装路径。例如,先将 lpm.exe 保存在用户配置目录下;然后在 Lite XL 窗口中按下 Ctrl + Shift + p 打开命令输入框;在提示符右侧输入 Core: Open User Module,打开 init.lua 配置文件;在文件中添加如下行:

luaconfig.plugins.plugin_manager.lpm_binary_path = USERDIR .. '/lpm.exe'

重启 Lite XL 使得插件生效。打开命令输入框,在提示符右侧输入 Plugin Manager: Show,打开插件管理器的图像界面。

使用 lpm 安装和卸载插件:

powershelllpm install autoinsert
lpm uninstall autoinsert

升级所有插件:

powershelllpm upgrade
注意

目前没有发现 lpm 可以设置代理服务器,因此 lpm 下载二进制文件时可能会出现网络问题。可以将代理设置成虚拟网卡。

安装 Miq

运行以下命令安装 Miq:

powershellgit clone https://github.com/TorchedSammy/Miq $env:USERPROFILE\.config\lite-xl\plugins\miq

重启 Lite XL 使得插件生效。在 USERDIR\init.lua 配置文件中声明需要安装的插件:

lua-- Plugins are specified in this table:
config.plugins.miq.plugins = {
    -- Miq can manage itself
    'TorchedSammy/Miq',

    -- Normal plugins hosted on a single git repo can be specified with AuthorName/RepoName
    'lite-xl/lite-xl-lsp',

    -- Plugins on the central lite-xl-plugins repo can be specified by name
    'autoinsert'

    -- If you want to install a plugin with from a specific repo, it can be done
    -- format would be url:branch/commit
    {'plugin', repo = 'https://github.com/user/lite-xl-plugins:master'}

    -- If needed, you can setup a local plugin, which will simply be symlinked.
    -- I personally do this for Miq.
    '~/lite-xl-plugin-path'

    -- Any native plugin or similar that needs compiling can have a post install command.
    {'TorchedSammy/Litepresence', run = 'go get && go build'}

    -- The destination plugin name can be specified if other plugins rely on a special name
    -- (gitdiff-highlight requires itself with an underscore)
    {'vincens2005/lite-xl-gitdiff-highlight', name = 'gitdiff_highlight'}
}

打开命令输入框,在提示符右侧输入 Miq: install ,安装全部插件。输入 Miq: update 升级全部插件。

Miq 在实际使用中发现不少问题。比如,使用官方提供的配置安装 autoinsert 插件时出错,提示 No suitable addon repository found

安装 autoinsert 失败

另外,该项目已经有 8 个月没有更新了。这个插件的可用性要打个问号。

常用插件

Lite XL 通过安装 LSP 插件可以实现代码自动补全等高级 IDE 功能,但是这样避免不了因安装插件过多而导致内存使用量的暴涨的问题。不如将 Lite XL 仅作为一个支持语法高亮和项目管理的轻量级 IDE 使用。如果要启用 LSP 支持,可以参考官方的文档:Language Server support

推荐安装的插件
名称描述
autoinsert自动闭合括号和引号
autosave当文件修改时自动保存
bracketmatch高亮匹配的括号
devicons丰富左侧 TreeView 的图标
formatter支持部分语言的代码格式化
gitblame显示 Git Blame 信息(每一行文件的最后修改版本和作者)
gitdiff_highlight高亮已修改的行
indentguide显示缩进对齐线
lfautoinsert新行后自动插入缩进和闭合括号
lintplus支持 Linter
meta_colors安装所有主题(addons 版本自带)
meta_languages安装所有支持语言的语法高亮插件(addons 版本自带)
minimapVSCode 风格代码小地图
search_ui友好的搜索界面
selectionhighlight高亮同选中文本一致的代码
snippets支持代码 snippets
sticky_scroll在视图置顶当前代码块
terminal嵌入终端
todotreeview在右侧边栏显示代码中所有带 TODO、BUG、FIX 和 IMPROVEMENT 的注释

我将这些插件整理后创建了一个 lpm repo 提交到了 GitHub。通过下列命令可以直接安装这些插件:

powershelllpm add https://github.com/tabris17/lite-xl-plugins:main
lpm install meta_lite_ide

在 Windows 上,启用 gitblame 插件会导致 Lite XL 挂起。排查原因后发现是插件脚本 gitblame.lua 中的代码导致:

lualocal function exec(cmd)
    local proc = process.start(cmd)

    if proc then

        local output = ""

        while true do
            local rdbuf = proc:read_stdout()
            if not rdbuf then
                break
            else
                output = output .. rdbuf
            end
        end

        return output
    end

    return nil
end

此处 proc:read_stdout() 永远返回一个空字符串,导致 while true do 循环无法退出。将此处代码改为如下即可:

lualocal function exec(cmd)
    local proc = process.start(cmd)

    if proc then
        proc:wait(process.WAIT_INFINITE)
        return proc:read_stdout()
    end

    return nil
end

附录

Keymap

转自:https://lite-xl.com/user-guide/keymap/

命令按键说明
autocomplete:cancelEsc
autocomplete:completeTab
autocomplete:nextDown
autocomplete:previousUp
command:completeTab
command:escapeEsc
command:select-nextDown
command:select-previousUp
command:submitNum Enter , Enter
context:focus-nextDown
context:focus-previousUp
context:hideEsc
context:on-selectedEnter
context:showMenu
core:change-project-folderCtrl + Shift + c在当前窗口打开项目文件夹
core:find-commandCtrl + Shift + p
core:find-fileCtrl + p在项目中查找文件
core:new-docCtrl + n
core:open-fileCtrl + o
core:open-project-folderCtrl + Shift + o在新窗口打开项目文件夹
core:restartCtrl + Alt + r
core:toggle-fullscreenAlt + Enter , F11打开/关闭全屏
dialog:next-entryRight
dialog:previous-entryLeft
dialog:selectNum Enter , Enter
dialog:select-noEsc
doc:backspaceBackspace , Shift + Backspace
doc:copyCtrl + c , Ctrl + Ins拷贝
doc:create-cursor-next-lineCtrl + Shift + Down在上一行创建光标
doc:create-cursor-previous-lineCtrl + Shift + Up在下一行创建光标
doc:cutCtrl + x剪切
doc:deleteDel , Shift + Del
doc:delete-linesCtrl + Shift + k删除光标所在行
doc:delete-to-next-word-endCtrl + Del , Ctrl + Shift + Del删除至后一个单词
doc:delete-to-previous-word-startCtrl + Backspace , Ctrl + Shift + Backspace删除至前一个单词
doc:duplicate-linesCtrl + Shift + d重复当前行
doc:go-to-lineCtrl + g跳转到行
doc:indentTab
doc:join-linesCtrl + j合并行
doc:move-lines-downCtrl + Down下移当前行
doc:move-lines-upCtrl + Up上移当前行
doc:move-to-end-of-docCtrl + End光标移动到文档末尾
doc:move-to-end-of-lineEnd光标移动到行末
doc:move-to-next-block-endCtrl + ]光标移动到下一个空白行
doc:move-to-next-charRight
doc:move-to-next-lineDown
doc:move-to-next-pagePage Down
doc:move-to-next-word-endCtrl + Right光标向后移动一个单词
doc:move-to-previous-block-startCtrl + [光标移动到上一个空白行
doc:move-to-previous-charLeft
doc:move-to-previous-lineUp
doc:move-to-previous-pagePage Up
doc:move-to-previous-word-startCtrl + Left光标向前移动一个单词
doc:move-to-start-of-docCtrl + Home光标移动到文档起始
doc:move-to-start-of-indentationHome光标移动到当前行缩进位置
doc:newlineNum Enter , Enter
doc:newline-aboveCtrl + Shift + Enter在当前行之前创建新行
doc:newline-belowCtrl + Enter
doc:pasteCtrl + v , Shift + Ins粘贴
doc:redoCtrl + y重复
doc:saveCtrl + s保存
doc:save-asCtrl + Shift + s另存为
doc:select-allCtrl + a全选
doc:select-linesCtrl + l选中光标所在行
doc:select-noneEsc
doc:select-to-cursorShift + Left Button
doc:select-to-end-of-docCtrl + Shift + End选中光标位置到文档末尾
doc:select-to-end-of-lineShift + End选中光标位置到行末
doc:select-to-next-block-endCtrl + Shift + ]选中光标位置到下一个空白行
doc:select-to-next-charShift + Right
doc:select-to-next-lineShift + Down
doc:select-to-next-pageShift + Page Down
doc:select-to-next-word-endCtrl + Shift + Right选中光标位置到后一个单词
doc:select-to-previous-block-startCtrl + Shift + [选中光标位置到上一个空白行
doc:select-to-previous-charShift + Left
doc:select-to-previous-lineShift + Up
doc:select-to-previous-pageShift + Page Up
doc:select-to-previous-word-startCtrl + Shift + Left选中光标位置到前一个单词
doc:select-to-start-of-docCtrl + Shift + Home选中光标位置到文档起始
doc:select-to-start-of-indentationShift + Home选中光标位置到当前行缩进位置
doc:select-wordCtrl + d , Ctrl + Shift + l选中光标所在的单词
doc:set-cursorLeft Button
doc:set-cursor-lineLeft Button
doc:set-cursor-wordLeft Button
doc:split-cursorCtrl + Left Button放置新光标
doc:toggle-block-commentsCtrl + Shift + /块注释/取消块注释光标所在的行
doc:toggle-line-commentsCtrl + /行注释/取消行注释光标所在的行
doc:undoCtrl + z撤销
doc:unindentShift + Tab取消缩进
find-replace:findCtrl + f查找
find-replace:previous-findShift + F3
find-replace:repeat-findF3
find-replace:replaceCtrl + r
find-replace:select-add-allCtrl + Shift + l
find-replace:select-add-nextCtrl + D
find-replace:select-nextCtrl + F3
find-replace:select-previousCtrl + Shift + F3
find-replace:toggle-regexCtrl + Shift + i
find-replace:toggle-sensitivityCtrl + i
line-wrapping:toggleF10
macro:playCtrl + ;播放宏
macro:toggle-recordCtrl + Shift + ;开始/结束录制宏
project-search:findCtrl + Shift + f在项目中搜索文件
project-search:move-to-end-of-docCtrl + End , End
project-search:move-to-next-pagePage Down
project-search:move-to-previous-pagePage Up
project-search:move-to-start-of-docCtrl + Home , Home
project-search:open-selectedEnter
project-search:refreshF5
project-search:select-nextDown
project-search:select-previousUp
quote:quoteCtrl +
reflow:reflowCtrl + Shift + q
root:closeCtrl + w关闭页面
root:horizontal-scrollHorizontal Wheel , Shift + Wheel
root:move-tab-leftCtrl + Page Up
root:move-tab-rightCtrl + Page Down
root:scrollWheel
root:split-downShift + Alt + k下方水平拆分页面
root:split-leftShift + Alt + j左侧垂直拆分页面
root:split-rightShift + Alt + l右侧垂直拆分页面
root:split-upShift + Alt + i上方水平拆分页面
root:switch-to-downAlt + k切换到下方页面
root:switch-to-leftAlt + j切换到左侧页面
root:switch-to-next-tabCtrl + Tab切换到下一个页面
root:switch-to-previous-tabCtrl + Shift + Tab切换到上一个页面
root:switch-to-rightAlt + l切换到右侧页面
root:switch-to-tab-1Alt + 1
root:switch-to-tab-2Alt + 2
root:switch-to-tab-3Alt + 3
root:switch-to-tab-4Alt + 4
root:switch-to-tab-5Alt + 5
root:switch-to-tab-6Alt + 6
root:switch-to-tab-7Alt + 7
root:switch-to-tab-8Alt + 8
root:switch-to-tab-9Alt + 9
root:switch-to-upAlt + i切换到上方页面
scale:decreaseCtrl + - , Ctrl + Wheel Down
scale:increaseCtrl + =, Ctrl + Wheel Up
scale:resetCtrl + 0
treeview:collapseLeft
treeview:deleteDel
treeview:deselectEsc
treeview:expandRight
treeview:new-folderCtrl + Left Button , Ctrl + Enter
treeview:nextDown
treeview:openEnter
treeview:previousUp
treeview:selectMiddle Button
treeview:select-and-openLeft Button
treeview:toggleCtrl + \打开/关闭左侧 TreeView
terminal:toggle-drawerAlt + t打开/关闭终端窗格
terminal:open-tabCtrl + Shift + `在新页面中打开终端窗口
terminal:close-tabCtrl + Shift + w
todotreeview:toggleCtrl + Shift + t打开/关闭 TodoTreeView