前言
继上一篇 keyd 入门文章后,关于 Kanata 的文章也来了(比计划要快)。如果你的需求复杂,或要求跨平台,我都强烈建议你迁移到 Kanata 上。它可以看作 Rust 版的 Kmonad。而 Kmonad 又可以看作软件版的 QMK。它们基本包含了 QMK 的全部高级设计和映射定制能力,甚至更加强大。
这是一篇探索 Kanata 安装、配置的新手向教程,过程十分简单!
以上提到的 QMK 是一个知名的键盘开源固件,大量客制化和商业键盘产品都基于它。
键盘
本文将以一个 61 键的小键盘为例,它长这样:

如果你第一次见到键位如此少的键盘,不必惊讶。在客制化圈子这类键盘很常见。它没有 F1-F12 功能键、没有方向键。没有导航/编辑键区。连删除键都没有。
在如此精简的布局下自定义就非常有必要的。配置得好是也是十分心应手的,不会差全尺寸键盘太多。如果你使用的是 108 键位的全尺寸键盘,本文仍然对你会有帮助。例如许多时候左手方便完成的事情,不麻烦右手就是更好的(因为右手得离开鼠标)。
Kanata
Kanata 是本文的主角,不同的平台上用不同的后端处理输入以实现键盘映射的自定义。在 Windows 上它基于 LLHOOK 机制或 Interception 驱动。在 Linux 上基于 uinput。在 macoOS 上使用 Karabiner 驱动。不同的后端,安装/配置略有所不同,但这种差异的总体占比极小。
在 Linux 上是最完美的,因为 uinput 提供了完整的用户空间输入设备模拟能力。
Kanata 支持“层”、“层映射”、“和弦”、“宏”等功能,各种精巧的动作,可以用“变量”、“别名”等特性优化配置。它的配置格式相比于 keyd 稍微有些门槛。后文将循序渐进的介绍。
下载
在此之前,请确保已经安装好了 Kanata。在 NixOS、Arch Linux、Void Linux 这类非常新颖的 Linux 系统中,直接安装 kanata 包即可使用。在 Ubuntu 这类可能过旧的系统中,可自行编译或跟 Windows 那样下载预编译的二进制。
请从这个页面找到适合你的系统和硬件架构的版本(展开 Assets)。例如 Windows 用户可将 windows-binaries-x64.zip 下载后解压到本地,其中的 kanata_windows_tty_winIOv2_x64.exe 程序就是我们将要运行的目标。
运行
打开终端软件(或 cmd),输入程序文件的路径加 --cfg <配置文件路径> 参数来运行它。这里是一个最简配置的例子:
(defcfg
;; 让未写进 defsrc 的键正常工作
process-unmapped-keys yes
)
(defsrc)
将它命名为 kanata.kbd,保存到喜欢的路径中(例如 D:\Config\kanata\)。现在我们这样启动 Kanata:
D:\Kanata\kanata_windows_tty_winIOv2_x64.exe --cfg D:\Config\kanata\kanata.kbd
在 Linux 上用命令行启动时,可能需要 sudo 运行。从最小化权限章节了解如何免去 sudo。
如果没有输出 error 相关的日志,那么说明 Kanata 已经成功运行了。但此时它没有任何效果,因为我们的配置是空的。
Kanata 通常作为后台服务运行,我将在单独的自启动章节介绍。为了尽快进入配置教程,目前我们在命令行中前台运行它即可。当配置修改后,手动重启进程让其生效。
配置语法
Kanata 的配置不是 .ini 这类简单的键值对风格,它类似于 Lisp 的 S-表达式。所以我说它的门槛略高一点,毕竟 Lisp 是编程语言。但不用怕,Kanata 的配置并非编程代码。S-表示式由括号包裹,括号内是元素列表。第一个值通常表示命令/功能,后续的值表示参数。例如:
(defcfg process-unmapped-keys yes)
这个表达式的含义是:声明 defcfg 配置,添加了 process-unmapped-keys 和 yes 两个参数。具体而言,我们用 defcfg 来定义全局配置。此处将 process-unmapped-keys 设置为 yes,让未写进 defsrc 的键也能正常工作。
元素本身也可以是一个列表(嵌套)。例如:
(defcfg
linux-dev ("device1" "device2")
)
这里的 defcfg 仍然只有两个参数,参数成对出现以作为单个配置项的键和值。若直接展开 linux-dev 后面的列表,那么 device2 将被错误的当作下一个配置项的键名。所以我们有必要将它们用括号包裹,作为一个“整体”。
也就是说 device1 和 device2 构成了一个纯粹的列表,作为 linux-dev 配置项的“值”。我们通常将成对的构成单个配置项作为独立的一行,例如:
(defcfg
process-unmapped-keys yes # <- 这是第一个全局配置项,让未写进 defsrc 的键正常工作
linux-dev ("device1" "device2") # <- 这也是一个全局配置项,指定了 Linux 上注册的输入设备
)
被嵌套的列表有时候不是纯粹的值,例如它的第一个元素可能是功能而后续元素是该功能的参数。在配置嵌套动作时很常见。理解 S-表达式的嵌套很重要,某些复杂场景中嵌套可以发挥巨大的作用。
基本配置
仍以本教程初始的配置为例子:
(defcfg
;; 让未写进 defsrc 的键正常工作
process-unmapped-keys yes
)
(defsrc)
一个最基础的配置,只能有也必须要有一个 defsrc(即便它是空的)。上面有介绍过 defcfg,这其实是一个可选配置。它是用于定义全局配置项的地方,有效参数必须是成对的结构(键和值)。
现在我们开始对 defsrc 动刀:
;; 向 defsrc 添加内容,声明输入按键的列表
(defsrc
a s d f
)
;; 定义第一个层,将 defsrc 中的按键映射为大写
(deflayer start
1 2 3 4
)
现在重启进程让配置生效,你会发现按下 A、S、D、F 键时,输出的却是 1、2、3、4。如注释所述,我们在 defsrc 中声明了需要映射的按键列表(“源”输入)。然后在 deflayer 中定义了与之一一对应的映射关系。注意 deflayer 的第一个参数 start,它并非映射的一部分,它指的是层的名称。
参数是否换行,都不影响 S-表达式结构的正确性。有些用空格,有些换行,是为了更方便我们组织配置。
就在刚才,我们已经简单的尝试了一个映射相关的配置。如上所示,映射的关键是“层”,它就好似“源”的目标输出一般。接下来我们将继续深入“层”的概念。
记得将 deflayer 整个删除,以恢复正常按键。
层
层(layer)是 Kanata 最重要的核心概念之一。它包含了与 defsrc 中声明的按键一一对应的映射动作的列表。每个层都有一个名字(例如 start),我们通过名字来激活它。稍等,上面章节的配置似乎没有任何激活操作?没错,因为配置文件中定义的第一个层会自动激活(作为初始层)。
我们延续基本配置章节的例子,对初始层小改的同时添加第二个层:
(deflayer start
(layer-while-held second) 2 3 4 ;; 第一个按键的映射改成了激活 second 层的动作
)
(deflayer second ;; 第二个层,名字为 second
_ w e r ;; 映射为新的字母
)
现在,我们按 S、D、F 键时,输出的仍然是 2、3、4。但一旦“按住” A 键,就会激活 second 层。此时再按下 S、D、F 键就会输出的 w、e、r。这是第二个层配置的映射,和第一个层不再相关。
这里还隐含了两个概念:
layer-while-held:一个按键动作(Action),可以让我们在按住时激活指定的层。_符号:作为“透明键”,在此处会保持原键功能不变。
关于第一个概念,我们将在独立的短按/长按章节介绍。此处重点介绍与层相关的 _ 系列符号。其实很好理解,由于在初始层激活 second 层时 A 键已被按住了(占用了)。所以第二个层对 A 键没有映射的必要了。这里的 _ 类似于一个占位符,但不完全等同。它的映射实际上会“穿透”到下一层的对应位置上。
这是进一步使用 _ 的例子:
(deflayer second ;; 第二个层,名字为 second
_ w _ _ ;; 映射第二个键为新字母
)
现在激活 second 层时,只有 S 键被映射为 w 了。D、F 键仍然输出 3、4,因为它们被 _ 穿透回到了 start 层上。注意:层与层之间是覆盖的关系,当前激活的层在最上。最底层就是 defsrc 中所声明按键的原始功能。其次是初始层。所以上面的例子穿透到了初始层的映射上。
有关层的内容我已不想再讲更多了,一方面是为节省篇幅,更重要的是我并不使用层。没错,层很重要,但它有个替代品。在进入下一个章节前,我想告诉你们我为何很少使用层。这是一个例子:
(defsrc
grv 1 2 3 4 5 6 7 8 9 0 - = bspc
tab q w e r t y u i o p [ ] \
caps a s d f g h j k l ; ' ret
lsft z x c v b n m , . / rsft
lctl lmet lalt spc ralt rmet rctl
)
(deflayer dvorak
grv 1 2 3 4 5 6 7 8 9 0 [ ] bspc
tab ' , . p y f g c r l / = \
caps a o e u i d h t n s - ret
lsft ; q j k x b m w v z rsft
lctl lmet lalt spc ralt rmet rctl
)
上面是层的典型用法。将几乎全部按键,按照布局排布出来。将一个完整布局,映射为另一种(如 dvorak,即德沃夏克)。它类似于 keyd 的“布局”概念。当我们不需要修改那么全的映射时,当我们有多个层时,就会带来模板式重复(如果只是映射少量按键,会有大量的 _)。
对于修改布局,它很有用。但少量改键加多层的玩法,它强制完整的「输入-输出」对应就显得死板。所以接下来将要介绍的“层映射”可能是更实用的,当我们不需要如此全面的修改按键映射时。
层映射
层映射(layermap)是定义层的另一种方法,它完全忽略 defsrc,直接将「输入-输出」的映射关系写在一起。这是一个将 WASD 映射为方向键的例子:
(deflayermap (arrows)
w up
a left
s down
d right
)
我们现在不再需要此前定义的 deflayer 了,把它们删掉。此外 defsrc 中也不再需要声明任何按键,留空它的同时将 process-unmapped-keys 配置为 yes。
在大多数键盘操控的游戏里,WASD 通常是默认的移动键(类似于真正的方向键)。这是因为方向键在键盘右侧,而我们的右手要使用鼠标。让我们用 Caps Lock 这个黄金位置的“搭档”激活它:
(deflayermap (base)
caps (tap-hold-press 180 180 caps (layer-while-held arrows))
)
上述配置的 tap-hold-press 动作有 4 个参数,在后续章节中我们会单独介绍它。简单来说,它会在短按时输出 Caps Lock 原键功能,长按时激活 arrows 层。

