가이드

단축키

gori의 단축키는 Hotkeys 편집기에서 재지정합니다. Preferences(Ctrl-,Editor & KeysHotkeys에서 )로 들어가거나, 커맨드 팔레트(Ctrl-P)의 **settings:hotkeys**로 바로 갈 수 있습니다. 에디터는 재지정 가능한 모든 동작을 발생 위치별(GLOBAL, HISTORY, REPEATER, FUZZER, INTERCEPT, …)로 묶어 나열합니다. 행을 고르고, 새 키를 누르면, 끝입니다.

Ctrl-,  → Editor & Keys → Hotkeys
Ctrl-P  → settings:hotkeys

키 예산 (새 단축키가 키를 얻는 방식)

맨 글자 키는 귀합니다. 새 동작은 키를 차지하기 전에 가격 등급을 정해야 합니다.

등급 가격 언제 예시
L0 구조적 Esc Enter Tab 화살표 Space(리더) 항상 포커스, 열기/닫기, READ/INS, space 메뉴
L1 루프 맨 글자 또는 스티키 패밀리(^R) 분당 여러 번 History/Issues j/k / y t(표시) v(뷰), 서브탭 스트립 t(표시), Repeater 전송
L2 세션 호흡 Global 맨 글자(상한: c i s만) 세션당 여러 번 capture, intercept, scope 렌즈
L3 맥락적 Space 다음 니모닉 가끔, 패널 로컬 compare, mine, send-group, copy-as
L4 드문 동작 / 설정 팔레트(Ctrl-P) 또는 Preferences(Ctrl-,) 드물게 설정, Match & Replace, 알림

경험칙:

  • 새 패널 동작의 기본값은 L3(space 메뉴 전용)입니다. 루프가 입증된 뒤에야 직접 키로 승격하세요.
  • Ctrl은 타이핑 중(INS)에도 작동해야 하는 동작, 그리고 워크벤치의 실행·중지(Ctrl-R / Ctrl-X)를 위한 것입니다. 맨 글자에서 한 단계 올리는 범용 승격 수단이 아닙니다.
  • Shift는 탭 전체를 비우는 동작을 맡습니다. ⇧X는 clear가 있는 모든 탭(History·Probe·Authorize·Issues·프로젝트 ACTIVITY 피드)에서 같은 키이고, 스페이스 메뉴 글자는 그 옆의 X입니다. c가 아니라 x인 이유는 shift 아래에 무엇이 있느냐입니다: 맨 x는 그 다섯 스코프 어디에도 바인딩되어 있지 않지만 맨 c는 다섯 곳 모두에서 살아 있고(capture.toggle, Probe 목록에서는 dismiss), 프로젝트를 지우는 동작이 하루 종일 누르는 키 바로 위 shift에 있어서는 안 됩니다. 파괴적인 코드는 누르기 전에 읽을 수 있는 곳에 이름이 적혀 있어야 하고(스페이스 메뉴만이 아니라 Help 시트와 그 탭의 본문 힌트에), 먼저 확인을 물어야 합니다.
  • d는 파괴합니다.d는 이 키를 바인딩한 모든 스코프(16곳)에서 선택한 행을 삭제하거나 무시합니다. Repeater의 응답 diff가 유일한 예외였고, 이제 ⇧D로 옮겨서 반사적으로 누른 d가 표시 토글에 떨어지지 않습니다. 스페이스 메뉴 글자도 ⇧D입니다. d는 아홉 개 서브탭 스트립 전부에서 서브탭 복제이고(space 메뉴 참고) 그 버킷은 모든 패널에 함께 그려지므로, 맨 글자는 더 이상 diff 토글의 것이 아닙니다 — 덕분에 메뉴 행과 키보드가 같은 철자를 씁니다. 삭제가 아닌 새 패널 동작은 d를 가져가지 않습니다.
  • 복사가 그 규칙의 실례입니다. y는 READ에서, Ctrl-YINS에서도, 모든 텍스트 상자에서 복사합니다. INS에서 맨 y는 그냥 문자이고, Shift+화살표로 만든 선택 위에 타이핑하면 그 선택을 덮어씁니다. 그래서 복사 반사에는 타이핑을 견디는 코드가 필요합니다. 둘은 같은 동사(*.copy)이므로 재지정은 READ 쪽 글자만 옮기고 Ctrl-Y는 그대로 남습니다. 모든 스코프에서, 명시적인 해제(unbind)를 해도 마찬가지입니다. y를 푸는 것은 READ 모드에 대한 결정이지, 방금 선택한 것을 복사할 방법을 텍스트 패널에서 조용히 없애도 된다는 뜻이 아니기 때문입니다.
  • 복사할 것이 있는 목록은 모두 y를 바인딩합니다. 바이트나 행, 기록 한 줄을 보여주면서 y에 아무 반응이 없는 패널은 설계가 아니라 구멍입니다. Intercept 큐, Evidence 보관함, 프로젝트 ACTIVITY 피드, OAST 콜백 상세가 각각 그런 구멍이었고 이제 모두 이 글자에 응답합니다. 한 곳에 복사가 둘 있고 서로 반대 방향을 가리킬 때는 — OAST 목록은 gori가 보낸 페이로드를, 상세는 돌아온 것을 복사합니다 — 코드는 하나만 가질 수 있고(키맵에는 포커스 차원이 없습니다), 나머지는 스페이스 메뉴 글자를 유지합니다.
  • /는 지금 보고 있는 목록을 거릅니다. 스크롤이 필요한 목록은 모두 이 키에 응답하며, 그렇지 않던 세 규칙 목록 — Colormarker, Match & Replace, Probe RULES 하위 탭(세 섹션에 걸친 내장 규칙 약 40개) — 도 이제 포함됩니다. 이 바는 렌즈입니다. 행을 숨길 뿐 비활성화하지 않으며, Esc로 지웁니다. 바뀌는 것은 순서 변경 하나뿐입니다: 어떤 규칙이 이기는지를 순서가 결정하는 두 목록에서는, 질의가 걸린 동안 이동이 거절됩니다. 걸러진 목록은 규칙 엔진이 들고 있는 순서가 아니기 때문입니다.
  • f는 두 계층과 예외 하나를 가집니다. 증거 맥락(Issue의 RELATED 카드, 증거 뷰어)에서는 freeze이고, 하위 탭 스트립에서는 find입니다 — 계층이 다르므로 충돌할 수 없습니다. History의 follow와 Comparer의 변경 없는 줄 접기는 대신 Space 메뉴 항목입니다. 둘 다 세션에 한 번 뒤집는 토글이고, 그것이 L3의 용도입니다. 예외는 Intercept 큐입니다. 거기서 f는 잡아둔 요청을 전달하고 ⇧F는 전부 전달합니다. 그 탭 고유의 루프 키이고 f/⇧F 가족이 그 자체로 일관되므로, 옮기는 대신 문서로 남깁니다 — History → Repeater가 Ctrl-R에서 받은 것과 같은 판단입니다.
  • x는 줄을 선택하고, t는 행의 플래그를 뒤집습니다. x는 열네 개 스코프에서 "이 줄 선택"이고, 네 곳(Colormarker·Match & Replace·Probe RULES 목록·OAST providers)에서만 "이 규칙 활성/비활성"이었습니다. 이제 그 넷은 t에 응답합니다. t는 History·Issues·Sitemap·Intercept 큐에서 이미 **표시(mark)**를 뜻하고, 규칙 목록에는 표시가 없으므로 충돌하지 않습니다. 덕분에 Rewriter의 토글도 손으로 짠 컨트롤러 키를 벗어나 평범한 재지정 가능 코드가 되었습니다.
  • s는 출처로 가거나, scope 렌즈를 뒤집습니다. 의미는 이 둘뿐입니다. s는 행이 사는 탭을 엽니다(Evidence 보관함, Issue의 RELATED 카드, Probe 목록과 상세). 그 밖의 모든 곳에서는 전역 scope 렌즈입니다. 더 이상 뜻하지 않게 된 것: Comparer와 Diff의 A ⇄ B 교체(이제 w), Colormarker와 Match & Replace 규칙 목록의 global ⇄ project(이제 Space 메뉴 항목이라 렌즈를 가리지 않습니다). 가리는 곳이 한 군데 남아 있고 그것은 이름을 붙여 둡니다: 프로젝트 ACTIVITY 피드의 s는 source 칩을 순환합니다. 그 패널의 / 바는 자유 텍스트 질의라 source: / level: / actor:를 파싱하지 않아 세 칩을 접어 넣을 곳이 없기 때문입니다.
  • space 메뉴는 INS의 대체 수단이 아닙니다. 텍스트 에디터가 키를 먼저 소비하므로 그곳에서 Space는 그냥 문자입니다. 타이핑 중에도 닿아야 하는 동작에는 Ctrl 코드가 필요하고, 니모닉만으로는 부족합니다. (Repeater/Fuzzer의 디코더 체인 편집기가 Ctrl-Y를 Copy에 넘겨준 뒤 space 메뉴만이 아니라 Ctrl-Q에 실린 이유가 이것입니다.)
  • History → RepeaterRepeater 전송은 **Ctrl-R**로 유지됩니다(동일한 근육 기억). History→Repeater를 맨 글자 r로 옮기지 마세요.
  • r는 Repeater로 보내고, Ctrl-R는 실행합니다.r는 보낼 플로우가 있는 다섯 스코프에서 "이 행을 Repeater로 보내기"이고, 그 밖에서는 아무것도 아닙니다. Diff의 Run은 Ctrl-R로 옮겼고(아홉 스코프에서 이미 Run을 맡고 있습니다), OAST의 Resume listener는 Shift-R로, 프로젝트 ACTIVITY 피드의 Refresh는 Space 메뉴 항목이 되었습니다 — 진입할 때·피어가 쓸 때·폴링할 때 이미 다시 읽으므로, 새로고침 키가 필요한 피드라면 아예 키가 없는 편이 낫습니다. 하위 탭 스트립의 r=이름 변경은 다른 계층이라 영향이 없습니다.
  • Match & Replace와 알림은 키 없이(팔레트 / 배지) 제공됩니다. Global 키 조합을 원하면 재지정하세요.

맨 글자 하나에 질문 하나

맨 글자는 탭별이 아니라 질문별로 정해집니다. 어떤 동작이 아래 글자를 가져가려면 그 글자의 질문에 답해야 하고, 그렇지 않으면 L3(스페이스 메뉴)에서 시작합니다.

Enter 이 행을 그 자리에서 보여주기
o 이 행 자신의 상세 열기(Enter의 별칭. Sitemap에서는 Enter가 펼치기이므로 o가 유일한 키)
s 이 행이 사는 탭으로 가기 — 아니면 scope 렌즈
d 선택한 행 삭제·무시
y 복사
t 이 행의 플래그 뒤집기(표시, 또는 규칙의 on/off)
a 여기에 행 추가
e 선택한 행 편집
/ 이 목록 거르기
f freeze(증거) · find(하위 탭 스트립)
r 이것을 Repeater로 보내기
Ctrl-R 실행
w A ⇄ B 교체
x 이 줄 선택
Shift-X 이 탭 비우기(먼저 확인)
Space 이 탭의 명령 메뉴

예외는 셋이며 모두 의도적입니다. 각각 그 탭 고유의 루프 키입니다: Interceptf는 전달(Shift-F는 전부 전달), History → RepeaterRepeater 전송Ctrl-R 유지, 프로젝트 ACTIVITY 피드의 s는 source 칩 순환.

편집

에디터는 작업 복사본을 엽니다. Enter를 누르기 전에는 아무것도 저장되지 않으며, Esc는 모든 변경을 버립니다.

동작
/ (또는 j / k), 휠 선택 이동
/ 동작 목록 검색
e 또는 Space 선택한 동작 재지정, 그다음 새 키를 누릅니다
x 또는 Backspace 선택한 동작의 바인딩 해제
r 선택한 동작을 기본값으로 초기화
Shift-R 모든 동작을 기본값으로 초기화
/ OS 기본 프로파일 순환(아래 참고)
Enter 저장 + 적용(실시간, 재시작 없음)
Esc 버리고 닫기

재지정을 시작하면 푸터에 *"press a key to bind"*가 표시됩니다. 아래 예약된 키에 나열된 것들을 제외하고, 원하는 키 조합을 수식 키와 함께 누르세요. 키가 예약되어 있거나 같은 위치의 다른 동작에서 이미 사용 중이면, 에디터는 이를 거부하고 이유를 알려줍니다. 키 입력 대기 상태는 그대로 열려 있으므로 다른 키를 눌러 보면 됩니다.

바인딩된 것이 없으면 행의 키 조합에 (unbound)가 표시됩니다. 마커는 기본값에서 변경했음을 뜻하고, ·은 기본값 상태를 뜻합니다.

충돌

두 동작은 다른 위치에서 발생할 때만 키를 공유할 수 있습니다. 이는 의도된 동작입니다(s는 거의 모든 곳에서 "scope 렌즈"지만 Probe에서는 "출처로 가기", c는 Intercept 큐에서 catch 방향을 순환하는 것을 제외하면 어디서나 "toggle capture"). 에디터는 같은 위치의 충돌만 막습니다. 거기서는 키맵이 둘 중 하나만 남길 수 있기 때문입니다.

숫자 키 패밀리

탭 바는 번호가 매겨진 아홉 개의 슬롯이고, 탭을 옮겨 다니는 기본 수단은 그 숫자입니다.

동작
19 탭 바의 N번 슬롯으로 점프
0 Go to tab… — 21개 탭 전체(슬롯 아홉 개 + 숨은 탭)를 타이핑으로 걸러 고르는 목록
⇧1⇧9 현재 탭의 N번 서브탭으로 점프
⇧0 Find sub-tab… — 스트립의 f가 여는 것과 같은 피커
gori Go to tab 카드: 탭 카탈로그 전체 위에 필터 바가 있고, 바에 올라간 아홉 개는 1부터 9까지 숫자를 달고 나머지는 숫자가 없으며, 각 행 뒤에 그 탭이 무엇을 위한 것인지 한 줄이 붙어 있다
0은 카탈로그 전체를 엽니다. 바 위의 아홉 개는 자기를 여는 숫자를 달고 있고 나머지는 달고 있지 않습니다 — 바깥에 있다는 것의 차이는 그게 전부입니다.

이 키들은 어디서나 동작합니다 — 탭 바, 서브탭 스트립, 리스트 본문, 드릴인 상세, 읽기 전용 페인. 예외는 하나뿐입니다. 필드가 텍스트를 받는 동안(INS 상태의 에디터, / 쿼리 바와 검색, 한 줄 프롬프트, 피커의 필터, CVSS 계산기, Decoder의 CHAIN 필드)에는 숫자가 문자입니다. Space와 같은 규칙입니다. Space가 공백을 입력하는 자리에서는 3도 3을 입력합니다 — base64, sha256, rot13을 변환 체인에 칠 수 있는 이유가 이것입니다.

바는 기본적으로 번호를 그립니다(Preferences → Layout → Tab numbers, settings:layout). 마지막 탭 바로 뒤의 알약은 0:Tabs로 읽힙니다 — 키, 그리고 그 키가 여는 것. 오른쪽 끝에 못박히는 대신 아홉 번째 슬롯에서 두 칸 뒤에 붙어서, 로 걷는 순서와 눈으로 읽는 순서가 같아집니다. 탭이 알약 옆에 더는 들어가지 않을 때만 오른쪽 끝에 고정되고 탭이 스크롤합니다. 레이아웃이 무엇이든 자리를 지킵니다. 0은 바 위의 아홉 개를 포함해 카탈로그 전체에 닿으므로 셀 것이 없고, 알약이 사라지는 레이아웃도 없습니다. 알약 오른쪽의 남는 구역은 일부러 비워 둡니다 — 탭이 아닌 정보를 놓을 자리입니다.

아홉 슬롯, 그리고 열 번째 탭

settings:tabs는 열 번째 탭을 거부하고 그 이유를 알려줍니다 — 대신 ⇧K로 이음선 위로 올리면 그 탭이 바에 올라가고 마지막 슬롯이 내려갑니다. 이전 빌드가 저장한 레이아웃(예전 바에는 상한이 없었습니다)은 사용자 자신의 순서대로 앞의 아홉 개로 잘리고, 잘린 탭 이름을 그 실행에서 한 번 알려줍니다.

한 탭만은 아홉 번째 슬롯 너머에 설 수 있습니다. 0으로 점프해 간 바깥 탭은 그 탭을 떠날 때까지 바의 맨 오른쪽에 번호 없이 놓입니다. 사용자가 배치한 슬롯이 아니라 지금 서 있는 자리이고, 어떤 숫자도 그것을 가리키지 않습니다.

상한 없는 예전 바를 되돌리려면 Preferences → Layout → Tab bar slots를 끄세요. 바는 다시 로 스크롤하고, 19는 여전히 앞의 아홉 탭에 닿고, 0은 여전히 모든 탭에 닿습니다.

키보드 레이아웃

kitty 키보드 프로토콜을 쓰는 터미널은 ⇧33 + shift 플래그로 보고하고, gori는 그것을 바인딩합니다. 다른 터미널은 시프트된 숫자를 문자로 보냅니다 — US 레이아웃에서는 # — 그래서 gori가 그것을 다시 ⇧3으로 접습니다. 비(非)US 레이아웃에서는 그 문자가 달라지므로, ⇧1⇧9는 터미널이 shift 모디파이어를 보고하는 경우에만 동작합니다. 대체 수단은 항상 살아 있습니다. 서브탭 스트립의 **f**는 ⇧0과 같은 피커를 열고, Ctrl-1Ctrl-9는 그것을 전달하는 터미널에서 ⇧1⇧9의 별칭입니다.

space 메뉴

탐색 가능한 패널에서 Space를 누르면 지금 서 있는 자리의 액션 메뉴가 열립니다. 그 패널의 동사들이 COMMON과 포커스된 영역 레이블 아래 묶이고, 각 행 앞에 니모닉 한 글자가 붙습니다. 팔레트와는 다릅니다. 입력도 필터도 없고, 한 행당 키 한 번입니다.

포커스와 무관하게, 탭당 하나의 메뉴

아홉 개 탭이 서브탭 스트립을 가집니다 — Repeater, Fuzzer, Miner, Sequencer, Decoder, JWT, Cookie, Comparer, Notes. 예전에는 스트립 자신의 액션도 다른 컨텍스트 섹션과 똑같이 다뤄져서, 스트립에 포커스가 있을 때 나타났습니다. 그래서 본문 패널에서는 Space가 "이 서브탭 닫기"를 제안하게 하려면 포커스를 한 단계 위로 옮겨야 했습니다.

