もうちょっと真面目にMSYS2でfishを使う

# はじめに

これまで私はずっとbashを使ってきた。なぜならば多くの環境でデフォルトのシェルだからだ。

無論zshの存在は知っていたが、面倒そうだったので敬遠していた。

ところがどうもfishという素晴らしいシェルがあるらしい。

使ってみよう。

# 先行研究

MSYS2でfishを使う - Qiita
https://qiita.com/sgur/items/6735815c860589ab4c5a

という記事があるが、これでは不十分であった。

# 導入

もちろんmsys2ではpacmanが利用できるので素直に

```bash
$ pacman -S fish
```

とするだけでいい。

ためしにfishを使うだけならこのあと

```bash
$ fish
```

として遊ぶと良い。
# 設定

msys2では多くの環境変数などの設定が必要だ。ログインシェルとして使う場合、これらを自力で設定する必要がある。

## `/usr/etc/fish/config.fish`

```zsh:/usr/etc/fish/config.fish
# from /etc/profile
if status --is-login
	set MSYS2_PATH /usr/local/bin /usr/bin /bin
	set MANPATH /usr/local/man /usr/share/fish/man /usr/share/man /usr/man /share/man $MANPATH
	set -gx INFOPATH /usr/local/info /usr/share/info /usr/info /share/info $INFOPATH

	if test -n "$MSYS2_PATH_TYPE"
		switch $MSYS2_PATH_TYPE
			case strict
				# Do not inherit any path configuration, and allow for full customization
				# of external path. This is supposed to be used in special cases such as
				# debugging without need to change this file, but not daily usage.
				set -e ORIGINAL_PATH
			case inherit
				# Inherit previous path. Note that this will make all of the Windows path
				# available in current shell, with possible interference in project builds.
				set ORIGINAL_PATH $PATH
			case '*'
				# Do not inherit any path configuration but configure a default Windows path
				# suitable for normal usage with minimal external interference.
				set WIN_ROOT (/usr/bin/env PATH=$MSYS2_PATH cygpath -Wu)
				set ORIGINAL_PATH $WIN_ROOT/System32 $WIN_ROOT $WIN_ROOT/System32/Wbem $WIN_ROOT/System32/WindowsPowerShell/v1.0
		end
	else
		# Do not inherit any path configuration but configure a default Windows path
		# suitable for normal usage with minimal external interference.
		set WIN_ROOT (/usr/bin/env PATH=$MSYS2_PATH cygpath -Wu)
		set ORIGINAL_PATH $WIN_ROOT/System32 $WIN_ROOT $WIN_ROOT/System32/Wbem $WIN_ROOT/System32/WindowsPowerShell/v1.0
	end
	if test -n $MSYSTEM
		switch $MSYSTEM
			case MINGW32
				set MINGW_MOUNT_POINT /mingw32
				set -gx PATH $MINGW_MOUNT_POINT/bin $MSYS2_PATH $ORIGINAL_PATH
				set -gx PKG_CONFIG_PATH $MINGW_MOUNT_POINT/lib/pkgconfig $MINGW_MOUNT_POINT/share/pkgconfig
				set ACLOCAL_PATH $MINGW_MOUNT_POINT/share/aclocal /usr/share/aclocal
				set -gx MANPATH $MINGW_MOUNT_POINT/share/man $MANPATH
			case MINGW64
				set MINGW_MOUNT_POINT /mingw64
				set -gx PATH $MINGW_MOUNT_POINT/bin $MSYS2_PATH $ORIGINAL_PATH
				set -gx PKG_CONFIG_PATH $MINGW_MOUNT_POINT/lib/pkgconfig $MINGW_MOUNT_POINT/share/pkgconfig
				set ACLOCAL_PATH $MINGW_MOUNT_POINT/share/aclocal /usr/share/aclocal
				set -gx MANPATH $MINGW_MOUNT_POINT/share/man $MANPATH
			case MSYS
				set -gx PATH $MSYS2_PATH /opt/bin:$ORIGINAL_PATH
				set -gx PKG_CONFIG_PATH /usr/lib/pkgconfig /usr/share/pkgconfig /lib/pkgconfig
				set -gx MANPATH $MANPATH
			case '*'
				set -gx PATH $MSYS2_PATH $ORIGINAL_PATH
				set -gx MANPATH $MANPATH
		end
	end

	# from /etc/msystem
	switch $MSYSTEM
		case MINGW32
			set -gx MSYSTEM_PREFIX /mingw32
			set -gx MSYSTEM_CARCH i686
			set -gx MSYSTEM_CHOST i686-w64-mingw32
			set -gx MINGW_CHOST $MSYSTEM_CHOST
			set -gx MINGW_PREFIX $MSYSTEM_PREFIX
			set -gx MINGW_PACKAGE_PREFIX mingw-w64-$MSYSTEM_CARCH
			set -gx CONFIG_SITE $MSYSTEM_PREFIX/etc/config.site
		case MINGW64
			set -gx MSYSTEM_PREFIX /mingw64
			set -gx MSYSTEM_CARCH x86_64
			set -gx MSYSTEM_CHOST x86_64-w64-mingw32
			set -gx MINGW_CHOST $MSYSTEM_CHOST
			set -gx MINGW_PREFIX $MSYSTEM_PREFIX
			set -gx MINGW_PACKAGE_PREFIX mingw-w64-$MSYSTEM_CARCH
			set -gx CONFIG_SITE $MSYSTEM_PREFIX/etc/config.site
		case '*'
			set -gx MSYSTEM_PREFIX /usr
			set -gx MSYSTEM_CARCH $HOSTTYPE
			set -gx MSYSTEM_CHOST $MACHTYPE
			set -gx CONFIG_SITE /etc/config.site
	end

	set -gx SYSCONFDIR /etc

	set ORIGINAL_TMP $TMP
	set ORIGINAL_TEMP $TEMP
	set -e TMP
	set -e TEMP
	set -gx tmp (cygpath -w $ORIGINAL_TMP 2> /dev/null)
	set -gx temp (cygpath -w $ORIGINAL_TEMP 2> /dev/null)
	set -gx TMP /tmp
	set -gx TEMP /tmp

	set p "/proc/registry/HKEY_CURRENT_USER/Software/Microsoft/Windows NT/CurrentVersion/Windows/Device"
	if test -e $p
		read PRINTER < $p
		set -gx PRINTER (echo $PRINTER | sed -e 's/,.*$//g')
	end
	set -e p

	if test -n "$ACLOCAL_PATH"
		set -gx ACLOCAL_PATH $ACLOCAL_PATH
	end

	set -gx LC_COLLATE C
	for postinst in /etc/post-install/*.post
		if test -e $postinst
			sh -c $postinst
		end
	end

	# from /etc/profile.d/lang.sh
	if test -n "$LC_ALL"; or test -n "$LANG"; or test -n "$LC_CTYPE"
		set -gx LC_CTYPE (/usr/bin/locale -uU)
		set -gx LC_NUMERIC $LC_CTYPE
		set -gx LC_TIME $LC_CTYPE
		set -gx LC_COLLATE $LC_CTYPE
		set -gx LC_MONETARY $LC_CTYPE
		set -gx LC_MESSAGES $LC_CTYPE
	end

	# from /etc/profile.d/perlbin.sh
	if test -d /usr/bin/site_perl
		set -gx PATH $PATH /usr/bin/site_perl
	end
	if test -d /usr/lib/perl5/site_perl/bin
		set -gx PATH $PATH /usr/lib/perl5/site_perl/bin
	end

	if test -d /usr/bin/vendor_perl
		set -gx PATH $PATH /usr/bin/vendor_perl
	end
	if test -d /usr/lib/perl5/vendor_perl/bin
		set -gx PATH $PATH /usr/lib/perl5/vendor_perl/bin
	end

	if test -d /usr/bin/core_perl
		set -gx PATH $PATH /usr/bin/core_perl
	end
end
```

このような設定ファイルを書けばいい。先行研究で上げた記事のものだと、`$MSYS2_PATH_TYPE`やlocale、`/etc/msystem`相当の内容、perl絡みの設定が抜け落ちている。

## `~/.config/fish/functions/fish_prompt.fish`

下で紹介しているように、`omf/theme-agnoster`を導入すると`~/.config/fish/functions/fish_prompt.fish`が生成されている。

この下の方に書かれている`function fish_prompt`の中に

```diff
--- /home/yumetodo/.config/fish/functions/fish_prompt.fish-old    2018-06-22 11:20:35.783796900 +0900
+++ /home/yumetodo/.config/fish/functions/fish_prompt.fish      2018-06-21 20:10:49.662732400 +0900

@@ -219,13 +219,14 @@
 # ===========================

 function fish_prompt
   set -g RETVAL $status
   prompt_status
   prompt_virtual_env
   prompt_user
+  prompt_segment black magenta $MSYSTEM
   prompt_dir
   type -q hg;  and prompt_hg
   type -q git; and prompt_git
   type -q svn; and prompt_svn
   prompt_finish
 end
```

のように書き足すと

![キャプチャ.PNG](https://qiita-image-store.s3.amazonaws.com/0/94177/258c0ee1-8d1e-d315-ab55-af598a59d034.png)

のように`MINGW64`とかを表示させられる。

なお私はConEmu使いなので`x-term256`とかが使えないため、`prompt_segment`にhexを渡すことはできない。

## `~/.config/fish/config.fish`

適宜aliasを貼ったりするとよい。

```zsh:~/.config/fish/config.fish
alias gnuplot="gnuplot -p"
alias ag='ag -S --stats --pager "less -F"'
alias agh='ag --hidden'
alias subl="'/c/Program Files/Sublime Text 3/sublime_text.exe'"
alias ffmpeg="C:/program1/aviutl100/exe_files/ffmpeg.exe"

set -g theme_display_user no
set -g theme_hide_hostname yes
```

`theme_display_user`と`theme_hide_hostname`をいじることで`uuu@hhh`みたいな表記を表示させるか決められる。上のはデフォルト設定と同じだ。

## `~/.config/fish/functions/code.fish`

aliasを`~/.config/fish/config.fish`に

```zsh
alias code="'C:/Program Files/Microsoft VS Code/bin/code'"
```

のように貼っても

```
/usr/bin/env: `bash': No such file or directory
```

とか言われて起動しない。そこでカスタム関数を追加する。

```zsh:~/.config/fish/functions/code.fish
function code --description "start Visual Studio Code"
    set NAME "Code"
    set VSCODE_PATH "/c/Program Files/Microsoft VS Code"
    set ELECTRON "$VSCODE_PATH/$NAME.exe"
    set CLI "$VSCODE_PATH/resources/app/out/cli.js"
    env ELECTRON_RUN_AS_NODE=1 "$ELECTRON" "$CLI" $argv
end
```
`VSCODE_PATH`は`code.exe`のあるパスだ。


# ConEmuの設定

私はcmderからConEmuを使っているのでこいつからfishを呼べるようにする。

`StartUp`>`Tasks`に

![image.png](https://qiita-image-store.s3.amazonaws.com/0/94177/ad65cff2-c5a5-d7fc-7e3a-1dbbee7d400f.png)

```
-new_console:d:C:\msys64\home\%USERNAME% set CHERE_INVOKING=1 & set MSYSTEM=MINGW64 & set XDG_RUNTIME_DIR=/tmp/fish.%USERNAME% & %ConEmuDrive%\msys64\usr\bin\fish.exe --login -i -new_console:C:"%ConEmuDrive%\msys64\msys2.ico"
```

を書けば良い。`XDG_RUNTIME_DIR`は多分必要なはず。

# Pluginで遊ぶ

```
curl -Lo ~/.config/fish/functions/fisher.fish --create-dirs git.io/fisher
fisher install 0rax/fish-bd omf/theme-agnoster edc/bass z
```

などとするとテーマが手に入ったり便利な機能が追加されるのでよい。

fisher コマンドについては
https://github.com/fisherman/fisherman
が公式repoで、検索すればいろいろな情報が手にはいる。

なおテーマを入れるに際し、フォントをいじってみたいな話が書かれているが、**私は心の目でフォント合成することにした**のでその設定は行わない。

# fishのマニュアル

下手にググる前に

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

を読むべし。

# 問題

## manが使えない

```
man: can't execute iconv: No such file or directory
man: can't execute less: No such file or directory
man: コマンドはステータス 255 で終了しました: /usr/lib/man-db/zsoelim | /usr/lib/man-db/manconv -f UTF-8:ISO-8859-1 -t ISO-8859-1//IGNORE | tbl | nroff -mandoc -rLL=264n -rLT=264n -Tascii8
```

などと言われる。わけがわからない。

## その他

pacmanやらなんかビルドするときやらになんか微妙に足りてなかったりしてうまくいかないので、利用を諦めbashに戻るなどした。

# License

[CC BY 4.0](https://creativecommons.org/licenses/by/4.0/deed.ja)

<a href="https://commons.wikimedia.org/wiki/File:CC-BY_icon.svg#/media/File:CC-BY_icon.svg"><img src="https://upload.wikimedia.org/wikipedia/commons/thumb/1/16/CC-BY_icon.svg/1200px-CC-BY_icon.svg.png" alt="CC-BY icon.svg" width="88px"></a>