GitLab steht aufgrund wichtiger Wartungsarbeiten am Montag, den 8. März, zwischen 17:00 und 19:00 Uhr nicht zur Verfügung.

Commit 2703330a authored by Douwe Maan's avatar Douwe Maan

Fix behavior around commands with optional arguments

parent 6f2f2a6b
...@@ -18,11 +18,11 @@ def execute(content, issuable) ...@@ -18,11 +18,11 @@ def execute(content, issuable)
content, commands = extractor.extract_commands(content, opts) content, commands = extractor.extract_commands(content, opts)
commands.each do |name, args| commands.each do |name, arg|
definition = self.class.command_definitions_by_name[name.to_sym] definition = self.class.command_definitions_by_name[name.to_sym]
next unless definition next unless definition
definition.execute(self, opts, args) definition.execute(self, opts, arg)
end end
[content, @updates] [content, @updates]
......
...@@ -28,13 +28,14 @@ def available?(opts) ...@@ -28,13 +28,14 @@ def available?(opts)
context.instance_exec(&condition_block) context.instance_exec(&condition_block)
end end
def execute(context, opts, args) def execute(context, opts, arg)
return if noop? || !available?(opts) return if noop? || !available?(opts)
block_arity = action_block.arity if arg.present?
return unless (args.present? && block_arity == 1) || (args.blank? && block_arity <= 0) context.instance_exec(arg, &action_block)
elsif action_block.arity == 0
context.instance_exec(args, &action_block) context.instance_exec(&action_block)
end
end end
def to_h(opts) def to_h(opts)
......
...@@ -39,7 +39,7 @@ def extract_commands(content, opts = {}) ...@@ -39,7 +39,7 @@ def extract_commands(content, opts = {})
content.delete!("\r") content.delete!("\r")
content.gsub!(commands_regex(opts)) do content.gsub!(commands_regex(opts)) do
if $~[:cmd] if $~[:cmd]
commands << [$~[:cmd], $~[:args]].reject(&:blank?) commands << [$~[:cmd], $~[:arg]].reject(&:blank?)
'' ''
else else
$~[0] $~[0]
...@@ -50,13 +50,14 @@ def extract_commands(content, opts = {}) ...@@ -50,13 +50,14 @@ def extract_commands(content, opts = {})
end end
private private
# Builds a regular expression to match known commands. # Builds a regular expression to match known commands.
# First match group captures the command name and # First match group captures the command name and
# second match group captures its arguments. # second match group captures its arguments.
# #
# It looks something like: # It looks something like:
# #
# /^\/(?<cmd>close|reopen|...)(?:( |$))(?<args>[^\/\n]*)(?:\n|$)/ # /^\/(?<cmd>close|reopen|...)(?:( |$))(?<arg>[^\/\n]*)(?:\n|$)/
def commands_regex(opts) def commands_regex(opts)
names = command_names(opts).map(&:to_s) names = command_names(opts).map(&:to_s)
...@@ -64,7 +65,7 @@ def commands_regex(opts) ...@@ -64,7 +65,7 @@ def commands_regex(opts)
(?<code> (?<code>
# Code blocks: # Code blocks:
# ``` # ```
# Anything, including `/cmd args` which are ignored by this filter # Anything, including `/cmd arg` which are ignored by this filter
# ``` # ```
^``` ^```
...@@ -75,7 +76,7 @@ def commands_regex(opts) ...@@ -75,7 +76,7 @@ def commands_regex(opts)
(?<html> (?<html>
# HTML block: # HTML block:
# <tag> # <tag>
# Anything, including `/cmd args` which are ignored by this filter # Anything, including `/cmd arg` which are ignored by this filter
# </tag> # </tag>
^<[^>]+?>\n ^<[^>]+?>\n
...@@ -86,7 +87,7 @@ def commands_regex(opts) ...@@ -86,7 +87,7 @@ def commands_regex(opts)
(?<html> (?<html>
# Quote block: # Quote block:
# >>> # >>>
# Anything, including `/cmd args` which are ignored by this filter # Anything, including `/cmd arg` which are ignored by this filter
# >>> # >>>
^>>> ^>>>
...@@ -102,7 +103,7 @@ def commands_regex(opts) ...@@ -102,7 +103,7 @@ def commands_regex(opts)
(?<cmd>#{Regexp.union(names)}) (?<cmd>#{Regexp.union(names)})
(?: (?:
[ ] [ ]
(?<args>[^\/\n]*) (?<arg>[^\/\n]*)
)? )?
(?:\n|$) (?:\n|$)
) )
......
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
describe "#noop?" do describe "#noop?" do
context "when the command has an action block" do context "when the command has an action block" do
before do before do
subject.action_block = -> { } subject.action_block = proc { }
end end
it "returns false" do it "returns false" do
...@@ -44,7 +44,7 @@ ...@@ -44,7 +44,7 @@
context "when the command has a condition block" do context "when the command has a condition block" do
before do before do
subject.condition_block = -> { go } subject.condition_block = proc { go }
end end
context "when the condition block returns true" do context "when the condition block returns true" do
...@@ -78,7 +78,7 @@ ...@@ -78,7 +78,7 @@
it "doesn't execute the command" do it "doesn't execute the command" do
expect(context).not_to receive(:instance_exec) expect(context).not_to receive(:instance_exec)
subject.execute(context, {}) subject.execute(context, {}, nil)
expect(context.run).to be false expect(context.run).to be false
end end
...@@ -86,52 +86,82 @@ ...@@ -86,52 +86,82 @@
context "when the command is not a noop" do context "when the command is not a noop" do
before do before do
subject.action_block = -> { self.run = true } subject.action_block = proc { self.run = true }
end end
context "when the command is not available" do context "when the command is not available" do
before do before do
subject.condition_block = -> { false } subject.condition_block = proc { false }
end end
it "doesn't execute the command" do it "doesn't execute the command" do
subject.execute(context, {}) subject.execute(context, {}, nil)
expect(context.run).to be false expect(context.run).to be false
end end
end end
context "when the command is available" do context "when the command is available" do
context "when the command has an exact number of arguments" do context "when the commnd has no arguments" do
before do before do
subject.action_block = ->(arg) { self.run = arg } subject.action_block = proc { self.run = true }
end end
context "when the command is provided a wrong number of arguments" do context "when the command is provided an argument" do
it "doesn't execute the command" do it "executes the command" do
subject.execute(context, {}, true, true) subject.execute(context, {}, true)
expect(context.run).to be false expect(context.run).to be true
end end
end end
context "when the command is provided the right number of arguments" do context "when the command is not provided an argument" do
it "executes the command" do
subject.execute(context, {}, nil)
expect(context.run).to be true
end
end
end
context "when the command has 1 required argument" do
before do
subject.action_block = ->(arg) { self.run = arg }
end
context "when the command is provided an argument" do
it "executes the command" do it "executes the command" do
subject.execute(context, {}, true) subject.execute(context, {}, true)
expect(context.run).to be true expect(context.run).to be true
end end
end end
context "when the command is not provided an argument" do
it "doesn't execute the command" do
subject.execute(context, {}, nil)
expect(context.run).to be false
end
end
end end
context "when the command has a variable number of arguments" do context "when the command has 1 optional argument" do
before do before do
subject.action_block = ->(*args) { self.run = args.first } subject.action_block = proc { |arg = nil| self.run = arg || true }
end
context "when the command is provided an argument" do
it "executes the command" do
subject.execute(context, {}, true)
expect(context.run).to be true
end
end end
context "when the command is provided any number of arguments" do context "when the command is not provided an argument" do
it "executes the command" do it "executes the command" do
subject.execute(context, {}, true, true) subject.execute(context, {}, nil)
expect(context.run).to be true expect(context.run).to be true
end end
......
...@@ -31,16 +31,12 @@ ...@@ -31,16 +31,12 @@
command :cond_action do |arg| command :cond_action do |arg|
arg arg
end end
command :wildcard do |*args|
args
end
end end
end end
describe '.command_definitions' do describe '.command_definitions' do
it 'returns an array with commands definitions' do it 'returns an array with commands definitions' do
no_args_def, one_arg_def, two_args_def, cc_def, cond_action_def, wildcard_def = DummyClass.command_definitions no_args_def, one_arg_def, two_args_def, cc_def, cond_action_def = DummyClass.command_definitions
expect(no_args_def.name).to eq(:no_args) expect(no_args_def.name).to eq(:no_args)
expect(no_args_def.aliases).to eq([:none]) expect(no_args_def.aliases).to eq([:none])
...@@ -76,13 +72,6 @@ ...@@ -76,13 +72,6 @@
expect(cond_action_def.params).to eq([]) expect(cond_action_def.params).to eq([])
expect(cond_action_def.condition_block).to be_a_kind_of(Proc) expect(cond_action_def.condition_block).to be_a_kind_of(Proc)
expect(cond_action_def.action_block).to be_a_kind_of(Proc) expect(cond_action_def.action_block).to be_a_kind_of(Proc)
expect(wildcard_def.name).to eq(:wildcard)
expect(wildcard_def.aliases).to eq([])
expect(wildcard_def.description).to eq('')
expect(wildcard_def.params).to eq([])
expect(wildcard_def.condition_block).to be_nil
expect(wildcard_def.action_block).to be_a_kind_of(Proc)
end end
end end
end end
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment