如何在 shell 中以不同方式顯示控製字元(^C、^D、^[、...)

如何在 shell 中以不同方式顯示控製字元(^C、^D、^[、...)

當您在 shell 中鍵入控製字元時,它們會使用所謂的「插入符號」顯示。例如,轉義符被寫成^[脫字符號。

我喜歡自訂我的 bash shell,讓它看起來很酷。例如,我改變了我的PS1PS2變得彩色。我現在希望控制角色也能獲得獨特的外觀,以使它們與常規角色更容易區分。

$ # Here I type CTRL-C to abort the command.
$ blahblah^C
          ^^ I want these two characters to be displayed differently

有沒有辦法讓我的 shell 以不同的方式突出顯示控製字元?

是否可以使其以粗體字體顯示,或使它們以與常規文字不同的顏色顯示?

我在用巴什shell 在這裡,但我沒有標記問題,bash因為也許有一個適用於許多不同 shell 的解決方案。

筆記我不知道控製字元的突出顯示發生在什麼級別。我首先以為它在殼本身。現在我聽說它是閱讀線控制控製字元在 shell 中的顯示方式,例如巴什。所以這個問題現在被標記為readline,我仍在尋找答案。

答案1

當您按 時Ctrl+X,終端模擬器會將位元組 0x18 寫入偽終端對的主端。

接下來發生的情況取決於 tty 線路規則(核心中的軟體模組,位於主端(在模擬器的控制下)和從端(在終端中運行的應用程式與之互動)之間)的配置方式。

一個命令來配置它tty線路紀律stty命令。

當運行這樣的愚蠢應用程式時,cat它不知道也不關心它的標準輸入是否是終端,終端處於預設狀態典範tty 線路規則實現粗略的模式行編輯器

一些互動式應用程式需要的不僅僅是簡單的行編輯器通常在啟動時更改這些設定並在離開時恢復它們。現代的貝殼,在他們的提示下是此類應用的範例。他們實現了自己更先進的行編輯器。

通常,當您輸入命令列時,shell 將 tty 線路規則置於該模式,並且當您按 Enter 運行當前命令時,shell 恢復正常的 tty 模式(與發出提示符之前有效)。

如果運行該stty -a命令,您將看到目前使用的設置愚蠢的應用程式。您可能會看到icanonechoechoctl設定已啟用。

這意味著:

  • icanon:粗略的行編輯器已啟用。
  • echo:您輸入的字元(終端模擬器寫入主端)是迴音返回(可供終端仿真器讀取)。
  • echoctl: 而不是迴音asis,控製字元是迴音作為^X

那麼,假設您輸入A B Backspace-aka-Ctrl+H/? C Ctrl+X Backspace Return.

您的終端模擬器將發送:AB\bC\x18\b\r。線路紀律將迴音back: AB\b \bC^X\b \b\b \b\r\n,從機端 ( ) 讀取輸入的應用程式/dev/pts/x將讀取AC\n.

所有應用程式看到的是AC\n, 並且僅當您按下時Enter,因此它無法對^X那裡的輸出進行任何控制。

你會注意到對於迴音,第一個^H^?對於某些終端,請參閱erase設定)導致被傳\b \b送回終端。這是將遊標向後移動、用空格覆蓋、再次將遊標向後移動的序列,而第二個^H結果是\b \b\b \b刪除這兩個^X字元。

(0x18)本身^X被轉換為^輸出X。就像 一樣B,它沒有進入應用程序,因為我們用 Backspace 刪除了它。

\r(aka ^M) 被翻譯為\r\n( ^M^J) 表示回顯,\n( ^J) 表示應用程式。

那麼,我們對這些人有什麼選擇啞的應用:

  • 禁用echo( stty -echo)。這有效地改變了控製字元的回顯方式,透過...不回顯任何內容。不是真正的解決方案。
  • 禁用echoctl。這改變了控製字元(除了^H, ^M... 以及行編輯器使用的所有其他字元)的回顯方式。他們那時迴音按原樣。也就是說,例如,ESC 字元會作為\e( ^[/ 0x1b) 位元組發送(終端將其識別為轉義序列的開始),^G您發送一個\a(BEL,使終端發出蜂鳴聲)...不是一個選項。
  • 停用粗行編輯器 ( stty -icanon)。這並不是一個真正的選擇,因為原始應用程式的可用性會大大降低。
  • 編輯內核程式碼以更改 tty 線路規則的行為,以便迴音控製字元的發送\e[7m^X\e[m而不是僅僅發送^X(這裡\e[7m通常在大多數終端中啟用反向視訊)。

一種選擇可能是使用像rlwrap這樣的包裝器,將一個奇特的行編輯器添加到愚蠢的應用程式中,這是一種骯髒的駭客行為。該包裝器實際上嘗試將read()終端設備中的簡單 s 替換為對 readline 行編輯器的呼叫(這確實會更改 tty 行規則的模式)。

更進一步,您甚至可以嘗試類似的解決方案這個依賴 GNU screen 的功能,劫持來自終端的所有輸入以通過 zsh 的行編輯器(恰好^X以反白方式突出顯示 s) 。:exec

現在,對於實現自己的行編輯器的應用程序,由他們來決定如何迴音已經完成了。bash使用 readline 來實現不支援自訂控製字元回顯方式的功能。

對於zsh,請參閱:

info --index-search='highlighting, special characters' zsh

zsh預設會反白顯示不可列印的字元。您可以自訂突出顯示,例如:

zle_highlight=(special:fg=white,bg=red)

對於那些特殊字符,紅底白字突出顯示。

但這些字元的文字表示形式不可自訂。

在 UTF-8 語言環境中,0x18 將呈現為^X, \u378, \U7fffffff(兩個未分配的 unicode 代碼點) as <0378>, <7FFFFFFF>, \u200b(不可打印的 unicode 字元) as <200B>

\x80在 iso8859-1 語言環境中將呈現為^�... 等。

答案2

我通常在 .bashrc 檔案中包含以下程式碼:

function get_exit_status()
{
        local code=$?
        if [ $code -ne 0 ]
        then
                printf $'\001\033[31m\002'"($code)"$'\001\033[0m\002'" "
        fi
}

然後我在 PS1 中呼叫這個函數

PS1='\u@\h \w $(get_exit_status)'

這樣,如果您按 ^C 您將在提示中看到它

I@mycomputer ~ ^C
I@mycomputer ~ (130)

所有非「0」的退出狀態代碼都會被提示。

相關內容