1*************************** Motivation **********************************
2
3Many interactive programs read input line by line, but would like to
4provide line editing and history functionality to the end-user that
5runs the program.
6
7The input-edit package provides that functionality. As far as the
8programmer is concerned, the program only asks for the next line
9of input. However, until the user presses the RETURN key they can use
10emacs-style line editing commands and can traverse the history of lines
11previously typed.
12
13Other packages, such as GNU's readline, have greater capability but are
14also substantially larger. Input-edit is small, since it uses neither
15stdio nor any termcap features, and is also quite portable. It only uses
16\b to backspace and \007 to ring the bell on errors. Since it cannot
17edit multiple lines it scrolls long lines left and right on the same line.
18
19Input edit uses classic (not ANSI) C, and should run on any Unix
20system (BSD, SYSV or POSIX), PC's under DOS with MSC, TurboC or djgpp,
21PC's under OS/2 with gcc (EMX), or Vax/VMS. Porting the package to new
22systems basicaly requires code to read a character when it is typed without
23echoing it, everything else should be OK.
24
25I have run the package on:
26
27 DECstation 5000, Ultrix 4.3 with cc 2.1 and gcc 2.3.3
28 Sun Sparc 2, SunOS 4.1.1, with cc
29 SGI Iris, IRIX System V.3, with cc
30 PC using DOS with MSC
31
32The description below is broken into two parts, the end-user (editing)
33interface and the programmer interface. Send bug reports, fixes and
34enhancements to:
35
36Chris Thewalt (thewalt@ce.berkeley.edu)
375/3/93
38
39Thanks to the following people who have provided enhancements and fixes:
40 Ron Ueberschaer, Christoph Keller, Scott Schwartz, Steven List,
41 DaviD W. Sanderson, Goran Bostrom, Michael Gleason, Glenn Kasten,
42 Edin Hodzic, Eric J Bivona, Kai Uwe Rommel, Danny Quah, Ulrich Betzler
43
44PS: I don't have, and don't want to add, a vi mode, sorry.
45
46************************** End-User Interface ***************************
47
48Entering printable keys generally inserts new text into the buffer (unless
49in overwrite mode, see below). Other special keys can be used to modify
50the text in the buffer. In the description of the keys below, ^n means
51Control-n, or holding the CONTROL key down while pressing "n". Errors
52will ring the terminal bell.
53
54^A/^E : Move cursor to beginning/end of the line.
55^F/^B : Move cursor forward/backward one character.
56ESC-F : Move cursor forward one word.
57ESC-B : Move cursor backward one word.
58^D : Delete the character under the cursor.
59^H, DEL : Delete the character to the left of the cursor.
60^K : Kill from the cursor to the end of line.
61^L : Redraw current line.
62^O : Toggle overwrite/insert mode. Initially in insert mode. Text
63 added in overwrite mode (including yanks) overwrite
64 existing text, while insert mode does not overwrite.
65^P/^N : Move to previous/next item on history list.
66^R/^S : Perform incremental reverse/forward search for string on
67 the history list. Typing normal characters adds to the current
68 search string and searches for a match. Typing ^R/^S marks
69 the start of a new search, and moves on to the next match.
70 Typing ^H or DEL deletes the last character from the search
71 string, and searches from the starting location of the last search.
72 Therefore, repeated DEL's appear to unwind to the match nearest
73 the point at which the last ^R or ^S was typed. If DEL is
74 repeated until the search string is empty the search location
75 begins from the start of the history list. Typing ESC or
76 any other editing character accepts the current match and
77 loads it into the buffer, terminating the search.
78^T : Toggle the characters under and to the left of the cursor.
79^U : Deletes the entire line
80^Y : Yank previously killed text back at current location. Note that
81 this will overwrite or insert, depending on the current mode.
82TAB : By default adds spaces to buffer to get to next TAB stop
83 (just after every 8th column), although this may be rebound by the
84 programmer, as described below.
85NL, CR : returns current buffer to the program.
86
87DOS and ANSI terminal arrow key sequences are recognized, and act like:
88
89 up : same as ^P
90 down : same as ^N
91 left : same as ^B
92 right : same as ^F
93
94************************** Programmer Interface ***************************
95
96The programmer accesses input-edit through these functions, and optionally
97through three additional function pointer hooks. The four functions are:
98
99char *getline(char *prompt)
100
101 Prints the prompt and allows the user to edit the current line. A
102 pointer to the line is returned when the user finishes by
103 typing a newline or a return. Unlike GNU readline, the returned
104 pointer points to a static buffer, so it should not be free'd, and
105 the buffer contains the newline character. The user enters an
106 end-of-file by typing ^D on an empty line, in which case the
107 first character of the returned buffer is '\0'. Getline never
108 returns a NULL pointer. The getline functions sets terminal modes
109 needed to make it work, and resets them before returning to the
110 caller. The getline function also looks for characters that would
111 generate a signal, and resets the terminal modes before raising the
112 signal condition. If the signal handler returns to getline,
113 the screen is automatically redrawn and editing can continue.
114 Getline now requires both the input and output stream be connected
115 to the terminal (not redirected) so the main program should check
116 to make sure this is true. If input or output have been redirected
117 the main program should use buffered IO (stdio) rather than
118 the slow 1 character read()s that getline uses.
119
120void gl_setwidth(int width)
121
122 Set the width of the terminal to the specified width. The default
123 width is 80 characters, so this function need only be called if the
124 width of the terminal is not 80. Since horizontal scrolling is
125 controlled by this parameter it is important to get it right.
126
127void gl_histadd(char *buf)
128
129 The gl_histadd function checks to see if the buf is not empty or
130 whitespace, and also checks to make sure it is different than
131 the last saved buffer to avoid repeats on the history list.
132 If the buf is a new non-blank string a copy is made and saved on
133 the history list, so the caller can re-use the specified buf.
134
135void gl_strwidth(size_t (*func)())
136 The gl_strwidth function allows the caller to supply a pointer to
137 a prompt width calculation function (strlen by default). This
138 allows the caller to embed escape sequences in the prompt and then
139 tell getline how many screen spaces the prompt will take up.
140
141The main loop in testgl.c, included in this directory, shows how the
142input-edit package can be used:
143
144extern char *getline();
145extern void gl_histadd();
146main()
147{
148 char *p;
149 do {
150 p = getline("PROMPT>>>> ");
151 gl_histadd(p);
152 fputs(p, stdout);
153 } while (*p != 0);
154}
155
156In order to allow the main program to have additional access to the buffer,
157to implement things such as completion or auto-indent modes, three
158function pointers can be bound to user functions to modify the buffer as
159described below. By default gl_in_hook and gl_out_hook are set to NULL,
160and gl_tab_hook is bound to a function that inserts spaces until the next
161logical tab stop is reached. The user can reassign any of these pointers
162to other functions. Each of the functions bound to these hooks receives
163the current buffer as the first argument, and must return the location of
164the leftmost change made in the buffer. If the buffer isn't modified the
165functions should return -1. When the hook function returns the screen is
166updated to reflect any changes made by the user function.
167
168int (*gl_in_hook)(char *buf)
169
170 If gl_in_hook is non-NULL the function is called each time a new
171 buffer is loaded. It is called when getline is entered, with an
172 empty buffer, it is called each time a new buffer is loaded from
173 the history with ^P or ^N, and it is called when an incremental
174 search string is accepted (when the search is terminated). The
175 buffer can be modified and will be redrawn upon return to getline().
176
177int (*gl_out_hook)(char *buf)
178
179 If gl_out_hook is non-NULL it is called when a line has been
180 completed by the user entering a newline or return. The buffer
181 handed to the hook does not yet have the newline appended. If the
182 buffer is modified the screen is redrawn before getline returns the
183 buffer to the caller.
184
185int (*gl_tab_hook)(char *buf, int prompt_width, int *cursor_loc)
186
187 If gl_tab_hook is non-NULL, it is called whenever a tab is typed.
188 In addition to receiving the buffer, the current prompt width is
189 given (needed to do tabbing right) and a pointer to the cursor
190 offset is given, where a 0 offset means the first character in the
191 line. Not only does the cursor_loc tell the programmer where the
192 TAB was received, but it can be reset so that the cursor will end
193 up at the specified location after the screen is redrawn.
194