zshからxonshに乗り越えるために
基本的にxonshは、source-zshを利用することで、zshの設定をある程度読み込むことができます。
しかし、zshで利用していたzの設定をうまく読み込めなかったので、xonshで書き換えてxonshをメインのshellとして利用することを目指します。
zについて
過去のディレクトリの移動履歴をカウントするものです。
自分はzとpecoを使って、よく移動するディレクトリを選択し、移動するインターフェースを常時利用しており、これがないままのxonshの利用は快適ではありません。
zshでzの結果をpecoって爆速でディレクトリ移動する
zは引数なしで実行した時,よく移動するディレクトリ順と,頻度の指標が表示されます
参考: https://qiita.com/maxmellon/items/23325c22581e9187639e
zをxonshで読み込んでみる
zの利用は、z.shをshellでsourceすることにより利用できる仕組みになっています。.zshrcでの設定は、下記の感じです。
export _Z_CMD=z
. $(brew --prefix)/etc/profile.d/z.sh
xonshは外部のshellを読み込む機能があるため、xonshでz.shをsourceしてみましたが、うまく動作しないようです。
$ source-bash /usr/local/etc/profile.d/z.sh
$ z
xonsh: subprocess mode: command not found: _z
Did you mean one of the following?
z: Alias
xz: Command (/Users/htaguchi/.pyenv/versions/anaconda3-5.0.1/bin/xz)
w: Command (/usr/bin/w)
[: Command (/bin/[)
cd: Alias
$ _z
xonsh: subprocess mode: command not found: _z
Did you mean one of the following?
z: Alias
xz: Command (/Users/htaguchi/.pyenv/versions/anaconda3-5.0.1/bin/xz)
w: Command (/usr/bin/w)
[: Command (/bin/[)
cd: Alias
何かうまくsourceする方法がありそうですが、.xonshrcにてzと同等の機能を作成した方が、目的をすぐに達成できそうなので、今回はそちらの手法を試みます。
zの書き換え
zで利用していた機能は、「よく移動するディレクトリ順と,頻度の指標の表示」でした。
そのため、zと同等の機能を得るために
- ディレクトリ移動のタイミングで、カレントディレクトリのパスのログを落とす
- カレントディレクトリのパスのログから、頻度順にパスを並び替える
の順番で実装を行っていこうと思います。
実装
xonshのチュートリアルを確認すると、関数に@events.on_chdirのデコレータを利用するだけで、ディレクトリ移動をフックできるようなので、これを利用します
参考: http://xon.sh/tutorial_events.html
from collections import Counter
from prompt_toolkit.keys import Keys
$DIR_HIST_PATH = "/Users/htaguchi/.dirhist"
"""
1. ディレクトリの移動タイミングで、カレントディレクトリのパスをファイルに保存
"""
@events.on_chdir
def add_to_file(olddir, newdir, **kw):
with open($DIR_HIST_PATH[0], 'a') as dh:
print(newdir, file=dh)
"""
2. パスの出現頻度を算出し、降順に並べる
"""
def z():
lines = open($DIR_HIST_PATH[0]).read().rstrip("\n").split("\n")
return("\n".join([p for p, c in Counter(lines).most_common()]))
"""
3. CTRL-F + CTRL-R のキーで関数を呼び出し
"""
@events.on_ptk_create
def custom_keybindings(bindings, **kw):
handler = bindings.registry.add_binding
@handler(Keys.ControlF, Keys.ControlR)
def _z(event):
selected = $(echo @(z()) | peco)
cd_cmd = "cd " + selected.strip()
event.current_buffer.insert_text(cd_cmd)
まとめ
zの設定を乗り越えたので、これでxonshをメインのshellとして利用できそうです。
Pythonの資産を利用したshellの拡張がすぐできるのは、とても良いですね。