WezTerm 사용법 2편 - 리더 단축키 스무 개 관리하기

요약. 1편에서 Ctrl+U 를 접두키로 두고 분할과 이동과 탭을 잡았습니다. 그렇게 쓰다 보면 다음 문제가 옵니다. 키가 스무 개를 넘어가면서 손이 기억하는 것과 설정 파일에 적힌 것이 어긋나기 시작합니다. 이 글은 키 정의를 표 하나로 모아 실제 바인딩과 도움말을 함께 만드는 방법, 그리고 접두키를 쓰면서 치르는 대가를 다룹니다.

도토리 한글 키보드 - 폰을 PC·TV 의 블루투스 키보드로

제가 만든 무료 앱입니다. 많이 써 주세요.

키 정의는 표 하나에 모읍니다

1편의 방식대로 leader("w", ...) 를 줄마다 늘어놓으면 설명을 적을 자리가 없습니다. 그래서 키·설명·액션을 세 칸짜리 항목 하나로 묶고, 그 목록에서 바인딩을 만들어냅니다. 설명은 주석이 아니라 데이터가 됩니다.

local leader_bindings = {
  { "w", "좌우 분할 (Width)", act.SplitHorizontal({ domain = "CurrentPaneDomain" }) },
  { "v", "상하 분할 (Vertical)", act.SplitVertical({ domain = "CurrentPaneDomain" }) },
  { "h", "왼쪽 pane 으로 이동", act.ActivatePaneDirection("Left") },
  { "/", "커맨드 팔레트", act.ActivateCommandPalette },
}

for _, b in ipairs(leader_bindings) do
  table.insert(keys, { mods = "LEADER", key = b[1], action = b[3] })
end

이제 같은 목록을 화면에도 띄웁니다. LEADER + . 에 act.InputSelector 를 붙이면 항목이 오버레이로 나오고, 고른 항목의 동작을 그 자리에서 실행합니다. 키를 하나 추가하면 도움말도 같이 늘어나므로 둘이 어긋날 수 없습니다.

act.InputSelector({
  title = "LEADER (Ctrl+U) 단축키",
  fuzzy = true,
  fuzzy_description = "단축키 검색 (↑↓ 이동 · Enter 실행 · Esc 닫기) : ",
  choices = cheatsheet_choices,   -- { id = 키, label = "키   설명" }
  action = wezterm.action_callback(function(win, p, id)
    for _, b in ipairs(leader_bindings) do
      if b[1] == id then win:perform_action(b[3], p) end
    end
  end),
})

표에 담기지 않는 키도 있습니다. 탭 번호는 for i = 0, 9 루프로 만들므로 항목이 열 개 늘어납니다. 이런 것은 도움말에만 안내로 한 줄 남기고 실행 대상에서는 빼야 합니다. id 를 빈 문자열로 주고 콜백에서 걸러내면 목록에는 보이지만 눌러도 아무 일이 없습니다. 열 폭을 string.format 으로 맞춰 두면 키와 설명이 세로로 정렬됩니다.

table.insert(choices, { id = "", label = string.format("%-12s%s", "0 - 9", "해당 번호 탭 (안내)") })
-- 콜백 첫 줄
if not id or id == "" then return end

도움말이 오조작을 만들던 두 가지

fuzzy = true 를 빼면 안 됩니다. InputSelector 의 기본 모드는 각 행에 빠른 선택 문자를 붙이는데, 그 문자가 alphabet 필드의 기본값 1234567890abc… 에서 순서대로 나옵니다. 화면에 적힌 단축키와는 아무 관계가 없습니다.

제 목록에서 네 번째 항목은 pane 닫기였습니다. 4번 탭으로 가려고 4 를 누르면 pane 이 닫힙니다. 도움말이 오조작을 만드는 셈이라 검색 모드로 고정했습니다.

두 번째는 choices 를 만드는 시점입니다. 이 목록을 키 핸들러 안에서 만들면 LEADER + . 를 누를 때마다 action_callback 이 새 이벤트 핸들러를 등록해 계속 쌓입니다. 목록은 어차피 고정이므로 설정 로드 시점에 한 번만 만들어 변수에 담아 둡니다.

안 외우는 쪽에는 커맨드 팔레트가 있습니다

단축키로 잡을 것과 잡지 않을 것을 나눠야 합니다. 하루에 몇 번 쓰는 동작까지 리더에 붙이면 목록이 다시 스무 개를 넘습니다. 저는 그 나머지를 커맨드 팔레트에 넘기고 LEADER + / 하나만 뒀습니다.

팔레트는 WezTerm 이 아는 명령 전체를 검색하는 모달 오버레이입니다. 타이핑하면 흐릿한 일치로 좁혀지고, 자주 쓴 것이 위로 올라옵니다. 기본 키는 Ctrl+Shift+P 이므로 리더에 붙이지 않아도 됩니다. pane 을 잠깐 전체 화면으로 키우는 Ctrl+Shift+Z 처럼 기본값에 이미 있는 것도 굳이 옮기지 않았습니다.

리더로 쓴 조합은 셸에서 잃습니다

접두키를 정하면 그 조합은 셸에 도달하지 않습니다. Ctrl+U 를 쓰기로 한 순간 bash 에서 커서 앞을 지우던 Ctrl+U 는 없어집니다. 리더 후보는 셸에서 손이 덜 가는 조합에서 고르는 편이 낫고, 이미 익숙해진 뒤에는 바꾸기 어려우니 처음에 정해야 합니다.

리더가 켜진 동안에는 바인딩에 없는 키도 삼켜집니다. 공식 문서의 표현으로도 터미널에 전달되지 않습니다. 그래서 1편의 물결 표시가 장식이 아닙니다. 표시가 없으면 대기 상태인지 확인하려고 누른 키 하나가 그대로 사라집니다. 2초가 지나면 대기는 저절로 풀립니다.

정리

키·설명·액션을 한 표에 모으면 바인딩과 도움말이 같은 원본을 읽습니다. InputSelector 는 fuzzy = true 로 고정하고 목록은 로드 시점에 한 번만 만듭니다. 자주 쓰지 않는 명령은 리더가 아니라 커맨드 팔레트에 맡깁니다.

1편의 키 목록이 이미 열 줄을 넘었다면, 그 줄들을 세 칸짜리 표로 옮기고 LEADER + . 를 붙이는 것부터 해 보십시오.