defmastership 1.0.18 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (89) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +4 -0
  3. data/.gitlab-ci.yml +42 -1
  4. data/Gemfile +49 -18
  5. data/Guardfile +44 -0
  6. data/LICENSE +1 -1
  7. data/README.adoc +24 -0
  8. data/Rakefile +0 -1
  9. data/bin/defmastership +5 -5
  10. data/config/cucumber.yml +3 -0
  11. data/config/mutant.yml +22 -16
  12. data/config/reek.yml +129 -105
  13. data/config/rubocop.yml +67 -28
  14. data/defmastership.gemspec +8 -6
  15. data/features/changeref.feature +0 -8
  16. data/features/definition_checksum.feature +0 -10
  17. data/features/definition_version.feature +168 -10
  18. data/features/export.feature +23 -18
  19. data/features/modify.feature +1 -5
  20. data/features/rename_included_files.feature +0 -5
  21. data/features/step_definitions/git_steps.rb +19 -0
  22. data/lib/defmastership/batch_modifier.rb +23 -5
  23. data/lib/defmastership/comment_filter.rb +2 -1
  24. data/lib/defmastership/definition.rb +26 -6
  25. data/lib/defmastership/definition_parser.rb +2 -2
  26. data/lib/defmastership/document.rb +45 -33
  27. data/lib/defmastership/export/body_formatter.rb +55 -0
  28. data/lib/defmastership/export/csv/formatter.rb +64 -0
  29. data/lib/defmastership/export/header_formatter.rb +51 -0
  30. data/lib/defmastership/filters.rb +15 -12
  31. data/lib/defmastership/matching_line.rb +3 -2
  32. data/lib/defmastership/modifier/change_ref.rb +117 -0
  33. data/lib/defmastership/modifier/factory.rb +17 -0
  34. data/lib/defmastership/modifier/modifier_common.rb +71 -0
  35. data/lib/defmastership/modifier/rename_included_files.rb +223 -0
  36. data/lib/defmastership/modifier/update_def.rb +72 -0
  37. data/lib/defmastership/modifier/update_def_checksum.rb +17 -0
  38. data/lib/defmastership/modifier/update_def_version.rb +110 -0
  39. data/lib/defmastership/set_join_hack.rb +2 -0
  40. data/lib/defmastership/version.rb +3 -2
  41. data/lib/defmastership.rb +6 -8
  42. data/spec/unit/{def_mastership → defmastership}/batch_modifier_spec.rb +15 -13
  43. data/spec/unit/{def_mastership → defmastership}/definition_parser_spec.rb +1 -1
  44. data/spec/unit/{def_mastership → defmastership}/definition_spec.rb +1 -1
  45. data/spec/unit/{def_mastership → defmastership}/document_spec.rb +57 -57
  46. data/spec/unit/{def_mastership/csv_formatter_body_spec.rb → defmastership/export/body_formatter_spec.rb} +4 -4
  47. data/spec/unit/{def_mastership/csv_formatter_spec.rb → defmastership/export/csv/formatter_spec.rb} +13 -8
  48. data/spec/unit/{def_mastership/csv_formatter_header_spec.rb → defmastership/export/header_formatter_spec.rb} +3 -3
  49. data/spec/unit/{def_mastership → defmastership}/matching_line_spec.rb +1 -1
  50. data/spec/unit/{def_mastership/change_ref_modifier_spec.rb → defmastership/modifier/change_ref_spec.rb} +19 -44
  51. data/spec/unit/defmastership/modifier/factory_spec.rb +45 -0
  52. data/spec/unit/{def_mastership/modifier_spec.rb → defmastership/modifier/modifier_common_spec.rb} +11 -18
  53. data/spec/unit/{def_mastership/rename_included_files_modifier_spec.rb → defmastership/modifier/rename_included_files_spec.rb} +3 -3
  54. data/spec/unit/{def_mastership/update_def_checksum_modifier_spec.rb → defmastership/modifier/update_def_checksum_spec.rb} +10 -10
  55. data/spec/unit/{def_mastership/update_def_modifier_spec.rb → defmastership/modifier/update_def_spec.rb} +22 -18
  56. data/spec/unit/defmastership/modifier/update_def_version_spec.rb +351 -0
  57. data/spec/unit/{def_mastership_spec.rb → defmastership_spec.rb} +2 -2
  58. data/tasks/code_quality.rake +74 -0
  59. data/tasks/documentation.rake +19 -0
  60. data/tasks/package.rake +4 -0
  61. data/tasks/test.rake +6 -21
  62. metadata +96 -51
  63. data/.rubocop.yml +0 -76
  64. data/README.rdoc +0 -6
  65. data/config/devtools.yml +0 -2
  66. data/config/flay.yml +0 -3
  67. data/config/flog.yml +0 -2
  68. data/config/yardstick.yml +0 -2
  69. data/cucumber.yml +0 -2
  70. data/defmastership.rdoc +0 -5
  71. data/lib/defmastership/change_ref_modifier.rb +0 -99
  72. data/lib/defmastership/constants.rb +0 -89
  73. data/lib/defmastership/csv_formatter.rb +0 -53
  74. data/lib/defmastership/csv_formatter_body.rb +0 -46
  75. data/lib/defmastership/csv_formatter_header.rb +0 -41
  76. data/lib/defmastership/modifier.rb +0 -42
  77. data/lib/defmastership/modifier_factory.rb +0 -12
  78. data/lib/defmastership/parsing_state.rb +0 -31
  79. data/lib/defmastership/rename_included_files_modifier.rb +0 -182
  80. data/lib/defmastership/update_def_checksum_modifier.rb +0 -16
  81. data/lib/defmastership/update_def_modifier.rb +0 -49
  82. data/lib/defmastership/update_def_version_modifier.rb +0 -66
  83. data/spec/unit/def_mastership/modifier_factory_spec.rb +0 -37
  84. data/spec/unit/def_mastership/parsing_state_spec.rb +0 -62
  85. data/spec/unit/def_mastership/update_def_version_modifier_spec.rb +0 -159
  86. data/tasks/package.task +0 -9
  87. data/tasks/smelling_code.rake +0 -38
  88. /data/{.rspec → config/rspec} +0 -0
  89. /data/spec/unit/{def_mastership → defmastership}/string_spec.rb +0 -0
@@ -23,7 +23,6 @@ Feature: The rename_included_files command
23
23
  And an empty file named "any_path/one_file.png"
24
24
  When I successfully run `defmastership modify --modifications rename_included_png thedoc.adoc`
25
25
  Then the stdout should not contain anything
26
- And the stderr should not contain anything
27
26
  And the file "thedoc.adoc" should contain:
28
27
  """
29
28
  include::any_path/one_file.png[]
@@ -49,7 +48,6 @@ Feature: The rename_included_files command
49
48
  And an empty file named "any_path/one_file.png"
50
49
  When I successfully run `defmastership modify --modifications rename_included_png thedoc.adoc`
51
50
  Then the stdout should not contain anything
52
- And the stderr should not contain anything
53
51
  And the file "thedoc.adoc" should contain:
54
52
  """
55
53
  [define, requirement, TOTO-WHATEVER-123]
@@ -77,7 +75,6 @@ Feature: The rename_included_files command
77
75
  And an empty file named "any_path/one_file.png"
78
76
  When I successfully run `defmastership modify --modifications rename_included_png thedoc.adoc`
79
77
  Then the stdout should not contain anything
80
- And the stderr should not contain anything
81
78
  And the file "thedoc.adoc" should contain:
82
79
  """
83
80
  [define, requirement, TOTO-WHATEVER-123]
@@ -109,7 +106,6 @@ Feature: The rename_included_files command
109
106
  And an empty file named "one_two/one_file.png"
110
107
  When I successfully run `defmastership modify --modifications rename_included_png thedoc.adoc`
111
108
  Then the stdout should not contain anything
112
- And the stderr should not contain anything
113
109
  And the file "thedoc.adoc" should contain:
114
110
  """
