How to prevent Vim from translating C-j into C-m when started by the zle widget `edit-command-line`?











up vote
2
down vote

favorite












I have the following code in my ~/.zshrc:



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


It binds the edit-command-line zle widget to the keysequence C-x C-e.
The widget is described in man zshcontrib (section ZLE FUNCTIONS, subsection Widgets):




edit-command-line
Edit the command line using your visual editor, as in ksh.



          bindkey -M vicmd v edit-command-line



The purpose is to be able to edit the current shell command line, in the default editor, by pressing C-x C-e, similar to what the readline function edit-and-execute-command does (man bash, section READLINE, subsection Commands for Manipulating the History).




edit-and-execute-command (C-xC-e)
Invoke an editor on the current command line, and execute the result as shell commands. Bash attempts
to invoke $VISUAL, $EDITOR, and emacs as the editor, in that order.




My default editor is Vim 8.1 (patches 1-538 included).
I have Vim mappings, using the keys C-h, C-j, C-k, C-l, to move the focus to neighbour windows.
They can be boiled down to:



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>


They all work as expected in a regular Vim instance (started by executing $ vim).
But C-j doesn't work as expected when Vim was started by edit-command-line.



When I press C-x C-e while on the shell command line, zsh starts Vim. If I split the window by executing :split, then press C-k to move to the top window, I get two windows, and the focus is moved to the top one. But then, if I press C-j to get back to the bottom window, nothing happens.



I don't know whether it's the cause of the issue, but if I try to insert a literal C-j in a Vim buffer (by pressing C-v C-j), ^M is displayed (the caret notation for a carriage return). In a regular Vim instance (started by executing $ vim), inserting a literal C-j results in a character whose caret notation is ^@ (a NUL).



I can reproduce the issue with this minimal ~/.zshrc:



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


And this minimal ~/.vimrc:



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


Pressing C-x C-e on the zsh command line starts Vim, then pressing C-j should print and log the message:



C-j has been pressed


But nothing happens.



I can't reproduce the issue in bash, nor with Neovim (v0.3.2-752-g4d7c7f9).
Besides, inserting a literal C-j in Vim, when the latter was started from bash after pressing C-x C-e, results in a NUL (^@). Same thing when Neovim is started from bash or zsh after pressing C-x C-e.



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


I thought that maybe some Vim terminal option was not properly configured, so I captured the output of:



:set termcap


from Vim started by $ vim, and from Vim started by C-x C-e.
But the output is identical in both cases:



--- 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


The output of $ stty -a is also identical in bash and zsh:



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


I'm using zsh 5.6.2-dev-1 (x86_64-pc-linux-gnu).



Is there a Vim or zsh option which should be set to prevent Vim from translating C-j into C-m when started by the zle widget edit-command-line?










share|improve this question


















  • 1




    Zsh modifies stty settings while zle is active. Running stty from a prompt shows the settings when running commands, not the settings during command line edition. This looks like a bug where it doesn't properly restore stty settings when it runs a command from within command line edition.
    – Gilles
    Nov 28 at 21:19










  • @Gilles, zsh does redirect stdin from /dev/null inside user-defined widgets, but edit-command-line does a exec < /dev/tty, but does not restore the non-zle settings, so the bug if more with that edit-command-line widget.
    – Stéphane Chazelas
    10 hours ago















up vote
2
down vote

favorite












I have the following code in my ~/.zshrc:



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


It binds the edit-command-line zle widget to the keysequence C-x C-e.
The widget is described in man zshcontrib (section ZLE FUNCTIONS, subsection Widgets):




edit-command-line
Edit the command line using your visual editor, as in ksh.



          bindkey -M vicmd v edit-command-line



The purpose is to be able to edit the current shell command line, in the default editor, by pressing C-x C-e, similar to what the readline function edit-and-execute-command does (man bash, section READLINE, subsection Commands for Manipulating the History).




edit-and-execute-command (C-xC-e)
Invoke an editor on the current command line, and execute the result as shell commands. Bash attempts
to invoke $VISUAL, $EDITOR, and emacs as the editor, in that order.




My default editor is Vim 8.1 (patches 1-538 included).
I have Vim mappings, using the keys C-h, C-j, C-k, C-l, to move the focus to neighbour windows.
They can be boiled down to:



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>


They all work as expected in a regular Vim instance (started by executing $ vim).
But C-j doesn't work as expected when Vim was started by edit-command-line.



When I press C-x C-e while on the shell command line, zsh starts Vim. If I split the window by executing :split, then press C-k to move to the top window, I get two windows, and the focus is moved to the top one. But then, if I press C-j to get back to the bottom window, nothing happens.



I don't know whether it's the cause of the issue, but if I try to insert a literal C-j in a Vim buffer (by pressing C-v C-j), ^M is displayed (the caret notation for a carriage return). In a regular Vim instance (started by executing $ vim), inserting a literal C-j results in a character whose caret notation is ^@ (a NUL).



I can reproduce the issue with this minimal ~/.zshrc:



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


And this minimal ~/.vimrc:



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


Pressing C-x C-e on the zsh command line starts Vim, then pressing C-j should print and log the message:



C-j has been pressed


But nothing happens.



I can't reproduce the issue in bash, nor with Neovim (v0.3.2-752-g4d7c7f9).
Besides, inserting a literal C-j in Vim, when the latter was started from bash after pressing C-x C-e, results in a NUL (^@). Same thing when Neovim is started from bash or zsh after pressing C-x C-e.



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


I thought that maybe some Vim terminal option was not properly configured, so I captured the output of:



:set termcap


from Vim started by $ vim, and from Vim started by C-x C-e.
But the output is identical in both cases:



--- 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


The output of $ stty -a is also identical in bash and zsh:



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


I'm using zsh 5.6.2-dev-1 (x86_64-pc-linux-gnu).



Is there a Vim or zsh option which should be set to prevent Vim from translating C-j into C-m when started by the zle widget edit-command-line?










share|improve this question


















  • 1




    Zsh modifies stty settings while zle is active. Running stty from a prompt shows the settings when running commands, not the settings during command line edition. This looks like a bug where it doesn't properly restore stty settings when it runs a command from within command line edition.
    – Gilles
    Nov 28 at 21:19










  • @Gilles, zsh does redirect stdin from /dev/null inside user-defined widgets, but edit-command-line does a exec < /dev/tty, but does not restore the non-zle settings, so the bug if more with that edit-command-line widget.
    – Stéphane Chazelas
    10 hours ago













up vote
2
down vote

favorite









up vote
2
down vote

favorite











I have the following code in my ~/.zshrc:



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


It binds the edit-command-line zle widget to the keysequence C-x C-e.
The widget is described in man zshcontrib (section ZLE FUNCTIONS, subsection Widgets):




edit-command-line
Edit the command line using your visual editor, as in ksh.



          bindkey -M vicmd v edit-command-line



The purpose is to be able to edit the current shell command line, in the default editor, by pressing C-x C-e, similar to what the readline function edit-and-execute-command does (man bash, section READLINE, subsection Commands for Manipulating the History).




edit-and-execute-command (C-xC-e)
Invoke an editor on the current command line, and execute the result as shell commands. Bash attempts
to invoke $VISUAL, $EDITOR, and emacs as the editor, in that order.




My default editor is Vim 8.1 (patches 1-538 included).
I have Vim mappings, using the keys C-h, C-j, C-k, C-l, to move the focus to neighbour windows.
They can be boiled down to:



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>


They all work as expected in a regular Vim instance (started by executing $ vim).
But C-j doesn't work as expected when Vim was started by edit-command-line.



When I press C-x C-e while on the shell command line, zsh starts Vim. If I split the window by executing :split, then press C-k to move to the top window, I get two windows, and the focus is moved to the top one. But then, if I press C-j to get back to the bottom window, nothing happens.



I don't know whether it's the cause of the issue, but if I try to insert a literal C-j in a Vim buffer (by pressing C-v C-j), ^M is displayed (the caret notation for a carriage return). In a regular Vim instance (started by executing $ vim), inserting a literal C-j results in a character whose caret notation is ^@ (a NUL).



I can reproduce the issue with this minimal ~/.zshrc:



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


And this minimal ~/.vimrc:



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


Pressing C-x C-e on the zsh command line starts Vim, then pressing C-j should print and log the message:



C-j has been pressed


But nothing happens.



I can't reproduce the issue in bash, nor with Neovim (v0.3.2-752-g4d7c7f9).
Besides, inserting a literal C-j in Vim, when the latter was started from bash after pressing C-x C-e, results in a NUL (^@). Same thing when Neovim is started from bash or zsh after pressing C-x C-e.



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


