diff options
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | buffer.c | 104 | ||||
-rw-r--r-- | command.c | 20 | ||||
-rw-r--r-- | command.h | 4 | ||||
-rw-r--r-- | main.c | 2 | ||||
-rw-r--r-- | ted.cfg | 8 | ||||
-rw-r--r-- | ted.h | 9 |
7 files changed, 138 insertions, 10 deletions
@@ -3,6 +3,7 @@ ted !windows_installer/ted/ted Debug Release +scratch obj *~ *.swp @@ -1036,7 +1036,7 @@ void buffer_center_cursor(TextBuffer *buffer) { // move left (if `by` is negative) or right (if `by` is positive) by the specified amount. // returns the signed number of characters successfully moved (it could be less in magnitude than `by` if the beginning of the file is reached) -i64 buffer_pos_move_horizontally(TextBuffer *buffer, BufferPos *p, i64 by) { +static i64 buffer_pos_move_horizontally(TextBuffer *buffer, BufferPos *p, i64 by) { buffer_pos_validate(buffer, p); if (by < 0) { by = -by; @@ -1088,7 +1088,7 @@ i64 buffer_pos_move_horizontally(TextBuffer *buffer, BufferPos *p, i64 by) { } // same as buffer_pos_move_horizontally, but for up and down. -i64 buffer_pos_move_vertically(TextBuffer *buffer, BufferPos *pos, i64 by) { +static i64 buffer_pos_move_vertically(TextBuffer *buffer, BufferPos *pos, i64 by) { buffer_pos_validate(buffer, pos); // moving up/down should preserve the column, not the index. // consider: @@ -1140,6 +1140,13 @@ i64 buffer_pos_move_down(TextBuffer *buffer, BufferPos *pos, i64 by) { return +buffer_pos_move_vertically(buffer, pos, +by); } +static bool buffer_line_is_blank(Line *line) { + for (u32 i = 0; i < line->len; ++i) + if (!is32_space(line->str[i])) + return false; + return true; +} + void buffer_cursor_move_to_pos(TextBuffer *buffer, BufferPos pos) { buffer_pos_validate(buffer, &pos); if (buffer_pos_eq(buffer->cursor_pos, pos)) { @@ -1202,6 +1209,86 @@ i64 buffer_cursor_move_down(TextBuffer *buffer, i64 by) { return ret; } +i64 buffer_pos_move_up_blank_lines(TextBuffer *buffer, BufferPos *pos, i64 by) { + if (by == 0) return 0; + if (by < 0) return buffer_pos_move_down_blank_lines(buffer, pos, -by); + + + buffer_pos_validate(buffer, pos); + + u32 line = pos->line; + + // skip blank lines at start + while (line > 0 && buffer_line_is_blank(&buffer->lines[line])) + --line; + + i64 i; + for (i = 0; i < by; ++i) { + while (1) { + if (line == 0) { + goto end; + } else if (buffer_line_is_blank(&buffer->lines[line])) { + // move to the top blank line in this group + while (line > 0 && buffer_line_is_blank(&buffer->lines[line-1])) + --line; + break; + } else { + --line; + } + } + } + end: + pos->line = line; + pos->index = 0; + return i; +} + +i64 buffer_pos_move_down_blank_lines(TextBuffer *buffer, BufferPos *pos, i64 by) { + if (by == 0) return 0; + if (by < 0) return buffer_pos_move_up_blank_lines(buffer, pos, -by); + + buffer_pos_validate(buffer, pos); + + u32 line = pos->line; + // skip blank lines at start + while (line + 1 < buffer->nlines && buffer_line_is_blank(&buffer->lines[line])) + ++line; + + i64 i; + for (i = 0; i < by; ++i) { + while (1) { + if (line + 1 >= buffer->nlines) { + goto end; + } else if (buffer_line_is_blank(&buffer->lines[line])) { + // move to the bottom blank line in this group + while (line + 1 < buffer->nlines && buffer_line_is_blank(&buffer->lines[line+1])) + ++line; + break; + } else { + ++line; + } + } + } + end: + pos->line = line; + pos->index = 0; + return i; +} + +i64 buffer_cursor_move_up_blank_lines(TextBuffer *buffer, i64 by) { + BufferPos cursor = buffer->cursor_pos; + i64 ret = buffer_pos_move_up_blank_lines(buffer, &cursor, by); + buffer_cursor_move_to_pos(buffer, cursor); + return ret; +} + +i64 buffer_cursor_move_down_blank_lines(TextBuffer *buffer, i64 by) { + BufferPos cursor = buffer->cursor_pos; + i64 ret = buffer_pos_move_down_blank_lines(buffer, &cursor, by); + buffer_cursor_move_to_pos(buffer, cursor); + return ret; +} + // move left / right by the specified number of words // returns the number of words successfully moved forward i64 buffer_pos_move_words(TextBuffer *buffer, BufferPos *pos, i64 nwords) { @@ -1610,7 +1697,6 @@ void buffer_select_to_pos(TextBuffer *buffer, BufferPos pos) { buffer->selection = !buffer_pos_eq(buffer->cursor_pos, buffer->selection_pos); // disable selection if cursor_pos = selection_pos. } -// Like shift+left in most editors, move cursor nchars chars to the left, selecting everything in between void buffer_select_left(TextBuffer *buffer, i64 nchars) { BufferPos cpos = buffer->cursor_pos; buffer_pos_move_left(buffer, &cpos, nchars); @@ -1635,6 +1721,18 @@ void buffer_select_up(TextBuffer *buffer, i64 nchars) { buffer_select_to_pos(buffer, cpos); } +void buffer_select_down_blank_lines(TextBuffer *buffer, i64 by) { + BufferPos cpos = buffer->cursor_pos; + buffer_pos_move_down_blank_lines(buffer, &cpos, by); + buffer_select_to_pos(buffer, cpos); +} + +void buffer_select_up_blank_lines(TextBuffer *buffer, i64 by) { + BufferPos cpos = buffer->cursor_pos; + buffer_pos_move_up_blank_lines(buffer, &cpos, by); + buffer_select_to_pos(buffer, cpos); +} + void buffer_select_left_words(TextBuffer *buffer, i64 nwords) { BufferPos cpos = buffer->cursor_pos; buffer_pos_move_left_words(buffer, &cpos, nwords); @@ -17,6 +17,8 @@ static CommandName const command_names[] = { {"select-down", CMD_SELECT_DOWN}, {"left-word", CMD_LEFT_WORD}, {"right-word", CMD_RIGHT_WORD}, + {"up-blank-line", CMD_UP_BLANK_LINE}, + {"down-blank-line", CMD_DOWN_BLANK_LINE}, {"select-left-word", CMD_SELECT_LEFT_WORD}, {"select-right-word", CMD_SELECT_RIGHT_WORD}, {"start-of-line", CMD_START_OF_LINE}, @@ -30,6 +32,8 @@ static CommandName const command_names[] = { {"select-page-up", CMD_SELECT_PAGE_UP}, {"select-page-down", CMD_SELECT_PAGE_DOWN}, {"select-all", CMD_SELECT_ALL}, + {"select-up-blank-line", CMD_SELECT_UP_BLANK_LINE}, + {"select-down-blank-line", CMD_SELECT_DOWN_BLANK_LINE}, {"page-up", CMD_PAGE_UP}, {"page-down", CMD_PAGE_DOWN}, {"tab", CMD_TAB}, @@ -154,6 +158,14 @@ void command_execute(Ted *ted, Command c, i64 argument) { else if (buffer) buffer_cursor_move_down(buffer, argument); autocomplete_close(ted); break; + case CMD_UP_BLANK_LINE: + if (buffer) buffer_cursor_move_up_blank_lines(buffer, argument); + autocomplete_close(ted); + break; + case CMD_DOWN_BLANK_LINE: + if (buffer) buffer_cursor_move_down_blank_lines(buffer, argument); + autocomplete_close(ted); + break; case CMD_SELECT_LEFT: if (buffer) buffer_select_left(buffer, argument); autocomplete_close(ted); @@ -222,6 +234,14 @@ void command_execute(Ted *ted, Command c, i64 argument) { if (buffer) buffer_select_all(buffer); autocomplete_close(ted); break; + case CMD_SELECT_UP_BLANK_LINE: + if (buffer) buffer_select_up_blank_lines(buffer, argument); + autocomplete_close(ted); + break; + case CMD_SELECT_DOWN_BLANK_LINE: + if (buffer) buffer_select_down_blank_lines(buffer, argument); + autocomplete_close(ted); + break; case CMD_INSERT_TEXT: { const char *str = arg_get_string(ted, argument); @@ -20,6 +20,8 @@ ENUM_U16 { CMD_SELECT_DOWN, CMD_LEFT_WORD, // move cursor left a word CMD_RIGHT_WORD, + CMD_UP_BLANK_LINE, + CMD_DOWN_BLANK_LINE, CMD_SELECT_LEFT_WORD, CMD_SELECT_RIGHT_WORD, CMD_START_OF_LINE, // move cursor to start of line @@ -33,6 +35,8 @@ ENUM_U16 { CMD_SELECT_ALL, // select entire buffer CMD_SELECT_PAGE_UP, CMD_SELECT_PAGE_DOWN, + CMD_SELECT_UP_BLANK_LINE, + CMD_SELECT_DOWN_BLANK_LINE, // insertion CMD_INSERT_TEXT, // insert text @@ -1,6 +1,6 @@ /* @TODO: -- make ctrl+up/ctrl+down move to next/prev blank line +- ted.h documentation - broken session fix: close buffers not in any used node - handle multiple symbols with same name in go-to-definition menu - better non-error window/showMessage(Request) @@ -140,10 +140,10 @@ Up = :up Shift+Up = :select-up Down = :down Shift+Down = :select-down -Ctrl+Up = 10 :up -Ctrl+Shift+Up = 10 :select-up -Ctrl+Down = 10 :down -Ctrl+Shift+Down = 10 :select-down +Ctrl+Up = 1 :up-blank-line +Ctrl+Shift+Up = 1 :select-up-blank-line +Ctrl+Down = 1 :down-blank-line +Ctrl+Shift+Down = 1 :select-down-blank-line Home = :start-of-line Shift+Home = :select-start-of-line Ctrl+Home = :start-of-file @@ -650,8 +650,6 @@ void buffer_scroll_to_pos(TextBuffer *buffer, BufferPos pos); void buffer_scroll_center_pos(TextBuffer *buffer, BufferPos pos); void buffer_scroll_to_cursor(TextBuffer *buffer); void buffer_center_cursor(TextBuffer *buffer); -i64 buffer_pos_move_horizontally(TextBuffer *buffer, BufferPos *p, i64 by); -i64 buffer_pos_move_vertically(TextBuffer *buffer, BufferPos *pos, i64 by); i64 buffer_pos_move_left(TextBuffer *buffer, BufferPos *pos, i64 by); i64 buffer_pos_move_right(TextBuffer *buffer, BufferPos *pos, i64 by); i64 buffer_pos_move_up(TextBuffer *buffer, BufferPos *pos, i64 by); @@ -661,6 +659,10 @@ i64 buffer_cursor_move_left(TextBuffer *buffer, i64 by); i64 buffer_cursor_move_right(TextBuffer *buffer, i64 by); i64 buffer_cursor_move_up(TextBuffer *buffer, i64 by); i64 buffer_cursor_move_down(TextBuffer *buffer, i64 by); +i64 buffer_pos_move_up_blank_lines(TextBuffer *buffer, BufferPos *pos, i64 by); +i64 buffer_pos_move_down_blank_lines(TextBuffer *buffer, BufferPos *pos, i64 by); +i64 buffer_cursor_move_up_blank_lines(TextBuffer *buffer, i64 by); +i64 buffer_cursor_move_down_blank_lines(TextBuffer *buffer, i64 by); i64 buffer_pos_move_words(TextBuffer *buffer, BufferPos *pos, i64 nwords); i64 buffer_pos_move_left_words(TextBuffer *buffer, BufferPos *pos, i64 nwords); i64 buffer_pos_move_right_words(TextBuffer *buffer, BufferPos *pos, i64 nwords); @@ -684,10 +686,13 @@ LSPDocumentPosition buffer_cursor_pos_as_lsp_document_position(TextBuffer *buffe BufferPos buffer_insert_text_at_pos(TextBuffer *buffer, BufferPos pos, String32 str); void buffer_insert_char_at_pos(TextBuffer *buffer, BufferPos pos, char32_t c); void buffer_select_to_pos(TextBuffer *buffer, BufferPos pos); +// Like shift+left in most editors, move cursor nchars chars to the left, selecting everything in between void buffer_select_left(TextBuffer *buffer, i64 nchars); void buffer_select_right(TextBuffer *buffer, i64 nchars); void buffer_select_down(TextBuffer *buffer, i64 nchars); void buffer_select_up(TextBuffer *buffer, i64 nchars); +void buffer_select_down_blank_lines(TextBuffer *buffer, i64 by); +void buffer_select_up_blank_lines(TextBuffer *buffer, i64 by); void buffer_select_left_words(TextBuffer *buffer, i64 nwords); void buffer_select_right_words(TextBuffer *buffer, i64 nwords); void buffer_select_to_start_of_line(TextBuffer *buffer); |