fishshell 2.6.0 の変更点ピックアップ

## はじめに
先月(2017/6/3)，fish shellのversion 2.6.0がリリースされました！
[リリースノート](https://fishshell.com/release_notes.html)を見ていたら結構変更点があり，fishユーザ待望の**あの機能(後述)**も入ったようなので，独断と偏見でversion 2.6.0での変更点をまとめてみました．

## 変更点ピックアップ
### コマンド置換が端末からの入力を受け付けるようになった
これ！ これをずっと待ってました．
これで`peco`や`fzf`のようなフィルタリングツールの使用がずっと楽になります．

fishにはbashの`^r`に相当する履歴絞込みが標準では付いていないので，`peco`や`fzf`を使ってこれを実現している方も多いと思います．

ネットの情報([oh-my-fish/plugin-peco](https://github.com/oh-my-fish/plugin-peco/blob/master/functions/peco_select_history.fish)とか)を見るとだいたい次のように書くことになっていました．

```sh
history | peco | read -l tmp; commandline $tmp
```

ここで気になるのが一時変数`tmp`です．履歴の取得は`history`，コマンドラインへの文字の挿入は`commandline`なので，次のように書けてよいはずです．

```sh
commandline (history | peco)
```

ところがこれまでのfishではこれができませんでした．具体的な原因は多分[このへん](https://github.com/fish-shell/fish-shell/issues/1362)で議論されています．

しかし，fish 2.6.0からは上記の簡単な(そして自然な)記法が有効です！

### functionsコマンドに--detailsオプションが追加

以下のようにして，関数がロードされた場所を取得できるようになりました．

```sh
functions --details hoge #=> /path/to/hoge.fish
```

これで関数定義を直接エディタで編集したり[^edit]，削除したり[^erase]が簡単にできます．`fundle`や`fresco`を使っている方なら，プラグインの関数は`~/.config/fish/functions`以外の場所に作られるので，関数が自作か他作かも簡単に判別できます．

さらに`--verbose`オプションを組み合わせることにより，より詳細な出力が得られます．

```sh
functions --details --verbose cd
/My/Home/.config/fish/functions/cd.fish
autoloaded 
1
scope-shadowing
Change directory
```

出力の意味は順番に

1. 関数が読み込まれたパス
2. オートロード関数かどうか
3. ファイルの中の，関数定義が開始する行
4. `--scope-no-shadowing`オプションが有効かどうか
5. `function -d`で関数に付けた説明

となります．`--scope-no-shadowing`付きの関数は外側のローカル変数を書き換えられる力を持っているので，チェックできる方法があるのはよいかも[^verbose4]．あと5. の関数の説明の取得は，むしろこれまでできなかったんだっけ？ という感じもします．

[^edit]: `funced`による編集では毎回一時ファイルに関数が書き出されるため，エディタのundo履歴等が使えませんでした．
[^erase]: `functions --erase`では関数の定義は削除できますが，定義の実体である`.fish`ファイルは消せないため，オートロード関数の削除はできませんでした．
[^verbose4]: でもそこまでチェックするか？ というとしない気はする．

### `string`コマンドに新しいサブコマンド & オプションが追加

文字列を繰り返し出力する`string repeat`サブコマンドが追加されました．まぁ`for`ループでできるんですが，ちょっとした区切り線を引くのに`for`ループ書くのもちょっと...と思っていた方には福音のはず．

```
string repeat [--count 繰り返す数] [--max 最大文字数] [--no-newline] 文字列...
```

`--no-newline (-N)`は`echo -n`相当のオプションです．

また，`string match`コマンドに`--entire`オプションが追加．「部分一致で判定し，マッチした文字列全体を出力」となります．要するに

```sh
string match h hoge # マッチしない
string match --entire h hoge #=> hoge

string match '*h*' hoge # つまりこれと等価
```

となります．正規表現と一緒に使った場合は「正規表現にマッチした部分だけでなく，マッチした文字列全体を表示」となります．

```sh
string match --regex h hoge #=> h
string match --regex --entire h hoge #=> hoge

string match --regex '.*h.*' hoge # これと等価
```

さらに，`string replace`に`--filter`オプションが追加．これも等価な表現を見るのが多分早くて，

```
cat hoge.txt | string replace --filter OLD NEW
cat hoge.txt | string match --entire OLD | string replace OLD NEW # これと等価
```

となります．置換を実際に行った行のみの出力となります．

いろいろ便利になっていく反面，等価な書き方がすでにあるものが多いので，fishのシンプルさが失われていくような気もして少し複雑です．

### `read`コマンドに`--silent`オプションが追加

<img width="288" alt="read --local --silent password" src="https://qiita-image-store.s3.amazonaws.com/0/124405/89c0dbe6-efee-0d45-2a6f-1546201e3c91.png">

端末から入力を受け付けますが，文字を画面に表示しなくなります．地味ながら嬉しい．

### おわりに

まだ変更点はあるのですが，紹介はこの辺で終了させて頂きます．詳細は本家[リリースノート](https://fishshell.com/release_notes.html)を御覧ください．fishのウリでもある補完設定も着々と追加・改善されています．
次のversion 2.7.0にも期待です．

### 余談
version 2.6.0の話ではないのですが，いつの間にかfishで`export`が使えるようになってました．といってもコレ，去年の夏(fish 2.2.0)には入っていたようです．これで他シェルからの移行も簡単なので，みんなfish使おう！

### 追記 (2017/7/18)
 string replace `--filter`の使い方を勘違いしていたのを修正