mustermann 1.0.1 → 1.0.2.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +18 -0
- data/.rspec +5 -0
- data/.travis.yml +25 -0
- data/.yardopts +3 -0
- data/Gemfile +7 -0
- data/README.md +230 -799
- data/Rakefile +27 -0
- data/mustermann-contrib/LICENSE +23 -0
- data/mustermann-contrib/README.md +1155 -0
- data/mustermann-contrib/examples/highlighting.rb +35 -0
- data/mustermann-contrib/highlighting.png +0 -0
- data/mustermann-contrib/irb.png +0 -0
- data/mustermann-contrib/lib/mustermann/cake.rb +19 -0
- data/mustermann-contrib/lib/mustermann/express.rb +38 -0
- data/mustermann-contrib/lib/mustermann/file_utils.rb +218 -0
- data/mustermann-contrib/lib/mustermann/file_utils/glob_pattern.rb +40 -0
- data/mustermann-contrib/lib/mustermann/fileutils.rb +1 -0
- data/mustermann-contrib/lib/mustermann/flask.rb +199 -0
- data/mustermann-contrib/lib/mustermann/pyramid.rb +29 -0
- data/mustermann-contrib/lib/mustermann/rails.rb +47 -0
- data/mustermann-contrib/lib/mustermann/shell.rb +57 -0
- data/mustermann-contrib/lib/mustermann/simple.rb +51 -0
- data/mustermann-contrib/lib/mustermann/string_scanner.rb +314 -0
- data/mustermann-contrib/lib/mustermann/strscan.rb +1 -0
- data/mustermann-contrib/lib/mustermann/template.rb +63 -0
- data/mustermann-contrib/lib/mustermann/uri_template.rb +1 -0
- data/mustermann-contrib/lib/mustermann/versions.rb +47 -0
- data/mustermann-contrib/lib/mustermann/visualizer.rb +39 -0
- data/mustermann-contrib/lib/mustermann/visualizer/highlight.rb +138 -0
- data/mustermann-contrib/lib/mustermann/visualizer/highlighter.rb +38 -0
- data/mustermann-contrib/lib/mustermann/visualizer/highlighter/ad_hoc.rb +95 -0
- data/mustermann-contrib/lib/mustermann/visualizer/highlighter/ast.rb +103 -0
- data/mustermann-contrib/lib/mustermann/visualizer/highlighter/composite.rb +46 -0
- data/mustermann-contrib/lib/mustermann/visualizer/highlighter/dummy.rb +19 -0
- data/mustermann-contrib/lib/mustermann/visualizer/highlighter/regular.rb +105 -0
- data/mustermann-contrib/lib/mustermann/visualizer/pattern_extension.rb +69 -0
- data/mustermann-contrib/lib/mustermann/visualizer/renderer/ansi.rb +24 -0
- data/mustermann-contrib/lib/mustermann/visualizer/renderer/generic.rb +47 -0
- data/mustermann-contrib/lib/mustermann/visualizer/renderer/hansi_template.rb +35 -0
- data/mustermann-contrib/lib/mustermann/visualizer/renderer/html.rb +51 -0
- data/mustermann-contrib/lib/mustermann/visualizer/renderer/sexp.rb +38 -0
- data/mustermann-contrib/lib/mustermann/visualizer/tree.rb +64 -0
- data/mustermann-contrib/lib/mustermann/visualizer/tree_renderer.rb +79 -0
- data/mustermann-contrib/mustermann-contrib.gemspec +19 -0
- data/mustermann-contrib/spec/cake_spec.rb +91 -0
- data/mustermann-contrib/spec/express_spec.rb +210 -0
- data/mustermann-contrib/spec/file_utils_spec.rb +120 -0
- data/mustermann-contrib/spec/flask_spec.rb +362 -0
- data/mustermann-contrib/spec/flask_subclass_spec.rb +369 -0
- data/mustermann-contrib/spec/pattern_extension_spec.rb +50 -0
- data/mustermann-contrib/spec/pyramid_spec.rb +102 -0
- data/mustermann-contrib/spec/rails_spec.rb +648 -0
- data/mustermann-contrib/spec/shell_spec.rb +148 -0
- data/mustermann-contrib/spec/simple_spec.rb +269 -0
- data/mustermann-contrib/spec/string_scanner_spec.rb +272 -0
- data/mustermann-contrib/spec/template_spec.rb +842 -0
- data/mustermann-contrib/spec/visualizer_spec.rb +199 -0
- data/mustermann-contrib/theme.png +0 -0
- data/mustermann-contrib/tree.png +0 -0
- data/mustermann/LICENSE +23 -0
- data/mustermann/README.md +853 -0
- data/{bench → mustermann/bench}/capturing.rb +0 -0
- data/{bench → mustermann/bench}/regexp.rb +0 -0
- data/{bench → mustermann/bench}/simple_vs_sinatra.rb +0 -0
- data/{bench → mustermann/bench}/template_vs_addressable.rb +0 -0
- data/{lib → mustermann/lib}/mustermann.rb +0 -0
- data/{lib → mustermann/lib}/mustermann/ast/boundaries.rb +0 -0
- data/{lib → mustermann/lib}/mustermann/ast/compiler.rb +0 -0
- data/{lib → mustermann/lib}/mustermann/ast/expander.rb +0 -0
- data/{lib → mustermann/lib}/mustermann/ast/node.rb +0 -0
- data/{lib → mustermann/lib}/mustermann/ast/param_scanner.rb +0 -0
- data/{lib → mustermann/lib}/mustermann/ast/parser.rb +0 -0
- data/{lib → mustermann/lib}/mustermann/ast/pattern.rb +0 -0
- data/{lib → mustermann/lib}/mustermann/ast/template_generator.rb +0 -0
- data/{lib → mustermann/lib}/mustermann/ast/transformer.rb +0 -0
- data/{lib → mustermann/lib}/mustermann/ast/translator.rb +0 -0
- data/{lib → mustermann/lib}/mustermann/ast/validation.rb +0 -0
- data/{lib → mustermann/lib}/mustermann/caster.rb +0 -0
- data/{lib → mustermann/lib}/mustermann/composite.rb +0 -0
- data/{lib → mustermann/lib}/mustermann/concat.rb +13 -2
- data/{lib → mustermann/lib}/mustermann/equality_map.rb +0 -0
- data/{lib → mustermann/lib}/mustermann/error.rb +0 -0
- data/{lib → mustermann/lib}/mustermann/expander.rb +0 -0
- data/{lib → mustermann/lib}/mustermann/extension.rb +0 -0
- data/{lib → mustermann/lib}/mustermann/identity.rb +0 -0
- data/{lib → mustermann/lib}/mustermann/mapper.rb +0 -0
- data/{lib → mustermann/lib}/mustermann/pattern.rb +1 -1
- data/{lib → mustermann/lib}/mustermann/pattern_cache.rb +0 -0
- data/{lib → mustermann/lib}/mustermann/regexp.rb +0 -0
- data/{lib → mustermann/lib}/mustermann/regexp_based.rb +0 -0
- data/{lib → mustermann/lib}/mustermann/regular.rb +0 -0
- data/{lib → mustermann/lib}/mustermann/simple_match.rb +0 -0
- data/{lib → mustermann/lib}/mustermann/sinatra.rb +1 -1
- data/{lib → mustermann/lib}/mustermann/sinatra/parser.rb +0 -0
- data/{lib → mustermann/lib}/mustermann/sinatra/safe_renderer.rb +0 -0
- data/{lib → mustermann/lib}/mustermann/sinatra/try_convert.rb +0 -0
- data/{lib → mustermann/lib}/mustermann/to_pattern.rb +0 -0
- data/{lib → mustermann/lib}/mustermann/version.rb +1 -1
- data/{mustermann.gemspec → mustermann/mustermann.gemspec} +0 -0
- data/{spec → mustermann/spec}/ast_spec.rb +0 -0
- data/{spec → mustermann/spec}/composite_spec.rb +0 -0
- data/{spec → mustermann/spec}/concat_spec.rb +12 -0
- data/{spec → mustermann/spec}/equality_map_spec.rb +0 -0
- data/{spec → mustermann/spec}/expander_spec.rb +0 -0
- data/{spec → mustermann/spec}/extension_spec.rb +0 -0
- data/{spec → mustermann/spec}/identity_spec.rb +0 -0
- data/{spec → mustermann/spec}/mapper_spec.rb +0 -0
- data/{spec → mustermann/spec}/mustermann_spec.rb +0 -0
- data/{spec → mustermann/spec}/pattern_spec.rb +0 -0
- data/{spec → mustermann/spec}/regexp_based_spec.rb +0 -0
- data/{spec → mustermann/spec}/regular_spec.rb +0 -0
- data/{spec → mustermann/spec}/simple_match_spec.rb +0 -0
- data/{spec → mustermann/spec}/sinatra_spec.rb +0 -0
- data/{spec → mustermann/spec}/to_pattern_spec.rb +0 -0
- data/support/lib/support.rb +7 -0
- data/support/lib/support/coverage.rb +23 -0
- data/support/lib/support/env.rb +19 -0
- data/support/lib/support/expand_matcher.rb +28 -0
- data/support/lib/support/generate_template_matcher.rb +27 -0
- data/support/lib/support/match_matcher.rb +39 -0
- data/support/lib/support/pattern.rb +42 -0
- data/support/lib/support/projects.rb +20 -0
- data/support/lib/support/scan_matcher.rb +63 -0
- data/support/support.gemspec +27 -0
- metadata +128 -58
@@ -0,0 +1,79 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'mustermann/visualizer/tree'
|
3
|
+
require 'mustermann/ast/translator'
|
4
|
+
require 'hansi'
|
5
|
+
|
6
|
+
module Mustermann
|
7
|
+
module Visualizer
|
8
|
+
# Turns an AST into a Tree
|
9
|
+
# @!visibility private
|
10
|
+
class TreeRenderer < AST::Translator
|
11
|
+
TEMPLATE = '"<base01>%s</base01><underline><green>%s</green></underline><base01>%s</base01>" '
|
12
|
+
THEME = Hansi::Theme[:solarized]
|
13
|
+
PREFIX_COLOR = THEME[:violet]
|
14
|
+
FakeNode = Struct.new(:type, :start, :stop, :length)
|
15
|
+
private_constant(:TEMPLATE, :THEME, :PREFIX_COLOR, :FakeNode)
|
16
|
+
|
17
|
+
# Takes a pattern (or pattern string and option) and turns it into a tree.
|
18
|
+
# Runs translation if pattern implements to_ast, otherwise returns single
|
19
|
+
# node tree.
|
20
|
+
#
|
21
|
+
# @!visibility private
|
22
|
+
def self.render(pattern, **options)
|
23
|
+
pattern &&= Mustermann.new(pattern, **options)
|
24
|
+
renderer = new(pattern.to_s)
|
25
|
+
if pattern.respond_to? :to_ast
|
26
|
+
renderer.translate(pattern.to_ast)
|
27
|
+
else
|
28
|
+
length = renderer.string.length
|
29
|
+
node = FakeNode.new("pattern (not AST based)", 0, length, length)
|
30
|
+
renderer.tree(node)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# @!visibility private
|
35
|
+
attr_reader :string
|
36
|
+
|
37
|
+
# @!visibility private
|
38
|
+
def initialize(string)
|
39
|
+
@string = string
|
40
|
+
end
|
41
|
+
|
42
|
+
# access a substring of the pattern, in inspect mode
|
43
|
+
# @!visibility private
|
44
|
+
def sub(*args)
|
45
|
+
string[*args].inspect[1..-2]
|
46
|
+
end
|
47
|
+
|
48
|
+
# creates a tree node
|
49
|
+
# @!visibility private
|
50
|
+
def tree(node, *children, **typed_children)
|
51
|
+
children += children_for(typed_children)
|
52
|
+
children = children.flatten.grep(Tree)
|
53
|
+
infos = sub(0, node.start), sub(node.start, node.length), sub(node.stop..-1)
|
54
|
+
description = Hansi.render(THEME[:green], node.type.to_s.tr("_", " "))
|
55
|
+
after = Hansi.render(TEMPLATE, *infos, theme: THEME, tags: true)
|
56
|
+
Tree.new(description, *children, after: after, prefix_color: PREFIX_COLOR)
|
57
|
+
end
|
58
|
+
|
59
|
+
# Take a hash with trees as values and turn the keys into trees, too.
|
60
|
+
# Read again if that didn't make sense.
|
61
|
+
# @!visibility private
|
62
|
+
def children_for(list)
|
63
|
+
list.map do |key, value|
|
64
|
+
value = Array(value).flatten
|
65
|
+
if value.any?
|
66
|
+
after = " " * string.inspect.length + " "
|
67
|
+
description = Hansi.render(THEME[:orange], key.to_s)
|
68
|
+
Tree.new(description, *value, after: after, prefix_color: PREFIX_COLOR)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
translate(:node) { t.tree(node, payload: t(payload)) }
|
74
|
+
translate(:with_look_ahead) { t.tree(node, head: t(head), payload: t(payload)) }
|
75
|
+
translate(Array) { map { |e| t(e) }}
|
76
|
+
translate(Object) { }
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
$:.unshift File.expand_path("../../mustermann/lib", __FILE__)
|
2
|
+
require "mustermann/version"
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.name = "mustermann-contrib"
|
6
|
+
s.version = Mustermann::VERSION
|
7
|
+
s.authors = ["Konstantin Haase", "Zachary Scott"]
|
8
|
+
s.email = "sinatrarb@googlegroups.com"
|
9
|
+
s.homepage = "https://github.com/sinatra/mustermann"
|
10
|
+
s.summary = %q{Collection of extensions for Mustermann}
|
11
|
+
s.description = %q{Adds many plugins to Mustermman}
|
12
|
+
s.license = 'MIT'
|
13
|
+
s.required_ruby_version = '>= 2.2.0'
|
14
|
+
s.files = `git ls-files`.split("\n")
|
15
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
16
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
17
|
+
s.add_dependency 'mustermann', Mustermann::VERSION
|
18
|
+
s.add_dependency 'hansi', '~> 0.2.0'
|
19
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'support'
|
3
|
+
require 'mustermann/cake'
|
4
|
+
|
5
|
+
describe Mustermann::Cake do
|
6
|
+
extend Support::Pattern
|
7
|
+
|
8
|
+
pattern '' do
|
9
|
+
it { should match('') }
|
10
|
+
it { should_not match('/') }
|
11
|
+
|
12
|
+
it { should expand.to('') }
|
13
|
+
it { should_not expand(a: 1) }
|
14
|
+
|
15
|
+
it { should generate_template('') }
|
16
|
+
|
17
|
+
it { should respond_to(:expand) }
|
18
|
+
it { should respond_to(:to_templates) }
|
19
|
+
end
|
20
|
+
|
21
|
+
pattern '/' do
|
22
|
+
it { should match('/') }
|
23
|
+
it { should_not match('/foo') }
|
24
|
+
|
25
|
+
it { should expand.to('/') }
|
26
|
+
it { should_not expand(a: 1) }
|
27
|
+
end
|
28
|
+
|
29
|
+
pattern '/foo' do
|
30
|
+
it { should match('/foo') }
|
31
|
+
it { should_not match('/bar') }
|
32
|
+
it { should_not match('/foo.bar') }
|
33
|
+
|
34
|
+
it { should expand.to('/foo') }
|
35
|
+
it { should_not expand(a: 1) }
|
36
|
+
end
|
37
|
+
|
38
|
+
pattern '/foo/bar' do
|
39
|
+
it { should match('/foo/bar') }
|
40
|
+
it { should_not match('/foo%2Fbar') }
|
41
|
+
it { should_not match('/foo%2fbar') }
|
42
|
+
|
43
|
+
it { should expand.to('/foo/bar') }
|
44
|
+
it { should_not expand(a: 1) }
|
45
|
+
end
|
46
|
+
|
47
|
+
pattern '/:foo' do
|
48
|
+
it { should match('/foo') .capturing foo: 'foo' }
|
49
|
+
it { should match('/bar') .capturing foo: 'bar' }
|
50
|
+
it { should match('/foo.bar') .capturing foo: 'foo.bar' }
|
51
|
+
it { should match('/%0Afoo') .capturing foo: '%0Afoo' }
|
52
|
+
it { should match('/foo%2Fbar') .capturing foo: 'foo%2Fbar' }
|
53
|
+
|
54
|
+
it { should_not match('/foo?') }
|
55
|
+
it { should_not match('/foo/bar') }
|
56
|
+
it { should_not match('/') }
|
57
|
+
it { should_not match('/foo/') }
|
58
|
+
|
59
|
+
example { pattern.params('/foo') .should be == {"foo" => "foo"} }
|
60
|
+
example { pattern.params('/f%20o') .should be == {"foo" => "f o"} }
|
61
|
+
example { pattern.params('').should be_nil }
|
62
|
+
|
63
|
+
it { should expand(foo: 'bar') .to('/bar') }
|
64
|
+
it { should expand(foo: 'b r') .to('/b%20r') }
|
65
|
+
it { should expand(foo: 'foo/bar') .to('/foo%2Fbar') }
|
66
|
+
|
67
|
+
it { should_not expand(foo: 'foo', bar: 'bar') }
|
68
|
+
it { should_not expand(bar: 'bar') }
|
69
|
+
it { should_not expand }
|
70
|
+
|
71
|
+
it { should generate_template('/{foo}') }
|
72
|
+
end
|
73
|
+
|
74
|
+
pattern '/*' do
|
75
|
+
it { should match('/') }
|
76
|
+
it { should match('/foo') }
|
77
|
+
it { should match('/foo/bar') }
|
78
|
+
|
79
|
+
example { pattern.params('/foo/bar') .should be == {"splat" => ["foo", "bar"]}}
|
80
|
+
it { should generate_template('/{+splat}') }
|
81
|
+
end
|
82
|
+
|
83
|
+
pattern '/**' do
|
84
|
+
it { should match('/') .capturing splat: '' }
|
85
|
+
it { should match('/foo') .capturing splat: 'foo' }
|
86
|
+
it { should match('/foo/bar') .capturing splat: 'foo/bar' }
|
87
|
+
|
88
|
+
example { pattern.params('/foo/bar') .should be == {"splat" => ["foo/bar"]} }
|
89
|
+
it { should generate_template('/{+splat}') }
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,210 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'support'
|
3
|
+
require 'mustermann/express'
|
4
|
+
|
5
|
+
describe Mustermann::Express do
|
6
|
+
extend Support::Pattern
|
7
|
+
|
8
|
+
pattern '' do
|
9
|
+
it { should match('') }
|
10
|
+
it { should_not match('/') }
|
11
|
+
|
12
|
+
it { should expand.to('') }
|
13
|
+
it { should_not expand(a: 1) }
|
14
|
+
|
15
|
+
it { should generate_template('') }
|
16
|
+
|
17
|
+
it { should respond_to(:expand) }
|
18
|
+
it { should respond_to(:to_templates) }
|
19
|
+
end
|
20
|
+
|
21
|
+
pattern '/' do
|
22
|
+
it { should match('/') }
|
23
|
+
it { should_not match('/foo') }
|
24
|
+
|
25
|
+
it { should expand.to('/') }
|
26
|
+
it { should_not expand(a: 1) }
|
27
|
+
end
|
28
|
+
|
29
|
+
pattern '/foo' do
|
30
|
+
it { should match('/foo') }
|
31
|
+
it { should_not match('/bar') }
|
32
|
+
it { should_not match('/foo.bar') }
|
33
|
+
|
34
|
+
it { should expand.to('/foo') }
|
35
|
+
it { should_not expand(a: 1) }
|
36
|
+
end
|
37
|
+
|
38
|
+
pattern '/foo/bar' do
|
39
|
+
it { should match('/foo/bar') }
|
40
|
+
it { should_not match('/foo%2Fbar') }
|
41
|
+
it { should_not match('/foo%2fbar') }
|
42
|
+
|
43
|
+
it { should expand.to('/foo/bar') }
|
44
|
+
it { should_not expand(a: 1) }
|
45
|
+
end
|
46
|
+
|
47
|
+
pattern '/:foo' do
|
48
|
+
it { should match('/foo') .capturing foo: 'foo' }
|
49
|
+
it { should match('/bar') .capturing foo: 'bar' }
|
50
|
+
it { should match('/foo.bar') .capturing foo: 'foo.bar' }
|
51
|
+
it { should match('/%0Afoo') .capturing foo: '%0Afoo' }
|
52
|
+
it { should match('/foo%2Fbar') .capturing foo: 'foo%2Fbar' }
|
53
|
+
|
54
|
+
it { should_not match('/foo?') }
|
55
|
+
it { should_not match('/foo/bar') }
|
56
|
+
it { should_not match('/') }
|
57
|
+
it { should_not match('/foo/') }
|
58
|
+
|
59
|
+
example { pattern.params('/foo') .should be == {"foo" => "foo"} }
|
60
|
+
example { pattern.params('/f%20o') .should be == {"foo" => "f o"} }
|
61
|
+
example { pattern.params('').should be_nil }
|
62
|
+
|
63
|
+
it { should expand(foo: 'bar') .to('/bar') }
|
64
|
+
it { should expand(foo: 'b r') .to('/b%20r') }
|
65
|
+
it { should expand(foo: 'foo/bar') .to('/foo%2Fbar') }
|
66
|
+
|
67
|
+
it { should_not expand(foo: 'foo', bar: 'bar') }
|
68
|
+
it { should_not expand(bar: 'bar') }
|
69
|
+
it { should_not expand }
|
70
|
+
|
71
|
+
it { should generate_template('/{foo}') }
|
72
|
+
end
|
73
|
+
|
74
|
+
pattern '/:foo+' do
|
75
|
+
it { should_not match('/') }
|
76
|
+
it { should match('/foo') .capturing foo: 'foo' }
|
77
|
+
it { should match('/foo/bar') .capturing foo: 'foo/bar' }
|
78
|
+
|
79
|
+
it { should expand .to('/') }
|
80
|
+
it { should expand(foo: nil) .to('/') }
|
81
|
+
it { should expand(foo: '') .to('/') }
|
82
|
+
it { should expand(foo: 'foo') .to('/foo') }
|
83
|
+
it { should expand(foo: 'foo/bar') .to('/foo/bar') }
|
84
|
+
it { should expand(foo: 'foo.bar') .to('/foo.bar') }
|
85
|
+
|
86
|
+
it { should generate_template('/{+foo}') }
|
87
|
+
end
|
88
|
+
|
89
|
+
pattern '/:foo?' do
|
90
|
+
it { should match('/foo') .capturing foo: 'foo' }
|
91
|
+
it { should match('/bar') .capturing foo: 'bar' }
|
92
|
+
it { should match('/foo.bar') .capturing foo: 'foo.bar' }
|
93
|
+
it { should match('/%0Afoo') .capturing foo: '%0Afoo' }
|
94
|
+
it { should match('/foo%2Fbar') .capturing foo: 'foo%2Fbar' }
|
95
|
+
it { should match('/') }
|
96
|
+
|
97
|
+
it { should_not match('/foo?') }
|
98
|
+
it { should_not match('/foo/bar') }
|
99
|
+
it { should_not match('/foo/') }
|
100
|
+
|
101
|
+
example { pattern.params('/foo') .should be == {"foo" => "foo"} }
|
102
|
+
example { pattern.params('/f%20o') .should be == {"foo" => "f o"} }
|
103
|
+
example { pattern.params('/') .should be == {"foo" => nil } }
|
104
|
+
|
105
|
+
it { should expand(foo: 'bar') .to('/bar') }
|
106
|
+
it { should expand(foo: 'b r') .to('/b%20r') }
|
107
|
+
it { should expand(foo: 'foo/bar') .to('/foo%2Fbar') }
|
108
|
+
it { should expand .to('/') }
|
109
|
+
|
110
|
+
it { should_not expand(foo: 'foo', bar: 'bar') }
|
111
|
+
it { should_not expand(bar: 'bar') }
|
112
|
+
|
113
|
+
it { should generate_template('/{foo}') }
|
114
|
+
it { should generate_template('/') }
|
115
|
+
end
|
116
|
+
|
117
|
+
pattern '/:foo*' do
|
118
|
+
it { should match('/') .capturing foo: '' }
|
119
|
+
it { should match('/foo') .capturing foo: 'foo' }
|
120
|
+
it { should match('/foo/bar') .capturing foo: 'foo/bar' }
|
121
|
+
|
122
|
+
it { should expand .to('/') }
|
123
|
+
it { should expand(foo: nil) .to('/') }
|
124
|
+
it { should expand(foo: '') .to('/') }
|
125
|
+
it { should expand(foo: 'foo') .to('/foo') }
|
126
|
+
it { should expand(foo: 'foo/bar') .to('/foo/bar') }
|
127
|
+
it { should expand(foo: 'foo.bar') .to('/foo.bar') }
|
128
|
+
|
129
|
+
it { should generate_template('/{+foo}') }
|
130
|
+
end
|
131
|
+
|
132
|
+
pattern '/:foo(.*)' do
|
133
|
+
it { should match('/') .capturing foo: '' }
|
134
|
+
it { should match('/foo') .capturing foo: 'foo' }
|
135
|
+
it { should match('/foo/bar') .capturing foo: 'foo/bar' }
|
136
|
+
|
137
|
+
it { should expand(foo: '') .to('/') }
|
138
|
+
it { should expand(foo: 'foo') .to('/foo') }
|
139
|
+
it { should expand(foo: 'foo/bar') .to('/foo/bar') }
|
140
|
+
it { should expand(foo: 'foo.bar') .to('/foo.bar') }
|
141
|
+
|
142
|
+
it { should generate_template('/{foo}') }
|
143
|
+
end
|
144
|
+
|
145
|
+
pattern '/:foo(\d+)' do
|
146
|
+
it { should_not match('/') }
|
147
|
+
it { should_not match('/foo') }
|
148
|
+
it { should match('/15') .capturing foo: '15' }
|
149
|
+
it { should generate_template('/{foo}') }
|
150
|
+
end
|
151
|
+
|
152
|
+
pattern '/:foo(\d+|bar)' do
|
153
|
+
it { should_not match('/') }
|
154
|
+
it { should_not match('/foo') }
|
155
|
+
it { should match('/15') .capturing foo: '15' }
|
156
|
+
it { should match('/bar') .capturing foo: 'bar' }
|
157
|
+
it { should generate_template('/{foo}') }
|
158
|
+
end
|
159
|
+
|
160
|
+
pattern '/:foo(\))' do
|
161
|
+
it { should_not match('/') }
|
162
|
+
it { should_not match('/foo') }
|
163
|
+
it { should match('/)').capturing foo: ')' }
|
164
|
+
it { should generate_template('/{foo}') }
|
165
|
+
end
|
166
|
+
|
167
|
+
pattern '/:foo(prefix(\d+|bar))' do
|
168
|
+
it { should_not match('/prefix') }
|
169
|
+
it { should_not match('/prefixfoo') }
|
170
|
+
it { should match('/prefix15') .capturing foo: 'prefix15' }
|
171
|
+
it { should match('/prefixbar') .capturing foo: 'prefixbar' }
|
172
|
+
it { should generate_template('/{foo}') }
|
173
|
+
end
|
174
|
+
|
175
|
+
pattern '/(.+)' do
|
176
|
+
it { should_not match('/') }
|
177
|
+
it { should match('/foo') .capturing splat: 'foo' }
|
178
|
+
it { should match('/foo/bar') .capturing splat: 'foo/bar' }
|
179
|
+
it { should generate_template('/{+splat}') }
|
180
|
+
end
|
181
|
+
|
182
|
+
pattern '/(foo(a|b))' do
|
183
|
+
it { should_not match('/') }
|
184
|
+
it { should match('/fooa') .capturing splat: 'fooa' }
|
185
|
+
it { should match('/foob') .capturing splat: 'foob' }
|
186
|
+
it { should generate_template('/{+splat}') }
|
187
|
+
end
|
188
|
+
|
189
|
+
context 'invalid syntax' do
|
190
|
+
example 'unexpected closing parenthesis' do
|
191
|
+
expect { Mustermann::Express.new('foo)bar') }.
|
192
|
+
to raise_error(Mustermann::ParseError, 'unexpected ) while parsing "foo)bar"')
|
193
|
+
end
|
194
|
+
|
195
|
+
example 'missing closing parenthesis' do
|
196
|
+
expect { Mustermann::Express.new('foo(bar') }.
|
197
|
+
to raise_error(Mustermann::ParseError, 'unexpected end of string while parsing "foo(bar"')
|
198
|
+
end
|
199
|
+
|
200
|
+
example 'unexpected ?' do
|
201
|
+
expect { Mustermann::Express.new('foo?bar') }.
|
202
|
+
to raise_error(Mustermann::ParseError, 'unexpected ? while parsing "foo?bar"')
|
203
|
+
end
|
204
|
+
|
205
|
+
example 'unexpected *' do
|
206
|
+
expect { Mustermann::Express.new('foo*bar') }.
|
207
|
+
to raise_error(Mustermann::ParseError, 'unexpected * while parsing "foo*bar"')
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|
@@ -0,0 +1,120 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'support'
|
3
|
+
require 'mustermann/file_utils'
|
4
|
+
|
5
|
+
describe Mustermann::FileUtils do
|
6
|
+
subject(:utils) { Mustermann::FileUtils }
|
7
|
+
include FileUtils
|
8
|
+
|
9
|
+
before do
|
10
|
+
@pwd = Dir.pwd
|
11
|
+
@tmp_dir = File.join(__dir__, 'tmp')
|
12
|
+
|
13
|
+
mkdir_p(@tmp_dir)
|
14
|
+
chdir(@tmp_dir)
|
15
|
+
|
16
|
+
touch("foo.txt")
|
17
|
+
touch("foo.rb")
|
18
|
+
touch("bar.txt")
|
19
|
+
touch("bar.rb")
|
20
|
+
end
|
21
|
+
|
22
|
+
after do
|
23
|
+
chdir(@pwd) if @pwd
|
24
|
+
rm_rf(@tmp_dir) if @tmp_dir
|
25
|
+
end
|
26
|
+
|
27
|
+
describe :glob_pattern do
|
28
|
+
example { utils.glob_pattern('/:foo') .should be == '/*' }
|
29
|
+
example { utils.glob_pattern('/*foo') .should be == '/**/*' }
|
30
|
+
example { utils.glob_pattern('/(ab|c)?/:foo/d/*bar') .should be == '/{{ab,c},}/*/d/**/*' }
|
31
|
+
example { utils.glob_pattern('/a', '/b') .should be == '{/a,/b}' }
|
32
|
+
example { utils.glob_pattern('**/*', type: :shell) .should be == '**/*' }
|
33
|
+
example { utils.glob_pattern(/can't parse this/) .should be == '**/*' }
|
34
|
+
example { utils.glob_pattern('/foo', type: :identity) .should be == '/foo' }
|
35
|
+
example { utils.glob_pattern('/fo*', type: :identity) .should be == '/fo\\*' }
|
36
|
+
end
|
37
|
+
|
38
|
+
describe :glob do
|
39
|
+
example do
|
40
|
+
utils.glob(":name.txt").sort.should be == ['bar.txt', 'foo.txt']
|
41
|
+
end
|
42
|
+
|
43
|
+
example do
|
44
|
+
extensions = []
|
45
|
+
utils.glob("foo.:ext") { |file, params| extensions << params['ext'] }
|
46
|
+
extensions.sort.should be == ['rb', 'txt']
|
47
|
+
end
|
48
|
+
|
49
|
+
example do
|
50
|
+
utils.glob(":name.:ext", capture: { ext: 'rb', name: 'foo' }).should be == ['foo.rb']
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
describe :glob_map do
|
55
|
+
example do
|
56
|
+
utils.glob_map(':name.rb' => ':name/init.rb').should be == {
|
57
|
+
"bar.rb" => "bar/init.rb",
|
58
|
+
"foo.rb" => "foo/init.rb"
|
59
|
+
}
|
60
|
+
end
|
61
|
+
|
62
|
+
example do
|
63
|
+
result = {}
|
64
|
+
returned = utils.glob_map(':name.rb' => ':name/init.rb') { |k, v| result[v] = k.upcase }
|
65
|
+
returned.sort .should be == ["BAR.RB", "FOO.RB"]
|
66
|
+
result["bar/init.rb"] .should be == "BAR.RB"
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
describe :cp do
|
71
|
+
example do
|
72
|
+
utils.cp(':name.rb' => ':name.ruby', ':name.txt' => ':name.md')
|
73
|
+
File.should be_exist('foo.ruby')
|
74
|
+
File.should be_exist('bar.md')
|
75
|
+
File.should be_exist('bar.txt')
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
describe :cp_r do
|
80
|
+
example do
|
81
|
+
mkdir_p "foo/bar"
|
82
|
+
utils.cp_r('foo/:name' => :name)
|
83
|
+
File.should be_directory('bar')
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
describe :mv do
|
88
|
+
example do
|
89
|
+
utils.mv(':name.rb' => ':name.ruby', ':name.txt' => ':name.md')
|
90
|
+
File.should be_exist('foo.ruby')
|
91
|
+
File.should be_exist('bar.md')
|
92
|
+
File.should_not be_exist('bar.txt')
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
describe :ln do
|
97
|
+
example do
|
98
|
+
utils.ln(':name.rb' => ':name.ruby', ':name.txt' => ':name.md')
|
99
|
+
File.should be_exist('foo.ruby')
|
100
|
+
File.should be_exist('bar.md')
|
101
|
+
File.should be_exist('bar.txt')
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
describe :ln_s do
|
106
|
+
example do
|
107
|
+
utils.ln_s(':name.rb' => ':name.ruby', ':name.txt' => ':name.md')
|
108
|
+
File.should be_symlink('foo.ruby')
|
109
|
+
File.should be_symlink('bar.md')
|
110
|
+
File.should be_exist('bar.txt')
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
describe :ln_sf do
|
115
|
+
example do
|
116
|
+
utils.ln_sf(':name.rb' => ':name.txt')
|
117
|
+
File.should be_symlink('foo.txt')
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|