现在按住 Caps Lock 键激活我们的 arrows 层,在这个层里 WASD 键被重新映射为方向键。几乎任意小巧的键盘,我们都能用一只左手轻易的完成方向键操作。
短按/长按
在层映射章节中,我们用过一个名为 tap-hold-press 的按键动作。它是 tap-hold 的变体,是最常用的高级动作之一。在该配置中,我们长按以激活 arrows 层。如何理解它呢?很简单,我们将 tap-hold 拆开来看:它是 tap(轻按)和 hold(长按)的组合。这里我们主要用它配置长按动作以执行激活层的操作。
将具体的配置 tap-hold-press 180 180 caps (layer-while-held arrows) 拆分开:
tap-hold-press:动作的名称。180:第一个参数,代表某个超时时间。180:第二个参数,代表另一个超时时间。caps:第三个参数,代表短按时的动作(或按键)。(layer-while-held arrows):第四个参数,代表长按时的动作。
我们暂时忽略两个超时参数,从短按和长按的动作配置讲起。首先是短按的动作配置成了 caps,也就是输出 Caps Lock 的功能(在这里是原键)。这个非常容易理解,无需额外解释。然后是长按的动作配置,它是一个嵌套的 S-表达式。它执行了 layer-while-held 动作,用于激活指定的层。而 arrows 就是它的参数,即被激活层的名字。
所以此配置的意思就是:短按 Caps Lock 键时输出原键功能,长按时激活 arrows 层。
这里就体现了一次 S-表达式的动作嵌套,层激活被嵌套进了短按/长按里。
那么两个超时参数呢?在开始之前,我们不得不先提及键盘的一个原生功能。当我们长按 A 键时,默认会得到 aaaaaa... 这种重复输出。那么问题来了,我们用 tap-hold 将长按配置为另一个动作了,岂不是把这种默认行为覆盖了?是的没错,但第一个超时参数就是为此需求准备的。
第一个参数值的单位是毫秒,此处是 180。它表示:当你在 180 毫秒内,二次按下这个键并按住时,就会重复输出短按动作,而不再触发长按动作。例如:
(deflayermap (base)
a (tap-hold 180 180 a b)
)
通过以上讲解,我们能轻易的明白。它配置的是:短按 A 键输出 A 键原有功能,长按时输出 B 键功能。现在,当我们正常长按 A 时,它会持续的输出 bbbbbb...。但如果我们第一次按下 A 键后松开然后 180 毫秒内再次按下 A 键并按住,它就会重复输出 aaaaaa...。
很好理解,多次短按本就是在表达想重复的意图。
那么,第二个超时参数是什么意思呢?它更容易理解,此时间用于判定我们是长按还是短按。超出 180 毫秒,就触发长按。低于这个时间抬起了按键,就触发短按动作。
最后,我们使用的是 tap-hold-press 这个变体,和基础 tap-hold 有什么差异?简单来说,它更适合用于修饰键的长按类型。我们可以想一下:
当我们按住 Ctrl 时,按下另一个键应立即触发组合键功能。而不必要等待一个固定的超时时间。类似的,当我们长按 Caps Lock 这样的键激活另一个层时,我们也应该期待另一个键立即触发动作。通常对 A、S、D、F 这类直接参与打字的键,固定的超时才有必要。因为快速打字时是有可能同时按下多个字母键的,但它们一般不用于修饰和组合。
简单来说 tap-hold-press 变体多了一个额外的「提前触发」长按动作的契机。
按键的触发模式还有更多类型,例如:一次性动作、连点动作、fork 动作等等。本文暂未介绍。
别名和变量
在上面的配置中,我们将输入按键和输出动作直接写在 deflayermap 中。当这类配置越来越多,越来越杂时,会非常不直观。或者我们要在不同的按键/不同的层多次使用某个相同操作时,怎么复用呢?这就是别名(alias)的用途了。将上面的操作提取到别名中:
;; 声明别名
(defalias
cap-arrows (tap-hold-press 180 180 caps (layer-while-held arrows))
)
(deflayermap (base)
caps @cap-arrows
)
现在这套操作被我们命名为 cap-arrows 放在 defalias 中。在 deflayermap 中通过前缀 @ 符号来引用它。这可以让复杂操作具备语义化的名称,也能让我们在其它地方复用它。
再假设我们的配置中有多个 tap-hold 动作,但部分时间参数是一样的。如果每一个都重复一次 180,一旦发生修改就不好统一管理。我们可以定义变量(var),然后在参数位置引用变量:
;; 定义变量
(defvar
repress-timeout 180
hold-timeout 180
)
(defalias
cap-arrows (tap-hold-press $repress-timeout $hold-timeout caps (layer-while-held arrows))
)
引用变量时使用 $ 前缀符号。现在我们只需要修改变量的值,就能统一修改所有引用它的参数了。同时,由于变量名具有语义化的作用,我们也能更清晰的知道这个参数的意义。
别名和变量都没有功能上的作用,它们主要用于优化配置:让配置更清晰,易于维护。它们的使用完全取决于个人习惯。对于复杂配置,合理的使用绝对比不用好。
和弦与组合
虽然和弦(chords)可能被部分人当作组合(combos),但严格来说它们是有区别的。和弦是无序的,可无需修饰键参与。而组合是有序的,通常需要修饰键参与。我们先来看和弦:
(defcfg
concurrent-tap-hold yes ;; <- defchordsv2 需要它
;; 省略其它配置……
)
;; 定义全局和弦
(defchordsv2
;; 编辑(打字)快捷操作
(d f) bspc 50 all-released () ;; 删除左侧字符
(j k) del 50 all-released () ;; 删除右侧字符
)
上述配置中的 concurrent-tap-hold 配置是必要的,否则 defchordsv2 定义的和弦可能无法正常工作。
这里通过 defchordsv2 定义了两个和弦。当我们同时按下 D 和 F 键,会触发退格键(Backspace,简写为 bspc)功能删除左侧字符。同时按下 J 和 K 键触发删除键(Delete,简写为 del)功能删除右侧字符。如下:

因为 F̠ 和 J̠ 分别是左右手食指的定位键,相比于退格和删除键,它让删除操作不打断标准指法。一个用于删除左侧字符,一个用于删除右侧字符,也十分自然。
我们再来看看 defchordsv2 中的具体配置。每一个有效配置包含 5 个参数,将其中一个拆解:
(d f):被组合的按键列表。bspc:触发的动作(此处为退格键名)。50:所有参与的键都被按下后,多久触发和弦(毫秒)。all-released:释放时机,此处为所有参与键都释放后释放和弦。():禁用的层列表,此处留空(没有禁用任何层)。
这里使用的 defchordsv2 定义的和弦是全局的,和层无关。还有一个 defchords 可以定义和弦,可以按层定义。本章节暂未做介绍。
说完了和弦,我们再来说说组合。它和各种图形环境、桌面软件的快捷键概念类似。先按下修饰键(例如 Ctrl),然后按下另一个键,触发组合动作。它相比于和弦更为简洁:
;; 用 Caps Lock 模拟 Ctrl 常用组合操作
(deflayermap (cap-zxcv)
z C-z
x C-x
c C-c
v C-v
)
在这个例子中,我们定义了一个层映射。它把原生的 Ctrl 常用组合键(复制、剪切、粘贴、撤销)映射到 Caps Lock 键上。注意看,被映射的动作由 C 前缀和 - 符号连接具体按键。这里的 C 实际上就是修饰键 Ctrl 的缩写。完整的如下:
| 功能 | 左侧键 (缩写) | 左侧键(说明) | 右侧键 (缩写) | 右侧键(说明) |
|---|---|---|---|---|
| Control | C | 左 Ctrl | RC | 右 Ctrl |
| Alt | A | 左 Alt | RA / AG | 右 Alt |
| Shift | S | 左 Shift | RS | 右 Shift |
| Meta | M | 左 Meta | RM | 右 Meta |
这里有个认知要点要区分开。本章节我们定义的和弦,是“输入”(即我们按下的键)。而此处定义的组合是“输出”(即触发的动作)。以上配置中的输出组合,本质是对其它操作的复用(例如原生组合按键)。
若要修改输入组合(带修饰键)的映射,可以使用 defoverridesv2 来简单配置。本章节暂未介绍。
宏
Kanata 的宏(macro)类似于现代键盘或鼠标设备的宏功能,它可以把预先配置的动作序列重新“播放”出来。以下是一个实用例子:
;; 快捷生成成对符号的层
(deflayermap (pairs-symbols)
apos (macro S-apos S-apos left) ;; 引号对
9 (macro S-9 S-0 left) ;; 括号对
lbrc (macro lbrc rbrc left) ;; 中括号
)
在这个层中,我们按下撇号键(Apostrophe,简写为 apos)时,会触发一个宏。这个宏会依次输出 Shift + Apostrophe(第一个引号),然后再输出一次 Shift + Apostrophe(第二个引号),最后输出左箭头键(left)将光标移动到引号中间。其余两个也是类似的。它们可以简化输入成对符号的操作,类似于 VS Code 中的片段。
此时我们的按键所映射的不再是简单的激活、长按这一类动作,而是连续的动作序列。宏还可以在动作间插入延迟时间,让我们感受到动作执行的过程。例如:
(defalias
copyall-next-window (macro C-a C-c 500 A-tab C-v)
)
若将按键映射到这个别名上,那么按下它时会先执行 Ctrl + A(全选)和 Ctrl + C(复制),然后等待 500 毫秒,再执行 Alt + Tab(切换窗口)和 Ctrl + V(粘贴)。这可以让我们快速在多个窗口间复制粘贴内容。由于我们等待了 500 毫秒,所以你会看到全选完成后要等一会儿才切换窗口。
宏还支持录制,以及鼠标控制。本教程暂未介绍这些内容。宏的作用不仅仅是“改键”,它可以简化许多过程。包括日常使用电脑的各种动作,游戏中的复杂操作等。
指定设备
默认 Kanata 会拦截检测到的所有键盘,无相关配置是直接可用的。但如果你有多个键盘且布局不同,那么就很有必要让特定配置只作用于特定的设备了。在 Linux 上,我们将键盘对应的 dev 设备路径写在 linux-dev 配置项中:
(defcfg
;; 指定设备
linux-dev (
"/dev/input/by-path/pci-0000:00:00.0-usb-0:0:0.0-event-kbd"
"/dev/input/by-path/pci-0000:00:00.0-usb-0:0:0.1-event-kbd"
)
)
以上是一个真实案例匿名化处理后的配置。同一个设备文件有多种不同的路径,例如 /dev/input/eventX、/dev/input/by-id/xxx、/dev/input/by-path/xxx 等等。通常来说,by-id 和 by-path 这类路径是比较稳定的,不会因为设备发现顺序改变而改变。而 eventX 这类路径可能会变动,所以不建议使用。
这里是一个多行命令,可复制后直接在终端执行:
for id_link in /dev/input/by-id/*-kbd; do
[ -e "$id_link" ] || continue
event_node=$(readlink -f "$id_link")
event_name=$(basename "$event_node")
path_link=$(find /dev/input/by-path/ -lname "*$event_name" | head -n 1)
echo -e "ID 路径\t\t: $id_link"
echo -e "Path 路径\t: ${path_link:-'未找到对应 Path'}"
echo -e "内核节点\t: $event_node\n"
done
它会列出所有键盘设备的 by-id 和 by-path 路径,其中 by-id 的路径能轻易分辨具体的设备(通常包含品牌或型号)。然后在配置中写 by-path 更加匿名化,分享配置时不暴露设备信息。
有时候你会看到一个键盘有多个设备,这是正常的,可全部添加到配置中。你还可能看到鼠标也被列举出来了,这是因为鼠标也有按键功能也会模拟成键盘输入设备,无视即可。
当你看到同一个键盘有多个设备文件,你通常有必要都添加到配置中。因为一些键盘为了实现全键无冲,会用多个逻辑输入节点来处理更多的按键组合。如果你不添加其它“看似无用”的设备文件,那么当你配置了 7 个或以上按键数量的和弦或组合键时,它可能永远不会被映射。
很遗憾,在 Windows 上无法指定设备。
自启动
在提供了 kanata 包的 Linux 发行版中,通常已经预设了服务脚本和配置文件路径。让服务自启动即可。否则你需要手动创建 Systemd 服务。如果是 NixOS,请添加这些配置:
{
# 启用 Kanata(按键映射)
services.kanata = {
enable = true;
keyboards = {
"61" = { # <- 定义一个配置名,例如 "61"
configFile = "/etc/kanata/61.kbd"; # <- 指定一个配置文件路径
};
};
};
}
然后将配置文件写在 /etc/kanata/61.kbd 中即可(可能要手动创建目录)。生成的服务名称为 kanata-61,可通过 systemctl 命令管理它。
在 Windows 上,会稍微“丑陋”一点。你通常不能用 Linux 的思维将 Kanata 进程服务化管理。因为 Windows 标准服务有 Session 0 隔离,会导致即使 Kanata 作为服务运行了,它也无法拦截修改你的任何输入。说简单点就是:核心功能不工作。
解决办法很简单,让 Kanata 作为普通自启动程序。按下 Win + R 键,输入 shell:startup 打开启动文件夹(路径类似于 C:\Users\你的用户名\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup)。创建 kanata_windows_gui_winIOv2_x64.exe 文件的快捷方式,将快捷方式放在这个文件夹中即可:

注意以上截图,我们在快捷方式的属性中,编辑过目标。需要加上 --cfg 参数以及配置文件的路径。我将这个快捷方式命名为了 Kanata_GUI,因为我们的启动程序是带 GUI 的。当然实际上它没有任何窗口,仅创建一个托盘图标。右键托盘图标可以进行一些简单的管理,如重载配置,选择配置或退出。
相比于 Linux 的服务,这样自启动的 Windows 程序是无法在登录前就工作的。
最小化权限
本章节仅适用于 Linux。
一般情况下 Kanata 作为系统服务运行是最合适的,因为它可以在登录前就启动。但如果你要用 cmd 功能执行外部程序,或有其它令人不放心的理由,也是能让以它普通权限运行的。首先把自己添加到两个必要的组:
sudo usermod -aG input $USER
sudo usermod -aG uinput $USER
组不存在就先用 sudo groupadd uinput 命令创建。然后添加 udev 规则(在 /etc/udev/rules.d 或 /lib/udev/rules.d 目录):
KERNEL=="uinput", MODE="0660", GROUP="uinput", OPTIONS+="static_node=uinput"
现在以自己的用户权限(无需 sudo)启动的 Kanata 进程,也能访问 input 和 uinput 子系统注入事件了。接下来手动创建用户级别的 Systemd 服务即可(或用自己的方式自启动)。
我本人仍然认为这是没必要的。我不会使用它启动外部程序,我也不希望它作为用户服务运行。
意外情况
某些时候,错误的配置可能导致严重后果(例如键盘无法正常使用,或无法恢复配置)。当然,这属于极端情况。正常来讲,错误的配置要么无效,要么不影响下次修改。但一旦真的出现了极端情况,停止 Kanata 进程就是恢复键盘的后路。结束 Kanata 方法如下:
同时按下 Esc + Ctrl + Space(空格)键,即可让 Kanata 自动退出。一切配置都会失效。这时候你就可以轻易还原配置了。如果你发现 Kanata 进程仍然存在,例如它又自动启动了。可能是 init 的自动重启策略,按照这里的方法将它禁用。
允许 Kanata 进程关闭自己是有必要的,自以为是的重启策略反而造成问题。
结束语
这就是 Kanata 的入门教程了。由于篇幅太长,我花了数次更新才完成。仍然有一些十分有用的功能没有介绍到,高级的使用模式没有介绍。毕竟这个工具比 keyd 还是复杂不少。而此项目所谓的「配置指南」实际上类似于手册,适合查询功能说明而并不适合入门。本教程的例子并一定实用,它更多的是为了突出功能设计目的和用法。
我的 Kanata 配置:Hentioe/dotfiles/kanata/61.kbd
番茄钟:Tauri 跨端应用开发前景的强大展现力
前言 长久以来本地客户端开发(包括桌面、移动端)都被认为没有前景了,尤其在国内这个论调严重得多。我个人其实仍看好本地客户端这个应用类型,同时我也看好 Web 的潜力。所以如果一个技术能将这两者结合,我就会很感兴趣。 本文的主角 Tauri 就是综合这二者优势的框架技术。相比于 Electron 它能
喵星 ICP 备案系统介绍
前言 最近收到某个神秘组织的委托,让我开发一套面向喵星的网站备案系统。在遥远的喵星,有一种高度智慧的猫科文明——喵星人。它们通过访问部署在地球的网站了解地球人。其实地球上存在着大量喵星驻地球大使馆,但都隐藏极深。而近期联系我的就是附近某个使馆中的神秘喵星人,更多的不能再说了。 喵星与互联网 在中文网
