以下我们提功一些□例给常见的命令解译器使用.
我们先从 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 是被设定为一个不被解释的值,
但变数在 "..." □如果有用到 $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 更精确的路径名.