Class: PatchYAML::Editor

Inherits:
Object
  • Object
show all
Defined in:
lib/patchyaml/find.rb,
lib/patchyaml/editor.rb,
lib/patchyaml/anchors.rb,
lib/patchyaml/pipeline.rb

Instance Method Summary collapse

Constructor Details

#initialize(data) ⇒ Editor

Returns a new instance of Editor.



5
6
7
8
9
10
# File 'lib/patchyaml/editor.rb', line 5

def initialize(data)
  @anchors = {}
  @pipeline = []

  reload(data)
end

Instance Method Details

#delete(path) ⇒ Object

Deletes a given path from the yaml

path - The path to the key to be deleted

Returns the same Editor instance



27
# File 'lib/patchyaml/editor.rb', line 27

def delete(path) = tap { @pipeline << [:delete, path] }

#exist?(path) ⇒ Boolean

Determines whether a given path exists in the loaded YAML

path - Path to be checked

Returns true if the path exists, false otherwise.

Returns:

  • (Boolean)


17
18
19
20
# File 'lib/patchyaml/editor.rb', line 17

def exist?(path)
  value, = find(@stream, path)
  !value.nil?
end

#find(from, path) ⇒ Object



5
6
7
8
9
10
11
12
13
14
# File 'lib/patchyaml/find.rb', line 5

def find(from, path)
  path = QueryParser.parse(path)
  # Pass through Psych::Nodes::Stream -> Psych::Nodes::Document
  node = [from, nil]
  path.each do |part|
    node = find_node(node, part)
    return [] if node.nil? || node.empty?
  end
  node
end

#find_mapping_key(from, named) ⇒ Object



57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/patchyaml/find.rb', line 57

def find_mapping_key(from, named)
  # A mapping is basically an even-numbered array containing keys followed by their values.
  # Keys are expressed as an scalar value.
  i = 0
  until i >= from.children.size - 1
    if from.children[i].value == named
      result = from.children[i + 1]
      return [result, from] unless result.is_a?(Psych::Nodes::Alias)

      item = @anchors[result.anchor]
      raise "patchyaml: Unknown anchor #{result.anchor} defined by #{result}" unless item

      return [item, from]
    end

    i += 2
  end
  [nil, from]
end

#find_node(from, part) ⇒ Object



16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/patchyaml/find.rb', line 16

def find_node(from, part)
  case part[:kind]
  when :simple
    case from.first
    when Psych::Nodes::Stream, Psych::Nodes::Document
      find_node([from.first.children.first, from], part)
    when Psych::Nodes::Mapping
      find_mapping_key(from.first, part[:value])
    when Psych::Nodes::Sequence
      [from.first.children.find { it.respond_to?(:value) && it.value == part[:value] }, from.first]
    when Psych::Nodes::Alias
      node = @anchors[from.first.anchor]
      raise "patchyaml: Unknown anchor #{from.anchor} defined by #{from.first}" unless node

      [find_node(node, part), node]
    when NilClass
      []
    else
      raise "patchyaml: Unexpected node #{from.first.class} in #find_node"
    end
  when :index
    case from.first
    when Psych::Nodes::Stream, Psych::Nodes::Document
      [find_node(from.first.children.first, part[:value]), from.first]
    when Psych::Nodes::Sequence
      [from.first.children[part[:value]], from.first]
    end
  when :expression
    case from.first
    when Psych::Nodes::Stream, Psych::Nodes::Document
      [find_node(from.first.children.first, part), from.first]
    when Psych::Nodes::Sequence
      v = from
        .first
        .children
        .find { it.is_a?(Psych::Nodes::Mapping) && find_mapping_key(it, part[:key]).first.value == part[:value] }
      [v, from]
    end
  end
end

#map_add(path, key, value) ⇒ Object

Adds a new key to the yaml

path - The path to the mapping that will receive the new key key - The new key name value - The new key value

Returns the same Editor instance



54
55
56
# File 'lib/patchyaml/editor.rb', line 54

def map_add(path, key, value)
  tap { @pipeline << [:map_add, path, key, value] }
end

#map_rename(path, to:) ⇒ Object

Renames a given path

path - The path to the key to be renamed to: - The new name of the key

Returns the same Editor instance



43
44
45
# File 'lib/patchyaml/editor.rb', line 43

def map_rename(path, to:)
  tap { @pipeline << [:rename, path, to] }
end

#process_anchor(from) ⇒ Object



5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# File 'lib/patchyaml/anchors.rb', line 5

def process_anchor(from)
  @anchors[from.anchor] = from if !from.is_a?(Psych::Nodes::Alias) && from.respond_to?(:anchor) && !from.anchor.nil?

  case from
  when Psych::Nodes::Stream, Psych::Nodes::Document
    process_anchor(from.children.first)
  when Psych::Nodes::Mapping
    process_anchor_map(from)
  when Psych::Nodes::Sequence
    from.children.each { process_anchor(it) }
  when Psych::Nodes::Scalar, Psych::Nodes::Alias
    # noop
  else
    raise "patchyaml: Unexpected node #{from.class} in #process_anchor"
  end
end

#process_anchor_map(from) ⇒ Object



22
23
24
25
26
# File 'lib/patchyaml/anchors.rb', line 22

def process_anchor_map(from)
  from.children.each.with_index do |item, idx|
    process_anchor(item) if idx.odd?
  end
end

#run_pipelineObject



5
6
7
8
# File 'lib/patchyaml/pipeline.rb', line 5

def run_pipeline
  run_pipeline_once until @pipeline.empty?
  @data
end

#seq_add(path, value, index: nil) ⇒ Object

Adds a new value to a sequence

path - The path to the sequence that will receive the new item value - The value to be added to the sequence index: - The index to insert the value into. Defaults to nil, and

appends to the end of the sequence.

Returns the same Editor instance



66
67
68
# File 'lib/patchyaml/editor.rb', line 66

def seq_add(path, value, index: nil)
  tap { @pipeline << [:seq_add, path, value, index] }
end

#update(path, value) ⇒ Object

Updates an existing path in the yaml to have the provided value

path - The path to the key to be updated value - The value to be set in the key

Returns the same Editor instance



35
# File 'lib/patchyaml/editor.rb', line 35

def update(path, value) = tap { @pipeline << [:update, path, value] }

#yamlObject

Returns the processed YAML after edits have been applied.



71
# File 'lib/patchyaml/editor.rb', line 71

def yaml = run_pipeline