diff options
Diffstat (limited to 'examples/scripts/line-input.bash')
-rw-r--r-- | examples/scripts/line-input.bash | 184 |
1 files changed, 184 insertions, 0 deletions
diff --git a/examples/scripts/line-input.bash b/examples/scripts/line-input.bash new file mode 100644 index 0000000..3f2efae --- /dev/null +++ b/examples/scripts/line-input.bash @@ -0,0 +1,184 @@ +#! /bin/bash +# +#From: kaz@cafe.net (Kaz Kylheku) +#Newsgroups: comp.unix.shell +#Subject: Funky little bash script +#Message-ID: <6mspb9$ft2@espresso.cafe.net> +#Date: Thu, 25 Jun 1998 06:11:39 GMT + +#Here is something I wrote a few years ago when I was bored one day. +#Warning: this contains control characters. + +# Line input routine for GNU Bourne-Again Shell +# plus terminal-control primitives. +# +# by Kaz Kylheku +# June 1996, Vancouver, Canada + + +# +# Function to disable canonical input processing. +# Terminal modes are saved into variable "savetty" +# +# + +function raw +{ + savetty=$(stty -g) + stty -icanon -isig -echo -echok -echonl inlcr +} + +# +# Function to restore terminal settings from savetty variable +# + +function restore +{ + stty $savetty +} + +# +# Set terminal MIN and TIME values. +# If the input argument is a zero, set up terminal to wait for +# a keystroke indefinitely. If the argument is non-zero, set up +# an absolute timeout of that many tenths of a second. The inter-keystroke +# timer facility of the terminal driver is not exploited. +# + +function settimeout +# $1 = tenths of a second +{ + if [ "$1" = "0" ] ; then + min=1 + timeout=0 + else + min=0 + timeout="$1" + fi + + stty min $min time $timeout + + unset min timeout +} + +# +# Input a single key using 'dd' and echo it to standard output. +# Launching an external program to get a single keystroke is a bit +# of a pig, but it's the best you can do! Maybe we could convince the +# GNU guys to make 'dd' a bash builtin. +# + +function getkey +{ + eval $1="\"\$(dd bs=1 count=1 2> /dev/null)\"" +} + +# +# Input a line of text gracefully. +# The first argument is the name of a variable where the input line is +# to be stored. If this variable is not empty, its contents are printed +# and treated as though the user had entered them. +# The second argument gives the maximum length of the input line; if it +# is zero, the input is unlimited (bad idea). +# ^W is used to delete words +# ^R redraws the line at any time by backspacing over it and reprinting it +# ^U backspaces to the beginning +# ^H or ^? (backspace or del) delete a single character +# ^M (enter) terminates the input +# all other control keys are ignored and cause a beep when pressed +# +# + + +function getline +{ + settimeout 0 # No keystroke timeout. + save_IFS="$IFS" # Save word delimiter and set it to + IFS="" # to null so ${#line} works correctly. + eval line=\${$1} # Fetch line contents + echo -n "$line" # and print the existing line. + while [ 1 ] ; do + getkey key # fetch a single keystroke + case "$key" in + | ) # BS or DEL + if [ ${#line} != 0 ] ; then # if line not empty + echo -n " " # print destructive BS + line="${line%%?}" # chop last character + else # else if line empty + echo -n # beep the terminal + fi + ;; + ) # kill to line beg + while [ ${#line} != 0 ] ; do # while line not empty + echo -n " " # print BS, space, BS + line="${line%?}" # shorten line by 1 + done + ;; + ) # redraw line + linesave="$line" # save the contents + while [ ${#line} != 0 ] ; do # kill to line beg + echo -n " " + line="${line%?}" + done + echo -n "$linesave" # reprint, restore + line="$linesave" + unset linesave # forget temp var + ;; + ) + while [ "${line% }" != "$line" ] && [ ${#line} != 0 ] ; do + echo -n " " + line="${line%?}" + done + while [ "${line% }" = "$line" ] && [ ${#line} != 0 ] ; do + echo -n " " + line="${line%?}" + done + ;; + | | | | | | | | | | |
) + echo -n # ignore various control characters + ;; # with an annoying beep + | | | | | | | | | | | | ) + echo -n + ;; + ' ' | | | | | ) + echo -n + ;; + '' ) # Break out of loop on carriage return. + echo # Send a newline to the terminal. + break # (Also triggered by NUL char!). + ;; + * ) # Append character to the end of the line. + # If length is restricted, and the line is too + # long, then beep... + + if [ "$2" != 0 ] && [ $(( ${#line} >= $2 )) = 1 ] ; then + echo -n + else # Otherwise add + line="$line$key" # the character. + echo -n "$key" # And echo it. + fi + ;; + esac + done + eval $1=\"\$line\" + IFS="$save_IFS" + unset line save_IFS +} + +# uncomment the lines below to create a standalone test program +# +echo "Line input demo for the GNU Bourne-Again Shell." +echo "Hacked by Kaz Kylheku" +echo +echo "Use ^H/Backspace/Del to erase, ^W to kill words, ^U to kill the" +echo "whole line of input, ^R to redraw the line." +echo "Pass an argument to this program to prime the buffer contents" +raw +echo -n "go: " +if [ ${#1} != 0 ] ; then + LINE=$1 +fi +getline LINE 50 +restore + +echo "<$LINE>" |