-
Notifications
You must be signed in to change notification settings - Fork 178
/
mcfly.ps1
117 lines (99 loc) · 4.13 KB
/
mcfly.ps1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
#!/usr/bin/env pwsh
$null = New-Module mcfly {
# We need PSReadLine for a number of capabilities
if ($null -eq (Get-Module -Name PSReadLine)) {
Write-Host "Installing PSReadLine as McFly dependency"
Install-Module PSReadLine
}
# Get history file and make a dummy file for psreadline (hopefully after it has loaded the real history file to its in memory history)
$env:HISTFILE = $null -eq $env:HISTFILE -or "" -eq $env:HISTFILE ? (Get-PSReadLineOption).HistorySavePath : $env:HISTFILE;
$psreadline_dummy = New-TemporaryFile
# Append history to dummy file for compatibility
Get-Content -Path $Env:HISTFILE | Out-File -FilePath $psreadline_dummy -Force
Set-PSReadLineOption -HistorySavePath $psreadline_dummy.FullName
$fileExists = Test-Path -path $env:HISTFILE
if (-not $fileExists) {
Write-Host "McFly: ${env:HISTFILE} does not exist or is not readable. Please fix this or set HISTFILE to something else before using McFly.";
return 1;
}
# MCFLY_SESSION_ID is used by McFly internally to keep track of the commands from a particular terminal session.
$MCFLY_SESSION_ID = new-guid
$env:MCFLY_SESSION_ID = $MCFLY_SESSION_ID
$env:MCFLY_HISTORY = New-TemporaryFile
Get-Content $env:HISTFILE | Select-Object -Last 100 | Set-Content $env:MCFLY_HISTORY
<#
.SYNOPSIS
Cmdlet to run McFly
.PARAMETER CommandToComplete
The command to complete
.EXAMPLE
Invoke-McFly -CommandToComplete "cargo bu"
#>
function Invoke-McFly {
Param([string]$CommandToComplete)
$lastExitTmp = $LASTEXITCODE
$tempFile = New-TemporaryFile
Start-Process -FilePath '::MCFLY::' -ArgumentList "search", "$CommandToComplete", -o, "$tempFile" -NoNewWindow -Wait
foreach($line in Get-Content $tempFile) {
$key, $value = $line -split ' ', 2
if ("mode" -eq $key) {
$mode = $value
}
if ("commandline" -eq $key) {
$commandline = $value
}
}
if(-not ($null -eq $commandline)) {
[Microsoft.PowerShell.PSConsoleReadLine]::DeleteLine()
[Microsoft.PowerShell.PSConsoleReadline]::Insert($commandline)
if("run" -eq $mode) {
[Microsoft.PowerShell.PSConsoleReadline]::AcceptLine()
}
}
Remove-Item $tempFile
$LASTEXITCODE = $lastExitTmp
}
<#
.SYNOPSIS
Add a command to McFly's history.
.PARAMETER Command
The string of the command to add to McFly's history
.PARAMETER ExitCode
The exit code of the command to add
.EXAMPLE
Add-CommandToMcFly -Command "cargo build"
#>
function Add-CommandToMcFly {
Param (
[string] $Command,
[int] $ExitCode
)
$ExitCode = $ExitCode ?? 0;
$Command | Out-File -FilePath $env:MCFLY_HISTORY -Append
Start-Process -FilePath '::MCFLY::' -ArgumentList add, --exit, $ExitCode, --append-to-histfile, $env:HISTFILE -NoNewWindow | Write-Host
}
# We need to make sure we call out AddToHistoryHandler right after each command is called
Set-PSReadLineOption -HistorySaveStyle SaveIncrementally
Set-PSReadLineOption -PredictionSource HistoryAndPlugin
Set-PSReadLineOption -AddToHistoryHandler {
Param([string]$Command)
$lastExitTmp = $LASTEXITCODE
$Command = $Command.Trim();
# PSReadLine executes this before the command even runs, so we don't know its exit code - assume 0
Add-CommandToMcFly -Command $Command -ExitCode 0
$LASTEXITCODE = $lastExitTmp
# Tell PSReadLine to save the command to their in-memory history (and also the dummy file)
return $true
}
Set-PSReadLineKeyHandler -Chord "Ctrl+r" -ScriptBlock {
$line = $null
$cursor = $null
[Microsoft.PowerShell.PSConsoleReadline]::GetBufferState([ref]$line, [ref]$cursor)
"#mcfly: $line" | Out-File -FilePath $env:MCFLY_HISTORY -Append
Invoke-McFly -CommandToComplete "`"$line`""
}
Export-ModuleMember -Function @(
"Invoke-McFly"
"Add-CommandToMcFly"
)
}