庆典和readline:tab完成在用户输入的循环? [英] bash and readline: tab completion in a user input loop?

查看:121
本文介绍了庆典和readline:tab完成在用户输入的循环?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在做一个bash脚本presents命令行给用户。

I'm making a bash script which presents a command line to the user.

在CLI code是因为这样:

The cli code is as this:

#!/bin/bash

cmd1() {
    echo $FUNCNAME: "$@"
}

cmd2() {
    echo $FUNCNAME: "$@"
}

cmdN() {
    echo $FUNCNAME: "$@"
}

__complete() {
    echo $allowed_commands
}

shopt -qs extglob

fn_hide_prefix='__'
allowed_commands="$(declare -f | sed -ne '/^'$fn_hide_prefix'.* ()/!s/ ().*//p' | tr '\n' ' ')"

complete -D -W "this should output these words when you hit TAB"

echo "waiting for commands"
while read -ep"-> "; do
    history -s $REPLY
    case "$REPLY" in
        @(${allowed_commands// /|})?(+([[:space:]])*)) $REPLY ;;
        \?) __complete ;;
        *) echo "invalid command: $REPLY" ;;
    esac
done

澄清:在Bash中制造和测试的 4

Clarification: made and tested in Bash 4

所以,读-e给出readline的能力,我可以调用命令,编辑输入线等的我不能以任何方式做什么是要有的readline的标签完成工作!

So, "read -e" gives readline capabilities, i can recall commands, edit the input line, etc. What i cannot do in any way is to have readline's tab completion to work!!

我试过两件事情:


  1. 那应该怎么做假想:使用bash的内建完全和compgen,这是上报工作<一个href=\"http://www.linuxquestions.org/questions/programming-9/bash-script-using-tab-complete-473112/#post2609565\">here的更新:它不是报道脚本工作

<一个href=\"http://www.linuxquestions.org/questions/linux-general-1/commandline-autocompletion-for-my-shell-script-668388/\">This丑陋的解决办法

使用完整的剧本时,里面为什么没有的ReadLine行为是否正确?它的工作原理,当我在交互模式下尝试从庆典...

Why doesn't readline behave correctly when using "complete" inside the script? it works when i try it from bash in interactive mode...

推荐答案

试图自定义完成剧本之后,我的知道的工作(我每天都使用它),并运行到同一个问题(调整时它类似于你),我决定通过在bash 4.1源窥探,并在发现这个有趣块的bash-4.1 /内建/ read.def:edit_line()

After trying a custom completion script that I know works (I use it every day) and running into the same issue (when rigging it up similar to yours), I decided to snoop through the bash 4.1 source, and found this interesting block in 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()被调用,它完成的功能重置为null出于某种原因,只有一个bash黑客长胡子可能知道。因此,在这样的内建可能仅仅是硬codeD被禁用。

It appears that before readline() is called, it resets the completion function to null for some reason that only a bash-hacking long beard might know. Thus, doing this with the read builtin may simply be hard-coded to be disabled.

修改:一些更多这样的:包装code停止在完成内置的bash-2.05a之间发生的与的bash-2.05b以上。我发现在该版本的的bash-2.05b以上/凯斯西储大学/变化文件本说明:

EDIT: Some more on this: The wrapping code to stop completion in the read builtin occurred between bash-2.05a and bash-2.05b. I found this note in that version's bash-2.05b/CWRU/changelog file:


      
  • edit_line(由read -e调用)现在只是做的readline的文件名完成,通过设置rl_attempted_completion_function为NULL,因为例如,做命令完成上线的第一个字是不是真的有用

  •   

我认为这是一个传统的监督,并自完成可编程已经走过了很长的路,你在做什么是非常有用的。也许你可以要求他们添加回去,或者只是修补它自己,如果那会是对你在做什么是可行的。

I think it's a legacy oversight, and since programmable completion has come a long way, what you're doing is useful. Maybe you can ask them to add it back in, or just patch it yourself, if that'd be feasible for what you're doing.

怕我没有从你想出什么迄今预留了不同的解决方案,但至少我们知道的为什么的它不会与阅读工作

Afraid I don't have a different solution aside from what you've come up with so far, but at least we know why it doesn't work with read.

EDIT2 :是的,这里有一个补丁我只是测试,似乎工作。通过所有单位和reg测试,显示了你的脚本这个输出使用bash的修补中运行时,如你预期:

EDIT2: Right, here's a patch I just tested that seems to "work". Passes all unit and reg tests, and shows this output from your script when run using the patched bash, as you expected:

$ ./tabcompl.sh
waiting for commands
-> **<TAB>**
TAB     hit     output  should  these   this    when    words   you
->

如您所见,我只是注释掉那些4行和部分定时器code重置 rl_attempted_completion_function 阅读-t 指定并出现超时,这不再是必要的。如果你要发送的切特的东西,你不妨先切除 rl_attempted_completion_function 垃圾的全部,但是这将至少让你的脚本可正常使用。

As you'll see, I just commented out those 4 lines and some timer code to reset the rl_attempted_completion_function when read -t is specified and a timeout occurs, which is no longer necessary. If you're going to send Chet something, you may wish to excise the entirety of the rl_attempted_completion_function junk first, but this will at least allow your script to behave properly.

修补程序:

--- 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;

请记住修补庆典将不得不分发或提供某种程度上的地方的人会使用你的脚本...

Keep in mind the patched bash would have to be distributed or made available somehow wherever people would be using your script...

这篇关于庆典和readline:tab完成在用户输入的循环?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