summaryrefslogtreecommitdiff
path: root/lib/gitlab/slash_commands/dsl.rb
blob: 3ded4109f2e780eaf0a6b54911b7f49801331c0c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
module Gitlab
  module SlashCommands
    module Dsl
      extend ActiveSupport::Concern

      included do
        @command_definitions = []
      end

      module ClassMethods
        def command_definitions
          @command_definitions
        end

        def command_names
          command_definitions.flat_map do |command_definition|
            [command_definition[:name], command_definition[:aliases]].flatten
          end
        end

        # Allows to give a description to the next slash command
        def desc(text)
          @description = text
        end

        # Allows to define params for the next slash command
        def params(*params)
          @params = params
        end

        # Registers a new command which is recognizeable
        # from body of email or comment.
        # Example:
        #
        #   command :command_key do |arguments|
        #     # Awesome code block
        #   end
        #
        def command(*command_names, &block)
          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)

          define_method(command_name) do |*args|
            proxy_method = method(proxy_method_name)

            if proxy_method.arity == -1 || proxy_method.arity == args.size
              instance_exec(*args, &proxy_method)
            end
          end

          private command_name
          aliases.each do |alias_command|
            alias_method alias_command, command_name
            private alias_command
          end

          command_definition = {
            name: command_name,
            aliases: aliases,
            description: @description || '',
            params: @params || []
          }
          @command_definitions << command_definition

          @description = nil
          @params = nil
        end
      end
    end
  end
end