From 86e6ba23fb1cf5ab6c8484ba8f689d5cdcdd34fa Mon Sep 17 00:00:00 2001 From: Paul Mulders Date: Fri, 24 Apr 2026 13:15:11 +0200 Subject: [PATCH] allow setting the completions menu sorter --- include/isocline.h | 11 +++++++++++ src/completions.c | 13 ++++++++++--- test/example.c | 3 +++ 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/include/isocline.h b/include/isocline.h index 9843334..f36ad0a 100644 --- a/include/isocline.h +++ b/include/isocline.h @@ -156,6 +156,17 @@ struct ic_completion_env_s; /// A completion environment typedef struct ic_completion_env_s ic_completion_env_t; +/// A comparator function passed to qsort in order to sort the completions menu. +typedef int (ic_sorter_fun_t)(const void* a, const void* b); + +/// Set the function used for sorting the completion menu entries. Accepts NULL +/// to avoid sorting at all, e.g. if the user needs complex sorting that would +/// already be done on the application side. +/// @param sorter The sorter function +/// The initial sorter uses case insensitive shortlex. +void ic_set_default_sorter( ic_sorter_fun_t* sorter); + + /// A completion callback that is called by isocline when tab is pressed. /// It is passed a completion environment (containing the current input and the current cursor position), /// the current input up-to the cursor (`prefix`) diff --git a/src/completions.c b/src/completions.c index 8546b16..ad0412f 100644 --- a/src/completions.c +++ b/src/completions.c @@ -31,6 +31,7 @@ struct completions_s { ic_completer_fun_t* completer; void* completer_arg; ssize_t completer_max; + ic_sorter_fun_t* sorter; ssize_t count; ssize_t len; completion_t* elems; @@ -38,12 +39,14 @@ struct completions_s { }; static void default_filename_completer( ic_completion_env_t* cenv, const char* prefix ); +static int default_ishortlex_sorter(const void* p1, const void* p2); ic_private completions_t* completions_new(alloc_t* mem) { completions_t* cms = mem_zalloc_tp(mem, completions_t); if (cms == NULL) return NULL; cms->mem = mem; cms->completer = &default_filename_completer; + cms->sorter = &default_ishortlex_sorter; return cms; } @@ -193,8 +196,12 @@ ic_private ssize_t completions_apply( completions_t* cms, ssize_t index, stringb return completion_apply( cm, sbuf, pos ); } +ic_public void ic_set_default_sorter(ic_sorter_fun_t* sorter) { + ic_env_t* env = ic_get_env(); if (env == NULL) return; + env->completions->sorter = sorter; +} -static int completion_compare(const void* p1, const void* p2) { +static int default_ishortlex_sorter(const void* p1, const void* p2) { if (p1 == NULL || p2 == NULL) return 0; const completion_t* cm1 = (const completion_t*)p1; const completion_t* cm2 = (const completion_t*)p2; @@ -202,8 +209,8 @@ static int completion_compare(const void* p1, const void* p2) { } ic_private void completions_sort(completions_t* cms) { - if (cms->count <= 0) return; - qsort(cms->elems, to_size_t(cms->count), sizeof(cms->elems[0]), &completion_compare); + if (cms->count <= 0 || cms->sorter == NULL) return; + qsort(cms->elems, to_size_t(cms->count), sizeof(cms->elems[0]), cms->sorter); } #define IC_MAX_PREFIX (256) diff --git a/test/example.c b/test/example.c index 3f33574..50086e8 100644 --- a/test/example.c +++ b/test/example.c @@ -47,6 +47,9 @@ int main(int argc, char** argv) // enable syntax highlighting with a highlight function ic_set_default_highlighter(highlighter, NULL); + // completion menu sorting is enabled by default (case insensitive shortlex) + // ic_set_default_sorter(NULL); + // try to auto complete after a completion as long as the completion is unique ic_enable_auto_tab(true );