以下我们提功一些范例给常见的命令解译器使用.
我们先从 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
更精确的路径名.