mirror of
https://github.com/ethauvin/sdkman-for-fish.git
synced 2025-04-25 13:27:10 -07:00
Account for fuzzy completions.
Introduced in Fish 3.1 cf. https://github.com/fish-shell/fish-shell/issues/5467 Needed to make tests less strict. Instead of checking the exact list of matches, we require the expected ones and exclude some others.
This commit is contained in:
parent
0c15f199cd
commit
479fa1e541
4 changed files with 154 additions and 115 deletions
|
@ -88,14 +88,14 @@ complete -c sdk -f -n '__fish_sdkman_no_command' \
|
||||||
-d 'Install new version'
|
-d 'Install new version'
|
||||||
complete -c sdk -f -n '__fish_sdkman_using_command i install' \
|
complete -c sdk -f -n '__fish_sdkman_using_command i install' \
|
||||||
-a "(__fish_sdkman_candidates)"
|
-a "(__fish_sdkman_candidates)"
|
||||||
|
# TODO complete available versions --> issue #4
|
||||||
complete -c sdk -f -n '__fish_sdkman_specifying_candidate i install' \
|
complete -c sdk -f -n '__fish_sdkman_specifying_candidate i install' \
|
||||||
# TODO complete available versions --> #4
|
|
||||||
-a 'a.b.c' \
|
-a 'a.b.c' \
|
||||||
-d "version list unavailable"
|
-d "version list unavailable"
|
||||||
complete -c sdk -f -n '__fish_sdkman_specifying_candidate i install' \
|
complete -c sdk -f -n '__fish_sdkman_specifying_candidate i install' \
|
||||||
-a 'x.y.z' \
|
-a 'x.y.z' \
|
||||||
-d "Add your own; specify path!"
|
-d "Specify path to install custom version."
|
||||||
# Implicit: complete files as fourth parameter
|
# Implicit: complete files as fourth parameter
|
||||||
complete -c sdk -f -n '__fish_sdkman_command_has_enough_parameters 3 i install'
|
complete -c sdk -f -n '__fish_sdkman_command_has_enough_parameters 3 i install'
|
||||||
# block
|
# block
|
||||||
|
|
||||||
|
|
|
@ -14,166 +14,179 @@ Feature: Shell Completion
|
||||||
Scenario Outline: Commands complete
|
Scenario Outline: Commands complete
|
||||||
When the user enters "<cmd>" into the prompt
|
When the user enters "<cmd>" into the prompt
|
||||||
Then completion should propose "<completions>"
|
Then completion should propose "<completions>"
|
||||||
|
But completion should not propose <exclusions>
|
||||||
Examples:
|
Examples:
|
||||||
| cmd | completions |
|
| cmd | completions | exclusions |
|
||||||
| b | b, broadcast |
|
| b | b, broadcast | /^[^b]+$/ |
|
||||||
| c | c, current |
|
| c | c, current | /^[^c]+$/ |
|
||||||
| d | d, default |
|
| d | d, default | /^[^d]+$/ |
|
||||||
| f | flush |
|
| f | flush | /^[^f]+$/ |
|
||||||
| h | h, help |
|
| h | h, help | /^[^h]+$/ |
|
||||||
| i | i, install |
|
| i | i, install | /^[^i]+$/ |
|
||||||
| in | install |
|
| in | install | |
|
||||||
| l | list, ls |
|
| l | list, ls | /^[^l]+$/ |
|
||||||
| o | offline |
|
| o | offline | /^[^o]+$/ |
|
||||||
| r | rm |
|
| r | rm | /^[^r]+$/ |
|
||||||
| s | selfupdate |
|
| s | selfupdate | /^[^s]+$/ |
|
||||||
| u | u, ug, uninstall, update, upgrade, use |
|
| u | u, ug, uninstall, update, upgrade, use | /^[^u]+$/ |
|
||||||
| un | uninstall |
|
| un | uninstall | |
|
||||||
| up | update, upgrade |
|
| up | update, upgrade | |
|
||||||
| us | use |
|
| us | use | |
|
||||||
| v | v, version |
|
| v | v, version | /^[^v]+$/ |
|
||||||
# Currently uncovered; include to catch new upstream commands:
|
# Currently uncovered (except by fuzzy matches);
|
||||||
| a | |
|
# include negatives to prevent accidents:
|
||||||
| e | |
|
| a | | /^a/ |
|
||||||
| g | |
|
| e | | /^e/ |
|
||||||
| j | |
|
| g | | /^g/ |
|
||||||
| k | |
|
| j | | /^j/ |
|
||||||
| m | |
|
| k | | /^k/ |
|
||||||
| n | |
|
| m | | /^m/ |
|
||||||
| p | |
|
| n | | /^n/ |
|
||||||
| q | |
|
| p | | /^p/ |
|
||||||
| t | |
|
| q | | /^q/ |
|
||||||
| w | |
|
| t | | /^t/ |
|
||||||
| x | |
|
| w | | /^w/ |
|
||||||
| y | |
|
| x | | /^x/ |
|
||||||
| z | |
|
| y | | /^y/ |
|
||||||
|
| z | | /^z/ |
|
||||||
|
|
||||||
Scenario Outline: Completion for 'install'
|
Scenario Outline: Completion for 'install'
|
||||||
When the user enters "install <cmd>" into the prompt
|
When the user enters "install <cmd>" into the prompt
|
||||||
Then completion should propose "<completions>"
|
Then completion should propose "<completions>"
|
||||||
|
But completion should not propose <exclusions>
|
||||||
Examples:
|
Examples:
|
||||||
| cmd | completions |
|
| cmd | completions | exclusions |
|
||||||
| an | ant |
|
| an | ant | gradle |
|
||||||
| xyz | |
|
| xyz | | /.*/ |
|
||||||
| 1. | |
|
| 1. | | /.*/ |
|
||||||
| gra | gradle, grails |
|
| gra | gradle, grails | ant |
|
||||||
| grad | gradle |
|
| grad | gradle | ant, grails |
|
||||||
| gradk | |
|
| gradk | | /.*/ |
|
||||||
# | ant 1.10. | 1.10.0, 1.10.1 | # TODO: list installable versions --> issue #4
|
# | ant 1.10. | 1.10.0, 1.10.1 | | # TODO: list installable versions --> issue #4
|
||||||
| ant 1.10.2-mine /tm | /tmp/ |
|
| ant 1.10.2-mine /tm | /tmp/ | /bin |
|
||||||
| 'ant 1.10.2-mine /tmp ' | |
|
| 'ant 1.10.2-mine /tmp ' | | /.*/ |
|
||||||
|
# NB: Excluding wildcard pattern /.*/ expresses "do not offer any completions"
|
||||||
|
|
||||||
Scenario Outline: Completion for 'uninstall'
|
Scenario Outline: Completion for 'uninstall'
|
||||||
When the user enters "uninstall <cmd>" into the prompt
|
When the user enters "uninstall <cmd>" into the prompt
|
||||||
Then completion should propose "<completions>"
|
Then completion should propose "<completions>"
|
||||||
|
But completion should not propose <exclusions>
|
||||||
Examples:
|
Examples:
|
||||||
| cmd | completions |
|
| cmd | completions | exclusions |
|
||||||
| | ant, crash |
|
| | ant, crash | gradle |
|
||||||
| a | ant |
|
| a | ant | gradle |
|
||||||
| j | |
|
| j | | /.*/ |
|
||||||
| 1. | |
|
| 1. | | /.*/ |
|
||||||
| an | ant | # installed
|
| an | ant | gradle, crash | # some installed
|
||||||
| gr | | # none installed
|
| gr | | /.*/ | # none installed
|
||||||
| xyz | | # no such candidate
|
| xyz | | /.*/ | # no such candidate
|
||||||
| 'an ' | | # no such candidate installed
|
| 'an ' | | /.*/ | # no such candidate installed
|
||||||
| 'ant 1' | 1.10.1, 1.9.9 |
|
| 'ant 1' | 1.10.1, 1.9.9 | /^\w+$/ |
|
||||||
| 'ant 1.10.' | 1.10.1 |
|
| 'ant 1.10.' | 1.10.1 | 1.9.9 |
|
||||||
| 'ant 2' | |
|
| 'ant 2' | | /.*/ |
|
||||||
| 'ant 1.10.1 ' | |
|
| 'ant 1.10.1 ' | | /.*/ | # only one version at a time
|
||||||
|
|
||||||
Scenario Outline: Completion for 'list'
|
Scenario Outline: Completion for 'list'
|
||||||
When the user enters "list <cmd>" into the prompt
|
When the user enters "list <cmd>" into the prompt
|
||||||
Then completion should propose "<completions>"
|
Then completion should propose "<completions>"
|
||||||
|
But completion should not propose <exclusions>
|
||||||
Examples:
|
Examples:
|
||||||
| cmd | completions |
|
| cmd | completions | exclusions |
|
||||||
| an | ant |
|
| an | ant | crash |
|
||||||
| xyz | |
|
| xyz | | /.*/ |
|
||||||
| 1. | |
|
| 1. | | /.*/ |
|
||||||
| 'ant ' | |
|
| 'ant ' | | /.*/ |
|
||||||
|
|
||||||
Scenario Outline: Completion for 'use'
|
Scenario Outline: Completion for 'use'
|
||||||
When the user enters "use <cmd>" into the prompt
|
When the user enters "use <cmd>" into the prompt
|
||||||
Then completion should propose "<completions>"
|
Then completion should propose "<completions>"
|
||||||
|
But completion should not propose <exclusions>
|
||||||
Examples:
|
Examples:
|
||||||
| cmd | completions |
|
| cmd | completions | exclusions |
|
||||||
| | ant, crash |
|
| | ant, crash | gradle |
|
||||||
| an | ant |
|
| an | ant | crash, gradle |
|
||||||
| j | |
|
| j | | /.*/ |
|
||||||
| 1. | |
|
| 1. | | /.*/ |
|
||||||
| 'ant ' | 1.10.1, 1.9.9 |
|
| 'ant ' | 1.10.1, 1.9.9 | /^\w+$/ |
|
||||||
| 'ant 1.10.1 ' | |
|
| 'ant 1.10.1 ' | | /.*/ |
|
||||||
|
|
||||||
Scenario Outline: Completion for 'default'
|
Scenario Outline: Completion for 'default'
|
||||||
When the user enters "default <cmd>" into the prompt
|
When the user enters "default <cmd>" into the prompt
|
||||||
Then completion should propose "<completions>"
|
Then completion should propose "<completions>"
|
||||||
|
But completion should not propose <exclusions>
|
||||||
Examples:
|
Examples:
|
||||||
| cmd | completions |
|
| cmd | completions | exclusions |
|
||||||
| | ant, crash |
|
| | ant, crash | gradle |
|
||||||
| an | ant |
|
| an | ant | crash, gradle |
|
||||||
| j | |
|
| j | | /.*/ |
|
||||||
| 1. | |
|
| 1. | | /.*/ |
|
||||||
| 'ant ' | 1.10.1, 1.9.9 |
|
| 'ant ' | 1.10.1, 1.9.9 | /^\w+$/ |
|
||||||
| 'ant 1.10.1 ' | |
|
| 'ant 1.10.1 ' | | /.*/ |
|
||||||
|
|
||||||
Scenario Outline: Completion for 'current'
|
Scenario Outline: Completion for 'current'
|
||||||
When the user enters "current <cmd>" into the prompt
|
When the user enters "current <cmd>" into the prompt
|
||||||
Then completion should propose "<completions>"
|
Then completion should propose "<completions>"
|
||||||
|
But completion should not propose <exclusions>
|
||||||
Examples:
|
Examples:
|
||||||
| cmd | completions |
|
| cmd | completions | exclusions |
|
||||||
| an | ant | # --> installed version
|
| an | ant | gradle | # --> installed version
|
||||||
| ja | java | # --> not installed
|
| gr | gradle | ant | # --> not installed
|
||||||
| xyz | |
|
| xyz | | /.*/ |
|
||||||
| 1. | |
|
| 1. | | /.*/ |
|
||||||
| 'ant ' | |
|
| 'ant ' | | /.*/ |
|
||||||
|
|
||||||
Scenario Outline: Completion for 'upgrade'
|
Scenario Outline: Completion for 'upgrade'
|
||||||
When the user enters "upgrade <cmd>" into the prompt
|
When the user enters "upgrade <cmd>" into the prompt
|
||||||
Then completion should propose "<completions>"
|
Then completion should propose "<completions>"
|
||||||
|
But completion should not propose <exclusions>
|
||||||
Examples:
|
Examples:
|
||||||
| cmd | completions |
|
| cmd | completions | exclusions |
|
||||||
| | ant, crash |
|
| | ant, crash | gradle |
|
||||||
| an | ant |
|
| an | ant | crash, gradle |
|
||||||
| j | |
|
| j | | /.*/ |
|
||||||
| 1. | |
|
| 1. | | /.*/ |
|
||||||
| 'ant ' | |
|
| 'ant ' | | /^\w+$/ |
|
||||||
|
|
||||||
Scenario Outline: Completion for 'offline'
|
Scenario Outline: Completion for 'offline'
|
||||||
When the user enters "offline <cmd>" into the prompt
|
When the user enters "offline <cmd>" into the prompt
|
||||||
Then completion should propose "<completions>"
|
Then completion should propose "<completions>"
|
||||||
|
But completion should not propose <exclusions>
|
||||||
Examples:
|
Examples:
|
||||||
| cmd | completions |
|
| cmd | completions | exclusions |
|
||||||
| | disable, enable |
|
| | disable, enable | /^(?!disable\|enable).*$/ | # NB: \| escaped to get it past Gherkin's parser
|
||||||
| e | enable |
|
| en | enable | /^(?!enable).*$/ |
|
||||||
| d | disable |
|
| di | disable | /^(?!disable).*$/ |
|
||||||
| a | |
|
| an | | /.*/ |
|
||||||
| 'enable ' | |
|
| 'enable ' | | /.*/ |
|
||||||
|
|
||||||
Scenario Outline: Completion for 'selfupdate'
|
Scenario Outline: Completion for 'selfupdate'
|
||||||
When the user enters "selfupdate <cmd>" into the prompt
|
When the user enters "selfupdate <cmd>" into the prompt
|
||||||
Then completion should propose "<completions>"
|
Then completion should propose "<completions>"
|
||||||
|
But completion should not propose <exclusions>
|
||||||
Examples:
|
Examples:
|
||||||
| cmd | completions |
|
| cmd | completions | exclusions |
|
||||||
| | force |
|
| | force | /^(?!force).*$/ |
|
||||||
| f | force |
|
| f | force | /^(?!force).*$/ |
|
||||||
| a | |
|
| a | | /.*/ |
|
||||||
| 'force ' | |
|
| 'force ' | | /.*/ |
|
||||||
|
|
||||||
Scenario Outline: Completion for 'flush'
|
Scenario Outline: Completion for 'flush'
|
||||||
When the user enters "flush <cmd>" into the prompt
|
When the user enters "flush <cmd>" into the prompt
|
||||||
Then completion should propose "<completions>"
|
Then completion should propose "<completions>"
|
||||||
|
But completion should not propose <exclusions>
|
||||||
Examples:
|
Examples:
|
||||||
| cmd | completions |
|
| cmd | completions | exclusions |
|
||||||
| | archives, broadcast, temp |
|
| | archives, broadcast, temp | /^(?!archives\|broadcast\|temp).*$/ |
|
||||||
| b | broadcast |
|
| b | broadcast | /^(?!broadcast).*$/ |
|
||||||
| a | archives |
|
| a | archives | /^(?!archives\|broadcast).*$/ |
|
||||||
| t | temp |
|
| t | temp | /^(?!temp\|broadcast).*$/ |
|
||||||
| x | |
|
| x | | /.*/ |
|
||||||
| 'temp ' | |
|
| 'temp ' | | /.*/ |
|
||||||
|
|
||||||
|
|
||||||
Scenario Outline: Completion for commands without parameters
|
Scenario Outline: Completion for commands without parameters
|
||||||
When the user enters "<cmd>" into the prompt
|
When the user enters "<cmd>" into the prompt
|
||||||
Then completion should propose ""
|
Then completion should not propose /.*/
|
||||||
Examples:
|
Examples:
|
||||||
| cmd |
|
| cmd |
|
||||||
| 'version ' |
|
| 'version ' |
|
||||||
|
|
|
@ -7,12 +7,8 @@ module CompletionHelper
|
||||||
completions = run_fish_command("complete -C\"sdk #{cmd}\"")
|
completions = run_fish_command("complete -C\"sdk #{cmd}\"")
|
||||||
|
|
||||||
completions.split("\n") \
|
completions.split("\n") \
|
||||||
.map { |line| line.split(/\s+/)[0].strip } \
|
.map { |line| line.split(/\s+/)[0].strip }
|
||||||
.sort \
|
|
||||||
.uniq \
|
|
||||||
.join(', ')
|
|
||||||
# TODO: Why do we get duplicates in the Docker container?
|
# TODO: Why do we get duplicates in the Docker container?
|
||||||
# --> remove uniq
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
World CompletionHelper
|
World CompletionHelper
|
||||||
|
@ -21,6 +17,15 @@ When('the user enters {string} into the prompt') do |cmd|
|
||||||
@response = complete(cmd.gsub(/["']/, ''))
|
@response = complete(cmd.gsub(/["']/, ''))
|
||||||
end
|
end
|
||||||
|
|
||||||
Then(/^completion should propose "(.*)"$/) do |completions|
|
Then('completion should propose {string}') do |completions|
|
||||||
expect(@response).to eq(completions)
|
completions = completions.split(',').map(&:strip)
|
||||||
|
expect(@response).to include(*completions)
|
||||||
|
end
|
||||||
|
|
||||||
|
Then('completion should not propose {patterns}') do |exclusions_patterns|
|
||||||
|
exclusions_patterns.each do |p|
|
||||||
|
@response.each do |r|
|
||||||
|
expect(r).not_to match(p)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
21
test/features/support/parameter_types.rb
Normal file
21
test/features/support/parameter_types.rb
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
ParameterType(
|
||||||
|
name: 'patterns',
|
||||||
|
regexp: %r{([^\s]*|'[^']*'|/[^/]*/)(,\s*([^\s]*|'[^']*'|/[^/]*/))*},
|
||||||
|
type: Array,
|
||||||
|
transformer: lambda do |*patterns|
|
||||||
|
patterns \
|
||||||
|
.map(&:strip) \
|
||||||
|
.map do |s|
|
||||||
|
s = if %r{^/(.*)/$} =~ s
|
||||||
|
Regexp.last_match(1)
|
||||||
|
elsif %r{^'(.*)'$} =~ s
|
||||||
|
"^#{Regexp.escape(Regexp.last_match(1))}$"
|
||||||
|
else
|
||||||
|
"^#{Regexp.escape(s)}$"
|
||||||
|
end
|
||||||
|
Regexp.compile(s)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
)
|
Loading…
Add table
Add a link
Reference in a new issue