115
111
  :any: one
@@ -142,7 +138,6 @@ Feature: The rename_included_files command
142
138
  And an empty file named "any_path/TOTO-WHATEVER-123_one_file.png"
143
139
  When I successfully run `defmastership modify --modifications rename_included_png thedoc.adoc`
144
140
  Then the stdout should not contain anything
145
- And the stderr should not contain anything
146
141
  And the file "thedoc.adoc" should contain:
147
142
  """
148
143
  [define, requirement, TOTO-WHATEVER-123]
@@ -0,0 +1,19 @@
1
+ # Copyright (c) 2024 Jerome Arbez-Gindre
2
+ # frozen_string_literal: true
3
+
4
+ require 'git'
5
+
6
+ Given('I initialize a git repo') do
7
+ Git.init(Aruba.config.home_directory)
8
+ end
9
+
10
+ Given('I add and commit the {string} file') do |filename|
11
+ git = Git.open(Aruba.config.home_directory)
12
+ git.add(filename)
13
+ git.commit('whatever')
14
+ end
15
+
16
+ Given('I set the {string} tag') do |tag_name|
17
+ git = Git.open(Aruba.config.home_directory)
18
+ git.add_tag(tag_name)
19
+ end
@@ -1,17 +1,35 @@
1
1
  # Copyright (c) 2020 Jerome Arbez-Gindre
2
2
  # frozen_string_literal: true
3
3
 
4
- module DefMastership
5
- # Change references from temporary to definitive with multiple RefChangers
4
+ module Defmastership
5
+ # Apply modications on a list of related asciidoc sources
6
6
  class BatchModifier
7
- attr_reader :config, :adoc_sources, :changes
8
-
7
+ # Stores the overall invocation configuration
8
+ # @return [YAML] configuration as eventualy modified by modifiers
9
+ attr_reader :config
10
+ # Stores the list of asciidoc files to modify and to save
11
+ # @return [Hash{String => String}] asciidoc sources as modified by modifiers
12
+ # * :key filename
13
+ # * :value file content
14
+ attr_reader :adoc_sources
15
+ # Provides the list of performed modifications
16
+ # @return [Array<Array<String>>] List of performed modifications
17
+ # (each line: [Modifier, Was, Becomes])
18
+ attr_reader :changes
19
+
20
+ # @param config [YAML] the overall modifications configurations
21
+ # @param adoc_sources [Hash{String => String}] asciidoctor files to be modified
22
+ # * Key: filename
23
+ # * Value: file content
9
24
  def initialize(config, adoc_sources)
10
25
  @config = config
11
26
  @adoc_sources = adoc_sources
12
27
  @changes = []
13
28
  end
14
29
 
30
+ # Apply modications on asciidoc sources of @adoc_sources
31
+ #
32
+ # @param modifs [Array<String>] The modifications to apply
15
33
  def apply(modifs)
16
34
  modifs.each do |modif|
17
35
  modifier = modifier_from(modif)
@@ -28,7 +46,7 @@ module DefMastership
28
46
  config_modif_sym = config[modif]
29
47
  raise(ArgumentError, "#{modif} is not a known modification") unless config_modif_sym
30
48
 
31
- ModifierFactory.from_config(config_modif_sym)
49
+ Modifier::Factory.from_config(config_modif_sym)
32
50
  end
33
51
 
34
52
  def collect_changes(modifier, modif)
@@ -4,7 +4,8 @@
4
4
  # adding a method to string to figure out if a string is commented or
5
5
  # not.
6
6
  class String
7
+ # @return [Boolean] true if the line is commented
7
8
  def commented?
8
- !!match(DefMastership::DMRegexp::SINGLE_LINE_COMMENT)
9
+ !!match(Defmastership::Core::DMRegexp::SINGLE_LINE_COMMENT)
9
10
  end
10
11
  end
@@ -3,8 +3,8 @@
3
3
 
4
4
  require 'digest'
5
5
 
6
- # Contains the content of a DefMastership definition
7
- module DefMastership
6
+ # Contains the content of a Defmastership definition
7
+ module Defmastership
8
8
  BUILD_FROM_MATCH = {
9
9
  type: ->(match) { match[:type] },
10
10
  reference: ->(match) { match[:reference] },
@@ -38,7 +38,7 @@ module DefMastership
38
38
 
39
39
  private_constant :DefinitionData
40
40
 
41
- # DefMastership definition: contains all data of a definition
41
+ # Defmastership definition: contains all data of a definition
42
42
  class Definition
43
43
  extend Forwardable
44
44
  def_delegators :@data,
@@ -52,6 +52,7 @@ module DefMastership
52
52
  :explicit_checksum,
53
53
  :explicit_version
54
54
 
55
+ # @param match [MatchData] the definition data from regepx match
55
56
  def initialize(match)
56
57
  @data = DefinitionData.new(
57
58
  *BUILD_FROM_MATCH.transform_values { |lamb| lamb.call(match) }
@@ -59,34 +60,53 @@ module DefMastership
59
60
  )
60
61
  end
61
62
 
63
+ # Add a line to the definition's value
64
+ #
65
+ # @param new_line [String] the new line
66
+ # @return [Definition] the definition itself
62
67
  def <<(new_line)
63
68
  lines << new_line
64
69
  self
65
70
  end
66
71
 
72
+ # Add a line to the definition's value
73
+ #
74
+ # @return [String] the complete value of the definition
67
75
  def value
68
76
  lines.join("\n")
69
77
  end
70
78
 
79
+ # @return [String] short representation (8 last characters) of the sha256 of the definition's value
71
80
  def sha256_short
72
81
  "~#{Digest::SHA2.hexdigest(value).chars.last(8).join}"
73
82
  end
74
83
 
84
+ # @return [String] the explicit checsum if wrong or nil
75
85
  def wrong_explicit_checksum
76
86
  explicit_checksum unless explicit_checksum.eql?(sha256_short)
77
87
  end
78
88
 
79
- def add_eref(refname, extrefs)
80
- eref[refname] = extrefs.strip.split(/\s*,\s*/)
89
+ # Set an external ref list for a given reference type
90
+ #
91
+ # @param ref [String] the type of cross reference
92
+ # @param extrefs [String] the comma separated external references
93
+ def add_eref(ref, extrefs)
94
+ eref[ref] = extrefs.strip.split(/\s*,\s*/)
81
95
  end
82
96
 
97
+ # Set an internal ref
98
+ #
99
+ # @param ref [String] the internal reference
83
100
  def add_iref(ref)
84
101
  iref << ref
85
102
  end
86
103
 
104
+ # Set an attribute for a given key
105
+ #
106
+ # @param key [String] the attribute's key
107
+ # @param value [String] the attribute's value
87
108
  def set_attribute(key, value)
88
109
  attributes[key] = value
89
110
  end
90
111
  end
91
- public_constant :Definition
92
112
  end
@@ -3,8 +3,8 @@
3
3
 
4
4
  require('aasm')
5
5
 
6
- module DefMastership
7
- # DefMastership definition: contains all data of a definition
6
+ module Defmastership
7
+ # Defmastership definition: contains all data of a definition
8
8
  class DefinitionParser
9
9
  include AASM
10
10
 
@@ -2,10 +2,12 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require('asciidoctor')
5
+ require('defmastership/core/constants')
6
+ require('defmastership/core/parsing_state')
5
7
  require('defmastership/matching_line')
6
8
 
7
- # Contains the content of a DefMastership document: mainly definitions
8
- module DefMastership
9
+ # Contains the content of a Defmastership document: mainly definitions
10
+ module Defmastership
9
11
  # Class to host data of Document class
10
12
  DocumentData = Struct.new(
11
13
  :definitions,
@@ -23,46 +25,38 @@ module DefMastership
23
25
  definition = Definition.new(matching_line.match)
24
26
  labels.merge(definition.labels)
25
27
  definitions << definition
26
- matching_line.line
27
28
  },
28
29
  add_line: lambda { |matching_line|
29
30
  line = matching_line.line
30
31
  definitions.last << line
31
- line
32
32
  },
33
33
  new_eref_setup: lambda { |matching_line|
34
- refname = matching_line[:refname].to_sym
35
- eref[refname] ||= {}
36
- eref[refname][matching_line[:symb].to_sym] = matching_line[:value]
37
- matching_line.line
34
+ reference = matching_line[:reference].to_sym
35
+ eref[reference] ||= {}
36
+ eref[reference][matching_line[:symb].to_sym] = matching_line[:value]
38
37
  },
39
38
  new_eref_def: lambda { |matching_line|
40
- definitions.last.add_eref(matching_line[:refname].to_sym, matching_line[:extrefs])
41
- matching_line.line
39
+ definitions.last.add_eref(matching_line[:reference].to_sym, matching_line[:extrefs])
42
40
  },
43
41
  new_iref_def: lambda { |matching_line|
44
- self.iref = true
42
+ self.has_iref = true
45
43
  line = matching_line.line
46
- line.scan(DMRegexp::IREF_DEF) do |_|
44
+ line.scan(Core::DMRegexp::IREF_DEF) do |_|
47
45
  definitions.last.add_iref(Regexp.last_match[:intref])
48
46
  end
49
- line
50
47
  },
51
48
  new_attribute_conf: lambda { |matching_line|
52
49
  attributes[matching_line[:attr].to_sym] = matching_line[:prefix]
53
- matching_line.line
54
50
  },
55
51
  new_attribute_value: lambda { |matching_line|
56
52
  definitions.last.set_attribute(matching_line[:attr].to_sym, matching_line[:value])
57
- matching_line.line
58
53
  },
59
54
  new_variable_def: lambda { |matching_line|
60
55
  variables[matching_line[:varname].to_sym] = matching_line[:value]
61
- matching_line.line
62
56
  },
63
57
  new_variable_use: lambda { |matching_line|
64
58
  line = matching_line.line
65
- line.scan(DMRegexp::VARIABLE_USE) do |_|
59
+ line.scan(Core::DMRegexp::VARIABLE_USE) do |_|
66
60
  varname = Regexp.last_match[:varname]
67
61
  value = variables[varname.to_sym]
68
62
 
@@ -83,36 +77,35 @@ module DefMastership
83
77
 
84
78
  def initialize
85
79
  @data = DocumentData.new([], Set.new, {}, false, {}, {})
86
- @parsing_state = ParsingState.new
80
+ @parsing_state = Core::ParsingState.new
87
81
  @definition_parser = DefinitionParser.new(self)
88
82
  end
89
83
 
90
- def parse(lines)
91
- lines.each do |line|
92
- if @parsing_state.enabled?(line)
93
- apply_filters(line)
94
- else
95
- generate_event(:new_line, MatchingLine.new(nil, line))
96
- end
97
- end
98
- end
99
-
84
+ # Parse asciidoc file after [Asciidoctor] preprocessing
85
+ #
86
+ # @param adoc_file [String] the file to parse
100
87
  def parse_file_with_preprocessor(adoc_file)
101
- parse(Asciidoctor.load_file(adoc_file, safe: :unsafe, parse: false).reader.read_lines)
88
+ do_parse(Asciidoctor.load_file(adoc_file, safe: :unsafe, parse: false).reader.read_lines)
102
89
  end
103
90
 
91
+ # @return [Boolean] true if the document has definitions with wrong explicit checksum
104
92
  def wrong_explicit_checksum?
105
93
  definitions.reduce(false) do |res, definition|
106
94
  res || !!definition.wrong_explicit_checksum
107
95
  end
108
96
  end
109
97
 
98
+ # @return [Boolean] true if the document has definitions with explicit versions
110
99
  def explicit_version?
111
100
  definitions.reduce(false) do |res, definition|
112
101
  res || !!definition.explicit_version
113
102
  end
114
103
  end
115
104
 
105
+ # Allow to add methods from parser actions
106
+ #
107
+ # @param method_name [Symbol] the name of the method
108
+ # @param args[Array<Object>] the arguments of the method
116
109
  def method_missing(method_name, *args)
117
110
  action = PARSER_ACTIONS[method_name]
118
111
  return instance_exec(*args, &action) if action
@@ -120,20 +113,36 @@ module DefMastership
120
113
  super
121
114
  end
122
115
 
116
+ # Allow to check if a parser action is available
117
+ #
118
+ # @param method_name [Symbol] the name of the method
119
+ # @param _args[Array<Object>] the arguments of the method
123
120
  # This method smells of :reek:UtilityFunction
124
121
  def respond_to_missing?(method_name, *_args)
125
122
  PARSER_ACTIONS.key?(method_name)
126
123
  end
127
124
 
128
- def ref_to_def(ref)
129
- definitions.find { |definition| definition.reference == ref }
125
+ # @param reference [String] the defintion from the reference
126
+ # @return [Definition] the defintion from the reference
127
+ def ref_to_def(reference)
128
+ definitions.find { |definition| definition.reference == reference }
130
129
  end
131
130
 
132
- def iref=(value)
131
+ private
132
+
133
+ def has_iref=(value)
133
134
  @data.iref = value
134
135
  end
135
136
 
136
- private
137
+ def do_parse(lines)
138
+ lines.each do |line|
139
+ if @parsing_state.enabled?(line)
140
+ apply_filters(line)
141
+ else
142
+ generate_event(:new_line, MatchingLine.new(nil, line))
143
+ end
144
+ end
145
+ end
137
146
 
138
147
  def apply_filters(line)
139
148
  Helper.reduce_filters_until_consumed(line) do |event, match, updated_line|
@@ -151,6 +160,9 @@ module DefMastership
151
160
 
152
161
  # Helper functions
153
162
  module Helper
163
+ # Helper function: apply all filters
164
+ #
165
+ # @param line [String] the line
154
166
  def self.reduce_filters_until_consumed(line)
155
167
  FILTERS.reduce(line) do |res, filter|
156
168
  next res unless line.match(filter.regexp)
@@ -0,0 +1,55 @@
1
+ # Copyright (c) 2020 Jerome Arbez-Gindre
2
+ # frozen_string_literal: true
3
+
4
+ require('defmastership/set_join_hack')
5
+
6
+ module Defmastership
7
+ module Export
8
+ # format CSV lines per definition
9
+ class BodyFormatter
10
+ # @param doc [Document] the document to export
11
+ # @param definition [String] the definition to export
12
+ def initialize(doc, definition)
13
+ @doc = doc
14
+ @definition = definition
15
+ end
16
+
17
+ # @return [Array<String>] list of always available columns values
18
+ def fixed
19
+ [@definition.type, @definition.reference, @definition.value, @definition.sha256_short]
20
+ end
21
+
22
+ # @return [Array<String>] Optional wrong_explicit_checksum column value
23
+ def wrong_explicit_checksum
24
+ wrong_explicit_checksum = @definition.wrong_explicit_checksum
25
+ wrong_explicit_checksum ? [wrong_explicit_checksum] : ['']
26
+ end
27
+
28
+ # @return [Array<String>] Optional version column value
29
+ def explicit_version
30
+ explicit_version = @definition.explicit_version
31
+ explicit_version ? [explicit_version] : ['']
32
+ end
33
+
34
+ # @return [Array<String>] Optional labels columns values
35
+ def labels
36
+ [@definition.labels.join("\n")]
37
+ end
38
+
39
+ # @return [Array<String>] Optional external refs columns values
40
+ def eref
41
+ @doc.eref.map { |key,| @definition.eref.fetch(key, []).join("\n") }
42
+ end
43
+
44
+ # @return [Array<String>] Optional internal refs column value
45
+ def iref
46
+ [@definition.iref.join("\n")]
47
+ end
48
+
49
+ # @return [Array<String>] Optional attributes columns values
50
+ def attributes
51
+ @doc.attributes.map { |key,| @definition.attributes.fetch(key, '') }
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,64 @@
1
+ # Copyright (c) 2020 Jerome Arbez-Gindre
2
+ # frozen_string_literal: true
3
+
4
+ require('csv')
5
+ require('defmastership/export/body_formatter')
6
+ require('defmastership/export/header_formatter')
7
+
8
+ module Defmastership
9
+ # Module to host export classes
10
+ module Export
11
+ # Module to host CSV export classes
12
+ module CSV
13
+ # to export a CSV file
14
+ class Formatter
15
+ # @param doc [Document] the document to export
16
+ # @param sep [String] the CSV separator
17
+ def initialize(doc, sep)
18
+ @doc = doc
19
+ @sep = sep
20
+ end
21
+
22
+ # Export the document to a CSV file
23
+ #
24
+ # @param output_file [Strinf] filename for the export
25
+ def export_to(output_file)
26
+ column_list = build_column_list
27
+ ::CSV.open(output_file, 'w:ISO-8859-1', col_sep: @sep) do |csv|
28
+ csv << header(column_list)
29
+ export_definitions_in(csv, column_list)
30
+ end
31
+ end
32
+
33
+ private
34
+
35
+ def export_definitions_in(csv, column_list)
36
+ @doc.definitions.each { |definition| csv << body(definition, column_list) }
37
+ end
38
+
39
+ def header(column_list)
40
+ header_formatter = HeaderFormatter.new(@doc)
41
+ header_line = column_list.map { |part| header_formatter.public_send(part) }
42
+ header_line.flatten
43
+ end
44
+
45
+ def body(definition, column_list)
46
+ body_formatter = BodyFormatter.new(@doc, definition)
47
+ body_line = column_list.map { |part| body_formatter.public_send(part) }
48
+ body_line.flatten
49
+ end
50
+
51
+ def build_column_list
52
+ [
53
+ [:wrong_explicit_checksum, @doc.wrong_explicit_checksum?],
54
+ [:explicit_version, @doc.explicit_version?],
55
+ [:labels, !@doc.labels.empty?],
56
+ [:eref, !@doc.eref.empty?],
57
+ [:iref, @doc.iref],
58
+ [:attributes, !@doc.attributes.empty?]
59
+ ].reduce([:fixed]) { |acc, elem| acc + (elem.fetch(1) ? [elem.first] : []) }
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,51 @@
1
+ # Copyright (c) 2020 Jerome Arbez-Gindre
2
+ # frozen_string_literal: true
3
+
4
+ require('csv')
5
+
6
+ module Defmastership
7
+ module Export
8
+ # format CSV header (first line) for one document
9
+ class HeaderFormatter
10
+ # @param doc [Document] the document to export
11
+ def initialize(doc)
12
+ @doc = doc
13
+ end
14
+
15
+ # @return [Array<String>] list of always available columns
16
+ def fixed
17
+ %w[Type Reference Value Checksum]
18
+ end
19
+
20
+ # @return [Array<String>] Optional wrong_explicit_checksum column caption
21
+ def wrong_explicit_checksum
22
+ @doc.wrong_explicit_checksum? ? ['Wrong explicit checksum'] : []
23
+ end
24
+
25
+ # @return [Array<String>] Optional version column captions
26
+ def explicit_version
27
+ @doc.explicit_version? ? ['Version'] : []
28
+ end
29
+
30
+ # @return [Array<String>] Optional labels columns captions
31
+ def labels
32
+ @doc.labels.empty? ? [] : %w[Labels]
33
+ end
34
+
35
+ # @return [Array<String>] Optional external refs columns captions
36
+ def eref
37
+ @doc.eref.map { |_, ref| ref.fetch(:prefix) }
38
+ end
39
+
40
+ # @return [Array<String>] Optional internal refs column caption
41
+ def iref
42
+ @doc.iref ? ['Internal links'] : []
43
+ end
44
+
45
+ # @return [Array<String>] Optional attributes columns captions
46
+ def attributes
47
+ @doc.attributes.map { |_, value| value }
48
+ end
49
+ end
50
+ end
51
+ end
@@ -1,23 +1,26 @@
1
1
  # Copyright (c) 2020 Jerome Arbez-Gindre
2
2
  # frozen_string_literal: true
3
3
 
4
- module DefMastership
4
+ require('defmastership/core/constants')
5
+
6
+ # Main module of the application
7
+ module Defmastership
5
8
  # Contains regexp / action couples
6
9
  Filter = Struct.new(:regexp, :event, :consumed_line)
7
10
  private_constant :Filter
8
11
 
9
12
  FILTERS = [
10
- Filter.new(DMRegexp::VARIABLE_DEF, :new_variable_def, false),
11
- Filter.new(DMRegexp::VARIABLE_USE, :new_variable_use, false),
12
- Filter.new(DMRegexp::DEFINITION, :new_definition, true),
13
- Filter.new(DMRegexp::EREF_CONFIG, :new_eref_setup, true),
14
- Filter.new(DMRegexp::EREF_DEF, :new_eref_def, false),
15
- Filter.new(DMRegexp::IREF_DEF, :new_iref_def, false),
16
- Filter.new(DMRegexp::ATTR_CONFIG, :new_attribute_conf, true),
17
- Filter.new(DMRegexp::ATTR_SET, :new_attribute_value, false),
18
- Filter.new(DMRegexp::BLOCK, :block_delimiter, true),
19
- Filter.new(DMRegexp::EMPTY_LINE, :empty_line, false),
20
- Filter.new(DMRegexp::WHATEVER, :new_line, true)
13
+ Filter.new(Core::DMRegexp::VARIABLE_DEF, :new_variable_def, false),
14
+ Filter.new(Core::DMRegexp::VARIABLE_USE, :new_variable_use, false),
15
+ Filter.new(Core::DMRegexp::DEFINITION, :new_definition, true),
16
+ Filter.new(Core::DMRegexp::EREF_CONFIG, :new_eref_setup, true),
17
+ Filter.new(Core::DMRegexp::EREF_DEF, :new_eref_def, false),
18
+ Filter.new(Core::DMRegexp::IREF_DEF, :new_iref_def, false),
19
+ Filter.new(Core::DMRegexp::ATTR_CONFIG, :new_attribute_conf, true),
20
+ Filter.new(Core::DMRegexp::ATTR_SET, :new_attribute_value, false),
21
+ Filter.new(Core::DMRegexp::BLOCK, :block_delimiter, true),
22
+ Filter.new(Core::DMRegexp::EMPTY_LINE, :empty_line, false),
23
+ Filter.new(Core::DMRegexp::WHATEVER, :new_line, true)
21
24
  ].freeze
22
25
  private_constant :FILTERS
23
26
  end
@@ -1,10 +1,11 @@
1
1
  # Copyright (c) 2020 Jerome Arbez-Gindre
2
2
  # frozen_string_literal: true
3
3
 
4
- module DefMastership
5
- # a composite class
4
+ module Defmastership
5
+ # a composite class storing a line and the corresponding match
6
6
  MatchingLine =
7
7
  Struct.new(:match, :line) do
8
+ # Act as a Hasg and delegate to the Match
8
9
  def [](key)
9
10
  value = match[key]
10
11
  return value if value