toml-merge 1.0.0 → 2.0.0

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.
@@ -5,11 +5,25 @@ module Toml
5
5
  # High-level merger for TOML content.
6
6
  # Orchestrates parsing, analysis, and conflict resolution.
7
7
  #
8
+ # Extends SmartMergerBase with backend-agnostic parsing via tree_haver.
9
+ # Supports both tree-sitter and Citrus/toml-rb backends (auto-selected by TreeHaver).
10
+ #
8
11
  # @example Basic usage
9
12
  # merger = SmartMerger.new(template_content, dest_content)
10
13
  # result = merger.merge
11
14
  # File.write("merged.toml", result.output)
12
15
  #
16
+ # @example Force Citrus backend via environment
17
+ # # Set TREE_HAVER_BACKEND=citrus before requiring toml/merge
18
+ # merger = SmartMerger.new(template, dest)
19
+ # result = merger.merge
20
+ #
21
+ # @example Force Citrus backend via TreeHaver
22
+ # TreeHaver.with_backend(:citrus) do
23
+ # merger = SmartMerger.new(template, dest)
24
+ # result = merger.merge
25
+ # end
26
+ #
13
27
  # @example With options
14
28
  # merger = SmartMerger.new(template, dest,
15
29
  # preference: :template,
@@ -23,33 +37,55 @@ module Toml
23
37
  # merger = SmartMerger.new(template, dest,
24
38
  # regions: [{ detector: SomeDetector.new, merger_class: SomeMerger }])
25
39
  class SmartMerger < ::Ast::Merge::SmartMergerBase
40
+ # @return [Symbol] The AST format being used (:tree_sitter or :citrus)
41
+ attr_reader :backend
42
+
26
43
  # Creates a new SmartMerger
27
44
  #
28
45
  # @param template_content [String] Template TOML content
29
46
  # @param dest_content [String] Destination TOML content
30
- # @param preference [Symbol] :destination or :template
47
+ # @param signature_generator [Proc, nil] Custom signature generator
48
+ # @param preference [Symbol, Hash] :destination, :template, or per-type Hash
31
49
  # @param add_template_only_nodes [Boolean] Whether to add nodes only found in template
50
+ # @param freeze_token [String, nil] Token for freeze block markers
32
51
  # @param match_refiner [#call, nil] Match refiner for fuzzy matching
33
52
  # @param regions [Array<Hash>, nil] Region configurations for nested merging
34
53
  # @param region_placeholder [String, nil] Custom placeholder for regions
54
+ # @param node_typing [Hash{Symbol,String => #call}, nil] Node typing configuration
55
+ # for per-node-type merge preferences
56
+ # @param options [Hash] Additional options for forward compatibility
57
+ #
58
+ # @note To force a specific backend, use TreeHaver.with_backend or TREE_HAVER_BACKEND env var.
59
+ # TreeHaver handles backend selection, auto-detection, and fallback.
35
60
  def initialize(
36
61
  template_content,
37
62
  dest_content,
63
+ signature_generator: nil,
38
64
  preference: :destination,
39
65
  add_template_only_nodes: false,
66
+ freeze_token: nil,
40
67
  match_refiner: nil,
41
68
  regions: nil,
42
- region_placeholder: nil
69
+ region_placeholder: nil,
70
+ node_typing: nil,
71
+ **options
43
72
  )
44
73
  super(
45
74
  template_content,
46
75
  dest_content,
76
+ signature_generator: signature_generator,
47
77
  preference: preference,
48
78
  add_template_only_nodes: add_template_only_nodes,
79
+ freeze_token: freeze_token,
49
80
  match_refiner: match_refiner,
50
81
  regions: regions,
51
82
  region_placeholder: region_placeholder,
83
+ node_typing: node_typing,
84
+ **options
52
85
  )
86
+
87
+ # Capture the resolved backend from template analysis (for NodeTypeNormalizer)
88
+ @backend = @template_analysis.backend
53
89
  end
54
90
 
55
91
  # Backward-compatible options hash
@@ -127,9 +163,11 @@ module Toml
127
163
 
128
164
  private
129
165
 
130
- # TOML FileAnalysis only accepts signature_generator, not freeze_token
166
+ # TOML FileAnalysis accepts signature_generator
131
167
  def build_full_analysis_options
