42

我在 Ubuntu 机器上将 zsh 作为默认 shell 运行,并且使用 gnome-terminal (据我所知模拟 xterm)一切正常。当我通过 ssh 和 putty(也模拟 xterm)从 Windows 框登录时,突然主页/结束键不再起作用。

我已经能够解决将这些行添加到我的 zshrc 文件中的问题...

bindkey '\e[1~' beginning-of-line
bindkey '\e[4~' end-of-line

...但我仍然想知道这里有什么问题。任何的想法?

4

8 回答 8

80

我发现这是一个组合:

ZSH 开发人员认为 ZSH 不应该定义Home, End, Del, ... 键的操作。

/etc/zsh/zshrcDebian 和 Ubuntu 通过定义普通用户在全局文件中期望的正常操作来解决这个问题。按照相关代码(在 Debian 和 Ubuntu 上相同):

if [[ "$TERM" != emacs ]]; then
[[ -z "$terminfo[kdch1]" ]] || bindkey -M emacs "$terminfo[kdch1]" delete-char
[[ -z "$terminfo[khome]" ]] || bindkey -M emacs "$terminfo[khome]" beginning-of-line
[[ -z "$terminfo[kend]" ]] || bindkey -M emacs "$terminfo[kend]" end-of-line
[[ -z "$terminfo[kich1]" ]] || bindkey -M emacs "$terminfo[kich1]" overwrite-mode
[[ -z "$terminfo[kdch1]" ]] || bindkey -M vicmd "$terminfo[kdch1]" vi-delete-char
[[ -z "$terminfo[khome]" ]] || bindkey -M vicmd "$terminfo[khome]" vi-beginning-of-line
[[ -z "$terminfo[kend]" ]] || bindkey -M vicmd "$terminfo[kend]" vi-end-of-line
[[ -z "$terminfo[kich1]" ]] || bindkey -M vicmd "$terminfo[kich1]" overwrite-mode

[[ -z "$terminfo[cuu1]" ]] || bindkey -M viins "$terminfo[cuu1]" vi-up-line-or-history
[[ -z "$terminfo[cuf1]" ]] || bindkey -M viins "$terminfo[cuf1]" vi-forward-char
[[ -z "$terminfo[kcuu1]" ]] || bindkey -M viins "$terminfo[kcuu1]" vi-up-line-or-history
[[ -z "$terminfo[kcud1]" ]] || bindkey -M viins "$terminfo[kcud1]" vi-down-line-or-history
[[ -z "$terminfo[kcuf1]" ]] || bindkey -M viins "$terminfo[kcuf1]" vi-forward-char
[[ -z "$terminfo[kcub1]" ]] || bindkey -M viins "$terminfo[kcub1]" vi-backward-char

# ncurses fogyatekos
[[ "$terminfo[kcuu1]" == "^[O"* ]] && bindkey -M viins "${terminfo[kcuu1]/O/[}" vi-up-line-or-history
[[ "$terminfo[kcud1]" == "^[O"* ]] && bindkey -M viins "${terminfo[kcud1]/O/[}" vi-down-line-or-history
[[ "$terminfo[kcuf1]" == "^[O"* ]] && bindkey -M viins "${terminfo[kcuf1]/O/[}" vi-forward-char
[[ "$terminfo[kcub1]" == "^[O"* ]] && bindkey -M viins "${terminfo[kcub1]/O/[}" vi-backward-char
[[ "$terminfo[khome]" == "^[O"* ]] && bindkey -M viins "${terminfo[khome]/O/[}" beginning-of-line
[[ "$terminfo[kend]" == "^[O"* ]] && bindkey -M viins "${terminfo[kend]/O/[}" end-of-line
[[ "$terminfo[khome]" == "^[O"* ]] && bindkey -M emacs "${terminfo[khome]/O/[}" beginning-of-line
[[ "$terminfo[kend]" == "^[O"* ]] && bindkey -M emacs "${terminfo[kend]/O/[}" end-of-line
fi

因此,如果您连接到 Debian 或 Ubuntu 机器,您无需执行任何操作。一切都应该自动运行(如果没有,请参见下文)。

但是...如果您要连接到另一个机器(例如 FreeBSD),则可能没有用户友好的默认值zshrc。解决方案当然是将 Debian/Ubuntu 中的行添加zshrc到您自己的.zshrc.

Puttyxterm作为终端类型发送到远程主机。但是在某处搞砸了,并且没有发送正确的控制代码Home, End, ... 这是人们期望从xterm. 或者xterm终端不应该发送那些或任何东西......(但是,如果您在 ZSH 中配置它,则Del密钥确实有效)。xterm另请注意,您的 Numpad 键在 Vim 中的行为很有趣,例如在xterm终端中。

解决方案是配置 Putty 发送另一种终端类型。我试过xterm-colorlinuxxterm-color修复了Home/End问题,但小键盘仍然很有趣。将其设置为linux解决了这两个问题。

您可以在连接 -> 数据下的 Putty 中设置终端类型。不要试图在.zshrcwith中设置终端类型export TERM=linux,这是错误的。终端类型应由您的终端应用程序指定。因此,例如,如果您从带有 Mac SSH 客户端的 Mac 机器连接,它可以设置自己的终端类型。

请注意,TERM 指定您的终端类型,与您要连接的主机无关。我可以将终端类型设置为linuxPutty 并毫无问题地连接到 FreeBSD 服务器。

所以,解决这两个问题,你应该没事:)

于 2009-03-26T16:15:48.820 回答
19

在 PuTTY 配置对话框中,转到 Connection -> Data 并在连接前在 Terminal-type 字符串中键入linux 。

于 2009-08-19T10:50:46.117 回答
7

这对我有用

bindkey -v

bindkey '\eOH'  beginning-of-line
bindkey '\eOF'  end-of-line
于 2014-11-11T09:08:45.140 回答
6

应该在所有发行版中移植的适当答案(尽管不一定是所有版本的 zsh,这里是 ymmv)是使用 zkbd 的 zkbd 帮助程序实用程序。

键盘定义
键盘、工作站、终端、仿真器和窗口系统的大量可能组合使得 zsh 不可能在每种情况下都有内置的键绑定。在 Functions/Misc 中找到的 zkbd 实用程序可以帮助您快速为您的配置创建键绑定。

运行 zkbd 作为自动加载的函数,或者作为 shell 脚本:

zsh -f ~/zsh-4.3.17/Functions/Misc/zkbd

当你运行 zkbd 时,它首先要求你输入你的终端类型;如果它提供的默认值是正确的,只需按回车键。然后它会要求您按多个不同的键来确定键盘和终端的特性;如果 zkbd 发现任何异常情况,例如既不发送 ^H 也不发送 ^? 的 Delete 键,zkbd 就会向您发出警告。

zkbd 读取的击键记录为名为 key 的关联数组的定义,写入 HOME 或 ZDOTDIR 目录中的子目录 .zkbd 中的文件。文件名由 TERM、VENDOR 和 OSTYPE 参数组成,由连字符连接。

source您可以使用or命令将此文件读入您​​的 .zshrc 或另一个启动文件.,然后在 bindkey 命令中引用 key 参数,如下所示:

          source ${ZDOTDIR:-$HOME}/.zkbd/$TERM-$VENDOR-$OSTYPE
          [[ -n ${key[Left]} ]] && bindkey "${key[Left]}" backward-char
          [[ -n ${key[Right]} ]] && bindkey "${key[Right]}" forward-char
          # etc.

请注意,为了autoload zkbd正常工作,该zkbd文件必须位于 fpath 数组中指定的目录之一中(请参阅 zshparam(1))。如果您有标准的 zsh 安装,这应该已经是这种情况了;如果不是,请将 Functions/Misc/zkbd 复制到适当的目录。

请参阅man -P "less -p 'keyboard definition'" zshcontrib或搜索元手册页zshall

