escort 0.1.0 → 0.2.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.
Files changed (86) hide show
  1. checksums.yaml +8 -8
  2. data/.travis.yml +8 -0
  3. data/README.md +365 -14
  4. data/TODO.md +157 -44
  5. data/escort.gemspec +1 -0
  6. data/examples/{1_1_basic.rb → attic/1_1_basic.rb} +0 -0
  7. data/examples/{1_2_basic_requires_arguments.rb → attic/1_2_basic_requires_arguments.rb} +0 -0
  8. data/examples/{2_2_command.rb → attic/2_2_command.rb} +0 -0
  9. data/examples/{2_2_command_requires_arguments.rb → attic/2_2_command_requires_arguments.rb} +0 -0
  10. data/examples/{2_3_nested_commands.rb → attic/2_3_nested_commands.rb} +0 -0
  11. data/examples/{3_validations.rb → attic/3_validations.rb} +0 -0
  12. data/examples/{4_1_config_file.rb → attic/4_1_config_file.rb} +0 -0
  13. data/examples/{argument_handling → attic/argument_handling}/basic.rb +0 -0
  14. data/examples/{argument_handling → attic/argument_handling}/basic_command.rb +0 -0
  15. data/examples/{argument_handling → attic/argument_handling}/no_arguments.rb +0 -0
  16. data/examples/{argument_handling → attic/argument_handling}/no_arguments_command.rb +0 -0
  17. data/examples/{command_aliases → attic/command_aliases}/app.rb +0 -0
  18. data/examples/{config_file → attic/config_file}/.apprc2 +0 -0
  19. data/examples/{config_file → attic/config_file}/app.rb +0 -0
  20. data/examples/{config_file → attic/config_file}/sub_commands.rb +0 -0
  21. data/examples/{default_command → attic/default_command}/app.rb +0 -0
  22. data/examples/{sub_commands → attic/sub_commands}/app.rb +0 -0
  23. data/examples/{validation_basic → attic/validation_basic}/app.rb +0 -0
  24. data/examples/basic +10 -0
  25. data/examples/basic_conflicts +17 -0
  26. data/examples/basic_depends_on +25 -0
  27. data/examples/basic_flags +15 -0
  28. data/examples/basic_options +14 -0
  29. data/examples/basic_options_multi +15 -0
  30. data/examples/basic_require_arguments +17 -0
  31. data/examples/basic_texts +21 -0
  32. data/examples/basic_validations +21 -0
  33. data/examples/command +19 -0
  34. data/examples/commands/example_command.rb +13 -0
  35. data/lib/escort/action_command/base.rb +4 -0
  36. data/lib/escort/app.rb +33 -11
  37. data/lib/escort/formatter/borderless_table.rb +4 -0
  38. data/lib/escort/formatter/command.rb +87 -0
  39. data/lib/escort/formatter/commands.rb +36 -0
  40. data/lib/escort/formatter/default_help_formatter.rb +68 -73
  41. data/lib/escort/formatter/global_command.rb +17 -0
  42. data/lib/escort/formatter/option.rb +138 -0
  43. data/lib/escort/formatter/options.rb +17 -3
  44. data/lib/escort/formatter/shell_command_executor.rb +49 -0
  45. data/lib/escort/formatter/terminal.rb +17 -9
  46. data/lib/escort/formatter/terminal_formatter.rb +6 -0
  47. data/lib/escort/logger.rb +4 -4
  48. data/lib/escort/option_dependency_validator.rb +83 -0
  49. data/lib/escort/option_parser.rb +11 -1
  50. data/lib/escort/setup/configuration/reader.rb +0 -2
  51. data/lib/escort/setup/configuration/writer.rb +0 -2
  52. data/lib/escort/setup/dsl/command.rb +2 -7
  53. data/lib/escort/setup/dsl/global.rb +2 -9
  54. data/lib/escort/setup/dsl/options.rb +56 -0
  55. data/lib/escort/setup_accessor.rb +23 -6
  56. data/lib/escort/trollop.rb +4 -3
  57. data/lib/escort/validator.rb +4 -1
  58. data/lib/escort/version.rb +1 -1
  59. data/lib/escort.rb +8 -1
  60. data/spec/integration/basic_conflicts_spec.rb +47 -0
  61. data/spec/integration/basic_depends_on_spec.rb +275 -0
  62. data/spec/integration/basic_options_spec.rb +9 -21
  63. data/spec/integration/basic_options_with_multi_spec.rb +30 -0
  64. data/spec/integration/basic_spec.rb +5 -6
  65. data/spec/integration/basic_validations_spec.rb +77 -0
  66. data/spec/integration/basic_with_arguments_spec.rb +33 -0
  67. data/spec/integration/basic_with_text_fields_spec.rb +21 -0
  68. data/spec/lib/escort/formatter/command_spec.rb +238 -0
  69. data/spec/lib/escort/formatter/global_command_spec.rb +50 -0
  70. data/spec/lib/escort/formatter/option_spec.rb +300 -0
  71. data/spec/lib/escort/formatter/shell_command_executor_spec.rb +59 -0
  72. data/spec/lib/escort/formatter/string_splitter_spec.rb +12 -0
  73. data/spec/lib/escort/formatter/terminal_spec.rb +19 -0
  74. data/spec/lib/escort/setup_accessor_spec.rb +1 -0
  75. data/spec/spec_helper.rb +9 -3
  76. data/spec/support/integration_helpers.rb +2 -0
  77. data/spec/{helpers/execute_action_matcher.rb → support/matchers/execute_action_for_command_matcher.rb} +3 -3
  78. data/spec/support/matchers/execute_action_with_arguments_matcher.rb +25 -0
  79. data/spec/support/matchers/execute_action_with_options_matcher.rb +29 -0
  80. data/spec/support/matchers/exit_with_code_matcher.rb +29 -0
  81. data/spec/support/shared_contexts/integration_setup.rb +34 -0
  82. metadata +86 -28
  83. data/examples/basic/app.rb +0 -16
  84. data/lib/escort/formatter/common.rb +0 -58
  85. data/spec/helpers/exit_with_code_matcher.rb +0 -21
  86. data/spec/helpers/give_option_to_action_with_value_matcher.rb +0 -22
