cli-template 3.2.0 → 3.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ebf247e389131d796f851f63170b372317765995899ac852510ae2e08d6807b7
4
- data.tar.gz: c6c607ea96e976aaa38791f1d4a16a3630f6ae2ef3a548093f6305cb69a9fba1
3
+ metadata.gz: 17cbbe8fe23b402c5d7186db07b36efb7558de259644e26b16bdcec71aef8e2d
4
+ data.tar.gz: 4786c899d4991565425a177028c0392af5d99d89578ebe16266f8b9d21eeb0a9
5
5
  SHA512:
6
- metadata.gz: ba5b206f2bfd776d993e00bc78ff39b539a70505082992af8935985ae76b6b67d17fd92913c9a997f460bd6578562b7b87c78b3ccaa5a031492842f5afe095ac
7
- data.tar.gz: e23520496b7e64d9c6563c9dd9a5b57ab921f5c069ea25a6c314047f4084785e96dfa6a81aa66401f8443414f84fbf79f56ec8f6ad6e516d8142be2033944eb3
6
+ metadata.gz: 62acac1019b70985dbcc86c45249ecd8d7ead6730780b8b90379981ae2a244c1716d3c93eb1fb6f23d5bc8057517fc7d4062548b5be633427794636ab61c0f59
7
+ data.tar.gz: 0a9b85c698aabcde90a88f8b47cb400dfee8ced3761d926ea7201752a287e487cf99630af0fd544bd8037e3cb4f49c4663b95897508bd86560b21b4865822d1e
@@ -3,6 +3,10 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  This project *tries* to adhere to [Semantic Versioning](http://semver.org/), even before v1.0.
5
5
 
6
+ ## [3.3.0]
7
+ - fix completer for thor group and use public_instance_methods(false)
8
+ - fix shared new options for thor group and cli
9
+
6
10
  ## [3.2.0]
7
11
  - Merge pull request #2 from tongueroo/basic: the deafult template is a basic Thor CLI instead of the colon_namespaces one.
8
12
  - cache eager_load call and handle Thor::InvocationError
@@ -8,7 +8,6 @@ Gem::Specification.new do |spec|
8
8
  spec.version = CliTemplate::VERSION
9
9
  spec.authors = ["Tung Nguyen"]
10
10
  spec.email = ["tongueroo@gmail.com"]
11
- spec.description = %q{Generate a CLI tool quickly}
12
11
  spec.summary = %q{Generate a CLI tool quickly}
13
12
  spec.homepage = "https://gitub.com/tongueroo/cli-template"
14
13
  spec.license = "MIT"
@@ -8,5 +8,5 @@ module CliTemplate
8
8
  autoload :Version, 'cli-template/version'
9
9
  autoload :Sequence, 'cli-template/sequence'
10
10
  autoload :New, 'cli-template/new'
11
- autoload :Helpers, 'cli-template/helpers'
11
+ autoload :Helper, 'cli-template/helper'
12
12
  end
@@ -1,4 +1,4 @@
1
- module CliTemplate::Helpers
1
+ module CliTemplate::Helper
2
2
  def project_class_name
3
3
  project_name.underscore.camelize
4
4
  end
@@ -5,6 +5,7 @@ module CliTemplate
5
5
  # Ugly, but when the class_option is only defined in the Thor::Group class
6
6
  # it doesnt show up with cli-template new help :(
7
7
  # If anyone knows how to fix this let me know.
8
+ # Also options from the cli can be pass through to here
8
9
  def self.cli_options
9
10
  [
10
11
  [:repo, desc: "GitHub repo to use. Format: user/repo"],
@@ -6,7 +6,7 @@ require 'bundler'
6
6
 
7
7
  class CliTemplate::Sequence < Thor::Group
8
8
  include Thor::Actions
9
- include CliTemplate::Helpers
9
+ include CliTemplate::Helper
10
10
 
11
11
  def self.source_root
12
12
  template = ENV['TEMPLATE'] || 'default'
@@ -1,3 +1,3 @@
1
1
  module CliTemplate
2
- VERSION = "3.2.0"
2
+ VERSION = "3.3.0"
3
3
  end
@@ -8,9 +8,9 @@ Gem::Specification.new do |spec|
8
8
  spec.version = <%= project_class_name %>::VERSION
9
9
  spec.authors = ["Tung Nguyen"]
10
10
  spec.email = ["tongueroo@gmail.com"]
11
- spec.description = "Generated with cli-template tool. Please write a gem description"
12
11
  spec.summary = "Generated with cli-template tool. Please write a gem summary"
13
- spec.homepage = ""
12
+ spec.description = "Generated with cli-template tool. Write a longer description or delete this line."
13
+ spec.homepage = "Generated with cli-template tool. Put your gem's website or public repo URL here."
14
14
  spec.license = "MIT"
15
15
 
16
16
  spec.files = `git ls-files`.split($/)
@@ -9,7 +9,7 @@ require "pp"
9
9
  root = File.expand_path("../../", __FILE__)
10
10
  require "#{root}/lib/<%= project_name %>"
11
11
 
12
- module Helpers
12
+ module Helper
13
13
  def execute(cmd)
14
14
  puts "Running: #{cmd}" if show_command?
15
15
  out = `#{cmd}`
@@ -25,5 +25,5 @@ module Helpers
25
25
  end
26
26
 
27
27
  RSpec.configure do |c|
28
- c.include Helpers
28
+ c.include Helper
29
29
  end
@@ -8,9 +8,9 @@ Gem::Specification.new do |spec|
8
8
  spec.version = <%= project_class_name %>::VERSION
9
9
  spec.authors = ["Tung Nguyen"]
10
10
  spec.email = ["tongueroo@gmail.com"]
11
- spec.description = "Generated with cli-template tool. Please write a gem description"
12
11
  spec.summary = "Generated with cli-template tool. Please write a gem summary"
13
- spec.homepage = ""
12
+ spec.description = "Generated with cli-template tool. Write a longer description or delete this line."
13
+ spec.homepage = "Generated with cli-template tool. Put your gem's website or public repo URL here."
14
14
  spec.license = "MIT"
15
15
 
16
16
  spec.files = `git ls-files`.split($/)
@@ -1,59 +1,74 @@
1
- # Code Explanation. This is mainly focused on the run method.
2
- #
3
- # There are 3 main branches of logic for completion:
4
- #
5
- # 1. top-level commands - when there are zero completed words
6
- # 2. params completion - when a command has some required params
7
- # 3. options completion - when we have finished auto-completing the top-level command and required params, the rest of the completion words will be options
8
- #
9
- # Terms:
10
- #
11
- # params - these are params in the command itself. Example: for the method `scale(service, count)` the params would be `service, count`.
12
- # options - these are cli options flags. Examples: --noop, --verbose
13
- #
14
- # When we are done processing method params, the completion will be only options. When the detected params size is greater than the arity we are have finished auto-completing the parameters in the method declaration. For example, say you had a method for a CLI command with the following form:
15
- #
16
- # scale(service, count) = arity of 2
17
- #
18
- # <%= project_name %> scale service count [TAB] # there are 3 params including the "scale" command
19
- #
20
- # So the completion will be something like:
21
- #
22
- # --noop --verbose etc
23
- #
24
- # A note about artity values:
25
- #
26
- # We are using the arity of the command method to determine if we have finish auto-completing the params completion. When the ruby method has a splat param, it's arity will be negative. Here are some example methods and their arities.
27
- #
28
- # ship(service) = 1
29
- # scale(service, count) = 2
30
- # ships(*services) = -1
31
- # foo(example, *rest) = -2
32
- #
33
- # Fortunately, negative and positive arity values are processed the same way. So we take simply take the abs of the arity.
34
- #
35
- # To test:
36
- #
37
- # <%= project_name %> completion
38
- # <%= project_name %> completion hello
39
- # <%= project_name %> completion hello name
40
- # <%= project_name %> completion hello name --
41
- # <%= project_name %> completion hello name --noop
42
- #
43
- # <%= project_name %> completion
44
- # <%= project_name %> completion sub:goodbye
45
- # <%= project_name %> completion sub:goodbye name
46
- #
47
- # Note when testing, the first top-level word must be an exact match
48
- #
49
- # <%= project_name %> completion hello # works fine
50
- # <%= project_name %> completion he # incomplete, this will just break
51
- #
52
- # The completion assumes that the top-level word that is being passed in
53
- # from completor/scripts.sh will always match exactly. This must be the
54
- # case. For parameters, the word does not have to match exactly.
55
- #
56
- module <%= project_class_name %>
1
+ =begin
2
+ Code Explanation:
3
+
4
+ There are 3 types of things to auto-complete:
5
+
6
+ 1. command: the command itself
7
+ 2. parameters: command parameters.
8
+ 3. options: command options
9
+
10
+ Here's an example:
11
+
12
+ mycli hello name --from me
13
+
14
+ * command: hello
15
+ * parameters: name
16
+ * option: --from
17
+
18
+ When command parameters are done processing, the remaining completion words will be options. We can tell that the command params are completed based on the method arity.
19
+
20
+ ## Arity
21
+
22
+ For example, say you had a method for a CLI command with the following form:
23
+
24
+ ufo scale service count --cluster development
25
+
26
+ It's equivalent ruby method:
27
+
28
+ scale(service, count) = has an arity of 2
29
+
30
+ So typing:
31
+
32
+ ufo scale service count [TAB] # there are 3 parameters including the "scale" command according to Thor's CLI processing.
33
+
34
+ So the completion should only show options, something like this:
35
+
36
+ --noop --verbose --cluster
37
+
38
+ ## Splat Arguments
39
+
40
+ When the ruby method has a splat argument, it's arity is negative. Here are some example methods and their arities.
41
+
42
+ ship(service) = 1
43
+ scale(service, count) = 2
44
+ ships(*services) = -1
45
+ foo(example, *rest) = -2
46
+
47
+ Fortunately, negative and positive arity values are processed the same way. So we take simply take the absolute value of the arity and process it the same.
48
+
49
+ Here are some test cases, hit TAB after typing the command:
50
+
51
+ <%= project_name %> completion
52
+ <%= project_name %> completion hello
53
+ <%= project_name %> completion hello name
54
+ <%= project_name %> completion hello name --
55
+ <%= project_name %> completion hello name --noop
56
+
57
+ <%= project_name %> completion
58
+ <%= project_name %> completion sub:goodbye
59
+ <%= project_name %> completion sub:goodbye name
60
+
61
+ ## Subcommands and Thor::Group Registered Commands
62
+
63
+ Sometimes the commands are not simple thor commands but are subcommands or Thor::Group commands. A good specific example is the ufo tool.
64
+
65
+ * regular command: ufo ship
66
+ * subcommand: ufo docker
67
+ * Thor::Group command: ufo init
68
+
69
+ Auto-completion accounts for each of these type of commands.
70
+ =end
71
+ module Ufo
57
72
  class Completer
58
73
  autoload :Script, '<%= underscored_name %>/completer/script'
59
74
 
@@ -79,10 +94,10 @@ module <%= project_class_name %>
79
94
 
80
95
  # will only get to here if command aws found (above)
81
96
  arity = @command_class.instance_method(@current_command).arity.abs
82
- if @params.size <= arity
83
- puts params_completion
84
- else
97
+ if @params.size > arity or thor_group_command?
85
98
  puts options_completion
99
+ else
100
+ puts params_completion
86
101
  end
87
102
  end
88
103
 
@@ -90,8 +105,13 @@ module <%= project_class_name %>
90
105
  @command_class.subcommands.include?(command)
91
106
  end
92
107
 
108
+ # hacky way to detect that command is a registered Thor::Group command
109
+ def thor_group_command?
110
+ command_params(raw=true) == [[:rest, :args]]
111
+ end
112
+
93
113
  def found?(command)
94
- public_methods = @command_class.public_instance_methods - Object.methods
114
+ public_methods = @command_class.public_instance_methods(false)
95
115
  command && public_methods.include?(command.to_sym)
96
116
  end
97
117
 
@@ -103,17 +123,19 @@ module <%= project_class_name %>
103
123
  commands.keys
104
124
  end
105
125
 
106
- def params_completion
107
- method_params = @command_class.instance_method(@current_command).parameters
126
+ def command_params(raw=false)
127
+ params = @command_class.instance_method(@current_command).parameters
108
128
  # Example:
109
129
  # >> Sub.instance_method(:goodbye).parameters
110
130
  # => [[:req, :name]]
111
131
  # >>
112
- method_params.map!(&:last)
132
+ raw ? params : params.map!(&:last)
133
+ end
113
134
 
135
+ def params_completion
114
136
  offset = @params.size - 1
115
- offset_params = method_params[offset..-1]
116
- method_params[offset..-1].first
137
+ offset_params = command_params[offset..-1]
138
+ command_params[offset..-1].first
117
139
  end
118
140
 
119
141
  def options_completion
@@ -9,7 +9,7 @@ require "byebug"
9
9
  root = File.expand_path("../", File.dirname(__FILE__))
10
10
  require "#{root}/lib/<%= project_name %>"
11
11
 
12
- module Helpers
12
+ module Helper
13
13
  def execute(cmd)
14
14
  puts "Running: #{cmd}" if show_command?
15
15
  out = `#{cmd}`
@@ -25,5 +25,5 @@ module Helpers
25
25
  end
26
26
 
27
27
  RSpec.configure do |c|
28
- c.include Helpers
28
+ c.include Helper
29
29
  end
@@ -9,7 +9,7 @@ require "pp"
9
9
  root = File.expand_path('../../', __FILE__)
10
10
  require "#{root}/lib/cli-template"
11
11
 
12
- module Helpers
12
+ module Helper
13
13
  def execute(cmd)
14
14
  puts "Running: #{cmd}" if show_command?
15
15
  out = `#{cmd}`
@@ -25,7 +25,7 @@ module Helpers
25
25
  end
26
26
 
27
27
  RSpec.configure do |c|
28
- c.include Helpers
28
+ c.include Helper
29
29
  c.before(:all) do
30
30
  FileUtils.rm_rf("tmp")
31
31
  FileUtils.mkdir_p("tmp")
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cli-template
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.2.0
4
+ version: 3.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tung Nguyen
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-02-11 00:00:00.000000000 Z
11
+ date: 2018-02-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor
@@ -136,7 +136,7 @@ dependencies:
136
136
  - - ">="
137
137
  - !ruby/object:Gem::Version
138
138
  version: '0'
139
- description: Generate a CLI tool quickly
139
+ description:
140
140
  email:
141
141
  - tongueroo@gmail.com
142
142
  executables:
@@ -160,7 +160,7 @@ files:
160
160
  - lib/cli-template/command.rb
161
161
  - lib/cli-template/help.rb
162
162
  - lib/cli-template/help/new.md
163
- - lib/cli-template/helpers.rb
163
+ - lib/cli-template/helper.rb
164
164
  - lib/cli-template/new.rb
165
165
  - lib/cli-template/sequence.rb
166
166
  - lib/cli-template/version.rb