-
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathUltimateCompleter.psm1
More file actions
117 lines (98 loc) · 5.2 KB
/
Copy pathUltimateCompleter.psm1
File metadata and controls
117 lines (98 loc) · 5.2 KB
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
# Define the path to the JSON data file
$DataPath = Join-Path -Path $PSScriptRoot -ChildPath "completions.json"
# Load the JSON data into memory (Using -AsHashTable to prevent case collisions like -d vs -D)
if (Test-Path $DataPath) {
# This requires PowerShell 6+ / 7
$Global:UltimateCompletions = Get-Content -Raw -Path $DataPath | ConvertFrom-Json -AsHashTable
} else {
Write-Warning "UltimateCompleter: completions.json not found!"
return
}
# Find the root commands in the JSON and register a completer for each
foreach ($RootCommand in $Global:UltimateCompletions.Keys) {
Register-ArgumentCompleter -CommandName $RootCommand, "$RootCommand.exe" -ScriptBlock {
param($wordToComplete, $commandAst, $cursorPosition)
$Elements = $commandAst.CommandElements
$RawRoot = $Elements[0].Value
$Root = ($RawRoot -replace '(?i)\.exe$', '').ToLower()
if (-not $Global:UltimateCompletions.Contains($Root)) { return }
$CurrentNode = $Global:UltimateCompletions[$Root]
$Results = @()
$IsTyping = ![string]::IsNullOrWhiteSpace($wordToComplete)
$IgnoredItems = @('--color', '--version', '-v', '--help', '-h')
# 1. SCAN FOR SUBCOMMAND: Scan the entire command line for a known subcommand
$FoundSubCommand = $null
$SubCommandIndex = -1
for ($i = 1; $i -lt $Elements.Count; $i++) {
$Value = $Elements[$i].Value.ToString().ToLower()
# Do not treat the word currently being typed as a finalized subcommand
if ($IsTyping -and $i -eq ($Elements.Count - 1)) { continue }
if ($CurrentNode.Contains('subcommands') -and $CurrentNode['subcommands'].Contains($Value)) {
$FoundSubCommand = $Value
$SubCommandIndex = $i
break
}
}
# 2. DETERMINE ALREADY TYPED ARGUMENTS
$AlreadyTyped = @()
$StartIndex = if ($FoundSubCommand) { $SubCommandIndex + 1 } else { 1 }
$EndIndex = if ($IsTyping) { $Elements.Count - 2 } else { $Elements.Count - 1 }
if ($EndIndex -ge $StartIndex) {
$AlreadyTyped = $Elements[$StartIndex..$EndIndex] | Select-Object -ExpandProperty Value
}
# 3. SMART DEPTH & STACKING LIMITER (The Magic Heuristic)
# If any of the already typed arguments does NOT start with '-', we assume it's a
# positional argument (like a filename, partition 'boot', or package name).
# Once a positional argument is typed, we STOP suggesting flags and let PowerShell suggest files.
$StopSuggesting = $false
foreach ($Arg in $AlreadyTyped) {
if (-not $Arg.StartsWith('-')) {
$StopSuggesting = $true
break
}
}
if ($StopSuggesting) {
return # Exit completer, enabling default file/path autocomplete
}
# 4. POPULATE RESULTS BASED ON CONTEXT
if ($FoundSubCommand) {
# Subcommand Context (e.g., fastboot flash)
$SubNode = $CurrentNode['subcommands'][$FoundSubCommand]
if ($SubNode.Contains('flags')) {
$Results += ($SubNode['flags'] -is [System.Collections.Hashtable]) ? $SubNode['flags'].Keys : $SubNode['flags']
}
} else {
# Root Context (e.g., fastboot)
if ($CurrentNode.Contains('subcommands')) { $Results += $CurrentNode['subcommands'].Keys }
if ($CurrentNode.Contains('flags')) {
$Results += ($CurrentNode['flags'] -is [System.Collections.Hashtable]) ? $CurrentNode['flags'].Keys : $CurrentNode['flags']
}
}
# 5. FILTER: Remove ignored items and already typed items (to prevent duplicates like vendor vendor)
if ($AlreadyTyped.Count -gt 0) {
$Results = $Results | Where-Object { $_ -notin $AlreadyTyped }
}
$Results = $Results | Where-Object { $_ -notin $IgnoredItems }
if ($IsTyping) {
$Results = $Results | Where-Object { $_ -like "$wordToComplete*" }
}
# 6. FORMAT: Convert to PowerShell's CompletionResult with Tooltips
$Results | Select-Object -Unique | ForEach-Object {
$ItemName = $_
$Tooltip = $ItemName
if ($CurrentNode.Contains('subcommands') -and $CurrentNode['subcommands'].Contains($ItemName)) {
if ($CurrentNode['subcommands'][$ItemName].Contains('description')) {
$Tooltip = $CurrentNode['subcommands'][$ItemName]['description']
}
} elseif ($CurrentNode.Contains('flags') -and $CurrentNode['flags'] -is [System.Collections.Hashtable] -and $CurrentNode['flags'].Contains($ItemName)) {
$Tooltip = $CurrentNode['flags'][$ItemName]
} elseif ($FoundSubCommand) {
$SubNode = $CurrentNode['subcommands'][$FoundSubCommand]
if ($SubNode.Contains('flags') -and $SubNode['flags'] -is [System.Collections.Hashtable] -and $SubNode['flags'].Contains($ItemName)) {
$Tooltip = $SubNode['flags'][$ItemName]
}
}
[System.Management.Automation.CompletionResult]::new($ItemName, $ItemName, 'ParameterValue', $Tooltip)
}
}
}