drudge 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,71 @@
1
+ require 'spec_helper'
2
+ require 'drudge/parsers/tokenizer'
3
+
4
+ class Drudge
5
+
6
+ module Parsers
7
+ describe Tokenizer do
8
+
9
+ describe ".tokenize" do
10
+
11
+ it "converts an array of command line arguments into an array of sexps" do
12
+ tokens = Tokenizer.tokenize(%w[hello world])
13
+
14
+ expect(tokens).to be_kind_of(Enumerable)
15
+
16
+ tokens.each do |type, arg, meta|
17
+ expect(type).to eq :val
18
+ expect(arg).to be_kind_of(String)
19
+ expect(meta).to include(:loc)
20
+ end
21
+ end
22
+
23
+ it "converts an ordinary argument 'arg' into the sexp [:val, 'arg']" do
24
+ tokens = Tokenizer.tokenize(%w[hello world])
25
+
26
+ expect(tokens).to eq [[:val, 'hello', {loc: [0, 0, 5]}],
27
+ [:val, 'world', {loc: [1, 0, 5]}]]
28
+ end
29
+ end
30
+
31
+ describe ".untokenize" do
32
+ let(:sexps) { [[:val, 'hello', {loc: [0, 0, 5]}],
33
+ [:val, 'dear', {loc: [1, 0, 4]}],
34
+ [:val, 'world', {loc: [2, 0, 5]}]] }
35
+
36
+ it "converts an array of s-exps into a string" do
37
+ expect(Tokenizer.untokenize(sexps)).to eq "hello dear world"
38
+ end
39
+ end
40
+
41
+ describe ".underline_token" do
42
+ let(:sexps) { [[:val, 'hello', {loc: [0, 0, 5]}],
43
+ [:val, 'dear', {loc: [1, 0, 4]}],
44
+ [:val, 'world', {loc: [2, 0, 5]}]] }
45
+
46
+ it "underlines first token" do
47
+ expect(Tokenizer.underline_token(sexps, sexps[0])).to eq "~~~~~"
48
+ end
49
+
50
+ it "underlines the second token" do
51
+ expect(Tokenizer.underline_token(sexps, sexps[1])).to eq " ~~~~"
52
+ end
53
+
54
+ it "underlines the third token" do
55
+ expect(Tokenizer.underline_token(sexps, sexps[2])).to eq " ~~~~~"
56
+ end
57
+
58
+ it "underlines the end of string when token is nil" do
59
+ expect(Tokenizer.underline_token(sexps, nil)).to eq " ^"
60
+ end
61
+
62
+ it "can be told which underline char to use" do
63
+ expect(Tokenizer.underline_token(sexps, sexps[0], underline_char: "-")).to eq "-----"
64
+ end
65
+ end
66
+
67
+ end
68
+
69
+ end
70
+ end
71
+
@@ -0,0 +1,149 @@
1
+ require 'spec_helper'
2
+
3
+ require 'drudge/parsers'
4
+ require 'drudge/errors'
5
+
6
+ class Drudge
7
+
8
+ describe Parsers do
9
+ include Parsers
10
+
11
+ describe "#parser" do
12
+ it "takes a block and extends it with ArgumentParser" do
13
+ p = parser { |input| EOS }
14
+
15
+ expect(p).to be_kind_of(Parsers::ArgumentParser)
16
+ end
17
+ end
18
+
19
+ describe "basic parsers" do
20
+ describe ".value" do
21
+ context "without arguments" do
22
+ subject { value }
23
+
24
+ it { should parse([[:val, "test"]]).as("test") }
25
+ it { should_not parse([[:foo, "bar"]]) }
26
+ it { should_not parse([]) }
27
+ it { should_not parse(nil) }
28
+ end
29
+
30
+ context "with a string argument 'something'" do
31
+ subject { value("something") }
32
+
33
+ it { should parse([[:val, "something"]]).as("something") }
34
+ it { should_not parse([[:val, "something else"]]) }
35
+ it { should_not parse([[:foo, "bar"]]) }
36
+ end
37
+
38
+ context "with a regexp argument /^ab.+/" do
39
+ subject { value(/^ab.+/) }
40
+
41
+ it { should parse([[:val, "abc"]]).as("abc") }
42
+ it { should parse([[:val, "abd"]]).as("abd") }
43
+ it { should_not parse([[:val, "cabc"]]) }
44
+ it { should_not parse([[:val, "something else"]]) }
45
+ it { should_not parse([[:foo, "bar"]]) }
46
+ end
47
+ end
48
+ end
49
+
50
+ describe "command & argument parsers" do
51
+
52
+ describe ".arg" do
53
+
54
+ context "with a single argument" do
55
+ context "arg parser for the arg named 'test'" do
56
+ subject { arg(:test) }
57
+
58
+ it { should tokenize_and_parse(%w[anything]).as([:arg, "anything"]) }
59
+
60
+ it "should include the expected paraemeter name in the error message" do
61
+ expect(subject.call([])).to eq(Failure("expected a value for <test>", []))
62
+ end
63
+ end
64
+
65
+ context "arg sequence" do
66
+ subject { arg(:first) > arg(:second) }
67
+
68
+ it { should tokenize_and_parse(%w[arg1 arg2]).as([[:arg, "arg1"], [:arg, "arg2"]]) }
69
+ it { should_not tokenize_and_parse(%w[arg1]) }
70
+ it { should_not tokenize_and_parse(%w[]) }
71
+ end
72
+
73
+ context "arg sequence with :eos" do
74
+ let(:p) { arg(:first) > arg(:second) > eos }
75
+ subject { p }
76
+
77
+ it { should tokenize_and_parse(%w[arg1 arg2]).as([[:arg, "arg1"], [:arg, "arg2"]]) }
78
+ it { should_not tokenize_and_parse(%w[arg1 arg2 arg3]) }
79
+ end
80
+ end
81
+
82
+ context "with a provided parser" do
83
+ subject { arg(:test, value("TEST")) }
84
+ describe "arg parser that acceptes only 'TEST'" do
85
+
86
+ it { should tokenize_and_parse(%w[TEST]).as([:arg, "TEST"]) }
87
+
88
+ it { should_not tokenize_and_parse(%w[anything]) }
89
+ end
90
+
91
+ end
92
+
93
+ end
94
+
95
+ describe ".command" do
96
+ context "command parser for command 'hello'" do
97
+ subject { command("hello") }
98
+
99
+ it { should tokenize_and_parse(%w[hello]).as([:arg, "hello"]) }
100
+ it { should_not tokenize_and_parse(%w[HELLO]) }
101
+ end
102
+ end
103
+
104
+ describe "collated arguments" do
105
+ let(:p) { command("hello") > arg(:first) > arg(:second) <= eos }
106
+ subject { p.collated_arguments }
107
+
108
+ it { should tokenize_and_parse(%w[hello first second]).as({args: %w[hello first second]}) }
109
+ end
110
+
111
+
112
+ end
113
+
114
+
115
+ describe Parsers::ArgumentParser do
116
+ include Parsers::ParseResults
117
+
118
+ context "a parser built with #parser" do
119
+ subject do
120
+ parser do |input|
121
+ if input[0][0] == :val && input[0][1] == "hello"
122
+ Success(Single(input[0][1]), input.drop(1))
123
+ else
124
+ Failure("f", input)
125
+ end
126
+ end
127
+ end
128
+
129
+ describe "#parse" do
130
+ it "tokenizes an array of [command line] args and parses it at once" do
131
+
132
+ expect(subject.parse(%w[hello world])).to eq(Success(Single("hello"), [[:val, "world", {:loc=>[1, 0, 5]}]]))
133
+ end
134
+ end
135
+
136
+ describe "#parse!" do
137
+ it "is like #parse, but returns just the result when successful" do
138
+ expect(subject.parse!(%w[hello world])).to eq("hello")
139
+ end
140
+
141
+ it "upon failed parse, it raises a CommandArgumentError" do
142
+ expect { subject.parse!(%w[world hello])}.to raise_error(ParseError)
143
+ end
144
+ end
145
+ end
146
+ end
147
+
148
+ end
149
+ end
@@ -0,0 +1,2 @@
1
+ $LOAD_PATH << File.join(File.dirname(__FILE__), '..', 'lib')
2
+ Dir["./spec/support/**/*.rb"].each {|f| require f}
@@ -0,0 +1,16 @@
1
+ # captures the STDOUT output produced by the provided block
2
+ def capture
3
+ original_stdout = $stdout
4
+ $stdout = fake = StringIO.new
5
+ begin
6
+ yield
7
+ ensure
8
+ $stdout = original_stdout
9
+ end
10
+ fake.string
11
+ end
12
+
13
+
14
+ def expect_capture(&block)
15
+ expect(capture &block)
16
+ end
@@ -0,0 +1,13 @@
1
+ require 'drudge/command'
2
+
3
+ def dummy_cmd(name, args = [])
4
+ Drudge::Command.new(name, args, -> { puts name } )
5
+ end
6
+
7
+ def splash_param(name)
8
+ Drudge::Param.any(name, splatt: true)
9
+ end
10
+
11
+ def optional_param(name)
12
+ Drudge::Param.any(name, optional: true)
13
+ end
@@ -0,0 +1,42 @@
1
+ require 'drudge/parsers/tokenizer'
2
+
3
+ RSpec::Matchers.define :parse do |input|
4
+ match do |parser|
5
+ res = parser.call(input)
6
+
7
+ res.success? and
8
+ res.remaining != input and
9
+ (res.result == @expected_output or not @expected_output)
10
+ end
11
+
12
+ chain :as do |expected_output|
13
+ @expected_output = expected_output
14
+ end
15
+ end
16
+
17
+ RSpec::Matchers.define :tokenize_and_parse do |input|
18
+ chain :as do |expected_output|
19
+ @expected_output = expected_output
20
+ end
21
+
22
+ match do |parser|
23
+ res = do_parse(parser, input)
24
+
25
+ res.success? and
26
+ (res.result == @expected_output or not @expected_output)
27
+ end
28
+
29
+ failure_message_for_should do |parser|
30
+ res = do_parse(parser, input)
31
+
32
+ if @expected_output and res.success?
33
+ "expected that \"#{parser}\"'s result would be #{@expected_output}, was '#{res.result}'"
34
+ else
35
+ "expected that #{parser} should tokenize and parse '#{input}'"
36
+ end
37
+ end
38
+
39
+ def do_parse(parser, input)
40
+ parser.call(Drudge::Parsers::Tokenizer.tokenize(input))
41
+ end
42
+ end
metadata ADDED
@@ -0,0 +1,219 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: drudge
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.4.0
5
+ platform: ruby
6
+ authors:
7
+ - Ognen Ivanovski
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-02-28 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.3'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
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: pry
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
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '2.14'
62
+ - - <
63
+ - !ruby/object:Gem::Version
64
+ version: '3.0'
65
+ type: :development
66
+ prerelease: false
67
+ version_requirements: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - '>='
70
+ - !ruby/object:Gem::Version
71
+ version: '2.14'
72
+ - - <
73
+ - !ruby/object:Gem::Version
74
+ version: '3.0'
75
+ - !ruby/object:Gem::Dependency
76
+ name: cucumber
77
+ requirement: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - '>='
80
+ - !ruby/object:Gem::Version
81
+ version: '0'
82
+ type: :development
83
+ prerelease: false
84
+ version_requirements: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - '>='
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ - !ruby/object:Gem::Dependency
90
+ name: aruba
91
+ requirement: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - '>='
94
+ - !ruby/object:Gem::Version
95
+ version: 0.4.6
96
+ type: :development
97
+ prerelease: false
98
+ version_requirements: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - '>='
101
+ - !ruby/object:Gem::Version
102
+ version: 0.4.6
103
+ - !ruby/object:Gem::Dependency
104
+ name: yard
105
+ requirement: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - '>='
108
+ - !ruby/object:Gem::Version
109
+ version: 0.8.6.1
110
+ type: :development
111
+ prerelease: false
112
+ version_requirements: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - '>='
115
+ - !ruby/object:Gem::Version
116
+ version: 0.8.6.1
117
+ - !ruby/object:Gem::Dependency
118
+ name: gem-release
119
+ requirement: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - '>='
122
+ - !ruby/object:Gem::Version
123
+ version: '0'
124
+ type: :development
125
+ prerelease: false
126
+ version_requirements: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - '>='
129
+ - !ruby/object:Gem::Version
130
+ version: '0'
131
+ description: |-
132
+ A library for building command-line
133
+ automation tools with the aim of transferring you (conceptionally) from the command line
134
+ interface into Ruby and then letting you use build your tool in a familiar
135
+ environement.
136
+ email:
137
+ - ognen.ivanovski@me.com
138
+ executables: []
139
+ extensions: []
140
+ extra_rdoc_files: []
141
+ files:
142
+ - .gitignore
143
+ - Gemfile
144
+ - Gemfile.lock
145
+ - LICENSE.txt
146
+ - README.md
147
+ - Rakefile
148
+ - drudge.gemspec
149
+ - features/optional-arguments.feature
150
+ - features/simple-commands.feature
151
+ - features/step_definitions/scripts_steps.rb
152
+ - features/support/env.rb
153
+ - features/variable-length-argument-lists.feature
154
+ - lib/drudge.rb
155
+ - lib/drudge/class_dsl.rb
156
+ - lib/drudge/command.rb
157
+ - lib/drudge/dispatch.rb
158
+ - lib/drudge/errors.rb
159
+ - lib/drudge/ext.rb
160
+ - lib/drudge/kit.rb
161
+ - lib/drudge/parsers.rb
162
+ - lib/drudge/parsers/parse_results.rb
163
+ - lib/drudge/parsers/primitives.rb
164
+ - lib/drudge/parsers/tokenizer.rb
165
+ - lib/drudge/version.rb
166
+ - spec/drudge/class_dsl_spec.rb
167
+ - spec/drudge/command_spec.rb
168
+ - spec/drudge/kit_spec.rb
169
+ - spec/drudge/parsers/parse_results_spec.rb
170
+ - spec/drudge/parsers/primitives_spec.rb
171
+ - spec/drudge/parsers/tokenizer_spec.rb
172
+ - spec/drudge/parsers_spec.rb
173
+ - spec/spec_helper.rb
174
+ - spec/support/capture.rb
175
+ - spec/support/fixtures.rb
176
+ - spec/support/parser_matchers.rb
177
+ homepage: https://github.com/ognen/drudge
178
+ licenses:
179
+ - MIT
180
+ metadata: {}
181
+ post_install_message:
182
+ rdoc_options: []
183
+ require_paths:
184
+ - lib
185
+ required_ruby_version: !ruby/object:Gem::Requirement
186
+ requirements:
187
+ - - '>='
188
+ - !ruby/object:Gem::Version
189
+ version: 2.0.0
190
+ required_rubygems_version: !ruby/object:Gem::Requirement
191
+ requirements:
192
+ - - '>='
193
+ - !ruby/object:Gem::Version
194
+ version: '0'
195
+ requirements: []
196
+ rubyforge_project:
197
+ rubygems_version: 2.0.14
198
+ signing_key:
199
+ specification_version: 4
200
+ summary: A gem that enables you to write command line automation tools using Ruby
201
+ 2.0.
202
+ test_files:
203
+ - features/optional-arguments.feature
204
+ - features/simple-commands.feature
205
+ - features/step_definitions/scripts_steps.rb
206
+ - features/support/env.rb
207
+ - features/variable-length-argument-lists.feature
208
+ - spec/drudge/class_dsl_spec.rb
209
+ - spec/drudge/command_spec.rb
210
+ - spec/drudge/kit_spec.rb
211
+ - spec/drudge/parsers/parse_results_spec.rb
212
+ - spec/drudge/parsers/primitives_spec.rb
213
+ - spec/drudge/parsers/tokenizer_spec.rb
214
+ - spec/drudge/parsers_spec.rb
215
+ - spec/spec_helper.rb
216
+ - spec/support/capture.rb
217
+ - spec/support/fixtures.rb
218
+ - spec/support/parser_matchers.rb
219
+ has_rdoc: