自定义 bash 客户端历史重叠

自定义 bash 客户端历史重叠

我正在编写一个客户端,用于通过 ssh 在 zimbra 服务器上执行各种任务,但遇到了一些问题。代码如下:

#!/bin/bash
set -e
export PATH=/usr/bin:/bin:/usr/sbin:/sbin
export HISTCONTROL=ignoreboth

# History management
if [ -f $HOME/.zmcli_history ]; then
  history -r $HOME/.zmcli_history
else
  touch $HOME/.zmcli_history
  history -r $HOME/.zmcli_history
fi
trap "history -a $HOME/.zmcli_history && echo -e '\nExiting now.\n'" exit

# Styling
yellow='[33m'
bold='[1m'
off='[0m'

echo

# Client
while :; do
  read -ep "$bold${yellow}zimbra_cli[${off}server_domain$bold${yellow}]> $off" comm
  history -s "$comm"
done

注意:如果您执行此脚本,它将在您的主目录中创建历史文件(.zmcli_history)。

一切都按预期工作,历史记录也都在那里,但当我继续滚动历史记录时,一些(通常很长的)前一个命令的部分通常会保留下来。除非我按下 CTRL+L 清除屏幕并将其重置为正常,否则该命令的这一部分将作为会话剩余部分的提示符。我读过许多帮助在 bash 终端中遇到此问题的人的帖子。他们的问题是 PS1 格式不正确,bash 对提示字符串的长度感到困惑。这里可能也有类似的情况,但这些解决方案不起作用,因为 read 命令不能像 echo 那样使用转义字符(\e)。

我设法找到了一种使用文字转义符(vim 插入模式下的 CTRL+V ESCAPE)来转义颜色序列的方法。这样颜色就可以正常工作了,但我还是被这个历史问题困扰着。

我尝试过的事情:

  • 命令替换:: 以 echo -e 可以打印的方式编写和转义颜色代码,然后在读取命令 $(echo -e '\e[33m') 中回显它。仍然可以看到颜色,但对历史问题没有帮助
  • 在颜色代码周围添加转义的 [ 和 ]
  • 将带有颜色代码的整个提示放在 read 命令之前的单独 echo 命令中。缺点是,我无法关闭格式化,直到 read 命令之后(在另一个 echo 中),这意味着整个提示和命令将以粗体显示并带有颜色。此外,如果我现在按 CTRL+L,即使提示也会被清除,我只剩下光标

最后,由于我无法删除历史记录,我尝试删除颜色。但这样就无法快速区分命令和输出。

您可以通过启动脚本并输入 10-15 条长(乱码)命令来复制该问题。之后,尝试上下滚动历史记录,您就会明白我在说什么。

有人知道如何让它工作吗?

答案1

你的剧本,就像它,无法让我重现这个问题。只有在启用颜色后,readline 才开始变得混乱。为了记录,我启用了这些功能

# Styling
yellow=$'\e[33m'
bold=$'\e[1m'
off=$'\e[0m'

这是真的\[,而且\]没有帮助他们这样做是为了PS1

但后来我发现这个答案.上面写着

我打开info readline发现:

[…]应用程序可以通过用特殊标记和(在中声明)
括住一连串这样的字符来表明提示符包含在显示时不占用物理屏幕空间的字符 。这可用于在提示符中嵌入特定于终端的转义序列。RL_PROMPT_START_IGNORERL_PROMPT_END_IGNOREreadline.h

正如所说文本我搜索RL_PROMPT_START_IGNORERL_PROMPT_END_IGNORE定义readline.h并发现以下内容:

/* Definitions available for use by readline clients. */
#define RL_PROMPT_START_IGNORE  '\001'
#define RL_PROMPT_END_IGNORE    '\002'

这让我想到了以下几点:

# Styling
yellow=$'\1\e[33m\2'
bold=$'\1\e[1m\2'
off=$'\1\e[0m\2'

它运行完美。

相关内容