diff options
| author | Marc André Tanner <mat@brain-dump.org> | 2017-01-20 09:11:41 +0100 |
|---|---|---|
| committer | Marc André Tanner <mat@brain-dump.org> | 2017-01-20 15:05:38 +0100 |
| commit | 181fe9aae12c6f25d8e5a10309c4e551bef338dd (patch) | |
| tree | 3109751b761e5869e4824ebfdb2322fa85f4e6c1 | |
| parent | 21dcbfe451be24786ac8f22e022cda07d17413d5 (diff) | |
| download | vis-181fe9aae12c6f25d8e5a10309c4e551bef338dd.tar.gz vis-181fe9aae12c6f25d8e5a10309c4e551bef338dd.tar.xz | |
vis: improve new line handling at end of file
<Enter> at the end of the file now inserts two newlines, unless there is
already one in place. This ensures that in 'normal' operation the file
is always new line terminated (as mandated by POSIX). It also means that
there is no problem displaying the right amount of ~ symbols at the end
of the file.
Unlike in vim the cell beyond the end of the file remains adressable
even in normal mode. This means something like the following (starting
from an empty file) might be a little confusing:
o<Escape><Left>dd
Because the starting position is beyond the last newline of the file,
nothing will be deleted.
For now we prefer to avoid the additional complexity, and difference
in behavior between normal and insert mode, needed to fix this slight
inconsistency.
Fix #294
| -rw-r--r-- | view.c | 17 | ||||
| -rw-r--r-- | vis.c | 20 |
2 files changed, 30 insertions, 7 deletions
@@ -328,11 +328,11 @@ void view_cursor_to(View *view, size_t pos) { void view_draw(View *view) { view_clear(view); /* read a screenful of text considering each character as 4-byte UTF character*/ - const size_t text_size = view->width * view->height * 4; + const size_t size = view->width * view->height * 4; /* current buffer to work with */ - char text[text_size+1]; + char text[size+1]; /* remaining bytes to process in buffer */ - size_t rem = text_bytes_get(view->text, view->start, text_size, text); + size_t rem = text_bytes_get(view->text, view->start, size, text); /* NUL terminate text section */ text[rem] = '\0'; /* absolute position of character currently being added to display */ @@ -361,7 +361,7 @@ void view_draw(View *view) { * wide character. advance file position and read * another junk into buffer. */ - rem = text_bytes_get(view->text, pos, text_size, text); + rem = text_bytes_get(view->text, pos, size, text); text[rem] = '\0'; cur = text; continue; @@ -404,7 +404,14 @@ void view_draw(View *view) { /* set end of vieviewg region */ view->end = pos; - view->lastline = view->line ? view->line : view->bottomline; + if (view->line) { + if (view->line->len == 0 && view->end == text_size(view->text) && view->line->prev) + view->lastline = view->line->prev; + else + view->lastline = view->line; + } else { + view->lastline = view->bottomline; + } /* clear remaining of line, important to show cursor at end of file */ if (view->line) { @@ -1421,8 +1421,24 @@ static void copy_indent_from_previous_line(Win *win, Cursor *cur) { } void vis_insert_nl(Vis *vis) { - const char *nl = text_newline_char(vis->win->file->text); - vis_insert_key(vis, nl, strlen(nl)); + Text *txt = vis->win->file->text; + const char *nl = text_newline_char(txt); + size_t len = strlen(nl); + for (Cursor *c = view_cursors(vis->win->view); c; c = view_cursors_next(c)) { + char byte; + size_t pos = view_cursors_pos(c); + /* insert second newline at end of file, except if there is already one */ + bool eof = pos == text_size(txt); + bool nl2 = eof && !(pos > 0 && text_byte_get(txt, pos-1, &byte) && byte == '\n'); + vis_insert(vis, pos, nl, len); + if (eof) { + if (nl2) + vis_insert(vis, pos, nl, len); + else + pos -= len; /* place cursor before, not after nl */ + } + view_cursors_scroll_to(c, pos + len); + } if (!vis->autoindent) return; |
