github_cli 0.5.3 → 0.5.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (94) hide show
  1. data/.travis.yml +14 -3
  2. data/CHANGELOG.md +15 -0
  3. data/Gemfile +1 -1
  4. data/Gemfile.lock +41 -44
  5. data/README.md +77 -14
  6. data/Rakefile +4 -2
  7. data/features/assignee.feature +1 -0
  8. data/features/blob.feature +1 -0
  9. data/features/collaborator.feature +1 -0
  10. data/features/commit.feature +2 -1
  11. data/features/config.feature +27 -28
  12. data/features/event.feature +1 -0
  13. data/features/init.feature +20 -23
  14. data/features/key.feature +5 -5
  15. data/features/milestone.feature +3 -2
  16. data/features/reference.feature +3 -2
  17. data/features/starring.feature +1 -0
  18. data/features/support/hooks.rb +1 -1
  19. data/features/tag.feature +2 -1
  20. data/features/tree.feature +17 -0
  21. data/features/watching.feature +1 -0
  22. data/fixtures/simple_config +3 -5
  23. data/github_cli.gemspec +1 -1
  24. data/lib/github_cli/api.rb +11 -6
  25. data/lib/github_cli/apis/event.rb +8 -8
  26. data/lib/github_cli/apis/label.rb +0 -12
  27. data/lib/github_cli/apis/starring.rb +5 -5
  28. data/lib/github_cli/apis/watching.rb +5 -5
  29. data/lib/github_cli/cli.rb +21 -30
  30. data/lib/github_cli/command.rb +1 -1
  31. data/lib/github_cli/commands/authorizations.rb +28 -2
  32. data/lib/github_cli/commands/collaborators.rb +12 -12
  33. data/lib/github_cli/commands/commits.rb +18 -2
  34. data/lib/github_cli/commands/events.rb +6 -8
  35. data/lib/github_cli/commands/followers.rb +1 -1
  36. data/lib/github_cli/commands/labels.rb +22 -20
  37. data/lib/github_cli/commands/milestones.rb +43 -13
  38. data/lib/github_cli/commands/references.rb +21 -6
  39. data/lib/github_cli/commands/starring.rb +3 -2
  40. data/lib/github_cli/commands/tags.rb +16 -1
  41. data/lib/github_cli/commands/trees.rb +11 -5
  42. data/lib/github_cli/commands/watching.rb +3 -2
  43. data/lib/github_cli/config.rb +15 -6
  44. data/lib/github_cli/dsl.rb +2 -2
  45. data/lib/github_cli/formatter.rb +2 -3
  46. data/lib/github_cli/formatters/csv.rb +29 -14
  47. data/lib/github_cli/formatters/table.rb +2 -3
  48. data/lib/github_cli/man/gcli-config.1 +17 -13
  49. data/lib/github_cli/man/gcli-config.1.txt +23 -21
  50. data/lib/github_cli/vendor/thor/actions/create_link.rb +3 -0
  51. data/lib/github_cli/vendor/thor/actions/directory.rb +29 -10
  52. data/lib/github_cli/vendor/thor/actions/file_manipulation.rb +9 -3
  53. data/lib/github_cli/vendor/thor/actions.rb +18 -18
  54. data/lib/github_cli/vendor/thor/base.rb +97 -89
  55. data/lib/github_cli/vendor/thor/{task.rb → command.rb} +16 -12
  56. data/lib/github_cli/vendor/thor/core_ext/hash_with_indifferent_access.rb +5 -0
  57. data/lib/github_cli/vendor/thor/core_ext/io_binary_read.rb +12 -0
  58. data/lib/github_cli/vendor/thor/error.rb +4 -7
  59. data/lib/github_cli/vendor/thor/group.rb +34 -32
  60. data/lib/github_cli/vendor/thor/invocation.rb +28 -26
  61. data/lib/github_cli/vendor/thor/parser/options.rb +66 -26
  62. data/lib/github_cli/vendor/thor/rake_compat.rb +3 -2
  63. data/lib/github_cli/vendor/thor/runner.rb +21 -20
  64. data/lib/github_cli/vendor/thor/shell/basic.rb +20 -16
  65. data/lib/github_cli/vendor/thor/shell/color.rb +13 -9
  66. data/lib/github_cli/vendor/thor/shell/html.rb +13 -9
  67. data/lib/github_cli/vendor/thor/util.rb +214 -210
  68. data/lib/github_cli/vendor/thor/version.rb +1 -1
  69. data/lib/github_cli/vendor/thor.rb +232 -153
  70. data/lib/github_cli/version.rb +1 -1
  71. data/man/gcli-config.1.ronn +14 -11
  72. data/spec/github_cli/commands/assignees_spec.rb +20 -0
  73. data/spec/github_cli/commands/blobs_spec.rb +21 -0
  74. data/spec/github_cli/commands/collaborators_spec.rb +31 -0
  75. data/spec/github_cli/commands/commits_spec.rb +26 -0
  76. data/spec/github_cli/commands/emails_spec.rb +24 -0
  77. data/spec/github_cli/commands/events_spec.rb +56 -0
  78. data/spec/github_cli/commands/followers_spec.rb +44 -0
  79. data/spec/github_cli/commands/keys_spec.rb +36 -0
  80. data/spec/github_cli/commands/labels_spec.rb +61 -0
  81. data/spec/github_cli/commands/milestones_spec.rb +47 -0
  82. data/spec/github_cli/commands/references_spec.rb +42 -0
  83. data/spec/github_cli/commands/starring_spec.rb +40 -0
  84. data/spec/github_cli/commands/tags_spec.rb +26 -0
  85. data/spec/github_cli/commands/trees_spec.rb +32 -0
  86. data/spec/github_cli/commands/watching_spec.rb +40 -0
  87. data/spec/github_cli/config_spec.rb +109 -116
  88. data/spec/github_cli/util/convert_value_spec.rb +19 -0
  89. data/spec/github_cli/util/convert_values_spec.rb +14 -0
  90. data/spec/github_cli/util_spec.rb +0 -29
  91. metadata +51 -19
  92. data/lib/github_cli/vendor/thor/core_ext/dir_escape.rb +0 -0
  93. data/lib/github_cli/vendor/thor/core_ext/file_binary_read.rb +0 -9
  94. data/lib/github_cli/vendor/thor/empty.txt +0 -0
