让我们假设你希望你的提示是这个样子:
left text----------------------------------------------------------right text
prompt$
这是相当直接的规定,right text
具有已知大小。 (例如,它可能是当前的日期和时间。)我们所做的是打印正确数量的破折号(或者,对于utf-8终端,更漂亮的\u2500
),然后是right text
,然后回车(\r
, 不是一个换行符)和左边的文字,它会覆盖破折号。唯一棘手的一点是“正确的破折号”,但我们可以使用$(tput cols)
来查看终端的宽度,幸运的是bash
将命令展开PS1
。因此,例如:
PS1='\[$(printf "%*s" $(($(tput cols)-20)) "" | sed "s/ /-/g") \d \t\r\[email protected]\h:\w \]\n\$ '
这里,$(($(tput cols)-20))
是终端减去20,其是基于\d \t
宽确切地说是20个字符(包括初始的空间)的宽度。
PS1
不理解utf-8转义(\uxxxx
),并且在sed
命令中插入适当的替换会涉及恼人的嵌入引号问题,虽然这是可能的。然而,printf
不明白UTF-8逃逸,所以更容易产生以不同的方式划线的序列:
PS1='\[$(printf "\\u2500%.0s" $(seq 21 $(tput cols))) \d \t\r\[email protected]\h:\w \]\n\$ '
另一种方式来做到这涉及关闭终端的autowrap,这是可能的,如果你正在使用xterm
或实现相同控制代码(或Linux控制台本身)的终端仿真程序。要禁用自动换行,输出序列ESC[?l。要打开它,请使用ESC[?h。禁用自动换行功能后,一旦输出到达行尾,最后一个字符将被下一个字符覆盖,而不是开始新行。使用这种技术,计算虚线序列的确切长度并不是必须的。我们只需要破折号的字符串,它的长度超过任何控制台将广,说以下内容:
DASHES="$(printf '\u2500%0.s' {1..1000})"
PS1='\[\e[?7l\[email protected]\h:\w $DASHES \e[19D \d \t\e[?7h\]\n\$ '
这里,\e[19D
是“移动光标倒退19个字符的”终端仿真程序代码。我本可以用$(tput cub 19)
代替。 (可能有一个tput
参数用于打开和关闭自动包装,但我不知道它会是什么。)
视频中的示例还涉及在实际命令行中插入右对齐的字符串。我不知道用bash
这样做的任何干净的方式;视频中的控制台几乎肯定使用zsh
和RPROMPT
功能。当然,您可以使用上述相同的技术在bash
中输出右对齐提示,但readline
不会知道任何有关它们的信息,因此只要您执行某些操作来编辑该行,正确的提示就会消失。