Module: Etna::CommandOrExecutor

Included in:
Command
Defined in:
lib/etna/command.rb

Overview

Provides the usage DSL and method that includes information about a CommandExecutor or a Command. Commands or CommandExecutors can call ‘usage’ in their definition to provide a specific description to be given about that command. By default, the command name + desc method will be shown.

Defined Under Namespace

Modules: Dsl

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.included(cls) ⇒ Object



145
146
147
# File 'lib/etna/command.rb', line 145

def self.included(cls)
  cls.extend(Dsl)
end

Instance Method Details

#command_nameObject



90
91
92
# File 'lib/etna/command.rb', line 90

def command_name
  self.class.name.snake_case.split(/::/).last
end

#completions_for(parameter) ⇒ Object



82
83
84
85
86
87
88
# File 'lib/etna/command.rb', line 82

def completions_for(parameter)
  if parameter == 'env' || parameter == 'environment' || parameter =~ /_env/
    ['production', 'staging', 'development']
  else
    ["__#{parameter}__"]
  end
end

#descObject

By default, the description of a command maps the execute parameters into CLI descriptions, where as CommandExecutors will display their subcommands.



115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
# File 'lib/etna/command.rb', line 115

def desc
  if respond_to?(:execute)
    method(:execute).parameters.map do |type, name|
      name = "..." if name.nil?

      case type
      when :req
        "<#{name}>"
      when :opt
        "[<#{name}>]"
      when :rest
        "<#{name}>..."
      when :keyrest
        "[flags...]"
      when :key
        flag = "--#{name.to_s.gsub('_', '-')}"
        if self.class.boolean_flags.include?(flag)
          "[#{flag}]"
        else
          "[#{flag} <#{name}>]"
        end
      else
        raise "Invalid command execute argument specification #{type}, unsure how to format description."
      end
    end.join(' ')
  elsif respond_to?(:subcommands)
    '<command> <args>...'
  end
end

#flag_argspecObject



98
99
100
# File 'lib/etna/command.rb', line 98

def flag_argspec
  @argspec ||= []
end

#flag_as_parameter(flag) ⇒ Object



44
45
46
# File 'lib/etna/command.rb', line 44

def flag_as_parameter(flag)
  flag.gsub('--', '').gsub('-', '_')
end

#parse_flags(*args) ⇒ Object



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
77
78
79
80
# File 'lib/etna/command.rb', line 48

def parse_flags(*args)
  new_args = []
  flags = {}
  found_non_flag = false

  until args.empty?
    next_arg = args.shift

    unless next_arg.start_with? '--'
      new_args << next_arg
      found_non_flag = true
      next
    end

    arg_name = flag_as_parameter(next_arg).to_sym

    if self.class.boolean_flags.include?(next_arg)
      flags[arg_name] = true
    elsif self.class.string_flags.include?(next_arg)
      if args.empty?
        raise "flag #{next_arg} requires an argument"
      else
        flags[arg_name] = args.shift
      end
    elsif !found_non_flag
      raise "#{program_name} does not recognize flag #{next_arg}"
    else
      new_args << next_arg
    end
  end

  [flags, new_args]
end

#program_nameObject

Program name is used to compose the usage display. The top level executor will just assume the running process’s bin name, while other executors will use the ‘command name’ of the Command / Exectuor (class name derived) and whatever program_name exists for its parent scope.



105
106
107
108
109
110
111
# File 'lib/etna/command.rb', line 105

def program_name
  if parent.nil? || !parent.respond_to?(:program_name)
    $PROGRAM_NAME
  else
    parent.program_name + " " + command_name
  end
end

#usageObject



94
95
96
# File 'lib/etna/command.rb', line 94

def usage
  "  #{"%-45s" % command_name}#{desc}"
end