gli 2.5.6 → 2.6.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- data/.travis.yml +1 -0
- data/Gemfile +1 -1
- data/features/step_definitions/todo_steps.rb +4 -0
- data/features/todo.feature +22 -0
- data/features/todo_legacy.feature +128 -0
- data/lib/gli.rb +3 -1
- data/lib/gli/app.rb +10 -2
- data/lib/gli/app_support.rb +39 -31
- data/lib/gli/command.rb +3 -2
- data/lib/gli/command_finder.rb +41 -0
- data/lib/gli/command_line_token.rb +0 -4
- data/lib/gli/command_support.rb +37 -64
- data/lib/gli/commands/doc.rb +12 -2
- data/lib/gli/commands/help.rb +3 -0
- data/lib/gli/commands/help_modules/command_help_format.rb +22 -5
- data/lib/gli/commands/scaffold.rb +1 -1
- data/lib/gli/exceptions.rb +17 -5
- data/lib/gli/gli_option_block_parser.rb +84 -0
- data/lib/gli/gli_option_parser.rb +116 -96
- data/lib/gli/option_parser_factory.rb +42 -10
- data/lib/gli/option_parsing_result.rb +19 -0
- data/lib/gli/version.rb +1 -1
- data/test/apps/todo/bin/todo +2 -0
- data/test/apps/todo/lib/todo/commands/make.rb +52 -0
- data/test/apps/todo_legacy/Gemfile +2 -0
- data/test/apps/todo_legacy/README.rdoc +6 -0
- data/test/apps/todo_legacy/Rakefile +23 -0
- data/test/apps/todo_legacy/bin/todo +61 -0
- data/test/apps/todo_legacy/lib/todo/commands/create.rb +24 -0
- data/test/apps/todo_legacy/lib/todo/commands/list.rb +63 -0
- data/test/apps/todo_legacy/lib/todo/commands/ls.rb +47 -0
- data/test/apps/todo_legacy/lib/todo/version.rb +3 -0
- data/test/apps/todo_legacy/test/tc_nothing.rb +14 -0
- data/test/apps/todo_legacy/todo.gemspec +23 -0
- data/test/apps/todo_legacy/todo.rdoc +5 -0
- data/test/tc_command.rb +84 -59
- data/test/{tc_compount_command.rb → tc_compound_command.rb} +0 -0
- data/test/tc_flag.rb +0 -1
- data/test/tc_gli.rb +2 -2
- data/test/tc_help.rb +11 -3
- data/test/tc_subcommand_parsing.rb +104 -0
- data/test/tc_subcommands.rb +1 -0
- data/test/tc_switch.rb +0 -1
- data/test/test_helper.rb +5 -0
- metadata +74 -13
- data/lib/gli/copy_options_to_aliases.rb +0 -33
@@ -1,27 +1,47 @@
|
|
1
1
|
module GLI
|
2
2
|
# Factory for creating an OptionParser based on app configuration and DSL calls
|
3
3
|
class OptionParserFactory
|
4
|
+
|
5
|
+
# Create an option parser factory for a command. This has the added
|
6
|
+
# feature of setting up -h and --help on the command if those
|
7
|
+
# options aren't otherwise configured, e.g. to allow todo add --help as an
|
8
|
+
# alternate to todo help add
|
9
|
+
def self.for_command(command,accepts)
|
10
|
+
self.new(command.flags,command.switches,accepts).tap { |factory|
|
11
|
+
add_help_switches_to_command(factory.option_parser,command)
|
12
|
+
}
|
13
|
+
end
|
14
|
+
|
4
15
|
# Create an OptionParserFactory for the given
|
5
16
|
# flags, switches, and accepts
|
6
17
|
def initialize(flags,switches,accepts)
|
7
18
|
@flags = flags
|
8
19
|
@switches = switches
|
9
|
-
@
|
20
|
+
@options_hash = {}
|
21
|
+
@option_parser = OptionParser.new do |opts|
|
22
|
+
self.class.setup_accepts(opts,accepts)
|
23
|
+
self.class.setup_options(opts,@switches,@options_hash)
|
24
|
+
self.class.setup_options(opts,@flags,@options_hash)
|
25
|
+
end
|
10
26
|
end
|
11
27
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
end
|
20
|
-
[option_parser,options]
|
28
|
+
attr_reader :option_parser
|
29
|
+
attr_reader :options_hash
|
30
|
+
|
31
|
+
def options_hash_with_defaults_set!
|
32
|
+
set_defaults(@flags,@options_hash)
|
33
|
+
set_defaults(@switches,@options_hash)
|
34
|
+
@options_hash
|
21
35
|
end
|
22
36
|
|
23
37
|
private
|
24
38
|
|
39
|
+
def set_defaults(options_by_name,options_hash)
|
40
|
+
options_by_name.each do |name,option|
|
41
|
+
options_hash[name] = option.default_value if options_hash[name].nil?
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
25
45
|
def self.setup_accepts(opts,accepts)
|
26
46
|
accepts.each do |object,block|
|
27
47
|
opts.accept(object) do |arg_as_string|
|
@@ -41,5 +61,17 @@ module GLI
|
|
41
61
|
end
|
42
62
|
end
|
43
63
|
|
64
|
+
def self.add_help_switches_to_command(option_parser,command)
|
65
|
+
help_args = %w(-h --help).reject { |_| command.has_option?(_) }
|
66
|
+
|
67
|
+
unless help_args.empty?
|
68
|
+
help_args << "Get help for #{command.name}"
|
69
|
+
option_parser.on(*help_args) do
|
70
|
+
raise CommandException.new(nil,command,0)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
|
44
76
|
end
|
45
77
|
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module GLI
|
2
|
+
class OptionParsingResult
|
3
|
+
attr_accessor :global_options
|
4
|
+
attr_accessor :command
|
5
|
+
attr_accessor :command_options
|
6
|
+
attr_accessor :arguments
|
7
|
+
|
8
|
+
def convert_to_openstruct!
|
9
|
+
@global_options = Options.new(@global_options)
|
10
|
+
@command_options = Options.new(@command_options)
|
11
|
+
self
|
12
|
+
end
|
13
|
+
|
14
|
+
# Allows us to splat this object into blocks and methods expecting parameters in this order
|
15
|
+
def to_a
|
16
|
+
[@global_options,@command,@command_options,@arguments]
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/gli/version.rb
CHANGED
data/test/apps/todo/bin/todo
CHANGED
@@ -17,6 +17,8 @@ end
|
|
17
17
|
sort_help (ENV['TODO_SORT_HELP'] || 'alpha').to_sym
|
18
18
|
wrap_help_text (ENV['TODO_WRAP_HELP_TEXT'] || 'to_terminal').to_sym
|
19
19
|
|
20
|
+
subcommand_option_handling :normal
|
21
|
+
|
20
22
|
program_desc 'Manages tasks'
|
21
23
|
program_long_desc "A test program that has a sophisticated UI that can be used to exercise a lot of GLI's power"
|
22
24
|
|
@@ -0,0 +1,52 @@
|
|
1
|
+
command [:make] do |c|
|
2
|
+
c.desc "Show long form"
|
3
|
+
c.flag [:l,:long]
|
4
|
+
|
5
|
+
c.desc 'make a new task'
|
6
|
+
c.command :task do |task|
|
7
|
+
task.desc 'make the task a long task'
|
8
|
+
task.flag [:l,:long]
|
9
|
+
|
10
|
+
task.action do |g,o,a|
|
11
|
+
puts 'new task'
|
12
|
+
puts a.join(',')
|
13
|
+
puts o[:long]
|
14
|
+
end
|
15
|
+
|
16
|
+
desc 'make a bug'
|
17
|
+
task.command :bug do |bug|
|
18
|
+
bug.desc 'make this bug in the legacy system'
|
19
|
+
bug.flag [:l,:legacy]
|
20
|
+
|
21
|
+
bug.action do |g,o,a|
|
22
|
+
puts 'new task bug'
|
23
|
+
puts a.join(',')
|
24
|
+
# All this .to_s is to make sure 1.8.7/REE don't convert nil to the string "nil"
|
25
|
+
puts o[:legacy].to_s
|
26
|
+
puts o[:long].to_s
|
27
|
+
puts o[:l].to_s
|
28
|
+
puts o[GLI::Command::PARENT][:l].to_s
|
29
|
+
puts o[GLI::Command::PARENT][:long].to_s
|
30
|
+
puts o[GLI::Command::PARENT][:legacy].to_s
|
31
|
+
puts o[GLI::Command::PARENT][GLI::Command::PARENT][:l].to_s
|
32
|
+
puts o[GLI::Command::PARENT][GLI::Command::PARENT][:long].to_s
|
33
|
+
puts o[GLI::Command::PARENT][GLI::Command::PARENT][:legacy].to_s
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
c.desc 'make a new context'
|
39
|
+
c.command :context do |context|
|
40
|
+
context.desc 'make the context a local context'
|
41
|
+
context.flag [:l,:local]
|
42
|
+
|
43
|
+
context.action do |g,o,a|
|
44
|
+
puts 'new context'
|
45
|
+
puts a.join(',')
|
46
|
+
puts o[:local].to_s
|
47
|
+
puts o[:long].to_s
|
48
|
+
puts o[:l].to_s
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'rake/clean'
|
2
|
+
require 'rubygems'
|
3
|
+
require 'rake/gempackagetask'
|
4
|
+
require 'rake/rdoctask'
|
5
|
+
|
6
|
+
Rake::RDocTask.new do |rd|
|
7
|
+
rd.main = "README.rdoc"
|
8
|
+
rd.rdoc_files.include("README.rdoc","lib/**/*.rb","bin/**/*")
|
9
|
+
rd.title = 'Your application title'
|
10
|
+
end
|
11
|
+
|
12
|
+
spec = eval(File.read('todo.gemspec'))
|
13
|
+
|
14
|
+
Rake::GemPackageTask.new(spec) do |pkg|
|
15
|
+
end
|
16
|
+
|
17
|
+
require 'rake/testtask'
|
18
|
+
Rake::TestTask.new do |t|
|
19
|
+
t.libs << "test"
|
20
|
+
t.test_files = FileList['test/tc_*.rb']
|
21
|
+
end
|
22
|
+
|
23
|
+
task :default => :test
|
@@ -0,0 +1,61 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# These would not be in a real GLI app; we do this so we can easily run this on the command line
|
4
|
+
$: << File.expand_path(File.join(File.dirname(__FILE__),'..','..','..','lib'))
|
5
|
+
$: << File.expand_path(File.join(File.dirname(__FILE__),'..','lib'))
|
6
|
+
|
7
|
+
require 'gli'
|
8
|
+
require 'todo/version'
|
9
|
+
|
10
|
+
|
11
|
+
if ENV['GLI1_COMPATIBILITY']
|
12
|
+
include GLI
|
13
|
+
else
|
14
|
+
include GLI::App
|
15
|
+
end
|
16
|
+
|
17
|
+
sort_help (ENV['TODO_SORT_HELP'] || 'alpha').to_sym
|
18
|
+
wrap_help_text (ENV['TODO_WRAP_HELP_TEXT'] || 'to_terminal').to_sym
|
19
|
+
|
20
|
+
program_desc 'Manages tasks'
|
21
|
+
program_long_desc "A test program that has a sophisticated UI that can be used to exercise a lot of GLI's power"
|
22
|
+
|
23
|
+
config_file "gli_test_todo.rc"
|
24
|
+
|
25
|
+
flag :flag
|
26
|
+
switch :switch
|
27
|
+
switch :otherswitch, :negatable => true
|
28
|
+
|
29
|
+
version Todo::VERSION
|
30
|
+
|
31
|
+
commands_from 'todo/commands'
|
32
|
+
commands_from File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'todo_plugins', 'commands'))
|
33
|
+
|
34
|
+
command :first do |c| c.action { |g,o,a| puts "first: #{a.join(',')}" } end
|
35
|
+
command :second do |c| c.action { |g,o,a| puts "second: #{a.join(',')}" } end
|
36
|
+
|
37
|
+
command :chained => [ :first, :second ]
|
38
|
+
command [:chained2,:ch2] => [ :second, :first ]
|
39
|
+
|
40
|
+
pre do |global,command,options,args|
|
41
|
+
# Pre logic here
|
42
|
+
# Return true to proceed; false to abort and not call the
|
43
|
+
# chosen command
|
44
|
+
# Use skips_pre before a command to skip this block
|
45
|
+
# on that command only
|
46
|
+
true
|
47
|
+
end
|
48
|
+
|
49
|
+
post do |global,command,options,args|
|
50
|
+
# Post logic here
|
51
|
+
# Use skips_post before a command to skip this
|
52
|
+
# block on that command only
|
53
|
+
end
|
54
|
+
|
55
|
+
on_error do |exception|
|
56
|
+
# Error logic here
|
57
|
+
# return false to skip default error handling
|
58
|
+
true
|
59
|
+
end
|
60
|
+
|
61
|
+
exit run(ARGV)
|
@@ -0,0 +1,24 @@
|
|
1
|
+
desc "Create a new task or context"
|
2
|
+
command [:create,:new] do |c|
|
3
|
+
c.desc "Make a new task"
|
4
|
+
c.arg_name 'task_name', :multiple
|
5
|
+
c.command :tasks do |tasks|
|
6
|
+
tasks.action do |global,options,args|
|
7
|
+
puts "#{args}"
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
c.desc "Make a new context"
|
12
|
+
c.arg_name 'context_name', :optional
|
13
|
+
c.command :contexts do |contexts|
|
14
|
+
contexts.action do |global,options,args|
|
15
|
+
puts "#{args}"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
c.default_desc "Makes a new task"
|
20
|
+
c.action do
|
21
|
+
puts "default action"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
@@ -0,0 +1,63 @@
|
|
1
|
+
desc "List things, such as tasks or contexts"
|
2
|
+
long_desc %(
|
3
|
+
List a whole lot of things that you might be keeping track of
|
4
|
+
in your overall todo list.
|
5
|
+
|
6
|
+
This is your go-to place or finding all of the things that you
|
7
|
+
might have
|
8
|
+
stored in
|
9
|
+
your todo databases.
|
10
|
+
)
|
11
|
+
command [:list] do |c|
|
12
|
+
c.default_command :tasks
|
13
|
+
|
14
|
+
c.desc "Show long form"
|
15
|
+
c.switch [:l,:long]
|
16
|
+
|
17
|
+
c.desc "List tasks"
|
18
|
+
c.long_desc %(
|
19
|
+
Lists all of your tasks that you have, in varying orders, and
|
20
|
+
all that stuff. Yes, this is long, but I need a long description.
|
21
|
+
)
|
22
|
+
c.command :tasks do |tasks|
|
23
|
+
tasks.desc "blah blah crud x whatever"
|
24
|
+
tasks.flag [:x], :must_match => Array
|
25
|
+
|
26
|
+
tasks.flag :flag
|
27
|
+
|
28
|
+
tasks.action do |global,options,args|
|
29
|
+
puts options[:x].inspect
|
30
|
+
puts "list tasks: #{args.join(',')}"
|
31
|
+
end
|
32
|
+
|
33
|
+
tasks.desc 'list open tasks'
|
34
|
+
tasks.command :open do |open|
|
35
|
+
open.action do |global,options,args|
|
36
|
+
puts "tasks open"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
tasks.default_desc 'list all tasks'
|
41
|
+
end
|
42
|
+
|
43
|
+
c.desc "List contexts"
|
44
|
+
c.long_desc %(
|
45
|
+
Lists all of your contexts, which are places you might be
|
46
|
+
where you can do stuff and all that.
|
47
|
+
)
|
48
|
+
c.command :contexts do |contexts|
|
49
|
+
|
50
|
+
contexts.desc "Foobar"
|
51
|
+
contexts.switch [:f,'foobar']
|
52
|
+
|
53
|
+
contexts.desc "Blah"
|
54
|
+
contexts.switch [:b]
|
55
|
+
|
56
|
+
contexts.flag :otherflag
|
57
|
+
|
58
|
+
contexts.action do |global,options,args|
|
59
|
+
puts "list contexts: #{args.join(',')}"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# This is copied so I can have two slightly different versions of the same thing
|
2
|
+
desc "LS things, such as tasks or contexts"
|
3
|
+
long_desc %(
|
4
|
+
List a whole lot of things that you might be keeping track of
|
5
|
+
in your overall todo list.
|
6
|
+
|
7
|
+
This is your go-to place or finding all of the things that you
|
8
|
+
might have
|
9
|
+
stored in
|
10
|
+
your todo databases.
|
11
|
+
)
|
12
|
+
command [:ls] do |c|
|
13
|
+
c.desc "Show long form"
|
14
|
+
c.switch [:l,:long]
|
15
|
+
|
16
|
+
c.desc "List tasks"
|
17
|
+
c.long_desc %(
|
18
|
+
Lists all of your tasks that you have, in varying orders, and
|
19
|
+
all that stuff. Yes, this is long, but I need a long description.
|
20
|
+
)
|
21
|
+
c.command :tasks do |tasks|
|
22
|
+
tasks.desc "blah blah crud x whatever"
|
23
|
+
tasks.flag [:x]
|
24
|
+
tasks.action do |global,options,args|
|
25
|
+
puts "ls tasks: #{args.join(',')}"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
c.desc "List contexts"
|
30
|
+
c.long_desc %(
|
31
|
+
Lists all of your contexts, which are places you might be
|
32
|
+
where you can do stuff and all that.
|
33
|
+
)
|
34
|
+
c.command :contexts do |contexts|
|
35
|
+
|
36
|
+
contexts.desc "Foobar"
|
37
|
+
contexts.switch [:f,'foobar']
|
38
|
+
|
39
|
+
contexts.desc "Blah"
|
40
|
+
contexts.switch [:b]
|
41
|
+
|
42
|
+
contexts.action do |global,options,args|
|
43
|
+
puts "ls contexts: #{args.join(',')}"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# Ensure we require the local version and not one we might have installed already
|
2
|
+
require File.join([File.dirname(__FILE__),'lib','todo','version.rb'])
|
3
|
+
spec = Gem::Specification.new do |s|
|
4
|
+
s.name = 'todo'
|
5
|
+
s.version = Todo::VERSION
|
6
|
+
s.author = 'Your Name Here'
|
7
|
+
s.email = 'your@email.address.com'
|
8
|
+
s.homepage = 'http://your.website.com'
|
9
|
+
s.platform = Gem::Platform::RUBY
|
10
|
+
s.summary = 'A description of your project'
|
11
|
+
# Add your other files here if you make them
|
12
|
+
s.files = %w(
|
13
|
+
bin/todo
|
14
|
+
)
|
15
|
+
s.require_paths << 'lib'
|
16
|
+
s.has_rdoc = true
|
17
|
+
s.extra_rdoc_files = ['README.rdoc','todo.rdoc']
|
18
|
+
s.rdoc_options << '--title' << 'todo' << '--main' << 'README.rdoc' << '-ri'
|
19
|
+
s.bindir = 'bin'
|
20
|
+
s.executables << 'todo'
|
21
|
+
s.add_development_dependency('rake')
|
22
|
+
s.add_development_dependency('rdoc')
|
23
|
+
end
|