escort 0.2.1 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. checksums.yaml +8 -8
  2. data/.irbrc +2 -0
  3. data/.travis.yml +1 -1
  4. data/README.md +272 -3
  5. data/TODO.md +118 -71
  6. data/examples/.my_apprc +24 -0
  7. data/examples/basic_config_file +16 -0
  8. data/examples/basic_conflicts +1 -1
  9. data/examples/basic_with_everything +30 -0
  10. data/examples/suite_complex +65 -0
  11. data/examples/{command → suite_simple} +0 -0
  12. data/examples/suite_with_sub_commands +94 -0
  13. data/lib/escort.rb +6 -4
  14. data/lib/escort/action_command/base.rb +7 -5
  15. data/lib/escort/app.rb +2 -8
  16. data/lib/escort/auto_options.rb +5 -3
  17. data/lib/escort/formatter/cursor_position.rb +29 -0
  18. data/lib/escort/formatter/default_help_formatter.rb +37 -32
  19. data/lib/escort/formatter/option.rb +1 -1
  20. data/lib/escort/formatter/stream_output_formatter.rb +88 -0
  21. data/lib/escort/formatter/{borderless_table.rb → string_grid.rb} +21 -19
  22. data/lib/escort/formatter/string_splitter.rb +24 -4
  23. data/lib/escort/setup/configuration/loader.rb +8 -2
  24. data/lib/escort/setup/configuration/locator/chaining.rb +29 -0
  25. data/lib/escort/setup/configuration/locator/executing_script_directory.rb +15 -0
  26. data/lib/escort/setup/configuration/locator/specified_directory.rb +21 -0
  27. data/lib/escort/setup/configuration/reader.rb +4 -2
  28. data/lib/escort/setup/configuration/writer.rb +6 -2
  29. data/lib/escort/setup/dsl/command.rb +7 -8
  30. data/lib/escort/setup/dsl/global.rb +3 -51
  31. data/lib/escort/version.rb +1 -1
  32. data/spec/integration/basic_config_file_spec.rb +82 -0
  33. data/spec/integration/suite_simple_spec.rb +45 -0
  34. data/spec/integration/suite_sub_command_spec.rb +51 -0
  35. data/spec/lib/escort/action_command/base_spec.rb +200 -0
  36. data/spec/lib/escort/formatter/option_spec.rb +2 -2
  37. data/spec/lib/escort/formatter/stream_output_formatter_spec.rb +214 -0
  38. data/spec/lib/escort/formatter/string_grid_spec.rb +59 -0
  39. data/spec/lib/escort/setup/configuration/generator_spec.rb +101 -0
  40. data/spec/lib/escort/setup/configuration/loader_spec.rb +79 -0
  41. data/spec/lib/escort/setup/configuration/locator/chaining_spec.rb +81 -0
  42. data/spec/lib/escort/setup/configuration/locator/descending_to_home_spec.rb +57 -0
  43. data/spec/lib/escort/setup/configuration/locator/executing_script_directory_spec.rb +29 -0
  44. data/spec/lib/escort/setup/configuration/locator/specified_directory_spec.rb +33 -0
  45. data/spec/lib/escort/setup/configuration/merge_tool_spec.rb +41 -0
  46. data/spec/lib/escort/setup/configuration/reader_spec.rb +41 -0
  47. data/spec/lib/escort/setup/configuration/writer_spec.rb +75 -0
  48. data/spec/spec_helper.rb +2 -1
  49. metadata +44 -24
  50. data/examples/attic/1_1_basic.rb +0 -15
  51. data/examples/attic/1_2_basic_requires_arguments.rb +0 -15
  52. data/examples/attic/2_2_command.rb +0 -18
  53. data/examples/attic/2_2_command_requires_arguments.rb +0 -20
  54. data/examples/attic/2_3_nested_commands.rb +0 -26
  55. data/examples/attic/3_validations.rb +0 -31
  56. data/examples/attic/4_1_config_file.rb +0 -42
  57. data/examples/attic/argument_handling/basic.rb +0 -12
  58. data/examples/attic/argument_handling/basic_command.rb +0 -18
  59. data/examples/attic/argument_handling/no_arguments.rb +0 -14
  60. data/examples/attic/argument_handling/no_arguments_command.rb +0 -20
  61. data/examples/attic/command_aliases/app.rb +0 -31
  62. data/examples/attic/config_file/.apprc2 +0 -16
  63. data/examples/attic/config_file/app.rb +0 -78
  64. data/examples/attic/config_file/sub_commands.rb +0 -35
  65. data/examples/attic/default_command/app.rb +0 -20
  66. data/examples/attic/sub_commands/app.rb +0 -18
  67. data/examples/attic/validation_basic/app.rb +0 -31
  68. data/lib/escort/formatter/terminal_formatter.rb +0 -58
  69. data/lib/escort/setup/dsl/validations.rb +0 -25
@@ -1,12 +0,0 @@
1
- #!/usr/bin/env ruby
2
- require File.expand_path(File.join(File.expand_path(__FILE__), "..", "..", "..", "lib", "escort"))
3
-
4
- Escort::App.create do |app|
5
- app.options do
6
- opt :global_option, "Global option", :short => '-g', :long => '--global', :type => :string, :default => "global"
7
- end
8
-
9
- app.action do |global_options, arguments|
10
- puts "Action for my_command\nglobal options: #{global_options} \narguments: #{arguments}"
11
- end
12
- end
@@ -1,18 +0,0 @@
1
- #!/usr/bin/env ruby
2
- require File.expand_path(File.join(File.expand_path(__FILE__), "..", "..", "..", "lib", "escort"))
3
-
4
- Escort::App.create do |app|
5
- app.options do
6
- opt :global_option, "Global option", :short => '-g', :long => '--global', :type => :string, :default => "global"
7
- end
8
-
9
- app.command :my_command do |command|
10
- command.options do
11
- opt :do_stuff, "Do stuff", :short => :none, :long => '--do-stuff', :type => :boolean, :default => true
12
- end
13
-
14
- command.action do |global_options, command_options, arguments|
15
- puts "Action for my_command\nglobal options: #{global_options} \ncommand options: #{command_options}\narguments: #{arguments}"
16
- end
17
- end
18
- end
@@ -1,14 +0,0 @@
1
- #!/usr/bin/env ruby
2
- require File.expand_path(File.join(File.expand_path(__FILE__), "..", "..", "..", "lib", "escort"))
3
-
4
- Escort::App.create do |app|
5
- app.valid_with_no_arguments
6
-
7
- app.options do
8
- opt :global_option, "Global option", :short => '-g', :long => '--global', :type => :string, :default => "global"
9
- end
10
-
11
- app.action do |global_options, arguments|
12
- puts "Action for my_command\nglobal options: #{global_options} \narguments: #{arguments}"
13
- end
14
- end
@@ -1,20 +0,0 @@
1
- #!/usr/bin/env ruby
2
- require File.expand_path(File.join(File.expand_path(__FILE__), "..", "..", "..", "lib", "escort"))
3
-
4
- Escort::App.create do |app|
5
- app.valid_with_no_arguments
6
-
7
- app.options do
8
- opt :global_option, "Global option", :short => '-g', :long => '--global', :type => :string, :default => "global"
9
- end
10
-
11
- app.command :my_command do |command|
12
- command.options do
13
- opt :do_stuff, "Do stuff", :short => :none, :long => '--do-stuff', :type => :boolean, :default => true
14
- end
15
-
16
- command.action do |global_options, command_options, arguments|
17
- puts "Action for my_command\nglobal options: #{global_options} \ncommand options: #{command_options}\narguments: #{arguments}"
18
- end
19
- end
20
- end
@@ -1,31 +0,0 @@
1
- #!/usr/bin/env ruby
2
- require File.expand_path(File.join(File.expand_path(__FILE__), "..", "..", "..", "lib", "escort"))
3
-
4
- Escort::App.create do |app|
5
- #app.summary "An app that does crazy things"
6
- #app.description "An app that asdfk df;adf a;df a;dfj a;df a;ldfkj a;lksdjf a;ldjf a;lfdj a;lsdfkj a;ldsfjk a;lksdfj a;lskdfj a;lkdfj a;ldfkj a;ldfjk a;ldfkj adf"
7
-
8
- app.options do
9
- opt :global_option, "Global option", :short => '-g', :long => '--global', :type => :string, :default => "global"
10
- end
11
-
12
- app.command :my_command, :description => "Command that does stuff", :aliases => [:mc, :mooc] do |command|
13
- command.options do
14
- opt :do_stuff, "Do stuff", :short => :none, :long => '--do-stuff', :type => :boolean, :default => true
15
- end
16
-
17
- command.action do |global_options, command_options, arguments|
18
- puts "Action for my_command\nglobal options: #{global_options} \ncommand options: #{command_options}\narguments: #{arguments}"
19
- end
20
- end
21
-
22
- app.command :blah, :description => "Command that does stuff adlkfjal;sdf alsdkjfa;ldkfj a;lsdfjk a;lsdfj a;ldkfj a;ldfkj a;lsdfj a;lfdjk" do |command|
23
- command.options do
24
- opt :do_stuff, "Do stuff", :short => :none, :long => '--do-stuff', :type => :boolean, :default => true
25
- end
26
-
27
- command.action do |global_options, command_options, arguments|
28
- puts "Action for my_command\nglobal options: #{global_options} \ncommand options: #{command_options}\narguments: #{arguments}"
29
- end
30
- end
31
- end
@@ -1,16 +0,0 @@
1
- {
2
- "global_options": {
3
- "global_option": "local",
4
- "another_option": "world",
5
- "blah": true
6
- },
7
- "command_options": {
8
- "my_command": {
9
- "command_option": "foo"
10
- }
11
- },
12
- "user_data": {
13
- "hello": "world",
14
- "foo": null
15
- }
16
- }
@@ -1,78 +0,0 @@
1
- #!/usr/bin/env ruby
2
- require File.expand_path(File.join(File.expand_path(__FILE__), "..", "..", "..", "lib", "escort"))
3
-
4
- Escort::App.create do |app|
5
- app.summary "An app that does crazy things"
6
- app.description "An app that asdfk df;adf a;df a;dfj a;df a;ldfkj a;lksdjf a;ldjf a;lfdj a;lsdfkj a;ldsfjk a;lksdfj a;lskdfj a;lkdfj a;ldfkj a;ldfjk a;ldfkj adf"
7
-
8
- #app.config_file ".apprc", :autocreate => true
9
-
10
- app.options do
11
- opt :global_option, "Global option", :short => '-g', :long => '--global', :type => :string, :default => "global"
12
- opt :another_option, "Another option", :short => '-a', :long => '--another', :type => :string, :default => "hello"
13
- opt :blah, "Blah options", :short => '-b', :long => '--blah', :type => :flag
14
- end
15
-
16
- app.validations do |opts|
17
- opts.validate(:global_option, "must be either 'global' or 'local'") { |option| ["global", "local"].include?(option) }
18
- end
19
-
20
- app.action do |global_options, arguments, config|
21
- puts "Action for my_command\nglobal options: #{global_options} \narguments: #{arguments}\nuser config data: #{config}"
22
- #puts "Action for my_command\nglobal options: #{global_options} \narguments: #{arguments}"
23
- end
24
- end
25
-
26
- #config file is loaded automatically if it exists by walking up the directory tree when config file is specified DONE
27
- #values from config file are merged into the parser correctly for global DONE
28
- #values from config file are correctly overriden by those provided on the command line DONE
29
- #values from config file get validated correctly DONE
30
- #values from config file are merged into the parser correctly for commands DONE
31
- #user config data can be passed through to action handling code DONE
32
- #
33
- #config file automatically gets created in user home directory when autocreate is true
34
- #when config file is automatically created all the global and command options get put in there with default values
35
- #when option --config get specified the provided config file is loaded as the default config file then execution continues
36
- #when option --create-default-config is specified and autocreate is false a default config file is created, if it doesn't exist yet, before being read and execution continues
37
- #when option --create-config is specified a config file with that name and default values is created, if it doesn't exit yet, before being read and execution continues
38
- #another global option needs to be created to allow user to set it to be notified which config file if any is being used for this session
39
-
40
- #app.rb --create-config = './yaddarc'
41
- #app.rb --config = './yaddarc'
42
-
43
- #- ability to switch on and off default creation of config file X
44
- #- an option to read specific config file instead of the default X
45
- #- a flag to create a default config in a specific directory X
46
- #- the ability to by default read a config file by walking up the directory tree X
47
- #- config file options should be validated just like the command line options ??
48
- #- ability to configure global options and command specific options (through the file) ??
49
- #- ability to configure extra user data that may be needed (through the file) ??
50
- #how will we pass the user level configuration up to handling code???
51
-
52
- #by default no configuration file at all DONE
53
- #if config_file was configured on the app DONE
54
- # the app gets a global --config options which takes a path of file to use as configuration file
55
- # the app gets a global --create-config which can have a path passed to it which will mean it creates a file with that name
56
- # the app gets a global --create-default-config option which is a flag meaning it will create a file in home director with default name
57
- #if config_file specified and auto_create false DONE
58
- #program will attempt to look for file by walking up the directory tree on every invocation DONE
59
- #but file never gets automatically created DONE
60
- #if config_file specified and auto_create true
61
- #program will attempt to look for file by walking up the directory tree on every invocation
62
- #if it doesn't exist when app is run then file gets created with some default values in the user home directory
63
- #autoloading only works with files that are default named if custom named config file is created either manually or through --create-config then you can only used it via the --config global option, this is obvious
64
- #creating a default named config file via --create-config without passing in a path will allow you to run the script from that directory and have that file picked up in preference to anyother config file lower down in the directory tree (e.g. in the home directory), this way you can have the script installed globally and run it from different directories with different default options
65
- #config file format will be json:
66
- #{
67
- #:global_options => {
68
- #},
69
- #:command_options => {
70
- #:my_command => {
71
- #},
72
- #:blah_command => {
73
- #}
74
- #},
75
- #:user_data => {
76
- #}
77
- #}
78
- #need to validate the options parts of the config file to make sure there is no rubbish in there
@@ -1,35 +0,0 @@
1
- #!/usr/bin/env ruby
2
- require File.expand_path(File.join(File.expand_path(__FILE__), "..", "..", "..", "lib", "escort"))
3
-
4
- Escort::App.create do |app|
5
- app.summary "An app that does crazy things"
6
- app.description "An app that asdfk df;adf a;df a;dfj a;df a;ldfkj a;lksdjf a;ldjf a;lfdj a;lsdfkj a;ldsfjk a;lksdfj a;lskdfj a;lkdfj a;ldfkj a;ldfjk a;ldfkj adf"
7
-
8
- app.config_file ".apprc"#, :autocreate => true
9
-
10
- app.options do
11
- opt :global_option, "Global option", :short => '-g', :long => '--global', :type => :string, :default => "global"
12
- opt :another_option, "Another option", :short => '-a', :long => '--another', :type => :string, :default => "hello"
13
- opt :blah, "Blah options", :short => '-b', :long => '--blah', :type => :flag
14
- end
15
-
16
- app.validations do |opts|
17
- opts.validate(:global_option, "must be either 'global' or 'local'") { |option| ["global", "local"].include?(option) }
18
- end
19
-
20
- app.command :my_command, :description => "KJHLKJH askj aldkjfhakldfjh akdjfh alkdfhj alkdjhf alkjsdhf alkjsdhf aklsjdhf aklsjdhf akljdhf alkdjfh" do |command|
21
- command.options do
22
- opt :command_option, "Command option", :short => '-c', :long => '--command', :type => :string, :default => "blah"
23
- opt :do_stuff, "Do stuff", :short => :none, :long => '--do-stuff', :type => :boolean, :default => true
24
- end
25
-
26
- command.action do |global_options, command_options, arguments, config|
27
- puts "Action for my_command\nglobal options: #{global_options} \ncommand options: #{command_options}\narguments: #{arguments}\nuser config data: #{config}"
28
- end
29
- end
30
-
31
- #app.action do |global_options, arguments, config|
32
- #puts "Action for my_command\nglobal options: #{global_options} \narguments: #{arguments}\nuser config data: #{config}"
33
- ##puts "Action for my_command\nglobal options: #{global_options} \narguments: #{arguments}"
34
- #end
35
- end
@@ -1,20 +0,0 @@
1
- #!/usr/bin/env ruby
2
- require File.expand_path(File.join(File.expand_path(__FILE__), "..", "..", "..", "lib", "escort"))
3
-
4
- Escort::App.create do |app|
5
- app.default "-g 'local' my_command --no-do-stuff foobar"
6
-
7
- app.options do
8
- opt :global_option, "Global option", :short => '-g', :long => '--global', :type => :string, :default => "global"
9
- end
10
-
11
- app.command :my_command do |command|
12
- command.options do
13
- opt :do_stuff, "Do stuff", :short => :none, :long => '--do-stuff', :type => :boolean, :default => true
14
- end
15
-
16
- command.action do |global_options, command_options, arguments|
17
- puts "Action for my_command\nglobal options: #{global_options} \ncommand options: #{command_options}\narguments: #{arguments}"
18
- end
19
- end
20
- end
@@ -1,18 +0,0 @@
1
- #!/usr/bin/env ruby
2
- require File.expand_path(File.join(File.expand_path(__FILE__), "..", "..", "..", "lib", "escort"))
3
-
4
- Escort::App.create do |app|
5
- app.options do
6
- opt :global_option, "Global option", :short => '-g', :long => '--global', :type => :string, :default => "global"
7
- end
8
-
9
- app.command :my_command, :description => "KJHLKJH askj aldkjfhakldfjh akdjfh alkdfhj alkdjhf alkjsdhf alkjsdhf aklsjdhf aklsjdhf akljdhf alkdjfh" do |command|
10
- command.options do
11
- opt :do_stuff, "Do stuff", :short => :none, :long => '--do-stuff', :type => :boolean, :default => true
12
- end
13
-
14
- command.action do |global_options, command_options, arguments|
15
- puts "Action for my_command\nglobal options: #{global_options} \ncommand options: #{command_options}\narguments: #{arguments}"
16
- end
17
- end
18
- end
@@ -1,31 +0,0 @@
1
- #!/usr/bin/env ruby
2
- require File.expand_path(File.join(File.expand_path(__FILE__), "..", "..", "..", "lib", "escort"))
3
-
4
- Escort::App.create do |app|
5
- app.options do
6
- opt :global_option, "Global option", :short => '-g', :long => '--global', :type => :string, :default => "global"
7
- opt :multi_option, "Option that can be specified multiple times", :short => '-m', :long => '--multi', :type => :string, :multi => true
8
- opt :a_number, "Do stuff", :short => "-n", :long => '--number', :type => :int
9
- end
10
-
11
- app.validations do |opts|
12
- opts.validate(:global_option, "must be either 'global' or 'local'") { |option| ["global", "local"].include?(option) }
13
- opts.validate(:a_number, "must be between 10 and 20 exclusive") { |option| option > 10 && option < 20 }
14
- end
15
-
16
- app.command :my_command do |command|
17
- command.options do
18
- opt :do_stuff, "Do stuff", :short => :none, :long => '--do-stuff', :type => :boolean, :default => true
19
- opt :string_with_format, "String with format", :short => "-f", :long => '--format', :type => :string, :default => "blah yadda11111111111"
20
- end
21
-
22
- command.validations do |opts|
23
- opts.validate(:string_with_format, "should be two words") {|option| option =~ /\w\s\w/}
24
- opts.validate(:string_with_format, "should be at least 20 characters long") {|option| option.length >= 20}
25
- end
26
-
27
- command.action do |global_options, command_options, arguments|
28
- puts "Action for my_command\nglobal options: #{global_options} \ncommand options: #{command_options}\narguments: #{arguments}"
29
- end
30
- end
31
- end
@@ -1,58 +0,0 @@
1
- #TODO rename to StreamOutputFormatter
2
- #get rid of the display method, it doesn't really add anything
3
- #the max_width should be max_line_width not terminal_columns, there should be no default max_width
4
- #indent_count should be indent_width
5
- #probably don't really need indent_char, we can assume it is a space
6
- #this will only work well with ASCII chars only!!!
7
- module Escort
8
- module Formatter
9
- class TerminalFormatter
10
- class << self
11
- def display(stream = $stdout, max_width = Terminal::DEFAULT_WIDTH, &block)
12
- formatter = self.new(stream, max_width)
13
- block.call(formatter)
14
- end
15
- end
16
-
17
- attr_reader :stream, :indent_char, :indent_count, :terminal_columns
18
-
19
- def initialize(stream = $stdout, max_width = Terminal::DEFAULT_WIDTH)
20
- @stream = stream
21
- @indent_char = " "
22
- @indent_count = 0
23
- @terminal_columns = (max_width < Terminal::DEFAULT_WIDTH/2 ? Terminal::DEFAULT_WIDTH/2 : max_width)
24
- end
25
-
26
- def put(data, options = {:newlines => 0})
27
- segments = StringSplitter.new(terminal_columns - current_indent_string.size - 1).split(data.to_s)
28
- segments.each do |segment|
29
- stream.print "#{current_indent_string}#{segment}"
30
- end
31
- newline(options[:newlines])
32
- end
33
-
34
- def puts(data)
35
- put(data, :newlines => 1)
36
- end
37
-
38
- def indent(count, &block)
39
- @indent_count += count
40
- block.call
41
- @indent_count -= count
42
- end
43
-
44
- def table(options = {}, &block)
45
- BorderlessTable.new(self, options).output(&block)
46
- newline(options[:newlines] || 1)
47
- end
48
-
49
- def newline(newline_count = 1)
50
- stream.print("\n" * newline_count)
51
- end
52
-
53
- def current_indent_string
54
- indent_char * indent_count
55
- end
56
- end
57
- end
58
- end
@@ -1,25 +0,0 @@
1
- module Escort
2
- module Setup
3
- module Dsl
4
- class Validations
5
- class << self
6
- def validations(command_name, instance, &block)
7
- block.call(instance) if block_given?
8
- rescue => e
9
- raise Escort::ClientError.new("Problem with syntax of #{instance.instance_variable_get(:"@command_name")} validations block", e)
10
- end
11
- end
12
-
13
- def initialize(command_name = :global)
14
- @command_name = command_name
15
- @validations = {}
16
- end
17
-
18
- def validate(name, description, &block)
19
- @validations[name] ||= []
20
- @validations[name] << {:desc => description, :block => block}
21
- end
22
- end
23
- end
24
- end
25
- end