我使用 Bash,我的 PS1 跨越两行。
╭-ivan·dotfiles (master)
╰ဝ █
有时我会运行一个命令,其输出没有尾随换行符,并且我的提示符会错位,
╭-ivan·dotfiles (master)
╰ဝ curl localhost:3002/is_alive
{"web_server_status":"success","db_status":"success"}╭-ivan·dotfiles (master)
╰ဝ █
我终于找到了一个解决方案,如果光标超出第一列,则有条件地在提示符前添加换行符:
build_prompt() {
export PS1="\$(ps1_head)...
}
ps1_head() {
if (( $(cursor_col) > 1 )); then
printf '\n╭-'
else
printf '╭-'
fi
}
cursor_col() {
local _row col
IFS=';' read -s -dR -p $'\033[6n' _row col
echo "${col}"
}
这解决了原来的问题,
╭-ivan·dotfiles (master)
╰ဝ curl localhost:3002/is_alive
{"web_server_status":"success","db_status":"success"}
╭-ivan·dotfiles (master)
╰ဝ █
但是,它引入了一个新的。我依靠 typeahead 来允许我在当前命令完成之前键入下一个命令。条件换行似乎打破了这种行为。
没有条件换行逻辑的示例:
╭-ivan·dotfiles (master)
╰ဝ git status
On branch master
Your branch is up-to-date with 'origin/master'.
lnothing to commit, working tree clean
s╭-ivan·dotfiles (master)
╰ဝ ls
myfile.txt
请注意,我在第一个命令的输出完成打印之前键入了l
( ),并且在第一个命令完成之后但在提示打印之前键入了。 typeahead 优雅地将两个字符 ( ) 拉入下一个命令。lnothing to commit
s
ls
现在,在我的提示中使用条件换行逻辑的相同示例:
╭-ivan·dotfiles (master)
╰ဝ git status
On branch master
Your branch is up-to-date with 'origin/master'.
lnothing to commit, working tree clean
s╭-ivan·dotfiles (master)
╰ဝ s
bash: s: command not found
请注意,这一次,typeahead 如何优雅地将 拉s
入第二个命令,但它留下了l
后面。
有什么方法可以更优雅地处理这个问题,或者我最终必须切换到 zsh 吗?
答案1
我有这样的动态提示文本,并且预输入没有问题。但PS1
我没有直接将进程替换嵌入到PROMPT_COMMAND
调用设置方法中。它们生成适当的动态文本,并将其存储在变量中,然后将变量嵌入到PS1
.
所以尝试这样的事情......
export ps1_head_text
build_prompt() {
export PS1="\${ps1_head_text}..."
}
ps1_head() {
if (( $(cursor_col) > 1 )); then
ps1_head_text=$'\n'╭-
else
ps1_head_text=╭-
fi
}
export PROMPT_COMMAND=ps1_head
我最终这样做是因为我在流程替换方面遇到了问题(尽管我不记得这是预先输入还是其他问题)。
编辑:现在我想起来了,您可能会遇到计时问题... ifPROMPT_COMMAND
是在阻止正确读取光标位置的时间调用的。如果发生这种情况,您可能会选择“使用 zsh”。但试一试吧。
更新:根据一个来自 dave_thompson_085 的评论读取对发出转义序列(用于打印光标位置)的响应可能会与预输入发生冲突。
这是有道理的,因为读取发生在与输入预输入文本相同的 shell 中。那么如果不在同一个 shell 中执行呢?用括号将其放在子 shell 中是否有帮助?重定向终端的响应(例如到文件或管道或其他什么)并从那里读取它怎么样?
感觉有办法解决这个问题,所以我把一些东西扔到墙上,看看什么能粘住。