Skip to content

edit: keep a CRLF file's line endings when JSON members are added or replaced - #830

Merged
yetone merged 1 commit into
yetone:mainfrom
charan-rathore:edit-keep-crlf-json
Oct 4, 2026
Merged

yetone merged 1 commit into
yetone:mainfrom
charan-rathore:edit-keep-crlf-json

Conversation

@charan-rathore

Copy link
Copy Markdown
Contributor

Same problem as #829, in JSON. A JSON or JSONC file saved with \r\n (VS Code on Windows does that) got a bare \n on every line SetJSON added, because insertKey and marshalAt build the new lines with \n:

{\r\n  "a": 1\r\n}\r\n   SetJSON b=2   ->   {\n  "b": 2,\r\n  "a": 1\r\n}\r\n

The result is now written back through keepCRLF, which turns every line break into \r\n when the original used \r\n for all of them. Untouched lines already carry their \r, so only the added lines change. A file that already mixed endings is written as before.

Tests: TestSetJSONKeepsCRLF fails on the old code; TestSetJSONKeepsMixedEndings pins that a mixed file is left alone.

Run: go vet and go test -tags nogui ./internal/edit ./internal/agent pass on this branch and on current main with it merged. Not run: the full ./... suite and the GUI tests. This touches only json.go, so it does not conflict with #829. SetJSONItem in jsonarray.go has the same gap; I left it out because the branch base predates that file, and will send it after this merges. Prepared with AI assistance.

…replaced

SetJSON splices new lines into the file with \n. In a JSON or JSONC file saved with \r\n (VS Code on Windows does that), a member added to an object or a nested value came back with a bare \n among the \r\n lines. SetJSON of "b" on "{\r\n  \"a\": 1\r\n}\r\n" gave "{\n  \"b\": 2,\r\n  \"a\": 1\r\n}\r\n".

The result is written back through keepCRLF, which turns every line break into \r\n when the original used \r\n for all of them. Untouched lines already carry their \r, so only the added lines change; a file that mixed endings is written as before.

TestSetJSONKeepsCRLF fails on the old code; TestSetJSONKeepsMixedEndings pins that a mixed file is left alone. go vet and go test ./internal/edit pass here and on current main with this merged.
@yetone
yetone merged commit 6b0a44e into yetone:main Oct 4, 2026
8 checks passed
yetone pushed a commit that referenced this pull request Oct 4, 2026
…AMLStrings rewrite it (#831)

* edit: keep a CRLF file's line endings when JSON members are added or replaced

SetJSON splices new lines into the file with \n. In a JSON or JSONC file saved with \r\n (VS Code on Windows does that), a member added to an object or a nested value came back with a bare \n among the \r\n lines. SetJSON of "b" on "{\r\n  \"a\": 1\r\n}\r\n" gave "{\n  \"b\": 2,\r\n  \"a\": 1\r\n}\r\n".

The result is written back through keepCRLF, which turns every line break into \r\n when the original used \r\n for all of them. Untouched lines already carry their \r, so only the added lines change; a file that mixed endings is written as before.

TestSetJSONKeepsCRLF fails on the old code; TestSetJSONKeepsMixedEndings pins that a mixed file is left alone. go vet and go test ./internal/edit pass here and on current main with this merged.

* edit: keep a CRLF file's line endings when SetYAML, DelYAML and EditYAMLStrings rewrite it

writeYAML renders the whole document with the YAML encoder, which writes \n. A YAML file saved with \r\n (the usual case for one edited on Windows) came back entirely LF after any SetYAML, DelYAML or EditYAMLStrings, so an edit of one key rewrote every line of the file and showed up as a full-file diff.

The result is written back through keepCRLF, which turns every line break into \r\n when the original used \r\n for all of them. A LF or mixed file is written as before.

TestSetYAMLKeepsCRLF fails on the old code; TestSetYAMLKeepsLF pins that an LF file is unchanged. This builds on the keepCRLF added for SetJSON in the previous commit (#830). go vet and go test ./internal/edit ./internal/agent ./internal/library ./internal/settings pass.
yetone added a commit that referenced this pull request Oct 4, 2026
… with no trailing break, in a multi-line TOML string, a YAML block scalar and after DelJSON (review of #829, #830, #831) — tests only. TestReviewLFUntouched and TestReviewCRLFEdges; the CRLF cases fail on the code before those PRs.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
@yetone

yetone commented Oct 4, 2026

Copy link
Copy Markdown
Owner

Thanks @charan-rathore, merged and released in v0.1.915.

I pulled #829, #830 and #831 together onto main and checked them:

  • go vet passes, the darwin, linux-nogui and windows builds pass, and go test -tags nogui ./... passes under a temp HOME.
  • Your CRLF tests fail on the old code, as they should.

I also added review tests (internal/edit/crlf_review_test.go, 2bfed7a). They cover:

  • LF files coming through SetEnvFile, DelEnvFile, the TOML setters, SetYAMLTop, DelYAMLTop, SetJSON, DelJSON, SetYAML and EditYAMLStrings byte-for-byte LF;
  • a CRLF dotenv file with no trailing line break;
  • a multi-line TOML string, which keeps \r\n inside it;
  • a YAML block scalar, which still reads back as one\ntwo\n;
  • DelJSON on a CRLF file.

All of them pass.

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.

2 participants