A simple project switcher for Kakoune

A simple project switcher for Kakoune

为 Kakoune 开发一个简单的项目切换器

Posted on 31st May 2026 in Editing, Kakoune 发布于 2026 年 5 月 31 日,归类于 Editing, Kakoune

I always appreciate a project-switching interface in my editor. I didn’t expect Kakoune, a barebones terminal editor, to have a built-in project switcher. But, after executing cd $project_dir; kak for the nth time, I started looking for a solution. 我一直很欣赏编辑器中自带的项目切换界面。我本没指望 Kakoune 这种极简的终端编辑器会内置项目切换器。但在第 N 次执行 cd $project_dir; kak 后,我开始寻找解决方案。

How other editors implement a project switcher

其他编辑器如何实现项目切换器

VS Code provides a project switcher through “Open Recent” action, bound to Ctrl + R on Linux. In my experience, any file or folder opened with VS Code’s “Open File” or “Open Folder” dialogs show up here. So it’s a bit of a stretch to call it a project switcher if you frequently open files directly. VS Code 通过“打开最近项目”(Open Recent)功能提供项目切换,在 Linux 上绑定为 Ctrl + R。根据我的经验,任何通过 VS Code 的“打开文件”或“打开文件夹”对话框打开的内容都会出现在这里。因此,如果你经常直接打开单个文件,将其称为“项目切换器”其实有些牵强。

JetBrains IDEs offer an unbounded “Open Recent Project” action, which opens the switcher at the tip of the cursor, though I use a FrameSwitcher plugin which performs the job better. JetBrains 系列 IDE 提供了一个无限制的“打开最近项目”操作,它会在光标处打开切换器,不过我更喜欢使用 FrameSwitcher 插件,它的表现更好。

Elements of a project switcher

项目切换器的要素

I identify two essential elements of a project switcher interface: 我认为项目切换器界面有两个核心要素:

  1. Display a list of projects already registered with the interface, through which one can fuzzy find and switch to a project. Once switched, the selected project’s directory becomes the current directory within the editor’s context, so that editor actions happen in the selected project directory’s context. So, for instance, a file finder would now look for a file within the selected project’s directory. And so on.

  2. 显示已注册的项目列表:用户可以通过该列表进行模糊搜索并切换到特定项目。切换后,所选项目的目录将成为编辑器上下文中的当前目录,从而确保后续的编辑器操作都在该项目目录下进行。例如,文件查找器现在会在所选项目目录内搜索文件,以此类推。

  3. Add a new project to the interface. Usually this is automatic. When user opens a new project in JetBrains IDEs or VS Code, the editor automatically registers the project to the switcher interface.

  4. 向界面添加新项目:通常这是自动完成的。当用户在 JetBrains IDE 或 VS Code 中打开新项目时,编辑器会自动将该项目注册到切换器界面中。

How I manifested the elements in Kakoune

我如何在 Kakoune 中实现这些要素

Kakoune’s scripting primitives, combined with its philosophy to use shell scripting to extend itself, were adequate tools to build a simple project switcher. I needed a place to persistently register opened project directories in Kakoune. I chose a plaintext projects file that sits besides kakoune’s config file ~/.config/kak/kakrc. Each line in projects stores a path to a project dir. Kakoune 的脚本原语,结合其利用 Shell 脚本进行扩展的哲学,为构建简单的项目切换器提供了充足的工具。我需要一个地方来持久化存储已打开的项目目录。我选择在 Kakoune 的配置文件 ~/.config/kak/kakrc 旁边创建一个纯文本的 projects 文件,每一行存储一个项目目录的路径。

Registering a new project with the interface

向界面注册新项目

I wrote a Kakoune command :project-add that: 我编写了一个 Kakoune 命令 :project-add,它可以:

  • lets user choose a directory from their filesystem, using Kakoune’s path completion interface
  • appends the path of the chosen directory in projects file
  • uses Kakoune’s :change-directory primitive to set the chosen directory as Kakoune’s working directory
  • 允许用户使用 Kakoune 的路径补全界面从文件系统中选择目录
  • 将所选目录的路径追加到 projects 文件中
  • 使用 Kakoune 的 :change-directory 原语将所选目录设置为当前工作目录

Here is the implementation: 实现如下:

define-command project-add \
    -docstring "Add a project" \
    -params 1 %{
        nop %sh{ printf "%s\n" "$1" >> ~/.config/kak/projects }
        change-directory %arg{1}
        exec ":file-picker "
    }
complete-command project-add file

Switching to a registered project

切换到已注册的项目

I implemented a Kakoune command :project-pick that: 我实现了一个 Kakoune 命令 :project-pick,它可以:

  • lists the paths stored in projects file using Kakoune’s completion interface. The completion interface also sorts and excludes duplicate entries.
  • sets the working directory of Kakoune to the selected path using its :change-directory primitive
  • 使用 Kakoune 的补全界面列出 projects 文件中存储的路径(补全界面会自动排序并排除重复项)
  • 使用 :change-directory 原语将 Kakoune 的工作目录设置为所选路径

Here is the implementation: 实现如下:

define-command project-pick \
    -docstring "Pick a project" \
    -params 1 %{
        change-directory %arg{1}
        exec ":file-picker "
    }
complete-command project-pick \
    shell-script-candidates \
    %{ cat ~/.config/kak/projects | sort | uniq }

Bonus - file picker

额外福利 - 文件选择器

Both :project-add and :project-pick commands land the user on a file picker interface, which again builds on top of Kakoune’s completion interface, so that they can start working right away on their project. :project-add:project-pick 命令执行后都会进入文件选择界面,该界面同样基于 Kakoune 的补全功能构建,让用户可以立即开始项目工作。

define-command file-picker \
    -docstring "Pick a file from current directory" \
    -params 1 %{
        edit %arg{1}
    }
complete-command file-picker \
    shell-script-candidates \
    %{ git ls-files -c -o --exclude-standard }

Bonus - keybindings

额外福利 - 快捷键

Both the commands received their own keybindings for quick execution. Kakoune offers custom user modes which can act as namespaces to neatly tuck away related keybindings. I created a project user mode to do just that for my project switcher. 这两个命令都分配了快捷键以便快速执行。Kakoune 提供了自定义用户模式(user modes),可以作为命名空间来整齐地组织相关快捷键。我为此创建了一个 project 用户模式。

# Define project user mode
# 定义 project 用户模式
declare-user-mode project
map global project p ":project-pick " -docstring "Pick a project"
map global project a ":project-add " -docstring "Add a project"

# Now tie up project mode to the global user mode
# so that project mode becomes a submode to the
# global user mode
# 将 project 模式绑定到全局用户模式,使其成为子模式
map global user p ":enter-user-mode project<ret>" -docstring "Project commands"

Now, Space + p + a triggers :project-add, while Space + p + p triggers :project-pick. 现在,Space + p + a 触发 :project-add,而 Space + p + p 触发 :project-pick

In closing

结语

The video snippet below showcases the final result. I apologise for a cropped Kakoune’s modeline in the video. I don’t know why that happened, and I can’t be bothered with making another video since the cropped modeline is still comprehensible. I could implement guardrails like checking for existence of the projects file, or add a :project-delete command, but I’m satisfied with the current state. Any comments are welcome. 下方的视频片段展示了最终效果。视频中 Kakoune 的状态栏(modeline)被裁剪了,对此我深表歉意。我不知道原因,也不想重录视频,因为被裁剪的状态栏依然清晰可辨。我本可以实现一些保护措施,比如检查 projects 文件是否存在,或者添加 :project-delete 命令,但我对目前的状态很满意。欢迎提出任何建议。

Written by Jayesh Bhoot 作者:Jayesh Bhoot