Programming and Scripting :: Dialog helper



I planned a script that helps to screate dialog based scripts.
Somehow passing variables with multiple words act differently. This script should work with whiptail too.

Read the source and post reply if you have some tips or improvements.

Code Sample
#!/bin/bash
# I don't know if the line above is for any use... But it's just my habit.
# Because this "script" should be sourced by another scripts.
# You could call this as helper-script.

# Yes. I like to add much comments.;)

# I added a licence to this script just if some one want to use this.

############################################################################
# LICENCE -=start=-                                                        #
############################################################################
#Copyright (c) 2007, Zucca
#
# All rights reserved.
#Redistribution and use in source and binary forms, with or without
#modification, are permitted provided that the following conditions are met:
#   - Redistributions of source code must retain the above copyright notice,
#     this list of conditions and the following disclaimer.
#   - Redistributions in binary form must reproduce the above copyright
#     notice, this list of conditions and the following disclaimer in the
#     documentation and/or other materials provided with the distribution.
#   - Neither the name of the Zucca's company nor the names of its
#     contributors may be used to endorse or promote products derived from
#     this software without specific prior written permission.
#
#       THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
#       CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
#       INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
#       MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
#       DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
#       CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
#       SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
#       NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
#       LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
#       HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
#       CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
#       OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
#       SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
############################################################################
# LICENCE -=end=-                                                          #
############################################################################


function chooseDialog {
   
   # This function simply choses the dialog app to use.
   # At the time of writing this only "dialog" is tested and it will be
   # chosen if found. Otherwise "whiptail" will be used.
       # There's propably many numbers of ways how to hide output.
       # I've seen much use of "> /dev/null 2>&1" but I'll stick with
       # "&> /dev/null" just because it's very neat.
       # http://tldp.org/LDP/abs/html/special-chars.html#REDIROUTERROR for
       # more. Here I use "2>" to hide error output (stderr) from
       # displaying. Normal output (stdout) will be directed to variable
       # DIALOGAPP and therefore will not be printed to screen.
   # I can't find any simplier way to assign this variable.
   # If you know better, plese inform me. ANY improvements are welcome.
   DIALOGAPP=`which dialog 2> /dev/null` \
   || DIALOGAPP=`which whiptail 2> /dev/null`
   
   # Uncomment next line to have some kind of debug information
   # echo "Dialogapp: $DIALOGAPP"
   
   # Do we need to return this variable? I haven't done research for this.
   # Just to be sure we do it.
   # return $DIALOGAPP
}

function setDialogDimensions {
   
   # This function needs just any text for it's arguments.
   # Before calling, variable IFS should be set to "\n".
   # http://www.google.com/linux?q=Bash+IFS for more.;)
   
   # It genrates dialog dimension variables ($DIALOG_H and $DIALOG_W) with
   # proper width and height for the text depending on the terminal screen
   # size.
   # Normally if dialog is big enough it looks dirty. This function will
   # fix that.
   
   # First, get screen dimensions.
   # Ok this was quite hard for me. As I thought when script is called
   # there's no actual screen size (for example when script is called from
   # GUI). I ran some test and found no answer. Until I googled:
   # http://www.google.com/linux?q=stty+size+bash+script and found the
   # answer from the first hit. My problem was that I ran this script with
   # sh when I should ran it with sh. sh is a symbolic link to /bin/bash.
   # Either bash regonizes how it is called or it's my Linux system that
   # replaces sh with bash (I belive symbolic link is the default).
   # Anyway I added #!/bin/bash to the beginning of this script. Just to be
   # sure.
   # So next lines didn't worked at all.
   # SCREEN_H=`stty size | sed -e "s/ /\n/g" | head -n 1`
   # SCREEN_W=`stty size | sed -e "s/ /\n/g" | tail -n 1`
   
   # Next section is taken from:
   # http://www.linuxfromscratch.org/hints/downloads/files/easyrc.txt with
   # some modifications.
   
               
               # If COLUMNS hasn't been set yet (bash sets it but not
               # when called as sh), do it ourself
               
               # Get the console device if we don't have it already
               # This is ok by the FHS as there is a fallback if
               # /usr/bin/tty isn't available, for example at bootup.
               test -x /usr/bin/tty && CONSOLE=`/usr/bin/tty`
               test -z "$CONSOLE" && CONSOLE=/dev/console
               
               # Get the console size (rows columns)
               SIZE=$(stty size < $CONSOLE)
               
               # Strip off the rows leaving the columns
               SCREEN_W=${SIZE#*\ }
               
               # And get the rows too
               SCREEN_H=${SIZE%%\ *}
               
   
   echo "Screen Dimensions: $SCREEN_H $SCREEN_W"
   
   # I think decreasing eight from width and height of the max screen
   # size is enough.
   let "MAX_W = $SCREEN_W - 8"
   let "MAX_H = $SCREEN_H - 8"
   
   # Uncomment next line to have some kind of debug information
   #echo "Max dialog dimensions: $MAX_H $MAX_W"
   
   # Measure text dimensions
   TEXT_W=`echo "$@" | wc -L`
   TEXT_H=`echo "$@" | fold -sw $MAX_W | wc -l`
   
   # Uncomment next line to have some kind of debug information
   #echo "Text dimensions: $TEXT_H $TEXT_W"
   
   # Dialog needs to be a bit bigger than text dimensions.
   let "DIALOG_W = $TEXT_W + 4"
   let "DIALOG_H = $TEXT_H + 4"
   
   # Uncomment next line to have some kind of debug information
   #echo "Dialog size before check: $DIALOG_H $DIALOG_W"
   
   # If dimensions required by text are more than current screen can show
   # then set dialog dimension(s) to max.
   if [ "$DIALOG_W" -gt "$MAX_W" ]
   then
       let "DIALOG_W = $MAX_W"
   fi
   
   if [ "$DIALOG_H" -gt "$MAX_H" ]
   then
       let "DIALOG_H = $MAX_H"
   fi
   
   # Uncomment next line to have some kind of debug information
   #echo "Dialog size: $DIALOG_H $DIALOG_W"
   
   # Next line is to make a pause to read debug information
   #read
   
   # Finally, return dialog dimensions.
   # Again, I don't know if this is required.
   # return "$DIALOG_H"
   # return "$DIALOG_W"
}

########################################################
# Next functions will execute/open simple dialog tasks.#
########################################################

function msgboxDialog {
   
   chooseDialog
   OIFS="$IFS"
   IFS="\n"
   setDialogDimensions "$@"
   # Change IFS back to default
   IFS="$OIFS"
   "$DIALOGAPP" \
   --backtitle "$DIALOGBACKTITLE" \
   --title "$DIALOGTITLE" \
   --msgbox "$@" "$DIALOG_H" "$DIALOG_W"
}

# Now we can (for example) show motd in dialog by:
# msgboxDialog `cat /etc/motd`

# More functions will be added after bugs have been killed.


Thanks for advance. =)

