Bash

在標題為 bash 的 GNU 螢幕上顯示完整命令,並與 Vim 緩衝區正確互動

  • October 16, 2020

網路上有很多關於這個的問題,但我能找到的有兩個共同點之一:

  • 他們給出了手動解決方案,它只列印目前正在執行的程序(沒有參數)
  • 使用 zsh preexec 功能(雖然我不確定它如何與螢幕互動)。我正在尋找 Bash 解決方案。

**如何讓我的螢幕標題顯示整個命令執行,例如,如果我執行 3 個長時間執行的 Python 腳本,我也可以在標題中看到腳本名稱?**對於獎勵積分,如果我能讓它繼續顯示最後一次執行的命令,那就更好了。

我目前的設置:

  • 出口PROMPT_COMMAND='/bin/echo -ne "\033k\033\0134"'
  • PS1以。。結束>
  • shelltitle ">|bash"

我試過:

  • \033k在和之間添加東西\033- 用${BASH_COMMAND}
  • 使用陷阱調試設置外部附加標題,因為對於沒有螢幕的 XTERM,我知道解決方案。這與PS1.

以及上述的變體。我想要一個通過螢幕的解決方案,所以視窗標題和螢幕視窗列表都顯示完整的命令。

作為獎勵,如果 Screen 可以與 Vim 很好地互動,我會非常喜歡它,因此可以更改緩衝區/打開新文件/等。將在螢幕標題中動態更新。

一年後,這是我的解決方案,使用陷阱。這將顯示主機名、正確PWD和命令(如果在螢幕上,還會顯示螢幕內容)。set_screen_window這很容易在下面定制。一切都應該放在你的.bashrc.

首先是一些輔助函式來檢查我是否打開screen

export PROMPT_COMMAND=''
if [[ "$TERM" == "screen"* ]]; then
   screen_title_slicer() { echo "${1:0:40}"; } # Arbitrary cut off. use echo $1 for full.
   screen_title_format='\ek%s\e\\'
else
   screen_title_slicer() { echo "${1//[^[:print:]]/}"; }
   screen_title_format='\033]0;%s\007'
fi

建設指揮的肉,靠的就是有用的BASH_COMMAND。我為fg(例如顯示原始命令)和cd(獲取真實目錄)做了一些自定義的東西:

ready="Ready!"

set_screen_window() {
   title_string=$1
   [ -z "$title_string" ] && title_string=$(screen_title_slicer "$BASH_COMMAND")
   [ "$title_string" = "fg" ] && read -ra job < <( jobs %% 2> /dev/null )
   [ "$title_string" = "fg " ] && read -ra job < <(jobs "${title_string:3} 2> /dev/null")
   if [ ${#job[@]} -gt 0 ]; then
       title_string=$(screen_title_slicer "${job[2]}")
   fi
   cwd=$PWD
   if [ "${title_string::3}" = "cd " ]; then
       cwd=$(  eval cd "$(awk '{print $2}' <<< "$BASH_COMMAND")" &> /dev/null && pwd)
       [ -z "$cwd" ] && cwd=$PWD
       title_string="$ready"
   fi
   [ "$title_string" = "cd" ] && title_string=$ready && cwd=$HOME
   printf "$screen_title_format" "$HOSTNAME -- ${cwd//$HOME/\~}> $title_string" > "$(tty)"
   unset job
   unset title_string
}

現在用我的字元串初始化終端頭ready,並擷取錯誤和調試以更新終端視窗:

set_screen_window "$ready"
trap "set_screen_window $ready" ERR
trap set_screen_window DEBUG

最後,在.vimrc我們有vim特定的東西:

function! Filename()
   if @% == ""
       return "noname"
   endif
   let is_tracked=system("git ls-files " . expand("%"))
   if is_tracked == ""
       return expand("%:t")
   endif
   return gitbranch#name() . "/" . expand("%:t")
endfunction

let &titlestring = hostname() . " -- vim " . Filename()
if &term[:5] == "screen"
 set t_ts=^[k
 set t_fs=^[\
 set title
endif
autocmd TabEnter,WinEnter,BufReadPost,FileReadPost,BufNewFile * silent execute '!printf "\033]0;'.hostname().' -- vim '.Filename().'\007"'
autocmd TabEnter,WinEnter,BufReadPost,FileReadPost,BufNewFile * let &titlestring = hostname() . ' -- vim ' . Filename()

在這裡Filename可以定制以獲得自己的標題風格。autocmd確保在緩衝區、視窗等之間移動時重新載入內容。在我的範例中,是一個可用於在儲存庫中編輯文件時生成(如您所料)分支名稱gitbranch的外掛。git

PROMPT_COMMAND='/bin/echo -ne "\033k\033\0134"'與in.bashrc一起使用shelltitle '$ |bash'.screenrc我來說很好。使用這個特定PROMPT_COMMAND的東西會破壞我的 PS1,所以我還添加了以下內容.bashrc

case "$TERM" in
   screen*) PROMPT_COMMAND='/bin/echo -ne "\033k\033\0134"';;
esac

附上範例圖片 - 在視窗 0 中執行睡眠,在視窗 1 中查找,在視窗 2 中觀看,在視窗 3 中執行 ping,在視窗 4 中執行 bash。 在此處輸入圖像描述

引用自:https://unix.stackexchange.com/questions/545458