http://www.cnblogs.com/bamanzi/p/zsh-simple-guide.html
bash用久了,有些地方开始觉得不爽,于是想看看有没有更好的选择。原来在网上瞎逛时,已经很多次看到有人推荐zsh了,加上zsh高度兼容bash,于是就来折腾这个。
不过试验了一下oh-my-zsh,感觉功能太强大了,太多东西不知道怎么配置的,这种过于“不知其所以然”的感觉我不太喜欢。于是自己来折腾,觉得基本够自己用就行了。
很多介绍zsh的文章都说zsh相对bash的一个优点是支持命令选项和参数的补全
(这两幅图来自 Z使用 Zsh 的九个理由 - 博客 - 伯乐在线)
其实bash里面如果你安装了bash-completion这个包的话,很多命令(比如pkill, dpkg, git等等,我的机器上/etc/bash_completion.d/
下面有200多个命令的补全配置。注意/etc/bash_completion.d/git
其实是git包提供的,而/etc/bash_completion.d/mercurial
其实是mercurial包提供的) 。
不过zsh在补全还是有些比bash强的地方,尤其是涉及到交互的地方:
zstyle ':completion::approximate:' max-errors 1 numeric
,以后输入cd /etc/x11, 按TAB后zsh会给你纠正为/etc/X11 (此条来自 终极Shell——Zsh — LinuxTOY,那里有详细的说明);另外,zsh自带的补全源的确比bash-completion多,我这里find /usr/share/zsh/functions/Completion -type f | wc -l
的结果是688个文件(参见 Debian -- Filelist of package zsh-common/jessie/all )
在写代码过程中,会在各个目录之间来回切换,原来用bash时有两点最不爽:
pushd/popd/dirs
虽然很有用,但很多时候等你想回到过去的某个目录时,才发现当时忘记pushd了
/opt/rubystack-1.9/
下面有apache2
和apps
这两个目录,输入cd /opt/rubystack-1.9/a
然后按TAB的话,首先会补齐为apache2,再按TAB会补齐为apps,不需要象bash下面那样继续输入字母;/opt/rubystack-1.9/apps/redmine
,那么可以先这样输入 cd /o/r/a/r
然后按TAB
,如果这是唯一匹配,那么zsh会补全为/opt/rubystack-1.9/apps/redmine,但如果还存在一个/opt/rubystack-1.8/apps/redmine,那zsh就会列出来让你挑选;
/opt/rubystack-1.9/apps/redmine,
但你想进入/opt/rubystack-1.8/apps/redmine,可以这样: cd 1.9 1.8 这表示将完整路径上的1.9替换为1.8再使用;
auto_pushd
选项(通过命令setopt auto_pushd
),这样你通过cd切换目录时,zsh会自动将前一个目录加到栈里,这样你就不会因为忘记pushd而遗憾了;cd -
回到上一个目录(即最后一次调用cd时所在的目录),但zsh里面有cd -2, cd +3这样的用法,并且在输入cd -之后按TAB能够列出目录名供挑选补全。不过需要注意的是,这里-2并不表示倒数第二次调用cd时的目录,而是倒数第二次通过pushd记录的目录,如果打开了auto_pushd选项,那么这两个的含义倒是一样的;
hash -d www=/var/www/html
定义一个路径别名,然后用cd ~www
就可以进入到/var/www/html
了参考资料: Refining Linux: ZSH Gem #20: Changing directories the pro's way
使用方法
/usr/local/lib/z.sh
);~/.bashrc
或者~/.zshrc
里面加入一句source /usr/local/lib/z.sh
,这使得以后的cd命令会被z.sh统计各目录访问频率;z -l
命令即可列出历史上你访问各个目录的频率了;z
regex 命令即可进入你频繁访问的目录oh-my-zsh提供了很多很花哨且功能强大的提示符设置,比如显示git当前分支名、提交状态等等:
不过我觉得Debian缺省推荐的(见/etc/zsh/newuser.zshrc.recommended
)提示符设置就可以了(只是简单地显示用户名、机器名和全路径)
autoload -Uz promptinit promptinit prompt adam1
不过我有时也想显示一点别的内容,zsh有个RPROMPT环境变量用来设置显示在右边的提示符,可以在有需要的时候即设即用,很方便。比如我用它配置了 用来显示当前git仓库名、分支名和提交状态(也许你又要问我为什么不用oh-my-zsh,那是因为我没看见它显示git仓库名,而这个庞大的东西我不 知道怎么去修改它。甚至下面这段代码我也是抛弃了StackOverflow上得票最多的答案,而是选了个得分为0的答案为基础,仅仅因为后面这个我能看懂,能修改它)
_git_repo_name() { gittopdir=$(git rev-parse --git-dir 2> /dev/null) if [[ "foo$gittopdir" == "foo.git" ]]; then echo `basename $(pwd)` elif [[ "foo$gittopdir" != "foo" ]]; then echo `dirname $gittopdir | xargs basename` fi } _git_branch_name() { git branch 2>/dev/null | awk '/^\*/ { print $2 }' } _git_is_dirty() { git diff --quiet 2> /dev/null || echo '*' } setopt prompt_subst RPROMPT='$(_git_repo_name) $(_git_branch_name) $(_git_is_dirty)'
4.1 多会话共享历史
我一般会用tmux
开多个会话,这种情况下记得刚才输入过这个命令,但找了半天没找到才意识到好像是在另外一个window/pane里面输入的。zsh的一个功能特性是share_history
,这样在一个会话里面可以访问另外一个会话的历史命令了。不过这个特性可能会让人有些不习惯,这样的话可以试试另外两个选项:setopt APPEND_HISTORY或者setopt INC_APPEND_HISTORY.
参考资料: Refining Linux: ZSH Gem #15: Shared history
setopt hist_ignore_space alias cd=" cd" alias ls=" ls"
第一句使得不将以空格开始的命令行记录到历史当中(这在需要在i命令行中明文输入密码时也挺有用,这样不会在历史记录中看到你的密码了);
后面两句使得cd/ls这些简单的命令就不记录到历史了,这样用history查看的时候是不是更清晰了?
来自 : http://chneukirchen.org/blog/archive/2012/02/10-new-zsh-tricks-you-may-not-know.html
另一个技巧: 每个目录记录自己的history: <http://linuxtoy.org/archives/zsh_per_dir_hist.html>
http://www.lowlevelmanager.com/2012/05/zsh-history-expansion.html
zsh支持更复杂的文件名匹配,不过我大部分我都没去学,只记住了我认为最有用的一个:
grep ":project_menu" **/*.erb
这个**会搜索所有的子目录,也就避免了用find了(bash下就得借用find了: find . -name '*.erb | xargs grep ":project_menu")
这是zsh缺省跟bash不兼容的一个地方。在zsh下,如果你执行dpkg -l firefox*
,很可能zsh不会列出名字以firefox开头的包,而是告诉你zsh: no matches found: firefox*
。这是因为zsh缺省情况下始终自己解释这个firefox*,而不会传递给dpkg来解释。
解决这个问题的方法是在~/.zshrc中加入:
setopt no_nomatch
zsh没有使用libreadline,而是自己实现了一套类似的(名字叫做zle - zsh command line editor)。所以你原来在~/.inputrc里面配置的快捷键都不再有效,而是要用zle的语法重新配置一遍(也在~/.zshrc中配置)。
例子1:
bindkey "^[0H" beginning-of-line bindkey "^[OF" end-of-line
例子2:
#按下F5时自动输入z -l | tail\n bindkey -s "\e[15~" "z -l | tail\n"
这是zsh跟bash不兼容的另一个地方,M-backspace会回删整个参数,而不是像bash/emacs那样只删除一个单词。
解决方法是在~/.zshrc中加入:
autoload -U select-word-style select-word-style bash
- [系统管理员工具包: 充分利用 zsh](http://www.ibm.com/developerworks/cn/aix/library/au-satzsh.html)
- [幕启:介绍 Z shell](http://www.ibm.com/developerworks/cn/linux/shell/z/)
- [终极Shell——Zsh — LinuxTOY](http://linuxtoy.org/archives/zsh.html)
- [使用 Zsh 的九个理由 - 博客 - 伯乐在线](http://blog.jobbole.com/28829/)
http://lcan.info/2011/01/myzshrc/
昨天装上了Arch,那bash shell的默认配置太烂了,pacman都不能补齐软件包名。用惯了zsh强大补齐功能的我自然用不下去了。果断换掉!
zsh要是默认配置的话,比bash还难用。但是配置好的zsh怎一个爽字了得!
我的.zshrc主要参考了Kardinal在LinuxToy上的一篇帖子,另外结合自己的需要和网上其他的一些配置综合而成。用起来相当顺手!很好很强大!贴出来共享下。
#color{{{
autoload colors
colors
for
color
in
RED GREEN YELLOW BLUE MAGENTA CYAN WHITE;
do
eval
_$color=
'%{$terminfo[bold]$fg[${(L)color}]%}'
eval
$color=
'%{$fg[${(L)color}]%}'
(( count = $count + 1 ))
done
FINISH=
"%{$terminfo[sgr0]%}"
#}}}
#命令提示符
RPROMPT=$(
echo
"$RED%D %T$FINISH"
)
PROMPT=$(
echo
"$CYAN%n@$YELLOW%M:$GREEN%/$_YELLOW>$FINISH "
)
#PROMPT=$(echo "$BLUE%M$GREEN%/
#$CYAN%n@$BLUE%M:$GREEN%/$_YELLOW>>>$FINISH ")
#标题栏、任务栏样式{{{
case
$TERM
in
(*xterm*|*rxvt*|(dt|k|E)term)
precmd () { print -Pn
"\e]0;%n@%M//%/\a"
}
preexec () { print -Pn
"\e]0;%n@%M//%/\ $1\a"
}
;;
esac
#}}}
#编辑器
export
EDITOR=vim
#输入法
export
XMODIFIERS=
"@im=ibus"
export
QT_MODULE=ibus
export
GTK_MODULE=ibus
#关于历史纪录的配置 {{{
#历史纪录条目数量
export
HISTSIZE=10000
#注销后保存的历史纪录条目数量
export
SAVEHIST=10000
#历史纪录文件
export
HISTFILE=~/.zhistory
#以附加的方式写入历史纪录
setopt INC_APPEND_HISTORY
#如果连续输入的命令相同,历史纪录中只保留一个
setopt HIST_IGNORE_DUPS
#为历史纪录中的命令添加时间戳
setopt EXTENDED_HISTORY
#启用 cd 命令的历史纪录,cd -[TAB]进入历史路径
setopt AUTO_PUSHD
#相同的历史路径只保留一个
setopt PUSHD_IGNORE_DUPS
#在命令前添加空格,不将此命令添加到纪录文件中
#setopt HIST_IGNORE_SPACE
#}}}
#每个目录使用独立的历史纪录{{{
cd
() {
builtin
cd
"$@"
# do actual cd
fc -W
# write current history file
local
HISTDIR=
"$HOME/.zsh_history$PWD"
# use nested folders for history
if
[ ! -d
"$HISTDIR"
] ;
then
# create folder if needed
mkdir
-p
"$HISTDIR"
fi
export
HISTFILE=
"$HISTDIR/zhistory"
# set new history file
touch
$HISTFILE
local
ohistsize=$HISTSIZE
HISTSIZE=0
# Discard previous dir's history
HISTSIZE=$ohistsize
# Prepare for new dir's history
fc -R
#read from current histfile
}
mkdir
-p $HOME/.zsh_history$PWD
export
HISTFILE=
"$HOME/.zsh_history$PWD/zhistory"
function
allhistory {
cat
$(
find
$HOME/.zsh_history -name zhistory) }
function
convhistory {
sort
$1 |
uniq
|
sed
's/^:\([ 0-9]*\):[0-9]*;\(.*\)/\1::::::\2/'
|
awk
-F
"::::::"
'{ $1=strftime("%Y-%m-%d %T",$1) "|"; print }'
}
#使用 histall 命令查看全部历史纪录
function
histall { convhistory =(allhistory) |
sed
'/^.\{20\} *cd/i\\'
}
#使用 hist 查看当前目录历史纪录
function
hist { convhistory $HISTFILE }
#全部历史纪录 top50
function
top50 { allhistory |
awk
-F
':[ 0-9]*:[0-9]*;'
'{ $1="" ; print }'
|
sed
's/ /\n/g'
|
sed
'/^$/d'
|
sort
|
uniq
-c |
sort
-nr |
head
-n 50 }
#}}}
#杂项 {{{
#允许在交互模式中使用注释 例如:
#cmd #这是注释
setopt INTERACTIVE_COMMENTS
#启用自动 cd,输入目录名回车进入目录
#稍微有点混乱,不如 cd 补全实用
setopt AUTO_CD
#扩展路径
#/v/c/p/p => /var/cache/pacman/pkg
setopt complete_in_word
#禁用 core dumps
limit coredumpsize 0
#Emacs风格 键绑定
bindkey -e
#bindkey -v
#设置 [DEL]键 为向后删除
#bindkey "\e[3~" delete-char
#以下字符视为单词的一部分
WORDCHARS=
'*?_-[]~=&;!#$%^(){}<>'
#}}}
#自动补全功能 {{{
setopt AUTO_LIST
setopt AUTO_MENU
#开启此选项,补全时会直接选中菜单项
#setopt MENU_COMPLETE
autoload -U compinit
compinit
#自动补全缓存
#zstyle ':completion::complete:*' use-cache on
#zstyle ':completion::complete:*' cache-path .zcache
#zstyle ':completion:*:cd:*' ignore-parents parent pwd
#自动补全选项
zstyle
':completion:*'
verbose
yes
zstyle
':completion:*'
menu
select
zstyle
':completion:*:*:default'
force-list always
zstyle
':completion:*'
select
-prompt
'%SSelect: lines: %L matches: %M [%p]'
zstyle
':completion:*:match:*'
original only
zstyle
':completion::prefix-1:*'
completer _complete
zstyle
':completion:predict:*'
completer _complete
zstyle
':completion:incremental:*'
completer _complete _correct
zstyle
':completion:*'
completer _complete _prefix _correct _prefix _match _approximate
#路径补全
zstyle
':completion:*'
expand
'yes'
zstyle
':completion:*'
squeeze-shlashes
'yes'
zstyle
':completion::complete:*'
'\\'
#彩色补全菜单
eval
$(
dircolors
-b)
export
ZLSCOLORS=
"${LS_COLORS}"
zmodload zsh
/complist
zstyle
':completion:*'
list-colors ${(s.:.)LS_COLORS}
zstyle
':completion:*:*:kill:*:processes'
list-colors
'=(#b) #([0-9]#)*=0=01;31'
#修正大小写
zstyle
':completion:*'
matcher-list
''
'm:{a-zA-Z}={A-Za-z}'
#错误校正
zstyle
':completion:*'
completer _complete _match _approximate
zstyle
':completion:*:match:*'
original only
zstyle
':completion:*:approximate:*'
max-errors 1 numeric
#kill 命令补全
compdef pkill=
kill
compdef pkill=killall
zstyle
':completion:*:*:kill:*'
menu
yes
select
zstyle
':completion:*:*:*:*:processes'
force-list always
zstyle
':completion:*:processes'
command
'ps -au$USER'
#补全类型提示分组
zstyle
':completion:*:matches'
group
'yes'
zstyle
':completion:*'
group-name
''
zstyle
':completion:*:options'
description
'yes'
zstyle
':completion:*:options'
auto-description
'%d'
zstyle
':completion:*:descriptions'
format
$
'\e[01;33m -- %d --\e[0m'
zstyle
':completion:*:messages'
format
$
'\e[01;35m -- %d --\e[0m'
zstyle
':completion:*:warnings'
format
$
'\e[01;31m -- No Matches Found --\e[0m'
zstyle
':completion:*:corrections'
format
$
'\e[01;32m -- %d (errors: %e) --\e[0m'
# cd ~ 补全顺序
zstyle
':completion:*:-tilde-:*'
group-order
'named-directories'
'path-directories'
'users'
'expand'
#}}}
##行编辑高亮模式 {{{
# Ctrl+@ 设置标记,标记和光标点之间为 region
zle_highlight=(region:
bg
=magenta
#选中区域
special:bold
#特殊字符
isearch:underline)
#搜索时使用的关键字
#}}}
##空行(光标在行首)补全 "cd " {{{
user-complete(){
case
$BUFFER
in
""
)
# 空行填入 "cd "
BUFFER=
"cd "
zle end-of-line
zle
expand
-or-complete
;;
"cd --"
)
# "cd --" 替换为 "cd +"
BUFFER=
"cd +"
zle end-of-line
zle
expand
-or-complete
;;
"cd +-"
)
# "cd +-" 替换为 "cd -"
BUFFER=
"cd -"
zle end-of-line
zle
expand
-or-complete
;;
* )
zle
expand
-or-complete
;;
esac
}
zle -N user-complete
bindkey
"\t"
user-complete
#}}}
##在命令前插入 sudo {{{
#定义功能
sudo
-
command
-line() {
[[ -z $BUFFER ]] && zle up-
history
[[ $BUFFER !=
sudo
\ * ]] && BUFFER=
"sudo $BUFFER"
zle end-of-line
#光标移动到行末
}
zle -N
sudo
-
command
-line
#定义快捷键为: [Esc] [Esc]
bindkey
"\e\e"
sudo
-
command
-line
#}}}
#命令别名 {{{
alias
cp
=
'cp -i'
alias
mv
=
'mv -i'
alias
rm
=
'rm -i'
alias
ls
=
'ls -F --color=auto'
alias
ll=
'ls -al'
alias
grep
=
'grep --color=auto'
alias
la=
'ls -a'
alias
pacman=
'sudo pacman-color'
alias
p=
'sudo pacman-color'
alias
y=
'yaourt'
alias
h=
'htop'
alias
vim=
'sudo vim'
#[Esc][h] man 当前命令时,显示简短说明
alias
run-help >&
/dev/null
&&
unalias
run-help
autoload run-help
#历史命令 top10
alias
top10=
'print -l ${(o)history%% *} | uniq -c | sort -nr | head -n 10'
#}}}
#路径别名 {{{
#进入相应的路径时只要 cd ~xxx
hash
-d A=
"/media/ayu/dearest"
hash
-d H=
"/media/data/backup/ayu"
hash
-d E=
"/etc/"
hash
-d D=
"/home/ayumi/Documents"
#}}}
##for Emacs {{{
#在 Emacs终端 中使用 Zsh 的一些设置 不推荐在 Emacs 中使用它
#if [[ "$TERM" == "dumb" ]]; then
#setopt No_zle
#PROMPT='%n@%M %/
#>>'
#alias ls='ls -F'
#fi
#}}}
#{{{自定义补全
#补全 ping
zstyle
':completion:*:ping:*'
hosts 192.168.1.{1,50,51,100,101} www.google.com
#补全 ssh scp sftp 等
#zstyle -e ':completion::*:*:*:hosts' hosts 'reply=(${=${${(f)"$(cat {/etc/ssh_,~/.ssh/known_}hosts(|2)(N) /dev/null)"}%%[# ]*}//,/ })'
#}}}
#{{{ F1 计算器
arith-
eval
-
echo
() {
LBUFFER=
"${LBUFFER}echo \$(( "
RBUFFER=
" ))$RBUFFER"
}
zle -N arith-
eval
-
echo
bindkey
"^[[11~"
arith-
eval
-
echo
#}}}
####{{{
function
timeconv {
date
-d @$1 +
"%Y-%m-%d %T"
}
# }}}
zmodload zsh
/mathfunc
autoload -U zsh-mime-setup
zsh-mime-setup
setopt EXTENDED_GLOB
#autoload -U promptinit
#promptinit
#prompt redhat
setopt correctall
autoload compinstall
#漂亮又实用的命令高亮界面
setopt extended_glob
TOKENS_FOLLOWED_BY_COMMANDS=(
'|'
'||'
';'
'&'
'&&'
'sudo'
'do'
'time'
'strace'
)
recolor-cmd() {
region_highlight=()
colorize=
true
start_pos=0
for
arg
in
${(z)BUFFER};
do
((start_pos+=${
#BUFFER[$start_pos+1,-1]}-${#${BUFFER[$start_pos+1,-1]## #}}))
((end_pos=$start_pos+${
#arg}))
if
$colorize;
then
colorize=
false
res=$(LC_ALL=C
builtin
type
$arg 2>
/dev/null
)
case
$res
in
*
'reserved word'
*) style=
"fg=magenta,bold"
;;
*
'alias for'
*) style=
"fg=cyan,bold"
;;
*
'shell builtin'
*) style=
"fg=yellow,bold"
;;
*
'shell function'
*) style=
'fg=green,bold'
;;
*
"$arg is"
*)
[[ $arg =
'sudo'
]] && style=
"fg=red,bold"
|| style=
"fg=blue,bold"
;;
*) style=
'none,bold'
;;
esac
region_highlight+=(
"$start_pos $end_pos $style"
)
fi
[[ ${${TOKENS_FOLLOWED_BY_COMMANDS[(r)${arg
//
|/\|}]}:+
yes
} =
'yes'
]] && colorize=
true
start_pos=$end_pos
done
}
check-cmd-self-insert() { zle .self-insert && recolor-cmd }
check-cmd-backward-delete-char() { zle .backward-delete-char && recolor-cmd }
zle -N self-insert check-cmd-self-insert
zle -N backward-delete-char check-cmd-backward-delete-char
|
原创文章,转载请注明: 转载自Lanpiceの鬼屋
本文链接地址: http://lcan.info/2011/01/myzshrc/