Skip to content
Merged
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
391 changes: 384 additions & 7 deletions src/System.CommandLine.StaticCompletions/shells/FishShellProvider.cs

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

#nullable disable

namespace System.CommandLine.StaticCompletions.Tests;

using System.CommandLine.StaticCompletions.Shells;

public class FishShellProviderTests(ITestOutputHelper log)
{
private IShellProvider provider = new FishShellProvider();

[Fact]
public async Task GenericCompletions()
{
await provider.Verify(new("mycommand"), log);
}

[Fact]
public async Task SimpleOptionCompletion()
{
await provider.Verify(new("mycommand") {
new Option<string>("--name")
}, log);
}

[Fact]
public async Task SubcommandAndOptionInTopLevelList()
{
await provider.Verify(new("mycommand") {
new Option<string>("--name"),
new Command("subcommand")
}, log);
}

[Fact]
public async Task NestedSubcommandCompletion()
{
await provider.Verify(new("mycommand") {
new Command("subcommand") {
new Command("nested")
}
}, log);
}

[Fact]
public async Task DynamicCompletionsGeneration()
{
var dynamicOption = new Option<int>("--dynamic")
{
IsDynamic = true
};
var dynamicArg = new Argument<int>("values")
{
IsDynamic = true
};
Command command = new Command("mycommand")
{
dynamicOption,
dynamicArg
};
await provider.Verify(command, log);
}

[Fact]
public async Task StaticOptionValues()
{
var staticOption = new Option<int>("--verbosity");
staticOption.AcceptOnlyFromAmong("quiet", "minimal", "normal", "detailed", "diagnostic");
Command command = new Command("mycommand")
{
staticOption
};
await provider.Verify(command, log);
}

[Fact]
public async Task BoundedMultiValueOption()
{
var multiOption = new Option<string[]>("--sources")
{
Arity = new ArgumentArity(1, 3)
};
multiOption.AcceptOnlyFromAmong("src1", "src2", "src3", "src4");
Command command = new Command("mycommand")
{
multiOption,
new Command("subcommand")
};
await provider.Verify(command, log);
}

[Fact]
public async Task UnboundedMultiValueOption()
{
var unboundedOption = new Option<string[]>("--items")
{
Arity = ArgumentArity.ZeroOrMore
};
unboundedOption.AcceptOnlyFromAmong("a", "b", "c");
Command command = new Command("mycommand")
{
unboundedOption,
new Option<string>("--name"),
new Command("subcommand")
};
await provider.Verify(command, log);
}

[Fact]
public async Task MixedArityOptions()
{
var singleOption = new Option<string>("--config");
singleOption.AcceptOnlyFromAmong("debug", "release");

var multiOption = new Option<string[]>("--framework", "-f")
{
Arity = new ArgumentArity(1, 3)
};
multiOption.AcceptOnlyFromAmong("net8.0", "net9.0", "net10.0");

var unboundedOption = new Option<string[]>("--sources")
{
Arity = ArgumentArity.OneOrMore
};

Command command = new Command("mycommand")
{
singleOption,
multiOption,
unboundedOption,
new Command("build")
};
await provider.Verify(command, log);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,6 @@ public static void Initialize()

EmptyFiles.FileExtensions.AddTextExtension("ps1");
EmptyFiles.FileExtensions.AddTextExtension("nu");
EmptyFiles.FileExtensions.AddTextExtension("fish");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# fish completions for mycommand

function _mycommand
set -l tokens (commandline -opc)

set -l state 0
set -l i 2
while test $i -le (count $tokens)
set -l word $tokens[$i]
switch $state
case 0
switch $word
case subcommand
set state 1
case --sources
set -l skip_max 3
set -l skipped 0
while test $skipped -lt $skip_max -a (math $i + 1) -le (count $tokens)
set -l next $tokens[(math $i + 1)]
if string match -q -- '-*' $next
break
end
set i (math $i + 1)
set skipped (math $skipped + 1)
end
end
end
set i (math $i + 1)
end

set -l opt_index 0
if test (count $tokens) -ge 2
for j in (seq (count $tokens) -1 2)
if string match -q -- '-*' $tokens[$j]
set opt_index $j
break
end
end
end

if test $opt_index -gt 0
set -l opt $tokens[$opt_index]
set -l values_after (math (count $tokens) - $opt_index)
switch $state
case 0
switch $opt
case --sources
if test $values_after -lt 3
printf '%s\n' 'src1'
printf '%s\n' 'src2'
printf '%s\n' 'src3'
printf '%s\n' 'src4'
return
end
end
end
end

switch $state
case 0
printf '%s\n' 'subcommand'
printf '%s\n' '--sources'
case 1
end
end

complete -c mycommand -f -a '(_mycommand)'
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# fish completions for mycommand

function _mycommand
set -l tokens (commandline -opc)

set -l state 0
set -l i 2
while test $i -le (count $tokens)
set -l word $tokens[$i]
switch $state
case 0
switch $word
case --dynamic
set i (math $i + 1)
end
end
set i (math $i + 1)
end

set -l opt_index 0
if test (count $tokens) -ge 2
for j in (seq (count $tokens) -1 2)
if string match -q -- '-*' $tokens[$j]
set opt_index $j
break
end
end
end

if test $opt_index -gt 0
set -l opt $tokens[$opt_index]
set -l values_after (math (count $tokens) - $opt_index)
switch $state
case 0
switch $opt
case --dynamic
if test $values_after -lt 1
command $tokens[1] complete --position (commandline -C) (commandline -cp) 2>/dev/null
return
end
end
end
end

switch $state
case 0
printf '%s\n' '--dynamic'
command $tokens[1] complete --position (commandline -C) (commandline -cp) 2>/dev/null
end
end

complete -c mycommand -f -a '(_mycommand)'
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# fish completions for mycommand

function _mycommand
set -l tokens (commandline -opc)

set -l state 0
set -l i 2
while test $i -le (count $tokens)
set -l word $tokens[$i]
switch $state
end
set i (math $i + 1)
end

switch $state
case 0
end
end

complete -c mycommand -f -a '(_mycommand)'
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# fish completions for mycommand

function _mycommand
set -l tokens (commandline -opc)

set -l state 0
set -l i 2
while test $i -le (count $tokens)
set -l word $tokens[$i]
switch $state
case 0
switch $word
case build
set state 1
case --config
set i (math $i + 1)
case --framework -f
set -l skip_max 3
set -l skipped 0
while test $skipped -lt $skip_max -a (math $i + 1) -le (count $tokens)
set -l next $tokens[(math $i + 1)]
if string match -q -- '-*' $next
break
end
set i (math $i + 1)
set skipped (math $skipped + 1)
end
case --sources
while test (math $i + 1) -le (count $tokens)
set -l next $tokens[(math $i + 1)]
if string match -q -- '-*' $next
break
end
set i (math $i + 1)
end
end
end
set i (math $i + 1)
end

set -l opt_index 0
if test (count $tokens) -ge 2
for j in (seq (count $tokens) -1 2)
if string match -q -- '-*' $tokens[$j]
set opt_index $j
break
end
end
end

if test $opt_index -gt 0
set -l opt $tokens[$opt_index]
set -l values_after (math (count $tokens) - $opt_index)
switch $state
case 0
switch $opt
case --config
if test $values_after -lt 1
printf '%s\n' 'debug'
printf '%s\n' 'release'
return
end
case --framework -f
if test $values_after -lt 3
printf '%s\n' 'net10.0'
printf '%s\n' 'net8.0'
printf '%s\n' 'net9.0'
return
end
case --sources
return
end
end
end

switch $state
case 0
printf '%s\n' 'build'
printf '%s\n' '--config'
printf '%s\n' '--framework'
printf '%s\n' '-f'
printf '%s\n' '--sources'
case 1
end
end

complete -c mycommand -f -a '(_mycommand)'
Loading
Loading