summaryrefslogtreecommitdiff
path: root/examples/scripts/line-input.bash
diff options
context:
space:
mode:
Diffstat (limited to 'examples/scripts/line-input.bash')
-rw-r--r--examples/scripts/line-input.bash184
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>"