Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,27 @@ soleil bench --suite smoke
soleil bench --suite core --runs 3 --json
```

### PowerShell tab completion

Windows PowerShell users can load deterministic completions for the `soleil`
command:

```powershell
. "$PWD\completions\soleil.ps1"
```

To keep it available, add the same line to your PowerShell profile:

```powershell
notepad $PROFILE
```

Remove the line from `$PROFILE` to uninstall the completion hook. The script
completes the documented commands (`doctor`, `setup`, `language`, `run`,
`bench`), common options (`--cwd`, `--mode`, `--language`, `--yes`, `--json`,
`--suite`, `--runs`), and known values for `--mode`, `--language`, and
`--suite`.

Benchmarks use the configured free/local routes and therefore consume their quota.
Each case runs in a new temporary project that is removed after verification.
See the [benchmark methodology and latest verified snapshot](docs/BENCHMARKS.md).
Expand Down
73 changes: 73 additions & 0 deletions completions/soleil.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# SoleilCode PowerShell tab completion.
# Load with: . "$PWD\completions\soleil.ps1"

$script:SoleilCommands = @(
'doctor',
'setup',
'language',
'languages',
'run',
'bench',
'benchmark'
)

$script:SoleilOptions = @(
'--cwd',
'--mode',
'--language',
'--lang',
'--yes',
'-y',
'--json',
'--prompt-file',
'--suite',
'--runs',
'--version',
'-v',
'--help',
'-h'
)

$script:SoleilModes = @('auto', 'free', 'local', 'private')
$script:SoleilLanguages = @('en', 'tr', 'es', 'fr', 'de', 'it', 'pt', 'ru', 'ja', 'ko')
$script:SoleilSuites = @('smoke', 'core')

function script:New-SoleilCompletionResult {
param(
[string] $Value,
[string] $ToolTip = $Value
)

[System.Management.Automation.CompletionResult]::new(
$Value,
$Value,
[System.Management.Automation.CompletionResultType]::ParameterValue,
$ToolTip
)
}

Register-ArgumentCompleter -Native -CommandName soleil -ScriptBlock {
param($wordToComplete, $commandAst, $cursorPosition)

$elements = @($commandAst.CommandElements | ForEach-Object { $_.ToString() })
$previous = if ($elements.Count -ge 2) { $elements[$elements.Count - 2] } else { '' }

$candidates = switch ($previous) {
'--mode' { $script:SoleilModes; break }
'--language' { $script:SoleilLanguages; break }
'--lang' { $script:SoleilLanguages; break }
'--suite' { $script:SoleilSuites; break }
default {
if ($wordToComplete -like '-*') {
$script:SoleilOptions
} else {
@($script:SoleilCommands + $script:SoleilOptions)
}
}
}

$candidates |
Where-Object { $_ -like "$wordToComplete*" } |
Sort-Object -Unique |
ForEach-Object { script:New-SoleilCompletionResult $_ }
}
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
},
"files": [
"bin",
"completions",
"dist",
"README.md",
"CHANGELOG.md",
Expand Down
36 changes: 36 additions & 0 deletions tests/powershell-completion.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import assert from "node:assert/strict";
import { readFile } from "node:fs/promises";
import path from "node:path";
import test from "node:test";

const completionPath = path.resolve("completions/soleil.ps1");

test("PowerShell completion covers documented commands and options", async () => {
const script = await readFile(completionPath, "utf8");

for (const command of ["doctor", "setup", "language", "run", "bench"]) {
assert.match(script, new RegExp(`'${command}'`));
}

for (const option of ["--cwd", "--mode", "--language", "--yes", "--json", "--suite", "--runs"]) {
assert.match(script, new RegExp(`'${option}'`));
}

for (const value of ["auto", "free", "local", "private", "smoke", "core"]) {
assert.match(script, new RegExp(`'${value}'`));
}

assert.match(script, /Register-ArgumentCompleter -Native -CommandName soleil/);
});

test("PowerShell completion candidate lists are deterministic and unique", async () => {
const script = await readFile(completionPath, "utf8");
const listMatches = script.matchAll(/\$script:Soleil(?:Commands|Options|Modes|Languages|Suites) = @\((?<body>[\s\S]*?)\)/g);

for (const match of listMatches) {
const body = match.groups?.body ?? "";
const values = [...body.matchAll(/'([^']+)'/g)].map((entry) => entry[1]);
assert.deepEqual(values, [...new Set(values)], `duplicate completion values in ${match[0].split(" = ")[0]}`);
assert.ok(values.length > 0);
}
});