From 23c49ad026daae717291d87e85e3aecd5c84e2b9 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Fri, 12 Dec 2025 23:43:41 +0900 Subject: [PATCH] mruby-bin-mirb: show incrementing line numbers in multi-line prompts Previously, all continuation lines showed the same line number (e.g., "1*" for every line). Now each line shows its actual line number: 1> class Foo 2* def bar 3* end 4* end Add mirb_editor_set_prompt_format() which accepts printf-style format strings (e.g., "%d> ", "%d* ") and calculates the correct prompt length for each line to ensure proper cursor positioning. Co-authored-by: Claude --- mrbgems/mruby-bin-mirb/tools/mirb/mirb.c | 5 +- .../mruby-bin-mirb/tools/mirb/mirb_editor.c | 61 +++++++++++++++++-- .../mruby-bin-mirb/tools/mirb/mirb_editor.h | 16 ++++- 3 files changed, 71 insertions(+), 11 deletions(-) diff --git a/mrbgems/mruby-bin-mirb/tools/mirb/mirb.c b/mrbgems/mruby-bin-mirb/tools/mirb/mirb.c index 6186d9f8f..2360495c7 100644 --- a/mrbgems/mruby-bin-mirb/tools/mirb/mirb.c +++ b/mrbgems/mruby-bin-mirb/tools/mirb/mirb.c @@ -557,12 +557,9 @@ main(int argc, char **argv) if (use_editor && mirb_editor_supported(&editor)) { /* Use multi-line editor */ char *input; - char prompt[16], prompt_cont[16]; mirb_edit_result res; - snprintf(prompt, sizeof(prompt), "%d> ", line_num); - snprintf(prompt_cont, sizeof(prompt_cont), "%d* ", line_num); - mirb_editor_set_prompts(&editor, prompt, prompt_cont); + mirb_editor_set_prompt_format(&editor, "%d> ", "%d* ", line_num); res = mirb_editor_read(&editor, &input); diff --git a/mrbgems/mruby-bin-mirb/tools/mirb/mirb_editor.c b/mrbgems/mruby-bin-mirb/tools/mirb/mirb_editor.c index 628947c5e..85f9e765c 100644 --- a/mrbgems/mruby-bin-mirb/tools/mirb/mirb_editor.c +++ b/mrbgems/mruby-bin-mirb/tools/mirb/mirb_editor.c @@ -202,6 +202,9 @@ mirb_editor_init(mirb_editor *ed) ed->prompt_cont = "* "; ed->prompt_len = 2; ed->prompt_cont_len = 2; + ed->prompt_fmt = NULL; + ed->prompt_cont_fmt = NULL; + ed->line_num_base = 1; ed->use_color = FALSE; ed->initialized = TRUE; @@ -223,7 +226,7 @@ mirb_editor_cleanup(mirb_editor *ed) } /* - * Set prompts + * Set prompts (fixed strings) */ void mirb_editor_set_prompts(mirb_editor *ed, const char *prompt, const char *prompt_cont) @@ -232,6 +235,23 @@ mirb_editor_set_prompts(mirb_editor *ed, const char *prompt, const char *prompt_ ed->prompt_cont = prompt_cont; ed->prompt_len = strlen(prompt); ed->prompt_cont_len = strlen(prompt_cont); + ed->prompt_fmt = NULL; + ed->prompt_cont_fmt = NULL; +} + +/* + * Set prompt format strings for line-numbered prompts + */ +void +mirb_editor_set_prompt_format(mirb_editor *ed, const char *prompt_fmt, + const char *prompt_cont_fmt, int line_num) +{ + ed->prompt_fmt = prompt_fmt; + ed->prompt_cont_fmt = prompt_cont_fmt; + ed->line_num_base = line_num; + /* Estimate prompt length (assuming line numbers up to 999) */ + ed->prompt_len = strlen(prompt_fmt) + 2; /* %d -> up to 3 digits, minus 2 for %d */ + ed->prompt_cont_len = strlen(prompt_cont_fmt) + 2; } /* @@ -262,20 +282,50 @@ mirb_editor_supported(mirb_editor *ed) return ed->term.supported; } +/* + * Calculate prompt length for given line + */ +static size_t +calc_prompt_len(mirb_editor *ed, size_t line_idx) +{ + if (ed->prompt_fmt != NULL) { + /* Format string: calculate actual length */ + int line_num = ed->line_num_base + (int)line_idx; + const char *fmt = (line_idx == 0) ? ed->prompt_fmt : ed->prompt_cont_fmt; + return (size_t)snprintf(NULL, 0, fmt, line_num); + } + else { + /* Fixed prompt string */ + return (line_idx == 0) ? ed->prompt_len : ed->prompt_cont_len; + } +} + /* * Print prompt for given line */ static void print_prompt(mirb_editor *ed, size_t line_idx) { - const char *p = (line_idx == 0) ? ed->prompt : ed->prompt_cont; + int line_num = ed->line_num_base + (int)line_idx; if (ed->use_color) { - printf("%s%s%s", COLOR_GREEN, p, COLOR_RESET); + printf("%s", COLOR_GREEN); + } + + if (ed->prompt_fmt != NULL) { + /* Use format string with line number */ + const char *fmt = (line_idx == 0) ? ed->prompt_fmt : ed->prompt_cont_fmt; + printf(fmt, line_num); } else { + /* Use fixed prompt string */ + const char *p = (line_idx == 0) ? ed->prompt : ed->prompt_cont; printf("%s", p); } + + if (ed->use_color) { + printf("%s", COLOR_RESET); + } } /* @@ -289,7 +339,6 @@ print_prompt(mirb_editor *ed, size_t line_idx) static void refresh_display(mirb_editor *ed) { - size_t prompt_len; size_t lines_to_go_up; /* Calculate how many lines up we need to go to reach start of input */ @@ -323,8 +372,8 @@ refresh_display(mirb_editor *ed) mirb_term_cursor_up((int)lines_up_from_end); } - /* Position column on cursor line */ - prompt_len = (ed->buf.cursor_line == 0) ? ed->prompt_len : ed->prompt_cont_len; + /* Position column on cursor line (calculate actual prompt length) */ + size_t prompt_len = calc_prompt_len(ed, ed->buf.cursor_line); mirb_term_cursor_col((int)(prompt_len + ed->buf.cursor_col + 1)); /* Update tracking */ diff --git a/mrbgems/mruby-bin-mirb/tools/mirb/mirb_editor.h b/mrbgems/mruby-bin-mirb/tools/mirb/mirb_editor.h index 2ccc8f229..40327111e 100644 --- a/mrbgems/mruby-bin-mirb/tools/mirb/mirb_editor.h +++ b/mrbgems/mruby-bin-mirb/tools/mirb/mirb_editor.h @@ -42,6 +42,10 @@ typedef struct mirb_editor { size_t prompt_len; /* length of primary prompt */ size_t prompt_cont_len; /* length of continuation prompt */ + const char *prompt_fmt; /* prompt format string (e.g., "%d> ") */ + const char *prompt_cont_fmt;/* continuation format (e.g., "%d* ") */ + int line_num_base; /* starting line number for prompts */ + mirb_check_complete_fn *check_complete; /* completion checker */ void *check_complete_data; /* user data for checker */ @@ -64,12 +68,22 @@ mrb_bool mirb_editor_init(mirb_editor *ed); void mirb_editor_cleanup(mirb_editor *ed); /* - * Set prompts + * Set prompts (fixed strings) */ void mirb_editor_set_prompts(mirb_editor *ed, const char *prompt, const char *prompt_cont); +/* + * Set prompt format strings for line-numbered prompts + * Format strings should contain %d for line number (e.g., "%d> ", "%d* ") + * line_num is the starting line number + */ +void mirb_editor_set_prompt_format(mirb_editor *ed, + const char *prompt_fmt, + const char *prompt_cont_fmt, + int line_num); + /* * Set completion checker callback */