新式菜单
测试系统版本:CentOS 6.4 x86_64
作用:提供彩色画面,实现方向键控制
实现:根据窗口大小确定各元素位置,彩色输出,各元素组件可选择是否输出。
各个菜单项切换的实现方式:原菜单项常规输出,新位置的菜单项使用特殊效果输出,箭标跟随移动。(添加应用函数或者脚本的方式,参考源代码注释中关于变量的部分)
演示:
查看可使用的选项,主要是控制颜色或各组件是否需要输出,可混合使用
没有任何参数(sh memu.sh)
可使用上下左右方向键进行控制,也可以使用菜单中出现的字母序号跳转位置
sh menu.sh --nocolor 使用加颜色的效果
将所有效果和组件不输出
sh menu.sh --notitle --noinfor --nodate --noframe --nocolor
代码专区:
#!/bin/bash # # ly # ------------------ # Copyright 2016.4.18 LingYi ([email protected]) QQ:1519952564 # # # This script is mainly used to define menu, and according to the user # selected to execute corresponding program, if it appears problem will # affect the running of the whole application. # #以下变量不建议修改 VER="1.0.0" COLS=$( tput cols ) LINES=$( tput lines ) # menu and frame left_width=4 right_width=4 upper_heigth=3 blow_heigth=3 # interval width of left menu and right menu interval_width=4 # length of each menu length=30 # half of menus sum lines=6 #Define the center position SUM_width=$((4+left_width+right_width+interval_width+2*length)) SUM_heigth=$((2+upper_heigth+blow_heigth+lines)) WIDTH=$(( COLS / 2 - SUM_width / 2 )) HEIGTH=$(( LINES / 2 - SUM_heigth / 2 )) #设置默认是否输出颜色或各相应组件,建议将 data_on_off关闭,使菜单运行更流畅,且不易出错 frame_on_off=on title_on_off=on title='Welcome To Use LY ToolS' infor_on_off=on date_on_off=on color_on_off=on #修改以下变量,显示对应的输出 #Define the specific options of menu. menu_A='A) FunctionNameA' menu_B="B) FunctionNameB" menu_C="C) FunctionNameC" menu_D="D) FunctionNameD" menu_E='E) FunctionNameE' menu_F='[ F ] Other List' menu_G='G) FunctionNameG' menu_H='H) FunctionNameH' menu_I='I) FunctionNameI' menu_J='J) FunctionNameJ' menu_K='K) FunctionNameK' menu_L='[ L ] Other List' #修改以下变量,添加相应的应用程序 #如果应用程序为此脚本中的一个函数,则可直接填写函数名称 #如果是此脚本外的一个脚本,明确指定运行方式和脚本的绝对路径,例如:"sh /path/to/file/func.sh" function_A_name=" echo FunctionA" function_B_name=" echo FunctionB" function_C_name=" echo FunctionC" function_D_name=" echo FunctionD" function_E_name=" echo FunctionE" function_F_name=" echo FunctionF" function_G_name=" echo FunctionG" function_H_name=" echo FunctionH" function_I_name=" echo FunctionI" function_J_name=" echo FunctionJ" function_K_name=" echo FunctionK" function_L_name=" echo FunctionL" USG(){ echo -e "\033[1;41m\nWainning:\033[0m"; echo -ne "\033[32m" cat<<EOF_Wainning you can use one or more vari at one time. if no args are set, the variables will be the values which are set at the beginning of the script. You'd better press the key 'q' to exit ! Sometimes, "ctrl + z" is necessary, then use the command "kill %1" ! EOF_Wainning echo -e "\033[0m"; echo -e "\033[1;43mOptions:\033[0m"; echo -ne "\033[32m" cat <<EOF_ly --help/-h display help information about the arguments. --title/--notitle weather display the title or not. --infor/--noinfor weather display the information about the author or not. --date /--nodate weather display the date information or not. --frame/--noframe weather display the frame or not. --color/--nocolor weather display elements with colors or not. EOF_ly echo -ne "\033[0m" } ly_menu_draw_frame(){ #draw upper lines. upper_blow_length=$(( 4 + left_width + right_width + interval_width + 2 * length )) echo -ne "\033[${frame_color}m" start_point_upper=( $(( HEIGTH + 1 )) $(( WIDTH + 1 )) ) end_point_upper=( $(( HEIGTH + 1 )) $(( WIDTH + upper_blow_length )) ) for (( j=${start_point_upper[1]}; j<=${end_point_upper[1]}; j++)); do echo -ne "\033[${start_point_upper[0]};${j}H=" done #draw blow lines. echo -ne "\033[${frame_color}m" start_point_blow=( $(( HEIGTH + 2 + upper_heigth + lines + blow_heigth )) $(( WIDTH + 1 )) ) end_point_blow=( $(( HEIGTH + 2 + upper_heigth + lines + blow_heigth )) $(( WIDTH + upper_blow_length )) ) for (( j=${start_point_blow[1]}; j<=${end_point_blow[1]}; j++)); do echo -ne "\033[${start_point_blow[0]};${j}H=" done #draw left lines left_right_length=$(( upper_heigth + lines + blow_heigth )) echo -ne "\033[${frame_color}m" for (( i=1; i<=2; i++ )); do start_point_left=( $(( HEIGTH + 2)) $(( WIDTH + i )) ) end_point_left=( $(( HEIGTH + 1 + left_right_length )) $(( WIDTH + i )) ) for (( j=${start_point_left[0]}; j<=${end_point_left[0]}; j++)); do echo -ne "\033[${j};${start_point_left[1]}H|" done done #draw right lines echo -ne "\033[${frame_color}m" for (( i=1; i<=2; i++ )); do start_point_right=( $(( HEIGTH + 2 )) $(( WIDTH + upper_blow_length - 2 + i )) ) end_point_right=( $(( HEIGTH + 1 + left_right_length )) $(( WIDTH + upper_blow_length - 2 + i )) ) for (( j=${start_point_right[0]}; j<=${end_point_right[0]}; j++)); do echo -ne "\033[${j};${start_point_right[1]}H|" done done echo -ne '\033[0m' } ly_menu_print_date(){ time_=`date +"%Y.%m.%d %H:%M:%S"` aa=$(( HEIGTH + 1 + upper_heigth + lines + blow_heigth )) bb=$(( WIDTH + 2 + left_width + length * 2 + interval_width + right_width - ${#time_} -1 )) while :; do echo -ne "\033[$aa;${bb}H" echo -ne "\033[1;${date_color}m`date +"%Y.%m.%d %H:%M:%S"`\033[0m" sleep 1 done } ly_menu_init_positions(){ i=1;j=1 for ABCDEF in {A..F}; do eval position_${ABCDEF}[0]=$(( HEIGTH + 1 + upper_heigth + i )) eval position_${ABCDEF}[1]=$(( WIDTH + 3 + left_width )) let i++ done for GHIJKL in {G..L}; do eval position_${GHIJKL}[0]=$(( HEIGTH + 1 + upper_heigth + j )) eval position_${GHIJKL}[1]=$(( WIDTH + 3 + left_width + length + interval_width )) let j++ done POSITION=A this_position=( ${position_A[0]} ${position_A[1]} ) judge_position_left=( ${position_A[0]} ${position_A[1]} ) judge_position_right=( ${position_G[0]} ${position_G[1]} ) } ly_menu_init_print_menu(){ if [[ $color_on_off == 'off' ]]; then except_FL_color=39 FL_color=39 else except_FL_color=36 FL_color=35 fi echo -n ' ' case $1 in A) echo -ne "\033[${position_A[0]};${position_A[1]}H\033[${except_FL_color}m${menu_A}\033[0m" ;; B) echo -ne "\033[${position_B[0]};${position_B[1]}H\033[${except_FL_color}m${menu_B}\033[0m" ;; C) echo -ne "\033[${position_C[0]};${position_C[1]}H\033[${except_FL_color}m${menu_C}\033[0m" ;; D) echo -ne "\033[${position_D[0]};${position_D[1]}H\033[${except_FL_color}m${menu_D}\033[0m" ;; E) echo -ne "\033[${position_E[0]};${position_E[1]}H\033[${except_FL_color}m${menu_E}\033[0m" ;; F) echo -ne "\033[${position_F[0]};${position_F[1]}H\033[${FL_color}m${menu_F}\033[0m" ;; G) echo -ne "\033[${position_G[0]};${position_G[1]}H\033[${except_FL_color}m${menu_G}\033[0m" ;; H) echo -ne "\033[${position_H[0]};${position_H[1]}H\033[${except_FL_color}m${menu_H}\033[0m" ;; I) echo -ne "\033[${position_I[0]};${position_I[1]}H\033[${except_FL_color}m${menu_I}\033[0m" ;; J) echo -ne "\033[${position_J[0]};${position_J[1]}H\033[${except_FL_color}m${menu_J}\033[0m" ;; K) echo -ne "\033[${position_K[0]};${position_K[1]}H\033[${except_FL_color}m${menu_K}\033[0m" ;; L) echo -ne "\033[${position_L[0]};${position_L[1]}H\033[${FL_color}m${menu_L}\033[0m" ;; esac } ly_menu_get_this_position(){ POSITION=$1 case $1 in A) this_position=( ${position_A[0]} ${position_A[1]} ) ;; B) this_position=( ${position_B[0]} ${position_B[1]} ) ;; C) this_position=( ${position_C[0]} ${position_C[1]} ) ;; D) this_position=( ${position_D[0]} ${position_D[1]} ) ;; E) this_position=( ${position_E[0]} ${position_E[1]} ) ;; F) this_position=( ${position_F[0]} ${position_F[1]} ) ;; G) this_position=( ${position_G[0]} ${position_G[1]} ) ;; H) this_position=( ${position_H[0]} ${position_H[1]} ) ;; I) this_position=( ${position_I[0]} ${position_I[1]} ) ;; J) this_position=( ${position_J[0]} ${position_J[1]} ) ;; K) this_position=( ${position_K[0]} ${position_K[1]} ) ;; L) this_position=( ${position_L[0]} ${position_L[1]} ) ;; *) echo "error position"; exit 1 ;; esac } ly_menu_exect(){ if [[ ${color_on_off} == off ]]; then selected_symbol_color=39 selected_menu_color=44 else selected_symbol_color=32 selected_menu_color=31 fi case $1 in A) echo -ne "\033[${position_A[0]};$(( ${position_A[1]} - 2 ))H$( ly_menu_init_print_menu A )" ;; B) echo -ne "\033[${position_B[0]};$(( ${position_B[1]} - 2 ))H$( ly_menu_init_print_menu B )" ;; C) echo -ne "\033[${position_C[0]};$(( ${position_C[1]} - 2 ))H$( ly_menu_init_print_menu C )" ;; D) echo -ne "\033[${position_D[0]};$(( ${position_D[1]} - 2 ))H$( ly_menu_init_print_menu D )" ;; E) echo -ne "\033[${position_E[0]};$(( ${position_E[1]} - 2 ))H$( ly_menu_init_print_menu E )" ;; F) echo -ne "\033[${position_F[0]};$(( ${position_F[1]} - 2 ))H$( ly_menu_init_print_menu F )" ;; G) echo -ne "\033[${position_G[0]};$(( ${position_G[1]} - 2 ))H$( ly_menu_init_print_menu G )" ;; H) echo -ne "\033[${position_H[0]};$(( ${position_H[1]} - 2 ))H$( ly_menu_init_print_menu H )" ;; I) echo -ne "\033[${position_I[0]};$(( ${position_I[1]} - 2 ))H$( ly_menu_init_print_menu I )" ;; J) echo -ne "\033[${position_J[0]};$(( ${position_J[1]} - 2 ))H$( ly_menu_init_print_menu J )" ;; K) echo -ne "\033[${position_K[0]};$(( ${position_K[1]} - 2 ))H$( ly_menu_init_print_menu K )" ;; L) echo -ne "\033[${position_L[0]};$(( ${position_L[1]} - 2 ))H$( ly_menu_init_print_menu L )" ;; esac case $2 in A) echo -ne "\033[${position_A[0]};$(( ${position_A[1]} - 2 ))H" echo -ne "\033[1;${selected_symbol_color}m=>\033[1;5;${selected_menu_color}m${menu_A}\033[0m" continue ;; B) echo -ne "\033[${position_B[0]};$(( ${position_B[1]} - 2 ))H" echo -ne "\033[1;${selected_symbol_color}m=>\033[1;5;${selected_menu_color}m${menu_B}\033[0m" continue ;; C) echo -ne "\033[${position_C[0]};$(( ${position_C[1]} - 2 ))H" echo -ne "\033[1;${selected_symbol_color}m=>\033[1;5;${selected_menu_color}m${menu_C}\033[0m" continue ;; D) echo -ne "\033[${position_D[0]};$(( ${position_D[1]} - 2 ))H" echo -ne "\033[1;${selected_symbol_color}m=>\033[1;5;${selected_menu_color}m${menu_D}\033[0m" continue ;; E) echo -ne "\033[${position_E[0]};$(( ${position_E[1]} - 2 ))H" echo -ne "\033[1;${selected_symbol_color}m=>\033[1;5;${selected_menu_color}m${menu_E}\033[0m" continue ;; F) echo -ne "\033[${position_F[0]};$(( ${position_F[1]} - 2 ))H" echo -ne "\033[1;${selected_symbol_color}m=>\033[1;5;${selected_menu_color}m${menu_F}\033[0m" continue ;; G) echo -ne "\033[${position_G[0]};$(( ${position_G[1]} - 2 ))H" echo -ne "\033[1;${selected_symbol_color}m=>\033[1;5;${selected_menu_color}m${menu_G}\033[0m" continue ;; H) echo -ne "\033[${position_H[0]};$(( ${position_H[1]} - 2 ))H" echo -ne "\033[1;${selected_symbol_color}m=>\033[1;5;${selected_menu_color}m${menu_H}\033[0m" continue ;; I) echo -ne "\033[${position_I[0]};$(( ${position_I[1]} - 2 ))H" echo -ne "\033[1;${selected_symbol_color}m=>\033[1;5;${selected_menu_color}m${menu_I}\033[0m" continue ;; J) echo -ne "\033[${position_J[0]};$(( ${position_J[1]} - 2 ))H" echo -ne "\033[1;${selected_symbol_color}m=>\033[1;5;${selected_menu_color}m${menu_J}\033[0m" continue ;; K) echo -ne "\033[${position_K[0]};$(( ${position_K[1]} - 2 ))H" echo -ne "\033[1;${selected_symbol_color}m=>\033[1;5;${selected_menu_color}m${menu_K}\033[0m" continue ;; L) echo -ne "\033[${position_L[0]};$(( ${position_L[1]} - 2 ))H" echo -ne "\033[1;${selected_symbol_color}m=>\033[1;5;${selected_menu_color}m${menu_L}\033[0m" continue ;; esac } ly_menu_up_down_left_right(){ left_or_right=$1; shift if [[ $left_or_right == 'left' ]] && [[ ${this_position[1]} == ${judge_position_left[1]} ]] ; then if [[ ${this_position[0]} == ${position_A[0]} ]]; then ly_menu_get_this_position $2 ly_menu_exect $1 $2 fi shift shift if [[ ${this_position[0]} == ${position_B[0]} ]]; then ly_menu_get_this_position $2 ly_menu_exect $1 $2 fi shift shift if [[ ${this_position[0]} == ${position_C[0]} ]]; then ly_menu_get_this_position $2 ly_menu_exect $1 $2 fi shift shift if [[ ${this_position[0]} == ${position_D[0]} ]]; then ly_menu_get_this_position $2 ly_menu_exect $1 $2 fi shift shift if [[ ${this_position[0]} == ${position_E[0]} ]]; then ly_menu_get_this_position $2 ly_menu_exect $1 $2 fi shift shift if [[ ${this_position[0]} == ${position_F[0]} ]]; then ly_menu_get_this_position $2 ly_menu_exect $1 $2 fi shift shift fi if [[ $left_or_right == 'right' ]] && [[ ${this_position[1]} == ${judge_position_right[1]} ]]; then if [[ ${this_position[0]} == ${position_G[0]} ]]; then ly_menu_get_this_position $2 ly_menu_exect $1 $2 fi shift shift if [[ ${this_position[0]} == ${position_H[0]} ]]; then ly_menu_get_this_position $2 ly_menu_exect $1 $2 fi shift shift if [[ ${this_position[0]} == ${position_I[0]} ]]; then ly_menu_get_this_position $2 ly_menu_exect $1 $2 fi shift shift if [[ ${this_position[0]} == ${position_J[0]} ]]; then ly_menu_get_this_position $2 ly_menu_exect $1 $2 fi shift shift if [[ ${this_position[0]} == ${position_K[0]} ]]; then ly_menu_get_this_position $2 ly_menu_exect $1 $2 fi shift shift if [[ ${this_position[0]} == ${position_L[0]} ]]; then ly_menu_get_this_position $2 ly_menu_exect $1 $2 fi shift shift fi } ly_menu_change_position(){ case $1 in up ) ly_menu_up_down_left_right left A F B A C B D C E D F E ly_menu_up_down_left_right right G L H G I H J I K J L K ;; down ) ly_menu_up_down_left_right left A B B C C D D E E F F A ly_menu_up_down_left_right right G H H I I J J K K L L G ;; left ) ly_menu_up_down_left_right right G A H B I C J D K E L F ;; right) ly_menu_up_down_left_right left A G B H C I D J E K F L ;; esac } ly_menu_jump_to_new_place(){ if [[ ${this_position[1]} == ${judge_position_left[1]} ]] ; then if [[ ${this_position[0]} == ${position_A[0]} ]]; then old_position='A'; fi if [[ ${this_position[0]} == ${position_B[0]} ]]; then old_position='B'; fi if [[ ${this_position[0]} == ${position_C[0]} ]]; then old_position='C'; fi if [[ ${this_position[0]} == ${position_D[0]} ]]; then old_position='D'; fi if [[ ${this_position[0]} == ${position_E[0]} ]]; then old_position='E'; fi if [[ ${this_position[0]} == ${position_F[0]} ]]; then old_position='F'; fi fi if [[ ${this_position[1]} == ${judge_position_right[1]} ]]; then if [[ ${this_position[0]} == ${position_G[0]} ]]; then old_position='G'; fi if [[ ${this_position[0]} == ${position_H[0]} ]]; then old_position='H'; fi if [[ ${this_position[0]} == ${position_I[0]} ]]; then old_position='I'; fi if [[ ${this_position[0]} == ${position_J[0]} ]]; then old_position='J'; fi if [[ ${this_position[0]} == ${position_K[0]} ]]; then old_position='K'; fi if [[ ${this_position[0]} == ${position_L[0]} ]]; then old_position='L'; fi fi new_position=$1 if [[ $old_position != $new_position ]]; then ly_menu_get_this_position $1 ly_menu_exect $old_position $new_position fi } ly_menu_exec_function(){ case $POSITION in A) ${function_A_name}; exit ;; B) ${function_B_name}; exit ;; C) ${function_C_name}; exit ;; D) ${function_D_name}; exit ;; E) ${function_E_name}; exit ;; F) ${function_F_name}; exit ;; G) ${function_G_name}; exit ;; H) ${function_H_name}; exit ;; I) ${function_I_name}; exit ;; J) ${function_J_name}; exit ;; K) ${function_K_name}; exit ;; L) ${function_L_name}; exit ;; esac } ly_menu_exit_menu(){ [[ ! -z ${back_PID} ]] && kill -9 ${back_PID} rm -fr ${root_path}/mnt/* clear; tput cnorm; stty echo echo "GoodBye" exit 0 } #Check the environment ! trap 'ly_menu_exit_menu' 2 1 3 if [[ -f /proc/$$/fd/255 ]]; then real_name=$( readlink /proc/$$/fd/255 ) root_path=$( dirname ${real_name} ) export root_path else echo -e "\033[1;5;31mNo file: /proc/$$/fd/255\033[0m" exit 1 fi PATH=${PATH}:${root_path}/bin:${root_path}/slave export PATH if [[ "${infor_on_off}" == "on" ]]; then if [[ ${upper_heigth} -lt 1 ]]; then upper_heigth=1 fi fi if [[ "${titile_on_off}" == "on" ]]; then if [[ ${HEIGTH} -lt 1 ]]; then HEIGTH=1 fi fi #Check the window whether big enough or not. SUM_COLS=$(( 4 + left_width + 2 * length + interval_width + right_width )) SUM_LINES=$(( 2 + upper_heigth + lines + blow_heigth )) if [[ $(tput lines) -lt $SUM_LINES ]] || [[ $(tput cols) -lt ${SUM_COLS} ]]; then echo -e '\033[1;31mError: lines or cols of windows too smail !\033[0m' tput cnorm exit 1 fi #About the arguments ! if [[ $( echo ${*} | grep "\-h" ) == "-h" || $( echo ${*} | grep "\--help" ) == "--help" ]]; then USG exit 111 fi #change the values of args according the args of user set. for ARGS_defined in "title" "infor" "date" "frame" "color"; do for ARGS_user_set in $*; do if [ "--${ARGS_defined}" == "${ARGS_user_set}" ]; then eval ${ARGS_defined}_on_off=on break elif [ "--no${ARGS_defined}" == "${ARGS_user_set}" ]; then eval ${ARGS_defined}_on_off=off break fi done done if [[ "${color_on_off}" == "off" ]]; then for element_color in "title_color" "infor_color" "date_color" "frame_color"; do eval ${element_color}=39 done else title_color="" infor_color='' date_color=35 frame_color=43 fi #Display the components ! #trap " " 2 tput cup 0 0 tput ed tput civis #print title if [[ ${title_on_off} == "on" ]]; then title_len=${#title} title_line=${HEIGTH} title_col=$(( COLS / 2 - title_len / 2 )) echo -e "\033[${title_line};${title_col}H\033[1;${title_color}m${title}\033[0m" fi #print frame if [[ ${frame_on_off} == "on" ]]; then ly_menu_draw_frame fi #print information if [[ ${infor_on_off} == "on" ]]; then chars_position_heigth=$(( HEIGTH + 1 )) chars_position_width=$(( WIDTH + 2 )) tput cup ${chars_position_heigth} ${chars_position_width} echo " Owner: LingYi ver:${VER}" #echo " [ Press \"Q\" to exit ]" fi #Initialize the positionof each menu, and print them ly_menu_init_positions for menu_list in {A..L}; do ly_menu_init_print_menu ${menu_list} done #Mark the default menu if [[ ${color_on_off} == "off" ]]; then init_symbol_color=39 init_menu_A_color=44 else init_symbol_color=32 init_menu_A_color=31 fi echo -ne "\033[${this_position[0]};$(( ${this_position[1]} - 2 ))H" echo -ne "\033[1;${init_symbol_color}m=>\033[1;5;${init_menu_A_color}m${menu_A}\033[0m" if [[ ${date_on_off} == "on" ]]; then ly_menu_print_date & back_PID=$! fi #Get the press keys of user ! ESC=`echo -e '\033'`; stty -echo while :; do read -s -n 1 key if [[ ${key} == ${ESC} ]]; then for (( i=0; i<=1; i++ )); do read -s -n 1 KEY[$i] #press twice ESC key to exit [[ ${KEY[0]} == ${ESC} ]] && ly_menu_exit_menu done [[ ${KEY[0]} == '[' ]] && { [[ ${KEY[1]} == 'A' ]] && ly_menu_change_position up [[ ${KEY[1]} == 'B' ]] && ly_menu_change_position down [[ ${KEY[1]} == 'C' ]] && ly_menu_change_position right [[ ${KEY[1]} == 'D' ]] && ly_menu_change_position left } fi #Space or Enter key to run whice you have choiced if [[ -z ${key} ]]; then clear; stty echo [[ ${date_on_off} == 'on' ]] && { tput cnorm kill -9 $back_PID } ly_menu_exec_function kill -2 $$ fi #press Q key to exit key=`echo $key | tr 'a-z' 'A-Z'` [[ ${key} == 'Q' ]] && ly_menu_exit_menu [[ $( echo {A..L} | grep -o ${key} ) ]] && ly_menu_jump_to_new_place ${key} done 2>/dev/null
附件下载源码
转载于:https://blog.51cto.com/lingyi/1764981