¿Cómo cambio al modo de edición vi en readline?

16

Quiero cambiar al modo de edición vi en un entorno de línea de lectura. Pero no quiero usar 'set -o vi'. Quiero cambiar temporalmente usando un atajo de teclado. La página del manual dice que puedo hacer esto M-C-j. Pero eso no funciona para mí.

Estoy usando Ubuntu y un xterm. Tampoco funciona bajo gnome-terminal.

Eric Johnson
fuente

Respuestas:

12

Confirmaría que la asignación de teclado Meta+ Control+ jes correcta en su sistema. Puede usar este comando para enumerar todas las combinaciones de teclas para los distintos modos de Bash. En mi sistema tampoco había una combinación de teclas.

$ bind -P| grep edit
edit-and-execute-command can be found on "\C-x\C-e".
emacs-editing-mode is not bound to any keys
vi-editing-mode is not bound to any keys

Puede hacer lo siguiente para que cuando escriba Esc+ ecambie entre los 2 modos.

$ set -o emacs
$ bind '"\ee": vi-editing-mode'
$ set -o vi
$ bind '"\ee": emacs-editing-mode'

El bindcomando ahora muestra esto:

en modo vi

$ bind -P |grep edit
edit-and-execute-command is not bound to any keys
emacs-editing-mode can be found on "\ee".
vi-editing-mode is not bound to any keys

en modo emacs

$ bind -P |grep edit
edit-and-execute-command can be found on "\C-x\C-e".
emacs-editing-mode is not bound to any keys
vi-editing-mode can be found on "\ee".

Ahora puede usar Esc+ epara alternar entre los 2 modos diferentes.

slm
fuente
Tenga en cuenta que debe ser rápido al escribir ESC E. Si hace una pausa, pasará del modo vi-insert al modo vi-command, o simplemente cancelará el comando vi actual.
spelufo
6

Bash inhabilita explícitamente este y algunos otros atajos de Readline. Consulte la initialize_readline()función en el código fuente de bash ( http://www.catonmat.net/download/bashline.c ):

   /* In Bash, the user can switch editing modes with "set -o [vi emacs]",
      so it is not necessary to allow C-M-j for context switching.  Turn
      off this occasionally confusing behaviour. */
   rl_unbind_key_in_map (CTRL('J'), emacs_meta_keymap);
   rl_unbind_key_in_map (CTRL('M'), emacs_meta_keymap);
#if defined (VI_MODE)
  rl_unbind_key_in_map (CTRL('E'), vi_movement_keymap);
#endif

Parece que no puedo anular este comportamiento usando el archivo de configuración de Readline (.inputrc).

Eric Johnson
fuente
6

Esto es lo que terminé usando para mi ~/.inputrc, basado en la respuesta de slm.

set show-mode-in-prompt on

set keymap emacs
"\ea": vi-editing-mode

set keymap vi-command
"k": history-search-backward
"j": history-search-forward
"z": emacs-editing-mode
"\ea": emacs-editing-mode

set keymap vi-insert
"\ea": emacs-editing-mode
"\C-l": clear-screen
"\C-e": end-of-line
"\C-k": kill-line

set editing-mode vi

Probé la $if mode=sintaxis, pero creo que se resuelve estáticamente (una vez, al leer el archivo), por lo que no funciona como esperaba. Por lo tanto, debemos cambiar a cada mapa de teclas y modificar sus asociaciones de teclas, incluso si se configuraron previamente en otros mapas de teclas. Al final digo con qué modo quiero comenzar.

spelufo
fuente
2

Intenté que las asignaciones con estilo emacs se usaran en modo vi. Terminé con:

set keymap vi-command
"k": history-search-backward
"j": history-search-forward

set keymap vi-insert
"\C-A": beginning-of-line
"\C-B": backward-char
"\C-D": delete-char
"\C-E": end-of-line
"\C-F": forward-char
"\C-K": kill-line
"\C-L": clear-screen
"\C-N": next-history
"\C-P": previous-history
"\C-O": operate-and-get-next

# Enable Readline not waiting for additional input when a key is pressed.
# Needed for the mappings below.
set keyseq-timeout 0

# `yank-last-arg` does not work exactly as in emacs mode
"\e.": yank-last-arg
"\e\177": backward-kill-word
"\e0": digit-argument
"\e1": digit-argument
"\e2": digit-argument
"\e3": digit-argument
"\e4": digit-argument
"\e5": digit-argument
"\e6": digit-argument
"\e7": digit-argument
"\e8": digit-argument
"\e9": digit-argument
"\eb": backward-word
"\ec": capitalize-word
"\ed": kill-word
"\ef": forward-word
"\el": downcase-word
"\en": non-incremental-forward-search-history
"\ep": non-incremental-reverse-search-history
"\et": transpose-words
"\eu": upcase-word
"\ey": yank-pop

# some other useful mappings

"\e/": complete-filename
"\ek": kill-whole-line
"\eo": "\C-v\C-j"
# quickly switch to "normal" mode
"\C-[": vi-movement-mode
# perserve the currently editing line so that we can 
# do something else before restoring it.
"\eg": insert-comment
"\er": "\C-R#\C-A\C-D\C-E"

set editing-mode vi

Es útil leer la página del manual readliney la READLINEsección de la bashpágina del manual.

Caizheng Peng
fuente