132
- {signature_generator: @signature_generator}
168
+ {
169
+ signature_generator: @signature_generator,
170
+ }
133
171
  end
134
172
  end
135
173
  end
@@ -90,8 +90,10 @@ module Toml
90
90
  def table_node?(node)
91
91
  return false unless node.respond_to?(:type)
92
92
 
93
- type = node.type.to_s
94
- type == "table" || type == "table_array_element"
93
+ # Use node's backend if available (NodeWrapper), otherwise default
94
+ backend = node.respond_to?(:backend) ? node.backend : nil
95
+ canonical = backend ? NodeTypeNormalizer.canonical_type(node.type, backend) : NodeTypeNormalizer.canonical_type(node.type)
96
+ NodeTypeNormalizer.table_type?(canonical)
95
97
  end
96
98
 
97
99
  # Compute similarity score between two tables.
@@ -5,7 +5,7 @@ module Toml
5
5
  # Version information for Toml::Merge
6
6
  module Version
7
7
  # Current version of the toml-merge gem
8
- VERSION = "1.0.0"
8
+ VERSION = "2.0.0"
9
9
  end
10
10
  VERSION = Version::VERSION # traditional location
11
11
  end
data/lib/toml/merge.rb CHANGED
@@ -1,41 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # std libs
4
+ require "set"
5
+
3
6
  # External gems
4
- # TreeHaver provides a unified cross-Ruby interface to tree-sitter and Citrus
7
+ # TreeHaver provides a unified cross-Ruby interface to tree-sitter.
8
+ # It handles grammar discovery, backend selection, and Citrus fallback automatically
9
+ # via parser_for(:toml). No manual registration needed.
5
10
  require "tree_haver"
6
-
7
- # Register tree-sitter grammar (preferred, fast)
8
- tree_sitter_finder = TreeHaver::GrammarFinder.new(:toml)
9
- tree_sitter_available = tree_sitter_finder.available?
10
- tree_sitter_finder.register! if tree_sitter_available
11
-
12
- # Register Citrus grammar (fallback, pure Ruby)
13
- citrus_finder = TreeHaver::CitrusGrammarFinder.new(
14
- language: :toml,
15
- gem_name: "toml-rb",
16
- grammar_const: "TomlRB::Document",
17
- require_path: "toml-rb", # Explicit require path (gem uses "toml-rb.rb" not "toml/rb.rb")
18
- )
19
- citrus_available = citrus_finder.available?
20
- citrus_finder.register! if citrus_available
21
-
22
- # Ensure at least one grammar is available
23
- unless tree_sitter_available || citrus_available
24
- raise TreeHaver::NotAvailable,
25
- "No TOML parser available. Install either:\n " \
26
- "- tree-sitter-toml (fast): #{tree_sitter_finder.not_found_message}\n " \
27
- "- toml-rb gem (pure Ruby): #{citrus_finder.not_found_message}"
28
- end
29
-
30
- # Warn if Citrus backend is forced but toml-rb not available
31
- if TreeHaver.backend == :citrus && !citrus_available && tree_sitter_available
32
- warn "WARNING: TREE_HAVER_BACKEND=citrus but toml-rb not installed. " \
33
- "Using tree-sitter backend instead. Install toml-rb: gem install toml-rb"
34
- TreeHaver.backend = :auto
35
- end
36
-
37
11
  require "version_gem"
38
- require "set"
39
12
 
40
13
  # Shared merge infrastructure
41
14
  require "ast/merge"
@@ -119,8 +92,10 @@ module Toml
119
92
  class DestinationParseError < ParseError; end
120
93
 
121
94
  autoload :DebugLogger, "toml/merge/debug_logger"
95
+ autoload :Emitter, "toml/merge/emitter"
122
96
  autoload :FileAnalysis, "toml/merge/file_analysis"
123
97
  autoload :MergeResult, "toml/merge/merge_result"
98
+ autoload :NodeTypeNormalizer, "toml/merge/node_type_normalizer"
124
99
  autoload :NodeWrapper, "toml/merge/node_wrapper"
125
100
  autoload :ConflictResolver, "toml/merge/conflict_resolver"
126
101
  autoload :SmartMerger, "toml/merge/smart_merger"
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: toml-merge
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Peter H. Boling
@@ -38,26 +38,35 @@ cert_chain:
38
38
  date: 1980-01-02 00:00:00.000000000 Z
39
39
  dependencies:
40
40
  - !ruby/object:Gem::Dependency
41
- name: toml-rb
41
+ name: tree_haver
42
42
  requirement: !ruby/object:Gem::Requirement
43
43
  requirements:
44
44
  - - "~>"
45
45
  - !ruby/object:Gem::Version
46
- version: '4.1'
46
+ version: '4.0'
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ version: 4.0.3
47
50
  type: :runtime
48
51
  prerelease: false
49
52
  version_requirements: !ruby/object:Gem::Requirement
50
53
  requirements:
51
54
  - - "~>"
52
55
  - !ruby/object:Gem::Version
53
- version: '4.1'
56
+ version: '4.0'
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ version: 4.0.3
54
60
  - !ruby/object:Gem::Dependency
55
- name: tree_haver
61
+ name: ast-merge
56
62
  requirement: !ruby/object:Gem::Requirement
57
63
  requirements:
58
64
  - - "~>"
59
65
  - !ruby/object:Gem::Version
60
66
  version: '3.1'
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: 3.1.0
61
70
  type: :runtime
62
71
  prerelease: false
63
72
  version_requirements: !ruby/object:Gem::Requirement
@@ -65,20 +74,9 @@ dependencies:
65
74
  - - "~>"
66
75
  - !ruby/object:Gem::Version
67
76
  version: '3.1'
68
- - !ruby/object:Gem::Dependency
69
- name: ast-merge
70
- requirement: !ruby/object:Gem::Requirement
71
- requirements:
72
- - - "~>"
73
- - !ruby/object:Gem::Version
74
- version: '1.1'
75
- type: :runtime
76
- prerelease: false
77
- version_requirements: !ruby/object:Gem::Requirement
78
- requirements:
79
- - - "~>"
77
+ - - ">="
80
78
  - !ruby/object:Gem::Version
81
- version: '1.1'
79
+ version: 3.1.0
82
80
  - !ruby/object:Gem::Dependency
83
81
  name: version_gem
84
82
  requirement: !ruby/object:Gem::Requirement
@@ -282,8 +280,10 @@ files:
282
280
  - lib/toml/merge.rb
283
281
  - lib/toml/merge/conflict_resolver.rb
284
282
  - lib/toml/merge/debug_logger.rb
283
+ - lib/toml/merge/emitter.rb
285
284
  - lib/toml/merge/file_analysis.rb
286
285
  - lib/toml/merge/merge_result.rb
286
+ - lib/toml/merge/node_type_normalizer.rb
287
287
  - lib/toml/merge/node_wrapper.rb
288
288
  - lib/toml/merge/smart_merger.rb
289
289
  - lib/toml/merge/table_match_refiner.rb
@@ -294,10 +294,10 @@ licenses:
294
294
  - MIT
295
295
  metadata:
296
296
  homepage_uri: https://toml-merge.galtzo.com/
297
- source_code_uri: https://github.com/kettle-rb/toml-merge/tree/v1.0.0
298
- changelog_uri: https://github.com/kettle-rb/toml-merge/blob/v1.0.0/CHANGELOG.md
297
+ source_code_uri: https://github.com/kettle-rb/toml-merge/tree/v2.0.0
298
+ changelog_uri: https://github.com/kettle-rb/toml-merge/blob/v2.0.0/CHANGELOG.md
299
299
  bug_tracker_uri: https://github.com/kettle-rb/toml-merge/issues
300
- documentation_uri: https://www.rubydoc.info/gems/toml-merge/1.0.0
300
+ documentation_uri: https://www.rubydoc.info/gems/toml-merge/2.0.0
301
301
  funding_uri: https://github.com/sponsors/pboling
302
302
  wiki_uri: https://github.com/kettle-rb/toml-merge/wiki
303
303
  news_uri: https://www.railsbling.com/tags/toml-merge
@@ -326,7 +326,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
326
326
  - !ruby/object:Gem::Version
327
327
  version: '0'
328
328
  requirements: []
329
- rubygems_version: 4.0.1
329
+ rubygems_version: 4.0.3
330
330
  specification_version: 4
331
331
  summary: "☯️ TOML file smart merge using tree-sitter AST analysis"
332
332
  test_files: []
metadata.gz.sig CHANGED
Binary file