2014-01-26 128 views
2

我注意到在this video,終端提示擴展終端的整個寬度,然後分解到一個新的行。我如何設置我的PS1變量來填充剩餘的終端空間中的某個角色,就像這個用戶所做的那樣?如何讓我的終端提示擴展終端的寬度?

問題是,我不知道如何更新每個命令的PS1變量。在我看來,PS1的字符串值只能被讀入一次,因爲.bashrc文件只被讀入一次。在每個命令或其他東西之後,我是否必須編寫某種鉤子?

我還應該指出,PS1變量將根據組成它的轉義字符評估到不同的長度。例如,打印路徑爲\w

我知道我可以使用$(COLUMNS)終端寬度,以及當前PS1變量與${#PS1}寬度,做數學題,並打印的字符緩衝區適量的,但我怎麼得到它更新每次。有沒有一種首選方式?

回答

1

使用PROMPT_COMMAND在每個命令前重置PS1的值。

PROMPT_COMMAND=set_prompt 
set_prompt() { 
    PS1=... 
} 

雖然一些系統腳本(或你自己)可能已經在使用PROMPT_COMMAND的東西,在這種情況下,你可以簡單地添加到它。

PROMPT_COMMAND="$PROMPT_COMMAND; set_prompt" 
2

讓我們假設你希望你的提示是這個樣子:

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這樣做的任何干淨的方式;視頻中的控制檯幾乎肯定使用zshRPROMPT功能。當然,您可以使用上述相同的技術在bash中輸出右對齊提示,但readline不會知道任何有關它們的信息,因此只要您執行某些操作來編輯該行,正確的提示就會消失。