以下我們提功一些範例給常見的命令解譯器使用.
我們先從 zsh 開始,
他可以提供許多靈巧的機制使得我們很容易地完成我們所要的工作.
然後我們再進展到難度較高的範例.
在所有的範例中我們都測試了 $TERM 環境變數.
以確定我們只需把這個溢位資訊送到 xterm. 我們對
$TERM=xterm* 做測試; 萬用字元是因為些許的差異性
(比如 rxvt) 會設定 $TERM=xterm-color.
我們要對 C 命令解譯器 (C Shell) 族系作特別的註解, 比如
tcsh 及 csh.
在 C 命令解譯器, 使用到未定義的變數就算是致命性的錯誤.
因此, 在測試變數 $TERM 之前,
先確定其是否存在否則會使在非交談模式下工作的命令解譯器停擺.
要達到這個目的你必須把部份東西用下面這種樣式包起來:
if ($?TERM) then
...
endif
(我們是不主張用 C 命令解譯器 的理由之一. 參考
Csh Programming Considered Harmful 有很多有用的討論文章).
以下的範例可以被用來插入到合適的命令解譯器的初始啟動檔;
即 那個在交談式命令解譯器啟動時會去讀的那個檔.
在大部份的情況它被稱為
.命令解譯器名rc (如 .zshrc, .tcshrc, 等).
zsh 提供部份功能與延伸功能, 而我們將用到:
precmd () 一個在提示命令前必執行的功能含式
chpwd () 一個在目錄有所變化時會執行的功能含式
\e 溢位字元 (ESC)
\a bell 的溢位字元 (BEL)
%n 被解釋為 $USERNAME
%m 被解釋為主機名稱在第一個 '.' 之前的部份
%~ 被解釋為目錄, 以 '~' 取代 $HOME
更多的延伸功能: 參考 zshmisc 使用手冊.
因此, 以下將設定 xterm 的主題為
"username@hostname: directory":
case $TERM in
xterm*)
precmd () {print -Pn "\e]0;%n@%m: %~\a"}
;;
esac
這也可以用 chpwd() 取代
precmd() 來達成. print 內建的工作是跟
echo 一樣, 但可以讓我們去存取 % 命令提示溢位資訊.
tcsh 的部份功能含式與延伸功能與 zsh 相同:
precmd () 一個在提示命令前必執行的功能含式
cwdcmd () 一個在目錄有所變化時會執行的功能含式
%n 被解釋為 $USERNAME
%m 被解釋為主機名稱
%~ 被解釋為目錄, 以 '~' 取代 $HOME
%# 對正常的使用者解釋為 '>', 而超級使用者則為 '#'
%{...%} 引入一個字串為連續的溢位序列
不幸的, 並沒有與 zsh 的 print 相同功能的指令,
能讓我們在主題字串中使用提示溢位資訊,
因此我們唯一能使用的命令解譯器變數 (在 ~/.tcshrc):
switch ($TERM)
case "xterm*":
alias precmd 'echo -n "\033]0;${HOST}:$cwd\007"'
breaksw
endsw
然而, 這會用目錄完整的路徑取代使用 ~.
改把這些字串插入題示字元:
switch ($TERM)
case "xterm*":
set prompt="%{\033]0;%n@%m:%~\007%}tcsh%# "
breaksw
default:
set prompt="tcsh%# "
breaksw
endsw
這會設定 "tcsh% " 的提示字元, 而 xterm 的主題及圖示為
"username@hostname: directory". 要注意
"%{...%}" 必須環繞在溢位序列外
(且不能被放在 提示的最後一項: 參考 tcsh 使用手冊說明會更詳細).
bash 支援變數 $PROMPT_COMMAND
內含一個指令在提示字元之前執行. 這個範例將設定主題為
username@hostname: directory:
PROMPT_COMMAND='echo -ne "\033]0;${USER}@${HOSTNAME}: ${PWD}\007"'
在這的 \033 是代表字元 ESC,
而 \007 則是 BEL.
記住引號在這相當重要: 會被解釋的變數是放在
"...", 而不是 '...'. 因此
$PROMPT_COMMAND 是被設定為一個不被解釋的值,
但變數在 "..." �埵p果有用到 $PROMPT_COMMAND 則會被解釋.
然而, $PWD 產生完整的路徑.
如果我們要使用 ~ 這種速記, 則我們要把溢位字串嵌入到提示字元,
這會讓我們可以利用命令解譯器所提供的命令列延伸功能:
\u 被解釋為 $USERNAME
\h 被解釋為主機名稱在第一個 '.' 之前的部份
\w 被解釋為目錄, 以 '~' 取代 $HOME
\$ 對正常的使用者解釋為 '>', 而超級使用者則為 '#'
\[...\] 嵌入非列印字元溢位序列
因此, 以下將產生 bash$ 的提示字元,
並設定 xterm 的主題為 username@hostname: directory:
case $TERM in
xterm*)
PS1="\[\033]0;\u@\h: \w\007\]bash\\$ "
;;
*)
PS1="bash\\$ "
;;
esac
記住 \[...\] 的使用, 在計算題示長度時,
將告訴 bash 忽略掉非列印的控制字元.
否則行編輯指令將會在移動游標時搞亂掉.
ksh 幾乎不提供這種方式的功能函式與延伸功能,
因此我們必須插入溢位字串到提示字元中, 使他能動態更新
這個範例將產生主題為
username@hostname: directory 而and a prompt of ksh$ .
case $TERM in
xterm*)
HOST=`hostname`
PS1='^[]0;${USER}@${HOST}: ${PWD}^Gksh$ '
;;
*)
PS1='ksh$ '
;;
esac
而, $PWD 會產生完整的目錄路徑. 我們可以
用 ${...##...} 的方式移去 $HOME/ 的字首.
我們也可以用 ${...%%...} 的方法來截去部份的 hostname:
HOST=`hostname`
HOST=${HOST%%.*}
PS1='^[]0;${USER}@${HOST}: ${PWD##${HOME}/}^Gksh$ '
記住 ^[ 及 ^G 在命令列字串是單一字元
的 ESC 及 BEL (在 emacs 的環境下可以用
C-q ESC 及 C-q C-g 輸入).
要在 csh 完成同樣的事真的有點困難, 而我們用下面的方式來解決問題:
switch ($TERM)
case "xterm*":
set host=`hostname`
alias cd 'cd \!*; echo -n "^[]0;${user}@${host}: ${cwd}^Gcsh% "'
breaksw
default:
set prompt='csh% '
breaksw
endsw
麻煩的地方是我們要把 cd 這個指令化身成可送出溢位字串的功能.
記住 ^[ 及 ^G 在命令列字串是單一字元的
ESC 及 BEL (在 emacs 的環境下可以用
C-q ESC 及 C-q C-g 輸入).
記住: 在部份的系統 hostname -s 可能會取得較短的
hostname 而不是完整的全名. 部份使用者在有符號連結的目錄應該會發現
`pwd` (括起來以確定執行的是 pwd 指令)
可以得到比 $cwd 更精確的路徑名.