shell 检测Vi视觉模式的zsh KEYMAP模式

mtb9vblg  于 2023-02-19  发布在  Shell
关注(0)|答案(2)|浏览(151)

Zsh使用zle函数检查提示符的状态。
有一个KEYMAP变量,它应该根据您使用的Vi模式保存某些值。
它在INSERTCOMMAND模式下工作正常,但我无法获得VISUAL模式的触发器。
来自Zsh手册:
18.2键Map
ZLE中的键Map包含键序列和ZLE命令之间的一组绑定。不能绑定空的键序列。
任何时候都可以有任意数量的键Map,每个键Map都有一个或多个名称。如果所有键Map的名称都被删除,它就会消失。bindkey可以用来操作键Map名称。
最初,有八个键Map:
emacs EMACS仿真
viins vi仿真-插入模式
vicmd vi仿真-命令模式
viopp vi仿真-操作员挂起
可视虚拟仿真-选择活动
isearch增量搜索模式
命令读取命令名
. safe回退键Map
我尝试了以下方法:

function zle-keymap-select {
    echo $KEYMAP
}
zle -N zle-keymap-select

但是输出在vicmdmain之间不断变化,当我按v进入视觉模式时没有输出。

mo49yndu

mo49yndu1#

完全正确,我可以理解你的担心,如果你不介意使用插件,我认为下面的一个可以帮助你完美,也是额外的奖金更好的体验vi模式等

zsh-vi模式:ZSH的一个更好更友好的vi(vim)模式插件。

https://github.com/jeffreytse/zsh-vi-mode
这个插件提供了一个ZVM_MODE变量,用于检索当前的vi模式并更好地显示指示器。
目前支持以下几种模式:

ZVM_MODE_NORMAL
ZVM_MODE_INSERT
ZVM_MODE_VISUAL
ZVM_MODE_VISUAL_LINE

要更新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...
      ;;
  esac
}

下面是一个例子:

gg58donl

gg58donl2#

如果不想使用额外的zsh插件,可以使用下面这段代码来检测INSERT、NORMAL、VISUAL、V-LINE和REPLACE模式:

case "${KEYMAP}" in
    vicmd)
        case "${REGION_ACTIVE}" in
            1)
                VI_KEYMAP="VISUAL"
                ;;
            2)
                VI_KEYMAP="V-LINE"
                ;;
            *)
                VI_KEYMAP="NORMAL"
                ;;
        esac
        ;;
    viins|main)
        if [[ "${ZLE_STATE}" == *overwrite* ]]; then
            VI_KEYMAP="REPLACE"
        else
            VI_KEYMAP="INSERT"
        fi
        ;;
esac

您可以添加一个线预重绘挂接,以便在每次键Map更改时更新PROMPT字符串:

autoload -U add-zle-hook-widget

function line_pre_redraw {
    local previous_vi_keymap="${VI_KEYMAP}"

    case "${KEYMAP}" in
        vicmd)
            case "${REGION_ACTIVE}" in
                1)
                    VI_KEYMAP="VISUAL"
                    ;;
                2)
                    VI_KEYMAP="V-LINE"
                    ;;
                *)
                    VI_KEYMAP="NORMAL"
                    ;;
            esac
            ;;
        viins|main)
            if [[ "${ZLE_STATE}" == *overwrite* ]]; then
                VI_KEYMAP="REPLACE"
            else
                VI_KEYMAP="INSERT"
            fi
            ;;
    esac

    if [[ "${VI_KEYMAP}" != "${previous_vi_keymap}" ]]; then
        zle reset-prompt
    fi

}
add-zle-hook-widget zle-line-pre-redraw line_pre_redraw

请参阅我的zsh主题,以获得更改光标形状和提示模式指示器的完整示例:https://github.com/IngoMeyer441/steeef.

相关问题