atuinsh / atuin

✨ Magical shell history
https://atuin.sh
MIT License
20.88k stars 562 forks source link

Powershell Support #84

Open Kixiron opened 3 years ago

Kixiron commented 3 years ago

I absolutely love the project and would love to be able to use it within powershell

gabriel-vanca commented 1 year ago

Any news on PowerShell support?

conradludgate commented 1 year ago

@ellie and I are not against getting some basic powershell support, but neither of us run powershell or have the time right now to get familiar.

We have started to partially and unofficially support windows builds now, so it'll be the powershell integration that needs investigating.

1) how can you hook into the prompt and detect key bindings 2) how can you monitor command start and end events 3) how can you update the prompt line with the search selection

stibinator commented 1 year ago

Might be worth noting that Powershell is not a windows-only shell. I use it on my Linux machines and it's available for OSX as well.

lzybkr commented 1 year ago

I've been playing around with PowerShell support, see my prototype - you can import this file from your profile.

This mostly works for adding and updating the history. It's not perfect, e.g. it will include the time to render the prompt, which can be non-trivial in some cases.

I couldn't find a clean way to use redirection to capture the result from an interactive search, so I resorted to using a temporary file. It feels pretty slow on my VM but it seems to work.

One other thing I think PowerShell needs that doesn't apply to any other currently supported shell. PowerShell's notion of the current directory goes beyond the filesystem. atuin should have an explicit parameter like atuin history --cwd hklm:\ -- ... so PowerShell can specify these non-filesystem paths.

brian6932 commented 1 year ago

@ellie and I are not against getting some basic powershell support, but neither of us run powershell or have the time right now to get familiar.

We have started to partially and unofficially support windows builds now, so it'll be the powershell integration that needs investigating.

1. how can you hook into the prompt and detect key bindings

2. how can you monitor command start and end events

3. how can you update the prompt line with the search selection

https://github.com/kelleyma49/PSFzf

atuin-bot commented 9 months ago

This issue has been mentioned on Atuin Community. There might be relevant details there:

https://forum.atuin.sh/t/terminal-setup/165/2

k4lizen commented 8 months ago

I would also love this feature!

jbayardo commented 7 months ago

In case people are interested, this almost works:

$env:ATUIN_SESSION = (atuin uuid | Out-String).Trim()
$env:ATUIN_HISTORY_ID = $null

Set-PSReadLineKeyHandler -Chord Enter -ScriptBlock {
    $line = $null
    $cursor = $null
    [Microsoft.PowerShell.PSConsoleReadLine]::GetBufferState([ref]$line, [ref]$cursor)

    if (-not $env:ATUIN_HISTORY_ID) {
        $env:ATUIN_HISTORY_ID = (atuin history start -- $line | Out-String).Trim()
        $global:ATUIN_HISTORY_ELAPSED = [System.Diagnostics.Stopwatch]::StartNew()
    }

    [Microsoft.PowerShell.PSConsoleReadLine]::AcceptLine()
}

$existingPromptFunction = Get-Item -Path Function:\prompt
Remove-Item -Path Function:\prompt
function prompt {
    if ($env:ATUIN_HISTORY_ID) {
        $durationNs = $global:ATUIN_HISTORY_ELAPSED.ElapsedTicks * 100
        $exitCode = $LASTEXITCODE
        atuin history end --duration $durationNs --exit $exitCode -- $env:ATUIN_HISTORY_ID | Out-Null

        Remove-Item -Path env:ATUIN_HISTORY_ID -ErrorAction SilentlyContinue
    }

    & $existingPromptFunction.ScriptBlock
}

# TODO: Fix all the bindings below
$InvokeAtuinSearch = {
    $keymapMode = "emacs"

    $line = $null
    $cursor = $null
    [Microsoft.PowerShell.PSConsoleReadLine]::GetBufferState([ref]$line, [ref]$cursor)

    $suggestion = (atuin search --keymap-mode=$keymapMode -i -- $line | Out-String).Trim()

    [Microsoft.PowerShell.PSConsoleReadLine]::RevertLine()

    if ($suggestion.StartsWith("__atuin_accept__:")) {
        $suggestion = $suggestion.Substring(16)
        [Microsoft.PowerShell.PSConsoleReadLine]::Insert($suggestion)
        [Microsoft.PowerShell.PSConsoleReadLine]::AcceptLine()
    }
    else {
        [Microsoft.PowerShell.PSConsoleReadLine]::Insert($suggestion)
    }
}

$InvokeAtuinUpSearch = {
    $bufferContent = [Microsoft.PowerShell.PSConsoleReadLine]::GetBufferContent()
    if (-not $bufferContent.Contains("`n")) {
        & $InvokeAtuinSearch -keymapMode "vim-normal"
    }
    else {
        [Microsoft.PowerShell.PSConsoleReadLine]::HistorySearchBackward()
    }
}

Set-PSReadLineKeyHandler -Chord "Ctrl+r" -ScriptBlock $InvokeAtuinSearch -BriefDescription "AtuinSearch" -Description "Invoke Atuin search for command history"
Set-PSReadLineKeyHandler -Chord "UpArrow" -ScriptBlock $InvokeAtuinUpSearch -BriefDescription "AtuinUpSearch" -Description "Invoke Atuin up search or navigate history"

A fight has to be had with PSReadLine to allow Ctrl + R and UpArrow to work, and deal with Vim vs Emacs mode, but running atuin history list seems to record all commands as expected.

Unfortunately, since PowerShell lacks precmd and postcmd hooks, it's hard to implement this in exactly the same way as other shells do. The recorded timing is a bit off: what I observe is the first couple of commands run in a new PowerShell session seem to get the time spent wrong (sometimes by as much as hundreds of ms), but afterwards the error decreases rapidly to about 10ms or 20ms.

ellie commented 4 months ago

If anyone has been using the above long term, and without major issue, it would be awesome to work towards getting it included

jbayardo commented 4 months ago

The key bindings don't work in the above, launching atuin interactive search by running Ctrl + R scrambles all characters in the screen. The issue has likely something to do with this: https://github.com/PowerShell/PSReadLine/issues/1576 .

PSFzf does manage to successfully make things work, I think the reason is they are spawning a process within PowersShell with appropriate redirections as part of the PSReadLine chord binding, so whomever has the heart to deal with that might find that technique useful (see here: https://github.com/kelleyma49/PSFzf/blob/master/PSFzf.Base.ps1#L406 ).

brian6932 commented 4 months ago

PSFzf does manage to successfully make things work

Not exactly https://github.com/kelleyma49/PSFzf/issues/189 https://github.com/kelleyma49/PSFzf/issues/274

Lockszmith-GH commented 4 months ago

But surly we can use a different chord - does it HAVE to be Ctrl+R ?

gabriel-vanca commented 2 months ago

Would be lovely to get an update on this.