defmastership 1.0.1 → 1.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/.gitlab-ci.yml +20 -0
- data/.rubocop.yml +5 -4
- data/Gemfile +1 -0
- data/LICENSE +22 -0
- data/Rakefile +2 -2
- data/bin/defmastership +25 -17
- data/cucumber.yml +2 -0
- data/defmastership.gemspec +18 -11
- data/features/changeref.feature +82 -129
- data/features/export.feature +102 -31
- data/features/modify.feature +143 -0
- data/features/rename_included_files.feature +121 -0
- data/features/step_definitions/defmastership_steps.rb +1 -0
- data/features/support/env.rb +1 -0
- data/lib/defmastership.rb +12 -3
- data/lib/defmastership/batch_modifier.rb +33 -0
- data/lib/defmastership/{ref_changer.rb → change_ref_line_modifier.rb} +19 -35
- data/lib/defmastership/change_ref_modifier.rb +15 -0
- data/lib/defmastership/comment_filter.rb +1 -0
- data/lib/defmastership/constants.rb +15 -1
- data/lib/defmastership/csv_formatter.rb +19 -18
- data/lib/defmastership/csv_formatter_body.rb +12 -6
- data/lib/defmastership/csv_formatter_header.rb +12 -10
- data/lib/defmastership/definition.rb +12 -0
- data/lib/defmastership/definition_parser.rb +46 -0
- data/lib/defmastership/document.rb +44 -75
- data/lib/defmastership/filters.rb +30 -0
- data/lib/defmastership/line_modifier_base.rb +29 -0
- data/lib/defmastership/modifier_base.rb +29 -0
- data/lib/defmastership/rename_included_files_line_modifier.rb +126 -0
- data/lib/defmastership/rename_included_files_modifier.rb +30 -0
- data/lib/defmastership/version.rb +2 -1
- data/spec/spec_helper.rb +2 -0
- data/spec/unit/defmastership/batch_modifier_spec.rb +115 -0
- data/spec/unit/defmastership/{ref_changer_spec.rb → change_ref_line_modifier_spec.rb} +49 -26
- data/spec/unit/defmastership/change_ref_modifier_spec.rb +76 -0
- data/spec/unit/defmastership/comment_filter_spec.rb +9 -4
- data/spec/unit/defmastership/csv_formatter_body_spec.rb +62 -37
- data/spec/unit/defmastership/csv_formatter_header_spec.rb +47 -22
- data/spec/unit/defmastership/csv_formatter_spec.rb +67 -105
- data/spec/unit/defmastership/definition_parser_spec.rb +63 -0
- data/spec/unit/defmastership/definition_spec.rb +31 -4
- data/spec/unit/defmastership/document_spec.rb +113 -35
- data/spec/unit/defmastership/rename_included_files_line_modifier_spec.rb +203 -0
- data/spec/unit/defmastership/rename_included_files_modifier_spec.rb +67 -0
- data/spec/unit/defmastership_spec.rb +1 -0
- metadata +44 -17
- data/Gemfile.lock +0 -140
- data/lib/defmastership/batch_changer.rb +0 -40
- data/lib/defmastership/project_ref_changer.rb +0 -27
- data/spec/unit/defmastership/batch_changer_spec.rb +0 -108
- data/spec/unit/defmastership/project_ref_changer_spec.rb +0 -79
@@ -1,40 +1,11 @@
|
|
1
|
+
# Copyright (c) 2020 Jerome Arbez-Gindre
|
1
2
|
# frozen_string_literal: true
|
2
3
|
|
3
|
-
require('aasm')
|
4
|
-
|
5
4
|
module DefMastership
|
6
5
|
# 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
6
|
|
35
7
|
# Reflects document structure from a definition point of view
|
36
8
|
class Document
|
37
|
-
include AASM
|
38
9
|
attr_reader :definitions, :labels, :eref, :iref, :attributes, :variables
|
39
10
|
|
40
11
|
def initialize
|
@@ -44,110 +15,108 @@ module DefMastership
|
|
44
15
|
@iref = false
|
45
16
|
@attributes = {}
|
46
17
|
@in_literal = true
|
47
|
-
@current_line = nil
|
48
18
|
@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
19
|
|
67
|
-
|
68
|
-
|
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
|
20
|
+
@definition_parser = DefinitionParser.new(self)
|
21
|
+
end
|
73
22
|
|
74
|
-
|
75
|
-
|
76
|
-
|
23
|
+
def wrong_explicit_checksum?
|
24
|
+
@definitions.reduce(false) do |res, definition|
|
25
|
+
res || !definition.wrong_explicit_checksum.nil?
|
77
26
|
end
|
78
27
|
end
|
79
28
|
|
80
|
-
def code_block_delimiter(_match)
|
29
|
+
def code_block_delimiter(_match, line)
|
81
30
|
@in_literal ^= true
|
31
|
+
line
|
82
32
|
end
|
83
33
|
|
84
|
-
def add_new_definition(match)
|
34
|
+
def add_new_definition(match, line)
|
85
35
|
definition = Definition.new(match)
|
86
36
|
@labels.merge(definition.labels)
|
87
37
|
@definitions << definition
|
38
|
+
line
|
88
39
|
end
|
89
40
|
|
90
|
-
def add_line(_match)
|
91
|
-
@definitions.last <<
|
41
|
+
def add_line(_match, line)
|
42
|
+
@definitions.last << line
|
43
|
+
line
|
92
44
|
end
|
93
45
|
|
94
|
-
def new_eref_setup(match)
|
46
|
+
def new_eref_setup(match, line)
|
95
47
|
@eref[match[:refname].to_sym] ||= {}
|
96
48
|
|
97
49
|
@eref[match[:refname].to_sym][match[:symb].to_sym] =
|
98
50
|
match[:value]
|
51
|
+
line
|
99
52
|
end
|
100
53
|
|
101
|
-
def new_eref_def(match)
|
54
|
+
def new_eref_def(match, line)
|
102
55
|
@definitions.last.add_eref(
|
103
56
|
match[:refname].to_sym,
|
104
57
|
match[:extrefs]
|
105
58
|
)
|
59
|
+
line
|
106
60
|
end
|
107
61
|
|
108
|
-
def new_iref_def(_match)
|
62
|
+
def new_iref_def(_match, line)
|
109
63
|
@iref = true
|
110
|
-
|
64
|
+
line.scan(DMRegexp::IREF_DEF) do |_|
|
111
65
|
@definitions.last.add_iref(Regexp.last_match[:intref])
|
112
66
|
end
|
67
|
+
line
|
113
68
|
end
|
114
69
|
|
115
|
-
def new_attribute_conf(match)
|
70
|
+
def new_attribute_conf(match, line)
|
116
71
|
@attributes[match[:attr].to_sym] = match[:prefix]
|
72
|
+
line
|
117
73
|
end
|
118
74
|
|
119
|
-
def new_attribute_value(match)
|
75
|
+
def new_attribute_value(match, line)
|
120
76
|
@definitions.last.set_attribute(
|
121
77
|
match[:attr].to_sym,
|
122
78
|
match[:value]
|
123
79
|
)
|
80
|
+
line
|
124
81
|
end
|
125
82
|
|
126
|
-
def new_variable_def(match)
|
83
|
+
def new_variable_def(match, line)
|
127
84
|
@variables[match[:varname].to_sym] = match[:value]
|
85
|
+
line
|
128
86
|
end
|
129
87
|
|
130
|
-
def new_variable_use(_match)
|
131
|
-
|
88
|
+
def new_variable_use(_match, line)
|
89
|
+
new_line = line.dup
|
90
|
+
line.scan(DMRegexp::VARIABLE_USE) do |_|
|
132
91
|
varname = Regexp.last_match[:varname]
|
133
92
|
next if @variables[varname.to_sym].nil?
|
134
93
|
|
135
|
-
|
136
|
-
"{#{varname}}", @variables[varname.to_sym]
|
137
|
-
)
|
94
|
+
new_line.gsub!("{#{varname}}", @variables[varname.to_sym])
|
138
95
|
end
|
96
|
+
new_line
|
139
97
|
end
|
140
98
|
|
141
99
|
def parse(lines)
|
142
100
|
lines.reject(&:commented?).each do |line|
|
143
|
-
@current_line = line
|
144
101
|
(@in_literal ? FILTERS : FILTERS_IN_LITERAL).each do |filter|
|
145
102
|
next unless line.match(filter.regexp)
|
146
103
|
|
147
|
-
|
104
|
+
line = generate_event(filter.event, Regexp.last_match, line)
|
105
|
+
|
148
106
|
break if filter.consumed_line
|
149
107
|
end
|
150
108
|
end
|
151
109
|
end
|
110
|
+
|
111
|
+
private
|
112
|
+
|
113
|
+
def generate_event(event, match, line)
|
114
|
+
if respond_to?(event)
|
115
|
+
line = public_send(event, match, line)
|
116
|
+
else
|
117
|
+
@definition_parser.public_send(event, match, line)
|
118
|
+
end
|
119
|
+
line
|
120
|
+
end
|
152
121
|
end
|
153
122
|
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# Copyright (c) 2020 Jerome Arbez-Gindre
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module DefMastership
|
5
|
+
# Contains regexp / action couples
|
6
|
+
Filter = Struct.new(:regexp, :event, :consumed_line)
|
7
|
+
private_constant :Filter
|
8
|
+
|
9
|
+
FILTERS_IN_LITERAL = [
|
10
|
+
Filter.new(DMRegexp::LITERAL_BLOCK, :code_block_delimiter, false),
|
11
|
+
Filter.new(DMRegexp::WHATEVER, :new_line, true)
|
12
|
+
].freeze
|
13
|
+
private_constant :FILTERS_IN_LITERAL
|
14
|
+
|
15
|
+
FILTERS = [
|
16
|
+
Filter.new(DMRegexp::VARIABLE_DEF, :new_variable_def, false),
|
17
|
+
Filter.new(DMRegexp::VARIABLE_USE, :new_variable_use, false),
|
18
|
+
Filter.new(DMRegexp::DEFINITION, :new_definition, true),
|
19
|
+
Filter.new(DMRegexp::EREF_CONFIG, :new_eref_setup, true),
|
20
|
+
Filter.new(DMRegexp::EREF_DEF, :new_eref_def, false),
|
21
|
+
Filter.new(DMRegexp::IREF_DEF, :new_iref_def, false),
|
22
|
+
Filter.new(DMRegexp::ATTR_CONFIG, :new_attribute_conf, true),
|
23
|
+
Filter.new(DMRegexp::ATTR_SET, :new_attribute_value, false),
|
24
|
+
Filter.new(DMRegexp::BLOCK, :block_delimiter, true),
|
25
|
+
Filter.new(DMRegexp::LITERAL_BLOCK, :code_block_delimiter, true),
|
26
|
+
Filter.new(DMRegexp::EMPTY_LINE, :empty_line, false),
|
27
|
+
Filter.new(DMRegexp::WHATEVER, :new_line, true)
|
28
|
+
].freeze
|
29
|
+
private_constant :FILTERS
|
30
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# Copyright (c) 2020 Jerome Arbez-Gindre
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module DefMastership
|
5
|
+
# Change references from temporary to definitive with multiple RefChangers
|
6
|
+
class LineModifierBase
|
7
|
+
attr_reader :changes, :config
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@config = {}
|
11
|
+
@changes = []
|
12
|
+
end
|
13
|
+
|
14
|
+
def method_missing(method_name, *args, &block)
|
15
|
+
return @config[method_name] if @config[method_name]
|
16
|
+
|
17
|
+
super
|
18
|
+
end
|
19
|
+
|
20
|
+
def respond_to_missing?(method_name, *args)
|
21
|
+
@config[method_name] || super
|
22
|
+
end
|
23
|
+
|
24
|
+
def from_config(config)
|
25
|
+
@config.merge!(config)
|
26
|
+
self
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# Copyright (c) 2020 Jerome Arbez-Gindre
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module DefMastership
|
5
|
+
# Change references from temporary to definitive with multiple RefChangers
|
6
|
+
class ModifierBase
|
7
|
+
attr_reader :config, :changes
|
8
|
+
|
9
|
+
def initialize(config)
|
10
|
+
@config = config
|
11
|
+
@changes = []
|
12
|
+
end
|
13
|
+
|
14
|
+
def do_modifications(adoc_texts)
|
15
|
+
line_modifier = line_modifier_class.from_config(@config)
|
16
|
+
|
17
|
+
adoc_texts =
|
18
|
+
replacements.reduce(adoc_texts) do |texts, method|
|
19
|
+
texts.transform_values do |text|
|
20
|
+
text.lines.map { |line| line_modifier.public_send(method, line) }.join
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
@config = line_modifier.config
|
25
|
+
@changes = line_modifier.changes
|
26
|
+
adoc_texts
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,126 @@
|
|
1
|
+
# Copyright (c) 2020 Jerome Arbez-Gindre
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module DefMastership
|
5
|
+
# Change included filenames on one line at a time
|
6
|
+
class RenameIncludedFilesLineModifier < LineModifierBase
|
7
|
+
LOCAL_FILTERS = [
|
8
|
+
Filter.new(DMRegexp::VARIABLE_DEF, :new_variable_def, false),
|
9
|
+
Filter.new(DMRegexp::DEFINITION, :new_definition, true),
|
10
|
+
Filter.new(DMRegexp::BLOCK, :block_delimiter, true),
|
11
|
+
Filter.new(DMRegexp::EMPTY_LINE, :empty_line, false),
|
12
|
+
Filter.new(DMRegexp::WHATEVER, :new_line, true)
|
13
|
+
].freeze
|
14
|
+
private_constant :LOCAL_FILTERS
|
15
|
+
|
16
|
+
def self.from_config(config)
|
17
|
+
new.from_config(config)
|
18
|
+
end
|
19
|
+
|
20
|
+
def initialize
|
21
|
+
super
|
22
|
+
@config = {
|
23
|
+
from_regexp: '',
|
24
|
+
to_template: ''
|
25
|
+
}
|
26
|
+
@variables = {}
|
27
|
+
@definition_parser = DefinitionParser.new(self)
|
28
|
+
end
|
29
|
+
|
30
|
+
def replace(line)
|
31
|
+
match = matched?(line)
|
32
|
+
|
33
|
+
return line unless match
|
34
|
+
|
35
|
+
new_line =
|
36
|
+
line.gsub(complete_regexp_from(from_regexp)) do
|
37
|
+
text_with(match, to_template % hmerge(match))
|
38
|
+
end
|
39
|
+
|
40
|
+
rename_file(line, new_line)
|
41
|
+
|
42
|
+
new_line
|
43
|
+
end
|
44
|
+
|
45
|
+
def add_new_definition(match, _line)
|
46
|
+
@config[:reference] = match[:reference]
|
47
|
+
end
|
48
|
+
|
49
|
+
def add_line(_match, _line) end
|
50
|
+
|
51
|
+
def new_variable_def(match, line)
|
52
|
+
@variables[match[:varname].to_sym] = match[:value]
|
53
|
+
line
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
def matched?(line)
|
59
|
+
return if line.commented?
|
60
|
+
|
61
|
+
parse(line)
|
62
|
+
|
63
|
+
return if @definition_parser.idle?
|
64
|
+
return unless line =~ complete_regexp_from(from_regexp)
|
65
|
+
|
66
|
+
match = Regexp.last_match
|
67
|
+
|
68
|
+
return if @config[:cancel_if_match] && match[:filename] =~ Regexp.new(cancel_if_match)
|
69
|
+
|
70
|
+
match
|
71
|
+
end
|
72
|
+
|
73
|
+
def parse(line)
|
74
|
+
LOCAL_FILTERS.each do |filter|
|
75
|
+
next unless line.match(filter.regexp)
|
76
|
+
|
77
|
+
line = generate_event(filter.event, Regexp.last_match, line)
|
78
|
+
|
79
|
+
break if filter.consumed_line
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def rename_file(from, to)
|
84
|
+
@changes << [extract_filename(from), extract_filename(to)]
|
85
|
+
File.rename(extract_filename(from), extract_filename(to))
|
86
|
+
end
|
87
|
+
|
88
|
+
def extract_filename(include_statement)
|
89
|
+
filename = include_statement
|
90
|
+
.gsub(Regexp.new(DMRegexp::INCLUDE_KEYWORD), '')
|
91
|
+
.gsub(Regexp.new(DMRegexp::INCLUDE_OPTIONS), '')
|
92
|
+
|
93
|
+
filename.dup.scan(DMRegexp::VARIABLE_USE) do |_|
|
94
|
+
varname = Regexp.last_match[:varname]
|
95
|
+
next if @variables[varname.to_sym].nil?
|
96
|
+
|
97
|
+
filename.gsub!("{#{varname}}", @variables[varname.to_sym])
|
98
|
+
end
|
99
|
+
filename
|
100
|
+
end
|
101
|
+
|
102
|
+
def complete_regexp_from(from)
|
103
|
+
Regexp.new(
|
104
|
+
DMRegexp::INCLUDE_KEYWORD + DMRegexp::INCLUDE_PATH +
|
105
|
+
"(?<filename>#{from})" + DMRegexp::INCLUDE_OPTIONS
|
106
|
+
)
|
107
|
+
end
|
108
|
+
|
109
|
+
def text_with(match, to)
|
110
|
+
"include::#{match[:path] || ''}#{to}[#{match[:options]}]"
|
111
|
+
end
|
112
|
+
|
113
|
+
def hmerge(match)
|
114
|
+
@config.merge(match.names.map(&:to_sym).zip(match.captures).to_h)
|
115
|
+
end
|
116
|
+
|
117
|
+
def generate_event(event, match, line)
|
118
|
+
if respond_to?(event)
|
119
|
+
public_send(event, match, line)
|
120
|
+
else
|
121
|
+
@definition_parser.public_send(event, match, line)
|
122
|
+
end
|
123
|
+
line
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# Copyright (c) 2020 Jerome Arbez-Gindre
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module DefMastership
|
5
|
+
# Change included filenames
|
6
|
+
class RenameIncludedFilesModifier < ModifierBase
|
7
|
+
def do_modifications(adoc_texts)
|
8
|
+
line_modifier = line_modifier_class.from_config(@config)
|
9
|
+
|
10
|
+
adoc_texts =
|
11
|
+
replacements.reduce(adoc_texts) do |texts, method|
|
12
|
+
texts.transform_values do |text|
|
13
|
+
text.lines.map { |line| line_modifier.public_send(method, line) }.join
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
@config = line_modifier.config
|
18
|
+
@changes = line_modifier.changes
|
19
|
+
adoc_texts
|
20
|
+
end
|
21
|
+
|
22
|
+
def replacements
|
23
|
+
%i[replace]
|
24
|
+
end
|
25
|
+
|
26
|
+
def line_modifier_class
|
27
|
+
RenameIncludedFilesLineModifier
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|