gli 2.5.6 → 2.6.0.rc1

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.
Files changed (46) hide show
  1. data/.travis.yml +1 -0
  2. data/Gemfile +1 -1
  3. data/features/step_definitions/todo_steps.rb +4 -0
  4. data/features/todo.feature +22 -0
  5. data/features/todo_legacy.feature +128 -0
  6. data/lib/gli.rb +3 -1
  7. data/lib/gli/app.rb +10 -2
  8. data/lib/gli/app_support.rb +39 -31
  9. data/lib/gli/command.rb +3 -2
  10. data/lib/gli/command_finder.rb +41 -0
  11. data/lib/gli/command_line_token.rb +0 -4
  12. data/lib/gli/command_support.rb +37 -64
  13. data/lib/gli/commands/doc.rb +12 -2
  14. data/lib/gli/commands/help.rb +3 -0
  15. data/lib/gli/commands/help_modules/command_help_format.rb +22 -5
  16. data/lib/gli/commands/scaffold.rb +1 -1
  17. data/lib/gli/exceptions.rb +17 -5
  18. data/lib/gli/gli_option_block_parser.rb +84 -0
  19. data/lib/gli/gli_option_parser.rb +116 -96
  20. data/lib/gli/option_parser_factory.rb +42 -10
  21. data/lib/gli/option_parsing_result.rb +19 -0
  22. data/lib/gli/version.rb +1 -1
  23. data/test/apps/todo/bin/todo +2 -0
  24. data/test/apps/todo/lib/todo/commands/make.rb +52 -0
  25. data/test/apps/todo_legacy/Gemfile +2 -0
  26. data/test/apps/todo_legacy/README.rdoc +6 -0
  27. data/test/apps/todo_legacy/Rakefile +23 -0
  28. data/test/apps/todo_legacy/bin/todo +61 -0
  29. data/test/apps/todo_legacy/lib/todo/commands/create.rb +24 -0
  30. data/test/apps/todo_legacy/lib/todo/commands/list.rb +63 -0
  31. data/test/apps/todo_legacy/lib/todo/commands/ls.rb +47 -0
  32. data/test/apps/todo_legacy/lib/todo/version.rb +3 -0
  33. data/test/apps/todo_legacy/test/tc_nothing.rb +14 -0
  34. data/test/apps/todo_legacy/todo.gemspec +23 -0
  35. data/test/apps/todo_legacy/todo.rdoc +5 -0
  36. data/test/tc_command.rb +84 -59
  37. data/test/{tc_compount_command.rb → tc_compound_command.rb} +0 -0
  38. data/test/tc_flag.rb +0 -1
  39. data/test/tc_gli.rb +2 -2
  40. data/test/tc_help.rb +11 -3
  41. data/test/tc_subcommand_parsing.rb +104 -0
  42. data/test/tc_subcommands.rb +1 -0
  43. data/test/tc_switch.rb +0 -1
  44. data/test/test_helper.rb +5 -0
  45. metadata +74 -13
  46. 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
- @accepts = accepts
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
- # Return an option parser to parse the given flags, switches and accepts
13
- def option_parser
14
- options = {}
15
- option_parser = OptionParser.new do |opts|
16
- self.class.setup_accepts(opts,@accepts)
17
- self.class.setup_options(opts,@switches,options)
18
- self.class.setup_options(opts,@flags,options)
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
@@ -1,5 +1,5 @@
1
1
  module GLI
2
2
  unless const_defined? :VERSION
3
- VERSION = '2.5.6' #:nodoc:
3
+ VERSION = '2.6.0.rc1'
4
4
  end
5
5
  end
@@ -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,2 @@
1
+ source :rubygems
2
+ gemspec
@@ -0,0 +1,6 @@
1
+ = todo
2
+
3
+ Describe your project here
4
+
5
+ :include:todo.rdoc
6
+
@@ -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,3 @@
1
+ module Todo
2
+ VERSION = '0.0.1'
3
+ end
@@ -0,0 +1,14 @@
1
+ require 'test/unit'
2
+
3
+ class TC_testNothing < Test::Unit::TestCase
4
+
5
+ def setup
6
+ end
7
+
8
+ def teardown
9
+ end
10
+
11
+ def test_the_truth
12
+ assert true
13
+ end
14
+ end
@@ -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