PowerShellモジュールのPSFzfとZLocationをつかってみる

`CUI`操作を便利にするコマンドは色々と有名なものがありますが、そのなかの一つとして`fzf`コマンドがあります。

 `fzf`コマンドはコマンドラインであいまい検索を提供するコマンドで。
入力履歴選択だったり、入力補完選択だったりをフィルタしたりします。

本記事では`PowerShell`から`fzf`コマンドを利用しやすくラップした`PSFzf`モジュールについて説明します。
また`PSFzf`は`PSReadLine`と`ZLocation`モジュールと連携することができるので、ここらへんについても少しだけ。

- `PSReadLine`はPowerShellコンソール上で入力補完だったり、色付けだったりの機能を提供するモジュール。
- `ZLocation`モジュールは`Jump-Location`モジュールの後継で、ディレクトリ移動をサポートするモジュールになります。

## Webサイト

[fzf](https://github.com/junegunn/fzf)
[PSFzf](https://github.com/kelleyma49/PSFzf)
[ZLocation](https://github.com/vors/ZLocation)

## インストール

[PSFzf Prerequisites](https://github.com/kelleyma49/PSFzf#prerequisites)

`PSFzf`のPrerequisitesを読むと、`fzf`を事前にインストールが必要と記載があるので、`fzf`コマンドをインストールします。

### fzfコマンドのインストール

[fzf windows](https://github.com/junegunn/fzf#windows)

PowerShellのパッケージマネージャである`Chocolatey`もしくは、`Scoop`で`fzf`コマンドをインストールできるようです。（2021年12月現在はwingetはない模様）

どちらも利用していない場合は[ダウロードページページ](https://github.com/marketplace)からバイナリをダウンロードして環境変数PATHを通して下さい。

### PSFzfとZLocationモジュールのインストール

`PSFzf`および`ZLocation`についてはどちらもPowerShell Galleryで公開されているため下記のコマンドレットでインストールできます。

```PowerShell:モジュールのインストール
Install-Module -Name PSFzf -scope currentUser
Install-Module -Name ZLocation -scope currentUser
```

インストール後にモジュールを読み込んで、Aliasを有効にするために下記のコマンドを実行します。

```PowerShell:起動プロファイル設定
# PSFzfの読み込みとAlias有効化
Import-Module PSFzf
Enable-PsFzfAliases
# ZLocationの読み込み
Import-Module ZLocation
```

ただし、これだけでは実行したプロセスでモジュールが読み込まれるだけなので、起動時に毎回モジュールを読み込むようにするには、起動プロファイルに下記を追加して下さい。
(起動プロファイルの場所は自動変数`$profile`で確認できます。）

## Invoke-FuzzySetLocation(alias fd)

`Invoke-FuzzySetLocation(aliad fd)`コマンドで、カレントディレクトリ以下のディレクトリの一覧が表示されるので、移動したいディレクトリを選択すると移動することができます。

下記のような構造を持った`c:\temp\fzf`がカレントディレクトリの際に`Invoke-FuzzySetLocation`を実行してみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1670622/44597e8d-bb27-40a4-8462-1e2dbb7b7989.png)

`Invoke-FuzzySetLocation(alias fd)`を実行するとディレクトリの一覧が出てくるので、移動したいディレクトリを選択してENTERを入力すると選択したディレクトリに移動できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1670622/00025538-d2f2-b864-d352-345e66778130.png)

なお、一覧が表示されている画面で検索値を入力すると、一覧がフィルタされます。下記画像は`foobar`でフィルタした場合。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1670622/52a2b754-c663-bc9a-d94e-de2582b07753.png)

## Invoke-FuzzyEdit(alias fe)

環境変数`EDITOR`に設定されたエディタで、ファイルを開きます。

`$env:EDITOR='notepad'`と設定するとnotepadで開きます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1670622/39ab7f3f-e4f0-57dd-f777-3937f4976596.png)

上記画像のように、コマンドを実行すると一覧が出力されるので、editしたいファイルを選択してENTERを実行すると指定されたEDITORでファイルが開きます。　画像の例では`c:\temp\fzf\hello world\helloworld.txt`を開きます。

## Invoke-FuzzyZLocation(alias fz)

コマンドを実行すると、`ZLocation`の入力履歴一覧を表示して入力履歴からディレクトリを移動することができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1670622/493abaff-b6b9-efde-445c-753813eacff3.png)

`ZLocation`は`cd`したディレクトリを記憶しており、ディレクトリに移動した回数で重み付けをして、よく移動するディレクトリを選択しやすくします。

### ZLocationについて

`ZLocation`モジュールの`Invoke-ZLocation`コマンドレットを実行すると一覧が表示されます。
aliasとして`z`が登録されている。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1670622/dc07cb81-b2eb-9b21-1c6c-819fbd23b6da.png)

`z`コマンドを実行すると　`Weight`　と　`Path`　が表示されます。

たとえばこの状態で`z fz`と実行すると、部分一致してWeightが一番大きい`c:\temp\fzf`に移動します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1670622/32b01635-3710-c631-aa3a-696da98db37f.png)

## Invoke-FuzzyHistory(alias fh)

`PSReadline`で提供されている実行履歴を`fzf`でフィルタできます

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1670622/e2ffe09e-6a10-4578-69a1-c32e1c7cad70.png)

`^cd c:\temp\fzf`でフィルタした場合。

なお`PSReadline`の機能としても、`CTRL-R`を入力して下記画像のように過去実行したコマンド検索を提供しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1670622/8ab77251-9ddd-3835-5d24-c0ac458f944d.png)

`PSReadLine`でも実行履歴検索もを提供していますが、`CTRL-R`を`fzf`を利用したフィルタに変更する事もできます。

下記を実行すれば`CTRL-R`の動作を`fzf`を利用した実行履歴検索に上書きする事ができます。

```PowerShell:コマンド履歴検索をfzfを利用
# replace 'Ctrl+t' and 'Ctrl+r' with your preferred bindings:
Set-PsFzfOption -PSReadlineChordProvider 'Ctrl+t' -PSReadlineChordReverseHistory 'Ctrl+r'
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1670622/02e04176-b886-acc6-0b10-d49a8fe9f9f9.png)

永続的に`CTRL-R`の動作を上書きした倍は、起動プロファイルに追加して下さい。

## Tab Expansion

`PSFzf`では一部コマンドのタブ補完を置き換えることができます。
下記でタブ拡張を有効化すると。

```PowerShell:Tab Expansionを有効化
Set-PSReadLineKeyHandler -Key Tab -ScriptBlock { Invoke-FzfTabCompletion }
```

- git
- Get-Service,Start-Service,Stop-Service
- Get-Process,Start-Process

のタブ補完を置き換えます。

下記画像は`Get-Service`の入力補完を`PSFzf`に切り替えた場合。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1670622/f1edef3b-223f-10df-a310-22f1d6aa9239.png)

get-serviceスペースと入力した後にtabキーを押して、^sshでフィルタした場合。

## 総評

`Invoke-FuzzySetLocation(alias fd)`と`Invoke-FuzzyZLocation(alias fz)`が便利そうと感じたため、本ツールを導入してみました。

色々と使い方があるモジュールとなっていますが、一つでも便利そうと感じたら一度使ってみるのもありかもしれません。