Bash:PS1 中的条件换行符破坏了预输入

Bash:PS1 中的条件换行符破坏了预输入

我使用 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 commitsls

现在,在我的提示中使用条件换行逻辑的相同示例:

╭-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 中是否有帮助?重定向终端的响应(例如到文件或管道或其他什么)并从那里读取它怎么样?

感觉有办法解决这个问题,所以我把一些东西扔到墙上,看看什么能粘住。

相关内容