PowerShellコンソールの入力履歴について

`PowerShell`コンソールを触っていると、履歴を取得する`Get-History`コマンドではセッション中の履歴しか取得できないが、`UpArrowキー`、`DownArrowキー`では現在のセッション以前に入力したコマンド履歴が選択できる事に気が付き、これはどういう事？　といった疑問を持つかと思います。

これは`PowerShell`では入力履歴を提供する仕組みが下記の2系統存在しているためです。

- PowerShell組み込みの入力履歴管理（現在のセッション履歴のみ）
- PSReadlineモジュールによる入力履歴管理（セッション関係なし）（Windows PowerShell v5.0から標準提供）

上記の違いがそれぞれの系統であり、また`PSReadline`はWindows PowerShell v5.0以降に標準提供されるため、`Windows PowerShell v5.0`以降では下記のようになっています。

`Get-History`コマンドレットはPowerShell組み込みの入力履歴管理に属しており、こちらは現在のセッション中の入力履歴のみを移動できる。

`UpArrowキー`、`DownArrowキー`で移動できる入力履歴は`PSReadline`で提供される物になり、こちらは現在のセッションだけではなくそれ以前の入力履歴も参照できます。

## PSReadlineについて

`PowerShellコンソール`をカスタマイズする`PowerShell`モジュールとなり、元々はOSSとして提供されていましたが。`Windows PowerShell v5.0`から`PowreSehll`の標準インストールに組み込まれているモジュールとなります。

`PSreadline`は今回話しをする入力履歴だけではなく、キーバンド設定だったり、構文の色分けだったり多種な機能を提供するモジュールになります。

## 今回使用している環境

- PowerSehll 7.3.0-preview.1
- PSReadLine 2.2.0 beta4

## ドキュメント

入力履歴については、ドキュメントの`about_History`に記載されているのてこちらが参考になります。

[PowerShell about_History](https://docs.microsoft.com/ja-jp/powershell/module/microsoft.powershell.core/about/about_history?view=powershell-7.2)

## PowerShell組み込みの入力履歴管理

[組み込みのセッション履歴の使用
](https://docs.microsoft.com/ja-jp/powershell/module/microsoft.powershell.core/about/about_history?view=powershell-7.2#using-the-built-in-session-history)

ドキュメントに記載がある通り、組み込みの入力履歴管理コマンドでは、現在のセッションで使用したコマンドだけが追跡され。セッションが終了すると削除されます。

![組み込みの履歴コマンド一覧](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1670622/5ef98d94-61bc-640c-5845-88832da6b429.png)

- Add-History コマンドの履歴にコマンドを追加する。Get-Hisotryで取得できる、HistoryInfoのオブジェクトでインプットできる
- Clear-History　コマンドの履歴からコマンドを削除する
- Get-History　コマンドの履歴を取得する
- Invoke-History　コマンドの履歴からコマンドを実行する

今現在も上記のコマンドレットは利用できますが、基本的には`PSReadline`の履歴管理を使う形になります。

## PSReadLineの入力履歴管理

[PSReadline history function](https://docs.microsoft.com/ja-jp/powershell/module/psreadline/about/about_psreadline?view=powershell-7.2#history-functions)

ドキュメントに記載があるように、`UpArrowキー`や`DownArrowキー`などのキー操作で以前の入力履歴を選択できる機能を`PSReadline`モジュールでは提供しています。

`PSReadline`ではカスタムキーバインドを設定する機能も提供しており、入力履歴の操作もこれを利用して設定されています。

今現在、`PSReadline`のデフォルトでは、`emacs`モードで下記履歴機能が提供されています。

- <`UpArrowキー`> PreviousHistory
- <`DownArrowキー`> NextHistory
- <`Ctrl+r`> ReverseSearchHistory
- <`Ctrl+s`> ForwardSearchHistory
- <`Alt+F7`> ClearHistory 現在のセッション中のみで利用する履歴をクリアするだけで、historysavepathに格納されている履歴がクリアされるわけではない。
- <`Alt+>`> EndOfHistory 入力履歴の最後の項目に移動

カスタムキーバインドについては、そもそも`PSReadline`ではemacsモードとviモードで違いが出てきたりするので細かいことはドキュメントを確認してください。

## PSReadlineの入力履歴保存場所

[コマンド履歴](https://docs.microsoft.com/ja-jp/powershell/module/psreadline/about/about_psreadline?view=powershell-7.2#command-history)

コマンドの入力履歴がどこで管理されているかについては上記ドキュメントに記載があります。

Windows環境では

- $env:APPDATA\Microsoft\Windows\PowerShell\PSReadLine

Windows以外の環境では以下のいずれかに格納されます。

- $env:XDG_DATA_HOME/powershell/PSReadLine
- $env:HOME/.local/share/powershell/PSReadLine

格納場所を確認する方法としては、`Get-PSReadLineOption`コマンドレットで`PSreadline`の設定を取得でき、設定項目`HistorySavePath`が保存場所のパスになります。

## PSReadlineの入力の履歴保存場所を変更する

デフォルト以外の場所に入力履歴保存場所を変更した場合は、`Set-PSReadLineOption`コマンドレットの`HistorySavePath`オプションを利用して変更することができます。

ただしこの設定は現在のセッションのみ有効となるため、永続的に設定するためには起動プロファイル $profile で取得できるファイルにコマンドを追記して下さい

```pwsh:入力履歴の保存場所を変更
# 現在のセッションのみ有効。永続的に変更する場合は起動プロファイルに追加
Set-PSReadLineOption -HistorySavePath <<保存場所のパス>>
```

### PSReadlineをRemove-Moduleして履歴が利用できなくなる事を確認してみる。

`PSReadline`といわれてピンとこない場合は、機能削除してどう変わるか見るのが早いと思います。

現在のセッションから読み込んでいる`PowerShell`モジュールを削除するコマンドを実行して、`PSReadline`を機能しないようにして履歴管理がどうなるか確認してみます。

なお`Remove-Module`は現在のセッションから削除するだけので、コンソールを開き直せば元に戻ります。

```pwsh:PSReadlineをremove-moudle
Remove-Module PSReadLine

# oh-my-posh を利用している場合はそちらもremove-module
Remove-Module oh-my-posh
```

`Remove-Moudle`をする事で入力履歴が`PowerShell`組み込みだけの利用となり、

`UpArrowキー`、`DownArrowキー`　で提供される入力履歴もセッション中に入力した物だけになる事が確認できると思います。

## 総評

今現在となっては、組み込みで用意されている履歴管理を使う機会はほぼないかとは思いますが。
歴史的経緯からPowerShellでは履歴管理が2系統あるといった事だけは理解しておいた方がいいかと思います。