Skip to content

diff: accepted text differs from :w in corner cases of 'fileformat' and 'fileformats' #581

Open

Description

@ThomasK33

The text that a split-layout diff accepts can differ from what :w writes for the same buffer in some corner cases of 'fileformat' and 'fileformats'. Each case below exists on main before #577 too. #577 fixes the common cases (CRLF proposals under the default 'fileformats', and an unedited proposal under any 'fileformats') and leaves these for a follow-up.

  1. ff=mac with a CR inside a line: :w writes that CR as NL, the accepted text keeps it. "a\rb\n" then :setlocal ff=mac gives "a\rb\r", while :w gives "a\nb\r". main joined with LF, which is also wrong. Codex flagged this on fix(diff): save a line the user types into a CRLF proposal with CRLF #577 (diff.lua, "Translate embedded CR bytes before joining Mac lines").
  2. set ffs=unix,mac: Neovim reads, for example, "a\r\nb\r\r\n" as mac, but the diff never detects mac. In 24 ff=mac edit cases, main's answer equals a file-read oracle and fix(diff): save a line the user types into a CRLF proposal with CRLF #577's does not. Both differ from :w of the same buffer.
  3. Empty proposal, then typed lines: 'eol' stays off (fix(diff): accept a proposal without a final line break as it is in the split layouts #542), so Gox gives "\nx", while :w of an empty file gives "\nx\n".
  4. 'fileformats' starting with dos and a proposal with no LF ("", "a", "a\r"): Neovim reads it as dos, the diff keeps unix, so a typed line gets LF where :w writes CRLF.
  5. set ffs=dos (one entry): Neovim reads every file as dos, an LF file too. An LF or mixed proposal stays unix, so a typed line gets LF where :w of the file writes CRLF.

Fix direction: one function that decides 'fileformat' and splits the proposal the way readfile does (empty value: 'fileformat'; one entry: forced; several entries: dos unless a lone LF, mac when there are more CRs than LFs, the first entry when there is no LF), plus a join that translates CRs for mac. The neovim_writes oracle in tests/integration/diff_accept_crlf_spec.lua (#577) can be reused.

Evidence: a probe of 1860 cases per run on Neovim 0.12.3 and 0.8.0, under 'fileformats' unix,dos, dos,unix, unix, dos and unix,mac. Mismatches with :w left on #577 (on main): 144 (748), 184 (788), 192 (304), 516 (1104), 544 (608).

The maintainer agreed to defer items 1 and 3 (and item 2, which belongs to item 1) from the README verification run, and later agreed to defer items 4 and 5 and item 6 in the comment below as well.

Owner: the next change to the diff accept path in lua/claudecode/diff.lua (follow-up trigger: any PR that touches how accepted text is joined or how 'fileformat' is set).


Generated with xum • Model: anthropic:claude-opus-5-5 • Thinking: high

Activity

  1. ThomasK33 commented on Nov 12, 2026

    @ThomasK33
    MemberAuthor

    One more item from the #577 advisor review:

    1. A proposal that differs from the file only in its line endings (for example an LF file and the same text as a CRLF proposal) now shows no changed lines in the diff view, while the accepted text keeps the proposal's line breaks. nvim -d of the same two files also marks none. This is not a defect, but no README line says it. Add one sentence to lua/claudecode/README.md next to the line-ending rule.

    Also from that review: the patch Codex suggested on #577 (turn CRs into LFs before the mac join) removes every mismatch against :w of the same buffer, but it is worse than main in 24 cases under set ffs=unix,mac, because the diff never detects mac. Items 1 and 2 above need to be fixed together.


    Generated with xum • Model: anthropic:claude-opus-5-5 • Thinking: high

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    needs-triageAwaiting maintainer triage

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions