Bash fish shell:仅当存在以前的输出时,才在提示前添加换行符
(免责声明:我正在使用fish,但这同样适用于bash)Bash fish shell:仅当存在以前的输出时,才在提示前添加换行符,bash,terminal,fish,Bash,Terminal,Fish,(免责声明:我正在使用fish,但这同样适用于bash) 我当前的shell在提示符前打印一个换行符,以便在命令输出之间轻松找到它 # [...] echo # newline before prompt echo -s $arrow ' ' $cwd $git_info echo -n -s '❯ ' 但是,当没有以前的输出时,也会打印换行符,例如,在用printf“\033c”清除终端后(或当终端首次打开时): 编辑:后期编辑更便于携带 下面是我在bash中的实现方式: \uuuu提示符\
我当前的shell在提示符前打印一个换行符,以便在命令输出之间轻松找到它
# [...]
echo # newline before prompt
echo -s $arrow ' ' $cwd $git_info
echo -n -s '❯ '
但是,当没有以前的输出时,也会打印换行符,例如,在用printf“\033c”
清除终端后(或当终端首次打开时):
编辑:后期编辑更便于携带
下面是我在bash中的实现方式:
\uuuu提示符\u换行符=$'\nvv'
__设置\u缺少\u换行\u修复()
{
本地CURPOS
echo-en“\033[6n”#ANSI DSR
读取-s-d-R CURPOS
CURPOS=${CURPOS}
如果[$CURPOS-等式1];则
__缺少\u新行\u FIX=“”
其他的
__缺少\u换行符\u修复=“$\u提示\u换行符”
fi
}
PROMPT\u命令=\uuuuuu集合\u缺少\u换行\u修复
PS1=“\${uu缺少新行\u修复}\w>”
注意,它被配置为在提示符前加上VVV
,让我知道最后一个命令没有以换行结束
演示:
施蒂克:
将导致终端将其当前光标位置写入为输入。由于我们是一个交互式shell,该输入可用于shell的stdin,因此我们只需读取-s
它(无回声)
在上面的链接中,您将看到响应的形式是CSI Pl;Pc R
,因此我们告诉read
读取并包括R
和-dr
然后我们使用bash的“remove matching prefix”语法${CURPOS#*}
提取Pc
部分,该语法删除分号;
之前的所有内容
然后,如果光标位置不是1,也就是说,我们不在换行符的开头,我们将手动向提示中添加一个换行符
ANSI DSR应适用于所有与ANSI兼容的终端,但如果您遵循链接,您将看到它并不是字面上说的\033[6n
,而是说CSI 6 n
。是。转义序列以ASCII 27 ESC字符(八进制033)开始
在我最初的答案中,我使用了\E
,bash内置的echo-E
命令解析的内容与\033
相同,因此上面进行了编辑。我仍然希望我们可以使用类似于DSR签入root的答案,但fish可能不支持这一点
因此,我将根据我遇到的问题,提出一个非常非常规的解决方案(如果你觉得这很有用,也可以对答案进行投票)。如果您使用tmux
,则可以通过其缓冲区访问终端内容。如果您不使用tmux
,则希望此信息对将来搜索时遇到它的人有用
假设一个相当直接的提示(您的提示似乎是):
我们可以使用以下功能:
function fish_prompt
if begin
# If we're running in a tmux session
command -q tmux
and set --query TMUX
end
# capture the screen contents, reverse them so that the
# last line is first, and remove any blank lines
set capt (tmux capture-pane -p | tac | grep ".")
if begin
# if the last line doesn't look like it started with the prompt
not string match -qre "^> " $capt[1]
# and the last line wasn't just an empty prompt
and not string match -q ">" $capt[1]
# and we didn't just repaint the screen
and not test (count $capt) -eq 0
end
# then add the newline
echo
end
else
echo
end
echo -s "--- First line of prompt ---"
echo -s -n "> "
end
我们将$capt
设置为当前屏幕上tmux窗格的内容,顺序颠倒,使最后一行位于顶部,并删除任何没有文本的行(因为tmux捕获到屏幕底部,而与当前行号无关)
如果在$capt
中没有任何行,则我们处于“屏幕清除”状态,提示被绘制为屏幕上的第一行。您说过在这种情况下不需要换行符,因此只有在$capt不为空时才打印它
但我们真正的测试是看最后一行输出($capt[1]
)是否与“提示符”匹配。在这种情况下,它意味着从
开始。在这种情况下,我们也不打印换行符
但是还有一个拐角处的情况,这是一行,提示时没有输入任何内容(按Enter键时,行上没有任何内容)。您可能认为检查
会捕捉到这一点,但由于某些原因,fish显然会重新绘制空提示符,而不带尾随空格。因此,还需要检查仅包含
的行
当然,如果最后一行更复杂,这需要修改。检查$capt[2]
可能更容易,因为它始终是前一个提示的第一行。Stock fish已经处理了这个问题(并且已经多年了),不需要提示
当输出没有以换行符结尾时,您将看到“缺少换行符”,如“^1”或⏎", 后跟换行符,然后才是提示。DSR行为是否取决于外壳、终端或操作系统?使用fish时,echo-en”\E[6n“
只是得到字面上的回应。在bash中,它总是生成;1R
,无论它是否是第一个命令。后编辑,但听起来你的终端没有正确报告,它是否也发生在其他终端上?另外,你如何测试它总是生成的内容?当位置不是1时,你需要发出DSR。”(验证…)并将其从终端读入类似于hextump
的内容,以便响应中的第一个ESC不会被外壳或终端吞没。@Luis Beaucamp首先,fishecho
等效为echo-en”\e[6n”
。然而,一旦我们克服了这一点,我仍然有一个拦截器,fish的读取
似乎无法处理这种情况。它的“静默”模式不会抑制,而是(从手册页)屏蔽写入终端的字符,用星号代替。这对于读取密码或其他敏感信息非常有用。"看起来bash的read
在得到ANSI返回结果时会自动返回,而fish的则不会。我还没有解决这个问题。Oops-Missed@root的edit.\033对fish来说也是可移植的,并正确返回位置。不过,仍然没有解决read
问题。请重新阅读o原始问题。这是关于创建cu的
$ source bashrc.sh
/tmp/so/newline > echo hello
hello
/tmp/so/newline > echo -n hello
hello
VVV /tmp/so/newline >
--- First line of prompt ---
>
function fish_prompt
if begin
# If we're running in a tmux session
command -q tmux
and set --query TMUX
end
# capture the screen contents, reverse them so that the
# last line is first, and remove any blank lines
set capt (tmux capture-pane -p | tac | grep ".")
if begin
# if the last line doesn't look like it started with the prompt
not string match -qre "^> " $capt[1]
# and the last line wasn't just an empty prompt
and not string match -q ">" $capt[1]
# and we didn't just repaint the screen
and not test (count $capt) -eq 0
end
# then add the newline
echo
end
else
echo
end
echo -s "--- First line of prompt ---"
echo -s -n "> "
end