Skip to content

Commit e9cb391

Browse files
committed
♻️ Extract complex completion suggestion process to separated files
1 parent e1df3d6 commit e9cb391

File tree

8 files changed

+123
-62
lines changed

8 files changed

+123
-62
lines changed

src/commands.ps1

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,3 @@
1-
. $PSScriptRoot\options.ps1
2-
. $PSScriptRoot\subCommands.ps1
3-
. $PSScriptRoot\values.ps1
4-
51
Set-Variable -Name commands -Value @(
62
'add',
73
'audit',

src/completion.ps1

Lines changed: 14 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,78 +1,35 @@
11
Register-ArgumentCompleter -Native -CommandName @('yarn', 'yarn.cmd') -ScriptBlock {
22
param($wordToComplete, $commandAst, $cursorPosition)
33

4-
. $PSScriptRoot\commands.ps1
4+
. $PSScriptRoot\lib.ps1
55
. $PSScriptRoot\utils.ps1
66

77
$searchBlock = { $_ -like "$wordToComplete*" }
8-
98
$completions = @()
109

1110
# Main command
12-
$mainCommand = if ($commandAst.CommandElements[1]) { $commandAst.CommandElements[1].Value } else { $null }
11+
$command = if ($commandAst.CommandElements[1]) { $commandAst.CommandElements[1].Value } else { $null }
1312
# Command's value or sub-command or command's options
14-
$valueOrsubCommandOrOption = if ($commandAst.CommandElements[2]) { $commandAst.CommandElements[2].Value } else { $null }
13+
$commandSubPart = if ($commandAst.CommandElements[2]) { $commandAst.CommandElements[2].Value } else { $null }
1514
# Sub-command's option or option's value of main command
16-
$subCommandOptionOrOptionValue = if ($commandAst.CommandElements[3]) { $commandAst.CommandElements[3].Value } else { $null }
15+
$command2ndSubPart = if ($commandAst.CommandElements[3]) { $commandAst.CommandElements[3].Value } else { $null }
1716

18-
# If word to complete is equal to main command, suggest all commands & options of `install` command
19-
if (AreEqual $mainCommand $wordToComplete) {
20-
$completions += $commands | Where-Object $searchBlock | ForEach-Object {
21-
[System.Management.Automation.CompletionResult]::new($_, $_, 'Command', $_)
22-
}
23-
$completions += $options['install'].Keys | Where-Object $searchBlock | ForEach-Object {
24-
[System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterName', $_)
25-
}
17+
# If word to complete is equal to command part, suggest all commands & options of `install` command
18+
if (Compare-CommandElement $command $wordToComplete) {
19+
$completions += Get-1stCompletions -WordToComplete $wordToComplete
2620
}
27-
# If word to complete is equal to command's value/sub-command/command's options, suggest command's values and sub-commmands and command's options
28-
elseif (AreEqual $valueOrsubCommandOrOption $wordToComplete) {
29-
# Main command's values
30-
if ($commandValues[$mainCommand]) {
31-
$completions += Invoke-Command -ScriptBlock $commandValues[$mainCommand] | ForEach-Object {
32-
[System.Management.Automation.CompletionResult]::new($_, $_, 'DynamicKeyword', $_)
33-
}
34-
}
35-
# Sub-commands
36-
if ($subCommands[$mainCommand]) {
37-
$completions += $subCommands[$mainCommand].Keys | Where-Object $searchBlock | ForEach-Object {
38-
[System.Management.Automation.CompletionResult]::new($_, $_, 'Command', $_)
39-
}
40-
}
41-
# Main command's options
42-
if ($options[$mainCommand]) {
43-
$completions += $options[$mainCommand].Keys | Where-Object $searchBlock | ForEach-Object {
44-
[System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterName', $_)
45-
}
46-
}
21+
# If word to complete is equal to command sub-part, suggest command's values and sub-commmands and command's options
22+
elseif (Compare-CommandElement $commandSubPart $wordToComplete) {
23+
$completions += Get-2ndCompletions -WordToComplete $wordToComplete -Command $command
4724
}
48-
# If word to complete is equal to main command option's values/sub-command's options,
25+
# If word to complete is equal to second sub-part,
4926
# suggest main command option's values or sub-command's options
50-
elseif (AreEqual $subCommandOptionOrOptionValue $wordToComplete) {
51-
# Main command option's value
52-
if ($options[$mainCommand][$valueOrsubCommandOrOption]) {
53-
$optionValues = $options[$mainCommand][$valueOrsubCommandOrOption]
54-
55-
$completions += $optionValues | Where-Object $searchBlock | ForEach-Object {
56-
[System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_)
57-
}
58-
59-
# Immediately return if it's command's value completion
60-
return $completions
61-
}
62-
63-
# Sub-command's options
64-
if ($subCommands[$mainCommand][$valueOrsubCommandOrOption]) {
65-
$subCommand = $subCommands[$mainCommand][$valueOrsubCommandOrOption]
66-
$subCommandOptionOrOptionValues = if ($subCommand.options) { $subCommand.options.Keys } else { $null }
67-
68-
$completions += $subCommandOptionOrOptionValues | Where-Object $searchBlock | ForEach-Object {
69-
[System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterName', $_)
70-
}
71-
}
27+
elseif (Compare-CommandElement $command2ndSubPart $wordToComplete) {
28+
$completions += Get-3rdCompletions -WordToComplete $wordToComplete -Command $command -CommandSubPart $commandSubPart
7229
}
7330

7431
# Always suggest global options
75-
$completions += $globalOptions | Where-Object $searchBlock | ForEach-Object {
32+
$completions += Get-GlobalOptionCompletions | Where-Object $searchBlock | ForEach-Object {
7633
[System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterName', $_)
7734
}
7835

src/lib.ps1

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
$libsScriptPath = "$PSScriptRoot\lib" | Resolve-Path
2+
$libsScripts = Get-ChildItem $libsScriptPath | Where-Object {
3+
$_.Name -like '*.ps1'
4+
}
5+
6+
# Load all sub-commands
7+
$libsScripts | ForEach-Object {
8+
. $_.FullName
9+
}

src/lib/Get-1stCompletions.ps1

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
function Get-1stCompletions([string] $WordToComplete) {
2+
if (-not $commands) {
3+
. $PSScriptRoot\..\commands.ps1
4+
}
5+
if ((-not $options) -or (-not $options['install'])) {
6+
. $PSScriptRoot\..\options\install.ps1
7+
}
8+
9+
$searchBlock = { $_ -like "$WordToComplete*" }
10+
$completions = @()
11+
12+
# Suggest commands
13+
$completions += $commands | Where-Object $searchBlock | ForEach-Object {
14+
[System.Management.Automation.CompletionResult]::new($_, $_, 'Command', $_)
15+
}
16+
# Suggest options of `install` command
17+
$completions += $options['install'].Keys | Where-Object $searchBlock | ForEach-Object {
18+
[System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterName', $_)
19+
}
20+
21+
return $completions
22+
}

src/lib/Get-2ndCompletions.ps1

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
function Get-2ndCompletions([string] $WordToComplete, [string] $Command) {
2+
if (-not $commandValues) {
3+
. $PSScriptRoot\..\values.ps1
4+
}
5+
if (-not $subCommands) {
6+
. $PSScriptRoot\..\subCommands.ps1
7+
}
8+
if (-not $options) {
9+
. $PSScriptRoot\..\options.ps1
10+
}
11+
12+
$searchBlock = { $_ -like "$WordToComplete*" }
13+
$completions = @()
14+
15+
# Command's values
16+
if ($commandValues[$Command]) {
17+
$completions += Invoke-Command -ScriptBlock $commandValues[$Command] | ForEach-Object {
18+
[System.Management.Automation.CompletionResult]::new($_, $_, 'DynamicKeyword', $_)
19+
}
20+
}
21+
# Sub-commands
22+
if ($subCommands[$Command]) {
23+
$completions += $subCommands[$Command].Keys | Where-Object $searchBlock | ForEach-Object {
24+
[System.Management.Automation.CompletionResult]::new($_, $_, 'Command', $_)
25+
}
26+
}
27+
# Command's options
28+
if ($options[$Command]) {
29+
$completions += $options[$Command].Keys | Where-Object $searchBlock | ForEach-Object {
30+
[System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterName', $_)
31+
}
32+
}
33+
34+
return $completions
35+
}

src/lib/Get-3rdCompletions.ps1

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
function Get-3rdCompletions([string] $WordToComplete, [string] $Command, [string] $CommandSubPart) {
2+
if (-not $options) {
3+
. $PSScriptRoot\..\options.ps1
4+
}
5+
if (-not $subCommands) {
6+
. $PSScriptRoot\..\subCommands.ps1
7+
}
8+
9+
$searchBlock = { $_ -like "$WordToComplete*" }
10+
$completions = @()
11+
12+
# Command option's values
13+
if ($options[$Command][$CommandSubPart]) {
14+
$optionValues = $options[$Command][$CommandSubPart]
15+
16+
$completions += $optionValues | Where-Object $searchBlock | ForEach-Object {
17+
[System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_)
18+
}
19+
20+
# Immediately return if it's command's value completion
21+
return $completions
22+
}
23+
24+
# Sub-command's options
25+
if ($subCommands[$Command][$CommandSubPart]) {
26+
$subCommand = $subCommands[$Command][$CommandSubPart]
27+
$subCommandOptions = if ($subCommand.options) { $subCommand.options.Keys } else { @() }
28+
29+
$completions += $subCommandOptions | Where-Object $searchBlock | ForEach-Object {
30+
[System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterName', $_)
31+
}
32+
}
33+
34+
return $completions
35+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
function Get-GlobalOptionCompletions {
2+
if (-not $globalOptions) {
3+
. $PSScriptRoot\..\options\__.ps1
4+
}
5+
6+
return $globalOptions
7+
}

src/utils.ps1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
function AreEqual($a, $b) {
1+
function Compare-CommandElement($a, $b) {
22
try {
33
return (
44
([string]::IsNullOrEmpty($a) -and [string]::IsNullOrEmpty($b)) -or

0 commit comments

Comments
 (0)