summaryrefslogtreecommitdiff
path: root/buffer.c
diff options
context:
space:
mode:
authorpommicket <pommicket@gmail.com>2023-01-02 19:22:27 -0500
committerpommicket <pommicket@gmail.com>2023-01-02 19:22:27 -0500
commit29824f8bef3dde9b091185be295de3ae07ee17fd (patch)
tree189661946119fd960cb9fd04e13fa335dfcbeb5a /buffer.c
parentc04562a24e7fbee0839d00a8bfd5253426a98f20 (diff)
:up-blank-line, etc.
Diffstat (limited to 'buffer.c')
-rw-r--r--buffer.c104
1 files changed, 101 insertions, 3 deletions
diff --git a/buffer.c b/buffer.c
index 34fc9a2..2dd67f4 100644
--- a/buffer.c
+++ b/buffer.c
@@ -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);