This might help.  I've added my comments to you in BLOCK but only so these are discernible - I don't mean to shout at you.


Code Sample
#!/bin/bash
# I don't know if the line above is for any use.
# IT IS.

# Yes. I like to add much comments.;)

# I added a licence to this script just if some one want to use this.

############################################################################
# LICENCE -=start=- #
############################################################################
#Copyright (c) 2007, Zucca
#
# All rights reserved.
#Redistribution and use in source and binary forms, with or without
#modification, are permitted provided that the following conditions are met:
# - Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# - Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# - Neither the name of the Zucca's company nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
# CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
############################################################################
# LICENCE -=end=- #
############################################################################


function chooseDialog {

# This function simply choses the dialog app to use.
# At the time of writing this only "dialog" is tested and it will be
# chosen if found. Otherwise "whiptail" will be used.
# There's propably many numbers of ways how to hide output.
# I've seen much use of "> /dev/null 2>&1" but I'll stick with
# "&> /dev/null" just because it's very neat.
# http://tldp.org/LDP/abs/html/special-chars.html#REDIROUTERROR for
# more. Here I use "2>" to hide error output (stderr) from
# displaying. Normal output (stdout) will be directed to variable
# DIALOGAPP and therefore will not be printed to screen.
# I can't find any simplier way to assign this variable.
# If you know better, plese inform me. ANY improvements are welcome.
DIALOGAPP=`which dialog 2> /dev/null` \
|| DIALOGAPP=`which whiptail 2> /dev/null`

# Uncomment next line to have some kind of debug information
#echo "Dialogapp: $DIALOGAPP"

# Do we need to return this variable? I haven't done research for this.
# Just to be sure we do it.
# return $DIALOGAPP
}

