在尝试了一个我知道有效的自定义完成脚本(我每天都使用它)并遇到相同的问题(在与您的类似的情况下安装它时)后,我决定窥探 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-hacking 长胡子可能知道。因此,使用read
内置函数执行此操作可能只是被硬编码为禁用。
编辑:关于此的更多信息:read
在 bash-2.05a 和 bash-2.05b 之间发生的用于停止内置完成的包装代码。bash-2.05b/CWRU/changelog
我在那个版本的文件中找到了这个注释:
- edit_line(由 read -e 调用)现在只是通过将 rl_attempted_completion_function 设置为 NULL 来完成 readline 的文件名完成,因为例如,对行上的第一个单词执行命令完成并不是很有用
我认为这是一个遗留的疏忽,而且由于可编程完成已经走了很长一段路,你所做的事情很有用。也许你可以要求他们重新添加它,或者只是自己修补它,如果这对你正在做的事情是可行的。
恐怕除了您到目前为止提出的解决方案之外,我没有其他解决方案,但至少我们知道为什么它不适用于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
并发生超时,这不再需要。如果您要向 Chet 发送一些东西,您可能希望首先删除整个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 必须以某种方式分发或以某种方式提供,无论人们将使用您的脚本...