Solve conflict of zsh zaw plugin

前回の記事でzshのzawプラグインの問題が解決できたと思っていた。しかし,zaw-cdrの問題に遭遇した。試行錯誤の上,この問題も解決した。ここでzshのzawに関する問題と解決策について整理する。

まず,zshのzawプラグインは Emacsの anythin.el やVimのunite.vimのようにディレクトリやファイル,プログラムへのアクセスなど普段の作業に必要なものをzsh上でアクセスするための機能を 提供するものだと私は認識している。例えばzaw-cdrという機能を使えば,最近アクセスしたディレクトリに瞬時に移動ができ,作業効率の向上が見込まれる。

問題

zawプラグインを導入する際に生じた問題について説明する。問題は大きく以下の3種類だ。

  1. zsh起動時にfilter: と表示され絞り込み検索状態になり,C-gで解除してもすぐに同じ状態になり,zshで作業できない。
  2. zsh-cdr の機能を使うために定義したキーを入力すると以下のエラーメッセージが表示され実行できない。
    zaw-src-cdr:2: closing brace expected
  3. auto-fu プラグインをzawより先に読み込むと,zawの絞り込み検索を使うには最初にC-gでキャンセルしてからでないとzawの機能が使えない。

1.の問題の解決策は冒頭に上げたとおり前回の記事で対処した問題である。2.の問題は1.の問題を解決した後に発覚した問題である。3.の問題は他のプラグインとの競合の問題である。

問題の発生条件

1.と2.と3.の問題が発生する状況について説明する。

zshの起動時にfilter: から抜け出せない問題の再現

この問題の発生は以下の二つの条件が重なって生じる。

  1. パッケージマ ネージャーantigenによりzawを管理している。
    antigen-bundle zsh-users/zaw.git
  2. lsのaliasを-Fオプションをつけて定義している。
    alias ls="ls -F"

antigenによりzawを管理していければこの問題は発生しない。正確にはsource antigen.zshを実行すると問題が発生する。この問題は 以下の.zshrc を使うこ とで再現できる。antigenによりパッケージ管理をする都合上,最初にantigen をインストールしておく。以下の.zshrcの2行目から3行目のコメント文で記述したコマンドを入力することでantigenのインストールはされる。 zawはzshの起動時に自動的にインストールされる。

##~/.zshrc
#mkdir ~/.zsh/
#cd ~/.zsh
#git clone https://github.com/zsh-users/antigen.git
alias ls="ls -F"
if [ -f ~/.zsh/antigen/antigen.zsh ]; then
  ADOTDIR=$HOME/.zsh/
  source ~/.zsh/antigen/antigen.zsh
  antigen-bundle zsh-users/zaw
  antigen-apply
fi

zaw-cdr実行時のzaw-src-cdr:2: closing brace expectedの再現

この問題は以下のコマンドによりオプションをどこかで有効にしていると発生する。

setopt sh_word_split

問題の起こる最小限の.zshrcを以下に示した。

## .zshrc
if [ -f ~/.zsh/antigen/antigen.zsh ]; then
  ADOTDIR=$HOME/.zsh/
  source ~/.zsh/antigen/antigen.zsh
  autoload -Uz chpwd_recent_dirs cdr add-zsh-hook # valid zsh cdr
  antigen-bundle zsh-users/zaw.git
    bindkey "^m^m" zaw-cdr
  antigen-apply
fi
setopt sh_word_split
# source ~/.zsh/repos/https-COLON--SLASH--SLASH-github.com-SLASH-zsh-users-SLASH-zaw.git/zaw.zsh

この問題はzawをantigenで管理していようが,上記の.zshrcの最終行にコメ ントで書いたようにsourceコマンドで直接zawを有効にしても発生する。具体的にはzshを起動後にC-m C-mによりzaw-cdrの絞り込み検索に移行しようとすると以下のエラーが表示される。

zaw-src-cdr:2: closing brace expected

auto-fuとの競合の問題の再現

この問題はzshのインクリメンタル補完を行ってくれる,auto-fuプラグインとの競合により起こる。auto-fuプラグインをzawプラグインより先に読み 込むとauto-fuプラグインの機能が優先され,最初にC-gでキャンセルしないと,zawの各種絞り込み機能が使えなくなる。C-m C-mによりzaw-cdrの絞り込みもできないし,C-x;による標準の絞り込み検索もできない。

問題の起こる最小限の.zshrcを以下に示した。

## .zshrc
if [ -f ~/.zsh/antigen/antigen.zsh ]; then
  ADOTDIR=$HOME/.zsh/
  source ~/.zsh/antigen/antigen.zsh
  antigen-bundle hchbaw/auto-fu.zsh # need unsetopt sh_word_split
    zle-line-init () {auto-fu-init;}
  autoload -Uz chpwd_recent_dirs cdr add-zsh-hook # valid zsh cdr
  antigen-bundle zsh-users/zaw.git
    bindkey "^m^m" zaw-cdr
  antigen-apply
fi

また,auto-fuもsh_word_splitのオプションを有効にしている問題が発生する。以下のエラーが表示される。

afu-register-zle-accept-line:local:3: not valid in this context: $afufun
hi=''
zstyle=''
zle=''

この問題は開発者のhchbawさんも公認している問題で以下で発言がある。

auto-fu.zsh を読み込む際には、unsetopt sh_wordsplit してくださいませ。
auto-fu.gif

確認はしていないが,おそらくantigenを使っていなくても auto-fuとの競合は発生すると思われる。

解決策

上記で示したzawをめぐる3点の問題に対して解決策を示す。問題と対処方法の流れを以下の図に示し た。

zawプラグインの問題対処の流れ

大きく以下の2条件により対処法が異なる。

  1. antigen によるパッケージ管理の有無。
  2. auto-fu の有無。

1. antigenによるパッケージ管理を行っている場合,zawを 読み込む前に以下のコマンドを実行してはいけない。zawを読み込む前なので.zshenvにも記載があってはならない

alias ls="ls -F"

2. auto-fuをzawを使う場合はzawをauto-fuよりも先に読み込む。

auto-fuとzawの両方に共通する事項として,sh_word_splitのオプションは有効にしない。zshではデフォルトではsh_word_splitオプションは無効になっているので通常は何も書かなければ問題ない。念の為に以下のコマンドで明示的に解除しておくのもよいだろう。

unsetopt sh_word_split

最後に以下の2条件に当てはまる人(自分)がすべき設定をまとめる。

  1. antigenによりパッケージ管理を行っている
  2. zawとauto-fuを読み込んでいる

以下の3条件をこなせば問題なくzawを運用できる。

  1. zawの前にalias ls="ls -F"は書かない。
  2. zawの設定を auto-fuの前に書く。
  3. setopt sh_word_splitを書かない。

ここまでで説明したzawの問題に対処して動作する最小限の.zshrcを参考までに以下に示す。

## .zshrc
if [ -f ~/.zsh/antigen/antigen.zsh ]; then
  ADOTDIR=$HOME/.zsh/
  source ~/.zsh/antigen/antigen.zsh
  ## zaw-cdr
  autoload -Uz chpwd_recent_dirs cdr add-zsh-hook # valid zsh cdr
 
  antigen-bundle zsh-users/zaw.git
    bindkey "^m^m" zaw-cdr
  ## auto-fu
  antigen-bundle hchbaw/auto-fu.zsh # need unsetopt sh_word_split
    zle-line-init () {auto-fu-init;}
  antigen-apply
fi

参考

参考として記事中に登場した各パッケージのリポジトリのURLを示しておく。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です