help-bash
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Help-bash] programmable completions via compgen -F


From: Муравьев Александр
Subject: [Help-bash] programmable completions via compgen -F
Date: Wed, 9 Oct 2019 09:31:14 +0300
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.8.0

Hello!

I am unable to use "compgen -F" and made a patch to make it works.

I explored source code and noted that programmable completion uses "pcomp_line" buffer, which is assigned to rl_line_buffer when you press <TAB> in bash and programmable completion activates (inside programmable_completions method in pcomplete.c). However, gen_compspec_completion mathod called by compgen realization method just assign pcomp_line to NULL. I made temporary buffer, which imitates line buffer from readline library (rl_line_buffer) and assign pcomp_line to it. That is my patch. Please, tell me how to improve it (if it is ugly).

Hope that it will be possible to use "compgen -F" in new BASH version.

My BASH version is "5.0.11(11)-release", OS "Ubuntu 18.04.3 LTS", machine "x86_64".

Here is patch:

diff --git a/builtins/complete.def b/builtins/complete.def
index 76b3eedd..e253fc60 100644
--- a/builtins/complete.def
+++ b/builtins/complete.def
@@ -709,6 +709,8 @@ compgen_builtin (list)
   char *word, **matches;
   char *old_line;
   int old_ind;
+  char pcomp_local[4096];
+  char *last_word = NULL;

   if (list == 0)
     return (EXECUTION_SUCCESS);
@@ -753,9 +755,55 @@ compgen_builtin (list)
   /* probably don't have to save these, just being safe */
   old_line = pcomp_line;
   old_ind = pcomp_ind;
-  pcomp_line = (char *)NULL;
-  pcomp_ind = 0;
-  sl = gen_compspec_completions (cs, "compgen", word, 0, 0, 0);
+
+  {
+      WORD_LIST *cword = list;
+      if (cword && cword->word
+          && strlen(cword->word->word) > 0)
+      {
+          last_word = cword->word->word;
+      }
+      *pcomp_local = '\0';
+      if (cword && cword->word)
+      {
+          strcat(pcomp_local, cword->word->word);
+          if (strlen(cword->word->word) > 0)
+          {
+              last_word = cword->word->word;
+          }
+          cword = cword->next;
+      }
+      while (cword)
+      {
+          if (strlen(cword->word->word) > 0)
+          {
+              last_word = cword->word->word;
+          }
+          strcat(pcomp_local, " ");
+          strcat(pcomp_local, cword->word->word);
+          cword = cword->next;
+      }
+  }
+  pcomp_line = pcomp_local;
+  pcomp_ind = strlen(pcomp_local);
+
+  sl = gen_compspec_completions (cs, "compgen", word, 0, pcomp_ind, 0);
+  if (sl != 0 && sl->list_len == 1)
+  {
+      int last_word_len = strlen(last_word);
+      int strcmp_complete_res = strncmp(*(sl->list), last_word,
+                                        last_word_len);
+      if (0 == strcmp_complete_res
+            && strlen(*(sl->list)) == last_word_len + 1
+            && (*(sl->list))[last_word_len] == ' ')
+      {
+        /* User already enter this word. Go to next one. */
+        strcat(pcomp_local, " ");
+        pcomp_ind++;
+        sl = gen_compspec_completions (cs, "compgen", word, 0, pcomp_ind, 0);
+      }
+  }
+
   pcomp_line = old_line;
   pcomp_ind = old_ind;




reply via email to

[Prev in Thread] Current Thread [Next in Thread]