Wie wechsle ich in readline in den vi-Bearbeitungsmodus?

16

Ich möchte in einer Readline-Umgebung in den vi-Bearbeitungsmodus wechseln. Aber ich möchte 'set -o vi' nicht verwenden. Ich möchte vorübergehend über eine Tastenkombination wechseln. Die Manpage sagt, dass ich das machen kann M-C-j. Aber das funktioniert bei mir nicht.

Ich benutze Ubuntu und ein xterm. Funktioniert auch nicht unter dem Gnome-Terminal.

Eric Johnson
quelle

Antworten:

12

Ich würde bestätigen , dass die Tastaturbelegung Meta+ Control+ ist jin der Tat richtig auf Ihrem System. Mit diesem Befehl können Sie alle Tastaturbelegungen für die verschiedenen Modi von Bash auflisten. Auf meinem System gab es auch keine Tastenkombination.

$ 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

Sie können Folgendes tun, um bei der Eingabe von Esc+ ezwischen den beiden Modi umzuschalten.

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

Der bindBefehl zeigt nun Folgendes:

im vi-Modus

$ 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

im emacs modus

$ 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".

Jetzt können Sie mit Esc+ ezwischen den 2 verschiedenen Modi wechseln.

slm
quelle
Beachten Sie, dass Sie beim Tippen schnell sein müssen ESC E. Wenn Sie anhalten, wechseln Sie vom vi-Einfügemodus in den vi-Befehlsmodus oder brechen einfach den aktuellen vi-Befehl ab.
Spelufo
6

Bash deaktiviert diese und einige andere Readline-Verknüpfungen explizit. Siehe die initialize_readline()Funktion im Bash-Quellcode ( 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

Ich bin anscheinend nicht in der Lage, dieses Verhalten mithilfe der Readline-Konfigurationsdatei (.inputrc) zu überschreiben.

Eric Johnson
quelle
6

~/.inputrcFolgendes habe ich für meine verwendet , basierend auf der Antwort von 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

Ich habe die $if mode=Syntax ausprobiert , aber ich denke, dass sie statisch aufgelöst ist (einmal beim Lesen der Datei), sodass sie nicht wie erwartet funktioniert. Daher müssen wir zu jeder Tastaturbelegung wechseln und ihre Tastaturbelegung ändern, auch wenn sie zuvor auf einer anderen Tastaturbelegung festgelegt wurde. Am Ende sage ich mit welchem ​​Modus ich anfangen möchte.

spelufo
quelle
2

Ich habe versucht, Emacs-Mappings im vi-Modus zu verwenden. Ich endete mit:

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 ist hilfreich, die Manpage für readlineund den READLINEAbschnitt auf der bashManpage zu lesen .

Caizheng Peng
quelle