Shell

如何使用 emacs 插入模式和 vi 命令模式設置混合讀取線?

  • June 30, 2020

我想要一種混合模式,預設情況下我可以使用所有預設keymap emacs鍵綁定,並且仍然能夠更改為vi-command模式。

我該如何設置?

在這里這裡閱讀了@Tom Hale的答案 。

我認為不是將vi-insert綁定移動到emacs,而是將綁定移動emacsvi-insert. 原因是vi-command具有切換到的綁定,vi-insert並且很難模擬使其切換到emacs模式的功能。

例如,A命令vi-command預設為vi-append-eol(附加在行尾並切換到vi-insert)。

您無法A切換到emacs模式,因為它綁定到函式而不是宏。

例如,這行不通

"A": vi-append-eol emacs-editing-mode

也不是這個,使用@Tom Hale回答

"A": vi-append-eol "\ee"

你可以這樣做:

"A": "$a\ee"

但是現在這取決於"a",vi-append-mode命令,它也需要被反彈。"a"那時可以前進"i""i"可以切換到emacs. 有一整套命令可以翻譯成宏,這很痛苦。

所以你最好將emacs綁定移動到vi-insert.


所以我們想要設置vi-insert唯一的綁定emacs 並且我們想要決定使用哪個綁定,如果它們對相同的鍵序列有不同的綁定。如果它們具有完全相同的綁定,我們將忽略它們。

這可以用這個命令來完成

comm -3\
 <(INPUTRC=/dev/null bash -c 'bind -pm emacs' |
   LC_ALL='C' grep -vE '^#|: (do-lowercase-version|self-insert)$' |
   sort) \
 <(INPUTRC=/dev/null bash -c 'bind -pm vi-insert' |
   LC_ALL='C' grep -vE '^#|: (do-lowercase-version|self-insert)$' |
   sort) | cat

這裡| cat解釋了存在的原因

丟棄了“完全相同的-3綁定”因此您瀏覽此列表並在左列中查找綁定。對於左列上的每個綁定:

如果同一個鍵序列存在重複綁定,比如

"\C-d": delete-char
   "\C-d": vi-eof-maybe

選擇其中之一。如果你想要那個vi-insert(在右邊),你可以刪除這兩行,因為我們將添加這些vi-insert已經有綁定的vi-insert綁定。如果你想要那個emacs(在左邊),刪除那個vi-insert

如果右列 ( ) 上存在唯一綁定vi-insert,例如

   "\e": vi-movement-mode

刪除它,因為 `vi-insert 已經有了它。

其餘綁定將位於左列 ( emacs)。不要管這些,因為我們會將這些添加到vi-insert.


這是我選擇.inputrcemacs綁定添加到vi-insert.

我決定不在@Tom Hale回答"kj"中使用to 切換到vi-command,因為它可以完成,將您從to 帶到另一個將您從to 。實際上,除了二十一點之外,還有包含 kj單詞和帶有 jk 的單詞(主要是地名)"\ee"``emacs``vi-insert``"\e"``vi-insert``vi-command

我留著"\C-d": delete-char扔了"\C-d": vi-eof-maybe。因為我可以只使用Enterforvi-eof-maybe並且我不想通過按 意外退出 readline "\C-d"。這意味著刪除"\C-d": vi-eof-maybe綁定,因為我們正在使用綁定覆蓋vi-eof-maybe模式vi-insert中的delete-char綁定。

我保留"\C-n": menu-complete了,而不是"\C-n": next-history因為我可以使用向下箭頭next-history。這意味著刪除兩個綁定,因為vi-insert已經有了menu-complete綁定。

我保留"\C-p": menu-complete-backward而不是"\C-p": previous-history因為我可以按向上箭頭previous-history。這意味著刪除兩個綁定,因為vi-insert已經有了menu-complete-backward綁定。

我保留"\C-w": vi-unix-word-rubout而不是"\C-w": unix-word-rubout. 我不知道有什麼區別。我只是堅持了vi-insert一個。這意味著刪除兩個綁定,因為vi-insert已經有了vi-unix-word-rubout綁定。

我保持著"\e": vi-movement-mode。這意味著刪除這個綁定,因為vi-insert已經有了這個vi-movement-mode綁定。

set editing-mode vi

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

set keymap vi-command
"\ee": emacs-editing-mode

# key bindings to get out of vi-editing-mode
set keymap vi-insert
"\ee": emacs-editing-mode

# emacs keybindings in vi-insert mode
"\C-@": set-mark
"\C-]": character-search
"\C-_": undo
"\C-a": beginning-of-line
"\C-b": backward-char
"\C-d": delete-char
"\C-e": end-of-line
"\C-f": forward-char
"\C-g": abort
"\C-k": kill-line
"\C-l": clear-screen
"\C-o": operate-and-get-next
"\C-q": quoted-insert
"\C-x!": possible-command-completions
"\C-x$": possible-variable-completions
"\C-x(": start-kbd-macro
"\C-x)": end-kbd-macro
"\C-x*": glob-expand-word
"\C-x/": possible-filename-completions
"\C-x@": possible-hostname-completions
"\C-x\C-?": backward-kill-line
"\C-x\C-e": edit-and-execute-command
"\C-x\C-g": abort
"\C-x\C-r": re-read-init-file
"\C-x\C-u": undo
"\C-x\C-v": display-shell-version
"\C-x\C-x": exchange-point-and-mark
"\C-xe": call-last-kbd-macro
"\C-xg": glob-list-expansions
"\C-x~": possible-username-completions
"\e ": set-mark
"\e!": complete-command
"\e#": insert-comment
"\e$": complete-variable
"\e&": tilde-expand
"\e*": insert-completions
"\e-": digit-argument
"\e.": insert-last-argument
"\e.": yank-last-arg
"\e/": complete-filename
"\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
"\e<": beginning-of-history
"\e=": possible-completions
"\e>": end-of-history
"\e?": possible-completions
"\e@": complete-hostname
"\e\C-?": backward-kill-word
"\e\C-]": character-search-backward
"\e\C-e": shell-expand-line
"\e\C-g": abort
"\e\C-h": backward-kill-word
"\e\C-i": dynamic-complete-history
"\e\C-r": revert-line
"\e\C-y": yank-nth-arg
"\e\\": delete-horizontal-space
"\e\e": complete
"\e^": history-expand-line
"\e_": insert-last-argument
"\e_": yank-last-arg
"\eb": backward-word
"\ec": capitalize-word
"\ed": kill-word
"\ef": forward-word
"\eg": glob-complete-word
"\el": downcase-word
"\en": non-incremental-forward-search-history
"\ep": non-incremental-reverse-search-history
"\er": revert-line
"\et": transpose-words
"\eu": upcase-word
"\ey": yank-pop
"\e{": complete-into-braces
"\e~": complete-username

更新

我想我做得好一點。有一段時間,我重新打開"jk"mooshing 切換到,vi command因為按下"\e"切換到vi-command有延遲,因為很多emacs命令轉移到vi-insert用作"\e"領導者。

這顯示了"jk"註釋掉的哞哞聲。我目前使用"\ee"循環模式。我沒有取消綁定"\e"to switch from vi-inserttovi-command因為我認為沒有必要。所以它的效果是,如果你按下"\e"vi-insert等待,你會去vi-command

要從vi-commandto 開始vi-insert,您只需按下命令之一,例如"A"允許"i"在 3 種模式之間循環不會受到傷害,因為您也可以在 2種vi模式之間循環。

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

set keymap vi-command
"\ee": emacs-editing-mode

# key bindings to get out of vi-editing-mode
set keymap vi-insert
# Choose one of these editor switching modes
# 
# moosh jk to switch
#"\ee": emacs-editing-mode
#"\ejk": vi-movement-mode
#"\ekj": vi-movement-mode
#
# "\ee" to cycle
# can unmap "\e" to switch to vi-command but don't see a need
#"\e":
"\ee": vi-movement-mode

更新

In vi-insert,"\C-w"綁定到 `vi-unix-word-rubout,它在單詞邊界或其他地方停止。我不喜歡那個功能。

例如,試試這個

$ cannot-delete'
# press left arrow to go back behind the single quote
# press \C-w in vi-insert to try to delete cannot-delete, it won't work

此錯誤報告描述了該問題,儘管我對提供的範例沒有問題。

所以你可以綁定"\C-w"到 emacsunix-word-rubout來解決這個問題。

要重新綁定"\C-w",您可能需要取消綁定預設值

# In .bashrc
stty werase undef

如果您想取消綁定所有預設值:

# In .inputrc
set bind-tty-special-chars off

不確定這是否重要,但我在 macOS 上,所以我刪除了其他預設綁定

然後在你的.inputrc

"\C-w": unix-word-rubout

引用自:https://unix.stackexchange.com/questions/303631