Class: Ask::Tools::Edit

Inherits:
Ask::Tool
  • Object
show all
Defined in:
lib/ask/tools/shell/edit.rb

Overview

Edit a file by replacing exact text. Supports BOM, line-ending preservation.

Constant Summary collapse

MAX_FILE_SIZE =
1_000_000

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#operationsObject



75
76
77
# File 'lib/ask/tools/shell/edit.rb', line 75

def operations
  @operations ||= Shell::DefaultEditOperations.new
end

Instance Method Details

#execute(path:, old_string:, new_string:, replace_all: false) ⇒ Object



79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# File 'lib/ask/tools/shell/edit.rb', line 79

def execute(path:, old_string:, new_string:, replace_all: false)
  path = operations.expand_path(path)

  unless operations.file_exist?(path)
    return Ask::Result.error(message: "File does not exist: " + path)
  end

  unless operations.file?(path)
    return Ask::Result.error(message: "Not a file: " + path)
  end

  size = operations.file_size(path)
  if size > MAX_FILE_SIZE
    return Ask::Result.error(
      message: "File too large (#{size} bytes). Maximum is #{MAX_FILE_SIZE} bytes."
    )
  end

  raw = operations.read_file(path)
  bom, content = Shell.strip_bom(raw)
  original_ending = Shell.detect_line_ending(content)
  content = Shell.normalize_line_endings(content)

  if replace_all
    count = content.scan(old_string).size
    return Ask::Result.error(message: "String not found") if count == 0
    content = content.gsub(old_string, new_string)
  else
    index = content.index(old_string)
    return Ask::Result.error(message: "String not found") unless index
    count = 1
    content = content.sub(old_string, new_string)
  end

  # Restore line endings and re-add BOM
  content = Shell.restore_line_endings(content, original_ending)
  content = bom + content

  operations.write_file(path, content)
  Ask::Result.ok(data: { path: path, replacements: count },
                  metadata: { path: path, replacements: count })
end