From d8045dc5bcfa4cefc793ea738ed58e57a9727472 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Mon, 15 Dec 2025 14:47:45 +0900 Subject: [PATCH] mruby-bin-mirb: re-indent current line on Enter Before inserting a newline, re-indent the current line to match the expected indent level. This fixes cases where the user typed with incorrect indentation. Co-authored-by: Claude --- .../mruby-bin-mirb/tools/mirb/mirb_editor.c | 73 +++++++++++++++++++ 1 file changed, 73 insertions(+) diff --git a/mrbgems/mruby-bin-mirb/tools/mirb/mirb_editor.c b/mrbgems/mruby-bin-mirb/tools/mirb/mirb_editor.c index 2a44b1ee1..edd0a56db 100644 --- a/mrbgems/mruby-bin-mirb/tools/mirb/mirb_editor.c +++ b/mrbgems/mruby-bin-mirb/tools/mirb/mirb_editor.c @@ -238,6 +238,77 @@ perform_dedent(mirb_buffer *buf) } } + +/* + * Re-indent current line to match expected indent level + * Used before inserting newline to fix any misaligned indentation + */ +static void +reindent_line(mirb_buffer *buf) +{ + mirb_line *line = &buf->lines[buf->cursor_line]; + size_t current_spaces = 0; + int expected_indent = 0; + const char *content; + + /* Count current leading whitespace */ + for (size_t i = 0; i < line->len && (line->data[i] == ' ' || line->data[i] == '\t'); i++) { + current_spaces++; + } + + /* Calculate expected indent from code up to previous line */ + if (buf->cursor_line > 0) { + char *partial = buffer_to_string_upto_line(buf, buf->cursor_line - 1); + if (partial) { + expected_indent = calc_indent_level(partial); + free(partial); + } + } + + /* Check if line content starts with dedenting keyword */ + content = line->data + current_spaces; + if ((strncmp(content, "end", 3) == 0 && + (content[3] == '\0' || content[3] == ' ' || content[3] == '\t' || + content[3] == '.' || content[3] == ')')) || + (strncmp(content, "else", 4) == 0 && + (content[4] == '\0' || content[4] == ' ' || content[4] == '\t')) || + (strncmp(content, "elsif", 5) == 0 && content[5] == ' ') || + (strncmp(content, "when", 4) == 0 && content[4] == ' ') || + (strncmp(content, "rescue", 6) == 0 && + (content[6] == '\0' || content[6] == ' ' || content[6] == '\t')) || + (strncmp(content, "ensure", 6) == 0 && + (content[6] == '\0' || content[6] == ' ' || content[6] == '\t')) || + content[0] == '}') { + if (expected_indent > 0) expected_indent--; + } + + size_t target_spaces = (size_t)(expected_indent * 2); + + /* Adjust indentation if needed */ + if (target_spaces != current_spaces) { + size_t saved_col = buf->cursor_col; + + if (target_spaces > current_spaces) { + /* Need to add spaces */ + size_t add = target_spaces - current_spaces; + buf->cursor_col = 0; + for (size_t i = 0; i < add; i++) { + mirb_buffer_insert_char(buf, ' '); + } + buf->cursor_col = saved_col + add; + } + else { + /* Need to remove spaces */ + size_t remove = current_spaces - target_spaces; + buf->cursor_col = current_spaces; + for (size_t i = 0; i < remove; i++) { + mirb_buffer_delete_back(buf); + } + buf->cursor_col = (saved_col > remove) ? (saved_col - remove) : 0; + } + } +} + /* * Initialize editor */ @@ -636,6 +707,8 @@ handle_key(mirb_editor *ed, int key, mirb_edit_result *result) case MIRB_KEY_ENTER: /* Stop history browsing */ mirb_history_browse_stop(&ed->hist); + /* Re-indent current line before inserting newline */ + reindent_line(&ed->buf); { /* * Smart Enter behavior: