Bash 如何使终端提示扩展终端的宽度?

Bash 如何使终端提示扩展终端的宽度?,bash,terminal,command-prompt,terminal-emulator,ps1,Bash,Terminal,Command Prompt,Terminal Emulator,Ps1,在中,我注意到终端提示符在分解为新行之前扩展了终端的整个宽度。我如何设置我的PS1变量来用一些字符填充剩余的终端空间,就像这个用户所做的那样 问题是,我不知道如何更新每个命令的PS1变量。在我看来,PS1的字符串值只读入一次,就像.bashrc文件只读入一次一样。我是否必须在每个命令后编写某种钩子 我还应该指出,PS1变量将根据组成它的转义字符计算为不同的长度。例如,\w打印路径 我知道我可以使用$(COLUMNS)获得终端宽度,使用${PS1}获得当前PS1变量的宽度,进行计算,并打印适当数量

在中,我注意到终端提示符在分解为新行之前扩展了终端的整个宽度。我如何设置我的
PS1
变量来用一些字符填充剩余的终端空间,就像这个用户所做的那样

问题是,我不知道如何更新每个命令的
PS1
变量。在我看来,
PS1
的字符串值只读入一次,就像
.bashrc
文件只读入一次一样。我是否必须在每个命令后编写某种钩子

我还应该指出,
PS1
变量将根据组成它的转义字符计算为不同的长度。例如,
\w
打印路径


我知道我可以使用
$(COLUMNS)
获得终端宽度,使用
${PS1}
获得当前
PS1
变量的宽度,进行计算,并打印适当数量的缓冲字符,但如何让它每次都更新。是否有首选方法?

在每个命令之前,使用
提示符命令
重置
PS1
的值

PROMPT_COMMAND=set_prompt
set_prompt () {
    PS1=...
}
虽然某些系统脚本(或您自己)可能已经对某些内容使用了
PROMPT\u命令
,但在这种情况下,您可以简单地添加到它

PROMPT_COMMAND="$PROMPT_COMMAND; set_prompt"

让我们假设您希望提示符看起来像这样:

left text----------------------------------------------------------right text
prompt$ 
如果
右文本
具有已知大小,则这是非常简单的。(例如,它可能是当前日期和时间。)我们要做的是打印正确数量的破折号(或者,对于utf-8终端,打印更漂亮的
\u2500
),然后是
右文本
,然后是回车(
\r
,而不是换行)和左文本,这将覆盖破折号。唯一棘手的是“正确的破折号数”,但我们可以使用
$(tput cols)
来查看终端的宽度,幸运的是
bash
将命令expand
PS1
。例如:

PS1='\[$(printf "%*s" $(($(tput cols)-20)) "" | sed "s/ /-/g") \d \t\r\u@\h:\w \]\n\$ '
这里,
$($(tput cols)-20))
是终端的宽度减去20,这是基于
\d\t
正好是20个字符宽(包括初始空格)

PS1
不理解utf-8转义(
\uxxx
),在
sed
命令中插入适当的替换涉及到一个恼人的嵌入式报价问题,尽管这是可能的。但是,
printf
确实理解utf-8转义,因此更容易以不同的方式生成破折号序列:

PS1='\[$(printf "\\u2500%.0s" $(seq 21 $(tput cols))) \d \t\r\u@\h:\w \]\n\$ '
另一种方法是关闭终端的自动包装,如果您使用的是
xterm
或实现相同控制代码的终端仿真器(或linux控制台本身),这是可能的。要禁用自动换行,请输出序列ESC[?7l。要重新启用,请使用ESC[?7h.禁用自动换行功能后,一旦输出到达行尾,最后一个字符将被下一个字符覆盖,而不是开始新的一行。使用这种技术,实际上不需要计算破折号序列的确切长度;我们只需要一个比任何控制台都要宽的破折号字符串以下是:

DASHES="$(printf '\u2500%0.s' {1..1000})"
PS1='\[\e[?7l\u@\h:\w $DASHES \e[19D \d \t\e[?7h\]\n\$ '
这里,
\e[19D
是“向后移动光标19个字符”的终端模拟器代码。我可以使用
$(tput cub 19)
(可能有一个
tput
参数用于打开和关闭自动换行,但我不知道它是什么。)

视频中的示例还涉及在实际的命令行中插入右对齐的字符串。我不知道使用
bash
执行此操作的任何干净方法;视频中的控制台几乎肯定使用
zsh
RPROMPT
功能。当然,您可以在
bash
中输出右对齐的提示g使用与上面相同的技术,但是
readline
不会知道任何关于它们的信息,因此只要您做一些事情来编辑行,正确的提示就会消失