이제 그것들은 자기 몫의 SUB-TABS 버킷이 되었고, 스트립이 있는 탭이라면 모든 레벨의 메뉴에 들어갑니다 — 본문 패널, 스트립 자신, 그리고 탭 바. ⇧1⇧9가 어디로든 데려다주는 만큼, Space가 무엇을 제안하는지가 커서가 놓인 행에 좌우되어서는 안 됩니다.

아홉 스트립에서 똑같은 아홉 글자

이 버킷은 아홉 개가 아니라 하나의 표로 익히는 것입니다. 해당 액션이 없는 탭은 그 행을 그냥 빼놓을 뿐, 그 글자를 다른 데 쓰지 않습니다.

동작 직접 코드
n 새 서브탭 Ctrl-N
w 서브탭 닫기 (마크된 것 전부) Ctrl-W
d 서브탭 복제
e 서브탭 이름 변경 스트립에서 r
t 서브탭 태그 (Repeater)
f 서브탭 검색 — 피커 스트립에서 f, 어디서나 ⇧0
/ 스트립 필터 (이름 / 호스트 / 메서드 / 태그)
T 필터가 보여주는 서브탭 전부 마크
N 서브탭 마크 해제 스트립에서 Esc

Ctrl-NCtrl-W는 해당 행 옆에 표시되며, 아홉 탭 어느 패널에서도 동작합니다. 메뉴가 더 빠른 키를 감추지 않고 가르칩니다. (Miner와 Sequencer는 실행으로 세션을 만들므로 n이 없습니다.)

이 버킷이 모든 패널에 함께 실리기 때문에, 그 아홉 글자는 해당 탭의 모든 뷰에서 예약됩니다. 그 글자를 쓰던 패널 액션은 자리를 옮겼습니다. 규칙은 패널 글자가 양보한다는 것입니다. 스트립의 글자는 아홉 스트립에서 똑같이 읽혀야 하기 때문입니다. Repeater/Fuzzer 편집기에서는 Space W가 단어를 마크하고, Space D가 응답 diff를 토글하며, JWT와 Cookie의 렌즈 토글은 m(Mode — 같은 동작에 대한 Decoder의 글자)으로 옮겼습니다.

에디터 키셋

gori의 텍스트 패널은 모달입니다. Esci로 READ와 INSERT를 오가고, READ에서는 맨 글자가 명령입니다. 기본으로 제공되는 문법은 helix 형태입니다 — x로 줄을 선택한 뒤 y로 복사. vim에서는 같은 동작이 V 다음 y이고, 딱 그 한 제스처가 vim에 익숙한 손이 하루 종일 부딪히는 지점입니다.

Preferences → Editor & Keys → Keys → Editor keyset(Ctrl-,) 또는 팔레트의 **settings:keys**에서 전환합니다.

키셋 줄 선택 실행 취소 찾기 뒤에 삽입 맨 위 / 맨 아래
helix-ish (기본) x Ctrl-Z Ctrl-F
vim-ish ⇧V u / a g / ⇧G

표에 없는 것은 두 키셋에서 동일합니다. gori가 이미 vim과 같게 쓰고 있기 때문입니다. i로 INSERT에 들어가고, Esc로 나오고, y로 복사하고, Ctrl-G로 줄로 이동하고, 화살표에 Shift를 더해 선택을 넓힙니다.

키셋은 매핑이지 에뮬레이션이 아닙니다

키셋은 소수의 고정된 에디터 동작에 대한 키 재정의 묶음입니다. OS 기본 프로파일이 쓰는 것과 정확히 같은 메커니즘을 한 층 위에 얹은 것입니다. operator-pending 문법도, 레지스터도, 반복 횟수도, 텍스트 오브젝트도, gori의 패널에 없는 편집 연산도 추가하지 않습니다. READ 모드 패널은 캐럿과 선택 영역과 복사가 전부이고, 없는 연산에 키 이름을 붙이는 것이야말로 "vim 모드"가 지키지 못할 약속이 되는 길입니다.

그래서 일부 vim 표기는 의도적으로 제공하지 않습니다. 각각 확인 가능한 이유가 있습니다.

  • gg, dd, yy 등 두 키 시퀀스 전부. gori의 키 조합은 한 번의 키 입력입니다. g 하나가 패널 맨 위이고, 선택이 없는 y는 이미 패널 전체를 복사합니다 — yy가 뜻하는 것의 쓸모 있는 절반입니다.
  • :42를 포함한 : 명령.:는 gori 자체의 명령줄로 예약되어 있으므로, go-to-line은 두 키셋 모두에서 Ctrl-G로 남습니다.
  • 삭제. READ 모드 패널에는 ddD에 얹을 줄 삭제가 없습니다. 편집은 INSERT에서 일어납니다.
  • 규칙 목록의 활성/비활성 x(Colormarker, Probe rules, OAST providers, Rewriter). 그 x는 규칙을 켜고 끄는 것이지 선택이 아니며, 키셋이 상태 변경을 ⇧V로 옮기지는 않습니다.
  • Intercept 큐의 줄 선택. 의도적으로 키가 없습니다 — 그 패널은 space 메뉴로 도달하며, 키셋은 키를 다시 쓰는 것이지 키를 두지 않기로 한 패널에 키를 쥐여 주는 것이 아닙니다.

재정의 순서

가장 구체적인 것부터 네 겹입니다.

직접 지정한 재바인딩  >  키셋  >  OS 기본 프로파일  >  기본 제공 키 조합

따라서 키셋은 더 나은 기본값이지 상한이 아닙니다. vim-ish를 고른 뒤 Hotkeys 에디터에서 동작 하나를 재지정하면, 그 하나는 지정한 자리에 그대로 남습니다. 행의 "기본값으로 되돌리기"는 현재 키셋의 표기로 되돌아가며, 기본 제공 키로 돌아가지 않습니다.

모든 화면이 별도 조치 없이 현재 키셋을 따릅니다. 전부 유효 키맵에서 읽기 때문입니다 — 상태 표시줄 힌트 스트립, Help 탭, 커맨드 팔레트, space 메뉴, 그리고 Hotkeys 에디터의 충돌 메시지까지. vim-ish에서 Notes 푸터는 ^F find 대신 / find로 읽히고, ⇧V에 무언가를 바인딩하려 하면 Select line이 거기 있다고 이름을 대며 거절합니다.

space 메뉴의 글자는 건드리지 않습니다

키셋이 옮기는 것은 패널에서 누르는 키이지, space 메뉴가 각 행 앞에 붙이는 글자가 아닙니다. 개별 재지정이 따르는 규칙과 같고, 그 글자들이 안정적인 식별자인 이유이기도 합니다. vim-ish에서도 메뉴는 Select line을 여전히 x로 앞세우고, 그 옆에 실제 키 조합을 함께 씁니다.

│ x Select line   ⇧V │

그래서 카드가 둘 중 어느 쪽인지 짐작하게 만드는 대신 양쪽을 모두 가르쳐 줍니다. 아홉 개 SUB-TABS 글자(n w d e t f / T N)도 어떤 키셋을 고르든 아홉 스트립 전부에서 같은 뜻입니다. 두 네임스페이스는 충돌할 수 없습니다. 메뉴는 모달이고, 키셋은 키맵에만 씁니다.

/도 마찬가지입니다. SUB-TABS 글자이면서 동시에 vim-ish의 찾기 키지만, 둘은 다른 계층입니다 — 메뉴 글자는 카드가 떠 있는 동안 스트립에 작용하고, 키 조합은 지금 서 있는 텍스트 패널을 검색합니다. 키 조합 쪽은 부팅 시점에 검사합니다. validate_chords!가 (OS 프로파일 × 키셋) 모든 칸을 훑으므로, 패널 고유 키를 가리는 키셋 글자는 배포되는 대신 빌드를 실패시킵니다.

무엇을 고르든 그대로인 것

vim-ish에서도 Ctrl-ZINSERT 안에서 계속 실행 취소입니다. 그 가드는 아홉 개 텍스트 에디터 전부에서 키맵보다 먼저 동작하고, 타이핑하는 손이 원하는 자리가 거기입니다. Ctrl-F도 마찬가지로 INSERT를 포함해 계속 찾기 프롬프트를 엽니다. /는 READ에서의 추가이지 대체가 아닙니다. 그리고 에디터 옆의 읽기 전용 패널(Repeater 응답, Fuzzer 결과, Decoder 출력)에서 i는 두 키셋 모두에서 메시지와 함께 거절됩니다.

예약된 키

