![如何自定义 zsh 的 vim 模式?](https://linux22.com/image/1241556/%E5%A6%82%E4%BD%95%E8%87%AA%E5%AE%9A%E4%B9%89%20zsh%20%E7%9A%84%20vim%20%E6%A8%A1%E5%BC%8F%EF%BC%9F.png)
好的,我终于做出了重大改变。在我的 .zshenv 中,我更改了我的编辑器:
export EDITOR=vim
我有几个问题太小了,我不想为它们单独提出问题。它们如下:
如何让 zsh 像在 vim 中一样区分插入模式和命令模式?最好将光标从下划线更改为块,就像在 vim 中一样,但在底部显示文本也可以。
我如何让它更像 vim?例如,我宁愿它默认处于命令模式,而不是在执行一个命令后退出。
答案1
1.) (看http://zshwiki.org/home/examples/zlewidgets和http://pthree.org/2009/03/28/add-vim-editing-mode-to-your-zsh-prompt/):
函数 zle-line-init zle-keymap-select { RPS1="${${KEYMAP/vicmd/-- 正常 --}/(main|viins)/-- 插入 --}" RPS2=$RPS1 zle 重置提示 } zle -N zle-line-init zle -N zle-键映射-选择
在哪里:
“RPS” 代表“右提示字符串”,定义出现在终端右侧的提示,${variable/pattern/replacement} 语法是“参数扩展”,请参阅:http://mywiki.wooledge.org/BashSheet#Parameter_Operations。
'zle -N' 导致用户可定义的小部件“zle-line-init”和“zle-keymap-select”被绑定(到同名的 shell 函数),以便在初始化行编辑器和更改键映射时分别调用它们,参见:http://zsh.sourceforge.net/Doc/Release/Zsh-Line-Editor.html#SEC125。
2.) 我怀疑您必须编写另一个 zsh-widget 来执行此操作,请从第一个问题的两个链接中的第一个链接中获得启发。
答案2
akira 的解决方案在使用多行提示符时存在以下问题:从 ins 模式切换到 cmd 模式时,提示符重绘会导致从先前的输出中删除几行(并且新提示符显示在几行上方)。有多少行取决于您的提示符中有多少行。
处理该问题的方法是使用zle-line-finish
,而不使用zle reset-prompt
there 。例如:
# perform parameter expansion/command substitution in prompt
setopt PROMPT_SUBST
vim_ins_mode="[INS]"
vim_cmd_mode="[CMD]"
vim_mode=$vim_ins_mode
function zle-keymap-select {
vim_mode="${${KEYMAP/vicmd/${vim_cmd_mode}}/(main|viins)/${vim_ins_mode}}"
zle reset-prompt
}
zle -N zle-keymap-select
function zle-line-finish {
vim_mode=$vim_ins_mode
}
zle -N zle-line-finish
然后您可以将其添加到您的右提示符中,例如:
RPROMPT='${vim_mode}'
这直接摘自我的博客文章:
答案3
zle-line-init() { zle -K vicmd; }
zle -N zle-line-init
这两行确保它以命令模式启动
答案4
下面将为你设置一个修改后的光标和一个显示你处于哪种模式的提示。你可以更改DEFAULT_VI_MODE
为viins
或vicmd
。只需将以下内容粘贴到新窗口中.zshrc
即可开始:
# Prefer vi shortcuts
bindkey -v
DEFAULT_VI_MODE=viins
KEYTIMEOUT=1
__set_cursor() {
local style
case $1 in
reset) style=0;; # The terminal emulator's default
blink-block) style=1;;
block) style=2;;
blink-underline) style=3;;
underline) style=4;;
blink-vertical-line) style=5;;
vertical-line) style=6;;
esac
[ $style -ge 0 ] && print -n -- "\e[${style} q"
}
# Set your desired cursors here...
__set_vi_mode_cursor() {
case $KEYMAP in
vicmd)
__set_cursor block
;;
main|viins)
__set_cursor vertical-line
;;
esac
}
__get_vi_mode() {
local mode
case $KEYMAP in
vicmd)
mode=NORMAL
;;
main|viins)
mode=INSERT
;;
esac
print -n -- $mode
}
zle-keymap-select() {
__set_vi_mode_cursor
zle reset-prompt
}
zle-line-init() {
zle -K $DEFAULT_VI_MODE
}
zle -N zle-line-init
zle -N zle-keymap-select
# Optional: allows you to open the in-progress command inside of $EDITOR
autoload -Uz edit-command-line
bindkey -M vicmd 'v' edit-command-line
zle -N edit-command-line
# PROMPT_SUBST enables functions and variables to re-run everytime the prompt
# is rendered
setopt PROMPT_SUBST
# Single quotes are important so that function is not run immediately and saved
# in the variable
RPROMPT='$(__get_vi_mode)'
注意:我仅在 MacOS (10.12.6) 上的 Terminal.app (2.7.3) 中使用 zsh (5.3.1) 测试了此操作。此外,如果您添加,edit-command-line
则模式也将正确设置。