리눅스에서 키맵핑하기 Ver.2 - Kanata
키맵핑에 kmonad를 쓴다면서?
맞다. kmonad를 썼었다. (Kmonad 1탄과 Kmonad 2탄을 참고하자.) 딱 한번만 설정해두면 더 이상 건드릴 일이 없기 때문에 큰 불만은 없었다.
그러나, 딱 하나 신경쓰이는 부분이 있었으니…
그것은 바로, 패키지 업그레이드할 때마다 온 화면을 뒤덮는 kmonad의 haskell 의존 패키지 목록이다. 이게 참… 묘하게 신경쓰인다 말이다. 사실, kmonad가 haskell 기반이란 걸 인지하지 못했었는데, 도대체 어떤 패키지가 이렇게 많은 haskell 패키지를 쓰나 역추적하다가 이 사실을 알게 되었다.
그렇게 맘에 들지 않는 부분을 발견한 시점에 우연히 유사한 프로젝트인 kanata를 발견한 것이다.
게다가 kanata는 사용방법 측면에서 kmonad와 사실 상 거의 똑같다.
그럼에도 좀 더 좋은 점들을 가지고 있다.
그럼, 같이 kanata를 찍먹해보도록 하자.
Kanata 개요
kanata의 개발자는 kmonad 프로젝트에 기여하고 싶었으나, haskell에 대한 지식이 없었기에 별도의 rust 기반 프로젝트인 kanata를 개발했다고 한다1.
그는 kmonad로부터 영감을 받았기 때문에 .kbd 파일들을 설정하는 방식 측면에서 일부 변수들의 이름만 조금 다르고 거의 똑같다.
게다가 kanata는 1) 뛰어난 documentation을 가졌고, 2) config 파일 오류 검출 기능 면에서 더 뛰어나며, 3) 모든 OS (windows, mac, linux)에서 사용할 수 있다. 일단, 설치부터 하고 차근차근 강점들에 대해 살펴보자.
Kanata 설치
Kanata 설치는 여러 방식으로 가능하다. 다음 방식들 중 어떤 방식을 사용해도 무방하다.
- Source에서 직접 컴파일하기 (cargo 사용)
- Release된 pre-built executable 다운받기
- Repo에서 컴파일된 패키지 설치하기
Kanata를 repo에서 지원하는 배포판들. 생각보다 그 종류가 적은 편이다.
그러나 우리는 이들 중 1번 방식을 사용할 것이다. 이유가 있다. Github의 설치 메뉴얼을 보다보면 이런 내용이 나온다.
Feature flags
When either building yourself or using cargo install, you can add feature flags that enable functionality that is turned off by default.
kanata에 슈퍼파워(?)를 부여하는 feature flag를 쓸려면 source에서 직접 빌드하란 말이다.
우리가 사용할 kanata의 슈퍼파워는 cmd 기능이다.
cmd flag는 kanata를 통해 터미널 명령어들을 실행하는 단축키나 매크로를 정의할 수 있게 해준다.
안쓸 이유가 없지 않나?
그래서 우린 1번 방식을 쓰는 것이다.
자, 그럼 다음 순서를 따라 설치해보자.
cargo와 rust 설치하기
kanata는 rust로 작성되었다. 그래서 먼저 rust를 컴파일하기 위한 환경을 갖춰야 한다. rust 공식 사이트에서 제공하는 설치 스크립트를 사용하여 cargo와 rust를 설치해주자.
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | shsource pull 하기
cargo와 rust가 설치되었으면 kanata의 소스파일을 git pull 해주자.
git clone https://github.com/jtroo/kanata $HOME/kanatabuild 하기
다음 명령어를 실행하여 source 폴더로 이동 후 build 해주자.
cd $HOME/kanata # kanata source 폴더로 이동
cargo build --features cmd # cmd 옵션을 추가좋다.
build가 끝났으면 $HOME/kanata/target/debug/에 kanata 실행파일이 생성된 것을 알 수 있다.
will@nuclearLab:~/kanata/target/debug (main)$ ls -ll
total 85684
drwxr-xr-x 36 will will 4096 Nov 4 18:05 build
drwxr-xr-x 2 will will 65536 Nov 4 18:05 deps
drwxr-xr-x 2 will will 4096 Nov 4 18:05 examples
drwxr-xr-x 8 will will 4096 Nov 4 18:05 incremental
-rwxr-xr-x 2 will will 65219616 Nov 4 18:05 kanata # -> 이 파일이 우리가 빌드한 kanata 실행파일이다.
-rw-r--r-- 1 will will 4378 Nov 4 18:05 kanata.d
-rw-r--r-- 1 will will 4197 Nov 4 18:05 libkanata_state_machine.d
-rw-r--r-- 2 will will 22588528 Nov 4 18:05 libkanata_state_machine.rlib$PATH에 build된 kanata 등록하기
개인적으로 생성한 스크립트를 저장하는 폴더가 있는가?
그러니까, PATH에 등록해두고 개인 스크립트를 저장하는 곳이 있냐는 의미다.
있으면 그 폴더에 빌드된 kanata를 복사해주자.
혹시 그런 폴더를 만들어서 사용하지 않고 있다면, 이 포스팅을 참고하여 스크립트용 경로를 만들고 PATH에 등록하는 절차를 수행하자.
필자는 $HOME/.local/bin 경로를 개인 스크립트용으로 사용하고 있다.
그래서 다음의 스크립트로 kanata를 복사해주었다.
cp $HOME/kanata/target/debug/kanata $HOME/.local/bin/앞의 kanata를 복사하고 PATH에 정상적으로 등록이 되었다면, 다음의 명령어 실행 시 kanata 경로가 출력될 것이다.
which kanata필자는 다음처럼 경로가 잘 출력되었다.
will@nuclearLab:~ $ which kanata
/home/will/.local/bin/kanataKanata 사용 설정하기
Keyboard configuration 파일 작성하기
kmonad의 설정 방법과 똑같다. (키보드의 고유 명칭 확인하는 절차, 원래 키배열 1개, 실제 사용할 Main 키배열 1개, 커스텀으로 사용할 배열 다수, 커스텀 배열을 toggle하는 키 설정 등)
대신, 몇몇 변수나 기능의 이름이 다를 수 있다. 그러니 kmonad 설정 포스팅을 참고하여 설정을 진행하되, kanata 메뉴얼을 함께 보면서 변수나 기능의 이름만 적절하게 바꿔주면 된다.
설정 파일은 원하는 곳에 저장하면 되는데, 필자는 $HOME/.config/kanata 경로에 저장하였다.
최종 설정 파일(.kbd)은 다음과 같은 형태를 가지게 될 것이다.
(defcfg
linux-dev /dev/input/by-id/usb-RDR_Rainy_75-event-kbd
process-unmapped-keys yes
log-layer-changes no
danger-enable-cmd yes
concurrent-tap-hold yes
)
;; Variables
(defvar
tap-time 300
hold-time 300
chord-time 60
)
;; Actual keyboard layout
(defsrc
esc f1 f2 f3 f4 f5 f6 f7 f8 f9 f10 f11 f12 del home
grv 1 2 3 4 5 6 7 8 9 0 - = bspc end
tab q w e r t y u i o p [ ] \ pgup
caps a s d f g h j k l ; ' ret pgdn
lsft z x c v b n m , . / rsft up
lctl lmet lalt spc rctl left down rght
)
;; main layer
(deflayer main
esc f1 f2 f3 f4 f5 f6 f7 f8 f9 f10 f11 f12 del @num
grv 1 2 3 4 5 6 7 8 9 0 - = bspc end
tab q w e r t y u i o p [ ] \ pgup
@lyr1 a s d f g h j k l ; ' ret pgdn
lsft z x c v b n m , . / rsft up
lctl lmet lalt spc rctl left down rght
)
(deflayer layer-1
esc f1 f2 f3 f4 f5 f6 f7 f8 f9 f10 f11 f12 del @num
grv 1 2 3 4 5 6 7 8 9 0 - = del end
caps pgup w pgdn r t y u i o p home end \ pgup
@lyr1 a s d f g left down up right ; ' ret pgdn
lsft z x c v b n m , . / rsft up
lctl lmet lalt spc rctl left down rght
)
(deflayer layer-num
esc f1 f2 f3 f4 f5 f6 f7 f8 f9 f10 f11 f12 del @num
grv 1 2 3 4 5 6 7 8 9 0 - = bspc end
tab 7 8 9 r t y u i o p [ ] \ pgup
caps 4 5 6 f g h j k l ; ' ret pgdn
lsft 1 2 3 v b n m , . / rsft up
lctl lmet 0 spc rctl left down rght
)
;; toggle
(defalias
num (layer-while-held layer-num)
lyr1 (layer-while-held layer-1)
)config에 문법 오류가 없다면 다음의 명령어를 실행했을 때 오류없이 정상 작동해야 한다.
sudo kanata -c $HOME/.config/kanata/rainy75.kbd혹시나 문법 오류가 존재한다면 kanata가 어느 부분이 틀렸는지 지적해줄 것이다.
sudo 권한 없이 실행 가능하게 만들기
기본적으로 kanata나 kmonad 모두 uinput 모듈에 대한 접근 권한을 필요로 한다. 그래서 sudo가 없이 실행이 안되는 것이다.
kmonad에서는 uinput에 권한을 가진 그룹을 만들고 내 사용자(필자는 will)를 해당 그룹에 포함하는 방식은 실패했었다. 그런데 kanata 공식 가이드에서도 똑같은 방식을 권하고 있는게 아닌가? 공식 가이드를 따라 다시 시도해봤지만, 여전히 실패한다.
그래서 kmonad에서 한 것처럼 systemd service를 생성해야하나 하다가, 이걸 어떻게든 해결하고 싶었다.
이리저리 구글링하면서 결국 원인을 찾아 해결했다!
해결책은 uinput group을 system 그룹으로 생성하는 것이다.
다음의 명령어를 실행하여 uinput을 시스템 그룹으로 생성하고, $USER를 input과 uinput 그룹에 추가해준다.
sudo groupadd --system uinput
sudo usermod -aG uinput $USER
sudo usermod -aG input $USER그리고 재부팅 해주자.
재부팅 후, 다음처럼 udev rule을 만들어주자.
여기선 rule 이름을 99-uinput.rules로 지었다.
다음처럼 작성하고 저장해주자.
KERNEL=="uinput", MODE:="0660", GROUP:="uinput", SUBSYSTEM=="misc"좋다.
다음으로 uinput 모듈이 부팅 시 자동으로 load되도록 해주자.
echo uinput | sudo tee /etc/modules-load.d/uinput.conf이걸로 되었다. 마지막으로 재부팅하고, 터미널에서 sudo를 빼고 kanata를 실행해보자.
kanata -c $HOME/.config/kanata/rainy75.kbd정상적으로 작동한다면 성공한 것이다. 이제 남은 것은 부팅 시 자동으로 이 kanata가 실행되도록 만드는 것이다.
자동 실행 설정하기
Autostart 방식은 개인이 사용하는 배포판마다 다르다. Arch 가이드를 참고하여 각자 배포판에 맞는 방식으로 autostart에 등록해주자.
필자는 사용중인 wm인 dwm의 autostart 항목에 다음처럼 추가해주었다.
#!/bin/sh
kanata -c ".config/kanata/rainy75.kbd"축하한다. 지금까지 잘 따라왔다면, 재부팅할 때마다 자동으로 kanata가 내가 지정한 키맵핑 파일을 load한 채 데몬으로 동작하게 될 것이다.
Kanata의 강점
이미 설정 과정에 알게 되었을테지만, kanata는 kmonad보다 다음과 같은 몇 가지 측면에서 더 좋다.
뛰어난 documentation
자세한 설치 가이드 제공, 설정 방식에 대한 상세한 설명, 설정 파일 샘플 제공, sudo 권한없이 실행을 위한 방식 제공 등 documentation 관리가 아주 잘 되어있다. 덕분에 kmonad에서처럼 온갖 유튜브와 구글을 뒤져가며 사용방법을 익히지 않아도 된다.
설정파일 오류 검출 기능과 online simulator
kmonad는 config에 오류가 있으면 그냥 실행이 안된다. 어디가 틀렸는지 친절하게 알려주는 법이 없다. 그러나, 우리의 친절한 kanata는 두 가지 방식으로 오류를 진단할 수 있게 해준다.
먼저, 틀린 config을 실행하려하면 정확하게 어디가 틀렸는지를 정확히 지적해준다. (kanata의 개발자는, 아마도, rust의 친절한 디버깅 전략을 수용한 것 같다.)
will@nuclearLab:~/.config/kanata (main)$ kanata -c ~/.config/kanata/rainy75_.kbd
19:21:41.4345 [INFO] kanata v1.10.0-prerelease-3 starting
19:21:41.4354 [ERROR] × Error in configuration
╭─[/home/will/.config/kanata/rainy75_.kbd:2:1]
2 │ linux-dev /dev/input/by-id/usb-RDR_Rainy_75-event-kbd
3 │ process-unmapped-key yes
· ──────────┬─────────
· ╰── Error here
4 │ log-layer-change no
╰────
help: Unknown defcfg option process-unmapped-key
For more info, see the configuration guide:
https://github.com/jtroo/kanata/blob/main/docs/config.adoc
19:21:41.4357 [ERROR] failed to parse file
Press enter to exit한술 더 떠서 kanata의 개발자는 오류를 진단하는 웹페이지(online simulator)를 운영하고 있다.
여기에 config 파일을 통째로 붙여넣으면 어디가 틀렸나 지적해준다. 또한, 변경한 키 스트로크를 테스트 해볼 수도 있다.
모든 OS에서 사용 가능!
개인적으로 언급하고 싶지 않은 부분이지만, kanata는 windows, macOS에서도 동작한다.
혹시 회사의 업무로 인해 windows를 강요당하는 사람이라면!! 리눅스의 쾌적한 키보드 맵핑정도는 윈도우에서도 누릴 수 있다는 의미이다. (물론, 그럼에도 필자는 가상화로 windows를 쓰는 방식을 택할 것이다.)
마무리하며
오늘은 kanata를 통해 키보드 맵핑을 하는 방법을 다뤘다. 이를 통해 QMK/VIA를 지원하지 않는 키보드라 하더라도, 우리는 그와 동일한 기능을 가질 수 있게 되었다.
이번 포스팅에서 자세하게 다루지 않았지만, 단순 toggle-layering 뿐만 아니라 매크로 기능과 cmd 실행 기능 등 많은 고급기능들이 있으니 한번 사용해보길 추천한다. 필자 또한 이런 세부 기능들을 익힌 후 추가로 kanata 포스팅을 이어나갈 계획이다. 특히, 슈퍼파워라고 했던 cmd 기능에 대해서 말이다.