readline - Changing tab-completion for read builtin in bash -


the current tab-completion while "read -e" active in bash seems matching filenames:

read -e [[tabtab]] abc.txt  bcd.txt  cde.txt   

i want completion set of strings defined me, while file/dir/hostname-completion etc. should deactivated duration of "read -e".

outside of script

complete -w 'string1 string2 string3' -e 

works well, cant kind of completion work inside script while using "read -e".

although seems reasonable request, don't believe possible.

the existing implementation of read builtin sets readline completion environment basic configuration before calling readline handle -e input.

you can see code in builtins/read.def, in edit_line function: sets rl_attempted_completion_function null duration of call readline. readline has several completion overrides, it's not 100% obvious resets entire completion environment, far know function used implement programmable completion per complete command.

with work, modify definition of read command allow specific completion function instead of or in addition readline standard filename completion function. require non-trivial understanding of bash internals, reasonable project if wanted gain familiarity internals.

as simpler less efficient alternative, write own little utility accepts 1 line of keyboard input readline , echoes stdout. invoke read redirecting stdin utility:

read -r < <(my_reader string1 string2 string3) 

(that assumes my_reader uses command-line arguments construct potential completion list readline library. you'd want option present prompt well.)

the readline documentation includes an example of application simple custom completion; once translate k&r function prototype syntax, might pretty easy adapt needs.


edit: after looked @ example again, thought had lot of unnecessary details, wrote following example fewer unnecessary details. might upload github, it's here though it's 100 lines:

#include <stdbool.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h>  #include <readline/readline.h>  static void version(const char* progname) {   fprintf(stderr, "%s 0.1\n", progname); } static void usage(const char* progname) {   fprintf(stderr, "usage: %s [-fhv] [-p prompt] [-n progname] [completion...]\n", progname);   fprintf(stderr,           "reads 1 line using readline, , prints stdout.\n"           "returns success if line read.\n"           "  -p prompt    output prompt before requesting input.\n"           "  -n progname  set application name progname readline config file\n"           "               (default: %s).\n"           "  -f           use filename completion specified completions.\n"           "  -h           print text , exit.\n"           "  -v           print version number , exit.\n"           "  completion   word add list of possible completions.\n",           progname); }  /* readline likes globals, none of hooks take context parameter. */ static char** completions = null; static char* generate_next_completion(const char* text, int state) {   static int index = 0;   if (state == 0) index = 0; /* reset index if we're starting */   size_t textlen = strlen(text);   while (completions[index++])     if (strncmp(completions[index - 1], text, textlen) == 0)       return strdup(completions[index - 1]);   return null; }  /* use if fall filename completion */ static char** generate_completions(const char* text, int start, int end) {   return rl_completion_matches(text, generate_next_completion); }  int main (int argc, char **argv) {   const char* prompt = "";   const char* progname = strrchr(argv[0], '/');   progname = progname ? progname + 1 : argv[0];   rl_readline_name = progname;    bool use_file_completion = false;    (;;) {     int opt = getopt(argc, argv, "+fp:n:hv");     switch (opt) {       case -1:  break;       case 'f': use_file_completion = true; continue;       case 'p': prompt = optarg; continue;       case 'n': rl_readline_name = optarg; continue;       case 'h': usage(progname); return 0;       case 'v': version(progname); return 0;       default:  usage(progname); return 2;     }     break;   }    /* default stdout, interfere capturing output. */   rl_outstream = stderr;    completions = argv + optind;   rl_completion_entry_function = rl_filename_completion_function;   if (*completions) {     if (use_file_completion)       rl_attempted_completion_function = generate_completions;      else       rl_completion_entry_function = generate_next_completion;   } else {     /* no specified strings */      if (!use_file_completion)       rl_inhibit_completion = true;    }    char* line = readline(prompt);    if (line) {     puts(line);     free(line);     return 0;   } else {     fputc('\n', rl_outstream);     return 1;   } } 

Comments

Popular posts from this blog

ruby - Trying to change last to "x"s to 23 -

jquery - Clone last and append item to closest class -

css - Can I use the :after pseudo-element on an input field? -