data/TODO.md CHANGED
@@ -1,62 +1,107 @@
1
1
  ROADMAP
2
2
 
3
- v0.1.0
4
- - some spec infrastructure DONE
5
- - a couple of basic specs DONE
6
- - some integration test infrastructure DONE
7
- - a couple of basic integration tests DONE
8
- - pull classes for formatting out into files DONE
9
- - summary and description for commands DONE
10
- - include command summary and description in help formatter DONE
11
- - rework how help is displayed for commands with summary and description DONE
12
- - the sub commands for command should use summary instead of description DONE
13
- - do for validation and action what I did for option within the dsl DONE
14
- - look again at conflicts support in dsl, we can probably do better naming for it DONE
15
- - up the version to 0.1.0
3
+ v0.2.0
4
+ - up the version to 0.2.0
16
5
  - tag and release
17
6
 
18
- v0.9.0
19
- - a few more tests
20
- - a few more integration tests
21
- - refactor the formatting code some more
22
- - pull some formatting code into separate classes
23
- - test some of the utility formatting code
24
- - up the version to 0.9.0
7
+
8
+ - test conflicts for non-exstant options (integration) DONE
9
+ - test all the new help stuff on option, for conflicts, dependencies, validations DONE
10
+ - fix up readme for conflicts block DONE
11
+ - rework validations to be part of the options block rather than in their own block DONE
12
+ - fix example, fix tests, fix readme DONE
13
+ - need to rework conflicts as currently not really very good DONE
14
+ - add dependencies to help text DONE
15
+ - add conflicts to help text DONE
16
+ - add validation texts to help text so that people can see what kind of values are valid DONE
17
+ - make sure we check conflicts for non-existant options DONE
18
+ - refactor the formatting code some more DONE
19
+ - pull some formatting code into separate classes DONE
20
+ - test some of the utility formatting code DONE
21
+ - fix up help text so that if arguments are mandatory they are shown as mandatory not optional DONE
22
+ - basic example with validations DONE
23
+ - integration test for validations DONE
24
+ - readme for validations DONE
25
+ - test the shell command executor, and the terminal class for width command DONE
26
+ - improve the readme to explain
27
+ - a basic app with no options DONE
28
+ - a basic app with options DONE
29
+ - supplying multiple of the same parameter using multi DONE
30
+ - a basic app with require arguments DONE
31
+ - a basic app specifying version, description and summary DONE
32
+ - test the readme for flags to make sure it works as expected DONE
33
+ - a basic app with dependant options (mention that a deadlock situation can occur if you're not careful) DONE
34
+ - example for conflicting options DONE
35
+ - integration test for conflicting options DONE
36
+ - readme for conflicting options DONE
37
+ - for print stacktrace, change it to print in INFO mode so that stacktrace not printed by default DONE
38
+ - BUG when a script requires arguments and user doesn't supply any escort treats this as an internal error and asks you to report it, this shouldn't be the case DONE
39
+ - depends_on support
40
+ - option depends on flag DONE
41
+ - flag depends on another flag DONE
42
+ - one option depends on another (the other must be not false not nil and not empty) DONE
43
+ - one option depends on specific value of another (the other must be of a specific values) DONE
44
+ - one option depends on several others (where are must be not false not nil and not empty) DONE
45
+ - one option depends on several others where some must have a specific value (some options have specific value, others are not false not nil and not empty) DONE
46
+ - error if option for which dependecy is being defined does not exist DONE
47
+ - error if depends on non-existant option DONE
48
+ - error if depends on itself DONE
49
+ - error if dependency not satisfied DONE
50
+ - error if missing on condition when specifying dependency DONE
51
+ - refactor the options dsl class dependency code DONE
52
+ - refactor the option_dependency_validator class to be nicer DONE
53
+ - integration test all the permutations of dependency specification with error and success cases etc DONE
54
+ - create a shortcut for dependency specification on the opt method options hash itself DONE
55
+ - fix up example for basic app with dependencies for options DONE
56
+
57
+ v0.4.0
58
+ - readme a basic app with config file (don't worry about explaining all the helper stuff that gets created)
59
+ - readme implementing and action for a basic app
60
+ - refactor terminal formatter and test it
61
+ - refactor borderless table and test it
62
+ - BUG parent_options when parent of command is global context doesn't seem to work???
63
+ - test the base command for actions well
64
+ - fix ppjson so that dependency suport feature is actually used
65
+ - readme a command app with options, validations, description, summary, require arguments and config file, integration tests for commands, example
66
+ - readme a sub command app with options, validations, description, summary, require arguments and config file
67
+ - extract all the dsl command stuff into a helper module so that global and command can be handled by the same code
68
+ - delete the stuff from the attic once it is no longer needed
69
+ - get rid of shell command executor new shell stuff (doesn't work in Jruby and not really needed anyway)
70
+ - up the version to 0.4.0
25
71
  - tag and release
26
72
 
73
+
27
74
  v1.0.0
28
- - rewrite the readme to explain:
29
- - a basic app with no options
30
- - a basic app with options
31
- - supplying multiple of the same parameter using multi
32
- - a basic app with require arguments
33
- - a basic app specifying version, description and summary
34
- - a basic app with options and validations
35
- - implementing and action for a basic app
36
- - a basic app with config file (don't worry about explaining all the helper stuff that gets created)
37
- - a basic app with conflicting options
38
- - a basic app with dependent options
39
- - a command app with options, validations, description, summary, require arguments and config file
40
- - a sub command app with options, validations, description, summary, require arguments and config file
41
- - rework the examples again to show of some/most of the features (along the lines of the integration tests and readme)
42
- - extract all the dsl command stuff into a helper module so that global and command can be handled by the same code
75
+ - perhaps rework actions with passing a class and having it being auto called
76
+ - implement servants for dealing with clumps of functionality, and action commands have access to all servants that were executed before them
77
+ - a few more tests (setup accessor, all the dsl classes)
78
+ - for borderless table, should be able to create another borderless table within a cell of an existing table
79
+ - have a think about how to make the integration tests a bit more robust, so that failures don't get swallowed (test for specific exit codes instead of non-zero exit code), fix the existing integration tests
80
+ - in trollop when errors are raised they should be wrapped as escort errors and propagate rather than being caught by trollop itself
81
+ - a few more integration tests (test that basic app automatically gets help and other automatic options)
43
82
  - up the version to 1.0.0
44
83
  - tag and release
45
84
  - get the blog updated with a new theme
46
85
  - put a new subscriber count widget on blog
47
86
  - blog Build Command-Line Apps Like a Pro Using Ruby and Escort
48
87
 
88
+ - rework the examples again to show of some/most of the features (along the lines of the integration tests and readme) DONE
89
+ - errors coming straigh out of configuration should still be caught by error handlers to only display stack trace when needed (refactor app create method) DONE
90
+ - readme for a basic app with conflicting options DONE
91
+ - readme for a basic app with dependent options DONE
92
+
49
93
  v1.0.1
50
- - more specs (setup accessor etc)
94
+ - more specs
51
95
  - more integration specs (more specs for the different types of options)
52
- - rework the integration specs and matchers so there are less moving parts (perhaps push some stuff down into a base class etc.)
53
96
  - lots more logging at different levels for debug purposes
54
- - add validation messages to help text
55
97
  - a way have helpers available when you don't want to have to create a command
56
98
  - the config auto option should not be included in the config file, same with other auto options
57
99
  - readme about how to actually pass the user config through to action and the fact that regardless if you have a config file or not, you can have a config var or not as part of the block variables
58
- - rewrite the help formatter to be a bit easier to understand (more like man output for output)
59
- - add depends support to dsl
100
+ - ability to specify a different command based on options declaratively or a convention for how to do different things for the same action based on options (bunch of options that are flags, options that are a clump of values etc)
101
+
102
+ - rework the integration specs and matchers so there are less moving parts (perhaps push some stuff down into a base class etc.) DONE
103
+ - rewrite the help formatter to be a bit easier to understand (more like man output for output) DONE
104
+ - add depends support to dsl DONE
60
105
 
61
106
  v1.0.2
62
107
  - more specs
@@ -68,7 +113,7 @@ v1.0.3
68
113
  - an option for setup that indicates it is a project specific CLI app
69
114
  - an options for setup that indicates it is an environment aware CLI app
70
115
  - make the configuration environment aware
71
- - make escort environment aware
116
+ - make escort environment aware (app.environment_aware)
72
117
  - json configuration should support defaults config
73
118
  - much better documentation and usage patterns
74
119
  - pull the terminal formatting stuff into separate gem
@@ -77,6 +122,33 @@ v1.0.3
77
122
 
78
123
 
79
124
  BUCKET
125
+ - dependencies for command options on options from parent commands or global
126
+ - a better way of executing action and servants for the actions
127
+
128
+ - specify the options via classes
129
+ #command.action StreamProvider::Commands::StopServer
130
+ - define servants for actions within context
131
+ #app.before_action :stop, :start, :restart do |action|
132
+ #action.servant :configatron, StreamProvider::Servants::ConfigatronServant
133
+ #end
134
+
135
+ #app.before_action :restart do |action|
136
+ #action.servant :blah, StreamProvider::Servants::BlahServant
137
+ #end
138
+ - a before action without command names in context
139
+ app.before :actions => :this - only action in current context
140
+ app.before :actions => :child - only child action in current context
141
+ app.before :actions => [:this, :child] - this action and child actions
142
+ app.before :actions => :descendant - all actions that descend from this one, but not this one
143
+
144
+ - can split out the shell command executor into a tiny gem for later use
145
+ - get the build working on ruby 1.8.7
146
+ - formatting code should support colours and styles for output
147
+ - formatting code should support a table with borders and stuff
148
+ - formatting code should support a simple progress bar for showing progress
149
+ - formatting code should be more well factored
150
+ - highline support should be added so that values can be asked for
151
+ - values should be asked for before validations are executed, since entered values should be validated
80
152
  - instead of before and after blocks, add before, after filters for commands, maybe
81
153
  - when no action found in the context we want to execute, it should error or at least print an error
82
154
  - can we flatten the configuration (as an option)
@@ -97,9 +169,9 @@ BUCKET
97
169
  - blog about dependencies with bundler, the spermy operator and what version will be chosen
98
170
  - blog about ppjson and how to use it
99
171
 
100
- - improve the terminal formatter, allowing wrapping text to anywhere, and tabular like output without an actual table, allowing configuring terminal of any size not just 80, spin it off a little separate project, with an example of how to possibly build a menu in it or something
101
- - BUG the help formatting is still not quite right as far as respecting the char limits and wrapping properly when doing tabular output!!!!
102
- - do a readme for how trollop was slightly modified to accept a formatter DONE
172
+ - improve the terminal formatter, allowing wrapping text to anywhere, and tabular like output without an actual table, allowing configuring terminal of any size not just 80, spin it off a little separate project, with an example of how to possibly build a menu in it or something DONE
173
+ - BUG the help formatting is still not quite right as far as respecting the char limits and wrapping properly when doing tabular output!!!! DONE
174
+ - do a readme for how trollop was slightly modified to accept a formatter
103
175
  - gemspec summary and description should be taken from the app definition/maybe
104
176
  - perhaps add a copyright with license to readme
105
177
  - via method missing we can make the dsl classes more robust by printing errors and exting when non-dsl methods are attempted
@@ -112,6 +184,32 @@ BUCKET
112
184
  PIE IN SKY
113
185
  - choosing default output format based on where the output is going STDOUT.tty?
114
186
  - look at ruby curses support a bit more closely and maybe use that for terminal stuff instead as it would be much better at it
187
+ - a library for specifying conditions and matching on those conditions
188
+ - possible syntax for conditions library:
189
+ Conditions.new do
190
+ _and do
191
+ _= a, 1
192
+ _not do
193
+ _or do
194
+ _nil :b
195
+ _empty :b
196
+ _false :b
197
+ end
198
+ end
199
+ _present :b
200
+ _present [:c, :d]
201
+ _nil :e
202
+ _empty :f
203
+ _false :g
204
+ _or do
205
+ _= :h, 5
206
+ _and do
207
+ _= :i, 7
208
+ _empty :j
209
+ end
210
+ end
211
+ end
212
+ end
115
213
 
116
214
 
117
215
 
@@ -150,3 +248,18 @@ DONE
150
248
  - better support for on_error blocks with explanations and examples of usage (roll exit code support into here), default handling of errors in block N/A
151
249
  - a convention for how to actually do the code that will handle the commands etc. DONE
152
250
  - support for infinitely nesting sub commands (is this really necessary) DONE
251
+
252
+ v0.1.0
253
+ - some spec infrastructure DONE
254
+ - a couple of basic specs DONE
255
+ - some integration test infrastructure DONE
256
+ - a couple of basic integration tests DONE
257
+ - pull classes for formatting out into files DONE
258
+ - summary and description for commands DONE
259
+ - include command summary and description in help formatter DONE
260
+ - rework how help is displayed for commands with summary and description DONE
261
+ - the sub commands for command should use summary instead of description DONE
262
+ - do for validation and action what I did for option within the dsl DONE
263
+ - look again at conflicts support in dsl, we can probably do better naming for it DONE
264
+ - up the version to 0.1.0 DONE
265
+ - tag and release DONE
data/escort.gemspec CHANGED
@@ -15,6 +15,7 @@ Gem::Specification.new do |gem|
15
15
  gem.add_development_dependency('rspec')
16
16
  gem.add_development_dependency('fakefs')
17
17
  gem.add_development_dependency('rake')
18
+ gem.add_development_dependency('travis-lint')
18
19
 
19
20
  gem.files = `git ls-files`.split($/)
20
21
  gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
File without changes
File without changes
File without changes
File without changes
data/examples/basic ADDED
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require File.expand_path(File.join(File.expand_path(__FILE__), "..", "..", "lib", "escort"))
4
+ require File.join(File.expand_path(__FILE__), "..", "commands", "example_command")
5
+
6
+ Escort::App.create do |app|
7
+ app.action do |options, arguments|
8
+ Escort::ExampleCommand.new(options, arguments).execute
9
+ end
10
+ end
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require File.expand_path(File.join(File.expand_path(__FILE__), "..", "..", "lib", "escort"))
4
+ require File.join(File.expand_path(__FILE__), "..", "commands", "example_command")
5
+
6
+ Escort::App.create do |app|
7
+ app.options do |opts|
8
+ opts.opt :flag1, "Flag 1", :short => '-f', :long => '--flag1', :type => :boolean
9
+ opts.opt :flag2, "Flag 2", :short => :none, :long => '--flag2', :type => :boolean
10
+
11
+ opts.conflict :flag1, :flag2, :flag3
12
+ end
13
+
14
+ app.action do |options, arguments|
15
+ Escort::ExampleCommand.new(options, arguments).execute
16
+ end
17
+ end
@@ -0,0 +1,25 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require File.expand_path(File.join(File.expand_path(__FILE__), "..", "..", "lib", "escort"))
4
+ require File.join(File.expand_path(__FILE__), "..", "commands", "example_command")
5
+
6
+ Escort::App.create do |app|
7
+ app.options do |opts|
8
+ opts.opt :flag1, "Flag 1", :short => '-f', :long => '--flag1', :type => :boolean
9
+ opts.opt :flag2, "Flag 2", :short => :none, :long => '--flag2', :type => :boolean, :default => true
10
+ opts.opt :option1, "Option1", :short => '-o', :long => '--option1', :type => :string
11
+ opts.opt :option2, "Option2", :short => :none, :long => '--option2', :type => :string, :multi => true
12
+ opts.opt :option3, "Option3", :short => :none, :long => '--option3', :type => :string
13
+ opts.opt :option4, "Option4", :short => :none, :long => '--option4', :type => :string
14
+
15
+ opts.dependency :option1, :on => :flag1
16
+ opts.dependency :option2, :on => [:flag1, :option1]
17
+ opts.dependency :option3, :on => {:option1 => 'foo'}
18
+ #opts.dependency :option4, :on => [{:flag1 => false}, :option1] #This will get you into big trouble as it can never be fulfilled
19
+ opts.dependency :option4, :on => [{:flag2 => false}, :option1]
20
+ end
21
+
22
+ app.action do |options, arguments|
23
+ Escort::ExampleCommand.new(options, arguments).execute
24
+ end
25
+ end
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require File.expand_path(File.join(File.expand_path(__FILE__), "..", "..", "lib", "escort"))
4
+ require File.join(File.expand_path(__FILE__), "..", "commands", "example_command")
5
+
6
+ Escort::App.create do |app|
7
+ app.options do |opts|
8
+ opts.opt :flag1, "Flag 1", :short => '-f', :long => '--flag1', :type => :boolean, :default => true
9
+ opts.opt :flag2, "Flag 2", :short => :none, :long => '--flag2', :type => :boolean
10
+ end
11
+
12
+ app.action do |options, arguments|
13
+ Escort::ExampleCommand.new(options, arguments).execute
14
+ end
15
+ end
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require File.expand_path(File.join(File.expand_path(__FILE__), "..", "..", "lib", "escort"))
4
+ require File.join(File.expand_path(__FILE__), "..", "commands", "example_command")
5
+
6
+ Escort::App.create do |app|
7
+ app.options do |opts|
8
+ opts.opt :option1, "Option1", :short => '-o', :long => '--option1', :type => :string, :default => "option 1"
9
+ end
10
+
11
+ app.action do |options, arguments|
12
+ Escort::ExampleCommand.new(options, arguments).execute
13
+ end
14
+ end
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require File.expand_path(File.join(File.expand_path(__FILE__), "..", "..", "lib", "escort"))
4
+ require File.join(File.expand_path(__FILE__), "..", "commands", "example_command")
5
+
6
+ Escort::App.create do |app|
7
+ app.options do |opts|
8
+ opts.opt :option1, "Option1", :short => '-o', :long => '--option1', :type => :string, :default => "option 1"
9
+ opts.opt :option2, "Option2", :short => :none, :long => '--option2', :type => :string, :multi => true
10
+ end
11
+
12
+ app.action do |options, arguments|
13
+ Escort::ExampleCommand.new(options, arguments).execute
14
+ end
15
+ end
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require File.expand_path(File.join(File.expand_path(__FILE__), "..", "..", "lib", "escort"))
4
+ require File.join(File.expand_path(__FILE__), "..", "commands", "example_command")
5
+
6
+ Escort::App.create do |app|
7
+ app.requires_arguments
8
+
9
+ app.options do |opts|
10
+ opts.opt :option1, "Option1", :short => '-o', :long => '--option1', :type => :string, :default => "option 1"
11
+ opts.opt :option2, "Option2", :short => :none, :long => '--option2', :type => :string, :multi => true
12
+ end
13
+
14
+ app.action do |options, arguments|
15
+ Escort::ExampleCommand.new(options, arguments).execute
16
+ end
17
+ end
@@ -0,0 +1,21 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require File.expand_path(File.join(File.expand_path(__FILE__), "..", "..", "lib", "escort"))
4
+ require File.join(File.expand_path(__FILE__), "..", "commands", "example_command")
5
+
6
+ Escort::App.create do |app|
7
+ app.version "0.1.1"
8
+ app.summary "Summary 1"
9
+ app.description "Description 1"
10
+
11
+ app.requires_arguments
12
+
13
+ app.options do |opts|
14
+ opts.opt :option1, "Option1", :short => '-o', :long => '--option1', :type => :string, :default => "option 1"
15
+ opts.opt :option2, "Option2", :short => :none, :long => '--option2', :type => :string, :multi => true
16
+ end
17
+
18
+ app.action do |options, arguments|
19
+ Escort::ExampleCommand.new(options, arguments).execute
20
+ end
21
+ end
@@ -0,0 +1,21 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require File.expand_path(File.join(File.expand_path(__FILE__), "..", "..", "lib", "escort"))
4
+ require File.join(File.expand_path(__FILE__), "..", "commands", "example_command")
5
+
6
+ Escort::App.create do |app|
7
+ app.options do |opts|
8
+ opts.opt :option1, "Option 1", :short => '-o', :long => '--option1', :type => :string
9
+ opts.opt :int1, "Int 1", :short => '-i', :long => '--int1', :type => :int
10
+ opts.opt :option2, "Option 2", :short => :none, :long => '--option2', :type => :string
11
+
12
+ opts.validate(:option1, "must be either 'foo' or 'bar'") { |option| ["foo", "bar"].include?(option) }
13
+ opts.validate(:int1, "must be between 10 and 20 exclusive") { |option| option > 10 && option < 20 }
14
+ opts.validate(:option2, "must be two words") {|option| option =~ /\w\s\w/}
15
+ opts.validate(:option2, "must be at least 20 characters long") {|option| option.length >= 20}
16
+ end
17
+
18
+ app.action do |options, arguments|
19
+ Escort::ExampleCommand.new(options, arguments).execute
20
+ end
21
+ end
data/examples/command ADDED
@@ -0,0 +1,19 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require File.expand_path(File.join(File.expand_path(__FILE__), "..", "..", "lib", "escort"))
4
+ require File.join(File.expand_path(__FILE__), "..", "commands", "example_command")
5
+
6
+ Escort::App.create do |app|
7
+ app.command :command1, :aliases => [:c1, :com1] do |command|
8
+ command.summary "Command summary 1"
9
+ command.description "Command description 1"
10
+
11
+ command.action do |options, arguments|
12
+ Escort::ExampleCommand.new(options, arguments).execute
13
+ end
14
+ end
15
+
16
+ app.action do |options, arguments|
17
+ Escort::ExampleCommand.new(options, arguments).execute
18
+ end
19
+ end
@@ -0,0 +1,13 @@
1
+ module Escort
2
+ class ExampleCommand < ::Escort::ActionCommand::Base
3
+ def execute
4
+ Escort::Logger.output.puts "Command: #{command_name}"
5
+ Escort::Logger.output.puts "Options: #{options}"
6
+ Escort::Logger.output.puts "Command options: #{command_options}"
7
+ Escort::Logger.output.puts "Arguments: #{arguments}"
8
+ if config
9
+ Escort::Logger.output.puts "User config: #{config}"
10
+ end
11
+ end
12
+ end
13
+ end
@@ -28,6 +28,10 @@ module Escort
28
28
  @command_context
29
29
  end
30
30
 
31
+ def command_name
32
+ command_context.first || :global
33
+ end
34
+
31
35
  def command_options
32
36
  @command_options ||= context_hash(command_context)[:options] || {}
33
37
  end
data/lib/escort/app.rb CHANGED
@@ -2,20 +2,40 @@ module Escort
2
2
  class App
3
3
  #TODO ensure that every command must have an action
4
4
  class << self
5
+ #def create(option_string = '', &block)
6
+ #cli_app_configuration = Escort::Setup::Dsl::Global.new(&block)
7
+ #setup = Escort::SetupAccessor.new(cli_app_configuration)
8
+ #app = self.new(option_string, setup)
9
+ #app.execute
10
+ #exit(0)
11
+ #end
12
+
5
13
  def create(option_string = '', &block)
6
- cli_app_configuration = Escort::Setup::Dsl::Global.new(&block)
7
- setup = Escort::SetupAccessor.new(cli_app_configuration)
8
- app = self.new(option_string, setup)
9
- app.execute
14
+ self.new(option_string, &block).setup_application.execute
10
15
  exit(0)
11
16
  end
12
17
  end
13
18
 
14
19
  attr_reader :setup, :option_string
15
20
 
16
- def initialize(option_string, setup)
17
- @setup = setup
21
+ def initialize(option_string, &block)
18
22
  @option_string = option_string
23
+ @setup = nil
24
+ @block = block
25
+ end
26
+
27
+ def setup_application
28
+ old_error_sev_threshold = error_logger.sev_threshold
29
+ begin
30
+ error_logger.sev_threshold = ::Logger::DEBUG
31
+ cli_app_configuration = Escort::Setup::Dsl::Global.new(&@block)
32
+ @setup = Escort::SetupAccessor.new(cli_app_configuration)
33
+ self
34
+ rescue => e
35
+ handle_escort_error(e)
36
+ ensure
37
+ error_logger.sev_threshold = old_error_sev_threshold
38
+ end
19
39
  end
20
40
 
21
41
  def execute
@@ -50,7 +70,9 @@ module Escort
50
70
 
51
71
  def execute_action(action, options, arguments, user_config)
52
72
  begin
73
+ #execute before servants here
53
74
  action.call(options, arguments, user_config)
75
+ #execute after servants here
54
76
  rescue => e
55
77
  handle_action_error(e)
56
78
  end
@@ -72,11 +94,11 @@ module Escort
72
94
 
73
95
  def handle_escort_error(e)
74
96
  if e.kind_of?(Escort::UserError)
75
- print_escort_error_message(e)
97
+ print_stacktrace(e)
76
98
  error_logger.debug{ "Escort app failed to execute successfully, due to user error" }
77
99
  exit(Escort::USER_ERROR_EXIT_CODE)
78
100
  elsif e.kind_of?(Escort::ClientError)
79
- print_escort_error_message(e)
101
+ print_stacktrace(e)
80
102
  error_logger.debug{ "Escort app failed to execute successfully, due to client setup error" }
81
103
  exit(Escort::CLIENT_ERROR_EXIT_CODE)
82
104
  else
@@ -99,13 +121,13 @@ module Escort
99
121
  end
100
122
 
101
123
  def print_stacktrace(e)
102
- error_logger.error{ e }
124
+ error_logger.error{ e.message }
125
+ error_logger.debug{ e }
103
126
  end
104
127
 
105
128
  def print_escort_error_message(e)
106
129
  print_stacktrace(e)
107
- error_logger.warn{ "\n\n" }
108
- error_logger.warn{ "An internal Escort error has occurred, you should probably report it by creating an issue on github!" }
130
+ error_logger.warn{ "An internal Escort error has occurred, you should probably report it by creating an issue on github! To get a stacktrace, up the verbosity level to DEBUG and execute your command again. Use --help for details." }
109
131
  end
110
132
  end
111
133
  end
@@ -1,3 +1,7 @@
1
+ #TODO needs some serious testing stuffs
2
+ #split out into many classes VirtuaRow, PhysicalRow, FormatterRow
3
+ #needs method each_formatted_row
4
+ #the printing out should only happen in the outputter class not in the table intself
1
5
  module Escort
2
6
  module Formatter
3
7
  class BorderlessTable