mirror of
https://github.com/neovim/neovim.git
synced 2026-06-16 00:31:16 +00:00
fix(shell): preserve CR when :! outputs to binary-mode buffer #39558
Problem:
When `:!` writes shell output to a buffer, write_output() splits on `\r`, `\n`,
and `\r\n`, replacing the terminator byte with NUL. For a binary-mode buffer
this is wrong: `\r` should be preserved verbatim, not treated as a line
terminator. This wrong behavior causes a file like `\r\n` round-trips through
`:%!cat` to `\n`.
This was masked when 'shelltemp' was enabled, because output went through a temp
file and the regular file I/O path handled binary-mode correctly. Switching the
default to 'noshelltemp' exposed the bug, since output is now piped directly
into write_output().
Solution:
In `write_output()`, skip the `\r` and `\r\n` splits for a binary-mode buffer;
only split on `\n`.
(cherry picked from commit 832a68835b)
This commit is contained in:
committed by
github-actions[bot]
parent
d8a94658f5
commit
2389cf2e39
@@ -1254,7 +1254,8 @@ static size_t write_output(char *output, size_t remaining, bool eof)
|
||||
size_t off = 0;
|
||||
while (off < remaining) {
|
||||
// CRLF
|
||||
if (output[off] == CAR && output[off + 1] == NL) {
|
||||
// special case: for binary mode, don't remove CR.
|
||||
if (output[off] == CAR && output[off + 1] == NL && !curbuf->b_p_bin) {
|
||||
output[off] = NUL;
|
||||
ml_append(curwin->w_cursor.lnum++, output, (int)off + 1, false);
|
||||
size_t skip = off + 2;
|
||||
@@ -1262,7 +1263,7 @@ static size_t write_output(char *output, size_t remaining, bool eof)
|
||||
remaining -= skip;
|
||||
off = 0;
|
||||
continue;
|
||||
} else if (output[off] == CAR || output[off] == NL) {
|
||||
} else if ((output[off] == CAR && !curbuf->b_p_bin) || output[off] == NL) {
|
||||
// Insert the line
|
||||
output[off] = NUL;
|
||||
ml_append(curwin->w_cursor.lnum++, output, (int)off + 1, false);
|
||||
|
||||
@@ -567,6 +567,25 @@ end)
|
||||
describe('shell :!', function()
|
||||
before_each(clear)
|
||||
|
||||
it('preserves newlines (including CR) in binary-mode buffer #39424', function()
|
||||
local fname = 'Xbinaryfile'
|
||||
finally(function()
|
||||
os.remove(fname)
|
||||
end)
|
||||
|
||||
t.write_file(fname, '\r\n', true)
|
||||
command('edit ++bin ' .. fname)
|
||||
command('%!cat')
|
||||
command('w')
|
||||
eq('\r\n', t.read_file(fname))
|
||||
|
||||
t.write_file(fname, '\r', true)
|
||||
command('edit ++bin ' .. fname)
|
||||
command('%!cat')
|
||||
command('w')
|
||||
eq('\r', t.read_file(fname))
|
||||
end)
|
||||
|
||||
it(':{range}! works when the first char is NUL #34163', function()
|
||||
api.nvim_buf_set_lines(0, 0, -1, true, { '\0hello', 'hello' })
|
||||
command('%!cat')
|
||||
|
||||
Reference in New Issue
Block a user