The Cookie Machine - Click here to drag window

DUMMY TEXT - Real text set in assets/js/theCookieMachine.js

Views: 609     Votes:  2     ✅ Solution
Tags: command-line   bash   scripts   menu  
Link: 🔍 See Original Question on Ask Ubuntu 🔗

URL: https://askubuntu.com/q/832766
Title: Can line draw characters (or colors) be added to a Bash file list menu?
ID: /2016/10/03/Can-line-draw-characters-_or-colors_-be-added-to-a-Bash-file-list-menu_
Created: October 3, 2016    Edited:  April 13, 2017
Upload: November 24, 2022    Layout:  post
TOC: false    Navigation:  true    Copy to clipboard:  false


I created the world’s ugliest menu using the first Linux tool I’m learning, BASH.

Skip

What the Menu Looks Like

The following /usr/local/bin/bell/sounds were found
1) /usr/local/bin/bell/sounds/Amsterdam.ogg
2) /usr/local/bin/bell/sounds/bell.ogg
3) /usr/local/bin/bell/sounds/Blip.ogg
4) /usr/local/bin/bell/sounds/default.ogg
5) /usr/local/bin/bell/sounds/Mallet.ogg
6) /usr/local/bin/bell/sounds/message.ogg
7) /usr/local/bin/bell/sounds/Positive.ogg
8) /usr/local/bin/bell/sounds/Rhodes.ogg
9) /usr/local/bin/bell/sounds/Slick.ogg
'a' to hear to all files, use number to hear a single file, 
'u' to update last single file heard as new default, or 'q' to quit:

Top ToS Skip

The Code

#! /bin/bash

# NAME: bell-select-menu
# PATH: /usr/local/bin
# DESC: Present menu of bell sounds to listen to all, listen to one and update default.
# CALL: bell-select-menu
# DATE: Created Oct 1, 2016.

echo "The following /usr/local/bin/bell/sounds were found"

# set the prompt used by select, replacing "#?"
PS3="'a' to hear to all files, use number to hear a single file, 
'u' to update last single file heard as new default, or 'q' to quit: "

lastfile="none"

# allow the user to choose a file
select filename in /usr/local/bin/bell/sounds/*.ogg

do

    # leave the loop if the user types 'q'
    if [[ "$REPLY" == q ]]; then break; fi

    # play all if the user types 'a'
    if [[ "$REPLY" == a ]] 
    then 
	    playall-bells
	    continue
    fi

    # update last file name as new default if the user types 'u'
    if [[ "$REPLY" == u ]]
    then
	    if [[ "$lastfile" == none ]]
	    then
	        echo "No file was selected."
	        break
        fi
	    echo "$lastfile selected"
	    cp $lastfile /usr/local/bin/bell/sounds/default.ogg
     	load-default-bell
        break
    fi

    # complain if no file was selected, and loop to ask again
    if [[ "$filename" == "" ]]
    then
        echo "'$REPLY' is not a valid number"
        continue
    else
	    lastfile="$filename"
    fi

    # listen to the selected file
    ogg123 "$filename"

    # loop back to ask for another
    continue
done

I based the code on an answer from AskUbuntu: Create bash menu based on file list (map files to numbers). The menu scrolls off the screen as user options are repeatedly entered though, so the loop needs to be adjusted.

The world’s ugliest menu is automatically generated so I can’t hard code ASCII line draw characters on the left and right sides. Would I need to call a program to reformat the menu?

The bulk of the menu is generated by a single bash command:

select filename in /usr/local/bin/bell/sounds/*.ogg

I read the Bash manual on the select statement but don’t see any options. Is there a program that can be called to massage the screen?

The closest thing I’ve found is called tput described here: linuxcommand.org/lc3_adv_tput but I’m not sure if it’s practical for this problem.

Thanks in advance :)

PS This menu is one of the tools to get rid of annoying loud speaker beep in Terminal and gedit as described here: Turn off Motherboard/PC Speaker "beep" in Ubuntu 16.04 regression


Top ToS Skip

Edit - Incorporating Accepted Answer

Many thanks to wjandrea for posting code to clean up the menu. Prior to the accepted answer I had added code for color in echo strings and PS3 (prompt). I had also put in a loop to redraw the menu to prevent it scrolling off the screen. I also put in a reset to clear the screen before repainting. This prevents more and old copy (sometimes truncated) and new copy of the menu appearing at the same time.

New Menu Look

The colors aren’t accurately represented when copying from terminal text output and pasting into AskUbuntu.

=====  Sound Files for Bell in /usr/local/bin/bell/sounds/  ====

1) Amsterdam.ogg  4) default.ogg    7) Positive.ogg
2) bell.ogg	      5) Mallet.ogg	    8) Rhodes.ogg
3) Blip.ogg	      6) message.ogg    9) Slick.ogg

===========================  Options  ==========================

'a' to hear to all files, use number to hear a single file, 
'u' update last number heard as new bell default, 'q' to quit: 

This is all that appears on the screen now. There is no $ sudo bell-menu call statement visible. No other history of previous commands typed visible.

A screen shot shows the colors accurately and you can see the screen has been programmatically blanked out:

bell-menu

Top ToS Skip

New Menu Code

#! /bin/bash

# NAME: bell-menu
# PATH: /usr/local/bin
# DESC: Present menu of bell sounds to listen to all, listen to one and update default.
# CALL: sudo bell-menu
# DATE: Created Oct 6, 2016.

# set the prompt used by select, replacing "#?"
PS3="
===========================  Options  ==========================

$(tput setaf 2)'$(tput setaf 7)a$(tput setaf 2)' to hear to all files, use $(tput setaf 7)number$(tput setaf 2) to hear a single file, 
'$(tput setaf 7)u$(tput setaf 2)' update last number heard as new bell default, '$(tput setaf 7)q$(tput setaf 2)' to quit: $(tput setaf 7)"

cd /usr/local/bin/bell/sounds/

# Prepare variables for loops
lastfile="none"
wend="n"

while true; do

  tput reset # Clear screen so multiple menu calls can't be seen.

  echo
  echo -e "===== \e[46m Sound Files for Bell in /usr/local/bin/bell/sounds/ \e[0m ===="
  echo

  # allow the user to choose a file
  select soundfile in *.ogg; do

    case "$REPLY" in
        q) # leave the loop if the user types 'q'
            wend="y" # end while loop
            break    # end do loop
            ;;
        a) # play all if the user types 'a'
            playall-bells
            break    # end do loop
            ;;
        u) # update last file name as new default if the user types 'u'
            if [[ "$lastfile" == none ]]; then
                echo "No file has been heard to update default. Listen first!"
                continue  # do loop repeat
            fi
            echo "$lastfile selected"
            cp "$lastfile" default.ogg
            load-default-bell
            wend="y" # end while loop
            break    # end do loop
            ;;
    esac

    # complain if no file was selected, and loop to ask again
    if [[ "$soundfile" == "" ]]; then
        echo "$REPLY: not a valid selection."
        continue    # repeat do loop
    else
        lastfile="$soundfile"
    fi

    # listen to the selected file
    canberra-gtk-play --file="$soundfile"

    # loop back to ask for another
    break
  done
  if [[ "$wend" == "y" ]]; then break; fi

done

The menu was renamed from bell-select-menu to bell-menu. Because it resides in /usr/local/bin it needs to be called with sudo bell-menu and the comments were updated to reflect this fact.

With a little work the world’s ugliest menu and now become and acceptable looking (but not beautiful) menu.

Top ToS
⇧ How can I identify an empty window? How to use my earphone button?  ⇩