speg03の雑記帳

主に未来の自分のために試したことなどを記録しています

xonshことはじめ

最近、xonshを使い始めました。

xonshrc

xonshの設定ファイルは~/.config/xonsh/rc.xshや~/.xonshrcが読み込まれるようですが、私は設定ファイルを何でも~/.configに集めたいので前者のファイルを作っています。

$COMPLETIONS_CONFIRM = True
$HISTCONTROL = "ignoredups"
$XONSH_AUTOPAIR = True

$DYNAMIC_CWD_WIDTH = (30, "c")
$PROMPT = (
    "{BOLD_GREEN}{user}@{hostname} {BOLD_BLUE}{cwd}{NO_COLOR} {gitstatus}\n"
    "{env_name}{prompt_end} "
)

@events.on_ptk_create
def custom_keybindings(bindings, **kw):

    @bindings.add("c-@")
    def _change_repository(event):
        repository = $(ghq list -p | peco).strip()
        if repository:
            cd @(repository)
            event.current_buffer.validate_and_handle()

環境変数による設定やプロンプトの設定はあまり凝ったことはせずシンプルなものです。重要なのはzshのときからずっと使っているghq+pecoの操作をショートカットキーで呼び出せるようにすることです。

c-@のキーバインドはc-spaceのエイリアスになっていて*1、実際にはc-spaceで入力しています。

$(ghq list -p | peco).strip() はシェルで実行されたghq+pecoの結果をPython文字列として処理しています(改行文字が末尾についているのでstrip)。

cd @(repository)Python文字列をシェルのコマンドラインに渡すための記法です。シェルとPythonを気軽に行ったり来たりできるのは便利ですね。

最後の event.current_buffer.validate_and_handle() *2 は現在のプロンプトにENTERキーを入力するようなもので、cdした結果がすぐにプロンプトに反映されるようにしています。

xonshの起動方法

なんとなくログインシェルに設定するには抵抗があるので、zshから起動して使います。

具体的には、zshenvにPATHなどの最低限の設定を書いておいて、zshrcからtmuxを起動し、tmuxのデフォルトシェルとしてxonshが起動するようにしています。

if [[ $TERM_PROGRAM != vscode && -z $XONSH_VERSION && -z $TMUX ]]; then
    run-tmux
fi

条件 $TERM_PROGRAM != vscodeVS Codeのターミナルで起動していないことを確認しています。VS CodePythonを書いているときにターミナルを開くと、Python仮想環境のactivateが自動的に実行されますが、それがxonshではうまく動作しません。そのため、VS Codeのターミナルではtmuxも使わず素のzshを使うようにしています。

条件 -z $XONSH_VERSION はxonshからzshが実行されていないことを確認しています。直接zshを実行した場合以外にも、xonshのsource-zshを実行した場合も該当します。

条件 -z $TMUX はtmuxが実行中でないことを確認しています。

スクリプト run-tmux はすでに起動中のtmuxセッションがあればそれに接続し、なければ新規のセッションにつなぐラッパースクリプトです。 ちなみに次のようなBashスクリプトになっています。

#!/usr/bin/env bash

session=${1:-main}

if [[ -z $TMUX ]]; then
    tmux new-session -A -s "$session"
else
    if ! tmux has-session -t "$session" &>/dev/null; then
        TMUX='' tmux new-session -d -s "$session"
    fi
    tmux switch-client -t "$session"
fi

これでひとまずは不自由なくxonsh生活が送れそうです。

*1:xonshが使っているprompt_toolkitのドキュメントに記載があります

*2:prompt_toolkitのBufferクラスからそれっぽい関数を見つけました