source: trunk/FACT++/src/Readline.cc@ 10951

Last change on this file since 10951 was 10922, checked in by tbretz, 13 years ago
Added a wait command.
File size: 33.0 KB
Line 
1// **************************************************************************
2/** @class Readline
3
4@brief C++ wrapper for GNU's readline library
5
6This class is meant as a C++ wrapper around GNU's readline library.
7Note that because readline uses a global namespace only one instance
8of this class can exist at a time. Instantiating a second object after
9a first one was deleted might show unexpected results.
10
11When the object is instantiated readline's history is read from a file.
12At destruction the history in memory is copied back to that file.
13The history file will be truncated to fMaxLines.
14
15By overloading the Readline class the function used for auto-completion
16can be overwritten.
17
18Simple example:
19
20\code
21
22 Readline rl("MyProg"); // will read the history from "MyProg.his"
23 while (1)
24 {
25 string txt = rl.Prompt("prompt> ");
26 if (txt=="quit)
27 break;
28
29 // ... do something ...
30
31 rl.AddHistory(txt);
32 }
33
34 // On destruction the history will be written to the file
35
36\endcode
37
38Simpler example (you need to implement the Process() function)
39
40\code
41
42 Readline rl("MyProg"); // will read the history from "MyProg.his"
43 rl.Run("prompt> ");
44
45 // On destruction the history will be written to the file
46
47\endcode
48
49@section References
50
51 - <A HREF="http://cnswww.cns.cwru.edu/php/chet/readline/rltop.html">GNU Readline</A>
52
53 */
54// **************************************************************************
55#include "Readline.h"
56
57#include <sstream>
58#include <fstream>
59#include <iostream>
60
61#include <readline/readline.h>
62#include <readline/history.h>
63
64#include "tools.h"
65
66using namespace std;
67
68Readline *Readline::This = 0;
69
70// --------------------------------------------------------------------------
71//
72//! Construct a Readline object. The constructor reads the history from a
73//! history file. The filename is compiled by adding ".his" to the
74//! supplied argument. The name oif the history file is stored in fName.
75//!
76//! Since readline has a global namespace, the creation of only one
77//! Readline instance is allowed.
78//!
79//! The provided program name is supplied to readline by means of
80//! rl_readline_name.
81//!
82//! Readlines default callback frunction for completions is redirected
83//! to CompletionImp which in turn will call Completion, which can be
84//! overwritten by the user.
85//!
86//! Bind some default key sequences like Page-up/-down for searching forward
87//! and backward in history.
88//!
89//! @param prgname
90//! The prefix of the history filename. Usually the program name, which
91//! can be initialized by argv[0].
92//
93Readline::Readline(const char *prgname) :
94 fMaxLines(500), fLine(0), fCompletion(0)
95{
96 if (This)
97 {
98 cout << "ERROR - Readline can only be instatiated once!" << endl;
99 exit(-1);
100 }
101
102 This = this;
103
104 // Alternative completion function
105 rl_attempted_completion_function = rl_ncurses_completion_function;
106
107 // Program name
108 rl_readline_name = prgname;
109
110 // Compile filename for history file
111 fName = string(prgname)+".his";
112
113 // Read history file
114 if (read_history(fName.c_str()))
115 cout << "WARNING - Reading " << fName << ": " << strerror(errno) << endl;
116
117 // Setup the readline callback which are needed to redirect
118 // the otuput properly to our ncurses panel
119 rl_getc_function = rl_ncurses_getc;
120 rl_startup_hook = rl_ncurses_startup;
121 rl_redisplay_function = rl_ncurses_redisplay;
122 rl_event_hook = rl_ncurses_event_hook;
123 rl_completion_display_matches_hook = rl_ncurses_completion_display;
124
125 // Bind delete, page up, page down
126 rl_bind_keyseq("\e[3~", rl_named_function("delete-char"));
127 rl_bind_keyseq("\e[5~", rl_named_function("history-search-backward"));
128 rl_bind_keyseq("\e[6~", rl_named_function("history-search-forward"));
129 rl_bind_keyseq("\033[1;3F", rl_named_function("kill-line"));
130 rl_bind_keyseq("\033[1;5D", rl_named_function("backward-word"));
131 rl_bind_keyseq("\033[1;5C", rl_named_function("forward-word"));
132 rl_bind_key(25, rl_named_function("kill-whole-line"));
133
134 //for (int i=0; i<10; i++) cout << (int)getchar() << endl;
135}
136
137// --------------------------------------------------------------------------
138//
139//! Writes the current history to the file with the name stored in fName.
140//! In addition the written file is truncated to fMaxLines to keep the
141//! file of a reasonable size. The number of lines fMaxLines can be set
142//! by SetMaxLines before the destructor is called. Setting fMaxLines
143//! to 0 or a negative value switches automatic truncation off.
144//
145Readline::~Readline()
146{
147 // Write current history to file
148 if (write_history(fName.c_str()))
149 cout << "WARNING - Write " << fName.c_str() << ": " << strerror(errno) << endl;
150
151 // Truncate file
152 if (fMaxLines>0 && history_truncate_file(fName.c_str(), fMaxLines))
153 cout << "WARNING - Truncate " << fName.c_str() << ": " << strerror(errno) << endl;
154}
155
156// --------------------------------------------------------------------------
157//
158//! This wraps the given readline function such that the output can be
159//! redirected from thr rl_outstream to the given C++ ostream.
160//!
161//! @param out
162//! The stream to which the output should be redirected.
163//!
164//! @param function
165//! Takes a function of type bool(*)() as argument
166//!
167//! @returns
168//! The return value of the function
169//
170bool Readline::RedirectionWrapper(ostream &out, bool (*function)())
171{
172 FILE *save = SetStreamOut(tmpfile());
173 const bool rc = function();
174 FILE *file = SetStreamOut(save);
175
176 const bool empty = ftell(file)==0;
177
178 rewind(file);
179
180 if (empty)
181 {
182 out << " <empty>" << endl;
183 fclose(file);
184 return rc;
185 }
186
187 while (1)
188 {
189 const int c = getc(file);
190 if (feof(file))
191 break;
192 out << (char)c;
193 }
194 out << endl;
195
196 fclose(file);
197
198 return rc;
199}
200
201// --------------------------------------------------------------------------
202//
203//! Redirected from rl_getc_function, calls Getc
204//
205int Readline::rl_ncurses_getc(FILE *f)
206{
207 return This->Getc(f);
208}
209
210// --------------------------------------------------------------------------
211//
212//! Redirected from rl_startup_hook, calls Startup.
213//! A function called just before readline prints the first prompt.
214//
215int Readline::rl_ncurses_startup()
216{
217 This->Startup();
218 return 0; // What is this for?
219}
220
221// --------------------------------------------------------------------------
222//
223//! Redirected from rl_redisplay_function, calls Redisplay.
224//! Readline will call indirectly to update the display with the current
225//! contents of the editing buffer.
226//
227void Readline::rl_ncurses_redisplay()
228{
229 This->Redisplay();
230}
231
232// --------------------------------------------------------------------------
233//
234//! Redirected from rl_event_hook, calls Update().
235//! A function called periodically when readline is waiting for
236//! terminal input.
237//!
238int Readline::rl_ncurses_event_hook()
239{
240 This->EventHook();
241 return 0;
242}
243
244// --------------------------------------------------------------------------
245//
246//! Redirected from rl_completion_display_matches_hook,
247//! calls CompletionDisplayImp
248//!
249//! A function to be called when completing a word would normally display
250//! the list of possible matches. This function is called in lieu of
251//! Readline displaying the list. It takes three arguments:
252//! (char **matches, int num_matches, int max_length) where matches is
253//! the array of matching strings, num_matches is the number of strings
254//! in that array, and max_length is the length of the longest string in
255//! that array. Readline provides a convenience function,
256//! rl_display_match_list, that takes care of doing the display to
257//! Readline's output stream.
258//
259void Readline::rl_ncurses_completion_display(char **matches, int num, int max)
260{
261 This->CompletionDisplay(matches, num, max);
262}
263
264char **Readline::rl_ncurses_completion_function(const char *text, int start, int end)
265{
266 return This->Completion(text, start, end);
267}
268
269// --------------------------------------------------------------------------
270//
271//! Calls the default rl_getc function.
272//
273int Readline::Getc(FILE *f)
274{
275 return rl_getc(f);
276}
277
278// --------------------------------------------------------------------------
279//
280//! Default: Do nothing.
281//
282void Readline::Startup()
283{
284}
285
286// --------------------------------------------------------------------------
287//
288//! The default is to redisplay the prompt which is gotten from
289//! GetUpdatePrompt(). If GetUpdatePrompt() returns an empty string the
290//! prompt is kept untouched. This can be used to keep a prompt updated
291//! with some information (e.g. time) just by overwriting GetUpdatePrompt()
292//!
293void Readline::EventHook()
294{
295 const string p = GetUpdatePrompt();
296 if (p.empty())
297 return;
298
299 UpdatePrompt("");
300 Redisplay();
301 UpdatePrompt(p);
302 Redisplay();
303}
304
305// --------------------------------------------------------------------------
306//
307//! Called from Prompt and PromptEOF after readline has returned. It is
308//! meant as the opposite of Startup (called after readline finsihes)
309//! The default is to do nothing.
310//!
311//! @param buf
312//! A pointer to the buffer returned by readline
313//
314void Readline::Shutdown(const char *)
315{
316}
317
318// --------------------------------------------------------------------------
319//
320//! Default: call rl_redisplay()
321//
322void Readline::Redisplay()
323{
324 rl_redisplay();
325}
326
327// --------------------------------------------------------------------------
328//
329//! Default: call rl_completion_display_matches()
330//
331void Readline::CompletionDisplay(char **matches, int num, int max)
332{
333 rl_display_match_list(matches, num, max);
334}
335
336// --------------------------------------------------------------------------
337//
338//! This is a static helper for the compilation of a completion-list.
339//! It compares the two inputs (str and txt) to a maximum of the size of
340//! txt. If they match, memory is allocated with malloc and a pointer to
341//! the null-terminated version of str is returned.
342//!
343//! @param str
344//! A reference to the string which is checked (e.g. "Makefile.am")
345//!
346//! @param txt
347//! A reference to the part of the string the user has already typed,
348//! e.g. "Makef"
349//!
350//! @returns
351//! A pointer to memory allocated with malloc containing the string str
352//
353char *Readline::Compare(const string &str, const string &txt)
354{
355 /*return strncmp(str.c_str(), txt.c_str(), txt.length())==0 ? */
356 return strncasecmp(str.c_str(), txt.c_str(), txt.length())==0 ?
357 strndup(str.c_str(), str.length()) : 0;
358}
359
360char **Readline::CompletionMatches(const char *text, char *(*func)(const char*, int))
361{
362 return rl_completion_matches(text, func);
363}
364
365// --------------------------------------------------------------------------
366//
367//! The given vector should be a reference to a vector of strings
368//! containing all possible matches. The actual match-making is then
369//! done in Complete(const char *, int)
370//!
371//! The pointer fCompletion is redirected to the vector for the run time
372//! of the function, but restored afterwards. So by this you can set a
373//! default completion list in case Complete is not called or Completion
374//! not overloaded.
375//!
376//! @param v
377//! reference to a vector of strings with all possible matches
378//!
379//! @param text
380//! the text which should be matched (it is just propagated to
381//! Readline::Completion)
382//!
383char **Readline::Complete(const vector<string> &v, const char *text)
384{
385 const vector<string> *save = fCompletion;
386
387 fCompletion = &v;
388 char **rc = rl_completion_matches(const_cast<char*>(text), CompleteImp);
389 fCompletion = save;
390
391 return rc;
392}
393
394// --------------------------------------------------------------------------
395//
396//! If fCompletion==0 the default is to call readline's
397//! rl_filename_completion_function. Otherwise the contents of fCompletion
398//! are returned. To change fCompletion either initialize it via
399//! SetCompletion() (in this case you must ensure the life time of the
400//! object) or call
401//! Complete(const vector<string>&, const char*)
402//! from
403//! Completion(const char * int, int)
404//!
405//! This is the so called generator function, the readline manual says
406//! about this function:
407//!
408//! The generator function is called repeatedly from
409//! rl_completion_matches(), returning a string each time. The arguments
410//! to the generator function are text and state. text is the partial word
411//! to be completed. state is zero the first time the function is called,
412//! allowing the generator to perform any necessary initialization, and a
413//! positive non-zero integer for each subsequent call. The generator
414//! function returns (char *)NULL to inform rl_completion_matches() that
415//! there are no more possibilities left. Usually the generator function
416//! computes the list of possible completions when state is zero, and
417//! returns them one at a time on subsequent calls. Each string the
418//! generator function returns as a match must be allocated with malloc();
419//! Readline frees the strings when it has finished with them.
420//
421char *Readline::Complete(const char* text, int state)
422{
423 if (fCompletion==0)
424 return rl_filename_completion_function(text, state);
425
426 static vector<string>::const_iterator pos;
427 if (state==0)
428 pos = fCompletion->begin();
429
430 while (pos!=fCompletion->end())
431 {
432 char *rc = Compare(*pos++, text);
433 if (rc)
434 return rc;
435 }
436
437 return 0;
438}
439
440// --------------------------------------------------------------------------
441//
442//! Calls Complete()
443//
444char *Readline::CompleteImp(const char* text, int state)
445{
446 return This->Complete(text, state);
447}
448
449// --------------------------------------------------------------------------
450//
451//! The readline manual says about this function:
452//!
453//! A pointer to an alternative function to create matches. The
454//! function is called with text, start, and end. start and end are
455//! indices in rl_line_buffer saying what the boundaries of text are.
456//! If this function exists and returns NULL, or if this variable is
457//! set to NULL, then rl_complete() will call the value of
458//! rl_completion_entry_function to generate matches, otherwise the
459//! array of strings returned will be used.
460//!
461//! This function is virtual and can be overwritten. It defaults to
462//! a call to rl_completion_matches with CompleteImp as an argument
463//! which defaults to filename completion, but can also be overwritten.
464//!
465//! It is suggested that you call
466//! Complete(const vector<string>&, const char*)
467//! from here.
468//!
469//! @param text
470//! A pointer to a char array conatining the text which should be
471//! completed. The text is null-terminated.
472//!
473//! @param start
474//! The start index within readline's line buffer rl_line_buffer,
475//! at which the text starts which presumably should be completed.
476//!
477//! @param end
478//! The end index within readline's line buffer rl_line_buffer,
479//! at which the text ends which presumably should be completed.
480//!
481//! @returns
482//! An array of strings which were allocated with malloc and which
483//! will be freed by readline with the possible matches.
484//
485char **Readline::Completion(const char *text, int /*start*/, int /*end*/)
486{
487 // To do filename completion call
488 return rl_completion_matches((char*)text, CompleteImp);
489}
490
491// --------------------------------------------------------------------------
492//
493//! Adds the given string to the history buffer of readline's history by
494//! calling add_history.
495//!
496//! @param str
497//! A reference to a string which should be added to readline's
498//! history.
499//!
500//! @param skip
501//! If skip is 1 and str matches the last added entry in the history,
502//! the entry is skipped. If skip==2, all entries matching str are
503//! removed from the history before the new entry is added as last one.
504//! <skip==2 is the default>
505//
506void Readline::AddToHistory(const string &str, int skip)
507{
508 if (skip==1 && fLastLine==str)
509 return;
510
511 if (str.empty())
512 return;
513
514 int p = -1;
515 while (skip==2)
516 {
517 p = history_search_pos(str.c_str(), 0, p+1);
518 if (p<0)
519 break;
520
521 // It seems like history_search_pos works more like
522 // history_search_prefix, therefore the identity is checked again
523 const HIST_ENTRY *e = history_get(p+1);
524 if (e && str==e->line)
525 free(remove_history(p));
526 }
527
528 add_history(str.c_str());
529 fLastLine = str;
530}
531
532// --------------------------------------------------------------------------
533//
534//! @returns
535//! a string containing [{fLine}]
536//
537string Readline::GetLinePrompt() const
538{
539 ostringstream str;
540 str << '[' << fLine << ']';
541 return str.str();
542}
543
544// --------------------------------------------------------------------------
545//
546//! Calls rl_set_prompt. This can be used from readline's callback function
547//! to change the prompt while a call to the readline function is in
548//! progress.
549//!
550//! @param prompt
551//! The new prompt to be shown
552//
553void Readline::UpdatePrompt(const string &prompt) const
554{
555 rl_set_prompt(prompt.c_str());
556}
557
558// --------------------------------------------------------------------------
559//
560//! This function is used to bind a key sequence via a call to
561//! rl_bind_keyseq.
562//!
563//! Readline's manual says about this function:
564//!
565//! Bind the key sequence represented by the string keyseq to the
566//! function function, beginning in the current keymap. This makes
567//! new keymaps as necessary. The return value is non-zero if keyseq
568//! is invalid.
569//!
570//! Key sequences are escaped sequences of characters read from an input
571//! stream when a special key is pressed. This is necessary because
572//! there are usually more keys and possible combinations than ascii codes.
573//!
574//! Possible key sequences are for example:
575//! "\033OP" F1
576//! "\033[1;5A" Ctrl+up
577//! "\033[1;5B" Ctrl+down
578//! "\033[1;3A" Alt+up
579//! "\033[1;3B" Alt+down
580//! "\033[5;3~" Alt+page up
581//! "\033[6;3~" Alt+page down
582//! "\033+" Alt++
583//! "\033-" Alt+-
584//! "\033\t" Alt+tab
585//! "\033[1~" Alt+tab
586//!
587//! @param seq
588//! The key sequence to be bound
589//!
590//! @param func
591//! A function of type "int func(int, int)
592//
593void Readline::BindKeySequence(const char *seq, int (*func)(int, int))
594{
595 rl_bind_keyseq(seq, func);
596}
597
598// --------------------------------------------------------------------------
599//
600//! Calls rl_variable_dumper(1)
601//!
602//! Print the readline variable names and their current values
603//! to rl_outstream. If readable is non-zero, the list is formatted
604//! in such a way that it can be made part of an inputrc file and
605//! re-read.
606//!
607//! rl_outstream can be redirected using SetStreamOut()
608//!
609//! @returns
610//! always true
611//
612bool Readline::DumpVariables()
613{
614 rl_variable_dumper(1);
615 return true;
616}
617
618// --------------------------------------------------------------------------
619//
620//! Calls rl_function_dumper(1)
621//!
622//! Print the readline function names and the key sequences currently
623//! bound to them to rl_outstream. If readable is non-zero, the list
624//! is formatted in such a way that it can be made part of an inputrc
625//! file and re-read.
626//!
627//! rl_outstream can be redirected using SetStreamOut()
628//!
629//! @returns
630//! always true
631//
632bool Readline::DumpFunctions()
633{
634 rl_function_dumper(1);
635 return true;
636}
637
638// --------------------------------------------------------------------------
639//
640//! Calls rl_list_funmap_names()
641//!
642//! Print the names of all bindable Readline functions to rl_outstream.
643//!
644//! rl_outstream can be redirected using SetStreamOut()
645//!
646//! @returns
647//! always true
648//
649bool Readline::DumpFunmap()
650{
651 rl_list_funmap_names();
652 return true;
653}
654
655// --------------------------------------------------------------------------
656//
657//! Sets rl_outstream (the stdio stream to which Readline performs output)
658//! to the new stream.
659//!
660//! @param f
661//! The new stdio stream to which readline should perform its output
662//!
663//! @return
664//! The old stream to which readline was performing output
665//
666FILE *Readline::SetStreamOut(FILE *f)
667{
668 FILE *rc = rl_outstream;
669 rl_outstream = f;
670 return rc;
671}
672
673// --------------------------------------------------------------------------
674//
675//! Sets rl_instream (the stdio stream from which Readline reads input)
676//! to the new stream.
677//!
678//! @param f
679//! The new stdio stream from which readline should read its input
680//!
681//! @return
682//! The old stream from which readline was reading it input
683//
684FILE *Readline::SetStreamIn(FILE *f)
685{
686 FILE *rc = rl_instream;
687 rl_instream = f;
688 return rc;
689}
690
691// --------------------------------------------------------------------------
692//
693//! return rl_display_prompt (the prompt which should currently be
694//! displayed on the screen) while a readline command is in progress
695//
696string Readline::GetPrompt()
697{
698 return rl_display_prompt;
699}
700
701// --------------------------------------------------------------------------
702//
703//! return rl_line_buffer (the current input line which should currently be
704//! displayed on the screen) while a readline command is in progress
705//!
706//! The length of the current line buffer (rl_end) is available as
707//! GetLineBuffer().size()
708//!
709//! Note that after readline has returned the contents of rl_end might
710//! not reflect the correct buffer length anymore, hence, the returned buffer
711//! might be truncated.
712//
713string Readline::GetBuffer()
714{
715 return string(rl_line_buffer, rl_end);
716}
717
718// --------------------------------------------------------------------------
719//
720//! return rl_point (the current cursor position within the line buffer)
721//
722int Readline::GetCursor()
723{
724 return rl_point;
725}
726
727// --------------------------------------------------------------------------
728//
729//! return strlen(rl_display_prompt) + rl_point
730//
731int Readline::GetAbsCursor()
732{
733 return strlen(rl_display_prompt) + rl_point;
734}
735
736// --------------------------------------------------------------------------
737//
738//! return rl_end (the current total length of the line buffer)
739//! Note that after readline has returned the contents of rl_end might
740//! not reflect the correct buffer length anymore.
741//
742int Readline::GetBufferLength()
743{
744 return rl_end;
745}
746
747// --------------------------------------------------------------------------
748//
749//! return the length of the prompt plus the length of the line buffer
750//
751int Readline::GetLineLength()
752{
753 return strlen(rl_display_prompt) + rl_end;
754}
755
756// --------------------------------------------------------------------------
757//
758//! Calls: Function: void rl_resize_terminal()
759//! Update Readline's internal screen size by reading values from the kernel.
760//
761void Readline::Resize()
762{
763 rl_resize_terminal();
764}
765
766// --------------------------------------------------------------------------
767//
768//! Calls: Function: void rl_set_screen_size (int rows, int cols)
769//! Set Readline's idea of the terminal size to rows rows and cols columns.
770//!
771//! @param width
772//! Number of columns
773//!
774//! @param height
775//! Number of rows
776//
777void Readline::Resize(int width, int height)
778{
779 rl_set_screen_size(height, width);
780}
781
782// --------------------------------------------------------------------------
783//
784//! Get the number of cols readline assumes the screen size to be
785//
786int Readline::GetCols() const
787{
788 int rows, cols;
789 rl_get_screen_size(&rows, &cols);
790 return cols;
791}
792
793// --------------------------------------------------------------------------
794//
795//! Get the number of rows readline assumes the screen size to be
796//
797int Readline::GetRows() const
798{
799 int rows, cols;
800 rl_get_screen_size(&rows, &cols);
801 return rows;
802}
803
804// --------------------------------------------------------------------------
805//
806//! Return a list of pointer to the history contents
807//
808vector<const char*> Readline::GetHistory() const
809{
810 HIST_ENTRY **next = history_list();
811
812 vector<const char*> v;
813
814 for (; *next; next++)
815 v.push_back((*next)->line);
816
817 return v;
818}
819
820// --------------------------------------------------------------------------
821//
822//! Clear readline history (calls clear_history())
823//!
824//! @returns
825//! always true
826//
827bool Readline::ClearHistory()
828{
829 clear_history();
830 return true;
831}
832
833// --------------------------------------------------------------------------
834//
835//! Displays the current history on rl_outstream
836//!
837//! rl_outstream can be redirected using SetStreamOut()
838//!
839//! @returns
840//! always true
841//
842bool Readline::DumpHistory()
843{
844 HIST_ENTRY **next = history_list();
845
846 if (!next)
847 return true;
848
849 for (; *next; next++)
850 fprintf(rl_outstream, "%s\n", (*next)->line);
851
852 return true;
853}
854
855// --------------------------------------------------------------------------
856//
857//! Print the available commands. This is intended for being overwritten
858//! by deriving classes.
859//!
860//! rl_outstream can be redirected using SetStreamOut()
861//!
862//! @returns
863//! always true
864//
865//
866bool Readline::PrintCommands()
867{
868 fprintf(rl_outstream, "\n");
869 fprintf(rl_outstream, " Commands:\n");
870 fprintf(rl_outstream, " No application specific commands defined.\n");
871 fprintf(rl_outstream, "\n");
872 return true;
873}
874
875// --------------------------------------------------------------------------
876//
877//! Print a general help message. This is intended for being overwritten
878//! by deriving classes.
879//!
880//!
881//! rl_outstream can be redirected using SetStreamOut()
882//!
883//! @returns
884//! always true
885//
886//
887bool Readline::PrintGeneralHelp()
888{
889 fprintf(rl_outstream, "\n");
890 fprintf(rl_outstream, " General help:\n");
891 fprintf(rl_outstream, " h,help Print this help message\n");
892 fprintf(rl_outstream, " clear Clear history buffer\n");
893 fprintf(rl_outstream, " lh,history Dump the history buffer to the screen\n");
894 fprintf(rl_outstream, " v,variables Dump readline variables\n");
895 fprintf(rl_outstream, " f,functions Dump readline functions\n");
896 fprintf(rl_outstream, " m,funmap Dump readline funmap\n");
897 fprintf(rl_outstream, " c,commands Dump available commands\n");
898 fprintf(rl_outstream, " k,keylist Dump key bindings\n");
899 fprintf(rl_outstream, " .w n Sleep n milliseconds\n");
900 fprintf(rl_outstream, " .x filename Execute a script of commands\n");
901 fprintf(rl_outstream, " .q,quit Quit\n");
902 fprintf(rl_outstream, "\n");
903 fprintf(rl_outstream, " The command history is automatically loaded and saves to\n");
904 fprintf(rl_outstream, " and from %s.\n", GetName().c_str());
905 fprintf(rl_outstream, "\n");
906 return true;
907}
908
909// --------------------------------------------------------------------------
910//
911//! Print a help text about key bindings. This is intended for being
912//! overwritten by deriving classes.
913//!
914//!
915//! rl_outstream can be redirected using SetStreamOut()
916//!
917//! @returns
918//! always true
919//
920//
921bool Readline::PrintKeyBindings()
922{
923 fprintf(rl_outstream, "\n");
924 fprintf(rl_outstream, " Key bindings:\n");
925 fprintf(rl_outstream, " Page-up Search backward in history\n");
926 fprintf(rl_outstream, " Page-dn Search forward in history\n");
927 fprintf(rl_outstream, " Ctrl-left One word backward\n");
928 fprintf(rl_outstream, " Ctrl-right One word forward\n");
929 fprintf(rl_outstream, " Ctrl-d Quit\n");
930 fprintf(rl_outstream, " Ctrl-y Delete line\n");
931 fprintf(rl_outstream, " Alt-end/Ctrl-k Delete until the end of the line\n");
932 fprintf(rl_outstream, " F1 Toggle visibility of upper panel\n");
933 fprintf(rl_outstream, "\n");
934 fprintf(rl_outstream, " Default key-bindings are identical with your bash.\n");
935 fprintf(rl_outstream, "\n");
936 return true;
937}
938
939// --------------------------------------------------------------------------
940//
941//!
942//
943bool Readline::Process(const string &str)
944{
945 if (str.substr(0, 3)==".w ")
946 {
947 usleep(atoi(str.c_str()+3)*1000);
948 return true;
949 }
950
951 if (str.substr(0, 3)==".x ")
952 {
953 Execute(str.substr(3));
954 return true;
955 }
956
957 // ----------- Readline static -------------
958
959 if (str=="clear")
960 return ClearHistory();
961
962 if (str=="lh" || str=="history")
963 return DumpHistory();
964
965 if (str=="v" || str=="variables")
966 return DumpVariables();
967
968 if (str=="f" || str=="functions")
969 return DumpFunctions();
970
971 if (str=="m" || str=="funmap")
972 return DumpFunmap();
973
974 // ---------- Readline virtual -------------
975
976 if (str=="h" || str=="help")
977 return PrintGeneralHelp();
978
979 if (str=="c" || str=="commands")
980 return PrintCommands();
981
982 if (str=="k" || str=="keylist")
983 return PrintKeyBindings();
984
985 return false;
986}
987
988// --------------------------------------------------------------------------
989//
990//! This function is a wrapper around the call to readline. It encapsultes
991//! the return buffer into a std::string and deletes the memory allocated
992//! by readline. Furthermore, it removes leading and trailing whitespaces
993//! before return the result. The result is returned in the given
994//! argument containing the prompt. Before the function returns Shutdown()
995//! is called (as opposed to Startup when readline starts)
996//!
997//! @param str
998//! The prompt which is to be shown by the readline libarary. it is
999//! directly given to the call to readline. The result of the
1000//! readline call is returned in this string.
1001//!
1002//! @returns
1003//! true if the call succeeded as usual, false if EOF was detected
1004//! by the readline call.
1005//
1006bool Readline::PromptEOF(string &str)
1007{
1008 char *buf = readline(str.c_str());
1009 Shutdown(buf);
1010
1011 // Happens when EOF is encountered
1012 if (!buf)
1013 return false;
1014
1015 str = Tools::Trim(buf);
1016
1017 free(buf);
1018
1019 return true;
1020}
1021
1022// --------------------------------------------------------------------------
1023//
1024//! This function is a wrapper around the call to readline. It encapsultes
1025//! the return buffer into a std::string and deletes the memory allocated
1026//! by readline. Furthermore, it removes leading and trailing whitespaces
1027//! before return the result. Before the function returns Shutdown() is
1028//! called (as opposed to Startup when readline starts)
1029//!
1030//! @param prompt
1031//! The prompt which is to be shown by the readline libarary. it is
1032//! directly given to the call to readline.
1033//!
1034//! @returns
1035//! The result of the readline call
1036//
1037string Readline::Prompt(const string &prompt)
1038{
1039 char *buf = readline(prompt.c_str());
1040
1041 Shutdown(buf ? buf : "");
1042
1043 const string str = !buf || (rl_done && rl_pending_input==4)
1044 ? ".q" : Tools::Trim(buf);
1045
1046 free(buf);
1047
1048 return str;
1049}
1050
1051// --------------------------------------------------------------------------
1052//
1053//! This implements a loop over readline calls. A prompt to issue can be
1054//! given. If it is NULL, the prompt is retrieved from GetUpdatePrompt().
1055//! It is updated regularly by means of calls to GetUpdatePrompt() from
1056//! EventHook(). If Prompt() returns with "quit" or ".q" the loop is
1057//! exited. If ".qqq" is entered exit(-1) is called. In case of ".qqqqqq"
1058//! abort(). Both ways to exit the program are not recommended. Empty
1059//! inputs are ignored. After that Process() with the returned string
1060//! is called. If Process returns true the input is not counted and not
1061//! added to the history, otherwise the line counter is increased
1062//! and the input is added to the history.
1063//!
1064//! @param prompt
1065//! The prompt to be issued or NULL if GetUPdatePrompt should be used
1066//! instead.
1067//!
1068void Readline::Run(const char *prompt)
1069{
1070 fLine = 0;
1071 while (1)
1072 {
1073 // Before we start we have to make sure that the
1074 // screen looks like and is ordered like expected.
1075 const string str = Prompt(prompt?prompt:GetUpdatePrompt());
1076 if (str.empty())
1077 continue;
1078
1079 if (str=="quit" || str==".q")
1080 break;
1081
1082 if (str==".qqq")
1083 exit(-1);
1084
1085 if (str==".qqqqqq")
1086 abort();
1087
1088 if (Process(str))
1089 continue;
1090
1091 fLine++;
1092
1093 AddToHistory(str);
1094 }
1095}
1096
1097// --------------------------------------------------------------------------
1098//
1099//! Executes commands read from an ascii file as they were typed in
1100//! the console. Empty lines and lines beginning with # are ignored.
1101//!
1102//! @param fname
1103//! Filename of file to read
1104//!
1105//! @returns
1106//! -1 if the file couldn't be read and the number of command for which
1107//! Process() was callled otherwise
1108//!
1109int Readline::Execute(const string &fname)
1110{
1111 int rc = 0;
1112
1113 ifstream fin(Tools::Trim(fname).c_str());
1114 if (!fin)
1115 return -1;
1116
1117 string buffer;
1118 while (getline(fin, buffer, '\n'))
1119 {
1120 buffer = Tools::Trim(buffer);
1121 if (buffer.empty())
1122 continue;
1123
1124 if (buffer[0]=='#')
1125 continue;
1126
1127 rc++;
1128
1129 if (Process(buffer))
1130 continue;
1131
1132 fLine++;
1133
1134 AddToHistory(buffer);
1135 }
1136
1137 return rc;
1138}
1139
1140// --------------------------------------------------------------------------
1141//
1142//! Stops the readline execution. It fakes the end of an editing by
1143//! setting rl_done to 1. To distinguish this from a normal edit,
1144//! rl_pending_input is set to EOT.
1145//!
1146void Readline::Stop()
1147{
1148 rl_done = 1;
1149 rl_pending_input = 4; // EOT (end of transmission, ctrl-d)
1150}
Note: See TracBrowser for help on using the repository browser.