😉

[fish] 空エンターで git status

頻繁に使う git status をより簡単に打てるようにしたい。

解答

1. 関数を作る

~/.config/fish/functions/do_enter.fish を追加する。内容は以下のように

function do_enter
    set -l query (commandline)

    if test -n $query
        echo
        evalh $query
        commandline ''
    else
        echo
        if test (git rev-parse --is-inside-work-tree 2> /dev/null)
            git status
        end
    end

    commandline -f repaint
end

もう 1 つ、~/.config/fish/functions/evalh.fish を追加する。内容は以下のように

function evalh
  eval $argv

  echo "- cmd:" $argv >> ~/.local/share/fish/fish_history
  echo "  when:" (date "+%s") >> ~/.local/share/fish/fish_history
end

2. キーバインドする

~/.config/fish/config.fish に以下を追記する

function fish_user_key_bindings
    bind \cm do_enter
end

3. 再読み込みする

$ . ~/.config/fish/config.fish

できあがるまで

1. 関数を作る

fish では、~/.config/fish/functions/ 配下に .fish ファイルを作り、そこで関数を定義すると、自動的にロードされるようになる

たとえば do_enter という関数を作りたいなら、do_enter.fish を作って、そこに中身を書けばいい

function do_enter
    echo 'hello'
end

2. 関数を特定のキーにバインドする

~/.config/fish/config.fish に以下の記述を追加して再読み込みすると、キーバインドが反映される

function fish_user_key_bindings
    bind <key> <function>
end

たとえば ctrl + mdo_enter を割り当てるには以下のように書く

function fish_user_key_bindings
    bind \cm do_enter
end

ここで do_enterctrl + m にバインドしたのは、fish では ctrl + menter が割り当てられているから (もとは Vim のキーバインド)。 したがって、ctrl + m にバインドすると enter にバインドしたことになる。

3. git status を実行する

特定のコマンドを実行したいときは、そのままコマンドを書けばいい。

echo を書いたのは、コマンド入力部分に git status の結果が表示されないようにするため。

commandline -f repaint を書かないと git status の表示が終わった後にコマンド入力部分が表示されないので注意。

function do_enter
    echo
    git status

    commandline -f repaint
end

4. 他のコマンドと共存させる

現段階では、コマンドラインに他のコマンドが入力されていても、それを無視して git status が実行されてしまいとても不便。 何らかの文字列が入力されているときは、それを実行するようにする。

set -l query (commandline) で 変数 query に 入力されているコマンド (commandline) をセットする。

test -n "string" は、"" が空文字列かどうかをチェックする (空なら true)。

コマンドを実行するには eval $query

commandline '' は、入力されていた値をリセットする (リセットしないと次のコマンドラインに表示されてしまう)

function git_status
    set -l query (commandline)

    if test -n $query
        echo
        eval $query
        commandline ''
    else
        echo
        git status
    end

    commandline -f repaint
end

5. リポジトリ内でのみ git status

リポジトリでないところで git status してメッセージが表示されるのは嫌なので、リポジトリかどうかをチェックする。

チェックは git rev-parse --is-inside-work-tree を使う。カレントディレクトリがリポジトリ内であれば true が返る。

function do_enter
    set -l query (commandline)

    if test -n $query
        echo
        eval $query
        commandline ''
    else
        echo
        if test (git rev-parse --is-inside-work-tree 2> /dev/null)
            git status
        end
    end

    commandline -f repaint
end

6. 履歴に表示されるようにする

現段階では、do_enter 経由で実行したコマンドが履歴に保存されない (eval で実行しているから)

履歴を保持しているファイルに直接書き込むことによって、実行したコマンドが履歴に表示されるようにする

まず、eval に履歴保存処理をつけた evalh という関数を自作する

~/.config/fish/functions/evalh.fish

function evalh
  eval $argv

  echo "- cmd:" $argv >> ~/.local/share/fish/fish_history
  echo "  when:" (date "+%s") >> ~/.local/share/fish/fish_history
end

次に、do_enterevalevalh に置き換える

完成!


Refs