わさっきhb

大学(教育研究)とか ,親馬鹿とか,和歌山とか,とか,とか.

俺流zsh追加設定

zshを快適に利用するために行っている,自分なりの設定をいくつか書きます.
バッドノウハウもあるかもしれませんので,ご利用は自己責任で.

ホーム直下ではなく

zshの設定(.zshrc)やヒストリ(.zsh_history)は,ホームディレクトリ直下ではなく,~/.zshというディレクトリに置いています.
~/.bashrcの中に,

export ZDOTDIR=$HOME/.zsh

と書いています.
以下,特別な場合を除いて,ディレクトリ名は書かず単に「.zshrc」と表記します.

Linux限定,Cygwin限定

.zshrcの早いところで,次のようにして,変数ARCHIに値(アーキテクチャ名,とでも言いましょうか)を割り当てています.

if [ -x /usr/bin/uname ] || [ -x /bin/uname ]; then
    case "`uname -sr`" in 
	Linux*);   export ARCHI="linux"   ;;
	CYGWIN*);  export ARCHI="cygwin"  ;;
	*);	   export ARCHI="dummy"   ;;
    esac
else
    export ARCHI="dummy"
fi

そして後方で

for suffix in "$ARCHI" "$HOST"
do
  local zshrc_suffix="$ZDOTDIR/.zshrc.$suffix"
  if [ -f $zshrc_suffix ]
  then
    source $zshrc_suffix
  fi
done

と書き,Linux環境であれば.zshrc.linuxを,Cygwin環境であれば.zshrc.cygwinを読みます.
マシン名(ホスト名)ごとに異なる設定は,.zshrc.マシン名 に書きます.

複数マシンで設定の共有

LinuxCygwinのいくつかのマシンで,.zshrc*を共有しているわけですが,そのやりとりにはSubversionを使っています.
ただし,~/.zshと,作業コピーは別に作り,必要に応じてやりとりし,更新やコミットをしています.
設定は次のとおりです.「for suffix in "$ARCHI" "$HOST" ... done」のあとに書きます.

if [ ${+SVN_HOME} = 1 ]
then
  function zshrc-up() {
    rsync -av --exclude=".*~" --exclude=".zsh_history" --exclude=".zcompdump" --exclude=".svn" "$SVN_HOME/env/zsh/" "$ZDOTDIR/"
  }
  function zshrc-ci() {
    rsync -av --exclude=".*~" --exclude=".zsh_history" --exclude=".zcompdump" --exclude=".svn" "$ZDOTDIR/" "$SVN_HOME/env/zsh/"
  }
  function zshrc-diff() {
    pushd $ZDOTDIR
    for f in .zshrc*
    do
	diff -q $f $SVN_HOME/env/zsh >/dev/null || diff -C 1 $f $SVN_HOME/env/zsh
    done
    popd
  }
fi

変数SVN_HOMEは,.zshrc.アーキテクチャ名またはホスト名 の中で設定しています.
zshrc-upは,作業コピーから~/.zshへ送ります.zshrc-ci(ciはcheck inの略)はその逆で,~/.zshから作業コピーへ送ります*1
やりとりする前に,ファイル単位で比較できるようにしたのが,zshrc-diffです.違いがあるときだけ,diff -C 1で出力するよう,diffコマンドを2つ並べています.

よく使うディレクトリ名

.zshrc.cygwinには,次のように設定を入れています.(某年月日,DRIVEDからDRIVEZまでを修正しました.)

export C="/cygdrive/c"; export DRIVEC="$C"
export D="/cygdrive/d"; export DRIVED="$D"
export E="/cygdrive/e"; export DRIVEE="$E"
export F="/cygdrive/f"; export DRIVEF="$F"
export G="/cygdrive/g"; export DRIVEG="$G"
export H="/cygdrive/h"; export DRIVEH="$H"
export I="/cygdrive/i"; export DRIVEI="$I"
export J="/cygdrive/j"; export DRIVEJ="$J"
export K="/cygdrive/k"; export DRIVEK="$K"
export L="/cygdrive/l"; export DRIVEL="$L"
export M="/cygdrive/m"; export DRIVEM="$M"
export N="/cygdrive/n"; export DRIVEN="$N"
export Z="/cygdrive/z"; export DRIVEZ="$Z"

export MYDOC="$C/Documents and Settings/$USER/My Documents"
export T="$C/Documents and Settings/$USER/デスクトップ"
if [ -d "$C/Users/$USER/Desktop" ]
then
  export T="$C/Users/$USER/Desktop"
  export DESKTOP="$T"
  export MYDOC="$C/Users/$USER"
fi

export DESKTOP="$T"
export MYDOCUMENT="$MYDOC"

これにより,ドライブ名は,$プラス大文字1文字で書くことができます.アルファベットすべてではなく,$Tはデスクトップとしています.$MYDOC, $MYDOCUMENT, $DESKTOPは,読んで字のごとしです.
if文を通るのはVista以降で,通らないのはXP以前…だったかな.最近XP+Cygwinを使っていないので,整理すべきかもしれません.

出力をクリップボード

これも,.zshrc.cygwinの設定です.

alias -g P='| nkf -sLw | putclip'

グローバルエイリアスです.例えば「df P」を実行すると,結果がクリップボードに入り,NTEmacsなどに貼り付けられます.
途中のnkfコマンドは,文字化け対策です*2nkfCygwinパッケージはなさそうなので,http://sourceforge.jp/projects/nkf/から取ってきてビルドし,/usr/local/binに入れています.

俺流コマンド

aliasやfunctionについて,.zshrcに書いているものをいくつか,ピックアップしてみました.

alias ls='ls -aFl --color --show-control-chars'
alias rm='echo rm'
alias SH='exec sh'
alias BASH='exec bash'
alias ZSH='exec zsh'
alias memo='cat > /dev/null'
alias eng='LANG=C LANGUAGE=C LC_ALL=C'
alias svn+exe='svn propset svn:executable ON'
alias svn-loghead="svn log --limit 1"
alias ymd='date +%y%m%d'
alias yymmdd=ymd
alias yyyymmdd=ymd
if which nkf > /dev/null
then
    alias nkf-unix="nkf --unix"
    alias nkf-dos="nkf --windows"
    alias nkf-unix-replace="nkf --unix --overwrite"
    alias nkf-dos-replace="nkf --windows --overwrite"
fi
function remake() {
    command rm $*
    command make $*
}

memoコマンドは,ターミナル上に自由に(といっても,Enterキーを押すと訂正できなくなりますが)書くときに実行します.
engを使う際,後ろにコマンドを置き,出力メッセージを英語にします.「df」と「eng df」とで,違いを確認できます.
大文字のSH,BASHZSHは,各シェルへの片道切符です.

アンチョコ

設定やシェルスクリプトを書いていると,変数展開の書式に悩むこともあります.そのつどWebで問い合わせるのも面倒なので,コンテンツを取ってきて貼り付けました.

# 変数展開
# http://amt.ty.land.to/OpenNote/zsh.info.html#sec42
#
# ${name}
#     変数の値に置換される。
# ${+name}
#     名前がセットされたパラメータだったら 1 そうでなかったらゼロ
# ${name:-word}
#     名前がセットされていて、ノンヌルな値ならば値を返す、
# ${name:=word}
#     名前がセットされていなければ、word をセットする
# ${name::=word}
#     名前にワードを無条件にセットする
# ${name:?word}
#     * 名前がセットされていてノンヌルならば、値をセットする
#     * そうでなければ、shell を exit する
# ${name:+word}
#     名前がセットされていてノンヌルならば、word に置換する
# ${name#pattern} ${name##pattern}
#     * パターンが値の頭にマッチしたら、マッチした部分を除いた値に置換
#     * そうでなかったら、単に値に置換
#     * # の方は最短マッチ、 ## は最長マッチ
# ${name%pattern} ${name%%pattern}
#     * パターンが値の終りにマッチしたら、マッチした部分を除いた値に置換
#     * そうでなかったら、単に値に置換
#     * % の方は最短マッチ、 %% は最長マッチ
# ${name:#pattern}
#     * パターンが名前にマッチしたら空文字列に置換
#     * そうでなかったら、単に値に置換
# ${name/pattern/repl} ${name//pattern/repl}
#     * 名前のパターンにマッチする部分が repl に置き換えられる
#     * ${name/pattern/repl} の方が、最初のマッチだけ置換
#     * ${name//pattern/repl} の方が、すべてんマッチを置換
#     * ダブルクォート文字列と同じ展開規則が適用されるので ${name/$opat/$npat} のように書くことができる
#     * パターンに # や % をつけて、最初や最後のマッチを指定できる
# ${#spec}
#     * spec が変数名だと値の長さ、配列だと配列長
#     * ^', `', and `~' を # と組み合わせる時は # より前(左)に置く

制御構文の短縮形も,同様にコマンド例を入れています.

setopt short_loops           # 制御構文で短縮形を使用する
# 例
# if [[ -r ~/.zshrc ]] source ~/.zshrc
# for distro in Vine Gentoo Berry Momonga; echo $distro Linux
# for distro ( Ubuntu Fedora SUSE Debian ) echo $distro Linux
# for (( i=1 ; i < 10 ; i++ )) echo $i
# i=0 ; while [[ $i -le 10 ]] { echo $((i++)) }

distroを順にechoする2つの行には,意味を持たせています.Vineほかは「〜 Linux」が公称となるのに対し,Ubuntuほかは「〜 Linux」が公称ではありません*3.何か月かおきにでも,.zshrcを見直すときには,このコマンド例も見直しています.

*1:NTEmacsでglobal-auto-revert-modeをtにしていて,.zshrcを編集して,作業コピーに送ろうとして手違いでzshrc-upを実行すると,悲惨なことになります.

*2:rubyと,標準添付ライブラリのnkfkconvを使ってワンライナーを書き,代用できないかいろいろ試したものの,文字化けは解消しませんでした.

*3:Debianは,「Debian/GNU Linux」または単に「Debian」.