clamp-completer 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
[![Build Status](https://travis-ci.org/kontena/clamp-completer.svg?branch=master)](https://travis-ci.org/kontena/clamp-completer)
|
2
|
+
[![Gem Version](https://badge.fury.io/rb/clamp-completer)](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: []
|