`Ctrl+R`を押したら、最近実行した順にコマンド履歴が列挙され、それを[[インクリメンタルサーチ]]で絞り込み、決定したらプロンプトに挿入したい。 ## 解決策 [[PSFzf]]を使う。インストールが必要。 ```console Install-Module PSFzf ``` [[Microsoft.PowerShell_profile.ps1]]に設定を追加。今回の方法では[[tac]]と[[AWK]]が必要。 ```powershell Set-PSReadLineKeyHandler -Chord Ctrl+r -ScriptBlock { $command = Get-Content (Get-PSReadlineOption).HistorySavePath | tac | awk '!a[$0]++' | Invoke-Fzf -NoSort -Exact [Microsoft.PowerShell.PSConsoleReadLine]::InvokePrompt() if (!$command) { return } [Microsoft.PowerShell.PSConsoleReadLine]::Insert($command) } ``` - `Get-Content (Get-PSReadlineOption).HistorySavepath` でコマンド履歴の取得 (昇順) - `tac`で順番を逆にする - `awk '!a[$0]++'` で重複行の削除 - `Invoke-Fzf` で[[fzf]]の実行 - `-NoSort` で結果をソートしない - ソートするとマッチ順になってしまい、最近のコマンドが見つからないため - `-Exact` で[[ファジー検索]]を無効化 - [[ファジー検索]]するとイメージしてたコマンドが上に来ないため - 🪦`Invoke-Fzf`には`-Tac`というオプションもあるが、重複削除後に表示順を入れ替えると、時間帯の古い方が残ってしまい、==以前に実行されたコマンドを再実行しても、最新の履歴として表示されない問題が発生する== - `[Microsoft.PowerShell.PSConsoleReadLine]::InvokePrompt()` でプロンプトの再表示 - 🪦==これを入れないと、プロンプトが表示されなくなる== - `if (!$command)` でコマンドを選択せず終了した場合になにもしない処理を追加 - 🪦==これを入れないと、エラーが表示される== - `[Microsoft.PowerShell.PSConsoleReadLine]::Insert($command)` でプロンプトに選択したコマンドを挿入 ## 参考 - [How to set up your PowerShell for a better developer experience \| Medium](https://medium.com/@dorlugasigal/how-to-set-up-your-powershell-f004c90bbafb) - [Windows PowerShell Ctrl\+R history with fzf](https://gist.github.com/nv-h/081684cee2505cd336e26c2660fc7541) ## 🪦うまくいかなかった方法 ### [[fzf]]をそのまま使う [[Microsoft.PowerShell_profile.ps1]] ```powershell Set-PSReadLineKeyHandler -Chord Ctrl+r -ScriptBlock { $command = Get-Content (Get-PSReadlineOption).HistorySavePath | awk '!a[$0]++' | fzf --no-sort --exact --tac [Microsoft.PowerShell.PSConsoleReadLine]::Insert($command) } ``` 以下のエラーが表示されてしまう。 ``` An exception occurred in custom key handler, see $error for more information: Argument types do not match ``` ### 履歴への重複登録を禁止する [[HistoryNoDuplicates]]を有効にした場合。 ```powershell (Get-PSReadLineOption).HistoryNoDuplicates = $True ``` この設定は連続する重複したコマンドがユニークになるだけであり、連続していない場合は登録されてしまうため利用できない。