1using namespace System.Management.Automation
2using namespace System.Management.Automation.Language
3
4Register-ArgumentCompleter -Native -CommandName 'just' -ScriptBlock {
5    param($wordToComplete, $commandAst, $cursorPosition)
6
7    $commandElements = $commandAst.CommandElements
8    $command = @(
9        'just'
10        for ($i = 1; $i -lt $commandElements.Count; $i++) {
11            $element = $commandElements[$i]
12            if ($element -isnot [StringConstantExpressionAst] -or
13                $element.StringConstantType -ne [StringConstantType]::BareWord -or
14                $element.Value.StartsWith('-')) {
15                break
16        }
17        $element.Value
18    }) -join ';'
19
20    $completions = @(switch ($command) {
21        'just' {
22            [CompletionResult]::new('--chooser', 'chooser', [CompletionResultType]::ParameterName, 'Override binary invoked by `--choose`')
23            [CompletionResult]::new('--color', 'color', [CompletionResultType]::ParameterName, 'Print colorful output')
24            [CompletionResult]::new('--dump-format', 'dump-format', [CompletionResultType]::ParameterName, 'Dump justfile as <FORMAT>')
25            [CompletionResult]::new('--list-heading', 'list-heading', [CompletionResultType]::ParameterName, 'Print <TEXT> before list')
26            [CompletionResult]::new('--list-prefix', 'list-prefix', [CompletionResultType]::ParameterName, 'Print <TEXT> before each list item')
27            [CompletionResult]::new('-f', 'f', [CompletionResultType]::ParameterName, 'Use <JUSTFILE> as justfile')
28            [CompletionResult]::new('--justfile', 'justfile', [CompletionResultType]::ParameterName, 'Use <JUSTFILE> as justfile')
29            [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'Override <VARIABLE> with <VALUE>')
30            [CompletionResult]::new('--shell', 'shell', [CompletionResultType]::ParameterName, 'Invoke <SHELL> to run recipes')
31            [CompletionResult]::new('--shell-arg', 'shell-arg', [CompletionResultType]::ParameterName, 'Invoke shell with <SHELL-ARG> as an argument')
32            [CompletionResult]::new('-d', 'd', [CompletionResultType]::ParameterName, 'Use <WORKING-DIRECTORY> as working directory. --justfile must also be set')
33            [CompletionResult]::new('--working-directory', 'working-directory', [CompletionResultType]::ParameterName, 'Use <WORKING-DIRECTORY> as working directory. --justfile must also be set')
34            [CompletionResult]::new('-c', 'c', [CompletionResultType]::ParameterName, 'Run an arbitrary command with the working directory, `.env`, overrides, and exports set')
35            [CompletionResult]::new('--command', 'command', [CompletionResultType]::ParameterName, 'Run an arbitrary command with the working directory, `.env`, overrides, and exports set')
36            [CompletionResult]::new('--completions', 'completions', [CompletionResultType]::ParameterName, 'Print shell completion script for <SHELL>')
37            [CompletionResult]::new('-s', 's', [CompletionResultType]::ParameterName, 'Show information about <RECIPE>')
38            [CompletionResult]::new('--show', 'show', [CompletionResultType]::ParameterName, 'Show information about <RECIPE>')
39            [CompletionResult]::new('--dotenv-filename', 'dotenv-filename', [CompletionResultType]::ParameterName, 'Search for environment file named <DOTENV-FILENAME> instead of `.env`')
40            [CompletionResult]::new('--dotenv-path', 'dotenv-path', [CompletionResultType]::ParameterName, 'Load environment file at <DOTENV-PATH> instead of searching for one')
41            [CompletionResult]::new('--check', 'check', [CompletionResultType]::ParameterName, 'Run `--fmt` in ''check'' mode. Exits with 0 if justfile is formatted correctly. Exits with 1 and prints a diff if formatting is required.')
42            [CompletionResult]::new('--dry-run', 'dry-run', [CompletionResultType]::ParameterName, 'Print what just would do without doing it')
43            [CompletionResult]::new('--highlight', 'highlight', [CompletionResultType]::ParameterName, 'Highlight echoed recipe lines in bold')
44            [CompletionResult]::new('--no-dotenv', 'no-dotenv', [CompletionResultType]::ParameterName, 'Don''t load `.env` file')
45            [CompletionResult]::new('--no-highlight', 'no-highlight', [CompletionResultType]::ParameterName, 'Don''t highlight echoed recipe lines in bold')
46            [CompletionResult]::new('-q', 'q', [CompletionResultType]::ParameterName, 'Suppress all output')
47            [CompletionResult]::new('--quiet', 'quiet', [CompletionResultType]::ParameterName, 'Suppress all output')
48            [CompletionResult]::new('--shell-command', 'shell-command', [CompletionResultType]::ParameterName, 'Invoke <COMMAND> with the shell used to run recipe lines and backticks')
49            [CompletionResult]::new('--clear-shell-args', 'clear-shell-args', [CompletionResultType]::ParameterName, 'Clear shell arguments')
50            [CompletionResult]::new('-u', 'u', [CompletionResultType]::ParameterName, 'Return list and summary entries in source order')
51            [CompletionResult]::new('--unsorted', 'unsorted', [CompletionResultType]::ParameterName, 'Return list and summary entries in source order')
52            [CompletionResult]::new('--unstable', 'unstable', [CompletionResultType]::ParameterName, 'Enable unstable features')
53            [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'Use verbose output')
54            [CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'Use verbose output')
55            [CompletionResult]::new('--changelog', 'changelog', [CompletionResultType]::ParameterName, 'Print changelog')
56            [CompletionResult]::new('--choose', 'choose', [CompletionResultType]::ParameterName, 'Select one or more recipes to run using a binary. If `--chooser` is not passed the chooser defaults to the value of $JUST_CHOOSER, falling back to `fzf`')
57            [CompletionResult]::new('--dump', 'dump', [CompletionResultType]::ParameterName, 'Print justfile')
58            [CompletionResult]::new('-e', 'e', [CompletionResultType]::ParameterName, 'Edit justfile with editor given by $VISUAL or $EDITOR, falling back to `vim`')
59            [CompletionResult]::new('--edit', 'edit', [CompletionResultType]::ParameterName, 'Edit justfile with editor given by $VISUAL or $EDITOR, falling back to `vim`')
60            [CompletionResult]::new('--evaluate', 'evaluate', [CompletionResultType]::ParameterName, 'Evaluate and print all variables. If a variable name is given as an argument, only print that variable''s value.')
61            [CompletionResult]::new('--fmt', 'fmt', [CompletionResultType]::ParameterName, 'Format and overwrite justfile')
62            [CompletionResult]::new('--init', 'init', [CompletionResultType]::ParameterName, 'Initialize new justfile in project root')
63            [CompletionResult]::new('-l', 'l', [CompletionResultType]::ParameterName, 'List available recipes and their arguments')
64            [CompletionResult]::new('--list', 'list', [CompletionResultType]::ParameterName, 'List available recipes and their arguments')
65            [CompletionResult]::new('--summary', 'summary', [CompletionResultType]::ParameterName, 'List names of available recipes')
66            [CompletionResult]::new('--variables', 'variables', [CompletionResultType]::ParameterName, 'List names of variables')
67            [CompletionResult]::new('-h', 'h', [CompletionResultType]::ParameterName, 'Print help information')
68            [CompletionResult]::new('--help', 'help', [CompletionResultType]::ParameterName, 'Print help information')
69            [CompletionResult]::new('-V', 'V', [CompletionResultType]::ParameterName, 'Print version information')
70            [CompletionResult]::new('--version', 'version', [CompletionResultType]::ParameterName, 'Print version information')
71            break
72        }
73    })
74
75    function Get-JustFileRecipes([string[]]$CommandElements) {
76        $justFileIndex = $commandElements.IndexOf("--justfile");
77
78        if ($justFileIndex -ne -1 && $justFileIndex + 1 -le $commandElements.Length) {
79            $justFileLocation = $commandElements[$justFileIndex + 1]
80        }
81
82        $justArgs = @("--summary")
83
84        if (Test-Path $justFileLocation) {
85            $justArgs += @("--justfile", $justFileLocation)
86        }
87
88        $recipes = $(just @justArgs) -split ' '
89        return $recipes | ForEach-Object { [CompletionResult]::new($_) }
90    }
91
92    $elementValues = $commandElements | Select-Object -ExpandProperty Value
93    $recipes = Get-JustFileRecipes -CommandElements $elementValues
94    $completions += $recipes
95    $completions.Where{ $_.CompletionText -like "$wordToComplete*" } |
96        Sort-Object -Property ListItemText
97}
98