Patch-ID: bash40-021
[bash.git] / examples / scripts / line-input.bash
blob3f2efaef0a3d756bf6afb1bf4744dbb4803e43d7
1 #! /bin/bash
3 #From: kaz@cafe.net (Kaz Kylheku)
4 #Newsgroups: comp.unix.shell
5 #Subject: Funky little bash script
6 #Message-ID: <6mspb9$ft2@espresso.cafe.net>
7 #Date: Thu, 25 Jun 1998 06:11:39 GMT
9 #Here is something I wrote a few years ago when I was bored one day.
10 #Warning: this contains control characters.
12 # Line input routine for GNU Bourne-Again Shell
13 # plus terminal-control primitives.
15 # by Kaz Kylheku
16 # June 1996, Vancouver, Canada
20 # Function to disable canonical input processing.
21 # Terminal modes are saved into variable "savetty"
25 function raw
27 savetty=$(stty -g)
28 stty -icanon -isig -echo -echok -echonl inlcr
32 # Function to restore terminal settings from savetty variable
35 function restore
37 stty $savetty
41 # Set terminal MIN and TIME values.
42 # If the input argument is a zero, set up terminal to wait for
43 # a keystroke indefinitely. If the argument is non-zero, set up
44 # an absolute timeout of that many tenths of a second. The inter-keystroke
45 # timer facility of the terminal driver is not exploited.
48 function settimeout
49 # $1 = tenths of a second
51 if [ "$1" = "0" ] ; then
52 min=1
53 timeout=0
54 else
55 min=0
56 timeout="$1"
59 stty min $min time $timeout
61 unset min timeout
65 # Input a single key using 'dd' and echo it to standard output.
66 # Launching an external program to get a single keystroke is a bit
67 # of a pig, but it's the best you can do! Maybe we could convince the
68 # GNU guys to make 'dd' a bash builtin.
71 function getkey
73 eval $1="\"\$(dd bs=1 count=1 2> /dev/null)\""
77 # Input a line of text gracefully.
78 # The first argument is the name of a variable where the input line is
79 # to be stored. If this variable is not empty, its contents are printed
80 # and treated as though the user had entered them.
81 # The second argument gives the maximum length of the input line; if it
82 # is zero, the input is unlimited (bad idea).
83 # ^W is used to delete words
84 # ^R redraws the line at any time by backspacing over it and reprinting it
85 # ^U backspaces to the beginning
86 # ^H or ^? (backspace or del) delete a single character
87 # ^M (enter) terminates the input
88 # all other control keys are ignored and cause a beep when pressed
93 function getline
95 settimeout 0 # No keystroke timeout.
96 save_IFS="$IFS" # Save word delimiter and set it to
97 IFS="" # to null so ${#line} works correctly.
98 eval line=\${$1} # Fetch line contents
99 echo -n "$line" # and print the existing line.
100 while [ 1 ] ; do
101 getkey key # fetch a single keystroke
102 case "$key" in
103 \b | \x7f ) # BS or DEL
104 if [ ${#line} != 0 ] ; then # if line not empty
105 echo -n "\b \b" # print destructive BS
106 line="${line%%?}" # chop last character
107 else # else if line empty
108 echo -n \a # beep the terminal
111 \x15 ) # kill to line beg
112 while [ ${#line} != 0 ] ; do # while line not empty
113 echo -n "\b \b" # print BS, space, BS
114 line="${line%?}" # shorten line by 1
115 done
117 \x12 ) # redraw line
118 linesave="$line" # save the contents
119 while [ ${#line} != 0 ] ; do # kill to line beg
120 echo -n "\b \b"
121 line="${line%?}"
122 done
123 echo -n "$linesave" # reprint, restore
124 line="$linesave"
125 unset linesave # forget temp var
127 \x17 )
128 while [ "${line% }" != "$line" ] && [ ${#line} != 0 ] ; do
129 echo -n "\b \b"
130 line="${line%?}"
131 done
132 while [ "${line% }" = "$line" ] && [ ${#line} != 0 ] ; do
133 echo -n "\b \b"
134 line="${line%?}"
135 done
137 \x7f | \x01 | \x02 | \x03 | \x04 | \x05 | \x06 | \a | \b | \v | \f | )
138 echo -n \a # ignore various control characters
139 ;; # with an annoying beep
140 \x0e | \x0f | \x10 | \x11 | \x12 | \x13 | \x14 | \x15 | \x16 | \x17 | \x18 | \x19 | \x1a )
141 echo -n \a
143 ' ' | \e | \x1d | \x1e | \x1f | \x1c )
144 echo -n \a
146 '' ) # Break out of loop on carriage return.
147 echo # Send a newline to the terminal.
148 break # (Also triggered by NUL char!).
150 * ) # Append character to the end of the line.
151 # If length is restricted, and the line is too
152 # long, then beep...
154 if [ "$2" != 0 ] && [ $(( ${#line} >= $2 )) = 1 ] ; then
155 echo -n \a
156 else # Otherwise add
157 line="$line$key" # the character.
158 echo -n "$key" # And echo it.
161 esac
162 done
163 eval $1=\"\$line\"
164 IFS="$save_IFS"
165 unset line save_IFS
168 # uncomment the lines below to create a standalone test program
170 echo "Line input demo for the GNU Bourne-Again Shell."
171 echo "Hacked by Kaz Kylheku"
172 echo
173 echo "Use ^H/Backspace/Del to erase, ^W to kill words, ^U to kill the"
174 echo "whole line of input, ^R to redraw the line."
175 echo "Pass an argument to this program to prime the buffer contents"
177 echo -n "go: "
178 if [ ${#1} != 0 ] ; then
179 LINE=$1
181 getline LINE 50
182 restore
184 echo "<$LINE>"