summaryrefslogtreecommitdiff
path: root/lib/gitlab/slash_commands
diff options
context:
space:
mode:
authorRémy Coutable <remy@rymai.me>2016-08-11 18:51:37 +0200
committerRémy Coutable <remy@rymai.me>2016-08-13 00:06:12 +0200
commit42e30a5012bb3384ee6f275ff058d4c0841776cd (patch)
treed38e8a2736eb6e73559a0d90390722b463c702cd /lib/gitlab/slash_commands
parent65349c22129fcdf2ae0c7103094bbf50ae73db61 (diff)
downloadgitlab-ce-42e30a5012bb3384ee6f275ff058d4c0841776cd.tar.gz
Accept blocks for `.desc` and `.condition` slash commands DSL
Also, pass options as instance variables, making the DSL more user-friendly / natural. Signed-off-by: Rémy Coutable <remy@rymai.me>
Diffstat (limited to 'lib/gitlab/slash_commands')
-rw-r--r--lib/gitlab/slash_commands/dsl.rb111
1 files changed, 73 insertions, 38 deletions
diff --git a/lib/gitlab/slash_commands/dsl.rb b/lib/gitlab/slash_commands/dsl.rb
index 20e1d071d06..3affd6253e9 100644
--- a/lib/gitlab/slash_commands/dsl.rb
+++ b/lib/gitlab/slash_commands/dsl.rb
@@ -8,20 +8,27 @@ module Gitlab
end
module ClassMethods
+ # This method is used to generate the autocompletion menu
+ # It returns no-op slash commands (such as `/cc`)
def command_definitions(opts = {})
@command_definitions.map do |cmd_def|
- next if cmd_def[:cond_lambda] && !cmd_def[:cond_lambda].call(opts)
+ context = OpenStruct.new(opts)
+ next if cmd_def[:cond_block] && !context.instance_exec(&cmd_def[:cond_block])
cmd_def = cmd_def.dup
if cmd_def[:description].present? && cmd_def[:description].respond_to?(:call)
- cmd_def[:description] = cmd_def[:description].call(opts) rescue ''
+ cmd_def[:description] = context.instance_exec(&cmd_def[:description]) rescue ''
end
cmd_def
end.compact
end
+ # This method is used to generate a list of valid commands in the current
+ # context of `opts`.
+ # It excludes no-op slash commands (such as `/cc`).
+ # This list can then be given to `Gitlab::SlashCommands::Extractor`.
def command_names(opts = {})
command_definitions(opts).flat_map do |command_definition|
next if command_definition[:noop]
@@ -30,59 +37,88 @@ module Gitlab
end.compact
end
- # Allows to give a description to the next slash command
- def desc(text)
- @description = text
+ # Allows to give a description to the next slash command.
+ # This description is shown in the autocomplete menu.
+ # It accepts a block that will be evaluated with the context given to
+ # `.command_definitions` or `.command_names`.
+ #
+ # Example:
+ #
+ # desc do
+ # "This is a dynamic description for #{noteable.to_ability_name}"
+ # end
+ # command :command_key do |arguments|
+ # # Awesome code block
+ # end
+ def desc(text = '', &block)
+ @description = block_given? ? block : text
end
- # Allows to define params for the next slash command
+ # Allows to define params for the next slash command.
+ # These params are shown in the autocomplete menu.
+ #
+ # Example:
+ #
+ # params "~label ~label2"
+ # command :command_key do |arguments|
+ # # Awesome code block
+ # end
def params(*params)
@params = params
end
- # Allows to define if a command is a no-op, but should appear in autocomplete
- def noop(noop)
- @noop = noop
- end
-
- # Allows to define if a lambda to conditionally return an action
- def condition(cond_lambda)
- @cond_lambda = cond_lambda
- end
-
- # Registers a new command which is recognizeable
- # from body of email or comment.
+ # Allows to define conditions that must be met in order for the command
+ # to be returned by `.command_names` & `.command_definitions`.
+ # It accepts a block that will be evaluated with the context given to
+ # `.command_definitions`, `.command_names`, and the actual command method.
+ #
# Example:
#
+ # condition do
+ # project.public?
+ # end
# command :command_key do |arguments|
# # Awesome code block
# end
+ def condition(&block)
+ @cond_block = block
+ end
+
+ # Registers a new command which is recognizeable from body of email or
+ # comment.
+ # It accepts aliases and takes a block.
#
+ # Example:
+ #
+ # command :my_command, :alias_for_my_command do |arguments|
+ # # Awesome code block
+ # end
def command(*command_names, &block)
+ opts = command_names.extract_options!
command_name, *aliases = command_names
proxy_method_name = "__#{command_name}__"
- # This proxy method is needed because calling `return` from inside a
- # block/proc, causes a `return` from the enclosing method or lambda,
- # otherwise a LocalJumpError error is raised.
- define_method(proxy_method_name, &block)
+ if block_given?
+ # This proxy method is needed because calling `return` from inside a
+ # block/proc, causes a `return` from the enclosing method or lambda,
+ # otherwise a LocalJumpError error is raised.
+ define_method(proxy_method_name, &block)
- define_method(command_name) do |*args|
- unless @cond_lambda.nil? || @cond_lambda.call(project: project, current_user: current_user, noteable: noteable)
- return
- end
+ define_method(command_name) do |*args|
+ return if @cond_block && !instance_exec(&@cond_block)
- proxy_method = method(proxy_method_name)
+ proxy_method = method(proxy_method_name)
- if proxy_method.arity == -1 || proxy_method.arity == args.size
- instance_exec(*args, &proxy_method)
+ if proxy_method.arity == -1 || proxy_method.arity == args.size
+ instance_exec(*args, &proxy_method)
+ end
end
- end
- private command_name
- aliases.each do |alias_command|
- alias_method alias_command, command_name
- private alias_command
+ private command_name
+ aliases.each do |alias_command|
+ alias_method alias_command, command_name
+ private alias_command
+ end
end
command_definition = {
@@ -91,14 +127,13 @@ module Gitlab
description: @description || '',
params: @params || []
}
- command_definition[:noop] = @noop unless @noop.nil?
- command_definition[:cond_lambda] = @cond_lambda unless @cond_lambda.nil?
+ command_definition[:noop] = opts[:noop] || false
+ command_definition[:cond_block] = @cond_block
@command_definitions << command_definition
@description = nil
@params = nil
- @noop = nil
- @cond_lambda = nil
+ @cond_block = nil
end
end
end