VIA처럼 키맵핑하기 1 - kmonad 설치 및 설정

VIA처럼 키맵핑하기 1 - kmonad 설치 및 설정

리눅스에서 VIA처럼 키맵핑이 가능할까?

나의 레이니 75
나의 레이니 75

레이니 75 키보드를 사용하면서 처음으로 VIA를 사용해보았다. 자주 사용하는 화살표를 vim처럼 [h, j, k, l]로 바꾸고, page up/down을 [q, e]로 바꾸고, 영문 키패드에 숫자를 입력할 수 있는 numpad를 만들어 넣었다. VIA를 사용하면 아주 손쉽게 이런 변경이 가능하다. VIA 덕분에 레이니의 적은 키 개수는 오히려 공간 절약이라는 강점으로 바뀌게 된다.

그러나 명암은 늘 공존한다. 60Hz 주사율의 휴대폰을 쓰다가 120Hz 주사율의 휴대폰을 사용하면 그 차이를 못느끼지만, 역으로 120Hz를 쓰다 60Hz를 쓰면 그렇게 신경에 거슬린다고 하지 않는가? 레이니의 단축키 설정에 익숙해진 나는 다른 키보드를 쓸때도 그 맵핑이 존재한다고 착각하여 사용하려고 한다. 그래서 굉장한 불편함을 느끼게 되었다. 특히 capslock을 function키로 사용하고 있기 때문에, 다른 키보드들에서 계속하여 대문자 입력을 껐다, 켰다하게 된다. 😵‍💫

참고 참다가 결국 대안을 물색하게 됐고, 언제나 그렇듯 리눅스는 답을 가지고 있었다. 그것은 바로 kmonad였다. 그래서, 오늘 포스팅의 주제는 kmonad를 사용하여 VIA처럼 low level에서 키맵핑하기다.

kmonad 기능에 대한 간단한 설명

kmonad는 VIA처럼 low level에서 키맵핑을 바꾸는 패키지다. 작동방식은 VIA와 똑같다. 다만, 하드웨어에 해당 사항을 저장해두는 것이 아니라 소프트웨어 수준에서 이를 저장한다. 그래서 Bios에서는 이 키맵핑이 동작하지 않는다. kmond는 간단하게 설명하자면 다음의 기능을 한다.

  1. function키를 지정한다. (e.g. capslock을 func1으로, right control을 func2로 지정한다)
  2. 1개의 base layer와 1개 이상의 custom layer를 정의한다.
  3. 특정 function키에 특정 custom layer 활성화 기능을 연결한다. (toggle 방식도 되고, 완전히 변경했다 돌아오는 방식도 된다.)
  4. 원한다면, base layer의 특정 키를 완전히 다른 키로 바꾸는 것도 가능하다. (e.g. capslock을 esc로 바꾸는 것도 가능)

공식 github page

kmonad를 사용하기 위해서 공식 github page를 참고할 필요가 있다. 다른 패키지들에 비해 생각보다 설정하는 방식이 까다로운 편이기도하고, 공식 github page로부터 몇 가지 template을 받아야 하기 때문이다. 공식 github page 를 참고하자.

kmonad 설치하고 설정하기

본 포스팅에서는 필자가 집에서 사용하는 anne pro2 키보드에 kmonad를 적용해보려고 한다. (물론, anne pro2도 제조사에서 제공하는 소프트웨어를 사용해 자유롭게 키맵핑을 할 수 있지만, 키맵핑 프로그램을 윈도우에서 사용해야해서 리눅스 유저로써 불편함이 있다.)

kmonad를 적용해볼 앤프로 2
kmonad를 적용해볼 앤프로 2

kmonad 설치

각자 배포판에 따라 kmonad를 설치해준다. Arch linux, GNU Guix, Void linux, 그리고 Nix os는 공식 repo에서 이를 공식적으로 지원하고 있다. 많은 사람들이 사용하는 debian 계열(e.g. 우분투, 데비안, 칼리 등등)은 안타깝지만 공식 repo를 통해선 설치할 수 없고, source를 받아서 stack을 통해 직접 빌드하고 설치해야한다.

arch linux의 경우, 다음의 명령어로 설치한다.

bash
sudo pacman -S kmonad

debian 계열의 경우, stack을 사용하여 직접 빌드하는 방법 에 명시된대로 1)haskel stack을 먼저 설치하고, 2)kmonad를 빌드해주면 된다.

1)haskel stack 설치하기
haskelstack 공식 사이트 에서 제공하는 설치 스크립트를 통해 stack을 설치한다.

bash
curl -sSL https://get.haskellstack.org/ | sh

2)stack을 사용하여 kmonad 빌드하기
여기선 build 후 자동으로 PATH에 설치까지 수행하는 stack install을 사용한다. 다음 명령어를 다운받은 source directory에서 실행하자.

bash
stack install # Builds *and* copies

install이 완료되면 which를 통해 kmonad가 정상적으로 PATH에 등록되었는지 확인해주자. 확인이 안된다면 위 절차를 다시 차근차근 수행해보자.

bash
which kmonad

kmonad config template 가져오기

공식 github repo에가서 우리는 두 개의 파일을 다운받아야 한다.

  1. kmonad/keymap/tutorial.kbd
  2. kmonad/keymap/template/iso_100.kbd: 여기서는 iso 100% 배열을 다운받았으나, 본인이 사용하는 키보드와 더 잘맞는 배열이 있다면 그걸 받아도 된다. (물론, 이러나 저러나 내 키보드에 맞게 고치긴 해야한다.)

이 두 파일을 원하는 곳에 저장하자. 필자는 ~/.config/kmonad에 저장하고, template으로 사용할 iso_100.kbd의 이름을 annepro2.kbd로 변경하였다.

첫번째 파일인 tutorial.kbd는 kmonad를 설정하는 방법에 대해 자세히 서술하고 있는데, 간단히 정리하자면 설정하는 순서는 다음과 같다.

  1. 내 키보드 장치 이름을 확인한다.
  2. defsrc를 설정한다.
  3. deflayer base를 설정한다.
  4. deflayer customlayer를 설정한다.
  5. layer activation을 설정한다.

두번째 파일인 iso_100.kbd는 iso_100% 키보드의 레이아웃을 담고 있는 템플릿으로, 그 내용은 이렇게 생겼다.

iso_100.kbd
#| --------------------------------------------------------------------------

                     KMonad: ISO 100% template

  This file contains the `defsrc' configuration for a standard
  ISO 100% keyboard, modelled on a standard European model.

  Copy out the `defsrc' layer to start your own keyboard configuration. Copy
  out the `deflayer' template to easily start a new layer with matching
  `transparent' buttons. `102d', the key on the right of the left shift key,
  which is named this way because it used to be the 102nd key on a 100% board,
  is the so called "iso" key. `nubs', short for "Non-US backslash", can also be
  used in place of `102d'. `lsgt', which stands for "less (<) / greater (>)",
  is yet another valid name for that key.

(deflayer name
  _    _    _    _    _    _    _    _    _    _    _    _    _          _    _    _
  _    _    _    _    _    _    _    _    _    _    _    _    _    _     _    _    _    _    _    _    _
  _    _    _    _    _    _    _    _    _    _    _    _    _    _     _    _    _    _    _    _    _
  _    _    _    _    _    _    _    _    _    _    _    _    _                         _    _    _
  _    _    _    _    _    _    _    _    _    _    _    _    _               _         _    _    _    _
  _    _    _              _                   _    _    _    _          _    _    _    _    _
)

  -------------------------------------------------------------------------- |#

(defsrc
  esc  f1   f2   f3   f4   f5   f6   f7   f8   f9   f10  f11  f12        ssrq slck pause
  grv  1    2    3    4    5    6    7    8    9    0    -    =    bspc  ins  home pgup  nlck kp/  kp*  kp-
  tab  q    w    e    r    t    y    u    i    o    p    [    ]    ret   del  end  pgdn  kp7  kp8  kp9  kp+
  caps a    s    d    f    g    h    j    k    l    ;    '    \                          kp4  kp5  kp6
  lsft 102d z    x    c    v    b    n    m    ,    .    /    rsft            up         kp1  kp2  kp3  kprt
  lctl lmet lalt           spc                 ralt rmet cmp  rctl       left down rght  kp0  kp.
)

우리는 첫번째 파일을 참고하면서 두번째 파일을 내 키보드 설정에 맞춰 수정할 것이다. 그럼 위 순서에 따라 하나씩 차근차근 따라가보자.

defcfg 작성하기

defcfg에서는 input과 output 등 몇 가지 옵션을 설정하는 부분이다. 이 내용은 tutorial.kbd에 있으며, 그 내용은 이렇게 되어있다.

