Skip to content

Add Path.replace_utf8!#461

Open
dmisiuk wants to merge 1 commit into
roc-lang:mainfrom
dmisiuk:issue-386-path-replace-utf8
Open

Add Path.replace_utf8!#461
dmisiuk wants to merge 1 commit into
roc-lang:mainfrom
dmisiuk:issue-386-path-replace-utf8

Conversation

@dmisiuk

@dmisiuk dmisiuk commented Jul 25, 2026

Copy link
Copy Markdown
Contributor

Adds Path.replace_utf8!, closes #386.

Discussed on Zulip@Anton-4 settled the four open questions and retitled the issue accordingly:

  • Location: Path.replace_utf8! only. File is now just buffered readers, so whole-file operations stay on Path. Nothing added to File.
  • Scope: the replace-all ("each") form only, mirroring Str.replace_each.
  • Argument name: pattern rather than the builtin's delimiter, which reads oddly for file contents.
  • Atomicity: kept as a plain read-modify-write composition, documented as non-atomic (see below).

Implementation

replace_utf8! : Path, Str, Str => Try({}, [PathErr(IOErr), ..])
replace_utf8! = |path, pattern, replacement| {
    content = read_utf8!(path)?
    write_utf8!(path, Str.replace_each(content, pattern, replacement))
}

Pure Roc over the existing read_utf8! / write_utf8! and the Str.replace_each builtin, so there are no host or glue changes.

Non-atomic, by decision. This reads the whole file, substitutes, and writes it back, so a failure mid-write can leave the file partially written — exactly as a bare write_utf8! would. The doc comment states this. A safe temp-file-and-rename variant is a larger change that would also apply to write_utf8!, so it belongs in its own issue rather than being folded in here.

Testing

examples/file-replace.roc demonstrates the API and doubles as the behavioral test: it writes "Hello, World! Hello, Roc!", calls replace_utf8!("Hello", "Goodbye"), and reads it back. Its test_spec.json case asserts the exact result After replacing: "Goodbye, World! Goodbye, Roc!", which proves the replace-each behavior — both occurrences change, not just the first.

The assertion was verified to fail when the expected string is altered, so it isn't vacuously green. Full ./scripts/test.py passes — host build plus all examples across every target.

replace_utf8! is effectful, so there's no pure core to cover with expect blocks; the executed example is the proportionate coverage.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add Path.replace_utf8

1 participant