escort 0.0.1 → 0.1.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.
- checksums.yaml +15 -0
- data/.gitignore +1 -0
- data/.irbrc +1 -0
- data/.rspec +3 -0
- data/.rvmrc +22 -0
- data/README.md +31 -56
- data/TODO.md +152 -0
- data/escort.gemspec +6 -2
- data/examples/1_1_basic.rb +15 -0
- data/examples/1_2_basic_requires_arguments.rb +15 -0
- data/examples/2_2_command.rb +18 -0
- data/examples/2_2_command_requires_arguments.rb +20 -0
- data/examples/2_3_nested_commands.rb +26 -0
- data/examples/3_validations.rb +31 -0
- data/examples/4_1_config_file.rb +42 -0
- data/examples/argument_handling/basic.rb +12 -0
- data/examples/argument_handling/basic_command.rb +18 -0
- data/examples/argument_handling/no_arguments.rb +14 -0
- data/examples/argument_handling/no_arguments_command.rb +20 -0
- data/examples/basic/app.rb +16 -0
- data/examples/command_aliases/app.rb +31 -0
- data/examples/config_file/.apprc2 +16 -0
- data/examples/config_file/app.rb +78 -0
- data/examples/config_file/sub_commands.rb +35 -0
- data/examples/default_command/app.rb +20 -0
- data/examples/sub_commands/app.rb +18 -0
- data/examples/validation_basic/app.rb +31 -0
- data/lib/escort.rb +51 -4
- data/lib/escort/action_command/base.rb +79 -0
- data/lib/escort/action_command/escort_utility_command.rb +53 -0
- data/lib/escort/app.rb +89 -36
- data/lib/escort/arguments.rb +20 -0
- data/lib/escort/auto_options.rb +71 -0
- data/lib/escort/error/error.rb +50 -0
- data/lib/escort/formatter/borderless_table.rb +102 -0
- data/lib/escort/formatter/common.rb +58 -0
- data/lib/escort/formatter/default_help_formatter.rb +106 -0
- data/lib/escort/formatter/options.rb +13 -0
- data/lib/escort/formatter/string_splitter.rb +30 -0
- data/lib/escort/formatter/terminal.rb +22 -0
- data/lib/escort/formatter/terminal_formatter.rb +52 -0
- data/lib/escort/global_pre_parser.rb +43 -0
- data/lib/escort/logger.rb +75 -0
- data/lib/escort/option_parser.rb +145 -0
- data/lib/escort/setup/configuration/generator.rb +75 -0
- data/lib/escort/setup/configuration/instance.rb +33 -0
- data/lib/escort/setup/configuration/loader.rb +37 -0
- data/lib/escort/setup/configuration/locator/base.rb +19 -0
- data/lib/escort/setup/configuration/locator/descending_to_home.rb +23 -0
- data/lib/escort/setup/configuration/merge_tool.rb +38 -0
- data/lib/escort/setup/configuration/reader.rb +36 -0
- data/lib/escort/setup/configuration/writer.rb +44 -0
- data/lib/escort/setup/dsl/action.rb +17 -0
- data/lib/escort/setup/dsl/command.rb +74 -0
- data/lib/escort/setup/dsl/config_file.rb +13 -0
- data/lib/escort/setup/dsl/global.rb +84 -0
- data/lib/escort/setup/dsl/options.rb +25 -0
- data/lib/escort/setup/dsl/validations.rb +25 -0
- data/lib/escort/setup_accessor.rb +194 -0
- data/lib/escort/trollop.rb +15 -4
- data/lib/escort/utils.rb +21 -0
- data/lib/escort/validator.rb +42 -0
- data/lib/escort/version.rb +1 -1
- data/spec/helpers/execute_action_matcher.rb +21 -0
- data/spec/helpers/exit_with_code_matcher.rb +21 -0
- data/spec/helpers/give_option_to_action_with_value_matcher.rb +22 -0
- data/spec/integration/basic_options_spec.rb +53 -0
- data/spec/integration/basic_spec.rb +24 -0
- data/spec/lib/escort/formatter/string_splitter_spec.rb +38 -0
- data/spec/lib/escort/setup_accessor_spec.rb +42 -0
- data/spec/lib/escort/utils_spec.rb +30 -0
- data/spec/spec_helper.rb +22 -0
- metadata +128 -16
- data/lib/escort/command.rb +0 -23
- data/lib/escort/dsl.rb +0 -20
- data/lib/escort/global_dsl.rb +0 -11
@@ -0,0 +1,24 @@
|
|
1
|
+
describe "Escort basic app with no options defined" do
|
2
|
+
subject { Escort::App.create(option_string, &app_configuration) }
|
3
|
+
let(:result) { [] }
|
4
|
+
|
5
|
+
let(:app_configuration) do
|
6
|
+
->(app) do
|
7
|
+
app.action do |options, arguments|
|
8
|
+
result << :global
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
context "when called with empty option string" do
|
14
|
+
let(:option_string) { "" }
|
15
|
+
it("should exit with code 0") { expect{ subject }.to exit_with_code(0) }
|
16
|
+
it("should execute the global action") { expect{subject}.to execute_action(:global, result) }
|
17
|
+
end
|
18
|
+
|
19
|
+
context "when called with non-empty option string" do
|
20
|
+
let(:option_string) { "hello" }
|
21
|
+
it("exit code should be 0") { expect{ subject }.to exit_with_code(0) }
|
22
|
+
it("should execute the global action") { expect{subject}.to execute_action(:global, result) }
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
describe Escort::Formatter::StringSplitter do
|
2
|
+
let(:splitter) {Escort::Formatter::StringSplitter.new(max_segment_width)}
|
3
|
+
|
4
|
+
describe "#split" do
|
5
|
+
subject {splitter.split(string)}
|
6
|
+
|
7
|
+
context "when segment width is 10" do
|
8
|
+
let(:max_segment_width) { 10 }
|
9
|
+
|
10
|
+
context "and string is 'abc123'" do
|
11
|
+
let(:string) {'abc123'}
|
12
|
+
it("should produce 1 segment") { subject.size.should == 1 }
|
13
|
+
it("first segment should be 'abc123'") { subject[0].should == 'abc123' }
|
14
|
+
end
|
15
|
+
|
16
|
+
context "and string is 'abc1234567'" do
|
17
|
+
let(:string) {'abc1234567'}
|
18
|
+
it("should produce 1 segment") { subject.size.should == 1 }
|
19
|
+
it("first segment should be 'abc1234567'") { subject[0].should == 'abc1234567' }
|
20
|
+
end
|
21
|
+
|
22
|
+
context "and string is 'abc123abc456'" do
|
23
|
+
let(:string) {'abc123abc456'}
|
24
|
+
it("should produce 2 segments") { subject.size.should == 2 }
|
25
|
+
it("first segment should be 'abc123abc4'") { subject[0].should == 'abc123abc4' }
|
26
|
+
it("first segment should be '56'") { subject[1].should == '56' }
|
27
|
+
end
|
28
|
+
|
29
|
+
context "and string is 'abc123abc456bbbcccddd'" do
|
30
|
+
let(:string) {'abc123abc456bbbcccddd'}
|
31
|
+
it("should produce 3 segments") { subject.size.should == 3 }
|
32
|
+
it("first segment should be 'abc123abc4'") { subject[0].should == 'abc123abc4' }
|
33
|
+
it("first segment should be '56bbbcccdd'") { subject[1].should == '56bbbcccdd' }
|
34
|
+
it("first segment should be 'd'") { subject[2].should == 'd' }
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
describe Escort::SetupAccessor do
|
2
|
+
let(:setup) { Escort::SetupAccessor.new(app_configuration) }
|
3
|
+
let(:global_app_configuration) do
|
4
|
+
Escort::Setup::Dsl::Global.new do |app|
|
5
|
+
app.options do |opts|
|
6
|
+
opts.opt :option1, "option1", :short => :none, :long => '--option1', :type => :string
|
7
|
+
end
|
8
|
+
|
9
|
+
app.action do |options, arguments|
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
let(:command_app_configuration) do
|
15
|
+
end
|
16
|
+
|
17
|
+
let(:sub_command_app_configuration) do
|
18
|
+
end
|
19
|
+
|
20
|
+
#context is nil
|
21
|
+
#no context supplied at all
|
22
|
+
#context is not an array
|
23
|
+
describe '#options_for' do
|
24
|
+
subject {setup.options_for(context)}
|
25
|
+
|
26
|
+
context "when app has no sub commands" do
|
27
|
+
let(:app_configuration) {global_app_configuration}
|
28
|
+
|
29
|
+
context "and context is global" do
|
30
|
+
let(:context) { [] }
|
31
|
+
it(":option1 should be present") {subject[:option1].should_not be_nil}
|
32
|
+
end
|
33
|
+
|
34
|
+
context "and context is an unknown command" do
|
35
|
+
let(:context) { ['hello'] }
|
36
|
+
it("should not raise an exception") { expect{subject}.to_not raise_error }
|
37
|
+
it("result should be a hash") { subject.class.should == Hash }
|
38
|
+
it("result should be empty") { subject.should be_empty }
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
describe Escort::Utils do
|
2
|
+
describe '::symbolize_keys' do
|
3
|
+
subject {Escort::Utils.symbolize_keys(hash)}
|
4
|
+
|
5
|
+
context "when single level hash" do
|
6
|
+
let(:hash) { {'a' => 1, :b => 2} }
|
7
|
+
it("the :a key should be a symbol") {subject[:a].should == 1}
|
8
|
+
it("the :b key should be a symbol") {subject[:b].should == 2}
|
9
|
+
end
|
10
|
+
|
11
|
+
context "when hash has nested hashes" do
|
12
|
+
let(:hash) { {'a' => 1, :b => {'c' => {'d' => 2}}} }
|
13
|
+
it("the :a key should be a symbol") {subject[:a].should == 1}
|
14
|
+
it("the nested keys, :b, :c and :d should all be symbols") {subject[:b][:c][:d].should == 2}
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe '::tokenize_option_string' do
|
19
|
+
subject {Escort::Utils.tokenize_option_string(option_string)}
|
20
|
+
|
21
|
+
context "when option string has short option, long option and argument" do
|
22
|
+
let(:option_string) {"-a 1 --foo='bar blah' yadda"}
|
23
|
+
it("tokenized string should have 4 values") {subject.size.should == 4}
|
24
|
+
it("the short option should be a separate token") {subject[0].should == '-a'}
|
25
|
+
it("the short option value should be a separate token") {subject[1].should == '1'}
|
26
|
+
it("the long option and value should be one token") {subject[2].should == '--foo=bar blah'}
|
27
|
+
it("the argument should be a separate token") {subject[3].should == 'yadda'}
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'escort'
|
2
|
+
#helpers
|
3
|
+
require 'helpers/exit_with_code_matcher'
|
4
|
+
require 'helpers/execute_action_matcher'
|
5
|
+
require 'helpers/give_option_to_action_with_value_matcher'
|
6
|
+
# This file was generated by the `rspec --init` command. Conventionally, all
|
7
|
+
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
|
8
|
+
# Require this file using `require "spec_helper"` to ensure that it is only
|
9
|
+
# loaded once.
|
10
|
+
#
|
11
|
+
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
12
|
+
RSpec.configure do |config|
|
13
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
14
|
+
config.run_all_when_everything_filtered = true
|
15
|
+
config.filter_run :focus
|
16
|
+
|
17
|
+
# Run specs in random order to surface order dependencies. If you find an
|
18
|
+
# order dependency and want to debug it, you can fix the order by providing
|
19
|
+
# the seed, which is printed after each run.
|
20
|
+
# --seed 1234
|
21
|
+
config.order = 'random'
|
22
|
+
end
|
metadata
CHANGED
@@ -1,19 +1,61 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: escort
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
5
|
-
prerelease:
|
4
|
+
version: 0.1.0
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Alan Skorkin
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date: 2013-
|
13
|
-
dependencies:
|
14
|
-
|
15
|
-
|
16
|
-
|
11
|
+
date: 2013-02-28 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rspec
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ! '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ! '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: fakefs
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ! '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ! '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ! '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
description: Writing even complex command-line apps should be quick, easy and fun.
|
56
|
+
Escort takes the excellent Trollop option parser and adds a whole bunch of awesome
|
57
|
+
features to produce a library you will always want to turn to when a 'quick script'
|
58
|
+
is in order.
|
17
59
|
email:
|
18
60
|
- alan@skorks.com
|
19
61
|
executables: []
|
@@ -21,40 +63,110 @@ extensions: []
|
|
21
63
|
extra_rdoc_files: []
|
22
64
|
files:
|
23
65
|
- .gitignore
|
66
|
+
- .irbrc
|
67
|
+
- .rspec
|
68
|
+
- .rvmrc
|
24
69
|
- Gemfile
|
25
70
|
- LICENSE.txt
|
26
71
|
- README.md
|
27
72
|
- Rakefile
|
73
|
+
- TODO.md
|
28
74
|
- escort.gemspec
|
75
|
+
- examples/1_1_basic.rb
|
76
|
+
- examples/1_2_basic_requires_arguments.rb
|
77
|
+
- examples/2_2_command.rb
|
78
|
+
- examples/2_2_command_requires_arguments.rb
|
79
|
+
- examples/2_3_nested_commands.rb
|
80
|
+
- examples/3_validations.rb
|
81
|
+
- examples/4_1_config_file.rb
|
82
|
+
- examples/argument_handling/basic.rb
|
83
|
+
- examples/argument_handling/basic_command.rb
|
84
|
+
- examples/argument_handling/no_arguments.rb
|
85
|
+
- examples/argument_handling/no_arguments_command.rb
|
86
|
+
- examples/basic/app.rb
|
87
|
+
- examples/command_aliases/app.rb
|
88
|
+
- examples/config_file/.apprc2
|
89
|
+
- examples/config_file/app.rb
|
90
|
+
- examples/config_file/sub_commands.rb
|
91
|
+
- examples/default_command/app.rb
|
92
|
+
- examples/sub_commands/app.rb
|
93
|
+
- examples/validation_basic/app.rb
|
29
94
|
- lib/escort.rb
|
95
|
+
- lib/escort/action_command/base.rb
|
96
|
+
- lib/escort/action_command/escort_utility_command.rb
|
30
97
|
- lib/escort/app.rb
|
31
|
-
- lib/escort/
|
32
|
-
- lib/escort/
|
33
|
-
- lib/escort/
|
98
|
+
- lib/escort/arguments.rb
|
99
|
+
- lib/escort/auto_options.rb
|
100
|
+
- lib/escort/error/error.rb
|
101
|
+
- lib/escort/formatter/borderless_table.rb
|
102
|
+
- lib/escort/formatter/common.rb
|
103
|
+
- lib/escort/formatter/default_help_formatter.rb
|
104
|
+
- lib/escort/formatter/options.rb
|
105
|
+
- lib/escort/formatter/string_splitter.rb
|
106
|
+
- lib/escort/formatter/terminal.rb
|
107
|
+
- lib/escort/formatter/terminal_formatter.rb
|
108
|
+
- lib/escort/global_pre_parser.rb
|
109
|
+
- lib/escort/logger.rb
|
110
|
+
- lib/escort/option_parser.rb
|
111
|
+
- lib/escort/setup/configuration/generator.rb
|
112
|
+
- lib/escort/setup/configuration/instance.rb
|
113
|
+
- lib/escort/setup/configuration/loader.rb
|
114
|
+
- lib/escort/setup/configuration/locator/base.rb
|
115
|
+
- lib/escort/setup/configuration/locator/descending_to_home.rb
|
116
|
+
- lib/escort/setup/configuration/merge_tool.rb
|
117
|
+
- lib/escort/setup/configuration/reader.rb
|
118
|
+
- lib/escort/setup/configuration/writer.rb
|
119
|
+
- lib/escort/setup/dsl/action.rb
|
120
|
+
- lib/escort/setup/dsl/command.rb
|
121
|
+
- lib/escort/setup/dsl/config_file.rb
|
122
|
+
- lib/escort/setup/dsl/global.rb
|
123
|
+
- lib/escort/setup/dsl/options.rb
|
124
|
+
- lib/escort/setup/dsl/validations.rb
|
125
|
+
- lib/escort/setup_accessor.rb
|
34
126
|
- lib/escort/trollop.rb
|
127
|
+
- lib/escort/utils.rb
|
128
|
+
- lib/escort/validator.rb
|
35
129
|
- lib/escort/version.rb
|
130
|
+
- spec/helpers/execute_action_matcher.rb
|
131
|
+
- spec/helpers/exit_with_code_matcher.rb
|
132
|
+
- spec/helpers/give_option_to_action_with_value_matcher.rb
|
133
|
+
- spec/integration/basic_options_spec.rb
|
134
|
+
- spec/integration/basic_spec.rb
|
135
|
+
- spec/lib/escort/formatter/string_splitter_spec.rb
|
136
|
+
- spec/lib/escort/setup_accessor_spec.rb
|
137
|
+
- spec/lib/escort/utils_spec.rb
|
138
|
+
- spec/spec_helper.rb
|
36
139
|
homepage: https://github.com/skorks/escort
|
37
140
|
licenses: []
|
141
|
+
metadata: {}
|
38
142
|
post_install_message:
|
39
143
|
rdoc_options: []
|
40
144
|
require_paths:
|
41
145
|
- lib
|
42
146
|
required_ruby_version: !ruby/object:Gem::Requirement
|
43
|
-
none: false
|
44
147
|
requirements:
|
45
148
|
- - ! '>='
|
46
149
|
- !ruby/object:Gem::Version
|
47
150
|
version: '0'
|
48
151
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
49
|
-
none: false
|
50
152
|
requirements:
|
51
153
|
- - ! '>='
|
52
154
|
- !ruby/object:Gem::Version
|
53
155
|
version: '0'
|
54
156
|
requirements: []
|
55
157
|
rubyforge_project:
|
56
|
-
rubygems_version:
|
158
|
+
rubygems_version: 2.0.0
|
57
159
|
signing_key:
|
58
|
-
specification_version:
|
59
|
-
summary:
|
60
|
-
|
160
|
+
specification_version: 4
|
161
|
+
summary: A library that makes building command line apps in ruby so easy, you'll feel
|
162
|
+
like an expert is guiding you through it
|
163
|
+
test_files:
|
164
|
+
- spec/helpers/execute_action_matcher.rb
|
165
|
+
- spec/helpers/exit_with_code_matcher.rb
|
166
|
+
- spec/helpers/give_option_to_action_with_value_matcher.rb
|
167
|
+
- spec/integration/basic_options_spec.rb
|
168
|
+
- spec/integration/basic_spec.rb
|
169
|
+
- spec/lib/escort/formatter/string_splitter_spec.rb
|
170
|
+
- spec/lib/escort/setup_accessor_spec.rb
|
171
|
+
- spec/lib/escort/utils_spec.rb
|
172
|
+
- spec/spec_helper.rb
|
data/lib/escort/command.rb
DELETED
@@ -1,23 +0,0 @@
|
|
1
|
-
module Escort
|
2
|
-
class Command
|
3
|
-
include Dsl
|
4
|
-
|
5
|
-
attr_reader :current_options, :name
|
6
|
-
|
7
|
-
def initialize(name, options_string)
|
8
|
-
@name = name
|
9
|
-
@options_string = options_string
|
10
|
-
end
|
11
|
-
|
12
|
-
def parse_options
|
13
|
-
parser = Trollop::Parser.new(&@options_block)
|
14
|
-
@current_options = Trollop::with_standard_exception_handling(parser) do
|
15
|
-
parser.parse @options_string
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
def perform_action(parent_command_options, remaining_arguments)
|
20
|
-
@action_block.call(parent_command_options, @current_options, remaining_arguments)
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
data/lib/escort/dsl.rb
DELETED
@@ -1,20 +0,0 @@
|
|
1
|
-
module Escort
|
2
|
-
module Dsl
|
3
|
-
attr_reader :command_names
|
4
|
-
|
5
|
-
def options(&block)
|
6
|
-
@options_block = block
|
7
|
-
end
|
8
|
-
|
9
|
-
def command(name, &block)
|
10
|
-
@command_names ||= []
|
11
|
-
@command_names << name.to_s
|
12
|
-
@command_blocks ||= {}
|
13
|
-
@command_blocks[name.to_s] = block
|
14
|
-
end
|
15
|
-
|
16
|
-
def action(&block)
|
17
|
-
@action_block = block
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|