寻找命令行包来显示带有箭头键的内联文本菜单选择器

寻找命令行包来显示带有箭头键的内联文本菜单选择器

我正在寻找一种在 shell 中显示内联菜单的工具,可以使用箭头键和 Enter 进行导航。 “内联”是指菜单显示在标准输出文本的正常流程中,不是在所有内容之上的弹出对话框中。

我只发现那个帖子试图解决这个问题,但它只提到自定义脚本或非内联/弹出解决方案(如dialogzenity)。

我正在寻找的是一个强大的包,我可以使用apt-get或简单地在 Docker 映像中安装它npm install -g,并使用选项列表从我的脚本中调用并获取用户选择的项目。

在nodeJS中,我正在使用询问者它不仅提供此类菜单,还提供各种输入。

这是一个例子截屏这样的内联菜单。

该工具不必用 shell 脚本编写。它可以是用任何语言编写的二进制/脚本,只要使用apt-get/很容易安装即可curl。即使是一个 nodeJS 工具也可以,只要它可以从 shell 脚本调用来传递选择。

答案1

我以前用过i选择为此,许多年前。

A非常基本示例:

$ sel="$(iselect -a 'foo' 'bar')"
$ echo $sel
foo

man iselect

iSelect 是一个用于 ASCII 文件的交互式行选择工具,通过基于 Curses 的全屏终端会话进行操作。它可以用作由 Bourne-Shell、Perl 或其他类型的脚本后端控制的用户界面前端作为其包装器,也可以批量用作管道过滤器(通常在 grep 和最终执行命令之间)。换句话说:iSelect 被设计用于任何类型的基于行的交互选择。

输入数据

输入可以从命令行 (line1 line2 ...) 读取,其中每个参数对应一个缓冲区行,也可以从 stdin(当未给出参数时)读取输入,其中缓冲区行根据换行符确定。

"<b>"..."</b>"您还可以使用HTML 中的构造,让不可选择的行的子字符串以粗体模式显示(因为可选择的行始终显示为粗体) 。

答案2

一个非常基本的方法是使用bash'sselect语句;无需安装任何东西(其他)。这是我手头刚刚得到的一个例子:

#!/bin/bash

[...]

sourceBranch=
targetBranch=
# Force one option per line
columnsBackup=${COLUMNS}
COLUMNS=40

echo "Select source and target branch:"
select branches in \
    "testing -> release-candidate" \
    "release-candidate -> stable-release" \
    "stable-release -> stable"
do
    if [ -z "${branches}" ]; then
        echo "Invalid selection"
        continue
    fi

    sourceBranch="${branches%% -> *}"
    targetBranch="${branches##* -> }"
    break
done

COLUMNS=${columnsBackup}
echo "Releasing from ${sourceBranch} to ${targetBranch}"

[...]

输出:

Select source and target branch:
1) testing -> release-candidate
2) release-candidate -> stable-release
3) stable-release -> stable
#? 1   
Releasing from testing to release-candidate

您可能会case ... esac在块中进行一些处理do ... done

答案3

这是我使用 bash 对这个问题的看法。

#!/usr/bin/env bash

# Renders a text based list of options that can be selected by the
# user using up, down and enter keys and returns the chosen option.
#
#   Arguments   : list of options, maximum of 256
#                 "opt1" "opt2" ...
#   Return value: selected index (0 for opt1, 1 for opt2 ...)


figlet -st "$COLUMNS" "Welcome $USER"
printf '\n?%s\n?%s\n?%s\n\n' "What's the name of your website simple-site" "What's the description of your website(optional):" "Please choose lincense":

# Change the value of options to whatever you want to use.
options=("MIT" "Apache-2.0" "GPL-3.0" "Others")

select_option (){
  # little helpers for terminal print control and key input
  ESC=$(printf '%b' "\033")

  cursor_blink_on() {
    printf '%s' "$ESC[?25h"
  }

  cursor_blink_off() {
    printf '%s' "$ESC[?25l"
  }

  cursor_to() {
    printf '%s' "$ESC[$1;${2:-1}H"
  }

  print_option() {
    printf '   %s ' "$1"
  }

  print_selected() {
    printf '  %s' "$ESC[7m $1 $ESC[27m"
  }

  get_cursor_row() {
    IFS=';' read -sdR -p $'\E[6n' ROW COL; printf '%s' ${ROW#*[}
  }

  key_input() {
    read -s -n3 key 2>/dev/null >&2
    if [[ $key = $ESC[A ]]; then
      echo up
    fi
    if [[ $key = $ESC[B ]]; then
      echo down
    fi
    if [[ $key = ""  ]]; then
      echo enter
    fi
  }

   # initially print empty new lines (scroll down if at bottom of screen)
   for opt; do
     printf "\n"
   done

   # determine current screen position for overwriting the options
   local lastrow=$(get_cursor_row)
   local startrow=$(($lastrow - $#))

   # ensure cursor and input echoing back on upon a ctrl+c during read -s
   trap "cursor_blink_on; stty echo; printf '\n'; exit" 2
   cursor_blink_off

   local selected=0
   while true; do
     # print options by overwriting the last lines
     local idx=0
     for opt; do
       cursor_to $((startrow + idx))
       if [[ $idx == $selected ]]; then
         print_selected "$opt"
       else
         print_option "$opt"
       fi
       ((idx++))
     done

     # user key control
     case $(key_input) in
       enter) break;;
       up)    ((selected--));
         if (( $selected < 0 )); then selected=$(($# - 1)); fi;;
         down)  ((selected++));
           if (( selected > $# )); then selected=0; fi;;
         esac
       done

       # cursor position back to normal
       cursor_to $lastrow
       printf "\n"
       cursor_blink_on

       return "$selected"
}


select_option "${options[@]}"
choice=$?

index=$choice
value=${options[$choice]}

case $value in 
  MIT)  ## User selected MIT
   read -rp "Really use? $value [Y/N] " answer
   [[ $answer ]] || { echo "No answer!" >&2; exit 1; }
   if [[ $answer == [Yy] ]]; then
     : ## User selected Y or y, what are you going to do about it?
   elif [[ $answer == [Nn] ]]; then
     : ## User selected N or n what are you going to do about it?
   fi
   printf '%s\n' "You have choosen $answer";;
  Apache-2.0)
   read -rp "Really use? $value [Y/N] " answer
   [[ $answer ]] || { echo "No answer!" >&2; exit 1; }
   if [[ $answer == [Yy] ]]; then
     :
   elif [[ $answer == [Nn] ]]; then
     :
   fi
   ;;
  GPL-3.0)
   read -rp "Really use? $value [Y/N] " answer
   [[ $answer ]] || { echo "No answer!" >&2; exit 1; }
   if [[ $answer == [Yy] ]]; then
     :
   elif [[ $answer == [Nn] ]]; then
     :
   fi
   ;;
  Others)
   read -rp "Really use? $value [Y/N] " answer
   [[ $answer ]] || { echo "No answer!" >&2; exit 1; }
   if [[ $answer == [Yy] ]]; then
     :
   elif [[ $answer == [Nn] ]]; then
     :
   fi
   ;;
esac

输出或多或少是在https://i.stack.imgur.com/RO9E5.png:if 语句内不执行任何操作,请替换 为:您的代码/流程或您想要执行的任何操作,如果答案是[Yy][Nn] 这应该足以让您开始。顺便说一下,我发现发布在某处的捕捉运动的代码我刚刚扩展/重写了一些语法。

相关内容