测试系统版本: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


附件下载源码