hammer_cli 0.0.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.
- data/LICENSE +5 -0
- data/README.md +105 -0
- data/bin/hammer +53 -0
- data/config/cli_config.template.yml +14 -0
- data/doc/design.png +0 -0
- data/doc/design.uml +24 -0
- data/hammer_cli_complete +13 -0
- data/lib/hammer_cli/abstract.rb +95 -0
- data/lib/hammer_cli/apipie/command.rb +75 -0
- data/lib/hammer_cli/apipie/options.rb +97 -0
- data/lib/hammer_cli/apipie/read_command.rb +58 -0
- data/lib/hammer_cli/apipie/resource.rb +54 -0
- data/lib/hammer_cli/apipie/write_command.rb +35 -0
- data/lib/hammer_cli/apipie.rb +3 -0
- data/lib/hammer_cli/autocompletion.rb +46 -0
- data/lib/hammer_cli/exception_handler.rb +69 -0
- data/lib/hammer_cli/exit_codes.rb +23 -0
- data/lib/hammer_cli/logger.rb +50 -0
- data/lib/hammer_cli/logger_watch.rb +14 -0
- data/lib/hammer_cli/main.rb +53 -0
- data/lib/hammer_cli/messages.rb +55 -0
- data/lib/hammer_cli/option_formatters.rb +13 -0
- data/lib/hammer_cli/output/adapter/abstract.rb +27 -0
- data/lib/hammer_cli/output/adapter/base.rb +143 -0
- data/lib/hammer_cli/output/adapter/silent.rb +17 -0
- data/lib/hammer_cli/output/adapter/table.rb +53 -0
- data/lib/hammer_cli/output/adapter.rb +6 -0
- data/lib/hammer_cli/output/definition.rb +17 -0
- data/lib/hammer_cli/output/dsl.rb +56 -0
- data/lib/hammer_cli/output/fields.rb +128 -0
- data/lib/hammer_cli/output/output.rb +27 -0
- data/lib/hammer_cli/output.rb +6 -0
- data/lib/hammer_cli/settings.rb +48 -0
- data/lib/hammer_cli/shell.rb +49 -0
- data/lib/hammer_cli/validator.rb +114 -0
- data/lib/hammer_cli/version.rb +5 -0
- data/lib/hammer_cli.rb +13 -0
- metadata +189 -0
@@ -0,0 +1,128 @@
|
|
1
|
+
require 'hammer_cli/output/dsl'
|
2
|
+
|
3
|
+
module HammerCLI::Output
|
4
|
+
|
5
|
+
|
6
|
+
class Field
|
7
|
+
|
8
|
+
def initialize(options={})
|
9
|
+
end
|
10
|
+
|
11
|
+
def get_value(data)
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
|
16
|
+
class LabeledField < Field
|
17
|
+
|
18
|
+
attr_reader :label
|
19
|
+
|
20
|
+
def initialize(options={})
|
21
|
+
@label = options[:label]
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
class DataField < LabeledField
|
26
|
+
|
27
|
+
attr_reader :path
|
28
|
+
|
29
|
+
def initialize(options={})
|
30
|
+
@path = options[:path] || []
|
31
|
+
super(options)
|
32
|
+
end
|
33
|
+
|
34
|
+
def get_value(data)
|
35
|
+
follow_path(data, path || [])
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def follow_path(record, path)
|
41
|
+
record = symbolize_hash_keys(record)
|
42
|
+
|
43
|
+
path.inject(record) do |record, path_key|
|
44
|
+
if record.has_key? path_key.to_sym
|
45
|
+
record[path_key.to_sym]
|
46
|
+
else
|
47
|
+
return nil
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def symbolize_hash_keys(h)
|
53
|
+
if h.is_a? Hash
|
54
|
+
return h.inject({}){|result,(k,v)| result.update k.to_sym => symbolize_hash_keys(v)}
|
55
|
+
elsif h.is_a? Array
|
56
|
+
return h.collect{|item| symbolize_hash_keys(item)}
|
57
|
+
else
|
58
|
+
h
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
|
64
|
+
|
65
|
+
module Fields
|
66
|
+
|
67
|
+
|
68
|
+
class Date < HammerCLI::Output::DataField
|
69
|
+
end
|
70
|
+
|
71
|
+
class OSName < HammerCLI::Output::DataField
|
72
|
+
end
|
73
|
+
|
74
|
+
class List < HammerCLI::Output::DataField
|
75
|
+
end
|
76
|
+
|
77
|
+
class KeyValue < HammerCLI::Output::DataField
|
78
|
+
end
|
79
|
+
|
80
|
+
class Server < HammerCLI::Output::DataField
|
81
|
+
end
|
82
|
+
|
83
|
+
class Joint < HammerCLI::Output::DataField
|
84
|
+
def initialize(options={}, &block)
|
85
|
+
super(options)
|
86
|
+
@attributes = options[:attributes] || []
|
87
|
+
end
|
88
|
+
|
89
|
+
attr_reader :attributes
|
90
|
+
end
|
91
|
+
|
92
|
+
class Label < HammerCLI::Output::LabeledField
|
93
|
+
|
94
|
+
def initialize(options={}, &block)
|
95
|
+
super(options)
|
96
|
+
dsl = HammerCLI::Output::Dsl.new :path => options[:path]
|
97
|
+
dsl.build &block if block_given?
|
98
|
+
|
99
|
+
self.output_definition.append dsl.fields
|
100
|
+
end
|
101
|
+
|
102
|
+
def output_definition
|
103
|
+
@output_definition ||= HammerCLI::Output::Definition.new
|
104
|
+
@output_definition
|
105
|
+
end
|
106
|
+
|
107
|
+
end
|
108
|
+
|
109
|
+
class Collection < HammerCLI::Output::DataField
|
110
|
+
|
111
|
+
def initialize(options={}, &block)
|
112
|
+
super(options)
|
113
|
+
dsl = HammerCLI::Output::Dsl.new
|
114
|
+
dsl.build &block if block_given?
|
115
|
+
|
116
|
+
self.output_definition.append dsl.fields
|
117
|
+
end
|
118
|
+
|
119
|
+
def output_definition
|
120
|
+
@output_definition ||= HammerCLI::Output::Definition.new
|
121
|
+
@output_definition
|
122
|
+
end
|
123
|
+
|
124
|
+
end
|
125
|
+
|
126
|
+
end
|
127
|
+
|
128
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module HammerCLI::Output
|
2
|
+
class Output
|
3
|
+
|
4
|
+
attr_accessor :adapter
|
5
|
+
attr_reader :definition
|
6
|
+
|
7
|
+
def initialize options={}
|
8
|
+
@adapter = options[:adapter] || HammerCLI::Output::Adapter::Base.new
|
9
|
+
@definition = options[:definition] || HammerCLI::Output::Definition.new
|
10
|
+
end
|
11
|
+
|
12
|
+
def print_message msg
|
13
|
+
adapter.print_message(msg.to_s)
|
14
|
+
end
|
15
|
+
|
16
|
+
def print_error msg, details=nil
|
17
|
+
adapter.print_error(msg.to_s, details)
|
18
|
+
end
|
19
|
+
|
20
|
+
def print_records records, heading=nil
|
21
|
+
records = [records] unless records.kind_of?(Array)
|
22
|
+
|
23
|
+
adapter.print_records(definition.fields, records, heading)
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,6 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'output/output')
|
2
|
+
require File.join(File.dirname(__FILE__), 'output/fields')
|
3
|
+
require File.join(File.dirname(__FILE__), 'output/adapter')
|
4
|
+
require File.join(File.dirname(__FILE__), 'output/definition')
|
5
|
+
require File.join(File.dirname(__FILE__), 'output/dsl')
|
6
|
+
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
require 'logging'
|
3
|
+
|
4
|
+
module HammerCLI
|
5
|
+
|
6
|
+
class Settings
|
7
|
+
|
8
|
+
def self.[] key
|
9
|
+
settings[key.to_sym]
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.load_from_file files
|
13
|
+
files.reverse.each do |path|
|
14
|
+
full_path = File.expand_path path
|
15
|
+
if File.exists? full_path
|
16
|
+
config = YAML::load(File.open(full_path))
|
17
|
+
if config
|
18
|
+
load(config)
|
19
|
+
path_history << full_path
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.load settings_hash
|
26
|
+
settings.merge! settings_hash.inject({}){ |sym_hash,(k,v)| sym_hash[k.to_sym] = v; sym_hash }
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.clear
|
30
|
+
settings.clear
|
31
|
+
path_history.clear
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.path_history
|
35
|
+
@path_history ||= []
|
36
|
+
@path_history
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
def self.settings
|
41
|
+
@settings_hash ||= {}
|
42
|
+
@settings_hash
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
|
48
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'hammer_cli/abstract'
|
2
|
+
require 'readline'
|
3
|
+
|
4
|
+
module HammerCLI
|
5
|
+
|
6
|
+
class ShellCommand < AbstractCommand
|
7
|
+
|
8
|
+
def execute
|
9
|
+
Readline.completion_append_character = " "
|
10
|
+
Readline.completer_word_break_characters = ''
|
11
|
+
Readline.completion_proc = complete_proc
|
12
|
+
|
13
|
+
stty_save = `stty -g`.chomp
|
14
|
+
|
15
|
+
begin
|
16
|
+
while line = Readline.readline('hammer> ', true)
|
17
|
+
HammerCLI::MainCommand.run('hammer', line.split) unless line.start_with? 'shell'
|
18
|
+
end
|
19
|
+
rescue Interrupt => e
|
20
|
+
puts
|
21
|
+
system('stty', stty_save) # Restore
|
22
|
+
exit
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def common_prefix(results)
|
29
|
+
results.delete_if{ |r| !r[0].start_with?(results[0][0][0]) }.length == results.length
|
30
|
+
end
|
31
|
+
|
32
|
+
def complete_proc
|
33
|
+
Proc.new do |cpl|
|
34
|
+
res = HammerCLI::MainCommand.autocomplete(cpl.split)
|
35
|
+
# if there is one result or if results have common prefix
|
36
|
+
# readline tries to replace current input with results
|
37
|
+
# thus we should join the results with the start of the line
|
38
|
+
if res.length == 1 || common_prefix(res)
|
39
|
+
res.map { |r| r.delete_if{ |e| e == '' }.reverse.join(' ') }
|
40
|
+
else
|
41
|
+
res.map{ |e| e[0] }
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
HammerCLI::MainCommand.subcommand "shell", "Interactive Shell", HammerCLI::ShellCommand
|
49
|
+
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
|
2
|
+
module HammerCLI
|
3
|
+
|
4
|
+
class Validator
|
5
|
+
|
6
|
+
class ValidationError < StandardError
|
7
|
+
end
|
8
|
+
|
9
|
+
class BaseConstraint
|
10
|
+
|
11
|
+
attr_reader :rejected_msg, :required_msg
|
12
|
+
|
13
|
+
def initialize(options, to_check)
|
14
|
+
@to_check = to_check
|
15
|
+
@rejected_msg = ""
|
16
|
+
@required_msg = ""
|
17
|
+
|
18
|
+
@options = options.inject({}) do |hash, opt|
|
19
|
+
hash.update({opt.attribute.attribute_name => opt})
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def rejected(args={})
|
24
|
+
msg = args[:msg] || rejected_msg % option_switches.join(", ")
|
25
|
+
raise ValidationError.new(msg) if exist?
|
26
|
+
end
|
27
|
+
|
28
|
+
def required(args={})
|
29
|
+
msg = args[:msg] || required_msg % option_switches.join(", ")
|
30
|
+
raise ValidationError.new(msg) unless exist?
|
31
|
+
end
|
32
|
+
|
33
|
+
def exist?
|
34
|
+
raise NotImplementedError
|
35
|
+
end
|
36
|
+
|
37
|
+
protected
|
38
|
+
|
39
|
+
def get_option(name)
|
40
|
+
name = name.to_s
|
41
|
+
raise "Unknown option name '%s'" % name unless @options.has_key? name
|
42
|
+
@options[name]
|
43
|
+
end
|
44
|
+
|
45
|
+
def option_passed?(option_name)
|
46
|
+
!get_option(option_name).get.nil?
|
47
|
+
end
|
48
|
+
|
49
|
+
def option_switches(opts=nil)
|
50
|
+
opts ||= @to_check
|
51
|
+
opts.collect do |option_name|
|
52
|
+
get_option(option_name).attribute.long_switch || get_option(option_name).attribute.switches.first
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
|
58
|
+
class AllConstraint < BaseConstraint
|
59
|
+
|
60
|
+
def initialize(options, to_check)
|
61
|
+
super(options, to_check)
|
62
|
+
@rejected_msg = "You can't set all options %s at one time"
|
63
|
+
@required_msg = "Options %s are required"
|
64
|
+
end
|
65
|
+
|
66
|
+
def exist?
|
67
|
+
@to_check.each do |opt|
|
68
|
+
return false unless option_passed?(opt)
|
69
|
+
end
|
70
|
+
return true
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
|
75
|
+
class AnyConstraint < BaseConstraint
|
76
|
+
|
77
|
+
def initialize(options, to_check)
|
78
|
+
super(options, to_check)
|
79
|
+
@rejected_msg = "You can't set any of options %s"
|
80
|
+
@required_msg = "At least one of options %s is required"
|
81
|
+
end
|
82
|
+
|
83
|
+
def exist?
|
84
|
+
@to_check.each do |opt|
|
85
|
+
return true if option_passed?(opt)
|
86
|
+
end
|
87
|
+
return @to_check.empty?
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
|
92
|
+
def initialize(options)
|
93
|
+
@options = options
|
94
|
+
end
|
95
|
+
|
96
|
+
def all(*to_check)
|
97
|
+
AllConstraint.new(@options, to_check)
|
98
|
+
end
|
99
|
+
|
100
|
+
def option(to_check)
|
101
|
+
all(to_check)
|
102
|
+
end
|
103
|
+
|
104
|
+
def any(*to_check)
|
105
|
+
AnyConstraint.new(@options, to_check)
|
106
|
+
end
|
107
|
+
|
108
|
+
def run(&block)
|
109
|
+
self.instance_eval &block
|
110
|
+
end
|
111
|
+
|
112
|
+
end
|
113
|
+
|
114
|
+
end
|
data/lib/hammer_cli.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'hammer_cli/version'
|
2
|
+
require 'hammer_cli/exit_codes'
|
3
|
+
require 'hammer_cli/settings'
|
4
|
+
require 'hammer_cli/validator'
|
5
|
+
require 'hammer_cli/abstract'
|
6
|
+
require 'hammer_cli/main'
|
7
|
+
|
8
|
+
require 'hammer_cli/output'
|
9
|
+
require 'hammer_cli/apipie'
|
10
|
+
|
11
|
+
# extend MainCommand
|
12
|
+
require 'hammer_cli/shell'
|
13
|
+
|
metadata
ADDED
@@ -0,0 +1,189 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: hammer_cli
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.4
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Martin Bačovský
|
9
|
+
- Tomáš Strachota
|
10
|
+
autorequire:
|
11
|
+
bindir: bin
|
12
|
+
cert_chain: []
|
13
|
+
date: 2013-08-30 00:00:00.000000000 Z
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: clamp
|
17
|
+
requirement: !ruby/object:Gem::Requirement
|
18
|
+
none: false
|
19
|
+
requirements:
|
20
|
+
- - ! '>='
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '0'
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
none: false
|
27
|
+
requirements:
|
28
|
+
- - ! '>='
|
29
|
+
- !ruby/object:Gem::Version
|
30
|
+
version: '0'
|
31
|
+
- !ruby/object:Gem::Dependency
|
32
|
+
name: rest-client
|
33
|
+
requirement: !ruby/object:Gem::Requirement
|
34
|
+
none: false
|
35
|
+
requirements:
|
36
|
+
- - ! '>='
|
37
|
+
- !ruby/object:Gem::Version
|
38
|
+
version: '0'
|
39
|
+
type: :runtime
|
40
|
+
prerelease: false
|
41
|
+
version_requirements: !ruby/object:Gem::Requirement
|
42
|
+
none: false
|
43
|
+
requirements:
|
44
|
+
- - ! '>='
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '0'
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: logging
|
49
|
+
requirement: !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
type: :runtime
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: !ruby/object:Gem::Requirement
|
58
|
+
none: false
|
59
|
+
requirements:
|
60
|
+
- - ! '>='
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: '0'
|
63
|
+
- !ruby/object:Gem::Dependency
|
64
|
+
name: awesome_print
|
65
|
+
requirement: !ruby/object:Gem::Requirement
|
66
|
+
none: false
|
67
|
+
requirements:
|
68
|
+
- - ! '>='
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
version: '0'
|
71
|
+
type: :runtime
|
72
|
+
prerelease: false
|
73
|
+
version_requirements: !ruby/object:Gem::Requirement
|
74
|
+
none: false
|
75
|
+
requirements:
|
76
|
+
- - ! '>='
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
version: '0'
|
79
|
+
- !ruby/object:Gem::Dependency
|
80
|
+
name: table_print
|
81
|
+
requirement: !ruby/object:Gem::Requirement
|
82
|
+
none: false
|
83
|
+
requirements:
|
84
|
+
- - ! '>='
|
85
|
+
- !ruby/object:Gem::Version
|
86
|
+
version: '0'
|
87
|
+
type: :runtime
|
88
|
+
prerelease: false
|
89
|
+
version_requirements: !ruby/object:Gem::Requirement
|
90
|
+
none: false
|
91
|
+
requirements:
|
92
|
+
- - ! '>='
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
version: '0'
|
95
|
+
- !ruby/object:Gem::Dependency
|
96
|
+
name: highline
|
97
|
+
requirement: !ruby/object:Gem::Requirement
|
98
|
+
none: false
|
99
|
+
requirements:
|
100
|
+
- - ! '>='
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: '0'
|
103
|
+
type: :runtime
|
104
|
+
prerelease: false
|
105
|
+
version_requirements: !ruby/object:Gem::Requirement
|
106
|
+
none: false
|
107
|
+
requirements:
|
108
|
+
- - ! '>='
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
description: ! 'Hammer cli provides universal extendable CLI interface for ruby apps
|
112
|
+
|
113
|
+
'
|
114
|
+
email: mbacovsk@redhat.com
|
115
|
+
executables:
|
116
|
+
- hammer
|
117
|
+
extensions: []
|
118
|
+
extra_rdoc_files:
|
119
|
+
- README.md
|
120
|
+
- LICENSE
|
121
|
+
- hammer_cli_complete
|
122
|
+
- config/cli_config.template.yml
|
123
|
+
- doc/design.uml
|
124
|
+
- doc/design.png
|
125
|
+
files:
|
126
|
+
- lib/hammer_cli/output.rb
|
127
|
+
- lib/hammer_cli/option_formatters.rb
|
128
|
+
- lib/hammer_cli/abstract.rb
|
129
|
+
- lib/hammer_cli/apipie/write_command.rb
|
130
|
+
- lib/hammer_cli/apipie/command.rb
|
131
|
+
- lib/hammer_cli/apipie/options.rb
|
132
|
+
- lib/hammer_cli/apipie/read_command.rb
|
133
|
+
- lib/hammer_cli/apipie/resource.rb
|
134
|
+
- lib/hammer_cli/apipie.rb
|
135
|
+
- lib/hammer_cli/autocompletion.rb
|
136
|
+
- lib/hammer_cli/validator.rb
|
137
|
+
- lib/hammer_cli/exit_codes.rb
|
138
|
+
- lib/hammer_cli/version.rb
|
139
|
+
- lib/hammer_cli/logger_watch.rb
|
140
|
+
- lib/hammer_cli/main.rb
|
141
|
+
- lib/hammer_cli/settings.rb
|
142
|
+
- lib/hammer_cli/output/output.rb
|
143
|
+
- lib/hammer_cli/output/adapter/abstract.rb
|
144
|
+
- lib/hammer_cli/output/adapter/table.rb
|
145
|
+
- lib/hammer_cli/output/adapter/base.rb
|
146
|
+
- lib/hammer_cli/output/adapter/silent.rb
|
147
|
+
- lib/hammer_cli/output/dsl.rb
|
148
|
+
- lib/hammer_cli/output/adapter.rb
|
149
|
+
- lib/hammer_cli/output/definition.rb
|
150
|
+
- lib/hammer_cli/output/fields.rb
|
151
|
+
- lib/hammer_cli/logger.rb
|
152
|
+
- lib/hammer_cli/exception_handler.rb
|
153
|
+
- lib/hammer_cli/messages.rb
|
154
|
+
- lib/hammer_cli/shell.rb
|
155
|
+
- lib/hammer_cli.rb
|
156
|
+
- bin/hammer
|
157
|
+
- README.md
|
158
|
+
- LICENSE
|
159
|
+
- hammer_cli_complete
|
160
|
+
- config/cli_config.template.yml
|
161
|
+
- doc/design.uml
|
162
|
+
- doc/design.png
|
163
|
+
homepage: http://github.com/theforeman/hammer-cli
|
164
|
+
licenses:
|
165
|
+
- GPL-3
|
166
|
+
post_install_message:
|
167
|
+
rdoc_options: []
|
168
|
+
require_paths:
|
169
|
+
- lib
|
170
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
171
|
+
none: false
|
172
|
+
requirements:
|
173
|
+
- - ! '>='
|
174
|
+
- !ruby/object:Gem::Version
|
175
|
+
version: '0'
|
176
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
177
|
+
none: false
|
178
|
+
requirements:
|
179
|
+
- - ! '>='
|
180
|
+
- !ruby/object:Gem::Version
|
181
|
+
version: '0'
|
182
|
+
requirements: []
|
183
|
+
rubyforge_project:
|
184
|
+
rubygems_version: 1.8.23
|
185
|
+
signing_key:
|
186
|
+
specification_version: 3
|
187
|
+
summary: Universal command-line interface
|
188
|
+
test_files: []
|
189
|
+
has_rdoc:
|