Skip to content

Full support edit CRLF(win) files in editor - #5151

Draft
KuzinAndrey wants to merge 2 commits into
MidnightCommander:masterfrom
KuzinAndrey:edit-crlf-files
Draft

Full support edit CRLF(win) files in editor#5151
KuzinAndrey wants to merge 2 commits into
MidnightCommander:masterfrom
KuzinAndrey:edit-crlf-files

Conversation

@KuzinAndrey

@KuzinAndrey KuzinAndrey commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

Resolves:

Proposed changes

This is opencode AI-driven improvement in editor for support edition of Win (CRLF) files (and with mixed line ends).

Current version of editor didn't support CRLF (win) files (show only ^M at line ends), adding any new line in such file was difficult, because it add all lines in LF (unix) mode. Now it automatically detect current line-end-style in file and can add new lines with right EOL (U - \n, W - \r\n, M - \r).

Before:

$ (cat > win.txt) << EOF
aaaaaa
bbbbbb
cccccc
dddddd
eeeeee
123456
EOF
$ todos win.txt
$ mcedit win.txt
win1

After:
win2

$ xxd win.txt 
00000000: 6161 6161 6161 0d0a 6262 6262 6262 0d0a  aaaaaa..bbbbbb..
00000010: 6363 6363 6363 0d0a 6e65 7720 7769 6e20  cccccc..new win 
00000020: 656f 6c20 7374 7269 6e67 0d0a 6464 6464  eol string..dddd
00000030: 6464 0d0a 6565 6565 6565 0d0a 3132 3334  dd..eeeeee..1234
00000040: 3536 0d0a                                56..

Checklist

  • I have referenced the issue(s) resolved by this PR (if any)
  • I have signed-off my contribution with git commit --amend -s
  • Lint and unit tests pass locally with my changes (make indent && make check)
  • I have added tests that prove my fix is effective or that my feature works
  • I have added the necessary documentation (if appropriate)

@github-actions github-actions Bot added needs triage Needs triage by maintainers prio: medium Has the potential to affect progress labels Sep 5, 2026
@github-actions github-actions Bot added this to the Future Releases milestone Sep 5, 2026
@KuzinAndrey
KuzinAndrey marked this pull request as draft September 6, 2026 05:25
@KuzinAndrey
KuzinAndrey force-pushed the edit-crlf-files branch 3 times, most recently from e45d979 to 0864dbb Compare September 6, 2026 07:38
A Windows ("\r\n") line break is no longer displayed as "^M" and is
handled as a single unit: End key and Delete/Backspace stop at / remove
the whole pair, line counting and cursor columns ignore the "\r" part.

A line break inserted with Enter inherits the type of the current line
("\r\n" or "\n"); for the last line of a file the previous line's type
is used. File content is kept raw in the buffer: mixed line breaks are
preserved as-is on save (the default LB_ASIS mode), the Save As dialog
still offers conversion to a single line break type.

Fix edit_write_stream() appending an extra "\n" to files that already
end with a line break in conversion modes.

Add a fifth character to the status line showing the detected line
breaks: U (all "\n"), W (all "\r\n"), M (all "\r"), "-" (mixed or none).

Add unit tests for line break detection, conversion, inheritance and
atomic deletion (tests/src/editor/edit_line_breaks.c).

Signed-off-by: Kuzin Andrey <kuzinandrey@yandex.ru>
Previously the "\r" of a "\r\n" line break was hidden (and the pair was
treated as an atomic line break) in every file. That made it impossible
to spot CRLF lines in a file with a mixture of line breaks (e.g. a patch
containing diffs of files saved with both "\n" and "\r\n").

Now the "\r" is hidden only when the buffer is detected as pure Windows
(all line breaks are "\r\n", status line shows "W"). In any other file
(mixed "-", Unix "U", Mac "M") it is shown as "^M".

