4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
5 // Competence Center NETwork research (NET), St. Augustin, GERMANY
6 // Stefan Bund <g0dil@berlios.de>
8 // This program is free software; you can redistribute it and/or modify
9 // it under the terms of the GNU General Public License as published by
10 // the Free Software Foundation; either version 2 of the License, or
11 // (at your option) any later version.
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU General Public License for more details.
18 // You should have received a copy of the GNU General Public License
19 // along with this program; if not, write to the
20 // Free Software Foundation, Inc.,
21 // 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 \brief Editor public header */
26 #ifndef HH_SENF_Utils_Termlib_Editor_
27 #define HH_SENF_Utils_Termlib_Editor_ 1
33 #include <senf/Scheduler/ClockService.hh>
34 #include <senf/Scheduler/TimerEvent.hh>
35 #include "AbstractTerminal.hh"
36 #include "Terminfo.hh"
38 //#include "Editor.mpp"
39 ///////////////////////////////hh.p////////////////////////////////////////
44 /** \brief Provide editor support terminal functionality
46 This base class utilizes an arbitrary AbstractTerminal and provides terminfo based
47 terminal navigation and key parsing.
49 All navigation is relative to the current line. The display area can then be extended
50 downwards up to a maximum of height() lines. Resetting this extended display area will
51 return to a one line area containing only the top line.
53 All navigation is restricted to a width() x height() area. The last column may not be
54 written to since auto-margin terminals will move the cursor to the next line when writing to
57 This base class calls v_keyReceived() which must be defined in a derived class whenever a
61 : public AbstractTerminal::Callbacks
64 typedef KeyParser::keycode_t keycode_t;
66 static unsigned const DEFAULT_KEY_TIMEOUT_MS = 500u;
68 explicit BaseEditor(AbstractTerminal & terminal);
70 void newline(); ///< Move to beginning of a new, empty line
71 void toColumn(unsigned c); ///< Move cursor to column \p c
72 void put(char ch); ///< Write \p ch at current column
73 void put(std::string const & text); ///< Write \a text starting at current column
74 void clearLine(); ///< Clear current line and move cursor to first column
75 void setBold(); ///< Set bold char display
76 void setNormal(); ///< Set normal char display
77 void maybeClrScr(); ///< Clear screen if possible
79 void toLine(unsigned l); ///< Move to relative display line \a l
80 void reset(); ///< Reset display area to single line
82 unsigned currentColumn() const; ///< Return number of current column
83 unsigned currentLine() const; ///< Return number of current relative line
84 unsigned width() const; ///< Return current screen width
85 unsigned height() const; ///< Return current screen height
88 virtual bool cb_init(); ///< Called when terminal is initialized
89 virtual void cb_windowSizeChanged();
90 ///< Called whenever the terminal window size changes
95 virtual void v_keyReceived(keycode_t key) = 0; ///< Called whenever a key is received
98 virtual void cb_charReceived(char c);
100 void keySequenceTimeout();
104 void write(std::string const & s);
106 AbstractTerminal * terminal_;
108 KeyParser keyParser_;
109 std::string inputBuffer_;
110 ClockService::clock_type keyTimeout_;
111 scheduler::TimerEvent timer_;
113 unsigned displayHeight_;
117 /** \brief Single line interactive text editor
119 LineEditor implements a single-line input widget on an arbitrary AbstractTerminal.
121 \li It supports all the customary editing functions
122 \li It is possible to arbitrarily assign functions to keys via a key map
123 \li LineEditor has builtin TAB completion support
124 \li The LineEditor has a built-in history
125 \li The LineEditor supports an arbitrary auxiliary display area below the input line
126 \li The LineEditor has hide() / show() support to allow editing to be temporarily
129 The LineEditor will query the user for an input line. When the user accepts a line,
130 LineEditor will call a user callback function. After the callback has been called, the
131 editor is disabled. To accept a new input line, call show().
133 \section editor_keymap The editor key map
135 Keys are defined in the keymap using defineKey(). The default bindings are:
138 <tr><td>\c Return</td> <td>bindings::accept</td></tr>
139 <tr><td>\c Right</td> <td>bindings::forwardChar</td></tr>
140 <tr><td>\c Left</td> <td>bindings::backwardChar</td></tr>
141 <tr><td>\c Up</td> <td>bindings::prevHistory</td></tr>
142 <tr><td>\c Down</td> <td>bindings::nextHistory</td></tr>
143 <tr><td>\c Backspace</td> <td>bindings::backwardDeleteChar</td></tr>
144 <tr><td>\c Delete</td> <td>bindings::deleteChar</td></tr>
145 <tr><td>\c Home</td> <td>bindings::beginningOfLine</td></tr>
146 <tr><td>\c End</td> <td>bindings::endOfLine</td></tr>
147 <tr><td>\c Ctrl-K</td> <td>bindings::deleteToEndOfLine</td></tr>
148 <tr><td>\c Ctrl-A</td> <td>bindings::beginningOfLine</td></tr>
149 <tr><td>\c Ctrl-E</td> <td>bindings::endOfLine</td></tr>
150 <tr><td>\c Ctrl-D</td> <td>bindings::deleteChar</td></tr>
151 <tr><td>\c Ctrl-C</td> <td>bindings::restartEdit</td></tr>
152 <tr><td>\c Ctrl-L</td> <td>bindings::clearScreen</td></tr>
155 See the senf::term::bindings namespace for a list of all default provided key binding
159 \section editor_complete Completion suppoprt
161 Completion support is provided by senf::term::bindings::complete(). To use the completer,
162 you need to implement a completion function and pass it as second argument to
163 bindings::complete():
166 void myCompleter(senf::term::LineEditor & editor, unsigned & b, unsigned & e,
167 std::string & prefix, std::vector<std::string> & completions)
169 // Get text to complete
170 std::string text (editor.text().substr(b, e-b));
172 // Return possible completions in 'completions' array
173 completions.push_back( ... );
176 senf::term::LineEditor editor (...);
177 editor.defineKey(senf::term::KeyParser::TAB,
178 boost::bind(&senf::term::bindings::complete, _1, &myCompleter));
181 When \c myCompleter is a class member, use senf::membind() and pass this instead of \c
182 &myCompleter to \c boost::bind() and thus to senf::term::bindings::complete.
184 The completion protocol is as follows: When completion is desired, the completer function is
185 called. \a b and \a e are set to 0 and <tt>editor.point()</tt> respectively. \a prefix and
186 \a completions are empty.
188 \li the completer may restrict the to-be-completed string to any subrange by changing \a b
189 and \a e accordingly.
190 \li If there is an initial substring which applies to \e all completions but should not be
191 listed in the list of completions, assign this value to \a prefix.
192 \li Add all possible completions to the \a completions vector not including the \a prefix.
193 \li The completion result is taken from the size of the \a completions vector \e only: If
194 this vector is empty, completion failed (even if \a prefix is set), a single entry in \a
195 completions (even if it is the empty string) signals a unique completion.
198 \section editor_auxarea The aux display area
200 The auxiliary display area is accessed using auxDisplay() and clearAuxDisplay(). The aux
201 display area is \e cleared \e before each new key is processed. Therefore it is only
202 temporary. The aux display area however will survive hide() / show().
205 \section editor_hideshow Temporarily disabling the editor
207 Calling hide() will temporarily disable the editor. All editor display will be
208 removed. Calling show() will redisplay the editor in it's current state including the aux
215 ///////////////////////////////////////////////////////////////////////////
218 typedef boost::function<void (LineEditor&)> KeyBinding; ///< Type of a key binding function
219 typedef boost::function<void (std::string const &)> AcceptCallback;
220 ///< Callback function type
222 static unsigned const MAX_HISTORY_SIZE = 1024u;
224 ///////////////////////////////////////////////////////////////////////////
226 LineEditor(AbstractTerminal & terminal, AcceptCallback cb);
227 ///< Create a LineEditor
228 /**< \parm[in] terminal abstract terminal interface
229 \parm[in] cb callback to call for complete input
232 ///////////////////////////////////////////////////////////////////////////
234 ///\name Overall edit control
237 void show(); ///< Enable editor widget
238 void hide(); ///< Disable editor widget
239 void accept(); ///< Accept current user input and call the accept callback
240 void clear(); ///< Clear editor buffer
241 void redisplay(); ///< Mark the editor buffer for redisplay
242 void forceRedisplay(); ///< Redisplay the editor buffer \e now
243 void prompt(std::string const & text); ///< Set prompt string
247 ///\name Cursor and display movement
250 void gotoChar(unsigned n); ///< Move cursor to position \a n
251 void scrollTo(unsigned n); ///< Move positon \n to beginning of display line
255 ///\name Text manipulation
258 void deleteChar(unsigned n=1); ///< Delete \a n characters at point
259 void insert(char ch); ///< Insert \a ch at point
260 void insert(std::string const & text); ///< Insert \a text at point
261 void set(std::string const & text, unsigned pos = 0u);
262 ///< Set edit buffer contents
263 /**< The edit buffer contents will be replaced by \a
264 text. The cursor will be placed at position \a pos
272 void pushHistory(std::string const & text, bool accept = false);
273 ///< Add string \a text to history
274 void prevHistory(); ///< Switch to previous history entry
275 void nextHistory(); ///< Switch to next history entry
282 void auxDisplay(unsigned line, std::string const & text);
283 ///< Display \a text on aux display line \a lilne
284 unsigned maxAuxDisplayHeight(); ///< Get maximum height of the aux display area
285 void clearAuxDisplay(); ///< Clear the aux display area
289 ///\name Get information
292 std::string const & text(); ///< Get current editor buffer contents
293 unsigned point(); ///< Get current cursor position
294 unsigned displayPos(); ///< Get current display position
295 keycode_t lastKey(); ///< Get last key code received
299 ///\name Key bindings
302 void defineKey(keycode_t key, KeyBinding binding);
303 ///< Bind key \a key to \a binding
304 void unsetKey(keycode_t key); ///< Remove all bindings for \a key
309 virtual bool cb_init();
310 virtual void cb_windowSizeChanged();
311 virtual void v_keyReceived(keycode_t key);
313 typedef std::map<keycode_t, KeyBinding> KeyMap;
314 typedef std::vector<std::string> History;
315 typedef std::vector<std::string> AuxDisplay;
318 bool redisplayNeeded_;
320 unsigned promptWidth_;
324 unsigned displayPos_;
326 AcceptCallback callback_;
329 unsigned historyPoint_;
330 AuxDisplay auxDisplay_;
333 /** \brief LineEditor key bindings
337 void selfInsertCommand (LineEditor & editor); ///< Insert key as literal character
338 void forwardChar (LineEditor & editor); ///< Move one char forward
339 void backwardChar (LineEditor & editor); ///< Move one char backwards
340 void accept (LineEditor & editor); ///< Accept input line
341 void acceptWithRepeat (LineEditor & editor); ///< Accept, possibly repeat last history entry
342 void backwardDeleteChar (LineEditor & editor); ///< Delete char before cursor
343 void deleteChar (LineEditor & editor); ///< Delete char at cursor
344 void beginningOfLine (LineEditor & editor); ///< Move to beginning of line
345 void endOfLine (LineEditor & editor); ///< Move to end of line
346 void deleteToEndOfLine (LineEditor & editor); ///< Delete from cursor to end of line
347 void restartEdit (LineEditor & editor); ///< Clear edit buffer and restart edit
348 void prevHistory (LineEditor & editor); ///< Move to previous history entry
349 void nextHistory (LineEditor & editor); ///< Move to next history entry
350 void clearScreen (LineEditor & editor); ///< Clear screen and redisplay editor
352 typedef boost::function<void (LineEditor &, unsigned & b, unsigned & e,
353 std::string & prefix, std::vector<std::string> &)> Completer;
354 void complete (LineEditor & editor, Completer completer);
355 ///< Complete text at cursor
356 /**< This function calls \a completer to find the list of
357 possible completions for the text between \a b and \a e
358 (as passed to the completer). The completer must add
359 all possible completions to the \a completions vector.
361 \see \ref editor_complete */
367 ///////////////////////////////hh.e////////////////////////////////////////
368 //#include "Editor.cci"
369 //#include "Editor.ct"
370 //#include "Editor.cti"
377 // comment-column: 40
378 // c-file-style: "senf"
379 // indent-tabs-mode: nil
380 // ispell-local-dictionary: "american"
381 // compile-command: "scons -u test"