Попробовав собственный сценарий завершения, который, как я знаю, работает (я использую его каждый день), и столкнувшись с той же проблемой (когда он настраивал его, как ваш), я решил просмотреть исходный код bash 4.1, и нашел этот интересный блок в bash-4.1/builtins/read.def:edit_line()
:
old_attempted_completion_function = rl_attempted_completion_function;
rl_attempted_completion_function = (rl_completion_func_t *)NULL;
if (itext)
{
old_startup_hook = rl_startup_hook;
rl_startup_hook = set_itext;
deftext = itext;
}
ret = readline (p);
rl_attempted_completion_function = old_attempted_completion_function;
old_attempted_completion_function = (rl_completion_func_t *)NULL;
Похоже, что перед вызовом readline()
он сбрасывает функцию завершения до нуля по какой-то причине, о которой может знать только длинная борода, взламывающая bash. Таким образом, выполнение этого с помощью встроенной функции read
может быть просто жестко запрограммировано для отключения.
РЕДАКТИРОВАТЬ. Еще кое-что: код упаковки для остановки завершения во встроенной read
произошел между bash-2.05a и bash-2.05b. Я нашел эту заметку в bash-2.05b/CWRU/changelog
файле этой версии:
- edit_line (вызывается read -e) теперь просто выполняет завершение имени файла readline, устанавливая для rl_attempted_completion_function значение NULL, поскольку, например, выполнение команды для первого слова в строке было не очень полезно
Я думаю, что это устаревший надзор, и, поскольку программируемое завершение прошло долгий путь, то, что вы делаете, полезно. Может быть, вы можете попросить их добавить его обратно или просто исправить самостоятельно, если это возможно для того, что вы делаете.
Боюсь, у меня нет другого решения, кроме того, что вы придумали до сих пор, но, по крайней мере, мы знаем, почему оно не работает с read
.
EDIT2: вот патч, который я только что протестировал, кажется, "работает". Проходит все модульные и reg-тесты и показывает эти выходные данные вашего скрипта при запуске с использованием исправленного bash, как вы и ожидали:
$ ./tabcompl.sh
waiting for commands
-> **<TAB>**
TAB hit output should these this when words you
->
Как вы увидите, я просто закомментировал эти 4 строки и некоторый код таймера для сброса rl_attempted_completion_function
, когда указан read -t
и наступает тайм-аут, который больше не нужен. Если вы собираетесь что-то послать Чету, вы можете сначала удалить весь rl_attempted_completion_function
мусор, но это, по крайней мере, позволит вашему скрипту вести себя должным образом.
Пластырь:
--- bash-4.1/builtins/read.def 2009-10-09 00:35:46.000000000 +0900
+++ bash-4.1-patched/builtins/read.def 2011-01-20 07:14:43.000000000 +0900
@@ -394,10 +394,12 @@
}
old_alrm = set_signal_handler (SIGALRM, sigalrm);
add_unwind_protect (reset_alarm, (char *)NULL);
+/*
#if defined (READLINE)
if (edit)
add_unwind_protect (reset_attempted_completion_function, (char *)NULL);
#endif
+*/
falarm (tmsec, tmusec);
}
@@ -914,8 +916,10 @@
if (bash_readline_initialized == 0)
initialize_readline ();
+/*
old_attempted_completion_function = rl_attempted_completion_function;
rl_attempted_completion_function = (rl_completion_func_t *)NULL;
+*/
if (itext)
{
old_startup_hook = rl_startup_hook;
@@ -923,8 +927,10 @@
deftext = itext;
}
ret = readline (p);
+/*
rl_attempted_completion_function = old_attempted_completion_function;
old_attempted_completion_function = (rl_completion_func_t *)NULL;
+*/
if (ret == 0)
return ret;
Имейте в виду, что пропатченный bash должен быть каким-то образом распространен или доступен везде, где люди будут использовать ваш скрипт ...
person
Sdaz MacSkibbons
schedule
19.01.2011
-D
complete
. Какую версию bash вы используете? - person sorpigal   schedule 18.01.2011