Zsh zle班次选择

时间:2011-03-23 15:46:54

标签: shell zsh zsh-zle

如何使用shift来选择部分命令行(就像许多文本编辑器一样)?

2 个答案:

答案 0 :(得分:10)

shift-arrow() {
  ((REGION_ACTIVE)) || zle set-mark-command
  zle $1
}
shift-left() shift-arrow backward-char
shift-right() shift-arrow forward-char
shift-up() shift-arrow up-line-or-history
shift-down() shift-arrow down-line-or-history
zle -N shift-left
zle -N shift-right
zle -N shift-up
zle -N shift-down

bindkey $terminfo[kLFT] shift-left
bindkey $terminfo[kRIT] shift-right
bindkey $terminfo[kri] shift-up
bindkey $terminfo[kind] shift-down

假设您的终端在 Arrow 发送的 Shift-Arrows 上发送了不同的转义序列,并且您的terminfo数据库已正确填充相应的kLFT和kRIT功能,并且您正在使用emacs样式键绑定。

或者,稍微分解代码:

shift-arrow() {
  ((REGION_ACTIVE)) || zle set-mark-command
  zle $1
}
for key  kcap seq        widget (
    left  LFT $'\e[1;2D' backward-char
    right RIT $'\e[1;2C' forward-char
    up    ri  $'\e[1;2A' up-line-or-history
    down  ind $'\e[1;2B' down-line-or-history
  ) {
  functions[shift-$key]="shift-arrow $widget"
  zle -N shift-$key
  bindkey ${terminfo[k$kcap]-$seq} shift-$key
}

上面是terminfo数据库没有信息的情况下的硬编码序列(使用xterm序列)。

答案 1 :(得分:10)

扩展了Stephane近三年前的优秀答案,我添加了一些更多的绑定,以使行为(几乎)与Windows的所有标准键盘行为完全一致:

  • 使用导航键(箭头,主页,结束)WITHOUT shift
  • 时清除选择
  • BackspaceDel删除有效选择
  • 使用Ctrl+Shift+Left / Ctrl+Shift+Right
  • 时,选择范围会扩展到下一个/上一个单词
  • Shift+HomeShift+End分别将选择范围扩展到行尾和行尾。 Ctrl+Shift+HomeCtrl+Shift+End也是这样做的。

两件不完全相同的事情:

  • 将选区扩展到下一个单词包括尾随空格,与windows不同。这可以修复,但不会打扰我。
  • 当有活动选择时键入将不会删除它并将其替换为您键入的字符。这似乎需要更多的工作来重新映射整个键盘。对我来说不值得。

请注意,默认的mintty行为是绑定Shift+EndShift+Home以访问回滚缓冲区。这取代了zsh配置;钥匙永远不会通过。为了使这些工作正常,您需要在/etc/minttyrc~/.minttyrc中配置不同的密钥(或禁用回滚)。请参阅“滚动修改器”here - 最简单的解决方案是设置ScrollMod=2以将其绑定到Alt而不是Shift

所以一切:

〜/ .minttyrc

ScrollMod=2

〜/ .zshrc

r-delregion() {
  if ((REGION_ACTIVE)) then
     zle kill-region
  else 
    local widget_name=$1
    shift
    zle $widget_name -- $@
  fi
}

r-deselect() {
  ((REGION_ACTIVE = 0))
  local widget_name=$1
  shift
  zle $widget_name -- $@
}

r-select() {
  ((REGION_ACTIVE)) || zle set-mark-command
  local widget_name=$1
  shift
  zle $widget_name -- $@
}

for key     kcap   seq        mode   widget (
    sleft   kLFT   $'\e[1;2D' select   backward-char
    sright  kRIT   $'\e[1;2C' select   forward-char
    sup     kri    $'\e[1;2A' select   up-line-or-history
    sdown   kind   $'\e[1;2B' select   down-line-or-history

    send    kEND   $'\E[1;2F' select   end-of-line
    send2   x      $'\E[4;2~' select   end-of-line

    shome   kHOM   $'\E[1;2H' select   beginning-of-line
    shome2  x      $'\E[1;2~' select   beginning-of-line

    left    kcub1  $'\EOD'    deselect backward-char
    right   kcuf1  $'\EOC'    deselect forward-char

    end     kend   $'\EOF'    deselect end-of-line
    end2    x      $'\E4~'    deselect end-of-line

    home    khome  $'\EOH'    deselect beginning-of-line
    home2   x      $'\E1~'    deselect beginning-of-line

    csleft  x      $'\E[1;6D' select   backward-word
    csright x      $'\E[1;6C' select   forward-word
    csend   x      $'\E[1;6F' select   end-of-line
    cshome  x      $'\E[1;6H' select   beginning-of-line

    cleft   x      $'\E[1;5D' deselect backward-word
    cright  x      $'\E[1;5C' deselect forward-word

    del     kdch1   $'\E[3~'  delregion delete-char
    bs      x       $'^?'     delregion backward-delete-char

  ) {
  eval "key-$key() {
    r-$mode $widget \$@
  }"
  zle -N key-$key
  bindkey ${terminfo[$kcap]-$seq} key-$key
}

这涵盖了我使用的几种不同键盘配置的键码。

注意:“key”列中的值没有任何意义,它们仅用于为zle构建命名引用。它们可以是任何东西。重要的是seqmodewidget列。

注2:您几乎可以绑定任何所需的密钥,只需要控制台模拟器中使用的密钥代码即可。打开常规控制台(不运行zsh)并键入 Ctrl + V ,然后键入所需的密钥。它应该发出代码。 ^[表示\E