diff --git a/src/buffer/mod.rs b/src/buffer/mod.rs index d1679a06a867..7b28c13d4c12 100644 --- a/src/buffer/mod.rs +++ b/src/buffer/mod.rs @@ -204,6 +204,7 @@ pub struct TextBuffer { ruler: CoordType, encoding: &'static str, newlines_are_crlf: bool, + insert_final_newline: bool, overtype: bool, wants_cursor_visibility: bool, @@ -249,7 +250,9 @@ impl TextBuffer { line_highlight_enabled: false, ruler: 0, encoding: "UTF-8", - newlines_are_crlf: cfg!(windows), // Unfortunately Windows users insist on CRLF + // Windows users want CRLF and no final newline. + newlines_are_crlf: cfg!(windows), + insert_final_newline: !cfg!(windows), overtype: false, wants_cursor_visibility: false, @@ -621,6 +624,7 @@ impl TextBuffer { // * the logical line count // * the newline type (LF or CRLF) // * the indentation type (tabs or spaces) + // * whether there's a final newline { let chunk = self.read_forward(0); let mut offset = 0; @@ -711,10 +715,13 @@ impl TextBuffer { (_, lines) = unicode::newlines_forward(chunk, offset, lines, CoordType::MAX); } + let final_newline = chunk.ends_with(b"\n"); + // Add 1, because the last line doesn't end in a newline (it ends in the literal end). self.stats.logical_lines = lines + 1; self.stats.visual_lines = self.stats.logical_lines; self.newlines_are_crlf = newlines_are_crlf; + self.insert_final_newline = final_newline; self.indent_with_tabs = indent_with_tabs; self.tab_size = tab_size; } @@ -1894,6 +1901,22 @@ impl TextBuffer { } } + // POSIX mandates that all valid lines end in a newline. + // This isn't all that common on Windows and so we have + // `self.final_newline` to control this. + // + // In order to not annoy people with this, we only add a + // newline if you just edited the very end of the buffer. + if self.insert_final_newline + && self.cursor.offset > 0 + && self.cursor.offset == self.text_length() + && self.cursor.logical_pos.x > 0 + { + let cursor = self.cursor; + self.edit_write(if self.newlines_are_crlf { b"\r\n" } else { b"\n" }); + self.set_cursor_internal(cursor); + } + self.edit_end(); }