zle 위젯 "edit-command-line"을 통해 Vim을 시작할 때 Vim이 Cj를 Cm으로 변환하는 것을 방지하는 방법은 무엇입니까?

zle 위젯 "edit-command-line"을 통해 Vim을 시작할 때 Vim이 Cj를 Cm으로 변환하는 것을 방지하는 방법은 무엇입니까?

내 코드는 다음과 같습니다 ~/.zshrc.

autoload -Uz edit-command-line
zle -N edit-command-line
bindkey '^X^E' edit-command-line

edit-command-linezle 위젯을 keysequence 에 바인딩 합니다 C-x C-e. 위젯은 man zshcontrib(섹션 ZLE FUNCTIONS, 하위 섹션 Widgets)에 설명되어 있습니다.

edit-command-line ksh와 같은 시각적 편집기를 사용하여 명령줄을 편집합니다.

          bindkey -M vicmd v edit-command-line

그 목적은 readline 함수 ( , section , subsection ) C-x C-e의 기능과 유사하게 기본 편집기에서 를 눌러 현재 쉘 명령줄을 편집할 수 있도록 하는 것입니다 .edit-and-execute-commandman bashREADLINECommands for Manipulating the History

편집 및 실행 명령(C-xC-e) 현재 명령줄에서 편집기를 호출하고 결과를 셸 명령으로 실행합니다. Bash는 $VISUAL, $EDITOR 및 emacs를 순서대로 편집기로 호출하려고 시도합니다.

내 기본 편집기는 Vim 8.1( 1-538패치 포함)입니다. C-h, C-j, C-k, , 키를 사용하여 C-l인접한 창으로 초점을 이동하는 Vim 맵이 있습니다 . 그것들은 다음과 같이 요약될 수 있습니다:

nnoremap <c-h> :<c-u>wincmd h<cr>
nnoremap <c-j> :<c-u>wincmd j<cr>
nnoremap <c-k> :<c-u>wincmd k<cr>
nnoremap <c-l> :<c-u>wincmd l<cr>

그것들은 모두 일반 Vim 인스턴스(실행하여 시작됨 $ vim)에서 예상대로 작동합니다. 하지만 C-jVim은 edit-command-line.

C-x C-e쉘 명령줄에서 키를 누르면 zsh가 Vim을 시작합니다 . 다음을 수행하여 창을 분할한 :split다음 C-k상단 창으로 이동을 누르면 두 개의 창이 생기고 포커스가 상단 창으로 이동합니다. 그러나 C-j하단 창으로 돌아가기를 누르면 아무 일도 일어나지 않습니다.

이것이 문제의 원인인지는 모르겠지만 C-jVim 버퍼에 텍스트를 삽입하려고 하면(를 눌러 C-v C-j) ^M(캐리지 리턴을 위한 캐럿)이 표시됩니다. 일반 Vim 인스턴스( exec 로 실행됨 $ vim)에서 텍스트를 삽입하면 C-j캐럿 ^@(NUL) 문자가 생성됩니다.

다음과 같은 최소한의 접근 방식으로 문제를 재현할 수 있습니다 ~/.zshrc.

export EDITOR=vim
autoload -Uz edit-command-line
zle -N edit-command-line
bindkey '^X^E' edit-command-line

이 가장 작은 것 ~/.vimrc:

nnoremap <c-j> :echom 'C-j has been pressed'<cr>

C-x C-ezsh 명령줄을 누르면 Vim이 시작되고, 누르면 다음 C-j메시지가 인쇄되고 기록됩니다.

C-j has been pressed

그러나 아무 일도 일어나지 않았습니다.

bash나 Neovim( v0.3.2-752-g4d7c7f9)을 사용하여 문제를 재현할 수 없습니다. 또한 C-jVim에 텍스트를 삽입하면 를 누른 후 bash에서 Vim을 시작할 때 C-x C-eNUL( )이 발생합니다 . ^@를 누른 후 bash 또는 zsh에서 Neovim을 시작할 때도 동일한 일이 발생합니다 C-x C-e.

┌────────┬──────┬─────┐
│        │ bash │ zsh │
├────────┼──────┼─────┤
│ Vim    │ ^@   │ ^M  │
├────────┼──────┼─────┤
│ Neovim │ ^@   │ ^@  │
└────────┴──────┴─────┘

일부 Vim 터미널 옵션이 잘못 구성되었을 수도 있다고 생각하여 다음 출력을 캡처했습니다.

:set termcap

Vim으로 시작하고 $ vim, Vim으로 시작하세요 C-x C-e. 그러나 두 경우 모두 출력은 동일합니다.

