zsh 使用 安装

http://www.cnblogs.com/bamanzi/p/zsh-simple-guide.html


bash用久了,有些地方开始觉得不爽,于是想看看有没有更好的选择。原来在网上瞎逛时,已经很多次看到有人推荐zsh了,加上zsh高度兼容bash,于是就来折腾这个。
不过试验了一下oh-my-zsh,感觉功能太强大了,太多东西不知道怎么配置的,这种过于“不知其所以然”的感觉我不太喜欢。于是自己来折腾,觉得基本够自己用就行了。

1. 补全

很多介绍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强的地方,尤其是涉及到交互的地方:

  1. 按TAB补全时,能够在多个备选项之间循环,如果备选项不多的话,你只需要不断按TAB就行了,而bash只会列出备选项,你得多输入一个或几个字母直到备选项缩小到一个了它才真正给你补全;
  2. 有一定的容错能力: 可以在配置文件中添加一句 zstyle ':completion::approximate:' max-errors 1 numeric ,以后输入cd /etc/x11, 按TAB后zsh会给你纠正为/etc/X11 (此条来自 终极Shell——Zsh — LinuxTOY,那里有详细的说明);
  3. 补全时可以用光标键或者Ctrl-p/Ctrl-n来挑选被选项(即很多文章说到的menu select方式)。不过针对第这一点,就得说到zsh的两个缺点:配置太TMD复杂、说明文档也巨罗嗦,你要是对缺省配置有一点点不满意,或者搞错了,就很容易陷入泥沼里,有兴趣的自己研究这个文档吧: Chapter 6: Completion, old and new - A User's Guide to the Z-Shell (P.S. 一篇简单的介绍: Refining Linux: ZSH Gem #5: Menu selection )

另外,zsh自带的补全源的确比bash-completion多,我这里find /usr/share/zsh/functions/Completion -type f | wc -l 的结果是688个文件(参见 Debian -- Filelist of package zsh-common/jessie/all )

2. 在目录中穿梭(cd命令)

在写代码过程中,会在各个目录之间来回切换,原来用bash时有两点最不爽:

  • 对cd命令有TAB补全的功能,但每一级目录都需要按TAB(并且有多个备选项的话需要继续输入才行)还是觉得繁琐,觉得效率不高;
  • pushd/popd/dirs虽然很有用,但很多时候等你想回到过去的某个目录时,才发现当时忘记pushd了

2.1 zsh的改进方法

  • 首先,假如/opt/rubystack-1.9/下面有apache2apps这两个目录,输入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而遗憾了;
  • bash里面可以cd -回到上一个目录(即最后一次调用cd时所在的目录),但zsh里面有cd -2, cd +3这样的用法,并且在输入cd -之后按TAB能够列出目录名供挑选补全。不过需要注意的是,这里-2并不表示倒数第二次调用cd时的目录,而是倒数第二次通过pushd记录的目录,如果打开了auto_pushd选项,那么这两个的含义倒是一样的;
  • zsh里面将~这个符号的用法进行了扩展,我们可以用hash -d www=/var/www/html定义一个路径别名,然后用cd ~www就可以进入到/var/www/html

参考资料: Refining Linux: ZSH Gem #20: Changing directories the pro's way

2.2 autojump: 快速进入频繁访问的目录(bash/zsh通用)

使用方法

  1. 下载这个 https://github.com/rupa/z/blob/master/z.sh (这个文件名跟zsh没有必然联系),放到某个位置(比如/usr/local/lib/z.sh);
  2. ~/.bashrc或者~/.zshrc里面加入一句source /usr/local/lib/z.sh,这使得以后的cd命令会被z.sh统计各目录访问频率;
  3. 你得按老方法切换目录一阵,以便z.sh能够知道哪些目录是最常用的;
  4. z -l命令即可列出历史上你访问各个目录的频率了;
  5. z regex 命令即可进入你频繁访问的目录

3. 提示符设置

oh-my-zsh提供了很多很花哨且功能强大的提示符设置,比如显示git当前分支名、提交状态等等:

3.1 基本设置

不过我觉得Debian缺省推荐的(见/etc/zsh/newuser.zshrc.recommended )提示符设置就可以了(只是简单地显示用户名、机器名和全路径)

autoload -Uz promptinit
promptinit
prompt adam1

3.2 RPROMPT

不过我有时也想显示一点别的内容,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. 命令历史

4.1 多会话共享历史

我一般会用tmux开多个会话,这种情况下记得刚才输入过这个命令,但找了半天没找到才意识到好像是在另外一个window/pane里面输入的。zsh的一个功能特性是share_history,这样在一个会话里面可以访问另外一个会话的历史命令了。不过这个特性可能会让人有些不习惯,这样的话可以试试另外两个选项:setopt APPEND_HISTORY或者setopt INC_APPEND_HISTORY.

参考资料: Refining Linux: ZSH Gem #15: Shared history

4.2 a clear 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

5. 其它设置

5.1 通配符带子目录

zsh支持更复杂的文件名匹配,不过我大部分我都没去学,只记住了我认为最有用的一个:

grep ":project_menu" **/*.erb

这个**会搜索所有的子目录,也就避免了用find了(bash下就得借用find了: find . -name '*.erb | xargs grep ":project_menu")

5.2 setopt no_nomatch

这是zsh缺省跟bash不兼容的一个地方。在zsh下,如果你执行dpkg -l firefox*,很可能zsh不会列出名字以firefox开头的包,而是告诉你zsh: no matches found: firefox*。这是因为zsh缺省情况下始终自己解释这个firefox*,而不会传递给dpkg来解释。

解决这个问题的方法是在~/.zshrc中加入:

setopt no_nomatch

5.3 ~/.inputrc无法工作?

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" 

5.4 让M-backspace象bash那样只回删一个单词

这是zsh跟bash不兼容的另一个地方,M-backspace会回删整个参数,而不是像bash/emacs那样只删除一个单词。

解决方法是在~/.zshrc中加入:

autoload -U select-word-style 
select-word-style bash

6. 参考资料

- [系统管理员工具包: 充分利用 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主要参考了KardinalLinuxToy上的一篇帖子,另外结合自己的需要和网上其他的一些配置综合而成。用起来相当顺手!很好很强大!贴出来共享下。

#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/


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值