The "\r\n" pair is nevertheless always a single (atomic) line break, in
every file type: the cursor stops before the "\r", Delete/Backspace and
Del-to-EOL/Del-line remove the pair as a unit, and the content of the
line ends at the "\r". The "^M" is only a visual marker of the line
break type, not an editable character, so pressing Enter at the end of a
CRLF line and navigating over blank CRLF lines behave the same as in a
pure Windows file (no duplicated "\r", the cursor stays before the "\r").

The cached line break type is moved to the buffer
(edit_buffer_get_line_breaks()/edit_buffer_refresh_line_breaks()) so the
column calculation and the renderer agree on how many columns the "\r"
occupies (two in a mixed file, none in a pure Windows file).

A standalone "\r" (Mac) is rendered as "^M" again instead of as a tab.

Extend the unit tests: trailing-whitespace detection for a CRLF line,
and End/Delete/Backspace/Del-to-EOL/Enter on a CRLF line in a file with
mixed line breaks.

Signed-off-by: Kuzin Andrey <kuzinandrey@yandex.ru>
@KuzinAndrey

Copy link
Copy Markdown
Contributor Author

Fix some editor behaviour in mixed EOL-type files and code clang-format CI tests

@KuzinAndrey
KuzinAndrey marked this pull request as ready for review September 6, 2026 09:04
edit_replace_cmd_SOURCES = \
edit_replace_cmd.c

edit_line_breaks_SOURCES = \

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please move it upper to have the same order as one in TESTS.

Comment thread src/editor/editbuffer.h
long curs_line; // line number of the cursor.

LineBreaks lb_detected; // cached detect_line_breaks() result
unsigned int lb_dirty : 1; // line breaks have changed, need detect_line_breaks()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the profit of having it a bit-field instead of boolean?

Comment thread src/editor/edit.c
{
// a CRLF line break ends the line before the "\r", not after it
return (upto != 0) ? (off_t) col
: (off_t) (edit_buffer_is_crlf (&edit->buffer, p - 1) ? p - 1 : p);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typecast is unneeded. p is of type off_t already.

Comment thread src/editor/editcmd.c
edit_get_save_file_as (WEdit *edit)
{
static LineBreaks cur_lb = LB_ASIS;
LineBreaks cur_lb = LB_ASIS;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the Save As dialog, the line breaks type (the position in radiobuttons) isn't preserved anymore.

Comment thread src/editor/editbuffer.c
off_t
edit_buffer_trailing_ws_start (const edit_buffer_t *buf, off_t bol)
{
off_t eol = edit_buffer_get_eol (buf, bol);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please do not mix variable declarations and code. Move function call after variable declarations.

@mc-worker

Copy link
Copy Markdown
Contributor

I'd like to make such large commits a bit smaller:

  • move the introducing of new buffer API to a separate commit

  • move refactoring (introducing new function edit_insert_line_break and usage it) to a separate commit.

@zyv zyv added area: mcedit mcedit, the built-in text editor and removed needs triage Needs triage by maintainers labels Sep 6, 2026
@zyv zyv linked an issue Sep 6, 2026 that may be closed by this pull request
@KuzinAndrey

Copy link
Copy Markdown
Contributor Author

I apologize, all the code was generated by the AI ​​agent, and I reviewed it as best I could. I even just tested the expected behavior in the editor and made corrective prompts (though some navigation issues are still possible, and I'll be using the modified editor for work now; I might find more bugs). I couldn't use the editor at all on WIN files until I decided to do something about it.
Naturally, the AI ​​agent did everything at its own discretion and may have touched code it shouldn't have. I'll try to correct your comments. But for now, perhaps it's worth converting the PR to draft again?
I think it's worth using the editor for at least a week to make sure nothing was broken.

@KuzinAndrey
KuzinAndrey marked this pull request as draft September 6, 2026 16:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: mcedit mcedit, the built-in text editor prio: medium Has the potential to affect progress

Development

Successfully merging this pull request may close these issues.

Hide ^M in editor

3 participants