Saturday, January 2, 2010

[Level 3] Customize menu script

My college asked me to write a customize menu script with several functions.
The features are:
1. can insert, update, delete menu items.
2. have timeout limitration.
3. setting no. of columns.
4. setting column width.
So, after I finished it, I also share it to you.

#!/usr/bin/bash
showUsage() {
  cat << EOF
Usage:
  $0
     [-e] (expert mode)
     [-h] (help menu)
     [-t] timeout_sec (default timeout = $nTimeout sec)
     [-c] no. of columns (default no. of column = $nColumn)
     [-w] column wide (default column wide = $nWide)
Ex.
  $0
  $0 -e
  $0 -h
  $0 -t 10
  $0 -c 3
  $0 -w 10
EOF
}

pak2c() {
  read -n 1 -p "Press any key to continue..." pak2c
}

buildMenu() {
  clear
  declare -i nColumn=$1
  declare -i nWide=$2
  declare -i nCount=0
  declare -i nMod=0
  declare    sCount=""

  while read fItem item x
  do
    nCount=$nCount+1 && sCount=$nCount && [ $isExpert -eq 0 ] && sCount=.
    aMenu[$nCount]=$item
    fDisable=`echo $fItem | sed -e 's/[^*]//g'`
    printf "%${#nTotalCount}s) %${nWide}s%1s" $sCount $item $fDisable
  
    nMod=$nCount%$nColumn
    if [ $nMod -eq 0 ]
    then
      printf "\n";
    else
      printf " ";
    fi
  done << EOF
`grep "$sFilter" $0 ## | sort -k 2 ## disable display with sorting`
EOF
  [ $nMod -ne 0 ] &&  printf "\n"

  [ "$isExpert" -eq 0 ] && \
print "---------------------------------------" && \
printf "%${#nTotalCount}s) %${nWide}s\n" "a" "add" && \
printf "%${#nTotalCount}s) %${nWide}s\n" "r" "remove" && \
printf "%${#nTotalCount}s) %${nWide}s\n" "e" "enable" && \
printf "%${#nTotalCount}s) %${nWide}s%s\n" "d" "disable" ", marked *" && \
printf "%${#nTotalCount}s) %${nWide}s\n" "s" "sorting data" && \
printf "%${#nTotalCount}s) %${nWide}s\n" "q" "quit" && \
print "---------------------------------------"
}

############################################# main
clear
set -o noglob
declare -i nTimeout=10
declare -i isExpert=1
declare -a aMenu
declare    sFilter=""
declare -i nTotalCount=0
declare -i nColumn=1
declare -i nWide=10

while getopts ":ehc:t:w:" opt
do
  case $opt in
  e)
    isExpert=0
    nTimeout=65535
    nColumn=3
    ;;
  h)
    showUsage
    exit 0
    ;;
  c)
    nColumn=$OPTARG
    ;;
  t)
    nTimeout=$OPTARG
    ;;
  w)
    nWide=$OPTARG
    ;;
  :)
    echo "The option ($opt) without parameters, exit program..."
    showUsage
    exit 1
    ;;
  \?)
    echo "Not such option($OPTARG), exit program..."
    showUsage
    exit 1
    ;;
  esac
done

if [ $isExpert -eq 0 ]
then
  sFilter="^#[@*] "
else
  sFilter="^#[@] "
fi
nTotalCount=`grep -c "$sFilter" $0`

while true
do
  buildMenu $nColumn $nWide
  declare -i nChoice
  declare    sChoice
  declare -i fRead=0

  while true
  do
    echo -n "Please enter your choice ($nTimeout secs to timeout): "
    read -t $nTimeout sChoice || fRead=$?
    [ $fRead -eq 142 ] && break
    nChoice=$sChoice

    [ -z "$sChoice" ] && buildMenu $nColumn $nWide && continue
    [ $isExpert -eq 1 ] && ( [ $nChoice -le 0 ] || [ $nChoice -gt $nTotalCount ] ) && continue
    [ $isExpert -eq 0 ] && ( [ $sChoice == "0" ] || [ $nChoice -ne 0 ] ) && continue
    break
  done

  if [ $fRead -eq 142 ]
  then
    echo "Time out..."
    break
  else
    #echo "sChoice:$sChoice/$nTotalCount:"
    case "$sChoice" in
    a)
      while true
      do
        read -p "Please enter the item you want to add: " sItem
        #echo "sFilter=$sFilter"
        [ `grep -c "$sFilter[ ]*$sItem$" $0` -gt 0 ] && echo "Item ($sItem) exist!!" && continue
        [ ! -z $sItem ] && break
      done
      echo "#@ $sItem" >> $0
      echo "Add item ($sItem) done..."
      ;;
    r)
      while true
      do
        read -p "Please enter the item you want to remove: " sItem
        [ ! -z $sItem ] && break
      done
      perl -pi -e "s/^#[@*] $sItem\n$//" $0
      echo "remove item ($sItem) done..."
      ;;
    e)
      while true
      do
        read -p "Please enter the item you want to enable: " sItem
        [ ! -z $sItem ] && break
      done
      perl -pi -e "s/^#\* $sItem$/#@ $sItem/" $0
      echo "enable item ($sItem) done..."
      ;;
    d)
      while true
      do
        read -p "Please enter the item you want to disable: " sItem
        [ ! -z $sItem ] && break
      done
      perl -pi -e "s/^#@ $sItem$/#* $sItem/" $0
      echo "disable item ($sItem) done..."
      ;;
    s)
      declare -i nEOS=`grep -n '#### \*\*\* Data \*\*\*$' $0 | cut -d: -f1`
      declare -i nBOD=$nEOS+1
      head -$nEOS $0 > /tmp/$$.main
      tail +$nBOD $0 | sed -e "s/^#[@*][ ]*$//" | sed -e "/^$/d" | sort > /tmp/$$.data
      cat /tmp/$$.main /tmp/$$.data > $0
      cp $0 $0.bak
      rm /tmp/$$.main /tmp/$$.data
      echo "Sorting data done, please restart your program..."
      exit 0
      ;;
    q)
      exit 0
      ;;
    "")
      ;;
    *)
      if [ $isExpert -eq 1 ]
      then
        #####################################################################
        #
        # Modify Here.....
        #
        #####################################################################
        case ${aMenu[$nChoice]} in
        apple)
          echo "apple is red!"
          ;;
        banana)
          echo "banana is yellow!"
          ;;
        esac
      
        echo "You press $nChoice, $nChoice is ${aMenu[$nChoice]}."
      else
        continue
      fi
      ;;
    esac
  fi
  pak2c
done

echo "End of process..."

####
#### Menu item:
####   Use '#@ ', '#* ' at the begin of the line for setting menu item
####   #@ enable items
####   #* disable items
#### Ex.
####   #@ item
#### PS.
####   Do not modify the data below, use option "-e" (export mode) to modify.
####
#### *** Data ***
#@ apple
#@ banana
#@ cake
#* drink
#@ egg
#@ fruit
#@ grape
#@ ham
#* ice
#* juice
#@ lemon


Wish this helps.

regards,

Stanley Huang