You are not logged in.

#1 2010-09-29 18:14:50

fsckd
Forum Moderator
Registered: 2009-06-15
Posts: 3,568

simple bash menu

I wanted a simple bash menu where arrow keys could be used to select items. So here it is. It requires cuu and cud in the teminfo or it fails to look nice.

Example usage, distro="`smenu ArchLinux Debian Ubuntu Gentoo`"
tNW9odw

Feel free to modify and adapt for your own personal usage.

#!/bin/bash

# input: list of menu items
# output: item selected
# exit codes: 0 - normal, 1 - abort, 2 - no menu items, 3 - too many items
# to select item, press enter; to abort press q

[[ $# -lt 1 ]] && exit 2 # no menu items, at least 1 required

[[ $# -gt $(( `tput lines` - 1 )) ]] && exit 3 # more items than rows

# set colors
cn="`echo -e '\r\e[0;1m'`" # normal
cr="`echo -e '\r\e[1;7m'`" # reverse

# keys
au="`echo -e '\e[A'`" # arrow up
ad="`echo -e '\e[B'`" # arrow down
ec="`echo -e '\e'`"   # escape
nl="`echo -e '\n'`"   # newline

tn="$#" # total number of items

{ # capture stdout to stderr

tput civis # hide cursor

cp=1 # current position

end=false

while ! $end
do

   for i in `seq 1 $tn`
   do

      echo -n "$cn"
      [[ $cp == $i ]] && echo -n "$cr"

      eval "echo \$$i"

   done

   read -sn 1 key
   [[ "$key" == "$ec" ]] &&
   {
      read -sn 2 k2
      key="$key$k2"
   }

   case "$key" in

      "$au")
         cp=$(( cp - 1 ))
         [[ $cp == 0 ]] && cp=$tn
         ;;

      "$ad")
         cp=$(( cp + 1 ))
         [[ $cp == $(( tn + 1 )) ]] && cp=1
         ;;

      "$nl")
         si=true
         end=true
         ;;

      "q")
         si=false
         end=true
         ;;

   esac

   tput cuu $tn

done

tput cud $(( tn - 1 ))
tput cnorm # unhide cursor
echo "$cn" # normal colors

} >&2 # end capture

$si && eval "echo \$$cp"

# eof

Last edited by fsckd (2010-09-29 21:31:17)


aur S & M :: forum rules :: Community Ethos
Resources for Women, POC, LGBT*, and allies

Offline

#2 2010-09-29 20:23:29

livibetter
Member
From: Taipei
Registered: 2008-05-14
Posts: 95
Website

Re: simple bash menu

Nice code.

I manually added j, k, and o (~Return) into the key checking part. I could use j,k or up,down to choose, but I wonder if that possible you can re-code to make it can accept multiple keys set in $au,$ad, and $nl.

Also, a new option to clean up the menu after user choice or leave?

Offline

#3 2010-09-29 20:50:59

fsckd
Forum Moderator
Registered: 2009-06-15
Posts: 3,568

Re: simple bash menu

livibetter wrote:

Nice code.

I manually added j, k, and o (~Return) into the key checking part. I could use j,k or up,down to choose, but I wonder if that possible you can re-code to make it can accept multiple keys set in $au,$ad, and $nl.

Thanks. In the case statement you can add multiple keys, like:

"$au"|k)
<snip>
"$ad"|j)
livibetter wrote:

Also, a new option to clean up the menu after user choice or leave?

I didn't want this which is why it's not in the script. At the bottom of the script, change tput cud $(( tn - 1 )) to tput dl $tn ; tput cuu1 and it should delete the lines.

Bug: does not work with fish shell, set distro (./smenu ArchLinux Debian Ubuntu Gentoo); I wonder how it fares with other shells and terminals.


aur S & M :: forum rules :: Community Ethos
Resources for Women, POC, LGBT*, and allies

Offline

#4 2010-09-29 21:04:04

livibetter
Member
From: Taipei
Registered: 2008-05-14
Posts: 95
Website

Re: simple bash menu

fsckd wrote:

Thanks. In the case statement you can add multiple keys, like:

"$au"|k)
<snip>
"$ad"|j)

That's what I am doing. That mess up with main code, so I asked if that possible to use $au, $ad to set up multiple keys. But I guess, based on your answer to second question, you don't want to do that in that way, either.

fsckd wrote:
livibetter wrote:

Also, a new option to clean up the menu after user choice or leave?

I didn't want this which is why it's not in the script. At the bottom of the script, change tput cud $(( tn - 1 )) to tput dl $tn ; tput cuu1 and it should delete the lines.

Thanks, this modification works well.

Offline

#5 2010-09-29 21:24:01

fsckd
Forum Moderator
Registered: 2009-06-15
Posts: 3,568

Re: simple bash menu

livibetter wrote:
fsckd wrote:

Thanks. In the case statement you can add multiple keys, like:

"$au"|k)
<snip>
"$ad"|j)

That's what I am doing. That mess up with main code, so I asked if that possible to use $au, $ad to set up multiple keys. But I guess, based on your answer to second question, you don't want to do that in that way, either.

$au and $ad exist to make it easier to read the case statements which is where the logic for the keys is supposed to be. If I may ask, how are you incorporating the script and in what ways does it mess with your code?


aur S & M :: forum rules :: Community Ethos
Resources for Women, POC, LGBT*, and allies

Offline

#6 2010-09-29 21:29:03

livibetter
Member
From: Taipei
Registered: 2008-05-14
Posts: 95
Website

Re: simple bash menu

fsckd wrote:

$au and $ad exist to make it easier to read the case statements which is where the logic for the keys is supposed to be. If I may ask, how are you incorporating the script and in what ways does it mess with your code?

Sorry for not being clear. I meant your main code, I haven't used it with my codes. I don't like to touch code just to suit my need, I prefer to change config or the variables section only.

By the way, what's the license of your code?

Last edited by livibetter (2010-09-29 21:30:15)

Offline

#7 2010-09-29 21:48:56

fsckd
Forum Moderator
Registered: 2009-06-15
Posts: 3,568

Re: simple bash menu

I see what you mean. I intended it so that the user can modify it to suit his needs. As such, there is no license and the code is in the public domain.


aur S & M :: forum rules :: Community Ethos
Resources for Women, POC, LGBT*, and allies

Offline

#8 2010-09-30 11:18:20

Dieter@be
Forum Fellow
From: Belgium
Registered: 2006-11-05
Posts: 1,959
Website

Re: simple bash menu

cool thingie.  Also check out KingBash : https://bbs.archlinux.org/viewtopic.php?id=101010
it does this, and more


< Daenyth> and he works prolifically
4 8 15 16 23 42

Offline

#9 2012-12-29 00:07:37

anonone
Member
Registered: 2012-12-28
Posts: 1

Re: simple bash menu

fsckd, thank you so much for posting your script. It was exactly what I was looking for.

After I adapted your script to my needs, I noticed a problem. The problem was that when more than nine menu items are specified on the command line, the tenth item displayed is actually the first item with a '0' appended to it; the eleventh item displayed is actually the first item with a '1' appended to it; and so on.

To correct the problem:
    Change '\$$i' to '\${$i}'
    Change '\$$cp' to '\${$cp}'

Offline

Board footer

Powered by FluxBB