I thought that maybe some Vim terminal option was not properly configured, so I captured the output of:



:set termcap


from Vim started by $ vim, and from Vim started by C-x C-e.
But the output is identical in both cases:



--- 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


The output of $ stty -a is also identical in bash and zsh:



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


I'm using zsh 5.6.2-dev-1 (x86_64-pc-linux-gnu).



Is there a Vim or zsh option which should be set to prevent Vim from translating C-j into C-m when started by the zle widget edit-command-line?










share|improve this question













I have the following code in my ~/.zshrc:



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


It binds the edit-command-line zle widget to the keysequence C-x C-e.
The widget is described in man zshcontrib (section ZLE FUNCTIONS, subsection Widgets):




edit-command-line
Edit the command line using your visual editor, as in ksh.



          bindkey -M vicmd v edit-command-line



The purpose is to be able to edit the current shell command line, in the default editor, by pressing C-x C-e, similar to what the readline function edit-and-execute-command does (man bash, section READLINE, subsection Commands for Manipulating the History).




edit-and-execute-command (C-xC-e)
Invoke an editor on the current command line, and execute the result as shell commands. Bash attempts
to invoke $VISUAL, $EDITOR, and emacs as the editor, in that order.




My default editor is Vim 8.1 (patches 1-538 included).
I have Vim mappings, using the keys C-h, C-j, C-k, C-l, to move the focus to neighbour windows.
They can be boiled down to:



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>


They all work as expected in a regular Vim instance (started by executing $ vim).
But C-j doesn't work as expected when Vim was started by edit-command-line.



When I press C-x C-e while on the shell command line, zsh starts Vim. If I split the window by executing :split, then press C-k to move to the top window, I get two windows, and the focus is moved to the top one. But then, if I press C-j to get back to the bottom window, nothing happens.



I don't know whether it's the cause of the issue, but if I try to insert a literal C-j in a Vim buffer (by pressing C-v C-j), ^M is displayed (the caret notation for a carriage return). In a regular Vim instance (started by executing $ vim), inserting a literal C-j results in a character whose caret notation is ^@ (a NUL).



I can reproduce the issue with this minimal ~/.zshrc:



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


And this minimal ~/.vimrc:



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


Pressing C-x C-e on the zsh command line starts Vim, then pressing C-j should print and log the message:



C-j has been pressed


But nothing happens.



I can't reproduce the issue in bash, nor with Neovim (v0.3.2-752-g4d7c7f9).
Besides, inserting a literal C-j in Vim, when the latter was started from bash after pressing C-x C-e, results in a NUL (^@). Same thing when Neovim is started from bash or zsh after pressing C-x C-e.



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


I thought that maybe some Vim terminal option was not properly configured, so I captured the output of:



:set termcap


from Vim started by $ vim, and from Vim started by C-x C-e.
But the output is identical in both cases:



--- 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


The output of $ stty -a is also identical in bash and zsh:



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


I'm using zsh 5.6.2-dev-1 (x86_64-pc-linux-gnu).



Is there a Vim or zsh option which should be set to prevent Vim from translating C-j into C-m when started by the zle widget edit-command-line?







zsh vim






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Nov 28 at 21:06









user938271

22919




22919








  • 1




    Zsh modifies stty settings while zle is active. Running stty from a prompt shows the settings when running commands, not the settings during command line edition. This looks like a bug where it doesn't properly restore stty settings when it runs a command from within command line edition.
    – Gilles
    Nov 28 at 21:19










  • @Gilles, zsh does redirect stdin from /dev/null inside user-defined widgets, but edit-command-line does a exec < /dev/tty, but does not restore the non-zle settings, so the bug if more with that edit-command-line widget.
    – Stéphane Chazelas
    10 hours ago














  • 1




    Zsh modifies stty settings while zle is active. Running stty from a prompt shows the settings when running commands, not the settings during command line edition. This looks like a bug where it doesn't properly restore stty settings when it runs a command from within command line edition.
    – Gilles
    Nov 28 at 21:19










  • @Gilles, zsh does redirect stdin from /dev/null inside user-defined widgets, but edit-command-line does a exec < /dev/tty, but does not restore the non-zle settings, so the bug if more with that edit-command-line widget.
    – Stéphane Chazelas
    10 hours ago








1




1




Zsh modifies stty settings while zle is active. Running stty from a prompt shows the settings when running commands, not the settings during command line edition. This looks like a bug where it doesn't properly restore stty settings when it runs a command from within command line edition.
– Gilles
Nov 28 at 21:19




Zsh modifies stty settings while zle is active. Running stty from a prompt shows the settings when running commands, not the settings during command line edition. This looks like a bug where it doesn't properly restore stty settings when it runs a command from within command line edition.
– Gilles
Nov 28 at 21:19












@Gilles, zsh does redirect stdin from /dev/null inside user-defined widgets, but edit-command-line does a exec < /dev/tty, but does not restore the non-zle settings, so the bug if more with that edit-command-line widget.
– Stéphane Chazelas
10 hours ago




@Gilles, zsh does redirect stdin from /dev/null inside user-defined widgets, but edit-command-line does a exec < /dev/tty, but does not restore the non-zle settings, so the bug if more with that edit-command-line widget.
– Stéphane Chazelas
10 hours ago










1 Answer
1






active

oldest

votes

















up vote
1
down vote



accepted










If you set your $EDITOR to a script or function that does stty -a, you'll notice that the terminal settings at the time vim is called by that edit-command-line are those of zle (where inlcr which causes the terminal device driver to translate NL to CR is on among other things).



^J is the newline character, so binding it is a bit delicate.



Here, you can work around it by defining a vim function as:



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


Or add edit the STTY=sane (or STTY=-inlcr) to edit-command-line.






share|improve this answer





















    Your Answer








    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "106"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    convertImagesToLinks: false,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: null,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f484764%2fhow-to-prevent-vim-from-translating-c-j-into-c-m-when-started-by-the-zle-widget%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    1 Answer
    1






    active

    oldest

    votes








    1 Answer
    1






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes








    up vote
    1
    down vote



    accepted










    If you set your $EDITOR to a script or function that does stty -a, you'll notice that the terminal settings at the time vim is called by that edit-command-line are those of zle (where inlcr which causes the terminal device driver to translate NL to CR is on among other things).



    ^J is the newline character, so binding it is a bit delicate.



    Here, you can work around it by defining a vim function as:



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


    Or add edit the STTY=sane (or STTY=-inlcr) to edit-command-line.






    share|improve this answer

























      up vote
      1
      down vote



      accepted










      If you set your $EDITOR to a script or function that does stty -a, you'll notice that the terminal settings at the time vim is called by that edit-command-line are those of zle (where inlcr which causes the terminal device driver to translate NL to CR is on among other things).



      ^J is the newline character, so binding it is a bit delicate.



      Here, you can work around it by defining a vim function as:



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


      Or add edit the STTY=sane (or STTY=-inlcr) to edit-command-line.






      share|improve this answer























        up vote
        1
        down vote



        accepted







        up vote
        1
        down vote



        accepted






        If you set your $EDITOR to a script or function that does stty -a, you'll notice that the terminal settings at the time vim is called by that edit-command-line are those of zle (where inlcr which causes the terminal device driver to translate NL to CR is on among other things).



        ^J is the newline character, so binding it is a bit delicate.



        Here, you can work around it by defining a vim function as:



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


        Or add edit the STTY=sane (or STTY=-inlcr) to edit-command-line.






        share|improve this answer












        If you set your $EDITOR to a script or function that does stty -a, you'll notice that the terminal settings at the time vim is called by that edit-command-line are those of zle (where inlcr which causes the terminal device driver to translate NL to CR is on among other things).



        ^J is the newline character, so binding it is a bit delicate.



        Here, you can work around it by defining a vim function as:



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


        Or add edit the STTY=sane (or STTY=-inlcr) to edit-command-line.







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered 14 hours ago









        Stéphane Chazelas

        295k54559902




        295k54559902






























            draft saved

            draft discarded




















































            Thanks for contributing an answer to Unix & Linux Stack Exchange!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.





            Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


            Please pay close attention to the following guidance:


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f484764%2fhow-to-prevent-vim-from-translating-c-j-into-c-m-when-started-by-the-zle-widget%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Entries order in /etc/network/interfaces

            新発田市

            Grub takes very long (several minutes) to open Menu (in Multi-Boot-System)