Class: Duse::CLI::Command

Inherits:
Object
  • Object
show all
Extended by:
Parser
Defined in:
lib/duse/cli/command.rb

Direct Known Subclasses

ApiCommand, Config, Help, MetaCommand, Version

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Parser

new, on, on_initialize

Constructor Details

#initialize(options = {}) ⇒ Command

Returns a new instance of Command.



27
28
29
30
31
32
33
34
35
# File 'lib/duse/cli/command.rb', line 27

def initialize(options = {})
  self.output      = $stdout
  self.input       = $stdin
  self.arguments ||= []
  options.each do |key, value|
    public_send("#{key}=", value) if respond_to? "#{key}="
  end
  @arguments ||= []
end

Instance Attribute Details

#argumentsObject

Returns the value of attribute arguments.



9
10
11
# File 'lib/duse/cli/command.rb', line 9

def arguments
  @arguments
end

#force_interactiveObject

Returns the value of attribute force_interactive.



9
10
11
# File 'lib/duse/cli/command.rb', line 9

def force_interactive
  @force_interactive
end

#inputObject

Returns the value of attribute input.



8
9
10
# File 'lib/duse/cli/command.rb', line 8

def input
  @input
end

#outputObject

Returns the value of attribute output.



8
9
10
# File 'lib/duse/cli/command.rb', line 8

def output
  @output
end

Class Method Details

.abstractObject



74
75
76
# File 'lib/duse/cli/command.rb', line 74

def self.abstract
  @@abstract << self
end

.abstract?Boolean

Returns:

  • (Boolean)


70
71
72
# File 'lib/duse/cli/command.rb', line 70

def self.abstract?
  @@abstract.include? self
end

.command_nameObject



158
159
160
161
# File 'lib/duse/cli/command.rb', line 158

def self.command_name
  return full_command.sub(super_command.full_command, '').strip.sub(' ', '-') if has_super_command?
  full_command
end

.description(description = nil) ⇒ Object



167
168
169
170
# File 'lib/duse/cli/command.rb', line 167

def self.description(description = nil)
  @description = description if description
  @description ||= ""
end

.full_commandObject



150
151
152
# File 'lib/duse/cli/command.rb', line 150

def self.full_command
  name[/[^:]*$/].split(/(?=[A-Z])/).map(&:downcase).join(' ')
end

.has_subcommands?Boolean

Returns:

  • (Boolean)


105
106
107
# File 'lib/duse/cli/command.rb', line 105

def self.has_subcommands?
  !@subcommands.empty?
end

.has_super_command?Boolean

Returns:

  • (Boolean)


86
87
88
# File 'lib/duse/cli/command.rb', line 86

def self.has_super_command?
  !@super_command.nil?
end

.skip(*names) ⇒ Object



78
79
80
# File 'lib/duse/cli/command.rb', line 78

def self.skip(*names)
  names.each { |n| define_method(n) {} }
end

.subcommand(command) ⇒ Object



94
95
96
97
98
99
# File 'lib/duse/cli/command.rb', line 94

def self.subcommand(command)
  return nil if command.nil?
  return subcommands.select { |sc| sc.command_name == command }.first if command.is_a? String
  command.super_command = self
  subcommands << command
end

.subcommandsObject



101
102
103
# File 'lib/duse/cli/command.rb', line 101

def self.subcommands
  @subcommands ||= []
end

.super_commandObject



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

def self.super_command
  @super_command
end

.super_command=(command_class) ⇒ Object



82
83
84
# File 'lib/duse/cli/command.rb', line 82

def self.super_command=(command_class)
  @super_command = command_class
end

Instance Method Details

#check_arity(method, *args) ⇒ Object



206
207
208
209
210
211
212
213
# File 'lib/duse/cli/command.rb', line 206

def check_arity(method, *args)
  return unless method.respond_to? :parameters
  method.parameters.each do |type, name|
    return if type == :rest
    wrong_args("few") unless args.shift or type == :opt or type == :block
  end
  wrong_args("many") if args.any?
end

#color(line, style) ⇒ Object



136
137
138
139
# File 'lib/duse/cli/command.rb', line 136

def color(line, style)
  return line.to_s unless interactive?
  terminal.color(line || '???', Array(style).map(&:to_sym))
end

#command_nameObject



163
164
165
# File 'lib/duse/cli/command.rb', line 163

def command_name
  self.class.command_name
end

#configObject



109
110
111
# File 'lib/duse/cli/command.rb', line 109

def config
  CLI.config
end

#error(message, &block) ⇒ Object



120
121
122
123
# File 'lib/duse/cli/command.rb', line 120

def error(message, &block)
  warn(message, &block)
  exit 1
end

#executeObject



43
44
45
46
47
48
49
# File 'lib/duse/cli/command.rb', line 43

def execute
  check_arity(method(:run), *arguments)
  setup
  run *arguments
rescue Interrupt
  say "\naborted!"
end

#format(data, format = nil, style = nil) ⇒ Object



221
222
223
224
225
226
227
# File 'lib/duse/cli/command.rb', line 221

def format(data, format = nil, style = nil)
  style ||= :important
  data = format % color(data, style) if format and interactive?
  data = data.gsub(/<\[\[/, '<%=').gsub(/\]\]>/, '%>')
  data.encode! 'utf-8' if data.respond_to? :encode!
  data
end

#full_commandObject



154
155
156
# File 'lib/duse/cli/command.rb', line 154

def full_command
  self.class.full_command
end

#help(info = "") ⇒ Object



172
173
174
175
176
# File 'lib/duse/cli/command.rb', line 172

def help(info = "")
  return help_subcommands unless self.class.subcommands.empty?
  parser.banner = usage
  self.class.description.sub(/./) { |c| c.upcase } + ".\n\n" + info + parser.to_s
end

#help_subcommandsObject



178
179
180
181
182
183
184
# File 'lib/duse/cli/command.rb', line 178

def help_subcommands
  result = "#{self.class.description}\n\n"
  result << "Usage: duse #{full_command} COMMAND ...\n\nAvailable commands:\n\n"
  self.class.subcommands.each { |command_class| result << "\t#{color(command_class.command_name, :command).ljust(22)} #{color(command_class.description, :info)}\n" }
  result << "\nrun `duse help #{full_command} COMMAND` for more infos"
  result
end

#interactive?(io = output) ⇒ Boolean

Returns:

  • (Boolean)


141
142
143
144
# File 'lib/duse/cli/command.rb', line 141

def interactive?(io = output)
  return io.tty? if force_interactive.nil?
  force_interactive
end

#parse(args) ⇒ Object



37
38
39
40
41
# File 'lib/duse/cli/command.rb', line 37

def parse(args)
  arguments.concat(parser.parse(args))
rescue OptionParser::ParseError => e
  error e.message
end

#say(data, format = nil, style = nil) ⇒ Object



146
147
148
# File 'lib/duse/cli/command.rb', line 146

def say(data, format = nil, style = nil)
  terminal.say format(data, format, style)
end

#setupObject



51
52
# File 'lib/duse/cli/command.rb', line 51

def setup
end

#success(line) ⇒ Object



125
126
127
# File 'lib/duse/cli/command.rb', line 125

def success(line)
  say color(line, :success) if interactive?
end

#terminalObject



64
65
66
# File 'lib/duse/cli/command.rb', line 64

def terminal
  @terminal ||= HighLine.new(input, output)
end

#usageObject



186
187
188
# File 'lib/duse/cli/command.rb', line 186

def usage
  "Usage: " << color(usage_for(full_command, :run), :command)
end

#usage_for(prefix, method) ⇒ Object



190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
# File 'lib/duse/cli/command.rb', line 190

def usage_for(prefix, method)
  usage = "duse #{prefix}"
  method = method(method)
  if method.respond_to? :parameters
    method.parameters.each do |type, name|
      name = name.upcase
      name = "[#{name}]"   if type == :opt
      name = "[#{name}..]" if type == :rest
      usage << " #{name}"
    end
  elsif method.arity != 0
    usage << " ..."
  end
  usage << " [OPTIONS]"
end

#warn(message) ⇒ Object



113
114
115
116
117
118
# File 'lib/duse/cli/command.rb', line 113

def warn(message)
  write_to($stderr) do
    say color(message, :error)
    yield if block_given?
  end
end

#write_to(io) ⇒ Object



129
130
131
132
133
134
# File 'lib/duse/cli/command.rb', line 129

def write_to(io)
  io_was, self.output = output, io
  yield
ensure
  self.output = io_was if io_was
end

#wrong_args(quantity) ⇒ Object



215
216
217
218
219
# File 'lib/duse/cli/command.rb', line 215

def wrong_args(quantity)
  error "too #{quantity} arguments" do
    say help
  end
end