一个更好、更友好的 ZSH vi(vim) 模式插件。
ZSH
插件。 也许你体验过 Zsh 中的默认 Vi 模式,开启默认 Vi 模式后,你逐渐发现它有很多问题,有些功能不完善或不存在,有些行为甚至与原生 Vi 不同(Vim ) 模式。
虽然默认的 Vi 模式有点尴尬和不愉快,但你还是继续使用它,并在使用了一段时间后逐渐失去了兴趣。最终,你失望地放弃了。
你已经很久没有想到Vi模式了,有一天你无意中发现了这个插件,你读到这里才意识到这个插件就是为了解决上述问题,让你重新爱上Vi模式。脸上突然浮现出笑容,就像重获美好生活一样。
冬天来了,春天还会远吗?
10p
和4fa
(进行中)。ZSH:>= 5.1.0
在.zshrc
中捆绑zsh-vi-mode
antigen bundle jeffreytse/zsh-vi-mode
将zsh-vi-mode
作为插件加载到.zshrc
中
zplug " jeffreytse/zsh-vi-mode "
在.zshrc
中包含加载命令
zgen load jeffreytse/zsh-vi-mode
在.zshrc
中包含加载命令
zinit ice depth=1
zinit light jeffreytse/zsh-vi-mode
注意: depth=1
冰的使用是可选的,此插件既不推荐也不官方支持其他类型的冰。
将zsh-vi-mode
克隆到您的自定义插件存储库中
git clone https://github.com/jeffreytse/zsh-vi-mode
$ZSH_CUSTOM /plugins/zsh-vi-mode
然后作为插件加载到.zshrc
中
plugins+=(zsh-vi-mode)
请记住,需要在获取oh-my-zsh.sh
之前添加插件。
将zsh-vi-mode
添加到您的插件文件(例如~/.zsh_plugins.txt
)
jeffreytse/zsh-vi-mode
将zsh-vi-mode
作为插件加载到.zshrc
中
plug " jeffreytse/zsh-vi-mode "
将zsh-vi-mode
作为插件加载到.zimrc
中
zmodule jeffreytse/zsh-vi-mode
对于Homebrew用户,可以通过以下命令安装
brew install zsh-vi-mode
然后将其源到您的.zshrc
(或.bashrc
)
source $( brew --prefix ) /opt/zsh-vi-mode/share/zsh-vi-mode/zsh-vi-mode.plugin.zsh
对于Arch Linux用户,可以通过以下命令安装
yay -S zsh-vi-mode
或最新更新(不稳定)
yay -S zsh-vi-mode-git
然后将其源到您的.zshrc
(或.bashrc
)
source /usr/share/zsh/plugins/zsh-vi-mode/zsh-vi-mode.plugin.zsh
对于 Nix 用户,从 e7e3480530b34a9fe8cb52963ec2cf66e6707e15 开始,您可以通过以下配置获取插件
programs = {
zsh = {
interactiveShellInit = ''
source ${ pkgs . zsh-vi-mode } /share/zsh-vi-mode/zsh-vi-mode.plugin.zsh
'' ;
} ;
} ;
或者如果您更喜欢home-manager
:
home-manager . users . [ your username ] = { pkgs , ... } : {
programs = {
zsh = {
initExtra = ''
source ${ pkgs . zsh-vi-mode } /share/zsh-vi-mode/zsh-vi-mode.plugin.zsh
'' ;
} ;
} ;
} ;
您还可以使用home-manager
的内置“插件”功能:
home-manager . users . [ your username ] = { pkgs , ... } : {
programs = {
zsh = {
plugins = [
{
name = "vi-mode" ;
src = pkgs . zsh-vi-mode ;
file = "share/zsh-vi-mode/zsh-vi-mode.plugin.zsh" ;
}
] ;
} ;
} ;
} ;
Fig 将应用程序、快捷方式和自动完成功能添加到您现有的终端。
只需一键安装zsh-vi-mode
。
可用于 dm9pZCAq 覆盖层
eselect repository enable dm9pZCAq
emerge --sync dm9pZCAq
emerge app-shells/zsh-vi-mode
然后将其源到您的.zshrc
(或.bashrc
)
source /usr/share/zsh/site-contrib/zsh-vi-mode/zsh-vi-mode.plugin.zsh
将此存储库克隆到某处(例如$HOME/.zsh-vi-mode
)
git clone https://github.com/jeffreytse/zsh-vi-mode.git $HOME /.zsh-vi-mode
然后将其源到您的.zshrc
(或.bashrc
)
source $HOME /.zsh-vi-mode/zsh-vi-mode.plugin.zsh
使用ESC
或CTRL-[
进入Normal mode
。
但有些人可能喜欢自定义转义键,例如jj
、 jk
等,如果您想自定义转义键,可以从这里了解更多信息。
ctrl-p
: 历史记录中的上一个命令ctrl-n
:历史记录中的下一个命令/
: 在历史记录中向后搜索n
: 重复最后一个/
Normal mode
默认使用块状光标指示, Insert mode
默认使用梁状光标指示。
在Normal mode
下,您可以使用vv
在编辑器(例如vi
/ vim
/ nvim
...)中编辑当前命令行,因为它与Visual mode
绑定。
您可以通过ZVM_VI_EDITOR
选项更改编辑器,默认为$EDITOR
。
$
:到行尾^
:到该行的第一个非空白字符0
:到该行的第一个字符w
: [计数] 字数W
: 向前 [count] 个字e
:转发到单词末尾 [count](含)E
: 转发到 WORD 末尾 [count](含)b
: 向后 [count] 个单词B
: 向后 [count] 个字t{char}
:直到右侧第 [count] 次出现 {char} 之前T{char}
:直到左侧第 [count] 次出现 {char} 之前f{char}
:到右侧第 [count] 次出现的 {char}F{char}
:到左侧第 [count] 次出现的 {char};
:重复最近的 f、t、F 或 T [count] 次,
: 以相反方向重复最新的 f、t、F 或 T i
: 在光标前插入文本I
:在该行的第一个字符之前插入文本a
: 在光标后添加文本A
: 在行尾添加文本o
:在当前命令行下方插入新命令行O
:在当前命令行上方插入新命令行环绕声操作有两种键绑定模式,默认为classic
模式,您可以通过设置ZVM_VI_SURROUND_BINDKEY
选项来选择模式。
classic
模式(动词->s->环绕)S"
: 添加"
用于视觉选择ys"
: 添加"
进行视觉选择cs"'
: 将"
更改为'
ds"
: 删除"
s-prefix
模式(s->动词->环绕)sa"
: 添加"
进行视觉选择sd"
:删除"
sr"'
: 将"
更改为'
请注意,必须以相当快的速度连续按下按键序列以避免超时。您可以使用ZVM_KEYTIMEOUT
选项延长此超时。
vi"
: 选择引号内的文本对象va(
: 选择包含括号的文本对象然后您可以对选择进行任何操作:
vi"
-> S[
或sa[
=> "object"
-> "[object]"
va"
-> S[
或sa[
=> "object"
-> ["object"]
di(
或vi(
-> d
ca(
或va(
-> c
yi(
或vi(
-> y
在正常模式下,输入ctrl-a
将增加到下一个关键字,输入ctrl-x
将减少到下一个关键字。关键字可以位于光标处,也可以位于光标右侧(同一行)。关键字可以如下:
例如:
9
=> 10
aa99bb
=> aa100bb
aa100bc
=> aa101bc
0xDe
=> 0xdf
0Xdf
=> 0Xe0
0b101
=> 0b110
0B11
=> 0B101
true
=> false
yes
=> no
on
=> off
T
=> F
Fri
=> Sat
Oct
=> Nov
Monday
=> Tuesday
January
=> February
+
=> -
++
=> --
==
=> !=
!==
=> ===
&&
=> ||
and
=> or
100
=> 99
aa100bb
=> aa99bb
0
=> -1
0xdE0
=> 0xDDF
0xffFf0
=> 0xfffef
0xfffF0
=> 0xFFFEF
0x0
=> 0xffffffffffffffff
0Xf
=> 0Xe
0b100
=> 0b010
0B100
=> 0B011
True
=> False
On
=> Off
Sun
=> Sat
Jan
=> Dec
Monday
=> Sunday
August
=> July
/
=> *
++
=> --
==
=> !=
!==
=> ===
||
=> &&
or
=> and
您可以使用以下选项来自定义更符合您口味的转义键,例如jj
或jk
等。
ZVM_VI_ESCAPE_BINDKEY
:所有模式下的 vi 转义键(默认为^[
=> ESC
)ZVM_VI_INSERT_ESCAPE_BINDKEY
:插入模式下的 vi 转义键(默认为$ZVM_VI_ESCAPE_BINDKEY
)ZVM_VI_VISUAL_ESCAPE_BINDKEY
:可视模式下的 vi 转义键(默认为$ZVM_VI_ESCAPE_BINDKEY
)ZVM_VI_OPPEND_ESCAPE_BINDKEY
:操作员挂起模式下的 vi 转义键(默认为$ZVM_VI_ESCAPE_BINDKEY
)例如:
# Only changing the escape key to `jk` in insert mode, we still
# keep using the default keybindings `^[` in other modes
ZVM_VI_INSERT_ESCAPE_BINDKEY=jk
该插件支持选择readkey引擎来读取和处理按键事件。通过ZVM_READKEY_ENGINE
选项很容易做到,目前支持以下引擎:
ZVM_READKEY_ENGINE_NEX
:它是一个更好的 readkey 引擎,可以替代 ZLE(Beta)。ZVM_READKEY_ENGINE_ZLE
:它是 Zsh 的默认 readkey 引擎(ZLE)。ZVM_READKEY_ENGINE_DEFAULT
:它是这个插件的默认引擎(现在是NEX引擎)。NEX 是比 Zsh 的 ZLE 引擎更好的读取和处理关键事件的引擎,目前 NEX 引擎仍处于测试阶段,如果您愿意,您可以改回 Zsh 的 ZLE 引擎。
例如:
# Change to Zsh's default readkey engine
ZVM_READKEY_ENGINE= $ZVM_READKEY_ENGINE_ZLE
您可以使用ZVM_KEYTIMEOUT
选项来调整等待下一个按键的按键输入超时时间,默认为0.4
秒。
转义键是一种特殊情况,它可以单独使用。 NEX 引擎在收到转义字符后等待一段时间,以确定它是独立的还是转义序列的一部分。等待期间,额外的按键会使转义键充当元键。如果没有其他按键输入,则将其作为独立转义处理。
对于NEX引擎,我们可以使用ZVM_ESCAPE_KEYTIMEOUT
选项来调整Escape键的等待超时时间,默认为0.03
秒。
由于有些配置选项依赖于插件中定义的某些变量,但有些则不然。我们需要提供统一的配置入口功能。入口函数的名称存储在名为ZVM_CONFIG_FUNC
的选项中,默认值为zvm_config
,您可以更改为其他值以适合您的口味。
如果这个配置函数存在,它会被自动调用,你可以在使用这个插件之前做一些这方面的配置。例如:
function zvm_config() {
ZVM_LINE_INIT_MODE= $ZVM_MODE_INSERT
ZVM_VI_INSERT_ESCAPE_BINDKEY=jk
}
source ~ /zsh-vi-mode.zsh
该插件提供了一种执行额外命令的机制,现在您可以通过以下方面来执行某些操作:
zvm_before_init_commands=()
zvm_after_init_commands=()
zvm_before_select_vi_mode_commands=()
zvm_after_select_vi_mode_commands=()
zvm_before_lazy_keybindings_commands=()
zvm_after_lazy_keybindings_commands=()
由于默认的初始化模式,该插件会覆盖之前的按键绑定,这会导致其他插件(即fzf
、 zsh-autocomplete
等)的按键绑定失败。
您可以通过以下方式解决兼容性问题:
# Append a command directly
zvm_after_init_commands+=( ' [ -f ~/.fzf.zsh ] && source ~/.fzf.zsh ' )
或者
# Define an init function and append to zvm_after_init_commands
function my_init() {
[ -f ~ /.fzf.zsh ] && source ~ /.fzf.zsh
}
zvm_after_init_commands+=(my_init)
或者
# The plugin will auto execute this zvm_after_init function
function zvm_after_init() {
[ -f ~ /.fzf.zsh ] && source ~ /.fzf.zsh
}
或者如果您正在使用zinit
:
# For postponing loading `fzf`
zinit ice lucid wait
zinit snippet OMZP::fzf
默认情况下,延迟键绑定功能已启用, normal
和visual
模式的所有键绑定都应由zvm_after_lazy_keybindings_commands
执行。例如:
# The plugin will auto execute this zvm_after_lazy_keybindings function
function zvm_after_lazy_keybindings() {
bindkey -M vicmd ' s ' your_normal_widget
bindkey -M visual ' n ' your_visual_widget
}
该插件有两个功能供您定义自定义小部件和键绑定。如果出现不必要的问题,最好使用它们,尤其是遇到关键冲突时。
要定义自定义小部件,您应该:
# If [your_custom_widget] were ignored, it will be the same with <your_custom_widget>
zvm_define_widget < your_custom_widget > [your_custom_function]
要定义键绑定,您应该:
zvm_bindkey < keymap > < keys > < widget >
例如:
# Your custom widget
function my_custom_widget() {
echo ' Hello, ZSH! '
}
# The plugin will auto execute this zvm_after_lazy_keybindings function
function zvm_after_lazy_keybindings() {
# Here we define the custom widget
zvm_define_widget my_custom_widget
# In normal mode, press Ctrl-E to invoke this widget
zvm_bindkey vicmd ' ^E ' my_custom_widget
}
该插件提供了一个ZVM_MODE
变量,供您检索当前的 vi 模式并更好地显示指示器。
目前支持以下模式:
ZVM_MODE_NORMAL
ZVM_MODE_INSERT
ZVM_MODE_VISUAL
ZVM_MODE_VISUAL_LINE
ZVM_MODE_REPLACE
为了更新 vi 模式指示器,我们应该将命令添加到zvm_after_select_vi_mode_commands
。例如:
# The plugin will auto execute this zvm_after_select_vi_mode function
function zvm_after_select_vi_mode() {
case $ZVM_MODE in
$ZVM_MODE_NORMAL )
# Something you want to do...
;;
$ZVM_MODE_INSERT )
# Something you want to do...
;;
$ZVM_MODE_VISUAL )
# Something you want to do...
;;
$ZVM_MODE_VISUAL_LINE )
# Something you want to do...
;;
$ZVM_MODE_REPLACE )
# Something you want to do...
;;
esac
}
该插件为用户提供了一些自定义光标样式的选项,以实现更好的终端兼容性。
ZVM_CURSOR_STYLE_ENABLED
选项禁用此功能(默认为true
) # Disable the cursor style feature
ZVM_CURSOR_STYLE_ENABLED=false
# The prompt cursor in normal mode
ZVM_NORMAL_MODE_CURSOR
# The prompt cursor in insert mode
ZVM_INSERT_MODE_CURSOR
# The prompt cursor in visual mode
ZVM_VISUAL_MODE_CURSOR
# The prompt cursor in visual line mode
ZVM_VISUAL_LINE_MODE_CURSOR
# The prompt cursor in operator pending mode
ZVM_OPPEND_MODE_CURSOR
ZVM_CURSOR_USER_DEFAULT
ZVM_CURSOR_BLOCK
ZVM_CURSOR_UNDERLINE
ZVM_CURSOR_BEAM
ZVM_CURSOR_BLINKING_BLOCK
ZVM_CURSOR_BLINKING_UNDERLINE
ZVM_CURSOR_BLINKING_BEAM
ZVM_INSERT_MODE_CURSOR= $ZVM_CURSOR_BEAM
ZVM_NORMAL_MODE_CURSOR= $ZVM_CURSOR_BLOCK
ZVM_OPPEND_MODE_CURSOR= $ZVM_CURSOR_UNDERLINE
# The plugin will auto execute this zvm_config function
zvm_config () {
# Retrieve default cursor styles
local ncur= $( zvm_cursor_style $ZVM_NORMAL_MODE_CURSOR )
local icur= $( zvm_cursor_style $ZVM_INSERT_MODE_CURSOR )
# Append your custom color for your cursor
ZVM_INSERT_MODE_CURSOR= $icur ' ee]12;reda '
ZVM_NORMAL_MODE_CURSOR= $ncur ' ee]12;#008800a '
}
我们可以使用ZVM_TERM
选项设置插件的术语类型来处理终端转义序列,默认为$TERM
。它可以是xterm-256color
、 alacritty-256color
、 st-256color
等。对于某些终端模拟器来说,正确显示光标非常重要。
您可以使用ZVM_VI_HIGHLIGHT_BACKGROUND
、 ZVM_VI_HIGHLIGHT_FOREGROUND
和ZVM_VI_HIGHLIGHT_EXTRASTYLE
来更改高亮行为(环绕、视线等),颜色值可以是颜色名称或十六进制颜色值。
例如:
ZVM_VI_HIGHLIGHT_FOREGROUND=green # Color name
ZVM_VI_HIGHLIGHT_FOREGROUND= # 008800 # Hex value
ZVM_VI_HIGHLIGHT_BACKGROUND=red # Color name
ZVM_VI_HIGHLIGHT_BACKGROUND= # ff0000 # Hex value
ZVM_VI_HIGHLIGHT_EXTRASTYLE=bold,underline # bold and underline
您可以通过ZVM_LINE_INIT_MODE
选项设置命令行初始模式。
目前支持以下模式:
ZVM_MODE_LAST
:从最后一个模式开始(默认)。ZVM_MODE_INSERT
:从插入模式开始。ZVM_MODE_NORMAL
:从正常模式开始。例如:
# Always starting with insert mode for each command line
ZVM_LINE_INIT_MODE= $ZVM_MODE_INSERT
该插件支持惰性键绑定功能,并且默认启用。要禁用它,您可以在加载此插件之前将选项ZVM_LAZY_KEYBINDINGS
设置为false
。此功能会将normal
和visual
模式的所有按键绑定推迟到您第一次进入普通模式时。
它可以大大提高启动速度,特别是你打开终端只想执行一个简单的命令。
为了防止插件来源顺序引起的与按键绑定相关的各种问题,并保持该插件的相同功能,该插件的初始化被推迟到第一个命令行启动。
然而,几乎所有插件都是在获取脚本时初始化的。因此,该插件提供了一个选项ZVM_INIT_MODE
来更改初始化模式。
例如:
# Do the initialization when the script is sourced (i.e. Initialize instantly)
ZVM_INIT_MODE=sourcing
非常感谢问题和请求请求。如果您之前从未为开源项目做出过贡献,我非常乐意引导您完成如何创建拉取请求。
您可以首先打开一个问题来描述您想要解决的问题,我们将从那里开始。
该主题已获得 MIT 许可 © Jeffrey Tse 的许可。