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.
Files changed (126) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +799 -230
  3. data/{mustermann/bench → bench}/capturing.rb +0 -0
  4. data/{mustermann/bench → bench}/regexp.rb +0 -0
  5. data/{mustermann/bench → bench}/simple_vs_sinatra.rb +0 -0
  6. data/{mustermann/bench → bench}/template_vs_addressable.rb +0 -0
  7. data/{mustermann/lib → lib}/mustermann.rb +0 -0
  8. data/{mustermann/lib → lib}/mustermann/ast/boundaries.rb +0 -0
  9. data/{mustermann/lib → lib}/mustermann/ast/compiler.rb +0 -0
  10. data/{mustermann/lib → lib}/mustermann/ast/expander.rb +0 -0
  11. data/{mustermann/lib → lib}/mustermann/ast/node.rb +0 -0
  12. data/{mustermann/lib → lib}/mustermann/ast/param_scanner.rb +0 -0
  13. data/{mustermann/lib → lib}/mustermann/ast/parser.rb +0 -0
  14. data/{mustermann/lib → lib}/mustermann/ast/pattern.rb +0 -0
  15. data/{mustermann/lib → lib}/mustermann/ast/template_generator.rb +0 -0
  16. data/{mustermann/lib → lib}/mustermann/ast/transformer.rb +0 -0
  17. data/{mustermann/lib → lib}/mustermann/ast/translator.rb +0 -0
  18. data/{mustermann/lib → lib}/mustermann/ast/validation.rb +0 -0
  19. data/{mustermann/lib → lib}/mustermann/caster.rb +0 -0
  20. data/{mustermann/lib → lib}/mustermann/composite.rb +0 -0
  21. data/{mustermann/lib → lib}/mustermann/concat.rb +0 -0
  22. data/{mustermann/lib → lib}/mustermann/equality_map.rb +0 -0
  23. data/{mustermann/lib → lib}/mustermann/error.rb +0 -0
  24. data/{mustermann/lib → lib}/mustermann/expander.rb +0 -0
  25. data/{mustermann/lib → lib}/mustermann/extension.rb +0 -0
  26. data/{mustermann/lib → lib}/mustermann/identity.rb +0 -0
  27. data/{mustermann/lib → lib}/mustermann/mapper.rb +0 -0
  28. data/{mustermann/lib → lib}/mustermann/pattern.rb +0 -0
  29. data/{mustermann/lib → lib}/mustermann/pattern_cache.rb +0 -0
  30. data/{mustermann/lib → lib}/mustermann/regexp.rb +0 -0
  31. data/{mustermann/lib → lib}/mustermann/regexp_based.rb +0 -0
  32. data/{mustermann/lib → lib}/mustermann/regular.rb +0 -0
  33. data/{mustermann/lib → lib}/mustermann/simple_match.rb +0 -0
  34. data/{mustermann/lib → lib}/mustermann/sinatra.rb +0 -0
  35. data/{mustermann/lib → lib}/mustermann/sinatra/parser.rb +0 -0
  36. data/{mustermann/lib → lib}/mustermann/sinatra/safe_renderer.rb +0 -0
  37. data/{mustermann/lib → lib}/mustermann/sinatra/try_convert.rb +0 -0
  38. data/{mustermann/lib → lib}/mustermann/to_pattern.rb +0 -0
  39. data/{mustermann/lib → lib}/mustermann/version.rb +1 -1
  40. data/{mustermann/mustermann.gemspec → mustermann.gemspec} +0 -0
  41. data/{mustermann/spec → spec}/ast_spec.rb +0 -0
  42. data/{mustermann/spec → spec}/composite_spec.rb +0 -0
  43. data/{mustermann/spec → spec}/concat_spec.rb +0 -0
  44. data/{mustermann/spec → spec}/equality_map_spec.rb +0 -0
  45. data/{mustermann/spec → spec}/expander_spec.rb +0 -0
  46. data/{mustermann/spec → spec}/extension_spec.rb +0 -0
  47. data/{mustermann/spec → spec}/identity_spec.rb +0 -0
  48. data/{mustermann/spec → spec}/mapper_spec.rb +0 -0
  49. data/{mustermann/spec → spec}/mustermann_spec.rb +0 -0
  50. data/{mustermann/spec → spec}/pattern_spec.rb +0 -0
  51. data/{mustermann/spec → spec}/regexp_based_spec.rb +0 -0
  52. data/{mustermann/spec → spec}/regular_spec.rb +0 -0
  53. data/{mustermann/spec → spec}/simple_match_spec.rb +0 -0
  54. data/{mustermann/spec → spec}/sinatra_spec.rb +0 -0
  55. data/{mustermann/spec → spec}/to_pattern_spec.rb +0 -0
  56. metadata +71 -126
  57. data/.gitignore +0 -18
  58. data/.rspec +0 -5
  59. data/.travis.yml +0 -25
  60. data/.yardopts +0 -3
  61. data/Gemfile +0 -7
  62. data/Rakefile +0 -27
  63. data/mustermann-contrib/LICENSE +0 -23
  64. data/mustermann-contrib/README.md +0 -1155
  65. data/mustermann-contrib/examples/highlighting.rb +0 -35
  66. data/mustermann-contrib/highlighting.png +0 -0
  67. data/mustermann-contrib/irb.png +0 -0
  68. data/mustermann-contrib/lib/mustermann/cake.rb +0 -19
  69. data/mustermann-contrib/lib/mustermann/express.rb +0 -38
  70. data/mustermann-contrib/lib/mustermann/file_utils.rb +0 -218
  71. data/mustermann-contrib/lib/mustermann/file_utils/glob_pattern.rb +0 -40
  72. data/mustermann-contrib/lib/mustermann/fileutils.rb +0 -1
  73. data/mustermann-contrib/lib/mustermann/flask.rb +0 -199
  74. data/mustermann-contrib/lib/mustermann/pyramid.rb +0 -29
  75. data/mustermann-contrib/lib/mustermann/rails.rb +0 -47
  76. data/mustermann-contrib/lib/mustermann/shell.rb +0 -57
  77. data/mustermann-contrib/lib/mustermann/simple.rb +0 -51
  78. data/mustermann-contrib/lib/mustermann/string_scanner.rb +0 -314
  79. data/mustermann-contrib/lib/mustermann/strscan.rb +0 -1
  80. data/mustermann-contrib/lib/mustermann/template.rb +0 -63
  81. data/mustermann-contrib/lib/mustermann/uri_template.rb +0 -1
  82. data/mustermann-contrib/lib/mustermann/versions.rb +0 -47
  83. data/mustermann-contrib/lib/mustermann/visualizer.rb +0 -39
  84. data/mustermann-contrib/lib/mustermann/visualizer/highlight.rb +0 -138
  85. data/mustermann-contrib/lib/mustermann/visualizer/highlighter.rb +0 -38
  86. data/mustermann-contrib/lib/mustermann/visualizer/highlighter/ad_hoc.rb +0 -95
  87. data/mustermann-contrib/lib/mustermann/visualizer/highlighter/ast.rb +0 -103
  88. data/mustermann-contrib/lib/mustermann/visualizer/highlighter/composite.rb +0 -46
  89. data/mustermann-contrib/lib/mustermann/visualizer/highlighter/dummy.rb +0 -19
  90. data/mustermann-contrib/lib/mustermann/visualizer/highlighter/regular.rb +0 -105
  91. data/mustermann-contrib/lib/mustermann/visualizer/pattern_extension.rb +0 -69
  92. data/mustermann-contrib/lib/mustermann/visualizer/renderer/ansi.rb +0 -24
  93. data/mustermann-contrib/lib/mustermann/visualizer/renderer/generic.rb +0 -47
  94. data/mustermann-contrib/lib/mustermann/visualizer/renderer/hansi_template.rb +0 -35
  95. data/mustermann-contrib/lib/mustermann/visualizer/renderer/html.rb +0 -51
  96. data/mustermann-contrib/lib/mustermann/visualizer/renderer/sexp.rb +0 -38
  97. data/mustermann-contrib/lib/mustermann/visualizer/tree.rb +0 -64
  98. data/mustermann-contrib/lib/mustermann/visualizer/tree_renderer.rb +0 -79
  99. data/mustermann-contrib/mustermann-contrib.gemspec +0 -19
  100. data/mustermann-contrib/spec/cake_spec.rb +0 -91
  101. data/mustermann-contrib/spec/express_spec.rb +0 -210
  102. data/mustermann-contrib/spec/file_utils_spec.rb +0 -120
  103. data/mustermann-contrib/spec/flask_spec.rb +0 -362
  104. data/mustermann-contrib/spec/flask_subclass_spec.rb +0 -369
  105. data/mustermann-contrib/spec/pattern_extension_spec.rb +0 -50
  106. data/mustermann-contrib/spec/pyramid_spec.rb +0 -102
  107. data/mustermann-contrib/spec/rails_spec.rb +0 -648
  108. data/mustermann-contrib/spec/shell_spec.rb +0 -148
  109. data/mustermann-contrib/spec/simple_spec.rb +0 -269
  110. data/mustermann-contrib/spec/string_scanner_spec.rb +0 -272
  111. data/mustermann-contrib/spec/template_spec.rb +0 -842
  112. data/mustermann-contrib/spec/visualizer_spec.rb +0 -199
  113. data/mustermann-contrib/theme.png +0 -0
  114. data/mustermann-contrib/tree.png +0 -0
  115. data/mustermann/LICENSE +0 -23
  116. data/mustermann/README.md +0 -853
  117. data/support/lib/support.rb +0 -7
  118. data/support/lib/support/coverage.rb +0 -23
  119. data/support/lib/support/env.rb +0 -19
  120. data/support/lib/support/expand_matcher.rb +0 -28
  121. data/support/lib/support/generate_template_matcher.rb +0 -27
  122. data/support/lib/support/match_matcher.rb +0 -39
  123. data/support/lib/support/pattern.rb +0 -42
  124. data/support/lib/support/projects.rb +0 -20
  125. data/support/lib/support/scan_matcher.rb +0 -63
  126. data/support/support.gemspec +0 -27
@@ -1 +0,0 @@
1
- require 'mustermann/string_scanner'
@@ -1,63 +0,0 @@
1
- # frozen_string_literal: true
2
- require 'mustermann'
3
- require 'mustermann/ast/pattern'
4
-
5
- module Mustermann
6
- # URI template pattern implementation.
7
- #
8
- # @example
9
- # Mustermann.new('/{foo}') === '/bar' # => true
10
- #
11
- # @see Mustermann::Pattern
12
- # @see file:README.md#template Syntax description in the README
13
- # @see http://tools.ietf.org/html/rfc6570 RFC 6570
14
- class Template < AST::Pattern
15
- include Concat::Native
16
- register :template, :uri_template
17
-
18
- on ?{ do |char|
19
- variable = proc do
20
- start = pos
21
- match = expect(/(?<name>\w+)(?:\:(?<prefix>\d{1,4})|(?<explode>\*))?/)
22
- node(:variable, match[:name], prefix: match[:prefix], explode: match[:explode], start: start)
23
- end
24
-
25
- operator = buffer.scan(/[\+\#\.\/;\?\&\=\,\!\@\|]/)
26
- expression = node(:expression, [variable[]], operator: operator) { variable[] if scan(?,) }
27
- expression if expect(?})
28
- end
29
-
30
- on(?}) { |c| unexpected(c) }
31
-
32
- # @!visibility private
33
- def compile(*args, **options)
34
- @split_params = {}
35
- super(*args, split_params: @split_params, **options)
36
- end
37
-
38
- # @!visibility private
39
- def map_param(key, value)
40
- return super unless variable = @split_params[key]
41
- value = value.split variable[:separator]
42
- value.map! { |e| e.sub(/\A#{key}=/, '') } if variable[:parametric]
43
- value.map! { |e| super(key, e) }
44
- end
45
-
46
- # @!visibility private
47
- def always_array?(key)
48
- @split_params.include? key
49
- end
50
-
51
- # Identity patterns support generating templates (the logic is quite complex, though).
52
- #
53
- # @example (see Mustermann::Pattern#to_templates)
54
- # @param (see Mustermann::Pattern#to_templates)
55
- # @return (see Mustermann::Pattern#to_templates)
56
- # @see Mustermann::Pattern#to_templates
57
- def to_templates
58
- [to_s]
59
- end
60
-
61
- private :compile, :map_param, :always_array?
62
- end
63
- end
@@ -1 +0,0 @@
1
- require 'mustermann/template'
@@ -1,47 +0,0 @@
1
- # frozen_string_literal: true
2
- module Mustermann
3
- # Mixin that adds support for multiple versions of the same type.
4
- # @see Mustermann::Rails
5
- # @!visibility private
6
- module Versions
7
- # Checks if class has mulitple versions available and picks one that matches the version option.
8
- # @!visibility private
9
- def new(*args, version: nil, **options)
10
- return super(*args, **options) unless versions.any?
11
- self[version].new(*args, **options)
12
- end
13
-
14
- # @return [Hash] version to subclass mapping.
15
- # @!visibility private
16
- def versions
17
- @versions ||= {}
18
- end
19
-
20
- # Defines a new version.
21
- # @!visibility private
22
- def version(*list, inherit_from: nil, &block)
23
- superclass = self[inherit_from] || self
24
- subclass = Class.new(superclass, &block)
25
- list.each { |v| versions[v] = subclass }
26
- end
27
-
28
- # Resolve a subclass for a given version string.
29
- # @!visibility private
30
- def [](version)
31
- return versions.values.last unless version
32
- detected = versions.detect { |v,_| version.start_with?(v) }
33
- raise ArgumentError, 'unsupported version %p' % version unless detected
34
- detected.last
35
- end
36
-
37
- # @!visibility private
38
- def name
39
- super || superclass.name
40
- end
41
-
42
- # @!visibility private
43
- def inspect
44
- name
45
- end
46
- end
47
- end
@@ -1,39 +0,0 @@
1
- # frozen_string_literal: true
2
- require 'mustermann'
3
- require 'mustermann/visualizer/highlight'
4
- require 'mustermann/visualizer/tree_renderer'
5
- require 'mustermann/visualizer/pattern_extension'
6
-
7
- module Mustermann
8
- # Namespace for Mustermann visualization logic.
9
- module Visualizer
10
- extend self
11
-
12
- # @example creating a highlight object
13
- # require 'mustermann/visualizer'
14
- #
15
- # pattern = Mustermann.new('/:name')
16
- # highlight = Mustermann::Visualizer.highlight(pattern)
17
- #
18
- # puts highlight.to_ansi
19
- #
20
- # @return [Mustermann::Visualizer::Highlight] highlight object for given pattern
21
- # @param (see Mustermann::Visualizer::Highlight#initialize)
22
- def highlight(pattern, **options)
23
- Highlight.new(pattern, **options)
24
- end
25
-
26
- # @example creating a tree object
27
- # require 'mustermann/visualizer'
28
- #
29
- # pattern = Mustermann.new('/:name')
30
- # tree = Mustermann::Visualizer.tree(pattern)
31
- #
32
- # puts highlight.to_s
33
- #
34
- # @return [Mustermann::Visualizer::Tree] tree object for given pattern
35
- def tree(pattern, **options)
36
- TreeRenderer.render(pattern, **options)
37
- end
38
- end
39
- end
@@ -1,138 +0,0 @@
1
- # frozen_string_literal: true
2
- require 'hansi'
3
- require 'mustermann'
4
- require 'mustermann/visualizer/highlighter'
5
- require 'mustermann/visualizer/renderer/ansi'
6
- require 'mustermann/visualizer/renderer/hansi_template'
7
- require 'mustermann/visualizer/renderer/html'
8
- require 'mustermann/visualizer/renderer/sexp'
9
-
10
- module Mustermann
11
- module Visualizer
12
- # Meta class for highlight objects.
13
- # @see Mustermann::Visualizer#highlight
14
- class Highlight
15
- # @!visibility private
16
- attr_reader :pattern, :theme
17
-
18
- # @!visibility private
19
- DEFAULT_THEME = Hansi::Theme.new(:solarized, {
20
- default: :base0,
21
- separator: :base1,
22
- escaped: :base1,
23
- capture: :orange,
24
- name: :yellow,
25
- special: :blue,
26
- quote: :red,
27
- illegal: :darkred
28
- })
29
-
30
- # @!visibility private
31
- BASE_THEME = Hansi::Theme.new({
32
- special: :default,
33
- capture: :special,
34
- char: :default,
35
- expression: :capture,
36
- composition: :special,
37
- group: :composition,
38
- union: :composition,
39
- optional: :special,
40
- root: :default,
41
- separator: :char,
42
- splat: :capture,
43
- named_splat: :splat,
44
- variable: :capture,
45
- escaped: :char,
46
- quote: :special,
47
- type: :special,
48
- illegal: :special
49
- })
50
-
51
- # @!visibility private
52
- def initialize(pattern, type: nil, inspect: nil, **theme)
53
- @pattern = Mustermann.new(pattern, type: type)
54
- @inspect = inspect.nil? ? pattern.is_a?(Mustermann::Composite) : inspect
55
- theme = theme.any? ? Hansi::Theme.new(theme) : DEFAULT_THEME
56
- @theme = BASE_THEME.merge(theme)
57
- end
58
-
59
- # @example
60
- # require 'mustermann/visualizer'
61
- #
62
- # pattern = Mustermann.new('/:name')
63
- # highlight = Mustermann::Visualizer.highlight(pattern)
64
- #
65
- # puts highlight.to_hansi_template
66
- #
67
- # @return [String] Hansi template representation of the pattern
68
- def to_hansi_template(**options)
69
- render_with(Renderer::HansiTemplate, **options)
70
- end
71
-
72
- # @example
73
- # require 'mustermann/visualizer'
74
- #
75
- # pattern = Mustermann.new('/:name')
76
- # highlight = Mustermann::Visualizer.highlight(pattern)
77
- #
78
- # puts highlight.to_ansi
79
- #
80
- # @return [String] ANSI colorized version of the pattern
81
- def to_ansi(**options)
82
- render_with(Renderer::ANSI, **options)
83
- end
84
-
85
- # @example
86
- # require 'mustermann/visualizer'
87
- #
88
- # pattern = Mustermann.new('/:name')
89
- # highlight = Mustermann::Visualizer.highlight(pattern)
90
- #
91
- # puts highlight.to_html
92
- #
93
- # @return [String] HTML rendering of the pattern
94
- def to_html(**options)
95
- render_with(Renderer::HTML, **options)
96
- end
97
-
98
- # @example
99
- # require 'mustermann/visualizer'
100
- #
101
- # pattern = Mustermann.new('/:name')
102
- # highlight = Mustermann::Visualizer.highlight(pattern)
103
- #
104
- # puts highlight.to_sexp
105
- #
106
- # @return [String] s-expression like representation of the pattern
107
- def to_sexp(**options)
108
- render_with(Renderer::Sexp, **options)
109
- end
110
-
111
- # @return [Mustermann::Pattern] the pattern used to create the highlight object
112
- def to_pattern
113
- pattern
114
- end
115
-
116
- # @return [String] string representation of the pattern
117
- def to_s
118
- pattern.to_s
119
- end
120
-
121
- # @return [String] stylesheet for HTML output from the pattern
122
- def stylesheet(**options)
123
- Renderer::HTML.new(self, **options).stylesheet
124
- end
125
-
126
- # @!visibility private
127
- def render_with(renderer, **options)
128
- options[:inspect] = @inspect if options[:inspect].nil?
129
- renderer.new(self, **options).render
130
- end
131
-
132
- # @!visibility private
133
- def render(renderer)
134
- Highlighter.highlight(pattern, renderer)
135
- end
136
- end
137
- end
138
- end
@@ -1,38 +0,0 @@
1
- # frozen_string_literal: true
2
- require 'mustermann/visualizer/highlighter/ast'
3
- require 'mustermann/visualizer/highlighter/ad_hoc'
4
- require 'mustermann/visualizer/highlighter/composite'
5
- require 'mustermann/visualizer/highlighter/dummy'
6
- require 'mustermann/visualizer/highlighter/regular'
7
-
8
- module Mustermann
9
- module Visualizer
10
- # @!visibility private
11
- module Highlighter
12
- extend self
13
-
14
- # @return [String] highlighted string
15
- # @!visibility private
16
- def highlight(pattern, renderer)
17
- highlighter_for(pattern).highlight(pattern, renderer)
18
- end
19
-
20
- # @return [#highlight] Highlighter for given pattern
21
- # @!visibility private
22
- def highlighter_for(pattern)
23
- return pattern.highlighter if pattern.respond_to? :highlighter and pattern.highlighter
24
- consts = constants.map { |name| const_get(name) }
25
- highlighter = consts.detect { |c| c.respond_to? :highlight? and c.highlight? pattern }
26
- highlighter || Dummy
27
- end
28
-
29
- # Used to generate highlighting rules on the fly.
30
- # @see {Mustermann::Shell#highlighter}
31
- # @see {Mustermann::Simple#highlighter}
32
- # @!visibility private
33
- def create(&block)
34
- Class.new(AdHoc, &block)
35
- end
36
- end
37
- end
38
- end
@@ -1,95 +0,0 @@
1
- # frozen_string_literal: true
2
- require 'strscan'
3
-
4
- module Mustermann
5
- module Visualizer
6
- # @!visibility private
7
- module Highlighter
8
- # Used to generate highlighting rules on the fly.
9
- # @see {Mustermann::Shell#highlighter}
10
- # @see {Mustermann::Simple#highlighter}
11
- # @!visibility private
12
- class AdHoc
13
- # @!visibility private
14
- def self.highlight(pattern, renderer)
15
- new(pattern, renderer).highlight
16
- end
17
-
18
- # @!visibility private
19
- def self.rules
20
- @rules ||= {}
21
- end
22
-
23
- # @!visibility private
24
- def self.on(regexp, type = nil, &callback)
25
- return regexp.map { |key, value| on(key, value, &callback) } if regexp.is_a? Hash
26
- raise ArgumentError, 'needs type or callback' unless type or callback
27
- callback ||= proc { |matched| element(type, matched) }
28
- regexp = Regexp.new(Regexp.escape(regexp)) unless regexp.is_a? Regexp
29
- rules[regexp] = callback
30
- end
31
-
32
- # @!visibility private
33
- attr_reader :pattern, :renderer, :rules, :output, :scanner
34
- def initialize(pattern, renderer)
35
- @pattern = pattern
36
- @renderer = renderer
37
- @output = String.new
38
- @rules = self.class.rules
39
- @scanner = ::StringScanner.new(pattern.to_s)
40
- end
41
-
42
- # @!visibility private
43
- def highlight(stop = /\Z/)
44
- output << renderer.pre(:root)
45
- until scanner.eos? or scanner.check(stop)
46
- position = scanner.pos
47
- apply(scanner)
48
- read_char(scanner) if position == scanner.pos and not scanner.check(stop)
49
- end
50
- output << renderer.post(:root)
51
- end
52
-
53
- # @!visibility private
54
- def apply(scanner)
55
- rules.each do |regexp, callback|
56
- next unless result = scanner.scan(regexp)
57
- instance_exec(result, &callback)
58
- end
59
- end
60
-
61
- # @!visibility private
62
- def read_char(scanner)
63
- return unless char = scanner.getch
64
- type = char == ?/ ? :separator : :char
65
- element(type, char)
66
- end
67
-
68
- # @!visibility private
69
- def escaped(content = ?\\, char)
70
- element(:escaped, content) { element(:escaped_char, char) }
71
- end
72
-
73
- # @!visibility private
74
- def nested(type, opening, closing, *separators)
75
- element(type, opening) do
76
- char = nil
77
- until char == closing or scanner.eos?
78
- highlight(Regexp.union(closing, *separators))
79
- char = scanner.getch
80
- output << char if char
81
- end
82
- end
83
- end
84
-
85
- # @!visibility private
86
- def element(type, content = nil)
87
- output << renderer.pre(type)
88
- output << renderer.escape(content) if content
89
- yield if block_given?
90
- output << renderer.post(type)
91
- end
92
- end
93
- end
94
- end
95
- end
@@ -1,103 +0,0 @@
1
- # frozen_string_literal: true
2
- require 'mustermann/ast/translator'
3
-
4
- module Mustermann
5
- module Visualizer
6
- # @!visibility private
7
- module Highlighter
8
- # Provides highlighting for AST based patterns
9
- # @!visibility private
10
- class AST
11
- Index = Struct.new(:type, :start, :stop, :payload) { undef :to_a }
12
- Indexer = Mustermann::AST::Translator.create do
13
- translate(:node) { |i| Index.new(type, start, stop, Array(t(payload, i)).flatten.compact) }
14
- translate(Array) { |i| map { |e| t(e, i) } }
15
- translate(Object) { |i| }
16
-
17
- translate(:with_look_ahead) do |input|
18
- [t(head, input), *t(payload, input)]
19
- end
20
-
21
- translate(:expression) do |input|
22
- index = Index.new(type, start, stop, Array(t(payload, input)).compact)
23
- index.payload.delete_if { |e| e.type == :separator }
24
- index
25
- end
26
-
27
- translate(:capture) do |input|
28
- substring = input[start, length]
29
- if substart = substring.index(name)
30
- substart += start
31
- substop = substart + name.length
32
- payload = [Index.new(:name, substart, substop, [])]
33
- end
34
- Index.new(type, start, stop, payload || [])
35
- end
36
-
37
- translate(:char) do |input|
38
- substring = input[start, length]
39
- if payload == substring
40
- Index.new(type, start, stop, [])
41
- elsif substart = substring.index(payload)
42
- substart += start
43
- substop = substart + payload.length
44
- Index.new(:escaped, start, stop, [Index.new(:escaped_char, substart, substop, [])])
45
- else
46
- Index.new(:escaped, start, stop, [])
47
- end
48
- end
49
- end
50
-
51
- private_constant(:Index, :Indexer)
52
-
53
- # @!visibility private
54
- def self.highlight?(pattern)
55
- pattern.respond_to? :to_ast
56
- end
57
-
58
- # @!visibility private
59
- def self.highlight(pattern, renderer)
60
- new(pattern, renderer).highlight
61
- end
62
-
63
- # @!visibility private
64
- def initialize(pattern, renderer)
65
- @ast = pattern.to_ast
66
- @string = pattern.to_s
67
- @renderer = renderer
68
- end
69
-
70
- # @!visibility private
71
- def highlight
72
- index = Indexer.translate(@ast, @string)
73
- inject_literals(index)
74
- render(index)
75
- end
76
-
77
- # @!visibility private
78
- def render(index)
79
- return @renderer.escape(@string[index.start..index.stop-1]) if index.type == :literal
80
- payload = index.payload.map { |i| render(i) }.join
81
- "#{ @renderer.pre(index.type) }#{ payload }#{ @renderer.post(index.type) }"
82
- end
83
-
84
- # @!visibility private
85
- def inject_literals(index)
86
- start, old_payload, index.payload = index.start, index.payload, []
87
- old_payload.each do |element|
88
- index.payload << literal(start, element.start) if start < element.start
89
- index.payload << element
90
- inject_literals(element)
91
- start = element.stop
92
- end
93
- index.payload << literal(start, index.stop) if start < index.stop
94
- end
95
-
96
- # @!visibility private
97
- def literal(start, stop)
98
- Index.new(:literal, start, stop, [])
99
- end
100
- end
101
- end
102
- end
103
- end