Fishの魅力のひとつに「ブラウザからカラーテーマが変更できる」というものがあります。
私も使い始めた頃はこの恩恵に預かっていたものの、次第にこんな悩みが出てきました。
- Vimのターミナルで正常な色が出てこない
- コマンドラインと出力の色が一致しない
- 別環境での再現が面倒だし、dotfilesで管理もできない
- そもそもブラウザが開けない環境では設定すらできない
これらが結構致命的だったため過去にこんなプラグインを作ったものの、いろいろあって以下の方法にすることにしました。
要約
-
fish_config
での色変更 = ただの変数定義 - base16-shellを使おう
- Fish バージョン 3.1.2 での話
入力の色設定
fish_config
コマンドをPythonの存在しない環境下で実行すると以下の表示が出ます。
Cannot launch the web configuration tool:
fish_config requires Python.
Installing python2 or python3 will fix this, and also enable completions to be
automatically generated from man pages.To change your prompt, create a fish_prompt function.
There are examples in $__fish_data_dir/tools/web_config/sample_prompts.You can tweak your colors by setting the $fish_color_* variables.
つまりfish_color_
で始まる変数を設定することでブラウザレスに色設定ができるというわけですね。
設定項目
まずは対象となる変数名を確認しておきましょう。公式に書いてありました。
変数名 (コマンドライン用) | 対象 | 備考 |
---|---|---|
fish_color_normal | デフォルト1 | |
fish_color_command | コマンド | |
fish_color_quote | クォートを含む文字列全体 | |
fish_color_redirection | リダイレクト >/dev/null など |
|
fish_color_error | エラーになる箇所 | |
fish_color_end | コマンド末端につけるもの - コマンド終端 ; - バックグラウンド実行 & など |
|
fish_color_param | コマンドの引数 | |
fish_color_comment | コメント | |
fish_color_match | カーソル位置に対応する括弧 | |
fish_color_selection | viモード時visualでの選択箇所 | -bもしくは-rによる背景色変更のみ可能 |
fish_color_search_match | 履歴検索時の一致箇所 Fishでのデフォルト履歴検索は矢印キー上下 |
-bもしくは-rによる背景色変更のみ可能 |
fish_color_operator | Fish内で使用する特殊記号 - $HOME ~ - ワイルドカード * など |
|
fish_color_escape | エスケープ文字 \n \x70 など |
|
fish_color_autosuggestion | コマンドライン右側に出てくるコマンドや引数の入力候補 | |
fish_color_cwd | カレントワーキングディレクトリ | デフォルトのプロンプトでのみ使用 |
fish_color_user | ユーザー名 | デフォルトのプロンプトでのみ使用 |
fish_color_host | ホスト名 | デフォルトのプロンプトでのみ使用 |
fish_color_host_remote | リモートホスト名 | デフォルトのプロンプトでのみ使用 |
fish_color_cancel | killシグナル ^C
|
変数名 (ページャー2用) | 対象 | 備考 |
---|---|---|
fish_pager_color_progress | ページャー下部にある行数表示部分 | |
fish_pager_color_background | ページャーの背景 | -bもしくは-rによる背景色変更のみ可能 |
fish_pager_color_prefix | 一致部分 | |
fish_pager_color_completion | 補完部分 | |
fish_pager_color_description | 説明文 | |
fish_pager_color_secondary_X | 非選択箇所の色を上書き。 以下の要素がXに入る。 - background - prefix - completion - description |
未指定の場合はそれぞれの fish_pager_color_X を継承する |
fish_pager_color_selected_X | 選択箇所の色を上書き。 以下の要素がXに入る。 - background - prefix - completion - description |
未指定の場合はそれぞれの fish_pager_color_X を継承する |
設定方法
つぎに設定方法ですね。ソースコードを読むと以下のことがわかります。
- 色設定の方法は2通り
- RGB形式による指定
- 色名による指定
- その他
set_color
のオプションも一部使用可能-
-b
,--background
背景色の指定。set_colorと違って = でつなげる必要あり 。
ただしこのオプションが反映されてない不具合がいくつか確認されているので気休め程度に。 -
-d
,--dim
色を暗くする。 -
-i
,--italics
斜体にする。 -
-o
,--bold
太字にする。 -
-r
,--reverse
文字色を背景色にして抜き文字で表示する。
-
色設定について、前者は以下の形式ができるとのこと。
// We support the following style of rgb formats (case insensitive):
// #FA3
// #F3A035
// FA3
// F3A035
対して後者はこんな感じ。接頭辞のbr
はbrightを意味するものと思われます。
色名 | ANSIカラー インデックス |
---|---|
black | 0 |
red | 1 |
green | 2 |
yellow brown |
3 |
blue | 4 |
magenta purple |
5 |
cyan | 6 |
white grey |
7 |
brblack brgrey |
8 |
brred | 9 |
brgreen | 10 |
bryellow brbrown |
11 |
brblue | 12 |
brmagenta brpurple |
13 |
brcyan | 14 |
brwhite | 15 |
問題はどちらを採用するかですが、私は後者の色名指定にしました。
GNOME-terminalやiTerm2しか使わない理想的環境下であれば前者でもいいのですが、それ以外の状況下では常に指定した色を確実に出力してくれる保証もなければ後述する理由で細かい色指定をする必要がないこともあり、いかなる環境下でも最低限「だいたいの色ルール」を維持しておきたいということでこうなりました。
できたもの
というわけで私のconfig.fish
には以下の記述が入っています。
br
だらけなのは視認性向上のため。
# 色配置は次のコマンドの出力に基づいています
# fish-vimcolor onedark
# commandline
set fish_color_normal brwhite
set fish_color_autosuggestion brblack
set fish_color_cancel brcyan
set fish_color_command brpurple
set fish_color_comment brblack
set fish_color_cwd brred
set fish_color_end brwhite
set fish_color_error brred
set fish_color_escape brcyan
set fish_color_host brgreen
set fish_color_host_remote bryellow
set fish_color_match brcyan --underline
set fish_color_operator brpurple
set fish_color_param brred
set fish_color_quote brgreen
set fish_color_redirection brcyan
set fish_color_search_match --background=brblack
set fish_color_selection --background=brblack
set fish_color_user brblue
# pager
set fish_pager_color_progress brblack --italics
set fish_pager_color_secondary_background # null
set fish_pager_color_secondary_completion brblack
set fish_pager_color_secondary_description brblack
set fish_pager_color_secondary_prefix brblack
set fish_pager_color_selected_background --background=brblack
set fish_pager_color_selected_completion bryellow
set fish_pager_color_selected_description bryellow
set fish_pager_color_selected_prefix bryellow
出力の色設定
つづいて出力の色設定です。 ls -al --color=always
などの色をコマンドで変えられます。
本来はターミナルの設定画面を開くなりしないと変えられないアウトプットカラーですが、コマンドラインから変更する方法もないわけではないためどの環境でも常に同じ色を瞬時に出力できるのです。
加えて出力のカラーパレットを上書きすることは前述の色名で指定したコマンドラインの色も連動的に変えられることも意味しています。これによりブラウザからの設定では絶対に実現し得ない100%のカラースキーム統一が実現できるのです。
出力の色はどうやって変えるのか
ここでは以前紹介したことのあるbase16-shellを使ってみます。
私としてはこんな理由があって使っています。
- Fishにも対応している
- プリセットが豊富
- プリセットからの書き換えも楽
- 10ミリ秒弱という実行コストの低さ
- 1000超のスター数とIssuesの活発さによる安心感
- そもそもbase16というプロジェクトが好き
以前はまだFishに対応もしていなかったり理解が足りていなかったこともあり雑なプラグインを作ってしまいましたが、久々に本家を見てみたらかなり進化していました。お気に入りのOneDarkもあって使わない手はないな、と。
使い方
公式の説明をまとめてconfig.fish
に書くならこんな感じです。
# base16-onedarkを設定したい
if status --is-interactive
set -l BASH16_DIR ~/.config/base16-shell
if test ! -d $BASH16_DIR
git clone https://github.com/chriskempson/base16-shell.git $BASE16_DIR
end
source $BASE16_DIR/profile_helper.fish
base16-onedark
end
しかしこのままだと問題がいくつか。
まず起動がほんのり遅くなります。time
コマンドで調べると私の環境では100 〜 200ミリ秒ほどかかっていました。anyenvほどじゃないけどやや重めといったところか。
調べてみるとprofile_helper.fish
というもの、基本的にはテーマの数だけforで回してshスクリプトを呼び出すFish関数を作成するだけのものだったので、使いたいテーマが決まっていればそのshスクリプトを実行するだけで済むということがわかりました。
続いてわかったのが特定のターミナル環境だと上手くいかないということ。たとえばVim/NeovimのターミナルなどはFish側では何をやっても色はつかない……なので環境変数にVIM
があるときはbase16-shellの実行を回避してVim側で色設定3する必要があります。
こんな感じでうまくいかない場面はけっこうあるので、設定中にbegin; ...; end
を作っておいてパスすればshを実行、とするといいでしょう。
というわけで上記を踏まえて書き換えたのが以下の通り。
# base16-onedarkを設定したい
if status --is-interactive
set -l BASH16_DIR ~/.config/base16-shell
if type -q git; and test ! -d $BASH16_DIR
git clone https://github.com/chriskempson/base16-shell.git $BASE16_DIR
end
begin
test -d $BASH16_DIR
and not set -qx VIM # Vim/Neovim
and not set -qx VSCODE # VSCode with terminal.integrated.env.linux
end
if test $status -eq 0
# POSIX準拠ではないらしいのでBashを強制
bash $BASE16_DIR/scripts/base16-onedark.sh
end
end
profile_helper
なしでコマンドひとつでカラースキームを変えたい場合はこんなものを付け加えてみてはいかがでしょうか。
# base16_theme -t monokai でテーマ変更が可能
function base16_theme -V BASE16_DIR -d "set base16 theme"
argparse -n=base16_theme 't/transparent' -- $argv; or return
test -z "$argv"; and return
set -l theme $argv[1]
set -lq _flag_transparent
and set -x BASE16_SHELL_SET_BACKGROUND false # clear
or set -x BASE16_SHELL_SET_BACKGROUND true # non-clear
sh $BASE16_DIR/scripts/base16-$theme.sh
end
function pick_themes -V BASE16_DIR -d "list themes to complete base16_theme argument"
find $BASE16_DIR/scripts/*.sh -type f -printf '%f\n' \
| string replace -ar '^base16-(.*)\.sh$' '$1' \
| string join ' '
end
complete -c base16_theme -s t -l transparent -d "make transparent background"
complete -c base16_theme -xa (pick_themes)
functions -e pick_themes
カスタマイズ
以前紹介した通りこのshスクリプトはRGB形式で宣言した色コードを加工しprintfすることでターミナルのカラーパレットを上書きする手法を採っています。
printfによる上書きの原理こそややこしいですが、シェルスクリプトとしてはとても簡単なものになっているのでカスタマイズもそう難しくないと思います。
まとめ
以前書いた色コードの記事がほぼすべて無駄になり、おかげで様々なしがらみからも解放され、bcコマンドの勉強もできました。
皆様もぜひFishを使いましょう。
-
これが適用されるところは見たことがないが、念の為設定しておくといいはず。 ↩
-
Tabを2回押すと出てくる補完候補を一覧してくれるやつのこと。 ↩
-
それぞれ Vimのターミナル色設定とNeovimのターミナル色設定。 ↩