diff --git a/src/nvim/os/shell.c b/src/nvim/os/shell.c index 4cc9188d16..71dce1783a 100644 --- a/src/nvim/os/shell.c +++ b/src/nvim/os/shell.c @@ -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); diff --git a/test/functional/vimscript/system_spec.lua b/test/functional/vimscript/system_spec.lua index 9a0df7acb7..d4e085cf9f 100644 --- a/test/functional/vimscript/system_spec.lua +++ b/test/functional/vimscript/system_spec.lua @@ -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')