zsh と peco による私のディレクトリ移動


似たようなものはいっぱいあるけれど、zsh と peco を使った私のディレクトリ移動。

z <dir name>

  • [tab] でディレクトリ一覧からディレクトリ名を補完
  • ディレクトリ名が一致したら一気に移動
  • ディレクトリが部分的に一致したら peco で選ぶ

peco とは "Simplistic interactive filtering tool"

% brew install peco

~/.zshrcz コマンドを書く。

autoload -U compinit; compinit

function _z {
  compadd `cat $HOME/.peco/z-paths | sed 's|.*/||'`
}

compdef _z z

# z <dir>
# z add . : add current directory to directory list
# z edit  : edit the directory list with $ZEDIT

function z() {
  local PCD_FILE=$HOME/.peco/z-paths
  local PCD_RETURN
  local ZEDIT=${EDITOR:-emacs} # set your favourite editor

  if [ $1 ] && [ $1 = "add" ]; then
    # z add <dir>
    if [ $2 ]; then
      local ADD_DIR=$2
      if [ $2 = "." ]; then
        ADD_DIR=$(pwd) 
      fi
      echo "Adding $ADD_DIR to $PCD_FILE"
      echo $ADD_DIR >> $PCD_FILE
    fi
  elif [ $1 ] && [ $1 = "edit" ]; then
    # z edit
    $ZEDIT $PCD_FILE
  elif [ $1 ] && [ $1 = "." ]; then
    PCD_RETURN=$(/bin/ls -F | grep /$ | sort | peco)
  elif [ $1 ]; then
    # z <dir> unique matching
    local GREP_RETURN
    local grepcmd="cat $PCD_FILE"
    for pat in $*
    do
      grepcmd="$grepcmd | grep -e '/$pat'"
    done

    grepcmd=`echo $grepcmd | sed "s/'$/\$'/"`

    GREP_RETURN=`eval $grepcmd`
    echo "grep return = $GREP_RETURN"

    if [ `expr "$GREP_RETURN" : '.*'` -ne 0 -a \
     $(echo $GREP_RETURN | wc -l) -eq 1 ]; then
      # unique match
      PCD_RETURN=$GREP_RETURN
    else
      PCD_RETURN=$(cat $PCD_FILE | sort | peco --query "$*")
    fi
  else
    PCD_RETURN=$(cat $PCD_FILE | sort | peco)
  fi

  if [ $PCD_RETURN ]; then
    echo $PCD_RETURN
    cd $PCD_RETURN
  fi
}

まずは

% mkdir ~/.peco
% touch ~/.peco/z-paths

私は一覧に追加したいディレクトリを手動で追加している

% z add .

もし、$HOME以下全部を自動的に登録したければ find など

% find $HOME -type d > ~/.peco/z-paths

ディレクトリ一覧をみたり編集するには

% z edit

参考

zshの関数などのネタ元は忘れてしまいました(_ _)。