paste: break lines at CR, CRLF #10877

Some terminals helpfully translate \n to \r.

fix #10872
ref #10223
This commit is contained in:
Justin M. Keyes
2019-08-29 23:45:02 +02:00
committed by GitHub
parent 00d46f6328
commit 9f81acc076
6 changed files with 97 additions and 49 deletions

View File

@@ -745,19 +745,32 @@ String ga_take_string(garray_T *ga)
return str;
}
/// Creates "readfile()-style" ArrayOf(String).
/// Creates "readfile()-style" ArrayOf(String) from a binary string.
///
/// - NUL bytes are replaced with NL (form-feed).
/// - If last line ends with NL an extra empty list item is added.
Array string_to_array(const String input)
/// - Lines break at \n (NL/LF/line-feed).
/// - NUL bytes are replaced with NL.
/// - If the last byte is a linebreak an extra empty list item is added.
///
/// @param input Binary string
/// @param crlf Also break lines at CR and CRLF.
/// @return [allocated] String array
Array string_to_array(const String input, bool crlf)
{
Array ret = ARRAY_DICT_INIT;
for (size_t i = 0; i < input.size; i++) {
const char *start = input.data + i;
const char *end = xmemscan(start, NL, input.size - i);
const size_t line_len = (size_t)(end - start);
const char *end = start;
size_t line_len = 0;
for (; line_len < input.size - i; line_len++) {
end = start + line_len;
if (*end == NL || (crlf && *end == CAR)) {
break;
}
}
i += line_len;
if (crlf && *end == CAR && i + 1 < input.size && *(end + 1) == NL) {
i += 1; // Advance past CRLF.
}
String s = {
.size = line_len,
.data = xmemdupz(start, line_len),
@@ -766,8 +779,8 @@ Array string_to_array(const String input)
ADD(ret, STRING_OBJ(s));
// If line ends at end-of-buffer, add empty final item.
// This is "readfile()-style", see also ":help channel-lines".
if (i + 1 == input.size && end[0] == NL) {
ADD(ret, STRING_OBJ(cchar_to_string(NUL)));
if (i + 1 == input.size && (*end == NL || (crlf && *end == CAR))) {
ADD(ret, STRING_OBJ(STRING_INIT));
}
}