首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在vi覆盖模式下,使zsh zle在backspace上恢复字符。

在vi覆盖模式下,使zsh zle在backspace上恢复字符。
EN

Stack Overflow用户
提问于 2019-08-22 07:53:13
回答 1查看 275关注 0票数 0

我在Vi模式下使用Zsh。

$KEYMAP == vicmd (即命令模式)时,我希望点击backspace将光标移动到左侧,而不删除任何内容。工作

$KEYMAP == viins && $ZLE_STATE == *insert* (即insert-模式)时,我希望单击backspace将光标移动到左边的一个字符,删除行中紧接前面的字符。工作

$KEYMAP == viins && $ZLE_STATE == *overwrite* (即覆盖模式/替换模式)时,我希望按下背板将光标移动到左边的一个字符,将前面的字符恢复到与进入覆盖模式之前最初在行的字符相同的位置。不工作

下面是一个示例:

代码语言:javascript
复制
# [COMMAND MODE] We start with the following string on the command line:
$ Hello, world!
     ^
     cursor position

# [REPLACE MODE] Now, I hit "R" to enter replace-mode and I type "stuff".
$ Helstufforld!
          ^
          cursor position

# [REPLACE MODE] Finally, I hit backspace 3 times.
$ Helst, world!
       ^
       cursor position

上面的示例显示了我在覆盖模式下访问backspace时想要发生的事情;然而,实际发生的情况如下:

代码语言:javascript
复制
# [COMMAND MODE] We start with the following string on the command line:
$ Hello, world!
     ^
     cursor position

# [REPLACE MODE] Now, I hit "R" to enter replace-mode and I type "stuff".
$ Helstufforld!
          ^
          cursor position

# [REPLACE MODE] Finally, I hit backspace 3 times.
$ Helstworld!
       ^
       cursor position

注意,在第二个示例中单击backspace时,与其还原刚刚覆盖的原始3个字符(即", w"),相反,替换这些字符(即"uff")的最后3个字符被删除,光标右侧的字符移到左侧。

我怎样才能得到我想要的行为?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-08-23 06:36:39

好的,所以我最终破解了一个解决问题的方法,我会在这里发布,以防其他人遇到同样的问题。

解决方案

把这个放进你的.zshrc

代码语言:javascript
复制
readonly ZLE_VI_MODE_CMD=0
readonly ZLE_VI_MODE_INS=1
readonly ZLE_VI_MODE_REP=2
readonly ZLE_VI_MODE_OTH=3

function zle-vi-mode {
    if [[ $KEYMAP == vicmd ]]; then
        echo -n $ZLE_VI_MODE_CMD
    elif [[ $KEYMAP == (viins|main) ]] && [[ $ZLE_STATE == *insert* ]]; then
        echo -n $ZLE_VI_MODE_INS
    elif [[ $KEYMAP == (viins|main) ]] && [[ $ZLE_STATE == *overwrite* ]]; then
        echo -n $ZLE_VI_MODE_REP
    else
        echo -n $ZLE_VI_MODE_OTH
    fi
}

function zle-backward-delete-char-fix {
    case "$(zle-vi-mode)" in
        $ZLE_VI_MODE_REP)
            if [[ $CURSOR -le $MARK ]]; then
                CURSOR=$(( $(($CURSOR-1)) > 0 ? $(($CURSOR-1)) : 0 ))
                MARK=$CURSOR
            else
                zle undo
            fi
            ;;
        *)
            zle backward-delete-char
            ;;
    esac
}

zle -N zle-backward-delete-char-fix

## Change cursor shape according to the current Vi-mode.
function zle-line-init zle-keymap-select {
    case "$(zle-vi-mode)" in
        $ZLE_VI_MODE_CMD) echo -ne '\e[2 q' ;; # cursor -> block
        $ZLE_VI_MODE_INS) echo -ne '\e[6 q' ;; # cursor -> vertical bar
        $ZLE_VI_MODE_REP)
            echo -ne '\e[4 q' # cursor -> underline
            MARK=$CURSOR
            ;;
        *)
            ;;
    esac
}

zle -N zle-line-init
zle -N zle-keymap-select

bindkey -v

bindkey '^?' zle-backward-delete-char-fix
bindkey '^h' zle-backward-delete-char-fix

此外,上面的代码将导致光标形状发生变化,这取决于您当前所处的vi模式(即,因为这是来自我的.zshrc的复制/粘贴,这正是我所喜欢的)。如果您不希望这样做,并且只需要简单的修复,请用以下方法替换zle-init-line / zle-keymap-select函数:

代码语言:javascript
复制
function zle-line-init zle-keymap-select {
    case "$(zle-vi-mode)" in
        $ZLE_VI_MODE_REP)
            MARK=$CURSOR
            ;;
        *)
            ;;
    esac
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57604539

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档