Skip to content

Commit 074906a

Browse files
[scripts/posh-vcpkg] Change TabExpansion to Register-ArgumentCompleter (#1512)
1 parent e4443de commit 074906a

File tree

6 files changed

+464
-43
lines changed

6 files changed

+464
-43
lines changed

.github/workflows/build.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ jobs:
8080
shell: pwsh
8181
run: |
8282
cd out/build/${{ matrix.preset }}
83+
Import-Module Pester -Force -MinimumVersion '5.6.1' -MaximumVersion '5.99'
8384
${{ github.workspace }}/azure-pipelines/end-to-end-tests.ps1 -RunArtifactsTests
8485
env:
8586
VCPKG_ROOT: ${{ github.workspace }}/vcpkg-root
Lines changed: 378 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,378 @@
1+
param (
2+
[Parameter(Mandatory)][string]$poshVcpkgModulePath,
3+
[Parameter(Mandatory)][System.IO.FileInfo]$vcpkgExe
4+
)
5+
6+
BeforeAll {
7+
Import-Module $poshVcpkgModulePath
8+
9+
$env:PATH = $vcpkgExe.Directory.FullName + [System.IO.Path]::PathSeparator + $env:PATH
10+
11+
function Complete-InputCaret {
12+
[OutputType([string[]])]
13+
param (
14+
[Parameter(Mandatory, Position = 0, ValueFromPipeline)]
15+
[string]$InputCaretScript
16+
)
17+
$positionMatches = [regex]::Matches($InputCaretScript, '\^')
18+
if ($positionMatches.Count -ne 1) {
19+
throw 'Invalid caret cursor command, please indicate by only one ^ character'
20+
}
21+
$command = [string]$InputCaretScript.Replace('^', '')
22+
$cursorPosition = [int]$positionMatches[0].Index
23+
$result = [System.Management.Automation.CommandCompletion]::CompleteInput($command, $cursorPosition, $null)
24+
return $result.CompletionMatches | Select-Object -ExpandProperty CompletionText
25+
}
26+
27+
$VcpkgPredefined = @{
28+
CommandList = @(
29+
'acquire_project', 'acquire', 'activate', 'add', 'create', 'deactivate', 'depend-info', 'edit', 'env'
30+
'export', 'fetch', 'find', 'format-manifest', 'hash', 'help', 'install', 'integrate', 'list', 'new', 'owns'
31+
'portsdiff', 'remove', 'search', 'update', 'upgrade', 'use', 'version', 'x-add-version', 'x-check-support'
32+
'x-init-registry', 'x-package-info', 'x-regenerate', 'x-set-installed', 'x-update-baseline'
33+
'x-update-registry', 'x-vsinstances'
34+
)
35+
CommonParameterList = @()
36+
CommandOptionList = @{
37+
install = @(
38+
'--allow-unsupported', '--clean-after-build', '--clean-buildtrees-after-build'
39+
'--clean-downloads-after-build', '--clean-packages-after-build', '--dry-run', '--editable'
40+
'--enforce-port-checks', '--head', '--keep-going', '--no-downloads', '--no-print-usage'
41+
'--only-binarycaching', '--only-downloads', '--recurse', '--x-feature', '--x-no-default-features'
42+
'--x-prohibit-backcompat-features', '--x-use-aria2', '--x-write-nuget-packages-config', '--x-xunit'
43+
)
44+
remove = @(
45+
'--dry-run', '--outdated', '--purge', '--recurse'
46+
)
47+
}
48+
}
49+
$VcpkgPredefined | Out-Null
50+
}
51+
52+
Describe 'Prerequisites tests' {
53+
Context 'Internal function Complete-InputCaret tests' {
54+
It 'Complete-InputCaret 1 caret string should success' {
55+
{ 'aaaa^' | Complete-InputCaret } | Should -Not -Throw
56+
}
57+
58+
It 'Complete-InputCaret 0 caret string should throw' {
59+
{ 'aaaa' | Complete-InputCaret } | Should -Throw
60+
}
61+
62+
It 'Complete-InputCaret 2 caret string should throw' {
63+
{ 'aaaa^^' | Complete-InputCaret } | Should -Throw
64+
}
65+
66+
It 'Complete-InputCaret self should success' {
67+
'Complete-InputCaret^' | Complete-InputCaret | Should -Contain 'Complete-InputCaret'
68+
}
69+
}
70+
71+
Context 'Exist module and command tests' {
72+
It 'Should imported module posh-vcpkg' {
73+
(Get-Module -Name posh-vcpkg).Name | Should -Be 'posh-vcpkg'
74+
}
75+
76+
It 'Should version greater than or equal 0.0.2' {
77+
(Get-Module posh-vcpkg).Version | Should -BeGreaterOrEqual '0.0.2'
78+
}
79+
80+
It 'Should have executable vcpkg' {
81+
$vcpkgExe | Should -Exist
82+
}
83+
84+
It 'Should have command vcpkg' {
85+
Get-Command -Name vcpkg | Should -Not -BeNullOrEmpty
86+
}
87+
88+
It 'Should command vcpkg is the executable' {
89+
(Get-Command -Name vcpkg).Path | Should -Be $vcpkgExe.FullName
90+
}
91+
}
92+
}
93+
94+
Describe 'Complete basic tests' {
95+
Context 'Complete full command contain tests' {
96+
It 'Should complete command [vcpkg <_>^] contain [<_>]' -ForEach @(
97+
'help'
98+
'install'
99+
'version'
100+
'integrate'
101+
) {
102+
'vcpkg {0}^' -f $_ | Complete-InputCaret | Should -Contain $_
103+
}
104+
}
105+
106+
Context 'Complete full command exact match tests' {
107+
It 'Should exact match command completions [vcpkg <_>^] be [<_>]' -ForEach @(
108+
'help'
109+
'install'
110+
'version'
111+
'integrate'
112+
) {
113+
'vcpkg {0}^' -f $_ | Complete-InputCaret | Should -Be $_
114+
}
115+
}
116+
117+
Context 'Complete part command contain tests' {
118+
It 'Should complete command [vcpkg <command>^] contain [<expected>]' -ForEach @(
119+
@{command = 'he'; expected = 'help' }
120+
@{command = 'in'; expected = 'install' }
121+
@{command = 've'; expected = 'version' }
122+
@{command = 'in'; expected = 'integrate' }
123+
) {
124+
'vcpkg {0}^' -f $command | Complete-InputCaret | Should -Contain $expected
125+
}
126+
}
127+
128+
Context 'Complete space tests' {
129+
It 'Should complete command for blank space [vcpkg ^] contain [<_>]' -ForEach @(
130+
'help'
131+
'install'
132+
'version'
133+
'integrate'
134+
) {
135+
'vcpkg ^' | Complete-InputCaret | Should -Contain $_
136+
}
137+
138+
It 'Should exact match command completions for blank space [vcpkg ^]' {
139+
$completions = 'vcpkg ^' | Complete-InputCaret
140+
$expected = $VcpkgPredefined.CommandList
141+
Compare-Object $completions $expected | Should -BeNullOrEmpty
142+
}
143+
}
144+
}
145+
146+
Describe 'Complete command tests' {
147+
Context 'Complete common option tests' -Skip {
148+
It 'Should complete common option for blank space [vcpkg ^] contain [--host-triplet]' {
149+
'vcpkg ^' | Complete-InputCaret | Should -Contain '--host-triplet'
150+
}
151+
152+
It 'Should complete common option for blank space [vcpkg ^] contain [--host-triplet=]' {
153+
'vcpkg ^' | Complete-InputCaret | Should -Contain '--host-triplet='
154+
}
155+
156+
It 'Should complete common option for blank space [vcpkg ^] contain [--vcpkg-root]' {
157+
'vcpkg ^' | Complete-InputCaret | Should -Contain '--vcpkg-root'
158+
}
159+
160+
It 'Should complete common option for blank space [vcpkg ^] contain [--vcpkg-root=]' {
161+
'vcpkg ^' | Complete-InputCaret | Should -Contain '--vcpkg-root='
162+
}
163+
}
164+
165+
Context 'Complete common option argument tests' -Skip {
166+
It 'Should complete common option arguments for [vcpkg --triplet^] contain [--triplet=]' {
167+
'vcpkg --triplet^' -f $argument | Complete-InputCaret | Should -Contain '--triplet=x64-windows'
168+
}
169+
170+
It 'Should complete common option arguments for [vcpkg --triplet=^] contain [--triplet=x64-windows]' {
171+
'vcpkg --triplet=^' -f $argument | Complete-InputCaret | Should -Contain '--triplet=x64-windows'
172+
}
173+
174+
It 'Should complete common option arguments for [vcpkg --triplet=x64^] contain [--triplet=x64-windows]' {
175+
'vcpkg --triplet=x64^' -f $argument | Complete-InputCaret | Should -Contain '--triplet=x64-windows'
176+
}
177+
}
178+
179+
# Skip due to https://github.com/PowerShell/PowerShell/issues/2912
180+
Context 'Complete command option list tests conditionally - CoreOnly' -Tag CoreOnly {
181+
It 'Should complete option flags with single minus [vcpkg <command> -^] contain [<expected>]' -ForEach @(
182+
@{ command = 'install' ; expected = '--editable' }
183+
@{ command = 'remove' ; expected = '--dry-run' }
184+
) {
185+
'vcpkg {0} -^' -f $command | Complete-InputCaret | Should -Contain $expected
186+
}
187+
188+
It 'Should complete option flags with double minus [vcpkg <command> --^] contain [<expected>]' -ForEach @(
189+
@{ command = 'install' ; expected = '--editable' }
190+
@{ command = 'remove' ; expected = '--dry-run' }
191+
) {
192+
'vcpkg {0} --^' -f $command | Complete-InputCaret | Should -Contain $expected
193+
}
194+
195+
It 'Should exact match command options for double minus [vcpkg <_> --^]' -ForEach @(
196+
'install'
197+
'remove'
198+
) {
199+
$completions = 'vcpkg {0} --^' -f $_ | Complete-InputCaret
200+
$expected = $VcpkgPredefined.CommandOptionList[$_]
201+
Compare-Object $completions $expected | Should -BeNullOrEmpty
202+
}
203+
}
204+
205+
Context 'Complete command argument tests conditionally' {
206+
It 'Should complete install with port name [<caretCmd>] contain [<expected>]' -ForEach @(
207+
@{ caretCmd = 'vcpkg install vcpkg-^' ; expected = 'vcpkg-cmake' }
208+
) {
209+
$caretCmd | Complete-InputCaret | Should -Contain $expected
210+
}
211+
212+
It 'Should complete install port with triplet [<caretCmd>] contain [<expected>]' -ForEach @(
213+
@{ caretCmd = 'vcpkg install vcpkg-cmake:^' ; expected = 'vcpkg-cmake:x64-windows' }
214+
) {
215+
$caretCmd | Complete-InputCaret | Should -Contain $expected
216+
}
217+
218+
It 'Should complete integrate with subcommand [vcpkg integrate inst^] be [install]' {
219+
'vcpkg integrate inst^' | Complete-InputCaret | Should -Be 'install'
220+
}
221+
222+
It 'Should complete integrate with subcommand [vcpkg integrate ^] contain [powershell] - WindowsOnly' -Tag WindowsOnly {
223+
'vcpkg integrate ^' | Complete-InputCaret | Should -Contain 'powershell'
224+
}
225+
226+
It 'Should complete integrate with subcommand [vcpkg integrate ^] contain [bash] - NonWindowsOnly' -Tag NonWindowsOnly {
227+
'vcpkg integrate ^' | Complete-InputCaret | Should -Contain 'bash'
228+
}
229+
230+
It 'Should exact match command subcommands [vcpkg integrate ^] - WindowsOnly' -Tag WindowsOnly {
231+
$expected = @('install', 'remove', 'powershell', 'project')
232+
$completions = 'vcpkg integrate ^' | Complete-InputCaret
233+
Compare-Object $completions $expected | Should -BeNullOrEmpty
234+
}
235+
236+
It 'Should exact match command subcommands [vcpkg integrate ^] - NonWindowsOnly' -Tag NonWindowsOnly {
237+
$expected = @('install', 'remove', 'bash', 'x-fish', 'zsh')
238+
$completions = 'vcpkg integrate ^' | Complete-InputCaret
239+
Compare-Object $completions $expected | Should -BeNullOrEmpty
240+
}
241+
}
242+
}
243+
244+
Describe 'Complete variants tests' {
245+
BeforeAll {
246+
Set-Variable vcpkgWithExt ($vcpkgExe.FullName)
247+
Set-Variable vcpkgNoExt ([System.IO.Path]::GetFileNameWithoutExtension($vcpkgExe.FullName))
248+
}
249+
250+
Context 'Complete basic variant command tests' {
251+
It 'Should exact match command completions with call operator absolute exe word be [version]' {
252+
"& $vcpkgWithExt ver^" | Complete-InputCaret | Should -Be 'version'
253+
}
254+
255+
It 'Should exact match command completions [<caretCmd>] <comment> be [version]' -ForEach @(
256+
@{ caretCmd = 'vcpkg ver^' ; comment = 'with word' }
257+
@{ caretCmd = '& vcpkg ver^' ; comment = 'with & word' }
258+
) {
259+
$caretCmd | Complete-InputCaret | Should -Be 'version'
260+
}
261+
262+
It 'Should exact match command completions for exe path [<caretCmd>] <comment> be [version]' -ForEach @(
263+
@{ caretCmd = './vcpkg ver^' ; comment = 'with dot slash word' }
264+
@{ caretCmd = '& ./vcpkg ver^' ; comment = 'with & dot slash word' }
265+
) {
266+
Set-Location $vcpkgExe.Directory
267+
$caretCmd | Complete-InputCaret | Should -Be 'version'
268+
}
269+
}
270+
271+
Context 'Complete variant command tests conditionally - WindowsOnly' -Tag WindowsOnly {
272+
It 'Should exact match command completions with call operator no-ext absolute exe word be [version]' {
273+
"& $vcpkgNoExt ver^" | Complete-InputCaret | Should -Be 'version'
274+
}
275+
276+
It 'Should exact match command completions [<caretCmd>] <comment> be [version]' -ForEach @(
277+
@{ caretCmd = '& vcpkg.exe ver^' ; comment = 'with & extension word' }
278+
@{ caretCmd = 'vcpkg.exe ver^' ; comment = 'with extension word' }
279+
) {
280+
$caretCmd | Complete-InputCaret | Should -Be 'version'
281+
}
282+
283+
It 'Should exact match command completions for exe path [<caretCmd>] <comment> be [version]' -ForEach @(
284+
@{ caretCmd = '.\vcpkg ver^' ; comment = 'with dot backslash word' }
285+
@{ caretCmd = '& .\vcpkg ver^' ; comment = 'with & dot backslash word' }
286+
@{ caretCmd = './vcpkg.exe ver^' ; comment = 'with dot slash extension word' }
287+
@{ caretCmd = '.\vcpkg.exe ver^' ; comment = 'with dot backslash extension word' }
288+
@{ caretCmd = '& ./vcpkg.exe ver^' ; comment = 'with & dot slash extension word' }
289+
@{ caretCmd = '& .\vcpkg.exe ver^' ; comment = 'with & dot backslash extension word' }
290+
) {
291+
Set-Location $vcpkgExe.Directory
292+
$caretCmd | Complete-InputCaret | Should -Be 'version'
293+
}
294+
}
295+
296+
Context 'Complete command with spaces tests' {
297+
It 'Should complete command [<caretCmd>] <comment> contain [version]' -ForEach @(
298+
@{ caretCmd = 'vcpkg ^' ; comment = 'many spaces' }
299+
@{ caretCmd = 'vcpkg ver^' ; comment = 'middle many spaces' }
300+
@{ caretCmd = ' vcpkg ver^' ; comment = 'with leading spaces' }
301+
@{ caretCmd = ' & vcpkg ver^' ; comment = 'with leading spaces and call operator' }
302+
) {
303+
$caretCmd | Complete-InputCaret | Should -Contain 'version'
304+
}
305+
}
306+
307+
Context 'Complete command quotation tests' {
308+
It "Should fallback to default completion with quoted full word [vcpkg 'install'^]" {
309+
"vcpkg 'install'^" | Complete-InputCaret | Should -Be $null
310+
}
311+
312+
It "Should prevent completion for quoted space [vcpkg ' '^]" {
313+
"vcpkg ' '^" | Complete-InputCaret | Should -Be $null
314+
}
315+
}
316+
}
317+
318+
Describe 'Complete position tests' {
319+
Context 'Complete command intermediate tests' {
320+
It 'Should exact match command completions [<caretCmd>] <comment> be [version]' -ForEach @(
321+
@{ caretCmd = 'vcpkg version^'; comment = 'end of word' }
322+
@{ caretCmd = 'vcpkg ver^sion'; comment = 'middle of word' }
323+
) {
324+
$caretCmd | Complete-InputCaret | Should -Be 'version'
325+
}
326+
327+
It 'Should exact match command completions [<_>]' -ForEach @(
328+
'vcpkg ^version'
329+
'vcpkg ^ '
330+
'vcpkg ^ '
331+
' vcpkg ^ '
332+
' & vcpkg ^ '
333+
'vcpkg ^ version '
334+
) {
335+
$completions = $_ | Complete-InputCaret
336+
$expected = $VcpkgPredefined.CommandList
337+
Compare-Object $completions $expected | Should -BeNullOrEmpty
338+
}
339+
}
340+
341+
Context 'Complete complex tests' {
342+
It 'Should complete complex command line [<caretCmd>] be [<expected>]' -ForEach (
343+
@{ caretCmd = 'echo powershell | % { vcpkg int^egr $_ }; echo $?'; expected = 'integrate' }
344+
) {
345+
$caretCmd | Complete-InputCaret | Should -Be $expected
346+
}
347+
}
348+
}
349+
350+
Describe 'Impossible command tests' {
351+
Context 'Complete non-exist command tests conditionally' {
352+
It 'Should prevent completion for non-exist command [vcpkg zzzzzzzz^]' {
353+
'vcpkg zzzzzzzz^' | Complete-InputCaret | Should -Be $null
354+
}
355+
356+
It 'Should prevent completion for non-exist command [vcpkg ---^]' {
357+
'vcpkg ---^' | Complete-InputCaret | Should -Be $null
358+
}
359+
360+
It 'Should fallback to default for non-exist command with trailing spaces [vcpkg zzzzzzzz ^] - WindowsOnly' -Tag WindowsOnly {
361+
'vcpkg zzzzzzzz ^' | Complete-InputCaret | Should -BeLike '.\*'
362+
}
363+
364+
It 'Should fallback to default for non-exist command with trailing spaces [vcpkg zzzzzzzz ^] - NonWindowsOnly' -Tag NonWindowsOnly {
365+
'vcpkg zzzzzzzz ^' | Complete-InputCaret | Should -BeLike './*'
366+
}
367+
}
368+
369+
Context 'Complete error command tests' {
370+
It 'Should prevent error from error command [vcpkg --triplet^]' {
371+
{ $ErrorActionPreference = 'Stop'; 'vcpkg --triplet^' | Complete-InputCaret } | Should -Not -Throw
372+
}
373+
374+
It 'Should prevent completion for error command [vcpkg --triplet^]' {
375+
'vcpkg --triplet^' | Complete-InputCaret | Should -Be $null
376+
}
377+
}
378+
}

0 commit comments

Comments
 (0)