diff --git a/lib/bashly/script/command.rb b/lib/bashly/script/command.rb index 6bcb6728..00d67b00 100644 --- a/lib/bashly/script/command.rb +++ b/lib/bashly/script/command.rb @@ -101,7 +101,7 @@ def commands end # Returns a flat array containing all the commands in this tree. - # This can children + grandchildres (recursive), and may include self + # This includes children + grandchildren (recursive), and may include self def deep_commands(include_self: false) result = [] result << self if include_self diff --git a/lib/bashly/views/command/parse_requirements_case_repeatable.gtx b/lib/bashly/views/command/parse_requirements_case_repeatable.gtx index 89e41fbd..8db30a13 100644 --- a/lib/bashly/views/command/parse_requirements_case_repeatable.gtx +++ b/lib/bashly/views/command/parse_requirements_case_repeatable.gtx @@ -6,6 +6,9 @@ args.each do |arg| > {{ condition }} [[ -z ${args['{{ arg.name }}']+x} ]]; then if arg.repeatable > args['{{ arg.name }}']="$escaped" + if arg.unique + > unique_lookup["{{ arg.name }}:$escaped"]=1 + end > shift if arg.unique > elif [[ -z "${unique_lookup["{{ arg.name }}:$escaped"]:-}" ]]; then diff --git a/spec/bashly/script/command_spec.rb b/spec/bashly/script/command_spec.rb index b376391b..8e701c8c 100644 --- a/spec/bashly/script/command_spec.rb +++ b/spec/bashly/script/command_spec.rb @@ -114,6 +114,13 @@ expect(subject.deep_commands.map(&:full_name)) .to eq ['docker container', 'docker container run', 'docker container stop', 'docker image'] end + + context 'when include_self is true' do + it 'prepends the result with the command itself' do + expect(subject.deep_commands(include_self: true).map(&:full_name)) + .to eq ['docker', 'docker container', 'docker container run', 'docker container stop', 'docker image'] + end + end end describe '#default_arguments' do @@ -333,6 +340,46 @@ end end + describe '#has_unique_args_or_flags?' do + context 'when the command has any args that are unique' do + let(:fixture) { :unique_args } + + it 'returns true' do + expect(subject.has_unique_args_or_flags?).to be true + end + end + + context 'when the command has any flags that are unique' do + let(:fixture) { :unique_flags } + + it 'returns true' do + expect(subject.has_unique_args_or_flags?).to be true + end + end + + context 'when the command has any subcommands with unique args' do + let(:fixture) { :unique_args_deep } + + it 'returns true' do + expect(subject.has_unique_args_or_flags?).to be true + end + end + + context 'when the command has any subcommands with unique flags' do + let(:fixture) { :unique_flags_deep } + + it 'returns true' do + expect(subject.has_unique_args_or_flags?).to be true + end + end + + context 'otherwise' do + it 'returns false' do + expect(subject.has_unique_args_or_flags?).to be false + end + end + end + describe '#load_user_file' do before do FileUtils.mkdir_p 'spec/tmp/src' diff --git a/spec/fixtures/script/commands.yml b/spec/fixtures/script/commands.yml index 02c98a53..0fc3ff10 100644 --- a/spec/fixtures/script/commands.yml +++ b/spec/fixtures/script/commands.yml @@ -398,6 +398,40 @@ - name: target repeatable: true +:unique_args: + name: get + args: + - name: file + repeatable: true + unique: true + +:unique_flags: + name: get + flags: + - short: --file + arg: path + repeatable: true + unique: true + +:unique_args_deep: + name: ftp + commands: + - name: upload + args: + - name: file + repeatable: true + unique: true + +:unique_flags_deep: + name: ftp + commands: + - name: upload + flags: + - long: --file + arg: path + repeatable: true + unique: true + :whitelist: name: cli args: