最好的(?)方法为半便携式shell脚本制作弹出菜单?

时间:2010-08-31 12:56:11

标签: bash scripting shell menu interactive

基本上我想说:

  echo `grep ^foo /usr/share/dict/words | popup_menu`

...并且有一些类型的键盘导航菜单弹出或选择工具,非常类似于vim的“:Explore”机制。

“使用标准工具随处可轻松工作”的极致奖励积分

同样可以接受的是“需要某种额外的配置文件或5-10行shell脚本”

不太可接受的是“下载这个perl库或100行python脚本等等......”此时,我宁愿尝试找到一些实际的程序/包来安装并将其列为硬依赖。但是如果你能想出一个2-5行的perl / python脚本,它不需要追踪那些可能也可以工作的库。

我调查过:

  • Dialog - 看起来更适合“shell应用程序”而不是ad-hoc脚本(看起来可能有办法让它做我想做的事情),缺点是它会覆盖当前的屏幕状态

  • Curses - 似乎它以“C”为目标,或者需要用作perl / python库的一部分,必须使用此编写自己的菜单程序

  • bash“select”builtin - 通过数字选择工作,而非键盘导航,使用起来有点尴尬但相当接近

  • Vim - “grep ^ foo / usr / share / dict / words | vim - ”...这让你惊讶地接近,只是缺少“将输入键绑定到终端打印当前行并退出”< / p>

...那么,我如何制作或找到一个体面的,简单的,特别的菜单制作工具,用于bash脚本以及当我在命令行上懒惰时?

 ... git checkout -b `git branch -a | menu`
 ... ssh `grep foo /etc/hosts | menu`
 ... rm `ls | menu`  # ignore obvious quoting issues with this...

编辑:感谢目前为止的答案,但我想再次强调我正在寻找ASCII /文本菜单(不是xwindows)。我在当地尝试了一些东西,但没有任何东西可以达到最佳位置。

4 个答案:

答案 0 :(得分:1)

zenity在脚本中使用非常简单,但它创建了GUI窗口。不确定它是否适用于你...

答案 1 :(得分:1)

如果您的版本有--keep-tite并且您的终端支持备用屏幕,则可以使用dialog选项。例如,xterm和一些xterm兼容的终端可以。

使用此选项,输出切换到备用屏幕,显示对话框,当它关闭时,屏幕会切换回显示之前的内容。例如,这就是vim的工作方式。

然而,对话框仍会完全占据屏幕。

“keep-tite”中的“ti”和“te”表示用于括起使用光标运动的程序的termcap代码。相应的terminfo代码为smcuprmcup。请参阅man 5 termcapman 5 terminfoman xterm(其他功能)。

你也可以自己做这样的事情:

tput smcup
# bash select menu
tput rmcup

答案 2 :(得分:1)

经过彻底调查后,制作弹出式菜单的最佳(?)方法获胜者如下:

    select f in aaa bbb ccc ddd ; do echo $f ; break ; done

它本身并不是一个弹出式菜单,但就使用标准的unix-isms而言,你可以获得最好的效果,而且它几乎普遍可用。无论您身在何处,都可以轻松地将其包装在简单的shell脚本中,这意味着您可以将其优势可靠地集成到您的工作流程中。

    $ cat ~/bin/menu.sh
    #!/bin/sh
    ALL=`cat`
    select FOO in $ALL ; do echo $FOO ; break ; done

    $ ls /usr | ~/bin/menu.sh
    1) bin      3) include    5) lib64    7) sbin    9) src
    2) games    4) lib        6) local    8) share
    #? 2
    games

实际上,您希望使用“select f in ...”这个习惯用作对话框命令不可用时的后备。下面的shell / dialog脚本很难看,但只要提供与上面相同的输入和输出,但用户界面更舒适,就可以完成工作。

    $ cat ~/bin/gui-menu.sh
    #!/bin/sh

    # get stdin
    ALL=`cat`

    # number the lines
    SPLITTED=$( echo $ALL | sed 's/ /\n/g' | awk -- '{print NR, $0 }' )

    # prompt via dialog (output-fd=1 is so that dialog gui doesn't go to subshell)
    OUT=$( dialog --output-fd 1 --ok-label Select --menu Choose 0 50 22 $SPLITTED )
    EXIT_CODE=$?

    # handle escape / cancel buttons
    if [ "1" = "$EXIT_CODE" ] ; then exit 1 ; fi
    if [ "255" = "$EXIT_CODE" ] ; then exit 1 ; fi

    # extract text corresponding to user's numeric selection
    CHOSEN=$( echo $ALL | sed 's/ /\n/g' | awk -- "NR==$OUT {print \$0 }" )

    # print result
    echo $CHOSEN

...它与上面的“menu.sh”完全一样,但提示gui而不是数字。扩展上面的内容以允许对话多个复选框相对容易(效率非常低,在下面的实现中可能是n ^ 2-ish),如下所示:

    $ cat ~/bin/gui-multiselect.sh
    #!/bin/sh

    # get stdin
    ALL=`cat`

    # number the lines
    SPLITTED=$( echo $ALL | sed 's/ /\n/g' | awk -- '{print NR, $0, 0 }' )

    # prompt via dialog (output-fd=1 is so that dialog gui doesn't go to subshell)
    OUT=$(dialog --output-fd 1 --ok-label Select --separate-output --checklist Choose 0 50 22 $SPLITTED)
    EXIT_CODE=$?

    # handle escape / cancel buttons
    if [ "1" = "$EXIT_CODE" ] ; then exit 1 ; fi
    if [ "255" = "$EXIT_CODE" ] ; then exit 1 ; fi

    # loop through selected numbers
    for X in $OUT ; do
        # inefficiently print out the text corresponding to the selections
        CHOSEN=$( echo $ALL | sed 's/ /\n/g' | awk -- "NR==$X {print \$0 }" )
        echo $CHOSEN
    done;

第三名是Joey Hess的“vipe”交互式管道编辑器(来自“moreutils”软件包),它允许您编辑管道并将其输出传回。

 echo `ls | vipe`

上面的命令不是一个对话框(不能只使用向上/向下箭头并按回车,实际上必须删除你不想要的所有行)但它很有用,因为它处理两个交互式单和多选用例,只是一个有趣的工具。

对于GUI选择,与对话框相比,Jack所引用的zenity看起来像是一个胜利者,但遗憾的是,对话框并不是“ad-hoc”,而是将对话框与“select f in”相结合。 ..“后备是最能满足我需求的。”

答案 3 :(得分:0)

如果您知道您的脚本将在特定的Linux发行版上运行,那么您可以使用他们已经开发的程序来执行通知弹出窗口。我在这里寻找同样的事情:linux command line popup