일부 키는 터미널이나 gori가 필요로 하므로 재지정할 수 없습니다.

  • 종료: Ctrl-C, Ctrl-D.

  • 명명된 키와 구별 불가: Ctrl-M / Ctrl-J (Enter), Ctrl-I (Tab), Ctrl-H (Backspace), Ctrl-[ (Escape).

  • 구조적: Enter, Esc, Tab, Backspace, Space(space 메뉴 리더), 그리고 맨 :(명령줄).

  • 키맵보다 먼저 점유되는 gori 단축키: Ctrl-G (go to line), Ctrl-F (find, Tab으로 find & replace), Ctrl-B (reveal whitespace), Ctrl-E (external editor), Ctrl-P (command palette), Ctrl-N (new repeater/fuzz/note), Ctrl-W (서브탭 닫기, 마크가 있으면 전부), Ctrl-Z (undo. 모든 텍스트 에디터가 소비합니다: Repeater, Fuzzer, Notes, Issues, Intercept, Decoder, JWT, Rewriter, Project 설명), Ctrl-, (Preferences), 그리고 Ctrl-1Ctrl-9 (switch sub-tab — ⇧1⇧9별칭입니다. 숫자 키 패밀리 참고). 이들은 키맵보다 먼저 하드코딩된 가드로 처리되므로, 여기에 바인딩해도 절대 발동하지 않습니다. 같은 이유로 Command palette, Reveal whitespace, New repeater request, New fuzz session은 에디터에 나열되지 않습니다. 그 키는 고정입니다.

    Ctrl-G / Ctrl-F는 포커스가 있는 여러 줄 패널에 적용됩니다. Repeater의 요청/응답, History 상세, Intercept 편집기, Notes, Project 설명, Decoder의 INPUT/OUTPUT, Fuzzer의 템플릿/결과 상세입니다. 편집 가능한 여섯 곳에서는 Tab이 find를 find & replace로 바꿉니다. 나머지는 읽기 전용이고, 프롬프트가 할 수 없는 교체를 제안하는 대신 그렇다고 알려줍니다.

    이 패밀리에서 개별 키를 옮길 수는 없지만, 패밀리 전체에 두 번째 모디파이어를 줄 수는 있습니다. 아래 커맨드 모디파이어를 참고하세요.

Ctrl-S 같은 흐름 제어/시그널 키 조합은 예약되어 있지 않습니다. gori는 터미널을 raw 모드로 실행하므로 이들이 앱에 도달합니다(Repeater의 SNI 토글은 Ctrl-S로 제공됩니다).

OS 기본 프로파일

/ 프로파일 선택기는 새(재정의되지 않은) 바인딩이 어떤 기본 키 세트를 사용할지 고릅니다: auto(gori가 빌드된 플랫폼을 추적), macOS, Linux, Windows. 직접 지정한 재바인딩은 OS와 무관하게 항상 선택한 프로파일 위에 얹힙니다.

현재 OS별 기본값은 동일합니다. 터미널에서 Ctrl+글자 조합은 macOS, Linux, Windows 모두에서 애플리케이션에 도달하며, 정말 위험한 키는 위의 예약된 제어 문자들입니다(어디서나 차단됨). 프로파일 메커니즘은 실제 터미널별 충돌이 생겼을 때 디스패치를 건드리지 않고 바로잡을 수 있도록 마련해 둔 것입니다. 지금으로서는 auto가 모두에게 옳은 선택입니다.

커맨드 모디파이어

예약된 키에 나열된 키 조합 패밀리는 키맵보다 먼저 하드코딩된 가드가 소비하기 때문에 고정입니다. 문제는 터미널이 Ctrl 형태를 아예 전달하지 않는 경우입니다.

  • Ctrl-1Ctrl-9는 상당수 터미널에서 전달 불가입니다. 대응하는 제어 문자가 없어서 서브탭 점프가 애초에 도착하지 않습니다. 없어도 됩니다. 서브탭 점프의 기본 키는 **⇧1⇧9**이고(숫자 키 패밀리), 서브탭 스트립에서는 어느 칩에 있든 **f**로 열려 있는 서브탭 전체를 나열·검색할 수 있습니다. (스트립 왼쪽 끝의 ****도 같은 목록을 엽니다. 클릭하거나, 첫 칩에서 를 누르면 됩니다.)
  • 멀티플렉서가 먼저 먹습니다. tmux의 기본 프리픽스는 Ctrl-B인데, gori도 reveal-whitespace로 씁니다.

Preferences → Editor & Keys → Keys → Command modifier(Ctrl-,), 또는 팔레트의 **settings:keys**에서 이 패밀리를 CtrlOption (⌥) 사이에서 고를 수 있습니다. 이는 교체가 아니라 별칭 추가입니다. Option을 고르면 ⌥P로도 팔레트가 열리고 ^P도 그대로 동작합니다. 바뀌는 것은 표시뿐입니다. 상태 힌트, Help 탭, 팔레트가 모두 ⌥P, ⌥N, ⌥1-9로 표시됩니다.

모디파이어 동작
Ctrl (기본) ^P ^N ^W ^G ^F ^B ^E ^Z ^, ^1-^9
Option (⌥) 위 전부 더하기 ⌥P ⌥N ⌥W ⌥G ⌥F ⌥B ⌥E ⌥Z ⌥, ⌥1-⌥9

Ctrl이 계속 살아있으므로 Option을 골라도 팔레트에 못 들어가는 상황은 생기지 않습니다. 다만 바꾸기 전에 알아둘 점이 있습니다. macOS에서는 터미널이 Option을 Meta/Esc+로 보내도록 설정해야 합니다. 그러지 않으면 ⌥Pπ로 도착해 아무 일도 일어나지 않습니다.

  • Terminal.app: 설정 → 프로파일 → 키보드 → Option을 Meta 키로 사용
  • iTerm2: Settings → Profiles → Keys → Left/Right Option key → Esc+

하지 않는 일 두 가지. 에디터에서 이미 재지정할 수 있는 키 조합(^R send, ^S SNI 등)은 건드리지 않습니다. 그건 동작별로 재지정하세요. 그리고 이 패밀리의 Option 조합(예: alt-n)에 어떤 동작을 바인딩해 뒀다면, 별칭을 켜는 순간 가려집니다. 가드가 이기고 해당 동작은 기본값으로 되돌아가며, 저장 토스트가 그 동작을 알려줍니다.

첫 실행 마법사의 Review 스텝에서도 이 값을 요약해 보여주므로, 앱에 들어가기 전에 모디파이어를 고를 수 있습니다.

저장 위치

~/.gori/settings.json(디렉터리는 $GORI_HOME으로 재정의)의 hotkeys 블록에, 필요한 값만 담아 저장됩니다. 변경한 바인딩만 동작 id별 키 조합 라벨 목록으로 기록되며, 빈 목록은 명시적 바인딩 해제입니다.

{
  "hotkeys": {
    "os": "auto",
    "command_modifier": "alt",
    "keyset": "vim",
    "bindings": {
      "rules.edit": ["g"],
      "scope.edit": []
    }
  }
}

command_modifier"ctrl"(기본) 또는 "alt"이고, keyset"helix"(기본) 또는 "vim"입니다 — 에디터 키셋을 참고하세요. 둘 다 알 수 없는 값은 키가 없는 상태가 아니라 기본값으로 되돌아갑니다. 손대지 않은 설치본은 hotkeys 블록 자체를 쓰지 않습니다.

없는 동작은 프로파일 기본값을 사용합니다. 알 수 없는 id와 파싱할 수 없는 키 조합은 로드할 때 무시되므로, 수동 편집이나 버전 차이가 있어도 무리 없이 동작합니다.

제약

  • 동작의 키 조합만 표시/편집됩니다. 탐색 별칭(예: j / k의 화살표 키 중복)은 나열되지 않습니다.
  • 재지정 가능한 키 조합을 표시하는 모든 화면은 유효 키맵에서 읽습니다. 커맨드 팔레트, space 메뉴, Help 탭과 팝업, 상태 표시줄의 힌트 스트립, 빈 상태 카드가 여기에 해당합니다. 리터럴로 남는 것은 동작(verb)이 아닌 키입니다. 예약된 ^P / ^N / ^W / ^1-9 계열과 구조 키(esc, , 화살표, )가 그렇습니다.
  • Space 메뉴 니모닉 글자는 동작을 가리키는 안정적인 식별자입니다(Helix와 비슷). 재지정은 직접 누르는 키 조합만 바꿀 뿐 space 메뉴 글자는 바꾸지 않습니다.
  • 하위 탭 스트립이 어떤 동작에 이미 글자를 바인딩해 두었다면 메뉴도 가능한 한 같은 글자로 그 동작을 씁니다: f는 하위 탭 목록·검색, t는 칩 마크, ⇧T는 스트립 전체 마크입니다. 맞출 수 없는 하나가 이름 변경입니다. 스트립은 r을 바인딩하지만 Repeater·Fuzzer·Miner·Sequencer에서 rCtrl-R을 메뉴에서 되울리는 Run/Send이고, 이름 변경이 그 자리를 빼앗을 수는 없습니다. 아홉 스트립에 걸쳐 한 동작이 두 가지로 불려서는 안 되므로, 이름 변경은 **전부 e**이고 스트립의 r은 원시 코드로 남습니다. 전체 표는 space 메뉴를 참고하세요.
  • 에디터 동작은 개별로도, 에디터 키셋으로 한 벌씩도 재지정할 수 있습니다. 재지정 에디터가 옮기지 않는 것은 하드코딩된 가드가 먼저 응답하는 몇 개뿐입니다 — Esc(READ로 복귀), Ctrl-Z, Ctrl-F, Ctrl-G. 읽을 수 있도록 Help 시트에는 실려 있고, 키셋은 여기에 두 번째 맨 글자 표기를 줄 수 있습니다. vim-ishu/에 도달하는 방식이 바로 이것입니다.
  • 탐색 가능한 컨텍스트에서 **?**를 누르면 Help 탭(mitmproxy 스타일 치트시트)으로 점프합니다.

다음 단계

  • Settings: Preferences 모달과 그 안의 모든 섹션
  • Themes: 같은 방식으로 컬러 테마를 전환하거나 만듭니다
  • Configuration Reference: settings.jsonhotkeys