2017-05-03 / syui

shell

fish+shell

fishを使う機会が増えていて、なんかfishに関する記事でも書こうかなと思いつつ書けていないので、ここらへんで思いつく限り適当なことを書いてく。

まず、fishは他のshellとの互換性を完全に捨ててる。考慮もあんまりしてない感じだけど、それ故に可読性は良いと思う。が、shellの強みって一貫した書き方だったりするわけで、その点では触っていてめんどくささはかなりある。まあ、これをshellと見ること無く、アプリとか言語の一つとかとして見る場合は普通なんだけど、そんな感じです。これは何が問題なのかというと、例えば、他のアプリがshell変数なんかをあてにしてたりする場合、fishを使うことによって思わぬ動作不良を招くことも多いため、あくまで嗜好品とか、楽しんで使うアプリとしてみるほうが良いのかもしれません。

fishはあまり設定書かなくても使える。補完とかプロンプトだったり。あと、プラグインが読みやすいし、オリジナルの設定を書きやすい、改変しやすい感じ。但し、補完も書かないと不便なところは多くて、それは例えば特殊文字の扱いとか色々なんだけど、zshのほうが便利な部分もある。

最初に嵌りそうな点は以下。

# export a="word"
set a "word"

# a=`echo word`
set a (echo word)

# if which ls;then echo ok ls;fi
if
	which ls
end

# case $1 in
switch (echo arvg[1])
	case test
		echo ok
	end
end

# function a (){echo a}
# functionは付けなくてもいいが、内容によってはバッティングするため動作不良を引き起こす可能性あり
function a
	echo a
end

# alias v="vim"
alias v="vim"
# aliasで書いた文はfunctionで再定義されるのでそのまま書いてもいい
$ type v
function v
	vim
end

# case $OSTYPE in
# fishではいくつかの環境変数が設定されていない
switch (uname)
	case Darwin 
		echo mac
	case Linux
		echo linux
	case '*'
		echo other
	end
end

# . ~/.zshrc && exec $SHELL
# fishは設定を再度読み込むより再起動したほうがいい事が多い
exec fish

いろんなものをインストール。よく使うのはz, fzf, ghq, hub, tmuxなのでそれらと連携するプラグインなど。

$ curl -Lo ~/.config/fish/functions/fisher.fish --create-dirs git.io/fisher
$ fisher fzf z edc/bass omf/thefuck omf/theme-bobthefish decors/fish-ghq

fishでは~/.config/fish/config.fishに書いたバインドは有効になる場合とならない場合があり、基本的には有効になるが、~/.config/fish/functions/以下に置いたfish_user_key_bindings関数が無効になる。つまり、fish_user_key_bindings関数に書くのが順当であり、かつその関数ファイルはfunctions/に置くのが一般的。内容によってはcommandline -f repaintを入れないとプロンプトでEnterを押す必要が出てくるので必要な場合あり。

~/.config/fish/functions/fish_user_key_bindings.fish

function fish_user_key_bindings
	bind \cf peco_select_ghq_repository
	bind \ck __fish_cd_up
	bind \cs __fzf_find_file
	bind \cx __fzf_find_and_execute
	bind \ec __fzf_cd
	bind \eC __fzf_cd_with_hidden
	bind -M insert \eD __fzf_cd_with_hidden
end

function __fish_cd_up
	cd ..
	ls -slFa
	commandline -f repaint
end

注意ですが、bindの後ろは¥(半角)を入れてください。例えば、bind ¥cf pecoとかになります。

補完などはインストール時についてくるファイルを利用したりとか色々。PATHを通してもいいし、補完を作成したり、~/.config/fish/completionsに置いてもいい。

# https://github.com/github/hub/blob/master/etc/hub.fish_completion
$ brew install hub
ls /usr/local/bin/share/fish/completions/
$ fish_update_completions
$ hub
	alias (show shell instructions for wrapping git)
	browse (browse the project on GitHub)
	ci-status (display GitHub Status information for a commit)
	compare (lookup commit in GitHub Status API)
	create (create new repo on GitHub for the current project)
	fork (fork origin repo on GitHub)
	pull-request (open a pull request on GitHub)

tmuxとの連携は~/.tmux.confset-option -g default-command "reattach-to-user-namespace -l fish"を書くことでvimでのクリップボードとか色々な不都合が起こりにくい。

config.fish

if test $TERM != "screen"
 tmux new-session
 and exit
end

zとの連携は以下のような感じ。j -lで取得したりできるので、それを元に関数を書く。キーバインドのC-jで移動。

~/.config/fish/config.fish

set -U Z_CMD "j"
set -U Z_DATA "$HOME/.z"

~/.config/fish/functions/fish_user_key_bindings.fish

function peco_z
 set -l query (commandline)

 if test -n $query
 set peco_flags --query "$query"
 end

 j -l | peco $peco_flags | awk '{ print $2 }' | read recent
 if [ $recent ]
 cd $recent
 commandline -r ''
 commandline -f repaint
 end
end

function fish_user_key_bindings
 bind \e peco_z
end

このようにfishは昔からある基本的なshellの決まりごとはことごとく通用しない。

https://fishshell.com/docs/current/index.html