clamp-completer 0.1.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 +7 -0
- data/README.md +98 -0
- data/clamp-completer.gemspec +24 -0
- data/lib/clamp/completer.rb +75 -0
- data/lib/clamp/completer/templates/bash.sh.erb +92 -0
- data/lib/clamp/completer/templates/zsh.sh.erb +94 -0
- data/lib/clamp/completer/version.rb +7 -0
- metadata +105 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 801dce4fae329b01ac6efe2a99e47a0bd6e7d1be310347c8abccfef53b7be900
|
4
|
+
data.tar.gz: 67f5db2a8d3d7bda3939523c2543435333a38811e93fcf679e20d0d9dfe66093
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 875e58f9bb107cfb1f66696a9e70cde324a5deabfed64494be63c71658eb0893df6ea1ec63d92bba0fd5d22277fda3cc9c00dbf58a0ed5f1581793ab1a9e2d9e
|
7
|
+
data.tar.gz: 07750b2fe30a8136eeb06cb6d19088e9848aa56915f34e5db2abaaadcfa2aa5ce76827dd5d91dcd4db2ec54c8145dab16f02e3d7245511bcc959f9988374c6da
|
data/README.md
ADDED
@@ -0,0 +1,98 @@
|
|
1
|
+
[](https://travis-ci.org/kontena/clamp-completer)
|
2
|
+
[](https://badge.fury.io/rb/clamp-completer)
|
3
|
+
|
4
|
+
# Clamp::Completer
|
5
|
+
|
6
|
+
Automatically generate shell auto-completion scripts for Ruby command-line tools built using the [clamp](https://github.com/mdub/clamp) gem.
|
7
|
+
|
8
|
+
## Installation
|
9
|
+
|
10
|
+
Add this line to your application's Gemfile:
|
11
|
+
|
12
|
+
```ruby
|
13
|
+
gem 'clamp-completer'
|
14
|
+
```
|
15
|
+
|
16
|
+
Or install it yourself as:
|
17
|
+
|
18
|
+
```
|
19
|
+
$ gem install clamp-completer
|
20
|
+
```
|
21
|
+
|
22
|
+
## Usage
|
23
|
+
|
24
|
+
Require the `clamp/completer` and in your application's root command, add a subcommand:
|
25
|
+
|
26
|
+
```ruby
|
27
|
+
require 'clamp/completer'
|
28
|
+
|
29
|
+
Clamp do
|
30
|
+
subcommand "complete", "shell autocompletions", Clamp::Completer.new(self)
|
31
|
+
end
|
32
|
+
```
|
33
|
+
|
34
|
+
This will add a `complete` subcommand:
|
35
|
+
|
36
|
+
```
|
37
|
+
$ your_app complete zsh
|
38
|
+
$ your_app complete bash
|
39
|
+
```
|
40
|
+
|
41
|
+
You can redirect the output to a static file or load the output directly into the running environment:
|
42
|
+
|
43
|
+
```
|
44
|
+
# zsh / bash:
|
45
|
+
$ source <(your_app complete)
|
46
|
+
# or for the macOs preinstalled bash version:
|
47
|
+
$ source /dev/stdin <<<"$(your_app complete bash)"
|
48
|
+
```
|
49
|
+
|
50
|
+
### Customizing completions
|
51
|
+
|
52
|
+
Currently, subcommand completions and flag-type options defined through `option '--debug', :flag, 'enable debug'` should work correctly out-of-the-box. For options that take parameters,
|
53
|
+
such as file paths or a predefined set of words, you can define methods on your command classes that will be used to determine how the values should be completed:
|
54
|
+
|
55
|
+
```ruby
|
56
|
+
Clamp do
|
57
|
+
option '--config', 'YAML_FILE', "configuration YAML file path"
|
58
|
+
|
59
|
+
def complete_yaml_file # name derived from the YAML_FILE argument description
|
60
|
+
{ glob: '*.yml' }
|
61
|
+
end
|
62
|
+
end
|
63
|
+
```
|
64
|
+
|
65
|
+
```ruby
|
66
|
+
Clamp do
|
67
|
+
option '--role', 'ROLE_NAME', "node role"
|
68
|
+
|
69
|
+
def complete_role # name derived from the attribute name
|
70
|
+
"master worker" # will add "master" and "worker" as completion responses when you do: your_app --role <tab>
|
71
|
+
end
|
72
|
+
end
|
73
|
+
```
|
74
|
+
|
75
|
+
#### Completion method response types
|
76
|
+
|
77
|
+
##### String
|
78
|
+
|
79
|
+
A space separated string of possible values for the option
|
80
|
+
|
81
|
+
##### Symbol
|
82
|
+
|
83
|
+
Currently known symbols:
|
84
|
+
|
85
|
+
* `:dirs` will complete directory names
|
86
|
+
* `:files` will complete file names
|
87
|
+
* `:hosts` will complete known host names
|
88
|
+
|
89
|
+
##### Hash
|
90
|
+
|
91
|
+
Much like the Symbols, but returned in Hash format to enable passing options:
|
92
|
+
|
93
|
+
* `{ glob: '*.yml' }` will complete files endinging with `.yml`
|
94
|
+
* `{ command: 'cut -d':' -f1 /etc/passwd' }` will run a command to get completion candidates, in this case the usernames from `/etc/password`
|
95
|
+
|
96
|
+
## Contributing
|
97
|
+
|
98
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/clamp-completer.
|
@@ -0,0 +1,24 @@
|
|
1
|
+
|
2
|
+
lib = File.expand_path("../lib", __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require "clamp/completer/version"
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "clamp-completer"
|
8
|
+
spec.version = Clamp::Completer::VERSION
|
9
|
+
spec.authors = ["Kontena, Inc"]
|
10
|
+
spec.email = ["info@kontena.io"]
|
11
|
+
|
12
|
+
spec.summary = %q{Automatically generate shell auto-completion scripts for clamp based cli tools}
|
13
|
+
spec.homepage = "https://github.com/kontena/clamp-completer"
|
14
|
+
|
15
|
+
spec.files = Dir["lib/**/*.{rb,erb}", "README.md", "LICENSE", "clamp-completer.gemspec"]
|
16
|
+
|
17
|
+
spec.require_paths = ["lib"]
|
18
|
+
|
19
|
+
spec.add_runtime_dependency "clamp"
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", ">= 1.17"
|
22
|
+
spec.add_development_dependency "rspec", "~> 3.0"
|
23
|
+
spec.add_development_dependency "rubocop", "~> 0.62"
|
24
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "clamp/completer/version"
|
4
|
+
require 'shellwords'
|
5
|
+
|
6
|
+
module Clamp
|
7
|
+
module Completer
|
8
|
+
module Builder
|
9
|
+
autoload :ERB, 'erb'
|
10
|
+
autoload :OpenStruct, 'ostruct'
|
11
|
+
|
12
|
+
class Iterator
|
13
|
+
def initialize(root)
|
14
|
+
@root = root
|
15
|
+
end
|
16
|
+
|
17
|
+
def recurse(base = [], &block)
|
18
|
+
if @root.has_subcommands?
|
19
|
+
@root.recognised_subcommands.each do |sc|
|
20
|
+
sc.names.each do |name|
|
21
|
+
Iterator.new(sc.subcommand_class).recurse(base + [name], &block)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
yield(base, @root) unless base.empty?
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def root
|
30
|
+
self.class.root_command
|
31
|
+
end
|
32
|
+
|
33
|
+
def template_path(shell_name)
|
34
|
+
File.join(__dir__, 'completer', 'templates', "#{shell_name}.sh.erb")
|
35
|
+
end
|
36
|
+
|
37
|
+
def wrapper
|
38
|
+
klass = Class.new(self.class)
|
39
|
+
klass.subcommand(File.basename($PROGRAM_NAME), root.description || "main", root)
|
40
|
+
klass
|
41
|
+
end
|
42
|
+
|
43
|
+
def execute
|
44
|
+
template_file = template_path(shell)
|
45
|
+
unless File.exist?(template_file)
|
46
|
+
warn "Completion generation is not supported for #{shell}, defaulting to bash"
|
47
|
+
template_file = template_path("bash")
|
48
|
+
end
|
49
|
+
|
50
|
+
puts ERB.new(File.read(template_file), nil, '%-').tap { |e| e.location = [template_file, nil] }.result(
|
51
|
+
OpenStruct.new(progname: File.basename($PROGRAM_NAME), iterator: Iterator.new(wrapper)).instance_eval { binding }
|
52
|
+
)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def self.new(root_command, inherit_from: Clamp::Command)
|
57
|
+
@klass = Class.new(inherit_from) do
|
58
|
+
include Builder
|
59
|
+
|
60
|
+
class << self
|
61
|
+
attr_accessor :root_command
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
@klass.parameter('[SHELL]', 'shell', environment_variable: 'SHELL', default: 'bash') do |shell|
|
66
|
+
File.basename(shell)
|
67
|
+
end
|
68
|
+
|
69
|
+
@klass.root_command = root_command
|
70
|
+
|
71
|
+
@klass.banner("To load, use: source <(#{File.basename($PROGRAM_NAME)} complete #{@klass.usage_descriptions.join(' ')})")
|
72
|
+
@klass
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
_clamp_completer_<%= progname %>_current_subcommand() {
|
2
|
+
local ret="_${COMP_WORDS[0]}"
|
3
|
+
for ((i=1; i<$COMP_CWORD; i++)); do
|
4
|
+
if [[ ! $COMP_WORDS[$i] == -* ]]; then
|
5
|
+
declare -fF -- "${ret}_${COMP_WORDS[$i]}" >/dev/null && ret="${ret}_${COMP_WORDS[$i]}"
|
6
|
+
fi
|
7
|
+
done
|
8
|
+
|
9
|
+
if [ -n "$ret" ]; then
|
10
|
+
RET="${ret}"
|
11
|
+
return 0
|
12
|
+
else
|
13
|
+
return 1
|
14
|
+
fi
|
15
|
+
}
|
16
|
+
|
17
|
+
_clamp_completer_<%= progname %>_nospace() {
|
18
|
+
command -v compopt &> /dev/null && compopt -o nospace
|
19
|
+
}
|
20
|
+
|
21
|
+
<%- iterator.recurse do |invocation_path, command_class| -%>
|
22
|
+
_<%= invocation_path.join('_') %>() {
|
23
|
+
local cur prev subcmd
|
24
|
+
COMPREPLY=()
|
25
|
+
cur="${COMP_WORDS[COMP_CWORD]}"
|
26
|
+
prev="${COMP_WORDS[COMP_CWORD-1]}"
|
27
|
+
_clamp_completer_<%= progname %>_current_subcommand && subcmd="$RET"
|
28
|
+
|
29
|
+
if [ "$subcmd" = "${FUNCNAME[0]}${funcstack[1]}" ]; then
|
30
|
+
<%- visible_opts = command_class.recognised_options.reject(&:hidden?) -%>
|
31
|
+
if [[ ${cur} == -* ]] ; then
|
32
|
+
COMPREPLY=( $(compgen -W "<%= visible_opts.map(&:long_switch).join(' ') %>" -- ${cur}) )
|
33
|
+
return 0
|
34
|
+
fi
|
35
|
+
|
36
|
+
<%- visible_non_flag_opts = visible_opts.reject { |o| o.type == :flag } -%>
|
37
|
+
<%- unless visible_non_flag_opts.empty? -%>
|
38
|
+
<%- instance = command_class.new(invocation_path) -%>
|
39
|
+
case "$prev" in
|
40
|
+
<%- visible_non_flag_opts.each do |option| -%>
|
41
|
+
<%= option.switches.join('|') %>)
|
42
|
+
COMPREPLY=()
|
43
|
+
<%- if instance.respond_to?("complete_#{option.attribute_name}")
|
44
|
+
reply = instance.send("complete_#{option.attribute_name}")
|
45
|
+
else
|
46
|
+
cleaned_type = "complete_#{option.type.downcase.delete_prefix('[').split(' ').first}"
|
47
|
+
if instance.respond_to?(cleaned_type)
|
48
|
+
reply = instance.send(cleaned_type)
|
49
|
+
end
|
50
|
+
end -%>
|
51
|
+
<%- [reply].compact.each do |reply| -%>
|
52
|
+
<%= case reply
|
53
|
+
when String
|
54
|
+
"COMPREPLY+=( $(compgen -W \"#{reply}\" -- \"${cur}\") );"
|
55
|
+
when Symbol
|
56
|
+
case reply
|
57
|
+
when :dirs
|
58
|
+
"COMPREPLY+=( $(compgen -o nospace -d -S \"/\" -- \"${cur}\") ); _clamp_completer_#{ progname }_nospace;"
|
59
|
+
when :hosts
|
60
|
+
"COMPREPLY+=( $(compgen -A hostname -- \"${cur}\") );"
|
61
|
+
when :files
|
62
|
+
"COMPREPLY+=( $(compgen -o filenames -f -- \"${cur}\") );"
|
63
|
+
end
|
64
|
+
when Hash
|
65
|
+
case reply.first.first
|
66
|
+
when :glob
|
67
|
+
"COMPREPLY+=( $(compgen -o filenames -f -G \"#{reply.first.last}\" -- \"${cur}\") );"
|
68
|
+
when :command
|
69
|
+
"COMPREPLY+=( $(compgen -C \"#{reply.first.last}\" -- \"${cur}\") );"
|
70
|
+
end
|
71
|
+
else
|
72
|
+
"COMPREPLY+=( $(compgen -o bashdefault -- \"${cur}\") );"
|
73
|
+
end %>
|
74
|
+
<%- end -%>
|
75
|
+
return 0
|
76
|
+
;;
|
77
|
+
<%- end -%>
|
78
|
+
esac
|
79
|
+
<%- end -%>
|
80
|
+
|
81
|
+
<%- if command_class.has_subcommands? -%>
|
82
|
+
COMPREPLY=( $(compgen -W "<%= command_class.recognised_subcommands.flat_map(&:names).join(' ') %>" -- ${cur}) )
|
83
|
+
<%- else -%>
|
84
|
+
COMPREPLY=()
|
85
|
+
<%- end -%>
|
86
|
+
elif [ -n "$subcmd" ]; then
|
87
|
+
eval "$subcmd"
|
88
|
+
fi
|
89
|
+
}
|
90
|
+
|
91
|
+
<%- end -%>
|
92
|
+
complete -F _<%= progname %> <%= progname %>
|
@@ -0,0 +1,94 @@
|
|
1
|
+
#compdef <%= progname %>
|
2
|
+
|
3
|
+
<%- iterator.recurse do |invocation_path, command_class| -%>
|
4
|
+
<%- if command_class.has_subcommands? -%>
|
5
|
+
_<%= invocation_path.join('_') %>_subcommands() {
|
6
|
+
local subcommands=( <%= command_class.recognised_subcommands.map { |sc| "'#{sc.names.first}:#{sc.description.gsub(/'\$\\/, '\\\1') }'" }.join(' ') %> )
|
7
|
+
_describe 'subcommands' subcommands && return 0
|
8
|
+
return 1
|
9
|
+
}
|
10
|
+
|
11
|
+
<%- else -%>
|
12
|
+
_<%= invocation_path.join('_') %>_subcommands() {
|
13
|
+
return 1
|
14
|
+
}
|
15
|
+
|
16
|
+
<%- end -%>
|
17
|
+
|
18
|
+
_<%= invocation_path.join('_') %>() {
|
19
|
+
local curcontext="$curcontext" state state_descr line expl
|
20
|
+
local ret=1
|
21
|
+
|
22
|
+
_arguments -C : \
|
23
|
+
'1:subcommands:_<%= invocation_path.join('_') %>_subcommands' \
|
24
|
+
<%- command_class.recognised_options.each do |opt| -%>
|
25
|
+
<%- if opt.type == :flag -%>
|
26
|
+
<%- if opt.long_switch.include?('[no-]') -%>
|
27
|
+
'<%= opt.long_switch.gsub('[no-]', 'no-') %>[(disable) <%= opt.description.gsub(/\[|\]|:/, '\\\1') %>]' \
|
28
|
+
'<%= opt.long_switch.gsub('[no-]', '') %>[(enable) <%= opt.description.gsub(/\[|\]|:/, '\\\1') %>]' \
|
29
|
+
<%- else -%>
|
30
|
+
'<%= opt.long_switch %>[<%= opt.description.gsub(/\[|\]|:/, '\\\1') %>]' \
|
31
|
+
<%- end -%>
|
32
|
+
<%- else
|
33
|
+
instance = command_class.new(invocation_path)
|
34
|
+
if instance.respond_to?("complete_#{opt.attribute_name}")
|
35
|
+
reply = instance.send("complete_#{opt.attribute_name}")
|
36
|
+
else
|
37
|
+
cleaned_type = "complete_#{opt.type.downcase.delete_prefix('[').split(' ').first}"
|
38
|
+
if instance.respond_to?(cleaned_type)
|
39
|
+
reply = instance.send(cleaned_type)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
result=[]
|
43
|
+
[reply].compact.each do |reply|
|
44
|
+
case reply
|
45
|
+
when String
|
46
|
+
result << "(#{reply})"
|
47
|
+
when Symbol
|
48
|
+
case reply
|
49
|
+
when :dirs
|
50
|
+
result << "_path_files -/"
|
51
|
+
when :hosts
|
52
|
+
when :files
|
53
|
+
result << "_path_files -f"
|
54
|
+
end
|
55
|
+
when Hash
|
56
|
+
case reply.first.first
|
57
|
+
when :glob
|
58
|
+
result << "_path_files -f -g \"#{reply.first.last}\""
|
59
|
+
when :command
|
60
|
+
result << "(${(k)commands})"
|
61
|
+
end
|
62
|
+
else
|
63
|
+
end
|
64
|
+
-%>
|
65
|
+
<%- if opt.long_switch.include?('[no-]') -%>
|
66
|
+
'<%= opt.long_switch.gsub('[no-]', 'no-') %>:(disable) <%= opt.description.gsub(/\[|\]|:/, '\\\1') %>:<%= result.first %>' \
|
67
|
+
'<%= opt.long_switch.gsub('[no-]', '') %>:(enable) <%= opt.description.gsub(/\[|\]|:/, '\\\1') %>:<%= result.first %>' \
|
68
|
+
<%- else -%>
|
69
|
+
'<%= opt.long_switch %>:<%= opt.description.gsub(/\[|\]|:/, '\\\1') %>:<%= result.first %>' \
|
70
|
+
<%- end -%>
|
71
|
+
<%- end -%>
|
72
|
+
<%- end -%>
|
73
|
+
<%- end -%>
|
74
|
+
'*::options:->options' && return 0
|
75
|
+
|
76
|
+
case "$state" in
|
77
|
+
command) _<%= invocation_path.join('_') %>_subcommands && return 0 ;;
|
78
|
+
options)
|
79
|
+
local command="${line[1]}"
|
80
|
+
curcontext="${curcontext%:*:*}:<%= invocation_path.join('-') %>-${command}"
|
81
|
+
|
82
|
+
line=(${line:1})
|
83
|
+
local completion_func="_<%= invocation_path.join('_') %>_${command//-/_}"
|
84
|
+
_call_function ret "${completion_func}" && return ret
|
85
|
+
|
86
|
+
_message "a completion function is not defined for ${command}"
|
87
|
+
return 1
|
88
|
+
;;
|
89
|
+
esac
|
90
|
+
}
|
91
|
+
|
92
|
+
<%- end -%>
|
93
|
+
|
94
|
+
compdef _<%= progname %> <%= progname %>
|
metadata
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: clamp-completer
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Kontena, Inc
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2019-01-09 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: clamp
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.17'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.17'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '3.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rubocop
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0.62'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0.62'
|
69
|
+
description:
|
70
|
+
email:
|
71
|
+
- info@kontena.io
|
72
|
+
executables: []
|
73
|
+
extensions: []
|
74
|
+
extra_rdoc_files: []
|
75
|
+
files:
|
76
|
+
- README.md
|
77
|
+
- clamp-completer.gemspec
|
78
|
+
- lib/clamp/completer.rb
|
79
|
+
- lib/clamp/completer/templates/bash.sh.erb
|
80
|
+
- lib/clamp/completer/templates/zsh.sh.erb
|
81
|
+
- lib/clamp/completer/version.rb
|
82
|
+
homepage: https://github.com/kontena/clamp-completer
|
83
|
+
licenses: []
|
84
|
+
metadata: {}
|
85
|
+
post_install_message:
|
86
|
+
rdoc_options: []
|
87
|
+
require_paths:
|
88
|
+
- lib
|
89
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
90
|
+
requirements:
|
91
|
+
- - ">="
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
95
|
+
requirements:
|
96
|
+
- - ">="
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
version: '0'
|
99
|
+
requirements: []
|
100
|
+
rubygems_version: 3.0.2
|
101
|
+
signing_key:
|
102
|
+
specification_version: 4
|
103
|
+
summary: Automatically generate shell auto-completion scripts for clamp based cli
|
104
|
+
tools
|
105
|
+
test_files: []
|