rcoli 0.5.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.
- data/.gitignore +5 -0
- data/Gemfile +2 -0
- data/Gemfile.lock +18 -0
- data/README.md +4 -0
- data/Rakefile +3 -0
- data/lib/rcoli/extensions.rb +12 -0
- data/lib/rcoli/help.rb +17 -0
- data/lib/rcoli/model.rb +190 -0
- data/lib/rcoli/templates/help.erb +22 -0
- data/lib/rcoli/version.rb +5 -0
- data/lib/rcoli.rb +27 -0
- data/rcoli.gemspec +20 -0
- metadata +95 -0
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
data/README.md
ADDED
data/Rakefile
ADDED
data/lib/rcoli/help.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'erb'
|
2
|
+
|
3
|
+
module RCoLi
|
4
|
+
|
5
|
+
module Help
|
6
|
+
|
7
|
+
def help
|
8
|
+
puts template 'help'
|
9
|
+
end
|
10
|
+
|
11
|
+
def template(name)
|
12
|
+
ERB.new(File.read(File.join(File.dirname(__FILE__), 'templates', "#{name}.erb")), nil, '-').result binding
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
data/lib/rcoli/model.rb
ADDED
@@ -0,0 +1,190 @@
|
|
1
|
+
class InvalidCommand < Exception
|
2
|
+
end
|
3
|
+
|
4
|
+
module RCoLi
|
5
|
+
|
6
|
+
module CommandContainer
|
7
|
+
|
8
|
+
attr_accessor :parent
|
9
|
+
|
10
|
+
def action(&block)
|
11
|
+
@action = block
|
12
|
+
end
|
13
|
+
|
14
|
+
def get_action
|
15
|
+
@action
|
16
|
+
end
|
17
|
+
|
18
|
+
def command(name, &block)
|
19
|
+
obj = Command.new(name)
|
20
|
+
obj.parent = self
|
21
|
+
block.call(obj)
|
22
|
+
commands << obj
|
23
|
+
end
|
24
|
+
|
25
|
+
def commands
|
26
|
+
(@commands ||= [])
|
27
|
+
end
|
28
|
+
|
29
|
+
def options
|
30
|
+
(@options ||= [])
|
31
|
+
end
|
32
|
+
|
33
|
+
def switch(names, &block)
|
34
|
+
obj = Switch.new(names)
|
35
|
+
block.call(obj) if block_given?
|
36
|
+
options << obj
|
37
|
+
end
|
38
|
+
|
39
|
+
def flag(names, &block)
|
40
|
+
obj = Flag.new(names)
|
41
|
+
block.call(obj) if block_given?
|
42
|
+
options << obj
|
43
|
+
end
|
44
|
+
|
45
|
+
def parse_args(args, result)
|
46
|
+
return if args.empty?
|
47
|
+
arg = args.delete_at(0)
|
48
|
+
if (is_option? arg)
|
49
|
+
if (option = find_option(arg))
|
50
|
+
if (option.is_a? Flag)
|
51
|
+
raise InvalidCommand, "Flag #{arg} is missing a value" if args.empty?
|
52
|
+
value = args.delete_at(0)
|
53
|
+
else
|
54
|
+
value = true
|
55
|
+
end
|
56
|
+
target = self.parent ? :options : :global_options
|
57
|
+
option.keys.each{|key| result.send(target)[key] = value}
|
58
|
+
else
|
59
|
+
raise InvalidCommand, "#'{arg}' is not a valid option"
|
60
|
+
end
|
61
|
+
else
|
62
|
+
if (cmd = find_command(arg))
|
63
|
+
result.command = cmd
|
64
|
+
cmd.parse_args(args, result)
|
65
|
+
elsif (commands.empty?)
|
66
|
+
result.arguments << arg
|
67
|
+
else
|
68
|
+
raise InvalidCommand, "'#{arg}' is not a valid #{@name} command"
|
69
|
+
end
|
70
|
+
end
|
71
|
+
parse_args(args, result)
|
72
|
+
end
|
73
|
+
|
74
|
+
private
|
75
|
+
|
76
|
+
def find_option(name)
|
77
|
+
options.find{|opt| opt.correspond?(name)}
|
78
|
+
end
|
79
|
+
|
80
|
+
def find_command(name)
|
81
|
+
commands.find{|command| command.value_of_name.eql? name}
|
82
|
+
end
|
83
|
+
|
84
|
+
def is_option?(value)
|
85
|
+
value.start_with?('-')
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
|
90
|
+
module Option
|
91
|
+
|
92
|
+
setter :description
|
93
|
+
|
94
|
+
def initialize(names)
|
95
|
+
@s_name = names[:short]
|
96
|
+
@l_name = names[:long]
|
97
|
+
end
|
98
|
+
|
99
|
+
def keys
|
100
|
+
[@s_name, @l_name].compact
|
101
|
+
end
|
102
|
+
|
103
|
+
def help_keys
|
104
|
+
result = []
|
105
|
+
result << "-#{@s_name}" if @s_name
|
106
|
+
result << "--#{@l_name}" if @l_name
|
107
|
+
result
|
108
|
+
end
|
109
|
+
|
110
|
+
def correspond?(value)
|
111
|
+
return (value.sub('-','').eql? @s_name or value.sub('--','').eql? @l_name)
|
112
|
+
end
|
113
|
+
|
114
|
+
end
|
115
|
+
|
116
|
+
class Switch
|
117
|
+
|
118
|
+
include Option
|
119
|
+
|
120
|
+
end
|
121
|
+
|
122
|
+
class Flag
|
123
|
+
|
124
|
+
include Option
|
125
|
+
|
126
|
+
setter :default_value
|
127
|
+
setter :arg_name
|
128
|
+
|
129
|
+
end
|
130
|
+
|
131
|
+
class Command
|
132
|
+
|
133
|
+
setter :name
|
134
|
+
setter :summary
|
135
|
+
setter :description
|
136
|
+
setter :syntax
|
137
|
+
|
138
|
+
def initialize(name)
|
139
|
+
@name = name
|
140
|
+
end
|
141
|
+
|
142
|
+
include CommandContainer
|
143
|
+
|
144
|
+
end
|
145
|
+
|
146
|
+
class Program
|
147
|
+
|
148
|
+
setter :name
|
149
|
+
setter :author
|
150
|
+
setter :version
|
151
|
+
setter :description
|
152
|
+
|
153
|
+
include Help
|
154
|
+
include CommandContainer
|
155
|
+
|
156
|
+
def execute(args, context)
|
157
|
+
result = ParsedArgs.new
|
158
|
+
parse_args(args, result)
|
159
|
+
if result.command
|
160
|
+
action = result.command.get_action
|
161
|
+
context.instance_exec(result.global_options, result.options, result.arguments, &action)
|
162
|
+
else
|
163
|
+
say "Display UI"
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
end
|
168
|
+
|
169
|
+
|
170
|
+
class ParsedArgs
|
171
|
+
|
172
|
+
attr_reader :global_options
|
173
|
+
attr_reader :options
|
174
|
+
attr_reader :arguments
|
175
|
+
|
176
|
+
attr_accessor :command
|
177
|
+
|
178
|
+
def initialize
|
179
|
+
@global_options = {}
|
180
|
+
@options = {}
|
181
|
+
@arguments = []
|
182
|
+
end
|
183
|
+
|
184
|
+
def no_command?
|
185
|
+
return @command.nil?
|
186
|
+
end
|
187
|
+
|
188
|
+
end
|
189
|
+
|
190
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
<%= $terminal.color "NAME", :bold %>:
|
2
|
+
<%= @name %>
|
3
|
+
|
4
|
+
<%= $terminal.color "VERSION", :bold %>:
|
5
|
+
<%= @version %>
|
6
|
+
|
7
|
+
<%= $terminal.color "DESCRIPTION", :bold %>:
|
8
|
+
<%= @description %>
|
9
|
+
|
10
|
+
<%= $terminal.color "COMMANDS", :bold %>:
|
11
|
+
<% @commands.sort{|a,b| a.value_of_name <=> b.value_of_name}.each do |c| -%>
|
12
|
+
<%= "%-20s %s" % [c.value_of_name, c.value_of_description] %>
|
13
|
+
<% end %>
|
14
|
+
|
15
|
+
<% unless @options.empty? -%>
|
16
|
+
<%= $terminal.color "GLOBAL OPTIONS", :bold %>:
|
17
|
+
<% for option in @options -%>
|
18
|
+
|
19
|
+
<%= option.help_keys.join ', ' %>
|
20
|
+
<%= option.value_of_description %>
|
21
|
+
<% end -%>
|
22
|
+
<% end -%>
|
data/lib/rcoli.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'highline/import'
|
2
|
+
require 'rcoli/extensions'
|
3
|
+
require 'rcoli/help'
|
4
|
+
require 'rcoli/model'
|
5
|
+
|
6
|
+
|
7
|
+
@program = RCoLi::Program.new
|
8
|
+
|
9
|
+
def application(id, &block)
|
10
|
+
@program.name id
|
11
|
+
@program.command(:help) do |c|
|
12
|
+
c.description "Display help documentation"
|
13
|
+
c.action do |global_opts, opts, args|
|
14
|
+
@program.help
|
15
|
+
end
|
16
|
+
end
|
17
|
+
@program.instance_eval &block
|
18
|
+
end
|
19
|
+
|
20
|
+
at_exit {
|
21
|
+
begin
|
22
|
+
@program.execute(ARGV, self)
|
23
|
+
rescue InvalidCommand => e
|
24
|
+
say "#{@program.value_of_name}: #{e.message}. See '#{@program.value_of_name} --help'"
|
25
|
+
end
|
26
|
+
|
27
|
+
}
|
data/rcoli.gemspec
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "rcoli/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "rcoli"
|
7
|
+
s.version = RCoLi::VERSION
|
8
|
+
s.authors = ["Jiri Pisa"]
|
9
|
+
s.email = ["jirka.pisa@gmail.com"]
|
10
|
+
s.homepage = "http://jiripisa.com"
|
11
|
+
s.summary = "The complete solution for commandline application written in ruby."
|
12
|
+
s.description = "The complete solution for commandline application written in ruby."
|
13
|
+
|
14
|
+
s.files = `git ls-files`.split("\n")
|
15
|
+
s.require_paths = ["lib"]
|
16
|
+
|
17
|
+
s.add_runtime_dependency("highline", "~> 1.6.11")
|
18
|
+
|
19
|
+
s.add_development_dependency("rake")
|
20
|
+
end
|
metadata
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rcoli
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.5.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Jiri Pisa
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-03-25 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: highline
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 1.6.11
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 1.6.11
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: rake
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
description: The complete solution for commandline application written in ruby.
|
47
|
+
email:
|
48
|
+
- jirka.pisa@gmail.com
|
49
|
+
executables: []
|
50
|
+
extensions: []
|
51
|
+
extra_rdoc_files: []
|
52
|
+
files:
|
53
|
+
- .gitignore
|
54
|
+
- Gemfile
|
55
|
+
- Gemfile.lock
|
56
|
+
- README.md
|
57
|
+
- Rakefile
|
58
|
+
- lib/rcoli.rb
|
59
|
+
- lib/rcoli/extensions.rb
|
60
|
+
- lib/rcoli/help.rb
|
61
|
+
- lib/rcoli/model.rb
|
62
|
+
- lib/rcoli/templates/help.erb
|
63
|
+
- lib/rcoli/version.rb
|
64
|
+
- rcoli.gemspec
|
65
|
+
homepage: http://jiripisa.com
|
66
|
+
licenses: []
|
67
|
+
post_install_message:
|
68
|
+
rdoc_options: []
|
69
|
+
require_paths:
|
70
|
+
- lib
|
71
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
72
|
+
none: false
|
73
|
+
requirements:
|
74
|
+
- - ! '>='
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '0'
|
77
|
+
segments:
|
78
|
+
- 0
|
79
|
+
hash: -1633884952265524071
|
80
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ! '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
segments:
|
87
|
+
- 0
|
88
|
+
hash: -1633884952265524071
|
89
|
+
requirements: []
|
90
|
+
rubyforge_project:
|
91
|
+
rubygems_version: 1.8.24
|
92
|
+
signing_key:
|
93
|
+
specification_version: 3
|
94
|
+
summary: The complete solution for commandline application written in ruby.
|
95
|
+
test_files: []
|