于 2012-04-30T02:38:03.560 回答
5

自首次发布此问题以来,已经将近 11 年了。当时,一些发行版确实附带了一个puttyterminfo 条目,但充其量只是平庸。从那以后的几年里,情况有所改善,不再需要十多年来必要的黑客攻击。为了兼容性,PuTTY 仍默认设置TERMxtermputty-256color

  1. 确保主机有一个 terminfo 条目putty-256colortoe -a | grep -F putty
  2. 撤消您可能启用的任何 hack,以使 PuTTY 与 zsh 或其他程序正常工作。
  3. 确保 PuTTY 是最新的。它不会在更新可用时通知您,如果它已过时,您可能会遇到很多相同的问题。您可能希望使用Chocolatey之类的东西自动保持最新状态。
  4. 在 PuTTY 的配置对话框中,转到 Connection -> Data 并将“Terminal-type string”设置为putty-256color.
  5. 当您使用它时,在同一个配置屏幕上,添加一个新的环境变量以启用 24 位颜色。这个变量不是标准化的,但它是由许多其他主流终端仿真器(例如,iTerm2)发送的,并且许多程序都可以理解它。
    1. 多变的:COLORTERM
    2. 价值:truecolor
  6. 在撰写本文时,我还没有找到默认通过 SSH 接受 COLORTERM 变量的发行版。您需要在主机上编辑 OpenSSH 配置以允许它。例如,在类似 Debian 的发行版上,编辑/etc/ssh/sshd_config并添加COLORTERM到该AcceptEnv行。
  7. 现在一切都应该“正常工作”。如果没有:
    1. 确保您在进行更改后重新连接,或者至少exec zsh在更改后运行TERM。zsh 在运行时不会对更改做出反应TERM
    2. 确保TERM实际设置为您想要的:echo $TERM
    3. 您使用的是最新版本的发行版吗?例如,如果您正在进行长期支持生命周期构建,即使您的版本在技术上仍受支持,它也可能没有最新的 terminfo 条目。
    4. 你是用screen还是tmux?那是另一整罐蠕虫。在没有先行者的情况下进行测试,以缩小问题发生的范围。在 tmux 中,尝试设置TERM=tmux-256color. 在屏幕内,尝试TERM=screen-256color.
    5. 您使用的是最新版本的 PuTTY 吗?
    6. 你有实现键绑定或其他黑客的 RC 文件吗?尝试使用默认的 RC 文件。
    7. 在尝试使用 terminfo 修复之前,您是否已经更改了各种 PuTTY 设置以尝试修复该问题?您可能需要重置这些设置。
于 2019-11-26T15:41:11.157 回答
3

这似乎是一个腻子的东西。Gnome-terminal 分别发送 Home 和 End 的代码^[OH^[OF,而 putty 发送^[[1~^[[4~。putty 中有一个选项可以将 Home/End 键从标准模式更改为rxvt模式,这似乎可以修复 Home 键,但不能修复 End 键(现在发送^[Ow)。猜猜是时候在某处提交错误报告了...... :-)

于 2008-10-02T12:59:56.000 回答
0

这些绑定根本不像是在 emacs 模式下设置的默认绑定的一部分。

在运行“bindkey -e”后在我的默认 zsh 安装上执行“where-is beginning-of-line”表明它只绑定到 ^a。也许你应该问 zsh 开发人员为什么 :-)

于 2008-10-02T11:55:42.253 回答
0

这对我有用。

将这些行添加到 ~/.zshrc

bindkey "\e[1;5D" backward-word
bindkey "\e[1;5C" forward-word

# ctrl-bs and ctrl-del
bindkey "\e[3;5~" kill-word
bindkey "\C-_"    backward-kill-word

# del, home and end
bindkey "\e[3~" delete-char
bindkey "\e[H"  beginning-of-line
bindkey "\e[F"  end-of-line

# alt-bs
bindkey "\e\d"  undo
于 2021-11-26T15:00:25.357 回答