From c23536daf95db4fd46cb91b1549a38d3456e78ca Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Mon, 23 Feb 2026 09:59:02 +0900 Subject: [PATCH] mirb_completion.c: unify global completion contexts Replace three separate global contexts (g_readline_ctx, g_linenoise_ctx, g_editor_ctx) with a single g_ctx and shared init_completion_ctx() helper. Consolidate the three identical cleanup functions into mirb_cleanup_completion(). Co-authored-by: Claude --- mrbgems/mruby-bin-mirb/tools/mirb/mirb.c | 2 +- .../tools/mirb/mirb_completion.c | 120 +++++++----------- .../tools/mirb/mirb_completion.h | 10 +- 3 files changed, 53 insertions(+), 79 deletions(-) diff --git a/mrbgems/mruby-bin-mirb/tools/mirb/mirb.c b/mrbgems/mruby-bin-mirb/tools/mirb/mirb.c index 475c36deb..a1699c92c 100644 --- a/mrbgems/mruby-bin-mirb/tools/mirb/mirb.c +++ b/mrbgems/mruby-bin-mirb/tools/mirb/mirb.c @@ -781,7 +781,7 @@ cleanup: } if (cxt) mrb_ccontext_free(mrb, cxt); if (use_editor) { - mirb_cleanup_editor_completion(); + mirb_cleanup_completion(); mirb_editor_cleanup(&editor); } mrb_close(mrb); diff --git a/mrbgems/mruby-bin-mirb/tools/mirb/mirb_completion.c b/mrbgems/mruby-bin-mirb/tools/mirb/mirb_completion.c index e889af07b..f2c92c2f0 100644 --- a/mrbgems/mruby-bin-mirb/tools/mirb/mirb_completion.c +++ b/mrbgems/mruby-bin-mirb/tools/mirb/mirb_completion.c @@ -569,6 +569,32 @@ mirb_generate_completions(mirb_completion_ctx *ctx, const char *line, int cursor } } +/* ============================================================ + * Shared Completion Context + * ============================================================ */ + +static mirb_completion_ctx *g_ctx = NULL; + +static mrb_bool +init_completion_ctx(mrb_state *mrb, mrb_ccontext *cxt) +{ + if (g_ctx) return TRUE; + g_ctx = (mirb_completion_ctx*)malloc(sizeof(mirb_completion_ctx)); + if (!g_ctx) return FALSE; + mirb_completion_init(g_ctx, mrb, cxt); + return TRUE; +} + +void +mirb_cleanup_completion(void) +{ + if (g_ctx) { + mirb_completion_free(g_ctx); + free(g_ctx); + g_ctx = NULL; + } +} + /* ============================================================ * Readline/Libedit Adapter * ============================================================ */ @@ -576,8 +602,6 @@ mirb_generate_completions(mirb_completion_ctx *ctx, const char *line, int cursor #ifdef MRB_USE_READLINE #ifndef MRB_USE_LINENOISE -static mirb_completion_ctx *g_readline_ctx = NULL; - static char * mirb_readline_generator(const char *text, int state) { @@ -585,18 +609,18 @@ mirb_readline_generator(const char *text, int state) /* state == 0: first call, generate completions */ if (state == 0) { - mirb_completion_free(g_readline_ctx); + mirb_completion_free(g_ctx); /* Generate completions based on full line */ - mirb_generate_completions(g_readline_ctx, rl_line_buffer, rl_point); + mirb_generate_completions(g_ctx, rl_line_buffer, rl_point); - g_readline_ctx->current_index = 0; + g_ctx->current_index = 0; } /* Return next completion or NULL when done */ - if (g_readline_ctx->current_index < g_readline_ctx->completion_count) { - char *completion = g_readline_ctx->completions[g_readline_ctx->current_index]; - g_readline_ctx->current_index++; + if (g_ctx->current_index < g_ctx->completion_count) { + char *completion = g_ctx->completions[g_ctx->current_index]; + g_ctx->current_index++; /* readline will free this, so duplicate */ return strdup(completion); @@ -621,11 +645,7 @@ mirb_readline_completion(const char *text, int start, int end) void mirb_setup_readline_completion(mrb_state *mrb, mrb_ccontext *cxt) { - /* Initialize global context */ - g_readline_ctx = (mirb_completion_ctx*)malloc(sizeof(mirb_completion_ctx)); - if (!g_readline_ctx) return; - - mirb_completion_init(g_readline_ctx, mrb, cxt); + if (!init_completion_ctx(mrb, cxt)) return; /* Set completion function */ rl_attempted_completion_function = mirb_readline_completion; @@ -635,16 +655,6 @@ mirb_setup_readline_completion(mrb_state *mrb, mrb_ccontext *cxt) rl_completer_word_break_characters = " \t\n\"\\'`@$><=;|&{(."; } -void -mirb_cleanup_readline_completion(void) -{ - if (g_readline_ctx) { - mirb_completion_free(g_readline_ctx); - free(g_readline_ctx); - g_readline_ctx = NULL; - } -} - #endif #endif @@ -654,8 +664,6 @@ mirb_cleanup_readline_completion(void) #ifdef MRB_USE_LINENOISE -static mirb_completion_ctx *g_linenoise_ctx = NULL; - static void mirb_linenoise_completion(const char *buf, linenoiseCompletions *lc) { @@ -664,15 +672,15 @@ mirb_linenoise_completion(const char *buf, linenoiseCompletions *lc) char completion_line[1024]; /* Clear previous completions */ - mirb_completion_free(g_linenoise_ctx); + mirb_completion_free(g_ctx); /* Generate completions */ - mirb_generate_completions(g_linenoise_ctx, buf, cursor_pos); + mirb_generate_completions(g_ctx, buf, cursor_pos); /* Add each completion to linenoise */ - for (i = 0; i < g_linenoise_ctx->completion_count; i++) { + for (i = 0; i < g_ctx->completion_count; i++) { /* Need to build full line with completion */ - prefix_start = cursor_pos - g_linenoise_ctx->prefix_len; + prefix_start = cursor_pos - g_ctx->prefix_len; /* Copy line up to prefix */ if (prefix_start > 0) { @@ -680,7 +688,7 @@ mirb_linenoise_completion(const char *buf, linenoiseCompletions *lc) } /* Add completion */ - strcpy(completion_line + prefix_start, g_linenoise_ctx->completions[i]); + strcpy(completion_line + prefix_start, g_ctx->completions[i]); linenoiseAddCompletion(lc, completion_line); } @@ -689,52 +697,22 @@ mirb_linenoise_completion(const char *buf, linenoiseCompletions *lc) void mirb_setup_linenoise_completion(mrb_state *mrb, mrb_ccontext *cxt) { - /* Initialize global context */ - g_linenoise_ctx = (mirb_completion_ctx*)malloc(sizeof(mirb_completion_ctx)); - if (!g_linenoise_ctx) return; - - mirb_completion_init(g_linenoise_ctx, mrb, cxt); + if (!init_completion_ctx(mrb, cxt)) return; /* Set completion callback */ linenoiseSetCompletionCallback(mirb_linenoise_completion); } -void -mirb_cleanup_linenoise_completion(void) -{ - if (g_linenoise_ctx) { - mirb_completion_free(g_linenoise_ctx); - free(g_linenoise_ctx); - g_linenoise_ctx = NULL; - } -} - #endif /* ============================================================ * Custom Editor Adapter * ============================================================ */ -static mirb_completion_ctx *g_editor_ctx = NULL; - void mirb_setup_editor_completion(mrb_state *mrb, mrb_ccontext *cxt) { - /* Initialize global context */ - g_editor_ctx = (mirb_completion_ctx*)malloc(sizeof(mirb_completion_ctx)); - if (!g_editor_ctx) return; - - mirb_completion_init(g_editor_ctx, mrb, cxt); -} - -void -mirb_cleanup_editor_completion(void) -{ - if (g_editor_ctx) { - mirb_completion_free(g_editor_ctx); - free(g_editor_ctx); - g_editor_ctx = NULL; - } + init_completion_ctx(mrb, cxt); } int @@ -743,35 +721,35 @@ mirb_get_completions(const char *line, int cursor_pos, { int i; - if (!g_editor_ctx) { + if (!g_ctx) { *completions_out = NULL; *prefix_len_out = 0; return 0; } /* Clear previous completions */ - mirb_completion_free(g_editor_ctx); + mirb_completion_free(g_ctx); /* Generate completions */ - mirb_generate_completions(g_editor_ctx, line, cursor_pos); + mirb_generate_completions(g_ctx, line, cursor_pos); /* Return results */ - *prefix_len_out = g_editor_ctx->prefix_len; + *prefix_len_out = g_ctx->prefix_len; - if (g_editor_ctx->completion_count == 0) { + if (g_ctx->completion_count == 0) { *completions_out = NULL; return 0; } /* Copy completions (caller will free) */ - *completions_out = (char**)malloc(g_editor_ctx->completion_count * sizeof(char*)); + *completions_out = (char**)malloc(g_ctx->completion_count * sizeof(char*)); if (!*completions_out) return 0; - for (i = 0; i < g_editor_ctx->completion_count; i++) { - (*completions_out)[i] = strdup(g_editor_ctx->completions[i]); + for (i = 0; i < g_ctx->completion_count; i++) { + (*completions_out)[i] = strdup(g_ctx->completions[i]); } - return g_editor_ctx->completion_count; + return g_ctx->completion_count; } void diff --git a/mrbgems/mruby-bin-mirb/tools/mirb/mirb_completion.h b/mrbgems/mruby-bin-mirb/tools/mirb/mirb_completion.h index 0fc4d423b..1e462b70f 100644 --- a/mrbgems/mruby-bin-mirb/tools/mirb/mirb_completion.h +++ b/mrbgems/mruby-bin-mirb/tools/mirb/mirb_completion.h @@ -100,27 +100,23 @@ mrb_value mirb_eval_receiver(mrb_state *mrb, const char *receiver_expr, mrb_ccon /* Check if in file completion context */ mrb_bool mirb_in_file_context(const char *line, int quote_pos); +/* Cleanup completion context (shared by all adapters) */ +void mirb_cleanup_completion(void); + /* Readline/Libedit adapter setup */ #ifdef MRB_USE_READLINE #ifndef MRB_USE_LINENOISE - void mirb_setup_readline_completion(mrb_state *mrb, mrb_ccontext *cxt); -void mirb_cleanup_readline_completion(void); - #endif #endif /* Linenoise adapter setup */ #ifdef MRB_USE_LINENOISE - void mirb_setup_linenoise_completion(mrb_state *mrb, mrb_ccontext *cxt); -void mirb_cleanup_linenoise_completion(void); - #endif /* Custom editor adapter */ void mirb_setup_editor_completion(mrb_state *mrb, mrb_ccontext *cxt); -void mirb_cleanup_editor_completion(void); /* Get completions for custom editor - returns number of completions */ int mirb_get_completions(const char *line, int cursor_pos,