読者です 読者をやめる 読者になる 読者になる

最近のzshrcとその解説

zsh週間と言うことで、最近の僕のzshrcを紹介してみる。

解説

zshrc本体を紹介する前に、ちょっと分かりにくい所の解説。

lessのオプションを環境変数で指定する
export LESS='--tabs=4 --no-init --LONG-PROMPT --ignore-case'

lessはよく使うので、快適なオプションを指定しておきたい。環境変数LESSで指定しておけば自動的にlessのオプションとして認識されるよ。

--LONG-PROMPT ってのはプロンプト(lessの一番下の行)に詳細を表示させるっていうオプションで、今は上から何行目で何%まで進んだか、とかが表示される。

ちなみにこれはzsh関係なくて、bashとかでもできる。

smart-insert-last-word の設定

コマンドライン編集用の便利なキーバインドで、Ctrl+] で一つ前のコマンドの最後の単語を挿入できるようになる。設定方法はこんな感じ。

autoload smart-insert-last-word
zle -N insert-last-word smart-insert-last-word
zstyle :insert-last-word match \
  '*([^[:space:]][[:alpha:]/\\]|[[:alpha:]/\\][^[:space:]])*'
bindkey '^]' insert-last-word

さらに zstyle :insert-last-wordって行の設定で、2文字以上の単語だけが補完対象になる。もっと詳しく言うと、[a-zA-Z], /, \ のいずれかを1文字以上含む、長さが2文字以上の単語。

使い方の例

% ls /usr/bin L
# さっき見たディレクトリに移動したい
% cd  # ここで ^] を押す
% cd /usr/bin # 最後の単語が挿入される。L は出てこない。

詳しくは man zshcontribsmart-insert-last-word 参照。

一つ前の単語を ' " で囲むキーバインド

コマンドライン編集中に、* とか [ とか含むのを指定するときみたいに、単語を ' (シングルコーテーション)で囲みたくなるときがある。そんなときはこれ。

# quote previous word in single or double quote
autoload -U modify-current-argument
_quote-previous-word-in-single() {
    modify-current-argument '${(qq)${(Q)ARG}}'
    zle vi-forward-blank-word
}
zle -N _quote-previous-word-in-single
bindkey '^[s' _quote-previous-word-in-single

_quote-previous-word-in-double() {
    modify-current-argument '${(qqq)${(Q)ARG}}'
    zle vi-forward-blank-word
}
zle -N _quote-previous-word-in-double
bindkey '^[d' _quote-previous-word-in-double

コマンドライン入力中に Meta-s で、一つ前の単語を ' で囲めるようになる(Meta-sAlt+s または Esc のあとに s)。Meta-s の代わりに Meta-d" で囲める。

詳しくは man zshcontribmodify-current-argument 参照。

補完メニューをemacs風操作で選ぶ

わりと有名なネタだけど、補完候補がいっぱい出てきたときサクサク選ぶための設定。

zstyle ':completion:*:default' menu select=1

これで補完候補を選ぶとき ^F で前に進む、とかemacsっぽい操作で選べるようになる。

候補候補を受け付けて一つ下のディレクトリの候補に降りたいときは、 / を押してから TAB でOK。setopt auto_remove_slash を指定してたら / が2重になったりしなくていい感じ。

ちょっと便利な global alias
alias -g V='| vim -R -'
alias -g U=' --help | head'
alias -g P=' --help | less'

1つ目はvimで表示するalias。diffの結果とかが色つきでみれるのが嬉しい。

2つ目はこんな感じで使う。

% ln
# おっと、ln ってリンク名とターゲットとどっちが先だったかな?
# そんなときは U で --help の上の方だけを見る
% ln U
Usage: ln [OPTION]... [-T] TARGET LINK_NAME   (1st form)
  or:  ln [OPTION]... TARGET                  (2nd form)
  or:  ln [OPTION]... TARGET... DIRECTORY     (3rd form)
  or:  ln [OPTION]... -t DIRECTORY TARGET...  (4th form)
# たいてい上の方に Usage がある

たまに便利。

zshrc 全体

で、zshrc 全体はこんな感じ。240行ぐらい。

# zshrc

umask 022
limit coredumpsize 0

##############################
#environment variables
##############################

export LANG=ja_JP.UTF-8
export EDITOR=vim
export PAGER=less
export LESS='--tabs=4 --no-init --LONG-PROMPT --ignore-case'
export GREP_OPTIONS='--color=auto'
export MAIL=/var/mail/$USERNAME
#export PS4 for bash
export PS4='-> $LINENO: '

if [ -d "/usr/share/zsh/help/" ]; then
    export HELPDIR=/usr/share/zsh/help/
fi

#ls color
eval $(dircolors -b)
#not use bold
if which perl >/dev/null 2>&1 ;then
    LS_COLORS=$(echo $LS_COLORS | perl -pe 's/(?<= [=;] ) 01 (?= [;:] )/00/xg')
    zstyle ':completion:*' list-colors ${(s.:.)LS_COLORS}
fi


##############################
#key bind
##############################
bindkey -e

bindkey '^V' vi-quoted-insert
bindkey "^[u" undo
bindkey "^[r" redo
# not accept-line, but insert newline
bindkey '^J' self-insert-unmeta

# like insert-last-word,
# except that non-words are ignored
autoload smart-insert-last-word
zle -N insert-last-word smart-insert-last-word
#   include words that is at least two characters long
zstyle :insert-last-word match '*([^[:space:]][[:alpha:]/\\]|[[:alpha:]/\\][^[:space:]])*'
bindkey '^]' insert-last-word

# like delete-char-or-list, except that list-expand is used
function _delete-char-or-list-expand() {
    if [[ -z "${RBUFFER}" ]]; then
        # the cursor is at the end of the line
        zle list-expand
    else
        zle delete-char
    fi
}
zle -N _delete-char-or-list-expand
bindkey '^D' _delete-char-or-list-expand

# kill backward one word,
# where a word is defined as a series of non-blank characters
function _kill-backward-blank-word() {
    zle set-mark-command
    zle vi-backward-blank-word
    zle kill-region
}
zle -N _kill-backward-blank-word
bindkey '^Y' _kill-backward-blank-word

# history-search-end:
# This implements functions like history-beginning-search-{back,for}ward,
# but takes the cursor to the end of the line after moving in the
# history, like history-search-{back,for}ward.
autoload history-search-end
zle -N history-beginning-search-backward-end history-search-end
bindkey "^O" history-beginning-search-backward-end

# quote previous word in single or double quote
autoload -U modify-current-argument
_quote-previous-word-in-single() {
    modify-current-argument '${(qq)${(Q)ARG}}'
    zle vi-forward-blank-word
}
zle -N _quote-previous-word-in-single
bindkey '^[s' _quote-previous-word-in-single

_quote-previous-word-in-double() {
    modify-current-argument '${(qqq)${(Q)ARG}}'
    zle vi-forward-blank-word
}
zle -N _quote-previous-word-in-double
bindkey '^[d' _quote-previous-word-in-double


##############################
#default configuration
##############################

#set PROMPT
autoload -U colors
colors

if [[ -z "${REMOTEHOST}${SSH_CONNECTION}" ]]; then
    #local shell
    PROMPT="%U%{${fg[red]}%}[%n@%m]%{${reset_color}%}%u(%j) %~
%# "
else
    #remote shell
    PROMPT="%U%{${fg[blue]}%}[%n@%m]%{${reset_color}%}%u(%j) %~
%# "
fi


#history configuration
HISTFILE=~/.zsh_history
HISTSIZE=1000000
SAVEHIST=1000000
setopt share_history
setopt hist_ignore_all_dups
setopt hist_save_nodups
#remove the history (fc -l) command from the history list
setopt hist_no_store
setopt hist_ignore_space
setopt hist_reduce_blanks

#completion
autoload -U compinit
compinit

setopt auto_menu
setopt extended_glob
#expand argument after = to filename
setopt magic_equal_subst
setopt print_eight_bit

zstyle ':completion:*:default' menu select=1
if [ -d ~/.zsh/cache ]; then
    zstyle ':completion:*' use-cache yes
    zstyle ':completion:*' cache-path ~/.zsh/cache
fi


#cd
setopt auto_cd
setopt auto_pushd
setopt pushd_ignore_dups
cdpath=(${HOME} ${HOME}/work)

#etc
#allow comments in interactive shell
setopt interactive_comments
setopt rm_star_silent
setopt no_prompt_cr

#not include / in word characters
WORDCHARS='*?_-.[]~=&;!#$%^(){}<>'
setopt auto_remove_slash

#disable flow control
setopt no_flow_control

#not exit on EOF
setopt ignore_eof

#never ever beep ever
setopt no_beep


##############################
#aliases
##############################

#list
alias ls='ls -F --color=auto'
alias l='ls'
alias la='ls -a'
alias ll='ls -l'
alias ld='ls -d'
alias lt='tree -F'

#file operation
alias rm='rm -i'
alias cp='cp -i'
alias mv='mv -i'

#vi
alias vi='vim'
alias v='vim'
alias vir='vim -R'
alias vr='vim -R'
alias winvi='vim -c "edit ++fileformat=dos ++enc=cp932"'
alias eucvi='vim -c "edit ++enc=euc-jp"'
alias gm='gvim'

#grep
alias grep='grep -E'

#history
#-n option suppresses command numbers
alias history='builtin history 1'
alias his='builtin history -n 1'
alias h='builtin history -n -10'

#enable alias to sudo command argument
alias sudo='sudo '

#etc
alias c='cd'
alias dirs='dirs -p'
alias ln='ln -s'
alias jb='jobs -l'
alias sc=screen
alias m='man'
alias eman="LANG=C man"
alias em="LANG=C man"
alias di='diff -u'
alias rlocate='locate --regex'

#global aliases
alias -g L='| less'
alias -g H='| head'
alias -g T='| tail'
alias -g G='| grep'
alias -g V='| vim -R -'
alias -g U=' --help | head'
alias -g P=' --help | less'


# cdd
if [ -f ~/local/etc/scripts/cdd ]; then
    source ~/local/etc/scripts/cdd
    function chpwd() {
        _reg_pwd_screennum
    }
fi

# source local rcfile
if [ -f ~/.zshrc_local ]; then
    source ~/.zshrc_local
fi

# vim:set ft=zsh: