cli-template 3.2.0 → 3.3.0

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.
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