🐚

PowerShellでfzfを使用した入力補完を試す

に公開

先人が試されていた方法がなかなか欲しいものとは違ったのですが、
claudeで調べましたら自分の欲しいものと近いものができそうでしたので、その結果をここに書いておきます。

まず、fzfをインストールします。

winget install fzf

次のコマンドなどでプロファイルを編集します。

code $PROFILE
# notepad $PROFILEでも可能

内容を次のようにします。


Set-PSReadLineKeyHandler -Key "Ctrl+Spacebar" -ScriptBlock {
    try {
        # 現在の入力を取得
        $line = $null
        $cursor = $null
        [Microsoft.PowerShell.PSConsoleReadLine]::GetBufferState([ref]$line, [ref]$cursor)
        
        # 補完候補を取得
        $completions = TabExpansion2 $line $cursor
        
        if ($completions.CompletionMatches.Count -eq 0) {
            Write-Host "`nNo completions found" -ForegroundColor Yellow
            [Microsoft.PowerShell.PSConsoleReadLine]::InvokePrompt()
            return
        }
        
        # fzf用のリストを作成
        $fzfItems = $completions.CompletionMatches | Select-Object -ExpandProperty CompletionText

        # fzfで選択
        $selected = ($fzfItems | fzf --height 10)

        if ($selected) {
            # 補完を適用
            $replacementIndex = $completions.ReplacementIndex
            $replacementLength = $completions.ReplacementLength
            
            # 現在の行を更新
            $newLine = $line.Substring(0, $replacementIndex) + $selected + $line.Substring($replacementIndex + $replacementLength)
            [Microsoft.PowerShell.PSConsoleReadLine]::RevertLine()
            [Microsoft.PowerShell.PSConsoleReadLine]::Insert($newLine)
        }
    }
    catch {
        Write-Host "Error in completion: $($_.Exception.Message)" -ForegroundColor Red
        [Microsoft.PowerShell.PSConsoleReadLine]::InvokePrompt()
    }
}

適用は

. $PROFILE

とするか、シェルを再起動してください。

行数設定がうまくいかないで全画面になってしまうのはよくわかりませんが、
コマンド入力時にctrl+spaceで従来の補完内容と同じものが選択できるかもしれません。
(Tabとctrl+spaceで内容が違ったような気がしますが…)

挙動としては、選択すると行が更新されてその部分が入力されると思います。
補完状況によってはうまくいかない可能性もあります。

Discussion