function setDialogDimensions {

# This function needs just any text for it's arguments.
# Before calling, variable IFS should be set to "\n".
# http://www.google.com/linux?q=Bash+IFS for more.;)

# It genrates dialog dimension variables ($DIALOG_H and $DIALOG_W) with
# proper width and height for the text depending on the terminal screen
# size.
# Normally if dialog is big enough it looks dirty. This function will
# fix that.

# First, get screen dimensions.
# Ok this was quite hard for me. As I thought when script is called
# there's no actual screen size (for example when script is called from
# GUI). I ran some test and found no answer. Until I googled:
# http://www.google.com/linux?q=stty+size+bash+script and found the
# answer from the first hit. My problem was that I ran this script with
# sh when I should ran it with sh. sh is a symbolic link to /bin/bash.
# Either bash regonizes how it is called or it's my Linux system that
# replaces sh with bash (I belive symbolic link is the default).
# Anyway I added #!/bin/bash to the beginning of this script. Just to be
# sure.
# So next lines didn't worked at all.
# SCREEN_H=`stty size | sed -e "s/ /\n/g" | head -n 1`
# SCREEN_W=`stty size | sed -e "s/ /\n/g" | tail -n 1`

# Next section is taken from:
# http://www.linuxfromscratch.org/hints/downloads/files/easyrc.txt with
# some modifications.


# If COLUMNS hasn't been set yet (bash sets it but not
# when called as sh), do it ourself

# Get the console device if we don't have it already
# This is ok by the FHS as there is a fallback if
# /usr/bin/tty isn't available, for example at bootup.
test -x /usr/bin/tty && CONSOLE=`/usr/bin/tty`
test -z "$CONSOLE" && CONSOLE=/dev/console

# Get the console size (rows columns)
SIZE=$(stty size < $CONSOLE)


# Strip off the rows leaving the columns
SCREEN_W=${SIZE#*\ }

# And get the rows too
SCREEN_H=${SIZE%%\ *}


echo "Screen Dimensions: $SCREEN_H $SCREEN_W"


# DECREASED BY 2 instead
# SET PARAMETERS LIKE THIS AS VARS SO YOU CAN PLAY WITH THEM

if [ "$SCREEN_W" -gt 0 ]; then
let "MAX_W = $SCREEN_W - 2"
fi

if [ "$SCREEN_H" -gt 0 ]; then
let "MAX_H = $SCREEN_H - 2"
fi

# Uncomment next line to have some kind of debug information
#echo "Max dialog dimensions: $MAX_H $MAX_W"

# Measure text dimensions

# NEED DOUBLE QUOTES AOUND $1 TO PRESERVE LINE FORMATTING
# ELSE JUST HAVE ONE LONG LINE

TEXT_W=`echo "$1" | wc -L`
TEXT_H=`echo "$1" | wc -l`

# DON'T NEED fmt HERE

# Uncomment next line to have some kind of debug information
echo "Text dimensions: $TEXT_W $TEXT_H "


# Dialog needs to be a bit bigger than text dimensions.
# EQUAL X & Y DIMS IN WHIPTAIL DON'T GIVE A SQUARE
# DOUBLE WIDTH TO GET APPROX SQUARE IF width < 2 x Height

let "DIALOG_H = $TEXT_H + 8"

let "THRESH = 2 * $DIALOG_H"

let "DIALOG_W = $TEXT_W + 8"

if [ $DIALOG_W -lt $THRESH ]; then
let "DIALOG_W = 2 * $DIALOG_W"
fi



# Uncomment next line to have some kind of debug information
#echo "Dialog size before check: $DIALOG_H $DIALOG_W"

# SET MIN SIZE OR CAN'T SEE ANYTHING - something like:

if [ "$DIALOG_W" -lt 20 ]
then
let "DIALOG_W = 20"
fi

if [ "$DIALOG_H" -lt 10 ]
then
let "DIALOG_H = 10"
fi


echo "MAX_W is $MAX_W MAX_H is $MAX_H"
# If dimensions required by text are more than current screen can show
# then set dialog dimension(s) to max.
if [ "$DIALOG_W" -gt "$MAX_W" ]
then
let "DIALOG_W = $MAX_W"
fi

if [ "$DIALOG_H" -gt "$MAX_H" ]
then
let "DIALOG_H = $MAX_H"
fi

# Uncomment next line to have some kind of debug information
echo "Dialog size: $DIALOG_H $DIALOG_W"

# Next line is to make a pause to read debug information
#read

# Finally, return dialog dimensions.

# THIS ISN'T DOING MUCH FOR YOU HERE

}

########################################################
# Next functions will execute/open simple dialog tasks.#
########################################################

function msgboxDialog {

chooseDialog
IN="${1}"
setDialogDimensions "${IN}"

echo "dims $DIALOG_W $DIALOG_H"
$DIALOGAPP --backtitle "DIALOGBACKTITLE" --title "DIALOGTITLE" --msgbox "${IN}"  $DIALOG_H $DIALOG_W
}

# Now we can (for example) show motd in dialog by:

msgboxDialog "$(cat /etc/motd)"

# More functions will be added after bugs have been killed.


Quote
EQUAL X & Y DIMS IN WHIPTAIL DON'T GIVE A SQUARE
As far as I know, it works the same as console measurments, width is number of characters and height is number of lines of text.

Quote
# Now we can (for example) show motd in dialog by:
msgboxDialog "$(cat /etc/motd)"
This seems like unnecessarily complicated syntax. If it were me I'd definitely make an effort to use the syntax "msgboxDialog /etc/motd" instead. An alternative, though, might be to use a pipe, which might be an easier adjustment to your script:
cat /etc/motd | msgboxDialog

Reading from stdin like that probably means he has to parse the file line by line.  This way just puts the whole file contents into a variable for display in whiptail.
Quote (mikshaw @ Oct. 06 2007,17:57)
Quote
EQUAL X & Y DIMS IN WHIPTAIL DON'T GIVE A SQUARE
As far as I know, it works the same as console measurments, width is number of characters and height is number of lines of text.

Quote
# Now we can (for example) show motd in dialog by:
msgboxDialog "$(cat /etc/motd)"
This seems like unnecessarily complicated syntax. If it were me I'd definitely make an effort to use the syntax "msgboxDialog /etc/motd" instead. An alternative, though, might be to use a pipe, which might be an easier adjustment to your script:
cat /etc/motd | msgboxDialog

dialog already has a feature to read text from a file. That was just an example. But reading from stdin would be a really nice feature.
I haven't studied bash scripting that much to make such feature yet. ;)

Next Page...
original here.