mustermann 1.0.2.rc1 → 1.0.2.rc2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +799 -230
- data/{mustermann/bench → bench}/capturing.rb +0 -0
- data/{mustermann/bench → bench}/regexp.rb +0 -0
- data/{mustermann/bench → bench}/simple_vs_sinatra.rb +0 -0
- data/{mustermann/bench → bench}/template_vs_addressable.rb +0 -0
- data/{mustermann/lib → lib}/mustermann.rb +0 -0
- data/{mustermann/lib → lib}/mustermann/ast/boundaries.rb +0 -0
- data/{mustermann/lib → lib}/mustermann/ast/compiler.rb +0 -0
- data/{mustermann/lib → lib}/mustermann/ast/expander.rb +0 -0
- data/{mustermann/lib → lib}/mustermann/ast/node.rb +0 -0
- data/{mustermann/lib → lib}/mustermann/ast/param_scanner.rb +0 -0
- data/{mustermann/lib → lib}/mustermann/ast/parser.rb +0 -0
- data/{mustermann/lib → lib}/mustermann/ast/pattern.rb +0 -0
- data/{mustermann/lib → lib}/mustermann/ast/template_generator.rb +0 -0
- data/{mustermann/lib → lib}/mustermann/ast/transformer.rb +0 -0
- data/{mustermann/lib → lib}/mustermann/ast/translator.rb +0 -0
- data/{mustermann/lib → lib}/mustermann/ast/validation.rb +0 -0
- data/{mustermann/lib → lib}/mustermann/caster.rb +0 -0
- data/{mustermann/lib → lib}/mustermann/composite.rb +0 -0
- data/{mustermann/lib → lib}/mustermann/concat.rb +0 -0
- data/{mustermann/lib → lib}/mustermann/equality_map.rb +0 -0
- data/{mustermann/lib → lib}/mustermann/error.rb +0 -0
- data/{mustermann/lib → lib}/mustermann/expander.rb +0 -0
- data/{mustermann/lib → lib}/mustermann/extension.rb +0 -0
- data/{mustermann/lib → lib}/mustermann/identity.rb +0 -0
- data/{mustermann/lib → lib}/mustermann/mapper.rb +0 -0
- data/{mustermann/lib → lib}/mustermann/pattern.rb +0 -0
- data/{mustermann/lib → lib}/mustermann/pattern_cache.rb +0 -0
- data/{mustermann/lib → lib}/mustermann/regexp.rb +0 -0
- data/{mustermann/lib → lib}/mustermann/regexp_based.rb +0 -0
- data/{mustermann/lib → lib}/mustermann/regular.rb +0 -0
- data/{mustermann/lib → lib}/mustermann/simple_match.rb +0 -0
- data/{mustermann/lib → lib}/mustermann/sinatra.rb +0 -0
- data/{mustermann/lib → lib}/mustermann/sinatra/parser.rb +0 -0
- data/{mustermann/lib → lib}/mustermann/sinatra/safe_renderer.rb +0 -0
- data/{mustermann/lib → lib}/mustermann/sinatra/try_convert.rb +0 -0
- data/{mustermann/lib → lib}/mustermann/to_pattern.rb +0 -0
- data/{mustermann/lib → lib}/mustermann/version.rb +1 -1
- data/{mustermann/mustermann.gemspec → mustermann.gemspec} +0 -0
- data/{mustermann/spec → spec}/ast_spec.rb +0 -0
- data/{mustermann/spec → spec}/composite_spec.rb +0 -0
- data/{mustermann/spec → spec}/concat_spec.rb +0 -0
- data/{mustermann/spec → spec}/equality_map_spec.rb +0 -0
- data/{mustermann/spec → spec}/expander_spec.rb +0 -0
- data/{mustermann/spec → spec}/extension_spec.rb +0 -0
- data/{mustermann/spec → spec}/identity_spec.rb +0 -0
- data/{mustermann/spec → spec}/mapper_spec.rb +0 -0
- data/{mustermann/spec → spec}/mustermann_spec.rb +0 -0
- data/{mustermann/spec → spec}/pattern_spec.rb +0 -0
- data/{mustermann/spec → spec}/regexp_based_spec.rb +0 -0
- data/{mustermann/spec → spec}/regular_spec.rb +0 -0
- data/{mustermann/spec → spec}/simple_match_spec.rb +0 -0
- data/{mustermann/spec → spec}/sinatra_spec.rb +0 -0
- data/{mustermann/spec → spec}/to_pattern_spec.rb +0 -0
- metadata +71 -126
- data/.gitignore +0 -18
- data/.rspec +0 -5
- data/.travis.yml +0 -25
- data/.yardopts +0 -3
- data/Gemfile +0 -7
- data/Rakefile +0 -27
- data/mustermann-contrib/LICENSE +0 -23
- data/mustermann-contrib/README.md +0 -1155
- data/mustermann-contrib/examples/highlighting.rb +0 -35
- data/mustermann-contrib/highlighting.png +0 -0
- data/mustermann-contrib/irb.png +0 -0
- data/mustermann-contrib/lib/mustermann/cake.rb +0 -19
- data/mustermann-contrib/lib/mustermann/express.rb +0 -38
- data/mustermann-contrib/lib/mustermann/file_utils.rb +0 -218
- data/mustermann-contrib/lib/mustermann/file_utils/glob_pattern.rb +0 -40
- data/mustermann-contrib/lib/mustermann/fileutils.rb +0 -1
- data/mustermann-contrib/lib/mustermann/flask.rb +0 -199
- data/mustermann-contrib/lib/mustermann/pyramid.rb +0 -29
- data/mustermann-contrib/lib/mustermann/rails.rb +0 -47
- data/mustermann-contrib/lib/mustermann/shell.rb +0 -57
- data/mustermann-contrib/lib/mustermann/simple.rb +0 -51
- data/mustermann-contrib/lib/mustermann/string_scanner.rb +0 -314
- data/mustermann-contrib/lib/mustermann/strscan.rb +0 -1
- data/mustermann-contrib/lib/mustermann/template.rb +0 -63
- data/mustermann-contrib/lib/mustermann/uri_template.rb +0 -1
- data/mustermann-contrib/lib/mustermann/versions.rb +0 -47
- data/mustermann-contrib/lib/mustermann/visualizer.rb +0 -39
- data/mustermann-contrib/lib/mustermann/visualizer/highlight.rb +0 -138
- data/mustermann-contrib/lib/mustermann/visualizer/highlighter.rb +0 -38
- data/mustermann-contrib/lib/mustermann/visualizer/highlighter/ad_hoc.rb +0 -95
- data/mustermann-contrib/lib/mustermann/visualizer/highlighter/ast.rb +0 -103
- data/mustermann-contrib/lib/mustermann/visualizer/highlighter/composite.rb +0 -46
- data/mustermann-contrib/lib/mustermann/visualizer/highlighter/dummy.rb +0 -19
- data/mustermann-contrib/lib/mustermann/visualizer/highlighter/regular.rb +0 -105
- data/mustermann-contrib/lib/mustermann/visualizer/pattern_extension.rb +0 -69
- data/mustermann-contrib/lib/mustermann/visualizer/renderer/ansi.rb +0 -24
- data/mustermann-contrib/lib/mustermann/visualizer/renderer/generic.rb +0 -47
- data/mustermann-contrib/lib/mustermann/visualizer/renderer/hansi_template.rb +0 -35
- data/mustermann-contrib/lib/mustermann/visualizer/renderer/html.rb +0 -51
- data/mustermann-contrib/lib/mustermann/visualizer/renderer/sexp.rb +0 -38
- data/mustermann-contrib/lib/mustermann/visualizer/tree.rb +0 -64
- data/mustermann-contrib/lib/mustermann/visualizer/tree_renderer.rb +0 -79
- data/mustermann-contrib/mustermann-contrib.gemspec +0 -19
- data/mustermann-contrib/spec/cake_spec.rb +0 -91
- data/mustermann-contrib/spec/express_spec.rb +0 -210
- data/mustermann-contrib/spec/file_utils_spec.rb +0 -120
- data/mustermann-contrib/spec/flask_spec.rb +0 -362
- data/mustermann-contrib/spec/flask_subclass_spec.rb +0 -369
- data/mustermann-contrib/spec/pattern_extension_spec.rb +0 -50
- data/mustermann-contrib/spec/pyramid_spec.rb +0 -102
- data/mustermann-contrib/spec/rails_spec.rb +0 -648
- data/mustermann-contrib/spec/shell_spec.rb +0 -148
- data/mustermann-contrib/spec/simple_spec.rb +0 -269
- data/mustermann-contrib/spec/string_scanner_spec.rb +0 -272
- data/mustermann-contrib/spec/template_spec.rb +0 -842
- data/mustermann-contrib/spec/visualizer_spec.rb +0 -199
- data/mustermann-contrib/theme.png +0 -0
- data/mustermann-contrib/tree.png +0 -0
- data/mustermann/LICENSE +0 -23
- data/mustermann/README.md +0 -853
- data/support/lib/support.rb +0 -7
- data/support/lib/support/coverage.rb +0 -23
- data/support/lib/support/env.rb +0 -19
- data/support/lib/support/expand_matcher.rb +0 -28
- data/support/lib/support/generate_template_matcher.rb +0 -27
- data/support/lib/support/match_matcher.rb +0 -39
- data/support/lib/support/pattern.rb +0 -42
- data/support/lib/support/projects.rb +0 -20
- data/support/lib/support/scan_matcher.rb +0 -63
- data/support/support.gemspec +0 -27
@@ -1,35 +0,0 @@
|
|
1
|
-
require 'bundler/setup'
|
2
|
-
require 'mustermann/visualizer'
|
3
|
-
|
4
|
-
Hansi.mode = ARGV[0].to_i if ARGV.any?
|
5
|
-
|
6
|
-
def self.example(type, *patterns)
|
7
|
-
print Hansi.render(:bold, " #{type}: ".ljust(14))
|
8
|
-
patterns.each do |pattern|
|
9
|
-
pattern = Mustermann.new(pattern, type: type)
|
10
|
-
space_after = pattern.to_s.size > 24 ? " " : " " * (25 - pattern.to_s.size)
|
11
|
-
highlight = Mustermann::Visualizer.highlight(pattern, inspect: true)
|
12
|
-
print highlight.to_ansi + space_after
|
13
|
-
end
|
14
|
-
puts
|
15
|
-
end
|
16
|
-
|
17
|
-
puts
|
18
|
-
example(:cake, '/:prefix/**')
|
19
|
-
example(:express, '/:prefix+/:id(\d+)', '/:page/:slug+')
|
20
|
-
example(:flask, '/<prefix>/<int:id>', '/user/<int(min=0):id>')
|
21
|
-
example(:identity, '/image.png')
|
22
|
-
example(:pyramid, '/{prefix:.*}/{id}', '/{page}/*slug')
|
23
|
-
example(:rails, '/:slug(.:ext)')
|
24
|
-
example(:regexp, '/(?<slug>[^/]+)', '/(?:page|user)/(\d+)')
|
25
|
-
example(:shell, '/**/*', '/\{a,b\}/{a,b}')
|
26
|
-
example(:simple, '/:page/*slug')
|
27
|
-
example(:sinatra, '/:page/*slug', '/users/{id}?')
|
28
|
-
example(:template, '/{+pre}/{page}{?q,p}', '/users/{id}?')
|
29
|
-
puts
|
30
|
-
|
31
|
-
example(:composition)
|
32
|
-
composite = Mustermann.new("/{a}", "/{b}/{c}")
|
33
|
-
puts " " + composite.to_ansi
|
34
|
-
puts " " + (Mustermann.new("/") ^ composite).to_ansi
|
35
|
-
puts
|
Binary file
|
data/mustermann-contrib/irb.png
DELETED
Binary file
|
@@ -1,19 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
require 'mustermann'
|
3
|
-
require 'mustermann/ast/pattern'
|
4
|
-
|
5
|
-
module Mustermann
|
6
|
-
# CakePHP style pattern implementation.
|
7
|
-
#
|
8
|
-
# @example
|
9
|
-
# Mustermann.new('/:foo', type: :cake) === '/bar' # => true
|
10
|
-
#
|
11
|
-
# @see Mustermann::Pattern
|
12
|
-
# @see file:README.md#cake Syntax description in the README
|
13
|
-
class Cake < AST::Pattern
|
14
|
-
register :cake
|
15
|
-
|
16
|
-
on(?:) { |c| node(:capture) { scan(/\w+/) } }
|
17
|
-
on(?*) { |c| node(:splat, convert: (-> e { e.split('/') } unless scan(?*))) }
|
18
|
-
end
|
19
|
-
end
|
@@ -1,38 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
require 'mustermann'
|
3
|
-
require 'mustermann/ast/pattern'
|
4
|
-
|
5
|
-
module Mustermann
|
6
|
-
# Express style pattern implementation.
|
7
|
-
#
|
8
|
-
# @example
|
9
|
-
# Mustermann.new('/:foo', type: :express) === '/bar' # => true
|
10
|
-
#
|
11
|
-
# @see Mustermann::Pattern
|
12
|
-
# @see file:README.md#flask Syntax description in the README
|
13
|
-
class Express < AST::Pattern
|
14
|
-
register :express
|
15
|
-
|
16
|
-
on(nil, ??, ?+, ?*, ?)) { |c| unexpected(c) }
|
17
|
-
on(?:) { |c| node(:capture) { scan(/\w+/) } }
|
18
|
-
on(?() { |c| node(:splat, constraint: read_brackets(?(, ?))) }
|
19
|
-
|
20
|
-
suffix ??, after: :capture do |char, element|
|
21
|
-
unexpected(char) unless element.is_a? :capture
|
22
|
-
node(:optional, element)
|
23
|
-
end
|
24
|
-
|
25
|
-
suffix ?*, after: :capture do |match, element|
|
26
|
-
node(:named_splat, element.name)
|
27
|
-
end
|
28
|
-
|
29
|
-
suffix ?+, after: :capture do |match, element|
|
30
|
-
node(:named_splat, element.name, constraint: ".+")
|
31
|
-
end
|
32
|
-
|
33
|
-
suffix ?(, after: :capture do |match, element|
|
34
|
-
element.constraint = read_brackets(?(, ?))
|
35
|
-
element
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
@@ -1,218 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
require 'mustermann'
|
3
|
-
require 'mustermann/file_utils/glob_pattern'
|
4
|
-
require 'mustermann/mapper'
|
5
|
-
require 'fileutils'
|
6
|
-
|
7
|
-
module Mustermann
|
8
|
-
# Implements handy file operations using patterns.
|
9
|
-
module FileUtils
|
10
|
-
extend self
|
11
|
-
|
12
|
-
# Turn a Mustermann pattern into glob pattern.
|
13
|
-
#
|
14
|
-
# @example
|
15
|
-
# require 'mustermann/file_utils'
|
16
|
-
#
|
17
|
-
# Mustermann::FileUtils.glob_pattern('/:name') # => '/*'
|
18
|
-
# Mustermann::FileUtils.glob_pattern('src/:path/:file.(js|rb)') # => 'src/**/*/*.{js,rb}'
|
19
|
-
# Mustermann::FileUtils.glob_pattern('{a,b}/*', type: :shell) # => '{a,b}/*'
|
20
|
-
#
|
21
|
-
# pattern = Mustermann.new('/foo/:page', '/bar/:page') # => #<Mustermann::Composite:...>
|
22
|
-
# Mustermann::FileUtils.glob_pattern(pattern) # => "{/foo/*,/bar/*}"
|
23
|
-
#
|
24
|
-
# @param [Object] pattern the object to turn into a glob pattern.
|
25
|
-
# @return [String] the glob pattern
|
26
|
-
def glob_pattern(*pattern, **options)
|
27
|
-
pattern_with_glob_pattern(*pattern, **options).last
|
28
|
-
end
|
29
|
-
|
30
|
-
# Uses the given pattern(s) to search for files and directories.
|
31
|
-
#
|
32
|
-
# @example
|
33
|
-
# require 'mustermann/file_utils'
|
34
|
-
# Mustermann::FileUtils.glob(':base.:ext') # => ['example.txt']
|
35
|
-
#
|
36
|
-
# Mustermann::FileUtils.glob(':base.:ext') do |file, params|
|
37
|
-
# file # => "example.txt"
|
38
|
-
# params # => {"base"=>"example", "ext"=>"txt"}
|
39
|
-
# end
|
40
|
-
def glob(*pattern, **options, &block)
|
41
|
-
raise ArgumentError, "no pattern given" if pattern.empty?
|
42
|
-
pattern, glob_pattern = pattern_with_glob_pattern(*pattern, **options)
|
43
|
-
results = [] unless block
|
44
|
-
Dir.glob(glob_pattern) do |result|
|
45
|
-
next unless params = pattern.params(result)
|
46
|
-
block ? block[result, params] : results << result
|
47
|
-
end
|
48
|
-
results
|
49
|
-
end
|
50
|
-
|
51
|
-
# Allows to search for files an map these onto other strings.
|
52
|
-
#
|
53
|
-
# @example
|
54
|
-
# require 'mustermann/file_utils'
|
55
|
-
#
|
56
|
-
# Mustermann::FileUtils.glob_map(':base.:ext' => ':base.bak.:ext') # => {'example.txt' => 'example.bak.txt'}
|
57
|
-
# Mustermann::FileUtils.glob_map(':base.:ext' => :base) { |file, mapped| mapped } # => ['example']
|
58
|
-
#
|
59
|
-
# @see Mustermann::Mapper
|
60
|
-
def glob_map(map = {}, **options, &block)
|
61
|
-
map = Mapper === map ? map : Mapper.new(map, **options)
|
62
|
-
mapped = glob(*map.to_h.keys).map { |f| [f, unescape(map[f])] }
|
63
|
-
block ? mapped.map(&block) : Hash[mapped]
|
64
|
-
end
|
65
|
-
|
66
|
-
# Copies files based on a pattern mapping.
|
67
|
-
#
|
68
|
-
# @example
|
69
|
-
# require 'mustermann/file_utils'
|
70
|
-
#
|
71
|
-
# # copies example.txt to example.bak.txt
|
72
|
-
# Mustermann::FileUtils.cp(':base.:ext' => ':base.bak.:ext')
|
73
|
-
#
|
74
|
-
# @see #glob_map
|
75
|
-
def cp(map = {}, recursive: false, **options)
|
76
|
-
utils_opts, opts = split_options(:preserve, :dereference_root, :remove_destination, **options)
|
77
|
-
cp_method = recursive ? :cp_r : :cp
|
78
|
-
glob_map(map, **opts) { |o,n| f.send(cp_method, o, n, **utils_opts) }
|
79
|
-
end
|
80
|
-
|
81
|
-
|
82
|
-
# Copies files based on a pattern mapping, recursively.
|
83
|
-
#
|
84
|
-
# @example
|
85
|
-
# require 'mustermann/file_utils'
|
86
|
-
#
|
87
|
-
# # copies Foo.app/example.txt to Foo.back.app/example.txt
|
88
|
-
# Mustermann::FileUtils.cp_r(':base.:ext' => ':base.bak.:ext')
|
89
|
-
#
|
90
|
-
# @see #glob_map
|
91
|
-
def cp_r(map = {}, **options)
|
92
|
-
cp(map, recursive: true, **options)
|
93
|
-
end
|
94
|
-
|
95
|
-
# Moves files based on a pattern mapping.
|
96
|
-
#
|
97
|
-
# @example
|
98
|
-
# require 'mustermann/file_utils'
|
99
|
-
#
|
100
|
-
# # moves example.txt to example.bak.txt
|
101
|
-
# Mustermann::FileUtils.mv(':base.:ext' => ':base.bak.:ext')
|
102
|
-
#
|
103
|
-
# @see #glob_map
|
104
|
-
def mv(map = {}, **options)
|
105
|
-
utils_opts, opts = split_options(**options)
|
106
|
-
glob_map(map, **opts) { |o,n| f.mv(o, n, **utils_opts) }
|
107
|
-
end
|
108
|
-
|
109
|
-
|
110
|
-
# Creates links based on a pattern mapping.
|
111
|
-
#
|
112
|
-
# @example
|
113
|
-
# require 'mustermann/file_utils'
|
114
|
-
#
|
115
|
-
# # creates a link from bin/example to lib/example.rb
|
116
|
-
# Mustermann::FileUtils.ln('lib/:name.rb' => 'bin/:name')
|
117
|
-
#
|
118
|
-
# @see #glob_map
|
119
|
-
def ln(map = {}, symbolic: false, **options)
|
120
|
-
utils_opts, opts = split_options(**options)
|
121
|
-
link_method = symbolic ? :ln_s : :ln
|
122
|
-
glob_map(map, **opts) { |o,n| f.send(link_method, o, n, **utils_opts) }
|
123
|
-
end
|
124
|
-
|
125
|
-
# Creates symbolic links based on a pattern mapping.
|
126
|
-
#
|
127
|
-
# @example
|
128
|
-
# require 'mustermann/file_utils'
|
129
|
-
#
|
130
|
-
# # creates a symbolic link from bin/example to lib/example.rb
|
131
|
-
# Mustermann::FileUtils.ln_s('lib/:name.rb' => 'bin/:name')
|
132
|
-
#
|
133
|
-
# @see #glob_map
|
134
|
-
def ln_s(map = {}, **options)
|
135
|
-
ln(map, symbolic: true, **options)
|
136
|
-
end
|
137
|
-
|
138
|
-
# Creates symbolic links based on a pattern mapping.
|
139
|
-
# Overrides potentailly existing files.
|
140
|
-
#
|
141
|
-
# @example
|
142
|
-
# require 'mustermann/file_utils'
|
143
|
-
#
|
144
|
-
# # creates a symbolic link from bin/example to lib/example.rb
|
145
|
-
# Mustermann::FileUtils.ln_sf('lib/:name.rb' => 'bin/:name')
|
146
|
-
#
|
147
|
-
# @see #glob_map
|
148
|
-
def ln_sf(map = {}, **options)
|
149
|
-
ln(map, symbolic: true, force: true, **options)
|
150
|
-
end
|
151
|
-
|
152
|
-
|
153
|
-
# Splits options into those meant for Mustermann and those
|
154
|
-
# meant for ::FileUtils.
|
155
|
-
#
|
156
|
-
# @!visibility private
|
157
|
-
def split_options(*utils_option_names, **options)
|
158
|
-
utils_options, pattern_options = {}, {}
|
159
|
-
utils_option_names += %i[force noop verbose]
|
160
|
-
|
161
|
-
options.each do |key, value|
|
162
|
-
list = utils_option_names.include?(key) ? utils_options : pattern_options
|
163
|
-
list[key] = value
|
164
|
-
end
|
165
|
-
|
166
|
-
[utils_options, pattern_options]
|
167
|
-
end
|
168
|
-
|
169
|
-
# Create a Mustermann pattern from whatever the input is and turn it into
|
170
|
-
# a glob pattern.
|
171
|
-
#
|
172
|
-
# @!visibility private
|
173
|
-
def pattern_with_glob_pattern(*pattern, **options)
|
174
|
-
options[:uri_decode] ||= false
|
175
|
-
pattern = Mustermann.new(*pattern.flatten, **options)
|
176
|
-
@glob_patterns ||= {}
|
177
|
-
@glob_patterns[pattern] ||= GlobPattern.generate(pattern)
|
178
|
-
[pattern, @glob_patterns[pattern]]
|
179
|
-
end
|
180
|
-
|
181
|
-
# The FileUtils method to use.
|
182
|
-
# @!visibility private
|
183
|
-
def f
|
184
|
-
::FileUtils
|
185
|
-
end
|
186
|
-
|
187
|
-
# Unescape an URI escaped string.
|
188
|
-
# @!visibility private
|
189
|
-
def unescape(string)
|
190
|
-
@uri ||= URI::Parser.new
|
191
|
-
@uri.unescape(string)
|
192
|
-
end
|
193
|
-
|
194
|
-
# Create a new version of Mustermann::FileUtils using a different ::FileUtils module.
|
195
|
-
# @see DryRun
|
196
|
-
# @!visibility private
|
197
|
-
def with_file_utils(&block)
|
198
|
-
Module.new do
|
199
|
-
include Mustermann::FileUtils
|
200
|
-
define_method(:f, &block)
|
201
|
-
private(:f)
|
202
|
-
extend self
|
203
|
-
end
|
204
|
-
end
|
205
|
-
|
206
|
-
private :pattern_with_glob_pattern, :split_options, :f, :unescape
|
207
|
-
|
208
|
-
alias_method :copy, :cp
|
209
|
-
alias_method :move, :mv
|
210
|
-
alias_method :link, :ln
|
211
|
-
alias_method :symlink, :ln_s
|
212
|
-
alias_method :[], :glob
|
213
|
-
|
214
|
-
DryRun ||= with_file_utils { ::FileUtils::DryRun }
|
215
|
-
NoWrite ||= with_file_utils { ::FileUtils::NoWrite }
|
216
|
-
Verbose ||= with_file_utils { ::FileUtils::Verbose }
|
217
|
-
end
|
218
|
-
end
|
@@ -1,40 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
require 'mustermann/ast/translator'
|
3
|
-
|
4
|
-
module Mustermann
|
5
|
-
module FileUtils
|
6
|
-
# AST Translator to turn Mustermann patterns into glob patterns.
|
7
|
-
# @!visibility private
|
8
|
-
class GlobPattern < Mustermann::AST::Translator
|
9
|
-
# Character that need to be escaped in glob patterns.
|
10
|
-
# @!visibility private
|
11
|
-
ESCAPE = %w([ ] { } * ** \\)
|
12
|
-
|
13
|
-
# Turn a Mustermann pattern into glob pattern.
|
14
|
-
# @param [#to_glob, #to_ast, Object] pattern the object to turn into a glob pattern.
|
15
|
-
# @return [String] the glob pattern
|
16
|
-
# @!visibility private
|
17
|
-
def self.generate(pattern)
|
18
|
-
return pattern.to_glob if pattern.respond_to? :to_glob
|
19
|
-
return new.translate(pattern.to_ast) if pattern.respond_to? :to_ast
|
20
|
-
return "**/*" unless pattern.is_a? Mustermann::Composite
|
21
|
-
"{#{pattern.patterns.map { |p| generate(p) }.join(',')}}"
|
22
|
-
end
|
23
|
-
|
24
|
-
translate(:root, :group, :expression) { t(payload) || "" }
|
25
|
-
translate(:separator, :char) { t.escape(payload) }
|
26
|
-
translate(:capture) { constraint ? "**/*" : "*" }
|
27
|
-
translate(:optional) { "{#{t(payload)},}" }
|
28
|
-
translate(:named_splat, :splat) { "**/*" }
|
29
|
-
translate(:with_look_ahead) { t(head) + t(payload) }
|
30
|
-
translate(:union) { "{#{payload.map { |e| t(e) }.join(',')}}" }
|
31
|
-
translate(Array) { map { |e| t(e) }.join }
|
32
|
-
|
33
|
-
# Escape with a slash rather than URI escaping.
|
34
|
-
# @!visibility private
|
35
|
-
def escape(char)
|
36
|
-
ESCAPE.include?(char) ? "\\#{char}" : char
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
@@ -1 +0,0 @@
|
|
1
|
-
require 'mustermann/file_utils'
|
@@ -1,199 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
require 'mustermann'
|
3
|
-
require 'mustermann/ast/pattern'
|
4
|
-
|
5
|
-
module Mustermann
|
6
|
-
# Flask style pattern implementation.
|
7
|
-
#
|
8
|
-
# @example
|
9
|
-
# Mustermann.new('/<foo>', type: :flask) === '/bar' # => true
|
10
|
-
#
|
11
|
-
# @see Mustermann::Pattern
|
12
|
-
# @see file:README.md#flask Syntax description in the README
|
13
|
-
class Flask < AST::Pattern
|
14
|
-
include Concat::Native
|
15
|
-
register :flask
|
16
|
-
|
17
|
-
on(nil, ?>, ?:) { |c| unexpected(c) }
|
18
|
-
|
19
|
-
on(?<) do |char|
|
20
|
-
converter_name = expect(/\w+/, char: char)
|
21
|
-
args, opts = scan(?() ? read_args(?=, ?)) : [[], {}]
|
22
|
-
|
23
|
-
if scan(?:)
|
24
|
-
name = read_escaped(?>)
|
25
|
-
else
|
26
|
-
converter_name, name = 'default', converter_name
|
27
|
-
expect(?>)
|
28
|
-
end
|
29
|
-
|
30
|
-
converter = pattern.converters.fetch(converter_name) { unexpected("converter %p" % converter_name) }
|
31
|
-
converter = converter.new(*args, **opts) if converter.respond_to? :new
|
32
|
-
constraint = converter.constraint if converter.respond_to? :constraint
|
33
|
-
convert = converter.convert if converter.respond_to? :convert
|
34
|
-
qualifier = converter.qualifier if converter.respond_to? :qualifier
|
35
|
-
node_type = converter.node_type if converter.respond_to? :node_type
|
36
|
-
node_type ||= :capture
|
37
|
-
|
38
|
-
node(node_type, name, convert: convert, constraint: constraint, qualifier: qualifier)
|
39
|
-
end
|
40
|
-
|
41
|
-
# A class for easy creating of converters.
|
42
|
-
# @see Mustermann::Flask#register_converter
|
43
|
-
class Converter
|
44
|
-
# Constraint on the format used for the capture.
|
45
|
-
# Should be a regexp (or a string corresponding to a regexp)
|
46
|
-
# @see Mustermann::Flask#register_converter
|
47
|
-
attr_accessor :constraint
|
48
|
-
|
49
|
-
# Callback
|
50
|
-
# Should be a Proc.
|
51
|
-
# @see Mustermann::Flask#register_converter
|
52
|
-
attr_accessor :convert
|
53
|
-
|
54
|
-
# Constraint on the format used for the capture.
|
55
|
-
# Should be a regexp (or a string corresponding to a regexp)
|
56
|
-
# @see Mustermann::Flask#register_converter
|
57
|
-
# @!visibility private
|
58
|
-
attr_accessor :node_type
|
59
|
-
|
60
|
-
# Constraint on the format used for the capture.
|
61
|
-
# Should be a regexp (or a string corresponding to a regexp)
|
62
|
-
# @see Mustermann::Flask#register_converter
|
63
|
-
# @!visibility private
|
64
|
-
attr_accessor :qualifier
|
65
|
-
|
66
|
-
# @!visibility private
|
67
|
-
def self.create(&block)
|
68
|
-
Class.new(self) do
|
69
|
-
define_method(:initialize) { |*a, **o| block[self, *a, **o] }
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
# Makes sure a given value falls inbetween a min and a max.
|
74
|
-
# Uses the passed block to convert the value from a string to whatever
|
75
|
-
# format you'd expect.
|
76
|
-
#
|
77
|
-
# @example
|
78
|
-
# require 'mustermann/flask'
|
79
|
-
#
|
80
|
-
# class MyPattern < Mustermann::Flask
|
81
|
-
# register_converter(:x) { between(5, 15, &:to_i) }
|
82
|
-
# end
|
83
|
-
#
|
84
|
-
# pattern = MyPattern.new('<x:id>')
|
85
|
-
# pattern.params('/12') # => { 'id' => 12 }
|
86
|
-
# pattern.params('/16') # => { 'id' => 15 }
|
87
|
-
#
|
88
|
-
# @see Mustermann::Flask#register_converter
|
89
|
-
def between(min, max)
|
90
|
-
self.convert = proc do |input|
|
91
|
-
value = yield(input)
|
92
|
-
value = yield(min) if min and value < yield(min)
|
93
|
-
value = yield(max) if max and value > yield(max)
|
94
|
-
value
|
95
|
-
end
|
96
|
-
end
|
97
|
-
end
|
98
|
-
|
99
|
-
# Generally available converters.
|
100
|
-
# @!visibility private
|
101
|
-
def self.converters(inherited = true)
|
102
|
-
return @converters ||= {} unless inherited
|
103
|
-
defaults = superclass.respond_to?(:converters) ? superclass.converters : {}
|
104
|
-
defaults.merge(converters(false))
|
105
|
-
end
|
106
|
-
|
107
|
-
# Allows you to register your own converters.
|
108
|
-
#
|
109
|
-
# It is reommended to use this on a subclass, so to not influence other subsystems
|
110
|
-
# using flask templates.
|
111
|
-
#
|
112
|
-
# The object passed in as converter can implement #convert and/or #constraint.
|
113
|
-
#
|
114
|
-
# It can also instead implement #new, which will then return an object responding
|
115
|
-
# to some of these methods. Arguments from the flask pattern will be passed to #new.
|
116
|
-
#
|
117
|
-
# If passed a block, it will be yielded to with a {Mustermann::Flask::Converter}
|
118
|
-
# instance and any arguments in the flask pattern.
|
119
|
-
#
|
120
|
-
# @example with simple object
|
121
|
-
# require 'mustermann/flask'
|
122
|
-
#
|
123
|
-
# MyPattern = Class.new(Mustermann::Flask)
|
124
|
-
# up_converter = Struct.new(:convert).new(:upcase.to_proc)
|
125
|
-
# MyPattern.register_converter(:upper, up_converter)
|
126
|
-
#
|
127
|
-
# MyPattern.new("/<up:name>").params('/foo') # => { "name" => "FOO" }
|
128
|
-
#
|
129
|
-
# @example with block
|
130
|
-
# require 'mustermann/flask'
|
131
|
-
#
|
132
|
-
# MyPattern = Class.new(Mustermann::Flask)
|
133
|
-
# MyPattern.register_converter(:upper) { |c| c.convert = :upcase.to_proc }
|
134
|
-
#
|
135
|
-
# MyPattern.new("/<up:name>").params('/foo') # => { "name" => "FOO" }
|
136
|
-
#
|
137
|
-
# @example with converter class
|
138
|
-
# require 'mustermann/flasl'
|
139
|
-
#
|
140
|
-
# class MyPattern < Mustermann::Flask
|
141
|
-
# class Converter
|
142
|
-
# attr_reader :convert
|
143
|
-
# def initialize(send: :to_s)
|
144
|
-
# @convert = send.to_sym.to_proc
|
145
|
-
# end
|
146
|
-
# end
|
147
|
-
#
|
148
|
-
# register_converter(:t, Converter)
|
149
|
-
# end
|
150
|
-
#
|
151
|
-
# MyPattern.new("/<t(send=upcase):name>").params('/Foo') # => { "name" => "FOO" }
|
152
|
-
# MyPattern.new("/<t(send=downcase):name>").params('/Foo') # => { "name" => "foo" }
|
153
|
-
#
|
154
|
-
# @param [#to_s] name converter name
|
155
|
-
# @param [#new, #convert, #constraint, nil] converter
|
156
|
-
def self.register_converter(name, converter = nil, &block)
|
157
|
-
converter ||= Converter.create(&block)
|
158
|
-
converters(false)[name.to_s] = converter
|
159
|
-
end
|
160
|
-
|
161
|
-
register_converter(:string) do |converter, minlength: nil, maxlength: nil, length: nil|
|
162
|
-
converter.qualifier = "{%s,%s}" % [minlength || 1, maxlength] if minlength or maxlength
|
163
|
-
converter.qualifier = "{%s}" % length if length
|
164
|
-
end
|
165
|
-
|
166
|
-
register_converter(:int) do |converter, min: nil, max: nil, fixed_digits: false|
|
167
|
-
converter.constraint = /\d/
|
168
|
-
converter.qualifier = "{#{fixed_digits}}" if fixed_digits
|
169
|
-
converter.between(min, max) { |string| Integer(string) }
|
170
|
-
end
|
171
|
-
|
172
|
-
register_converter(:float) do |converter, min: nil, max: nil|
|
173
|
-
converter.constraint = /\d*\.?\d+/
|
174
|
-
converter.qualifier = ""
|
175
|
-
converter.between(min, max) { |string| Float(string) }
|
176
|
-
end
|
177
|
-
|
178
|
-
register_converter(:path) do |converter|
|
179
|
-
converter.node_type = :named_splat
|
180
|
-
end
|
181
|
-
|
182
|
-
register_converter(:any) do |converter, *strings|
|
183
|
-
strings = strings.map { |s| Regexp.escape(s) unless s == {} }.compact
|
184
|
-
converter.qualifier = ""
|
185
|
-
converter.constraint = Regexp.union(*strings)
|
186
|
-
end
|
187
|
-
|
188
|
-
register_converter(:default, converters['string'])
|
189
|
-
|
190
|
-
supported_options :converters
|
191
|
-
attr_reader :converters
|
192
|
-
|
193
|
-
def initialize(input, converters: {}, **options)
|
194
|
-
@converters = self.class.converters.dup
|
195
|
-
converters.each { |k,v| @converters[k.to_s] = v } if converters
|
196
|
-
super(input, **options)
|
197
|
-
end
|
198
|
-
end
|
199
|
-
end
|