summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeo Tenenbaum <pommicket@gmail.com>2021-02-10 11:16:24 -0500
committerLeo Tenenbaum <pommicket@gmail.com>2021-02-11 14:50:02 -0500
commit90b4b08717730733402df25190bba0cc5d2fd952 (patch)
treefe85f6fa7d8128e6195a313f428fb3bf6b446929
parent5bffb50207f8d8ba873f4c40dde4859179153001 (diff)
indent/dedent selection
-rw-r--r--buffer.c61
-rw-r--r--command.c14
-rw-r--r--main.c1
-rw-r--r--math.c9
4 files changed, 78 insertions, 7 deletions
diff --git a/buffer.c b/buffer.c
index 640e64c..78d5191 100644
--- a/buffer.c
+++ b/buffer.c
@@ -2199,12 +2199,69 @@ void buffer_render(TextBuffer *buffer, Rect r) {
// buffer_insert_text_at_pos(buffer, another position, "text2")
// buffer_end_edit_chain(buffer)
// pressing ctrl+z will undo both the insertion of text1 and text2.
-static void buffer_start_edit_chain(TextBuffer *buffer) {
+void buffer_start_edit_chain(TextBuffer *buffer) {
assert(!buffer->chaining_edits);
assert(!buffer->will_chain_edits);
buffer->will_chain_edits = true;
}
-static void buffer_end_edit_chain(TextBuffer *buffer) {
+void buffer_end_edit_chain(TextBuffer *buffer) {
buffer->chaining_edits = buffer->will_chain_edits = false;
}
+
+void buffer_indent_lines(TextBuffer *buffer, u32 first_line, u32 last_line) {
+ assert(first_line <= last_line);
+ buffer_start_edit_chain(buffer);
+ for (u32 i = first_line; i <= last_line; ++i) {
+ BufferPos pos = {.line = i, .index = 0};
+ char32_t c = '\t';
+ buffer_insert_text_at_pos(buffer, pos, str32(&c, 1));
+ }
+ buffer_end_edit_chain(buffer);
+}
+
+void buffer_dedent_lines(TextBuffer *buffer, u32 first_line, u32 last_line) {
+ assert(first_line <= last_line);
+ buffer_start_edit_chain(buffer);
+ Settings const *settings = buffer_settings(buffer);
+ u8 const tab_width = settings->tab_width;
+
+ for (u32 line_idx = first_line; line_idx <= last_line; ++line_idx) {
+ Line *line = &buffer->lines[line_idx];
+ if (line->len) {
+ u32 chars_to_delete = 0;
+ if (line->str[0] == '\t') {
+ chars_to_delete = 1;
+ } else {
+ u32 i;
+ for (i = 0; i < line->len && i < tab_width; ++i) {
+ char32_t c = line->str[i];
+ if (c == '\t' || !is32_space(c))
+ break;
+ }
+ chars_to_delete = i;
+ }
+ if (chars_to_delete) {
+ BufferPos pos = {.line = line_idx, .index = 0};
+ buffer_delete_chars_at_pos(buffer, pos, chars_to_delete);
+ }
+ }
+ }
+ buffer_end_edit_chain(buffer);
+}
+
+void buffer_indent_selection(TextBuffer *buffer) {
+ if (!buffer->selection) return;
+ u32 l1 = buffer->cursor_pos.line;
+ u32 l2 = buffer->selection_pos.line;
+ sort2_u32(&l1, &l2); // ensure l1 <= l2
+ buffer_indent_lines(buffer, l1, l2);
+}
+
+void buffer_dedent_selection(TextBuffer *buffer) {
+ if (!buffer->selection) return;
+ u32 l1 = buffer->cursor_pos.line;
+ u32 l2 = buffer->selection_pos.line;
+ sort2_u32(&l1, &l2); // ensure l1 <= l2
+ buffer_dedent_lines(buffer, l1, l2);
+} \ No newline at end of file
diff --git a/command.c b/command.c
index 1d628b0..9cc7ad7 100644
--- a/command.c
+++ b/command.c
@@ -98,17 +98,23 @@ void command_execute(Ted *ted, Command c, i64 argument) {
break;
case CMD_TAB:
- if (ted->replace && ted->active_buffer == &ted->find_buffer) {
+ if (ted->replace && buffer == &ted->find_buffer) {
ted->active_buffer = &ted->replace_buffer;
- buffer_select_all(ted->active_buffer);
- } else {
- buffer_insert_char_at_cursor(buffer, '\t');
+ buffer_select_all(buffer);
+ } else if (buffer) {
+ if (buffer->selection)
+ buffer_indent_selection(buffer);
+ else
+ buffer_insert_char_at_cursor(buffer, '\t');
}
break;
case CMD_BACKTAB:
if (ted->replace && ted->active_buffer == &ted->replace_buffer) {
ted->active_buffer = &ted->find_buffer;
buffer_select_all(ted->active_buffer);
+ } else if (buffer) {
+ if (buffer->selection)
+ buffer_dedent_selection(buffer);
}
break;
case CMD_NEWLINE:
diff --git a/main.c b/main.c
index 790c461..3af8a89 100644
--- a/main.c
+++ b/main.c
@@ -1,5 +1,4 @@
// @TODO:
-// - indent/dedent region
// - highlight matching parentheses
// - split
// - completion
diff --git a/math.c b/math.c
index 37e3e1b..b76c049 100644
--- a/math.c
+++ b/math.c
@@ -109,6 +109,15 @@ static inline u32 max_u32(u32 a, u32 b) {
return a > b ? a : b;
}
+// set *a to the minimum of *a and *b, and *b to the maximum
+static inline void sort2_u32(u32 *a, u32 *b) {
+ u32 x = *a, y = *b;
+ if (x > y) {
+ *a = y;
+ *b = x;
+ }
+}
+
static inline i32 min_i32(i32 a, i32 b) {
return a < b ? a : b;
}