Bash 函数用于制作菜单功能

Bash 函数用于制作菜单功能

我正在尝试在终端中制作一个更漂亮的菜单,以提高我的 bash 技能。如果我对所有值进行硬编码,我就可以做到这一点。但是,如果选项数量不同,那么我不确定最佳做法是什么。例如,我可能在一个文件夹中拥有的 *.java 程序数量。我应该有一个为菜单中的选项构建函数的函数吗,或者有没有更好的对话框方法?

   #/bin/bash

      E='echo -e';e='echo -en';trap "R;exit" 2
    ESC=$( $e "\e")
   TPUT(){ $e "\e[${1};${2}H";}
  CLEAR(){ $e "\ec";}
  CIVIS(){ $e "\e[?25l";}
   DRAW(){ $e "\e%@\e(0";}
  WRITE(){ $e "\e(B";}
   MARK(){ $e "\e[7m";}
 UNMARK(){ $e "\e[27m";}
      R(){ CLEAR ;stty sane;$e "\ec\e[37;44m\e[J";};
   HEAD(){ DRAW
           for each in $(seq 1 13);do
           $E "   x                                          x"
           done
           WRITE;MARK;TPUT 1 5
           $E "BASH SELECTION MENU                       ";UNMARK;}
           i=0; CLEAR; CIVIS;NULL=/dev/null
   FOOT(){ MARK;TPUT 13 5
           printf "ENTER - SELECT,NEXT                       ";UNMARK;}
  ARROW(){ read -s -n3 key 2>/dev/null >&2
           if [[ $key = $ESC[A ]];then echo up;fi
           if [[ $key = $ESC[B ]];then echo dn;fi;}

     M0(){ TPUT  4 20; $e "Run";}
     M1(){ TPUT  5 20; $e "Compile and Run";}
     M2(){ TPUT  6 20; $e "Make .Jar File";}
     M3(){ TPUT  7 20; $e "-Xlint";}
     M4(){ TPUT  8 20; $e "";}

     LM=4
  
 MENU(){ for each in $(seq 0 $LM);do M${each};done;}
    POS(){ if [[ $cur == up ]];then ((i--));fi
           if [[ $cur == dn ]];then ((i++));fi
           if [[ $i -lt 0   ]];then i=$LM;fi
           if [[ $i -gt $LM ]];then i=0;fi;}
REFRESH(){ after=$((i+1)); before=$((i-1))
           if [[ $before -lt 0  ]];then before=$LM;fi
           if [[ $after -gt $LM ]];then after=0;fi
           if [[ $j -lt $i      ]];then UNMARK;M$before;else UNMARK;M$after;fi
           if [[ $after -eq 0 ]] || [ $before -eq $LM ];then
           UNMARK; M$before; M$after;fi;j=$i;UNMARK;M$before;M$after;}
   INIT(){ R;HEAD;FOOT;MENU;}
     SC(){ REFRESH;MARK;$S;$b;cur=`ARROW`;}
     ES(){ MARK;$e "ENTER = main menu ";$b;read;INIT;};INIT
  while [[ "$O" != " " ]]; do case $i in

        0) S=M0;SC;if [[ $cur == "" ]];then R;~/Home/Bash_Menu/./jrun.sh;ES;fi;;
        1) S=M1;SC;if [[ $cur == "" ]];then R;~/Home/Bash_Menu/./jcompile.sh;ES;fi;;
        2) S=M2;SC;if [[ $cur == "" ]];then R;~/Home/Bash_Menu/./jjar.sh;ES;fi;;
        4) S=M6;SC;if [[ $cur == "" ]];then R;exit 0;fi;;

  esac;POS;done

以上是我所拥有的硬编码示例。每个选项都基于 M#(){ TPUT 4 20; $e "Run";}。我尝试创建

##Files to be added as menu options
options=( $(cd Java_Files && find . -maxdepth 1 -type f -name "*.java") )
##code that sorts
readarray -t sorted_options < <(IFS=$'\n'; sort <<<"${options[*]}")
...(skipping irreverent code)...
#Where the M0(){} part exists i replaced it with this but it does not seem to quiet work
  for(( x=0; x<${#sorted_options[@]}; x++ )); do
     
     M$x+"()"{ TPUT x+4 20; $e "$opt" }

    LM=${#sorted_options[@]} 
    done

我将此更改与“for each in $(M#()); do”下方底部的代码结合起来,其中对每个选项进行硬编码,如“ 1) S=M1;SC;if [[ $cur == "" ]];then R;$e "\n$(ifconfig )\n";ES;fi;;”

  for each in $(M#()); do
    S=M#;SC;if [[ $cur == "" ]];then R;$e "${#sorted_options[@]}";ES;fi;;
  esac;POS;done

答案1

我找到了一个可行的解决方案,只是看起来不太好。

如果有人想窃取代码,这里是代码。

    #! /bin/bash

function choose_from_menu() {
    local prompt="$1" outvar="$2"
    shift
    shift
    local options=("$@") cur=0 count=${#options[@]} index=0
    local esc=$(echo -en "\e") # cache ESC as test doesn't allow esc codes
    printf "$prompt\n"
    while true
    do
        # list all options (option list is zero-based)
        index=0 
        for o in "${options[@]}"
        do
            if [ "$index" == "$cur" ]
            then echo -e " >\e[7m$o\e[0m" # mark & highlight the current option
            else echo "  $o"
            fi
            index=$(( $index + 1 ))
        done
        read -s -n3 key # wait for user to key in arrows or ENTER
        if [[ $key == $esc[A ]] # up arrow
        then cur=$(( $cur - 1 ))
            [ "$cur" -lt 0 ] && cur=0
        elif [[ $key == $esc[B ]] # down arrow
        then cur=$(( $cur + 1 ))
            [ "$cur" -ge $count ] && cur=$(( $count - 1 ))
        elif [[ $key == "" ]] # nothing, i.e the read delimiter - ENTER
        then break
        fi
        echo -en "\e[${count}A" # go up to the beginning to re-render
    done
    # export the selection to the requested output variable
    printf -v $outvar "${options[$cur]}"
}

selections=( $(cd Java_Files && find . -maxdepth 1 -type f -name "*.java") )
readarray -t sorted_selections < <(IFS=$'\n'; sort <<<"${selections[*]}")

choose_from_menu "Please make a choice:" selected_choice "${sorted_selections[@]}"
echo "Selected choice: $selected_choice"

有一些明显的改进,例如添加陷阱命令。

相关内容