@@ -1,22 +1,24 @@
1
+ require 'set'
1
2
  require 'thor/base'
2
3
 
3
4
  class Thor
4
5
  class << self
5
- # Sets the default task when thor is executed without an explicit task to be called.
6
+ # Sets the default command when thor is executed without an explicit command to be called.
6
7
  #
7
8
  # ==== Parameters
8
- # meth<Symbol>:: name of the default task
9
- #
10
- def default_task(meth=nil)
11
- case meth
12
- when :none
13
- @default_task = 'help'
14
- when nil
15
- @default_task ||= from_superclass(:default_task, 'help')
16
- else
17
- @default_task = meth.to_s
9
+ # meth<Symbol>:: name of the default command
10
+ #
11
+ def default_command(meth=nil)
12
+ @default_command = case meth
13
+ when :none
14
+ 'help'
15
+ when nil
16
+ @default_command || from_superclass(:default_command, 'help')
17
+ else
18
+ meth.to_s
18
19
  end
19
20
  end
21
+ alias default_task default_command
20
22
 
21
23
  # Registers another Thor subclass as a command.
22
24
  #
@@ -35,7 +37,7 @@ class Thor
35
37
  end
36
38
  end
37
39
 
38
- # Defines the usage and the description of the next task.
40
+ # Defines the usage and the description of the next command.
39
41
  #
40
42
  # ==== Parameters
41
43
  # usage<String>
@@ -44,29 +46,29 @@ class Thor
44
46
  #
45
47
  def desc(usage, description, options={})
46
48
  if options[:for]
47
- task = find_and_refresh_task(options[:for])
48
- task.usage = usage if usage
49
- task.description = description if description
49
+ command = find_and_refresh_command(options[:for])
50
+ command.usage = usage if usage
51
+ command.description = description if description
50
52
  else
51
53
  @usage, @desc, @hide = usage, description, options[:hide] || false
52
54
  end
53
55
  end
54
56
 
55
- # Defines the long description of the next task.
57
+ # Defines the long description of the next command.
56
58
  #
57
59
  # ==== Parameters
58
60
  # long description<String>
59
61
  #
60
62
  def long_desc(long_description, options={})
61
63
  if options[:for]
62
- task = find_and_refresh_task(options[:for])
63
- task.long_description = long_description if long_description
64
+ command = find_and_refresh_command(options[:for])
65
+ command.long_description = long_description if long_description
64
66
  else
65
67
  @long_desc = long_description
66
68
  end
67
69
  end
68
70
 
69
- # Maps an input to a task. If you define:
71
+ # Maps an input to a command. If you define:
70
72
  #
71
73
  # map "-T" => "list"
72
74
  #
@@ -74,10 +76,10 @@ class Thor
74
76
  #
75
77
  # thor -T
76
78
  #
77
- # Will invoke the list task.
79
+ # Will invoke the list command.
78
80
  #
79
81
  # ==== Parameters
80
- # Hash[String|Array => Symbol]:: Maps the string or the strings in the array to the given task.
82
+ # Hash[String|Array => Symbol]:: Maps the string or the strings in the array to the given command.
81
83
  #
82
84
  def map(mappings=nil)
83
85
  @map ||= from_superclass(:map, {})
@@ -95,7 +97,7 @@ class Thor
95
97
  @map
96
98
  end
97
99
 
98
- # Declares the options for the next task to be declared.
100
+ # Declares the options for the next command to be declared.
99
101
  #
100
102
  # ==== Parameters
101
103
  # Hash[Symbol => Object]:: The hash key is the name of the option and the value
@@ -111,15 +113,15 @@ class Thor
111
113
  alias options method_options
112
114
 
113
115
  # Adds an option to the set of method options. If :for is given as option,
114
- # it allows you to change the options from a previous defined task.
116
+ # it allows you to change the options from a previous defined command.
115
117
  #
116
- # def previous_task
118
+ # def previous_command
117
119
  # # magic
118
120
  # end
119
121
  #
120
- # method_option :foo => :bar, :for => :previous_task
122
+ # method_option :foo => :bar, :for => :previous_command
121
123
  #
122
- # def next_task
124
+ # def next_command
123
125
  # # magic
124
126
  # end
125
127
  #
@@ -138,38 +140,38 @@ class Thor
138
140
  #
139
141
  def method_option(name, options={})
140
142
  scope = if options[:for]
141
- find_and_refresh_task(options[:for]).options
143
+ find_and_refresh_command(options[:for]).options
142
144
  else
143
145
  method_options
144
146
  end
145
147
 
146
148
  build_option(name, options, scope)
147
149
  end
148
-
149
150
  alias option method_option
150
151
 
151
- # Prints help information for the given task.
152
+ # Prints help information for the given command.
152
153
  #
153
154
  # ==== Parameters
154
155
  # shell<Thor::Shell>
155
- # task_name<String>
156
+ # command_name<String>
156
157
  #
157
- def task_help(shell, task_name)
158
- meth = normalize_task_name(task_name)
159
- task = all_tasks[meth]
160
- handle_no_task_error(meth) unless task
158
+ def command_help(shell, command_name)
159
+ meth = normalize_command_name(command_name)
160
+ command = all_commands[meth]
161
+ handle_no_command_error(meth) unless command
161
162
 
162
163
  shell.say "Usage:"
163
- shell.say " #{banner(task)}"
164
+ shell.say " #{banner(command)}"
164
165
  shell.say
165
- class_options_help(shell, nil => task.options.map { |_, o| o })
166
- if task.long_description
166
+ class_options_help(shell, nil => command.options.map { |_, o| o })
167
+ if command.long_description
167
168
  shell.say "Description:"
168
- shell.print_wrapped(task.long_description, :indent => 2)
169
+ shell.print_wrapped(command.long_description, :indent => 2)
169
170
  else
170
- shell.say task.description
171
+ shell.say command.description
171
172
  end
172
173
  end
174
+ alias task_help command_help
173
175
 
174
176
  # Prints help information for this class.
175
177
  #
@@ -177,32 +179,34 @@ class Thor
177
179
  # shell<Thor::Shell>
178
180
  #
179
181
  def help(shell, subcommand = false)
180
- list = printable_tasks(true, subcommand)
182
+ list = printable_commands(true, subcommand)
181
183
  Thor::Util.thor_classes_in(self).each do |klass|
182
- list += klass.printable_tasks(false)
184
+ list += klass.printable_commands(false)
183
185
  end
184
186
  list.sort!{ |a,b| a[0] <=> b[0] }
185
187
 
186
- shell.say "Tasks:"
188
+ shell.say "Commands:"
187
189
  shell.print_table(list, :indent => 2, :truncate => true)
188
190
  shell.say
189
191
  class_options_help(shell)
190
192
  end
191
193
 
192
- # Returns tasks ready to be printed.
193
- def printable_tasks(all = true, subcommand = false)
194
- (all ? all_tasks : tasks).map do |_, task|
195
- next if task.hidden?
194
+ # Returns commands ready to be printed.
195
+ def printable_commands(all = true, subcommand = false)
196
+ (all ? all_commands : commands).map do |_, command|
197
+ next if command.hidden?
196
198
  item = []
197
- item << banner(task, false, subcommand)
198
- item << (task.description ? "# #{task.description.gsub(/\s+/m,' ')}" : "")
199
+ item << banner(command, false, subcommand)
200
+ item << (command.description ? "# #{command.description.gsub(/\s+/m,' ')}" : "")
199
201
  item
200
202
  end.compact
201
203
  end
204
+ alias printable_tasks printable_commands
202
205
 
203
206
  def subcommands
204
207
  @subcommands ||= from_superclass(:subcommands, [])
205
208
  end
209
+ alias subtasks subcommands
206
210
 
207
211
  def subcommand(subcommand, subcommand_class)
208
212
  self.subcommands << subcommand.to_s
@@ -210,9 +214,10 @@ class Thor
210
214
 
211
215
  define_method(subcommand) do |*args|
212
216
  args, opts = Thor::Arguments.split(args)
213
- invoke subcommand_class, args, opts
217
+ invoke subcommand_class, args, opts, :invoked_via_subcommand => true, :class_options => options
214
218
  end
215
219
  end
220
+ alias subtask subcommand
216
221
 
217
222
  # Extend check unknown options to accept a hash of conditions.
218
223
  #
@@ -235,10 +240,10 @@ class Thor
235
240
  options = check_unknown_options
236
241
  return false unless options
237
242
 
238
- task = config[:current_task]
239
- return true unless task
243
+ command = config[:current_command]
244
+ return true unless command
240
245
 
241
- name = task.name
246
+ name = command.name
242
247
 
243
248
  if subcommands.include?(name)
244
249
  false
@@ -251,129 +256,203 @@ class Thor
251
256
  end
252
257
  end
253
258
 
254
- protected
255
-
256
- # The method responsible for dispatching given the args.
257
- def dispatch(meth, given_args, given_opts, config) #:nodoc:
258
- meth ||= retrieve_task_name(given_args)
259
- task = all_tasks[normalize_task_name(meth)]
260
-
261
- if task
262
- args, opts = Thor::Options.split(given_args)
263
- else
264
- args, opts = given_args, nil
265
- task = Thor::DynamicTask.new(meth)
266
- end
259
+ # Stop parsing of options as soon as an unknown option or a regular
260
+ # argument is encountered. All remaining arguments are passed to the command.
261
+ # This is useful if you have a command that can receive arbitrary additional
262
+ # options, and where those additional options should not be handled by
263
+ # Thor.
264
+ #
265
+ # ==== Example
266
+ #
267
+ # To better understand how this is useful, let's consider a command that calls
268
+ # an external command. A user may want to pass arbitrary options and
269
+ # arguments to that command. The command itself also accepts some options,
270
+ # which should be handled by Thor.
271
+ #
272
+ # class_option "verbose", :type => :boolean
273
+ # stop_on_unknown_option! :exec
274
+ # check_unknown_options! :except => :exec
275
+ #
276
+ # desc "exec", "Run a shell command"
277
+ # def exec(*args)
278
+ # puts "diagnostic output" if options[:verbose]
279
+ # Kernel.exec(*args)
280
+ # end
281
+ #
282
+ # Here +exec+ can be called with +--verbose+ to get diagnostic output,
283
+ # e.g.:
284
+ #
285
+ # $ thor exec --verbose echo foo
286
+ # diagnostic output
287
+ # foo
288
+ #
289
+ # But if +--verbose+ is given after +echo+, it is passed to +echo+ instead:
290
+ #
291
+ # $ thor exec echo --verbose foo
292
+ # --verbose foo
293
+ #
294
+ # ==== Parameters
295
+ # Symbol ...:: A list of commands that should be affected.
296
+ def stop_on_unknown_option!(*command_names)
297
+ @stop_on_unknown_option ||= Set.new
298
+ @stop_on_unknown_option.merge(command_names)
299
+ end
267
300
 
268
- opts = given_opts || opts || []
269
- config.merge!(:current_task => task, :task_options => task.options)
301
+ def stop_on_unknown_option?(command) #:nodoc:
302
+ !!@stop_on_unknown_option && @stop_on_unknown_option.include?(command.name.to_sym)
303
+ end
270
304
 
271
- instance = new(args, opts, config)
272
- yield instance if block_given?
273
- args = instance.args
274
- trailing = args[Range.new(arguments.size, -1)]
275
- instance.invoke_task(task, trailing || [])
305
+ protected
306
+
307
+ # The method responsible for dispatching given the args.
308
+ def dispatch(meth, given_args, given_opts, config) #:nodoc:
309
+ # There is an edge case when dispatching from a subcommand.
310
+ # A problem occurs invoking the default command. This case occurs
311
+ # when arguments are passed and a default command is defined, and
312
+ # the first given_args does not match the default command.
313
+ # Thor use "help" by default so we skip that case.
314
+ # Note the call to retrieve_command_name. It's called with
315
+ # given_args.dup since that method calls args.shift. Then lookup
316
+ # the command normally. If the first item in given_args is not
317
+ # a command then use the default command. The given_args will be
318
+ # intact later since dup was used.
319
+ if config[:invoked_via_subcommand] && given_args.size >= 1 && default_command != "help" && given_args.first != default_command
320
+ meth ||= retrieve_command_name(given_args.dup)
321
+ command = all_commands[normalize_command_name(meth)]
322
+ command ||= all_commands[normalize_command_name(default_command)]
323
+ else
324
+ meth ||= retrieve_command_name(given_args)
325
+ command = all_commands[normalize_command_name(meth)]
276
326
  end
277
327
 
278
- # The banner for this class. You can customize it if you are invoking the
279
- # thor class by another ways which is not the Thor::Runner. It receives
280
- # the task that is going to be invoked and a boolean which indicates if
281
- # the namespace should be displayed as arguments.
282
- #
283
- def banner(task, namespace = nil, subcommand = false)
284
- "#{basename} #{task.formatted_usage(self, $thor_runner, subcommand)}"
328
+ if command
329
+ args, opts = Thor::Options.split(given_args)
330
+ if stop_on_unknown_option?(command) && !args.empty?
331
+ # given_args starts with a non-option, so we treat everything as
332
+ # ordinary arguments
333
+ args.concat opts
334
+ opts.clear
335
+ end
336
+ else
337
+ args, opts = given_args, nil
338
+ command = Thor::DynamicCommand.new(meth)
285
339
  end
286
340
 
287
- def baseclass #:nodoc:
288
- Thor
289
- end
341
+ opts = given_opts || opts || []
342
+ config.merge!(:current_command => command, :command_options => command.options)
290
343
 
291
- def create_task(meth) #:nodoc:
292
- if @usage && @desc
293
- base_class = @hide ? Thor::HiddenTask : Thor::Task
294
- tasks[meth] = base_class.new(meth, @desc, @long_desc, @usage, method_options)
295
- @usage, @desc, @long_desc, @method_options, @hide = nil
296
- true
297
- elsif self.all_tasks[meth] || meth == "method_missing"
298
- true
299
- else
300
- puts "[WARNING] Attempted to create task #{meth.inspect} without usage or description. " <<
301
- "Call desc if you want this method to be available as task or declare it inside a " <<
302
- "no_tasks{} block. Invoked from #{caller[1].inspect}."
303
- false
304
- end
305
- end
344
+ instance = new(args, opts, config)
345
+ yield instance if block_given?
346
+ args = instance.args
347
+ trailing = args[Range.new(arguments.size, -1)]
348
+ instance.invoke_command(command, trailing || [])
349
+ end
306
350
 
307
- def initialize_added #:nodoc:
308
- class_options.merge!(method_options)
309
- @method_options = nil
310
- end
351
+ # The banner for this class. You can customize it if you are invoking the
352
+ # thor class by another ways which is not the Thor::Runner. It receives
353
+ # the command that is going to be invoked and a boolean which indicates if
354
+ # the namespace should be displayed as arguments.
355
+ #
356
+ def banner(command, namespace = nil, subcommand = false)
357
+ "#{basename} #{command.formatted_usage(self, $thor_runner, subcommand)}"
358
+ end
311
359
 
312
- # Retrieve the task name from given args.
313
- def retrieve_task_name(args) #:nodoc:
314
- meth = args.first.to_s unless args.empty?
315
- if meth && (map[meth] || meth !~ /^\-/)
316
- args.shift
317
- else
318
- nil
319
- end
360
+ def baseclass #:nodoc:
361
+ Thor
362
+ end
363
+
364
+ def create_command(meth) #:nodoc:
365
+ if @usage && @desc
366
+ base_class = @hide ? Thor::HiddenCommand : Thor::Command
367
+ commands[meth] = base_class.new(meth, @desc, @long_desc, @usage, method_options)
368
+ @usage, @desc, @long_desc, @method_options, @hide = nil
369
+ true
370
+ elsif self.all_commands[meth] || meth == "method_missing"
371
+ true
372
+ else
373
+ puts "[WARNING] Attempted to create command #{meth.inspect} without usage or description. " <<
374
+ "Call desc if you want this method to be available as command or declare it inside a " <<
375
+ "no_commands{} block. Invoked from #{caller[1].inspect}."
376
+ false
320
377
  end
378
+ end
379
+ alias create_task create_command
321
380
 
322
- # receives a (possibly nil) task name and returns a name that is in
323
- # the tasks hash. In addition to normalizing aliases, this logic
324
- # will determine if a shortened command is an unambiguous substring of
325
- # a task or alias.
326
- #
327
- # +normalize_task_name+ also converts names like +animal-prison+
328
- # into +animal_prison+.
329
- def normalize_task_name(meth) #:nodoc:
330
- return default_task.to_s.gsub('-', '_') unless meth
331
-
332
- possibilities = find_task_possibilities(meth)
333
- if possibilities.size > 1
334
- raise ArgumentError, "Ambiguous task #{meth} matches [#{possibilities.join(', ')}]"
335
- elsif possibilities.size < 1
336
- meth = meth || default_task
337
- elsif map[meth]
338
- meth = map[meth]
339
- else
340
- meth = possibilities.first
341
- end
381
+ def initialize_added #:nodoc:
382
+ class_options.merge!(method_options)
383
+ @method_options = nil
384
+ end
342
385
 
343
- meth.to_s.gsub('-','_') # treat foo-bar as foo_bar
386
+ # Retrieve the command name from given args.
387
+ def retrieve_command_name(args) #:nodoc:
388
+ meth = args.first.to_s unless args.empty?
389
+ if meth && (map[meth] || meth !~ /^\-/)
390
+ args.shift
391
+ else
392
+ nil
344
393
  end
394
+ end
395
+ alias retrieve_task_name retrieve_command_name
345
396
 
346
- # this is the logic that takes the task name passed in by the user
347
- # and determines whether it is an unambiguous substrings of a task or
348
- # alias name.
349
- def find_task_possibilities(meth)
350
- len = meth.to_s.length
351
- possibilities = all_tasks.merge(map).keys.select { |n| meth == n[0, len] }.sort
352
- unique_possibilities = possibilities.map { |k| map[k] || k }.uniq
353
-
354
- if possibilities.include?(meth)
355
- [meth]
356
- elsif unique_possibilities.size == 1
357
- unique_possibilities
358
- else
359
- possibilities
360
- end
397
+ # receives a (possibly nil) command name and returns a name that is in
398
+ # the commands hash. In addition to normalizing aliases, this logic
399
+ # will determine if a shortened command is an unambiguous substring of
400
+ # a command or alias.
401
+ #
402
+ # +normalize_command_name+ also converts names like +animal-prison+
403
+ # into +animal_prison+.
404
+ def normalize_command_name(meth) #:nodoc:
405
+ return default_command.to_s.gsub('-', '_') unless meth
406
+
407
+ possibilities = find_command_possibilities(meth)
408
+ if possibilities.size > 1
409
+ raise ArgumentError, "Ambiguous command #{meth} matches [#{possibilities.join(', ')}]"
410
+ elsif possibilities.size < 1
411
+ meth = meth || default_command
412
+ elsif map[meth]
413
+ meth = map[meth]
414
+ else
415
+ meth = possibilities.first
361
416
  end
362
417
 
363
- def subcommand_help(cmd)
364
- desc "help [COMMAND]", "Describe subcommands or one specific subcommand"
365
- class_eval <<-RUBY
366
- def help(task = nil, subcommand = true); super; end
367
- RUBY
418
+ meth.to_s.gsub('-','_') # treat foo-bar as foo_bar
419
+ end
420
+ alias normalize_task_name normalize_command_name
421
+
422
+ # this is the logic that takes the command name passed in by the user
423
+ # and determines whether it is an unambiguous substrings of a command or
424
+ # alias name.
425
+ def find_command_possibilities(meth)
426
+ len = meth.to_s.length
427
+ possibilities = all_commands.merge(map).keys.select { |n| meth == n[0, len] }.sort
428
+ unique_possibilities = possibilities.map { |k| map[k] || k }.uniq
429
+
430
+ if possibilities.include?(meth)
431
+ [meth]
432
+ elsif unique_possibilities.size == 1
433
+ unique_possibilities
434
+ else
435
+ possibilities
368
436
  end
437
+ end
438
+ alias find_task_possibilities find_command_possibilities
439
+
440
+ def subcommand_help(cmd)
441
+ desc "help [COMMAND]", "Describe subcommands or one specific subcommand"
442
+ class_eval <<-RUBY
443
+ def help(command = nil, subcommand = true); super; end
444
+ RUBY
445
+ end
446
+ alias subtask_help subcommand_help
447
+
369
448
  end
370
449
 
371
450
  include Thor::Base
372
451
 
373
452
  map HELP_MAPPINGS => :help
374
453
 
375
- desc "help [TASK]", "Describe available tasks or one specific task"
376
- def help(task = nil, subcommand = false)
377
- task ? self.class.task_help(shell, task) : self.class.help(shell, subcommand)
454
+ desc "help [COMMAND]", "Describe available commands or one specific command"
455
+ def help(command = nil, subcommand = false)
456
+ command ? self.class.command_help(shell, command) : self.class.help(shell, subcommand)
378
457
  end
379
458
  end
@@ -1,5 +1,5 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  module GithubCLI
4
- VERSION = "0.5.3"
4
+ VERSION = "0.5.4"
5
5
  end
@@ -3,9 +3,9 @@ gcli-config(1) - Get or set global or local configuration options
3
3
 
4
4
  ## SYNOPSIS
5
5
 
6
- `gcli config` --global|--local name [value]<br>
7
- `gcli config` --global|--local `-l | -list` [name_regex]<br>
8
- `gcli config` --global|--local `-e | --edit`
6
+ `gcli config` [--local] name [value]<br>
7
+ `gcli config` [--local] `-l | -list` [name_regex]<br>
8
+ `gcli config` [--local] `-e | --edit`
9
9
 
10
10
  ## DESCRIPTION
11
11
 
@@ -23,9 +23,6 @@ This command line will fail (with the exit code ret) if:
23
23
 
24
24
  ## OPTIONS
25
25
 
26
- * `--global`:
27
- Writes configuration settings to global ~/.githubrc file inside user home directory.
28
-
29
26
  * `--local`:
30
27
  Writes cofinguration settings inside the current directory to the .githubrc file.
31
28
 
@@ -47,11 +44,17 @@ The configuration file is written in `yaml`. Therfore all formatting rules are d
47
44
 
48
45
  ### VARIABLES
49
46
 
50
- * `auth.token`:
47
+ * `user.token`:
51
48
  Authentication token.
52
49
 
53
- * `auth.basic`:
54
- Basic credentials in the form `login:password`.
50
+ * `user.login`:
51
+ Basic login credentials.
52
+
53
+ * `user.password`:
54
+ Basic password credentials.
55
+
56
+ * `core.adapter`:
57
+ Sets http adapter used to perform requests to GitHub API v3.
55
58
 
56
59
  * `core.endpoint`:
57
60
  Sets host path used as the base for all requests to GitHub API v3.
@@ -63,7 +66,7 @@ The configuration file is written in `yaml`. Therfore all formatting rules are d
63
66
  The command that will be used to paginate output. Can be overridden with PAGER environment variable. less
64
67
 
65
68
  * `core.no-pager`:
66
- false
69
+ Switched off results paging.
67
70
 
68
71
  * `core.no-color`:
69
72
  If set to true disables color output. By default is set to false.
@@ -71,7 +74,7 @@ The configuration file is written in `yaml`. Therfore all formatting rules are d
71
74
  * `core.format`:
72
75
  Determines output formatting. Defaults to table output.
73
76
 
74
- * `core.auto`:
77
+ * `core.auto_pagination`:
75
78
  Automatic pagination of requests to GitHub.
76
79
 
77
80
  * `core.aliases`:
@@ -0,0 +1,20 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe GithubCLI::Commands::Assignees do
6
+ let(:format) { 'table' }
7
+ let(:user) { 'peter-murach' }
8
+ let(:repo) { 'github_cli' }
9
+ let(:api_class) { GithubCLI::Assignee }
10
+
11
+ it "invokes assignee:list" do
12
+ api_class.should_receive(:all).with(user, repo, {}, format)
13
+ subject.invoke "assignee:list", [user, repo]
14
+ end
15
+
16
+ it "invokes assignee:check" do
17
+ api_class.should_receive(:check).with(user, repo, 'git', {}, format)
18
+ subject.invoke "assignee:check", [user, repo, 'git']
19
+ end
20
+ end
@@ -0,0 +1,21 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe GithubCLI::Commands::Blobs do
6
+ let(:format) { 'table' }
7
+ let(:user) { 'peter-murach' }
8
+ let(:repo) { 'github_cli' }
9
+ let(:sha) { '3a0f86fb8db8eea7ccbb9a95f325ddbedfb25e15' }
10
+ let(:api_class) { GithubCLI::Blob }
11
+
12
+ it "invokes blob:get" do
13
+ api_class.should_receive(:get).with(user, repo, sha, {}, format)
14
+ subject.invoke "blob:get", [user, repo, sha]
15
+ end
16
+
17
+ it "invokes blob:create" do
18
+ api_class.should_receive(:create).with(user, repo, {}, format)
19
+ subject.invoke "blob:create", [user, repo]
20
+ end
21
+ end