defmastership 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +4 -0
- data/.rspec +4 -0
- data/.rubocop.yml +63 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +140 -0
- data/README.rdoc +6 -0
- data/Rakefile +53 -0
- data/bin/defmastership +99 -0
- data/config/devtools.yml +2 -0
- data/config/flay.yml +3 -0
- data/config/flog.yml +2 -0
- data/config/mutant.yml +6 -0
- data/config/reek.yml +106 -0
- data/config/rubocop.yml +44 -0
- data/config/yardstick.yml +2 -0
- data/defmastership.gemspec +37 -0
- data/defmastership.rdoc +5 -0
- data/features/changeref.feature +296 -0
- data/features/defmastership.feature +8 -0
- data/features/export.feature +275 -0
- data/features/step_definitions/defmastership_steps.rb +8 -0
- data/features/support/env.rb +18 -0
- data/lib/defmastership.rb +15 -0
- data/lib/defmastership/batch_changer.rb +40 -0
- data/lib/defmastership/comment_filter.rb +42 -0
- data/lib/defmastership/constants.rb +77 -0
- data/lib/defmastership/csv_formatter.rb +42 -0
- data/lib/defmastership/csv_formatter_body.rb +34 -0
- data/lib/defmastership/csv_formatter_header.rb +35 -0
- data/lib/defmastership/definition.rb +41 -0
- data/lib/defmastership/document.rb +153 -0
- data/lib/defmastership/project_ref_changer.rb +27 -0
- data/lib/defmastership/ref_changer.rb +102 -0
- data/lib/defmastership/version.rb +6 -0
- data/spec/spec_helper.rb +35 -0
- data/spec/unit/defmastership/batch_changer_spec.rb +108 -0
- data/spec/unit/defmastership/comment_filter_spec.rb +121 -0
- data/spec/unit/defmastership/csv_formatter_body_spec.rb +167 -0
- data/spec/unit/defmastership/csv_formatter_header_spec.rb +100 -0
- data/spec/unit/defmastership/csv_formatter_spec.rb +171 -0
- data/spec/unit/defmastership/definition_spec.rb +110 -0
- data/spec/unit/defmastership/document_spec.rb +398 -0
- data/spec/unit/defmastership/project_ref_changer_spec.rb +79 -0
- data/spec/unit/defmastership/ref_changer_spec.rb +205 -0
- data/spec/unit/defmastership_spec.rb +7 -0
- metadata +234 -0
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require('aruba/cucumber')
|
4
|
+
|
5
|
+
# ENV['PATH'] = "#{File.expand_path(File.dirname(__FILE__) + '/../../bin')}"\
|
6
|
+
# "#{File::PATH_SEPARATOR}#{ENV['PATH']}"
|
7
|
+
# LIB_DIR = File.join(__dir__, '..', '..', 'lib')
|
8
|
+
|
9
|
+
# Before do
|
10
|
+
# # Using "announce" causes massive warnings on 1.9.2
|
11
|
+
# @puts = true
|
12
|
+
# @original_rubylib = ENV['RUBYLIB']
|
13
|
+
# ENV['RUBYLIB'] = LIB_DIR + File::PATH_SEPARATOR + ENV['RUBYLIB'].to_s
|
14
|
+
# end
|
15
|
+
|
16
|
+
# After do
|
17
|
+
# ENV['RUBYLIB'] = @original_rubylib
|
18
|
+
# end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require('defmastership/version')
|
4
|
+
|
5
|
+
# Add requires for other files you add to your project here, so
|
6
|
+
# you just need to require this one file in your bin file
|
7
|
+
require('defmastership/constants')
|
8
|
+
require('defmastership/definition')
|
9
|
+
require('defmastership/document')
|
10
|
+
require('defmastership/comment_filter')
|
11
|
+
require('defmastership/csv_formatter')
|
12
|
+
|
13
|
+
require('defmastership/ref_changer')
|
14
|
+
require('defmastership/batch_changer')
|
15
|
+
require('defmastership/project_ref_changer')
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DefMastership
|
4
|
+
# Change references from temporary to definitive with multiple RefChangers
|
5
|
+
class BatchChanger
|
6
|
+
attr_reader :refchangers
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
@refchangers = {}
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.from_h(hash)
|
13
|
+
new.from_h(hash)
|
14
|
+
end
|
15
|
+
|
16
|
+
def from_h(hash)
|
17
|
+
@refchangers =
|
18
|
+
hash.transform_values do |value|
|
19
|
+
DefMastership::RefChanger.from_h(value)
|
20
|
+
end
|
21
|
+
self
|
22
|
+
end
|
23
|
+
|
24
|
+
def to_h
|
25
|
+
@refchangers.transform_values(&:to_h)
|
26
|
+
end
|
27
|
+
|
28
|
+
def replace(symb, line)
|
29
|
+
@refchangers.reduce(line) do |res_line, (_, refchanger)|
|
30
|
+
refchanger.public_send("replace_#{symb}".to_sym, res_line)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def changes
|
35
|
+
@refchangers.reduce([]) do |all_changes, (_, refchanger)|
|
36
|
+
all_changes + refchanger.changes
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Add a class to handled asciidoctor comments
|
4
|
+
module DefMastership
|
5
|
+
attr_reader :comment_filter
|
6
|
+
|
7
|
+
# Kind of proxy that Filters comments fome Asciidoctor document
|
8
|
+
class CommentFilter
|
9
|
+
def initialize
|
10
|
+
@in_multiline_comment = false
|
11
|
+
end
|
12
|
+
|
13
|
+
def accept?(line)
|
14
|
+
case line
|
15
|
+
when DMRegexp::SINGLE_LINE_COMMENT then false
|
16
|
+
when DMRegexp::MULTI_LINE_COMMENT_DELIM
|
17
|
+
@in_multiline_comment ^= true
|
18
|
+
false
|
19
|
+
else !@in_multiline_comment
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
@comment_filter = CommentFilter.new
|
25
|
+
|
26
|
+
def self.reset_comments
|
27
|
+
@comment_filter = CommentFilter.new
|
28
|
+
nil
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.comment_filter
|
32
|
+
@comment_filter
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# adding a method to string to figure out if a string is commented or
|
37
|
+
# not.
|
38
|
+
class String
|
39
|
+
def commented?
|
40
|
+
!DefMastership.comment_filter.accept?(self)
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DefMastership
|
4
|
+
# set of regexp of added asciidoctor constructions
|
5
|
+
module DMRegexp
|
6
|
+
SINGLE_LINE_COMMENT = %r{^//[^/]}.freeze
|
7
|
+
|
8
|
+
MULTI_LINE_COMMENT_DELIM = %r{^////\s*$}.freeze
|
9
|
+
|
10
|
+
DEF_BEFORE_REF = <<~'BEF'
|
11
|
+
^\s*
|
12
|
+
\[\s*define\s*,
|
13
|
+
\s*(?<type>[\w:_-]+)\s*,
|
14
|
+
\s*
|
15
|
+
BEF
|
16
|
+
|
17
|
+
DEF_AFTER_REF = <<~'AFT'
|
18
|
+
\s*
|
19
|
+
(,\s*\[\s*(?<labels>.*?)\s*\])?\s*\]
|
20
|
+
AFT
|
21
|
+
DEFINITION = Regexp.new(
|
22
|
+
"#{DEF_BEFORE_REF}(?<reference>[\\w:_-]+)#{DEF_AFTER_REF}",
|
23
|
+
Regexp::EXTENDED
|
24
|
+
)
|
25
|
+
|
26
|
+
VARIABLE_DEF = /^\s*:(?<varname>[\w:_-]+):\s*
|
27
|
+
\s*(?<value>\S.*\S)\s*$/x.freeze
|
28
|
+
|
29
|
+
VARIABLE_USE = /{(?<varname>[\w:_-]+)}/x.freeze
|
30
|
+
|
31
|
+
EREF_CONFIG = /^\s*:eref-(?<refname>[\w:_-]+)-(?<symb>prefix|url):\s*
|
32
|
+
\s*(?<value>\S.*\S)\s*/x.freeze
|
33
|
+
EREF_DEF = /^\s*
|
34
|
+
defs:eref\[
|
35
|
+
\s*(?<refname>[\w:_-]+)\s*,
|
36
|
+
\s*\[(?<extrefs>[^\]]+)\]\s*\]/x.freeze
|
37
|
+
BLOCK = /^--\s*$/.freeze
|
38
|
+
LITERAL_BLOCK = /^\.\.\.\.\s*$/.freeze
|
39
|
+
|
40
|
+
IREF_DEF_BEF = 'defs:iref\[\s*'
|
41
|
+
IREF_DEF_AFT = '\s*\]'
|
42
|
+
IREF_DEF = Regexp.new(
|
43
|
+
"#{IREF_DEF_BEF}(?<intref>[\\w:_-]+)#{IREF_DEF_AFT}",
|
44
|
+
Regexp::EXTENDED
|
45
|
+
)
|
46
|
+
|
47
|
+
ATTR_CONFIG = /\s*:attr-(?<attr>[\w:_-]+)-prefix:
|
48
|
+
\s+(?<prefix>.+?)\s*$/x.freeze
|
49
|
+
ATTR_SET = /\s*
|
50
|
+
defs:attribute\[
|
51
|
+
\s*(?<attr>[\w:_-]+)\s*,
|
52
|
+
\s*(?<value>.+?)\s*\]/x.freeze
|
53
|
+
|
54
|
+
EMPTY_LINE = /^\s*$/.freeze
|
55
|
+
|
56
|
+
WHATEVER = //.freeze
|
57
|
+
|
58
|
+
public_constant :SINGLE_LINE_COMMENT,
|
59
|
+
:MULTI_LINE_COMMENT_DELIM,
|
60
|
+
:DEF_BEFORE_REF,
|
61
|
+
:DEF_AFTER_REF,
|
62
|
+
:DEFINITION,
|
63
|
+
:VARIABLE_DEF,
|
64
|
+
:VARIABLE_USE,
|
65
|
+
:EREF_CONFIG,
|
66
|
+
:EREF_DEF,
|
67
|
+
:BLOCK,
|
68
|
+
:LITERAL_BLOCK,
|
69
|
+
:IREF_DEF_BEF,
|
70
|
+
:IREF_DEF_AFT,
|
71
|
+
:IREF_DEF,
|
72
|
+
:ATTR_CONFIG,
|
73
|
+
:ATTR_SET,
|
74
|
+
:EMPTY_LINE,
|
75
|
+
:WHATEVER
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require('csv')
|
4
|
+
require('defmastership/csv_formatter_header')
|
5
|
+
require('defmastership/csv_formatter_body')
|
6
|
+
|
7
|
+
module DefMastership
|
8
|
+
# to export a CSV file
|
9
|
+
class CSVFormatter
|
10
|
+
COLUMN_LIST = %w[fixed labels eref iref attributes].freeze
|
11
|
+
private_constant :COLUMN_LIST
|
12
|
+
|
13
|
+
def initialize(doc)
|
14
|
+
@doc = doc
|
15
|
+
@header_formatter = CSVFormatterHeader.new(@doc)
|
16
|
+
@body_formatter = CSVFormatterBody.new(@doc)
|
17
|
+
end
|
18
|
+
|
19
|
+
def export_to(output_file)
|
20
|
+
CSV.open(output_file, 'w:ISO-8859-1') do |csv|
|
21
|
+
csv << header
|
22
|
+
@doc.definitions.each { |definition| csv << body(definition) }
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def header
|
27
|
+
header_line =
|
28
|
+
COLUMN_LIST.map do |part|
|
29
|
+
@header_formatter.public_send("#{part}_header".to_sym)
|
30
|
+
end
|
31
|
+
header_line.reduce(:+)
|
32
|
+
end
|
33
|
+
|
34
|
+
def body(definition)
|
35
|
+
body_line =
|
36
|
+
COLUMN_LIST.map do |part|
|
37
|
+
@body_formatter.public_send("#{part}_body".to_sym, definition)
|
38
|
+
end
|
39
|
+
body_line.reduce(:+)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require('csv')
|
4
|
+
|
5
|
+
module DefMastership
|
6
|
+
# format lines per definition
|
7
|
+
class CSVFormatterBody
|
8
|
+
def initialize(doc)
|
9
|
+
@doc = doc
|
10
|
+
end
|
11
|
+
|
12
|
+
def fixed_body(definition)
|
13
|
+
[definition.type, definition.reference, definition.value]
|
14
|
+
end
|
15
|
+
|
16
|
+
def labels_body(definition)
|
17
|
+
@doc.labels.empty? ? [] : [definition.labels.to_a.join("\n")]
|
18
|
+
end
|
19
|
+
|
20
|
+
def eref_body(definition)
|
21
|
+
@doc.eref.map { |key, _| definition.eref[key].join("\n") }
|
22
|
+
end
|
23
|
+
|
24
|
+
def iref_body(definition)
|
25
|
+
@doc.iref ? [definition.iref.join("\n")] : []
|
26
|
+
end
|
27
|
+
|
28
|
+
def attributes_body(definition)
|
29
|
+
@doc.attributes.map do |key, _|
|
30
|
+
definition.attributes[key]
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require('csv')
|
4
|
+
|
5
|
+
module DefMastership
|
6
|
+
# format header for one document
|
7
|
+
class CSVFormatterHeader
|
8
|
+
def initialize(doc)
|
9
|
+
@doc = doc
|
10
|
+
end
|
11
|
+
|
12
|
+
def fixed_header
|
13
|
+
%w[Type Reference Value]
|
14
|
+
end
|
15
|
+
|
16
|
+
def labels_header
|
17
|
+
@doc.labels.empty? ? [] : %w[Labels]
|
18
|
+
end
|
19
|
+
|
20
|
+
def eref_header
|
21
|
+
@doc.eref.map do |_, ref|
|
22
|
+
ref[:prefix] +
|
23
|
+
(ref[:url].nil? || ref[:url] == 'none' ? '' : " #{ref[:url]}")
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def iref_header
|
28
|
+
@doc.iref ? ['Internal links'] : []
|
29
|
+
end
|
30
|
+
|
31
|
+
def attributes_header
|
32
|
+
@doc.attributes.map { |_, value| value }
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DefMastership
|
4
|
+
# DefMastership definition: contains all data of a definition
|
5
|
+
class Definition
|
6
|
+
attr_reader :type, :reference, :lines, :labels, :eref, :iref, :attributes
|
7
|
+
|
8
|
+
def initialize(match)
|
9
|
+
@type = match[:type]
|
10
|
+
@reference = match[:reference]
|
11
|
+
@lines = []
|
12
|
+
@labels = Set.new
|
13
|
+
labels = match[:labels]
|
14
|
+
@labels.merge(labels.split(/\s*,\s*/).to_set) if labels
|
15
|
+
@eref = Hash.new([])
|
16
|
+
@iref = []
|
17
|
+
@attributes = {}
|
18
|
+
end
|
19
|
+
|
20
|
+
def <<(new_line)
|
21
|
+
@lines << new_line
|
22
|
+
self
|
23
|
+
end
|
24
|
+
|
25
|
+
def value
|
26
|
+
@lines.join("\n")
|
27
|
+
end
|
28
|
+
|
29
|
+
def add_eref(refname, extrefs)
|
30
|
+
@eref[refname] = extrefs.strip.split(/\s*,\s*/)
|
31
|
+
end
|
32
|
+
|
33
|
+
def add_iref(ref)
|
34
|
+
@iref << ref
|
35
|
+
end
|
36
|
+
|
37
|
+
def set_attribute(key, value)
|
38
|
+
@attributes[key] = value
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,153 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require('aasm')
|
4
|
+
|
5
|
+
module DefMastership
|
6
|
+
# Contains the content of a DefMastership document: mainly definitions
|
7
|
+
# TODO: make this class smaller by defining a separated parser
|
8
|
+
|
9
|
+
# Contains regexp / action couples
|
10
|
+
Filter = Struct.new(:regexp, :event, :consumed_line)
|
11
|
+
private_constant :Filter
|
12
|
+
|
13
|
+
FILTERS_IN_LITERAL = [
|
14
|
+
Filter.new(DMRegexp::LITERAL_BLOCK, :code_block_delimiter, false),
|
15
|
+
Filter.new(DMRegexp::WHATEVER, :new_line, true)
|
16
|
+
].freeze
|
17
|
+
private_constant :FILTERS_IN_LITERAL
|
18
|
+
|
19
|
+
FILTERS = [
|
20
|
+
Filter.new(DMRegexp::VARIABLE_DEF, :new_variable_def, false),
|
21
|
+
Filter.new(DMRegexp::VARIABLE_USE, :new_variable_use, false),
|
22
|
+
Filter.new(DMRegexp::DEFINITION, :new_definition, true),
|
23
|
+
Filter.new(DMRegexp::EREF_CONFIG, :new_eref_setup, true),
|
24
|
+
Filter.new(DMRegexp::EREF_DEF, :new_eref_def, false),
|
25
|
+
Filter.new(DMRegexp::IREF_DEF, :new_iref_def, false),
|
26
|
+
Filter.new(DMRegexp::ATTR_CONFIG, :new_attribute_conf, true),
|
27
|
+
Filter.new(DMRegexp::ATTR_SET, :new_attribute_value, false),
|
28
|
+
Filter.new(DMRegexp::BLOCK, :block_delimiter, true),
|
29
|
+
Filter.new(DMRegexp::LITERAL_BLOCK, :code_block_delimiter, true),
|
30
|
+
Filter.new(DMRegexp::EMPTY_LINE, :empty_line, false),
|
31
|
+
Filter.new(DMRegexp::WHATEVER, :new_line, true)
|
32
|
+
].freeze
|
33
|
+
private_constant :FILTERS
|
34
|
+
|
35
|
+
# Reflects document structure from a definition point of view
|
36
|
+
class Document
|
37
|
+
include AASM
|
38
|
+
attr_reader :definitions, :labels, :eref, :iref, :attributes, :variables
|
39
|
+
|
40
|
+
def initialize
|
41
|
+
@definitions = []
|
42
|
+
@labels = Set.new
|
43
|
+
@eref = {}
|
44
|
+
@iref = false
|
45
|
+
@attributes = {}
|
46
|
+
@in_literal = true
|
47
|
+
@current_line = nil
|
48
|
+
@variables = {}
|
49
|
+
end
|
50
|
+
|
51
|
+
aasm do
|
52
|
+
state :idle, initial: true
|
53
|
+
state :wait_content
|
54
|
+
state :in_block
|
55
|
+
state :single_para
|
56
|
+
|
57
|
+
event :new_definition do
|
58
|
+
transitions from: :idle, to: :wait_content, after: :add_new_definition
|
59
|
+
end
|
60
|
+
|
61
|
+
event :block_delimiter do
|
62
|
+
transitions from: :wait_content, to: :in_block
|
63
|
+
transitions from: %i[in_block idle], to: :idle
|
64
|
+
transitions from: :single_para, to: :idle
|
65
|
+
end
|
66
|
+
|
67
|
+
event :new_line do
|
68
|
+
transitions from: :wait_content, to: :single_para, after: :add_line
|
69
|
+
transitions from: :single_para, to: :single_para, after: :add_line
|
70
|
+
transitions from: :in_block, to: :in_block, after: :add_line
|
71
|
+
transitions from: :idle, to: :idle
|
72
|
+
end
|
73
|
+
|
74
|
+
event :empty_line do
|
75
|
+
transitions from: %i[wait_content single_para idle], to: :idle
|
76
|
+
transitions from: :in_block, to: :in_block
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def code_block_delimiter(_match)
|
81
|
+
@in_literal ^= true
|
82
|
+
end
|
83
|
+
|
84
|
+
def add_new_definition(match)
|
85
|
+
definition = Definition.new(match)
|
86
|
+
@labels.merge(definition.labels)
|
87
|
+
@definitions << definition
|
88
|
+
end
|
89
|
+
|
90
|
+
def add_line(_match)
|
91
|
+
@definitions.last << @current_line
|
92
|
+
end
|
93
|
+
|
94
|
+
def new_eref_setup(match)
|
95
|
+
@eref[match[:refname].to_sym] ||= {}
|
96
|
+
|
97
|
+
@eref[match[:refname].to_sym][match[:symb].to_sym] =
|
98
|
+
match[:value]
|
99
|
+
end
|
100
|
+
|
101
|
+
def new_eref_def(match)
|
102
|
+
@definitions.last.add_eref(
|
103
|
+
match[:refname].to_sym,
|
104
|
+
match[:extrefs]
|
105
|
+
)
|
106
|
+
end
|
107
|
+
|
108
|
+
def new_iref_def(_match)
|
109
|
+
@iref = true
|
110
|
+
@current_line.scan(DMRegexp::IREF_DEF) do |_|
|
111
|
+
@definitions.last.add_iref(Regexp.last_match[:intref])
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def new_attribute_conf(match)
|
116
|
+
@attributes[match[:attr].to_sym] = match[:prefix]
|
117
|
+
end
|
118
|
+
|
119
|
+
def new_attribute_value(match)
|
120
|
+
@definitions.last.set_attribute(
|
121
|
+
match[:attr].to_sym,
|
122
|
+
match[:value]
|
123
|
+
)
|
124
|
+
end
|
125
|
+
|
126
|
+
def new_variable_def(match)
|
127
|
+
@variables[match[:varname].to_sym] = match[:value]
|
128
|
+
end
|
129
|
+
|
130
|
+
def new_variable_use(_match)
|
131
|
+
@current_line.scan(DMRegexp::VARIABLE_USE) do |_|
|
132
|
+
varname = Regexp.last_match[:varname]
|
133
|
+
next if @variables[varname.to_sym].nil?
|
134
|
+
|
135
|
+
@current_line = @current_line.gsub(
|
136
|
+
"{#{varname}}", @variables[varname.to_sym]
|
137
|
+
)
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
def parse(lines)
|
142
|
+
lines.reject(&:commented?).each do |line|
|
143
|
+
@current_line = line
|
144
|
+
(@in_literal ? FILTERS : FILTERS_IN_LITERAL).each do |filter|
|
145
|
+
next unless line.match(filter.regexp)
|
146
|
+
|
147
|
+
public_send(filter.event, Regexp.last_match)
|
148
|
+
break if filter.consumed_line
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|