Module: Archsight::Editor::FileWriter

Defined in:
lib/archsight/editor/file_writer.rb

Overview

FileWriter handles reading and writing YAML documents in multi-document files

Defined Under Namespace

Classes: WriteError

Class Method Summary collapse

Class Method Details

.find_document_end(lines, start_idx) ⇒ Integer

Find the end index of a document (the line index of the next — or EOF)

Parameters:

  • lines (Array<String>)

    File lines

  • start_idx (Integer)

    Starting line index (0-indexed)

Returns:

  • (Integer)

    End index (exclusive - the line after the document ends)



63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/archsight/editor/file_writer.rb', line 63

def find_document_end(lines, start_idx)
  # Start searching from the line after start_idx
  idx = start_idx + 1

  while idx < lines.length
    # Check if this line is a document separator
    return idx if lines[idx].strip == "---"

    idx += 1
  end

  # No separator found, document goes to EOF
  lines.length
end

.read_document(path:, start_line:) ⇒ String

Read a YAML document from a file starting at a given line

Parameters:

  • path (String)

    File path

  • start_line (Integer)

    Line number where document starts (1-indexed)

Returns:

  • (String)

    Document content

Raises:

  • (WriteError)

    if file not found or line out of bounds



16
17
18
19
20
21
22
23
24
25
26
27
28
29
# File 'lib/archsight/editor/file_writer.rb', line 16

def read_document(path:, start_line:)
  raise WriteError, "File not found: #{path}" unless File.exist?(path)

  lines = File.readlines(path)
  start_idx = start_line - 1 # Convert to 0-indexed

  raise WriteError, "Line #{start_line} is beyond end of file" if start_idx >= lines.length

  # Find the end of this document (next --- or EOF)
  end_idx = find_document_end(lines, start_idx)

  # Extract and join the document lines
  lines[start_idx...end_idx].join
end

.replace_document(path:, start_line:, new_yaml:) ⇒ Object

Replace a YAML document in a file starting at a given line

Parameters:

  • path (String)

    File path

  • start_line (Integer)

    Line number where document starts (1-indexed)

  • new_yaml (String)

    New YAML content (without leading —)

Raises:

  • (WriteError)

    if file cannot be written or document not found at expected line



36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/archsight/editor/file_writer.rb', line 36

def replace_document(path:, start_line:, new_yaml:)
  raise WriteError, "File not found: #{path}" unless File.exist?(path)
  raise WriteError, "File not writable: #{path}" unless File.writable?(path)

  lines = File.readlines(path)
  start_idx = start_line - 1 # Convert to 0-indexed

  raise WriteError, "Line #{start_line} is beyond end of file" if start_idx >= lines.length

  # Find the end of this document (next --- or EOF)
  end_idx = find_document_end(lines, start_idx)

  # Build the new content
  # Ensure new_yaml ends with a newline
  new_yaml = "#{new_yaml}\n" unless new_yaml.end_with?("\n")

  # Replace the document
  new_lines = lines[0...start_idx] + [new_yaml] + lines[end_idx..]

  # Write atomically by writing to temp file then renaming
  File.write(path, new_lines.join)
end