tutorial.kbd
(defcfg
  ;; For Linux
  input  (device-file "/dev/input/by-id/usb-04d9_daskeyboard-event-kbd")
  output (uinput-sink "My KMonad output"
    ;; To understand the importance of the following line, see the section on
    ;; Compose-key sequences at the near-bottom of this file.
    "sleep 1 && setxkbmap -option compose:ralt")
  cmp-seq ralt    ;; Set the compose key to `RightAlt'
  cmp-seq-delay 5 ;; 5ms delay between each compose-key sequence press
  key-seq-delay 5 ;; 5ms delay between each outputted key event

  ;; For Windows
  ;; input  (low-level-hook)
  ;; output (send-event-sink)

  ;; For MacOS
  ;; input  (iokit-name "my-keyboard-product-string")
  ;; output (kext)

  ;; Comment this if you want unhandled events not to be emitted
  fallthrough true

  ;; Set this to false to disable any command-execution in KMonad
  allow-cmd true

  ;; Set the implicit around to `around`
  implicit-around around
)

여기서 설정해줘야 할 사항은 두 가지다.

  1. input을 내 키보드에 맞게 바꾸기
  2. key-seq-delay 제거하기

먼저, input의 " " 내의 내용을 내 키보드 장치의 파일명으로 바꿔줘야 한다. 장치명은 /dev/input/by-id/ 디렉토리에서 확인할 수 있다. 나의 경우 다음의 명령어를 통해 결과를 확인하였다. 확인한 항목들 중에서 *event-kbd로 끝나는 파일명을 defcfg의 input에 입력해주자.

bash
ls /dev/input/by-id | grep Anne
# ls 결과
usb-OBINS_OBINS_AnnePro2_00000000000000000000000000000000-event-if01
usb-OBINS_OBINS_AnnePro2_00000000000000000000000000000000-event-if02
usb-OBINS_OBINS_AnnePro2_00000000000000000000000000000000-event-kbd
usb-OBINS_OBINS_AnnePro2_00000000000000000000000000000000-if02-event-kbd
usb-OBINS_OBINS_AnnePro2_00000000000000000000000000000000-if02-event-mouse
usb-OBINS_OBINS_AnnePro2_00000000000000000000000000000000-if02-mouse
usb-OBINS_OBINS_AnnePro2_00000000000000000000000000000000-if03-event-joystick
usb-OBINS_OBINS_AnnePro2_00000000000000000000000000000000-if03-joystick

다음으로, key-seq-delay 항목 자체를 제거해주자. 정확한 이유는 모르지만 오류가 발생하는 현상이 있다.

수정이 완료되면, 작성한 defcfg 블록을 아까 만들어둔 annepro2.kbd에 입력해준다.

defsrc 작성하기

다음으로 작성할 내용은 defsrc 부분이다. defsrc는 내 키보드의 모양을 설정하는 부분이라고 보면 된다.

본 가이드에서는, annepro2.kbd라고 만들어둔 iso 100% 키보드를 가져와서 anne pro2 키보드 layer에 맞도록 수정해볼 것이다.

현재 시작 상태는 이렇게 되어있다.

annepro2.kbd
(defsrc
  esc  f1   f2   f3   f4   f5   f6   f7   f8   f9   f10  f11  f12        ssrq slck pause
  grv  1    2    3    4    5    6    7    8    9    0    -    =    bspc  ins  home pgup  nlck kp/  kp*  kp-
  tab  q    w    e    r    t    y    u    i    o    p    [    ]    ret   del  end  pgdn  kp7  kp8  kp9  kp+
  caps a    s    d    f    g    h    j    k    l    ;    '    \                          kp4  kp5  kp6
  lsft 102d z    x    c    v    b    n    m    ,    .    /    rsft            up         kp1  kp2  kp3  kprt
  lctl lmet lalt           spc                 ralt rmet cmp  rctl       left down rght  kp0  kp.
)

그러나 anne pro2는 이 양식보다 30개 이상 키 개수가 적고 키들의 위치도 다르다. 그러니 실제 키보드 모양을 보면서 이를 바꿔주면 된다. Anne pro2의 경우, fn키들이 리눅스에서 입력으로 인식되지 않기 때문에 설정에서 제외하였다. (xev를 실행해서 fn키를 눌러보면 입력으로 인식되지 않음을 알 수 있다.)

나는 다음처럼 defsrc을 작성하였다. 사진과 수정된 annepro2.kbd를 비교해보면서 어떻게 작성하는지 확인해보자.

앤프로2
앤프로2
annepro2.kbd
(defsrc
  esc  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      rctl      
)

이로써 annepro2.kbd에는 defcfg와 defsrc까지 포함되게 되었다.

deflayer base 작성하기

다음으로 작성할 사항은 base layer이다. base layer는 어떤 기본적으로 사용하게 되는 키 스트로크를 설정하는 부분이다. 이 내용은 앞서 설정한 defsrc와 거의 동일하게 작성될 것이다.

가장 먼저, defsrc를 복붙하고 그 블록 이름을 다음처럼 deflayer base라고 설정해준다.

annepro2.kbd
(deflayer base
  esc  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      rctl
)

이로써 annepro2.kbd에는 defcfg, defsrc, deflayer base가 포함되었다.

custom layer 작성하기

이제 본격적으로 custom layer를 만든다. 앞서 작성했던 deflayer base를 그대로 복붙하자. 그리고 그 블록의 이름을 deflayer 원하는이름의 형태로 바꿔준다. 나는 다음처럼 deflayer layer1이라고 설정해주었다.

annepro2.kbd
(deflayer layer1
  esc  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      rctl      
)

자, 그리고 이렇게 새로만든 layer1에 원하는대로 키 맵핑을 해준다. 필자는 다음의 사항들을 설정했다.

  1. esc을 `(grv)로 설정
  2. h, j, k , l을 left, down, up, right로 설정
  3. q, e를 pgup, pgdn로 설정
  4. [, ]를 home, end로 설정
  5. tab을 caps로 설정 (원래 caps는 _로 입력을 제거)

그 결과는 다음과 같다.

annepro2.kbd
(deflayer layer1
  grv  1    2    3    4    5    6    7    8    9    0    -    =    bspc
  caps pgup w    pgdn r    t    y    u    i    o    p    home end  \
  _    a    s    d    f    g    left down up   rght ;    '    ret
  lsft z    x    c    v    b    n    m    ,    .    /         rsft            
  lctl lmet lalt           spc                      ralt      rctl      
)

좋다. 이걸로 원하는 레이어를 정의했다. 이제 우리의 설정파일인 annepro2.kbd에는 defcfg, defsrc, deflayer base, deflayer layer1라는 총 4 개의 항목이 포함되게 되었다.

defalias 작성하기

이제 앞서 설정했던 custom layer인 layer1을 활성화하는 키를 설정하고 이걸 defsrc에 추가해줘야 한다. 나의 경우, caps키를 layer1을 활성화하는 ly1이라 alias하고 이걸 defsrc에 추가해줄 것이다.

먼저, 다음처럼 layer1을 활성화하는 ly1이라는 키를 alias해주자.

annepro2.kbd
(defalias
   ly1 (layer-toggle layer1)
)

위 설정은 누르고 있는 상태(layer-toggle)에서 layer1을 활성화하란 의미를 가지는 ly1이라는 키를 정의한다는 의미를 가진다.

이어서 아까 작성한 deflayer base에 ly1키를 추가해주자. 나의 경우, caps를 제거하고 그 자리에 @ly1이라고 설정해주었다. 여기서 @은 ly1에로 정의된 기능을 수행한단 의미이다.

annepro2.kbd
(defsrc
  esc  1    2    3    4    5    6    7    8    9    0    -    =    bspc
  tab  q    w    e    r    t    y    u    i    o    p    [    ]    \
  @ly1 a    s    d    f    g    h    j    k    l    ;    '    ret
  lsft z    x    c    v    b    n    m    ,    .    /         rsft            
  lctl lmet lalt           spc                      ralt      rctl      
)

자, 지금까지 잘 따라왔다면 annepro2.kbd의 내용은 다음처럼 완성되었을 것이다.

annepro2.kbd
(defcfg
  ;; For Linux
  input  (device-file "/dev/input/by-id/usb-OBINS_OBINS_AnnePro2_00000000000000000000000000000000-event-kbd")
  output (uinput-sink "My KMonad output"
    ;; To understand the importance of the following line, see the section on
    ;; Compose-key sequences at the near-bottom of this file.
    "sleep 1 && setxkbmap -option compose:ralt")
  cmp-seq ralt    ;; Set the compose key to `RightAlt'
  cmp-seq-delay 5 ;; 5ms delay between each compose-key sequence press

  ;; For Windows
  ;; input  (low-level-hook)
  ;; output (send-event-sink)

  ;; For MacOS
  ;; input  (iokit-name "my-keyboard-product-string")
  ;; output (kext)

  ;; Comment this if you want unhandled events not to be emitted
  fallthrough true

  ;; Set this to false to disable any command-execution in KMonad
  allow-cmd true

  ;; Set the implicit around to `around`
  implicit-around around
)


(defsrc
  esc  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      rctl
)

(deflayer base
  esc  1    2    3    4    5    6    7    8    9    0    -    =    bspc
  tab  q    w    e    r    t    y    u    i    o    p    [    ]    \
  @ly1  a    s    d    f    g    h    j    k    l    ;    '    ret
  lsft z    x    c    v    b    n    m    ,    .    /         rsft
  lctl lmet lalt           spc                      ralt      rctl
)

(deflayer layer1
  grv  1    2    3    4    5    6    7    8    9    0    -    =    bspc
  caps pgup w    pgdn r    t    y    u    i    o    p    home end  \
  _    a    s    d    f    g    left down up   rght ;    '    ret
  lsft z    x    c    v    b    n    m    ,    .    /         rsft
  lctl lmet lalt           spc                      ralt      rctl
)

(defalias
  ly1 (layer-toggle layer1)
)

kmonad 실행해서 작동상태 확인하기

자, 이제 우리가 설정한 내용이 정상 작동하는지 kmonad를 실행해볼 시간이다. 실행은 다음처럼 하면 된다.

bash
sudo kmonad .config/kmonad/annepro2.kbd

그러면 kmonad가 실행된 상태가 되는데, 이 상태에서 내가 설정한 ly1을 누른상태에서 layer1이 활성화되는지 확인해보자. 필자는 아주 잘 작동한다!

마무리하며

우리는 kmonad를 설치하고 설정하는 방법을 알아봤다. 정상적으로 키맵핑까지 성공했으면 거의 90%는 완성했다고 볼 수 있다. 이제 남은 작업은, 우리가 작성한 annepro2.kbd를 실행하는 kmonad .config/kmonad/annepro2.kbd를 부팅할 때 자동으로 실행되도록 만들어주는 것이다. 이 작업은 사용자 계정에 권한을 주는 등 꽤나 복잡한 절차가 있다. 그래서 이 부분은 (기회가 되면) 다음 포스팅으로 작성해볼까 한다.

그러나 걱정 마시라! 지금 상태에서도, 조금 귀찮을 순 있지만, 매 부팅 직후 다음의 명령어를 순서대로 실행해주면 kmonad 프로세스를 백그라운드에서 동작하게 할 수 있다.

bash
sudo -v  # sudo 인증 유효화
sudo kmonad .config/kmonad/annepro2.kbd & disown # background에서 kmonad 프로세스 실행

번외: numpad 전용 레이어를 추가하기

나는 numpad 레이어를 추가해서 숫자키가 없는 키보드의 단점을 보완하고 있다. 이를 위해서는 deflayer numpad를 추가하고, 이걸 layer1의 w키에 맵핑해줬다. 이렇게 설정해주면, caps+w로 numpad 모드로 넘어갈 수 있고 숫자 입력이 끝나면 esc를 눌러서 다시 base로 돌아오게 설정된다.

annepro2.kbd
(deflayer layer1
  grv  1    2    3    4    5    6    7    8    9    0    -    =    del
  caps pgup @num pgdn r    t    y    u    i    o    p    home end  \
  _    a    s    d    f    g    left down up   rght ;    '    ret
  lsft z    x    c    v    b    n    m    ,    .    /         rsft
  lctl lmet lalt           spc                      ralt      rctl
)

(deflayer numpad
  @base _    _    _    _    _    _    _    _    _    _    _    _    _
  _    _    _    _    _    _    _    _    _    7    8    9    _    _
  _    _    _    _    _    _    _    _    _    4    5    6    _
  _    _    _    _    _    _    _    _    1    2    3         _
  _    _    _           _                      0         _
)

(defalias
  ly1 (layer-toggle layer1)
  num (layer-switch numpad)
  base (layer-switch base)
)

참조 문헌

Last updated on