Class: Ast::Merge::Recipe::Preset

Inherits:
Object
  • Object
show all
Defined in:
lib/ast/merge/recipe/preset.rb

Overview

Base configuration for merge presets.

A Preset provides merge configuration (signature generators, node typing, preferences) without requiring a template file. This is useful for defining reusable merge behaviors that can be applied to any merge operation.

Config inherits from Preset and adds template/target file handling for standalone recipe execution.

Examples:

Loading a preset

preset = Preset.load("presets/gemfile.yml")
merger = Prism::Merge::SmartMerger.new(
  template, destination,
  **preset.to_h
)

Creating a preset programmatically

preset = Preset.new(
  "name" => "my_preset",
  "merge" => { "preference" => "template" }
)

See Also:

Direct Known Subclasses

Config

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(config, preset_path: nil) ⇒ Preset

Initialize a preset from a hash.

Parameters:

  • config (Hash)

    Parsed YAML config or programmatic config

  • preset_path (String, nil) (defaults to: nil)

    Path to preset file (for script resolution)



72
73
74
75
76
77
78
79
80
# File 'lib/ast/merge/recipe/preset.rb', line 72

def initialize(config, preset_path: nil)
  @preset_path = preset_path
  @name = config['name'] || 'unnamed'
  @description = config['description']
  @parser_explicit = config.key?('parser') || config.key?(:parser)
  @parser = (config['parser'] || config[:parser] || 'prism').to_sym
  @merge_config = parse_merge_config(config['merge'] || {})
  @freeze_token = config['freeze_token']
end

Instance Attribute Details

#descriptionString? (readonly)

Returns Preset description.

Returns:

  • (String, nil)

    Preset description



37
38
39
# File 'lib/ast/merge/recipe/preset.rb', line 37

def description
  @description
end

#freeze_tokenString? (readonly)

Returns Freeze token for preserving sections.

Returns:

  • (String, nil)

    Freeze token for preserving sections



46
47
48
# File 'lib/ast/merge/recipe/preset.rb', line 46

def freeze_token
  @freeze_token
end

#merge_configHash (readonly)

Returns Merge configuration.

Returns:

  • (Hash)

    Merge configuration



43
44
45
# File 'lib/ast/merge/recipe/preset.rb', line 43

def merge_config
  @merge_config
end

#nameString (readonly)

Returns Preset name.

Returns:

  • (String)

    Preset name



34
35
36
# File 'lib/ast/merge/recipe/preset.rb', line 34

def name
  @name
end

#parserSymbol (readonly)

Returns Parser to use (:prism, :markly, :psych, etc.).

Returns:

  • (Symbol)

    Parser to use (:prism, :markly, :psych, etc.)



40
41
42
# File 'lib/ast/merge/recipe/preset.rb', line 40

def parser
  @parser
end

#parser_explicitBoolean (readonly)

Returns Whether the parser was explicitly configured in YAML/hash input.

Returns:

  • (Boolean)

    Whether the parser was explicitly configured in YAML/hash input



52
53
54
# File 'lib/ast/merge/recipe/preset.rb', line 52

def parser_explicit
  @parser_explicit
end

#preset_pathString? (readonly)

Returns Path to the preset file (for script resolution).

Returns:

  • (String, nil)

    Path to the preset file (for script resolution)



49
50
51
# File 'lib/ast/merge/recipe/preset.rb', line 49

def preset_path
  @preset_path
end

Class Method Details

.load(path) ⇒ Preset

Load a preset from a YAML file.

Parameters:

  • path (String)

    Path to the preset YAML file

Returns:

Raises:

  • (ArgumentError)

    If file not found



60
61
62
63
64
65
# File 'lib/ast/merge/recipe/preset.rb', line 60

def load(path)
  raise ArgumentError, "Preset file not found: #{path}" unless File.exist?(path)

  yaml = YAML.safe_load_file(path, permitted_classes: [Regexp, Symbol])
  new(yaml, preset_path: path)
end

Instance Method Details

#add_missingBoolean, Proc

Get the add_missing setting, loading as callable if it's a script reference.

Returns:

  • (Boolean, Proc)

    Boolean value or callable filter



103
104
105
106
107
108
109
110
111
# File 'lib/ast/merge/recipe/preset.rb', line 103

def add_missing
  value = merge_config[:add_missing]
  return true if value.nil?
  return value if [true, false].include?(value)
  return value if value.respond_to?(:call)

  # It's a script reference - load it
  script_loader.load_callable(value)
end

#add_missing?Boolean, Proc

Convenience alias for boolean check.

Returns:

  • (Boolean, Proc)


116
117
118
# File 'lib/ast/merge/recipe/preset.rb', line 116

def add_missing?
  add_missing
end

#match_refinerObject?

Get the match_refiner callable, loading from script if needed.

Returns:

  • (Object, nil)

    Match refiner instance or callable



145
146
147
148
149
150
151
# File 'lib/ast/merge/recipe/preset.rb', line 145

def match_refiner
  value = merge_config[:match_refiner]
  return if value.nil?
  return value if value.respond_to?(:call) || value.is_a?(Ast::Merge::MatchRefinerBase)

  script_loader.load_callable(value)
end

#node_typingHash?

Get the node_typing configuration with callables loaded.

Returns:

  • (Hash, nil)

    Hash of type => callable



134
135
136
137
138
139
140
# File 'lib/ast/merge/recipe/preset.rb', line 134

def node_typing
  value = merge_config[:node_typing]
  return if value.nil?
  return value if value.is_a?(Hash) && value.values.all? { |v| v.respond_to?(:call) }

  script_loader.load_callable_hash(value)
end

#normalize_whitespaceBoolean

Get the normalize_whitespace setting.

This is a format-specific post-processing option forwarded to mergers that explicitly support it (currently markdown-family recipe flows).

Returns:

  • (Boolean)


159
160
161
# File 'lib/ast/merge/recipe/preset.rb', line 159

def normalize_whitespace
  merge_config[:normalize_whitespace] == true
end

#parser_explicit?Boolean

Whether the parser was explicitly configured.

This lets callers distinguish between the recipe model's internal default (:prism) and a parser choice the recipe author intended the stock runner to honor automatically.

Returns:

  • (Boolean)


89
90
91
# File 'lib/ast/merge/recipe/preset.rb', line 89

def parser_explicit?
  parser_explicit == true
end

#preferenceSymbol, Hash

Get the merge preference setting.

Returns:

  • (Symbol, Hash)

    Preference (:template, :destination, or per-type hash)



96
97
98
# File 'lib/ast/merge/recipe/preset.rb', line 96

def preference
  merge_config[:preference] || :template
end

Get the rehydrate_link_references setting.

Returns:

  • (Boolean)

    Whether to convert inline links to reference style



166
167
168
# File 'lib/ast/merge/recipe/preset.rb', line 166

def rehydrate_link_references
  merge_config[:rehydrate_link_references] == true
end

#script_loaderScriptLoader

Get the script loader instance.

Returns:



189
190
191
# File 'lib/ast/merge/recipe/preset.rb', line 189

def script_loader
  @script_loader ||= ScriptLoader.new(recipe_path: preset_path)
end

#signature_generatorProc?

Get the signature_generator callable, loading from script if needed.

Returns:

  • (Proc, nil)

    Signature generator callable



123
124
125
126
127
128
129
# File 'lib/ast/merge/recipe/preset.rb', line 123

def signature_generator
  value = merge_config[:signature_generator]
  return if value.nil?
  return value if value.respond_to?(:call)

  script_loader.load_callable(value)
end

#to_hHash

Convert preset to a hash suitable for SmartMerger options.

Returns:

  • (Hash)


173
174
175
176
177
178
179
180
181
182
183
184
# File 'lib/ast/merge/recipe/preset.rb', line 173

def to_h
  {
    preference: preference,
    add_template_only_nodes: add_missing,
    signature_generator: signature_generator,
    node_typing: node_typing,
    match_refiner: match_refiner,
    freeze_token: freeze_token,
    normalize_whitespace: normalize_whitespace,
    rehydrate_link_references: rehydrate_link_references
  }.compact
end