-
-
Notifications
You must be signed in to change notification settings - Fork 584
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This adds PowerShell support by invoking the following expression: atuin init powershell | Out-String | Invoke-Expression Co-authored-by: Jason Shirk <[email protected]>
- Loading branch information
1 parent
05aec6f
commit 567ee37
Showing
5 changed files
with
214 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
use atuin_dotfiles::store::{var::VarStore, AliasStore}; | ||
use eyre::Result; | ||
|
||
pub fn init_static(disable_up_arrow: bool, disable_ctrl_r: bool) { | ||
let base = include_str!("../../../shell/atuin.ps1"); | ||
|
||
let (bind_ctrl_r, bind_up_arrow) = if std::env::var("ATUIN_NOBIND").is_ok() { | ||
(false, false) | ||
} else { | ||
(!disable_ctrl_r, !disable_up_arrow) | ||
}; | ||
|
||
fn bool(value: bool) -> &'static str { | ||
if value { | ||
"$true" | ||
} else { | ||
"$false" | ||
} | ||
} | ||
|
||
println!("{base}"); | ||
println!( | ||
"Enable-AtuinSearchKeys -CtrlR {} -UpArrow {}", | ||
bool(bind_ctrl_r), | ||
bool(bind_up_arrow) | ||
); | ||
} | ||
|
||
pub async fn init( | ||
_aliases: AliasStore, | ||
_vars: VarStore, | ||
disable_up_arrow: bool, | ||
disable_ctrl_r: bool, | ||
) -> Result<()> { | ||
init_static(disable_up_arrow, disable_ctrl_r); | ||
|
||
// dotfiles are not supported yet | ||
|
||
Ok(()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,144 @@ | ||
# Atuin PowerShell module | ||
# | ||
# Usage: atuin init powershell | Out-String | Invoke-Expression | ||
|
||
if (Get-Module Atuin -ErrorAction Ignore) { | ||
Write-Warning "The Atuin module is already loaded." | ||
return | ||
} | ||
|
||
if (!(Get-Command atuin -ErrorAction Ignore)) { | ||
Write-Error "The 'atuin' executable needs to be available in the PATH." | ||
return | ||
} | ||
|
||
if (!(Get-Module PSReadLine -ErrorAction Ignore)) { | ||
Write-Error "Atuin requires the PSReadLine module to be installed." | ||
return | ||
} | ||
|
||
New-Module -Name Atuin -ScriptBlock { | ||
$env:ATUIN_SESSION = atuin uuid | ||
|
||
$script:atuinHistoryId = $null | ||
$script:previousPSConsoleHostReadLine = $Function:PSConsoleHostReadLine | ||
|
||
# The ReadLine overloads changed with breaking changes over time, make sure the one we expect is available. | ||
$script:hasExpectedReadLineOverload = ([Microsoft.PowerShell.PSConsoleReadLine]::ReadLine).OverloadDefinitions.Contains("static string ReadLine(runspace runspace, System.Management.Automation.EngineIntrinsics engineIntrinsics, System.Threading.CancellationToken cancellationToken, System.Nullable[bool] lastRunStatus)") | ||
|
||
function PSConsoleHostReadLine { | ||
# This needs to be done as the first thing because any script run will flush $?. | ||
$lastRunStatus = $? | ||
|
||
# Exit statuses are maintained separately for native and PowerShell commands, this needs to be taken into account. | ||
$exitCode = if ($lastRunStatus) { 0 } elseif ($global:LASTEXITCODE) { $global:LASTEXITCODE } else { 1 } | ||
|
||
if ($script:atuinHistoryId) { | ||
# The duration is not recorded in old PowerShell versions, let Atuin handle it. | ||
$duration = (Get-History -Count 1).Duration.Ticks * 100 | ||
$durationArg = if ($duration) { "--duration=$duration" } else { "" } | ||
|
||
atuin history end --exit=$exitCode $durationArg -- $script:atuinHistoryId | Out-Null | ||
|
||
$global:LASTEXITCODE = $exitCode | ||
$script:atuinHistoryId = $null | ||
} | ||
|
||
# PSConsoleHostReadLine implementation from PSReadLine, adjusted to support old versions. | ||
Microsoft.PowerShell.Core\Set-StrictMode -Off | ||
|
||
$line = if ($script:hasExpectedReadLineOverload) { | ||
# When the overload we expect is available, we can pass $lastRunStatus to it. | ||
[Microsoft.PowerShell.PSConsoleReadLine]::ReadLine($Host.Runspace, $ExecutionContext, [System.Threading.CancellationToken]::None, $lastRunStatus) | ||
} else { | ||
# Either PSReadLine is older than v2.2.0-beta3, or maybe newer than we expect, so use the function from PSReadLine as-is. | ||
& $script:previousPSConsoleHostReadLine | ||
} | ||
|
||
$script:atuinHistoryId = atuin history start -- $line | ||
|
||
return $line | ||
} | ||
|
||
function RunSearch { | ||
param([string]$ExtraArgs = "") | ||
|
||
$line = $null | ||
$cursor = $null | ||
[Microsoft.PowerShell.PSConsoleReadLine]::GetBufferState([ref]$line, [ref]$cursor) | ||
|
||
# Atuin is started through Start-Process to avoid interfering with the current shell, | ||
# and to capture its output which is provided in stderr (redirected to a temporary file). | ||
|
||
$suggestion = "" | ||
$resultFile = New-TemporaryFile | ||
try { | ||
$env:ATUIN_SHELL_POWERSHELL = "true" | ||
$argString = "search -i $ExtraArgs -- $line" | ||
Start-Process -Wait -NoNewWindow -RedirectStandardError $resultFile.FullName -FilePath atuin -ArgumentList $argString | ||
$suggestion = (Get-Content -Raw $resultFile | Out-String).Trim() | ||
} | ||
finally { | ||
$env:ATUIN_SHELL_POWERSHELL = $null | ||
Remove-Item $resultFile | ||
} | ||
|
||
$previousOutputEncoding = [System.Console]::OutputEncoding | ||
try { | ||
[System.Console]::OutputEncoding = [System.Text.Encoding]::UTF8 | ||
|
||
# PSReadLine maintains its own cursor position, which will no longer be valid if Atuin scrolls the display in inline mode. | ||
# Fortunately, InvokePrompt can receive a new Y position and reset the internal state. | ||
[Microsoft.PowerShell.PSConsoleReadLine]::InvokePrompt($null, $Host.UI.RawUI.CursorPosition.Y) | ||
} | ||
finally { | ||
[System.Console]::OutputEncoding = $previousOutputEncoding | ||
} | ||
|
||
if ($suggestion -eq "") { | ||
# The previous input was already rendered by InvokePrompt | ||
return | ||
} | ||
|
||
$acceptPrefix = "__atuin_accept__:" | ||
|
||
if ( $suggestion.StartsWith($acceptPrefix)) { | ||
[Microsoft.PowerShell.PSConsoleReadLine]::RevertLine() | ||
[Microsoft.PowerShell.PSConsoleReadLine]::Insert($suggestion.Substring($acceptPrefix.Length)) | ||
[Microsoft.PowerShell.PSConsoleReadLine]::AcceptLine() | ||
} else { | ||
[Microsoft.PowerShell.PSConsoleReadLine]::RevertLine() | ||
[Microsoft.PowerShell.PSConsoleReadLine]::Insert($suggestion) | ||
} | ||
} | ||
|
||
function Enable-AtuinSearchKeys { | ||
param([bool]$CtrlR = $true, [bool]$UpArrow = $true) | ||
|
||
if ($CtrlR) { | ||
Set-PSReadLineKeyHandler -Chord "Ctrl+r" -BriefDescription "Runs Atuin search" -ScriptBlock { | ||
RunSearch | ||
} | ||
} | ||
|
||
if ($UpArrow) { | ||
Set-PSReadLineKeyHandler -Chord "UpArrow" -BriefDescription "Runs Atuin search" -ScriptBlock { | ||
$line = $null | ||
[Microsoft.PowerShell.PSConsoleReadLine]::GetBufferState([ref]$line, [ref]$null) | ||
|
||
if (!$line.Contains("`n")) { | ||
RunSearch -ExtraArgs "--shell-up-key-binding" | ||
} else { | ||
[Microsoft.PowerShell.PSConsoleReadLine]::PreviousLine() | ||
} | ||
} | ||
} | ||
} | ||
|
||
$ExecutionContext.SessionState.Module.OnRemove += { | ||
$env:ATUIN_SESSION = $null | ||
$Function:PSConsoleHostReadLine = $script:previousPSConsoleHostReadLine | ||
} | ||
|
||
Export-ModuleMember -Function @("Enable-AtuinSearchKeys", "PSConsoleHostReadLine") | ||
} | Import-Module -Global |