Upload Tizen:Base source
[external/bash.git] / examples / scripts / line-input.bash
1 #! /bin/bash
2 #
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
8
9 #Here is something I wrote a few years ago when I was bored one day.
10 #Warning: this contains control characters.
11
12 # Line input routine for GNU Bourne-Again Shell
13 # plus terminal-control primitives.
14 #
15 # by Kaz Kylheku
16 # June 1996, Vancouver, Canada
17
18
19 #
20 # Function to disable canonical input processing.
21 # Terminal modes are saved into variable "savetty"
22 #
23 #
24
25 function raw
26 {
27         savetty=$(stty -g)
28         stty -icanon -isig -echo -echok -echonl inlcr
29 }
30
31 #
32 # Function to restore terminal settings from savetty variable
33 #
34
35 function restore
36 {
37         stty $savetty
38 }
39
40 #
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.
46 #
47
48 function settimeout
49 # $1 = tenths of a second
50 {
51         if [ "$1" = "0" ] ; then
52                 min=1
53                 timeout=0
54         else
55                 min=0
56                 timeout="$1"
57         fi
58
59         stty min $min time $timeout
60
61         unset min timeout
62 }
63
64 #
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.
69 #
70
71 function getkey
72 {
73         eval $1="\"\$(dd bs=1 count=1 2> /dev/null)\""
74 }
75
76 #
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
89
90 #
91
92
93 function getline
94 {
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 | \7f )                         # 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
109                         fi
110                         ;;
111                 \15 )                                     # 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
116                         ;;
117                 \12 )                                     # 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
126                         ;;
127                 \17 )
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
136                         ;;
137                 \7f | \ 1 | \ 2 | \ 3 | \ 4 | \ 5 | \ 6 | \a | \b | \v | \f | \r )
138                         echo -n \a       # ignore various control characters
139                         ;;              # with an annoying beep
140                 \ e | \ f | \10 | \11 | \12 | \13 | \14 | \15 | \16 | \17 | \18 | \19 | \1a )
141                         echo -n \a
142                         ;;
143                 '       ' | \e | \1d | \1e | \1f | \1c )
144                         echo -n \a
145                         ;;
146                 '' )                    # Break out of loop on carriage return.
147                         echo            # Send a newline to the terminal.
148                         break           # (Also triggered by NUL char!).
149                         ;;
150                 * )             # Append character to the end of the line.
151                                 # If length is restricted, and the line is too
152                                 # long, then beep...
153
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.
159                         fi
160                         ;;
161                 esac
162         done
163         eval $1=\"\$line\"
164         IFS="$save_IFS"
165         unset line save_IFS
166 }
167
168 # uncomment the lines below to create a standalone test program
169 #
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"
176 raw
177 echo -n "go: "
178 if [ ${#1} != 0 ] ; then
179         LINE=$1
180 fi
181 getline LINE 50
182 restore
183
184 echo "<$LINE>"