Хотя это кажется разумным запросом, я не считаю, что это возможно.
Существующая реализация встроенного комплекса read
устанавливает среду завершения чтения в довольно базовую конфигурацию перед вызовом readline для обработки ввода -e
.
Вы можете увидеть код в builtins/read.def
, в edit_line
function: она устанавливает rl_attempted_completion_function
в NULL
на время вызова readline
. readline
имеет несколько переопределений завершения, поэтому на 100% очевидно, что это сбрасывает всю среду завершения, но насколько я знаю, это функция, которая используется для реализации программируемого завершения согласно команде complete
.
С некоторыми работами вы, вероятно, можете изменить определение команды read
, чтобы разрешить определенную функцию завершения вместо или в дополнение к стандартной функции завершения имени файла readline. Для этого потребуется нетривиальное понимание внутренних элементов bash, но это был бы разумный проект, если бы вы хотели получить знакомство с этими внутренностями.
Как простая, но менее эффективная альтернатива, вы можете написать свою собственную небольшую утилиту, которая просто принимает одну строку ввода с клавиатуры с readline
и перекликается с ней на стандартный вывод. Затем вызовите read
перенаправляют его стандартный ввод в ваши утилиты:.
read -r < <(my_reader string1 string2 string3)
(Это предполагает, что my_reader
использует свои аргументы командной строки для построения потенциального списка завершения для readline
библиотеки Вы, вероятно, хотите возможность представить запрос а также.)
В документацию readline входит an example of an application, которая выполняет простую настройку; как только вы переводите его из синтаксиса прототипа функции R 0 0 0 0 0 0 0 0 32
Edit: После я снова посмотрел на этот пример, я думал, что это было много ненужных деталей, поэтому я написал следующий пример с меньшим количеством ненужных деталей. Я мог бы загрузить его на GitHub, но теперь он здесь, хотя это почти 100 строк:
#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 one line using readline, and prints it to stdout.\n"
"Returns success if a line was read.\n"
" -p PROMPT Output PROMPT before requesting input.\n"
" -n PROGNAME Set application name to PROGNAME for readline config file\n"
" (Default: %s).\n"
" -f Use filename completion as well as specified completions.\n"
" -h Print this help text and exit.\n"
" -v Print version number and exit.\n"
" COMPLETION word to add to the list of possible completions.\n",
progname);
}
/* Readline really likes globals, so none of its hooks take a 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;
}
/* We use this if we will fall back to 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;
for (;;) {
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;
}
/* The default is stdout, which would interfere with 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;
}
}
Когда вы смотрите «автодополнение внутри сценария», вы используете текстовый редактор, чтобы написать сценарий? I.e., это не в подсказке bash, а внутри vim/emacs/etc.? – chrisaycock
Вы запустили эту команду завершения внутри своего скрипта? Или просто верьте, что он был установлен в среде? (Помогает ли использование 'complete -E -W ....'?Документация заставляет это звучать, как порядок может иметь значение, хотя, вероятно, это не так.) –
@chrisaycock Я думаю, что OP означает, что 'read -e' запускается из сценария не использует это завершение. –