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

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