--- Terminal codes ---

  t_AL=^[[%p1%dL      t_DL=^[[%p1%dM      t_mr=^[[7m          t_se=^[[27m         t_us=^[[4m
  t_al=^[[L           t_dl=^[[M           t_ms=y              t_Sf=               t_ut=
  t_bc=               t_EC=               t_nd=^[[C           t_SH=               t_vb=^[g
  t_BE=               t_EI=^[[2 q         t_op=^[[39;49m      t_SI=^[[6 q         t_vi=^[[?25l
  t_BD=               t_fs=^G             t_RF=               t_Si=               t_VS=
  t_cd=^[[J           t_GP=               t_RB=               t_so=^[[7m          t_vs=^[[34l
  t_ce=^[[K           t_IE=               t_RC=               t_SR=^[[4 q         t_WP=
  t_cl=^[[H^[[J       t_IS=               t_RI=^[[%p1%dC      t_sr=^[M            t_WS=
  t_Ce=               t_ke=^[[?1l^[>      t_Ri=               t_ST=               t_xn=y
  t_Co=256            t_ks=^[[?1h^[=      t_RS=               t_Te=               t_xs=
  t_CS=               t_le=^H             t_RT=               t_Ts=               t_ZH=^[[3m
  t_CV=               t_mb=^[[5m          t_RV=               t_ts=^[]0;          t_ZR=^[[23m
  t_da=               t_md=^[[1m          t_Sb=               t_u7=               t_8f=
  t_db=               t_me=^[[0m          t_SC=               t_ue=^[[24m         t_8b=
  t_AB=^[[%?%p1%{8}%<%t4%p1%d%e%p1%{16}%<%t10%p1%{8}%-%d%e48;5;%p1%d%;m
  t_AF=^[[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;m
  t_cm=^[[%i%p1%d;%p2%dH
  t_Cs=^[]12;%p1%s^G
  t_cs=^[[%i%p1%d;%p2%dr
  t_te=^[[2 q^[[?1004l^[[?1049l
  t_ti=^[[2 q^[[?1004h^[[?1049h
  t_ve=^[[34h^[[?25h

--- Terminal keys ---

t_#2 <S-Home>    ^[[1;2H   t_k6 <F6>        ^[[17~    t_kh <Home>      ^[[1~          <ð>        ^[p
t_#4 <S-Left>    ^[[1;2D   t_k7 <F7>        ^[[18~    t_kl <Left>      ^[OD           <ô>        ^[t
t_%i <S-Right>   ^[[1;2C   t_k8 <F8>        ^[[19~    t_kr <Right>     ^[OC           <õ>        ^[u
t_*7 <S-End>     ^[[1;2F   t_k9 <F9>        ^[[20~    t_ku <Up>        ^[OA           <ù>        ^[y
t_@7 <End>       ^[[4~     t_k; <F10>       ^[[21~         <á>        ^[a            <ú>        ^[z
t_F1 <F11>       ^[[23~    t_kB <S-Tab>     ^[[Z           <â>        ^[b            <Mouse>     ^[[M
t_F2 <F12>       ^[[24~    t_kD <Del>       ^[[3~          <ä>        ^[d            <S-F18>     ^[[O
t_k1 <F1>        ^[OP      t_kI <Insert>    ^[[2~          <å>        ^[e            <S-F19>     ^[[I
t_k2 <F2>        ^[OQ      t_kN <PageDown>  ^[[6~          <æ>        ^[f            <xUp>       ^[[1;*A
t_k3 <F3>        ^[OR      t_kP <PageUp>    ^[[5~          <ç>        ^[g            <xDown>     ^[[1;*B
t_k4 <F4>        ^[OS      t_kb <BS>        ^?             <í>        ^[m            <xLeft>     ^[[1;*D
t_k5 <F5>        ^[[15~    t_kd <Down>      ^[OB           <î>        ^[n            <xRight>    ^[[1;*C

Bash와 zsh의 출력 $ stty -a도 동일합니다.

speed 38400 baud; rows 33; columns 119; line = 0;
intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = <undef>;
eol2 = <undef>; swtch = <undef>; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R;
werase = ^W; lnext = ^V; discard = ^O; min = 1; time = 0;
-parenb -parodd -cmspar cs8 -hupcl -cstopb cread -clocal -crtscts
-ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl -ixon -ixoff
-iuclc -ixany -imaxbel iutf8
opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
isig icanon iexten echo echoe echok -echonl -noflsh -xcase -tostop -echoprt
echoctl echoke -flusho -extproc

나는 그것을 사용하고 있습니다 zsh 5.6.2-dev-1 (x86_64-pc-linux-gnu).

zle 위젯으로 시작할 때 Vim이 변환되지 않도록 Vim 또는 zsh 옵션을 설정해야 합니까 C-j?C-medit-command-line

답변1

$EDITOR이를 수행하기 위해 스크립트나 함수를 설정하면 호출되는 터미널 설정이 zle 설정( 터미널 장치 드라이버가 NL에서 CR로 전환되도록 함)이라는 stty -a것을 알 수 있습니다 .vimedit-command-lineinlcr

^J개행이므로 바인딩이 약간 미묘합니다.

여기서는 다음과 같이 함수를 정의하여 이 문제를 해결할 수 있습니다 vim.

vim() STTY=sane command vim "$@"

또는 에 편집 STTY=sane(또는 )을 추가합니다 .STTY=-inlcredit-command-line

관련 정보