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

Last change on this file since 10691 was 10654, checked in by tbretz, 13 years ago
Added script execution.
File size: 32.5 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, " .x filename Execute a script of commands\n");
900 fprintf(rl_outstream, " .q,quit Quit\n");
901 fprintf(rl_outstream, "\n");
902 fprintf(rl_outstream, " The command history is automatically loaded and saves to\n");
903 fprintf(rl_outstream, " and from %s.\n", GetName().c_str());
904 fprintf(rl_outstream, "\n");
905 return true;
906}
907
908// --------------------------------------------------------------------------
909//
910//! Print a help text about key bindings. This is intended for being
911//! overwritten by deriving classes.
912//!
913//!
914//! rl_outstream can be redirected using SetStreamOut()
915//!
916//! @returns
917//! always true
918//
919//
920bool Readline::PrintKeyBindings()
921{
922 fprintf(rl_outstream, "\n");
923 fprintf(rl_outstream, " Key bindings:\n");
924 fprintf(rl_outstream, " Page-up Search backward in history\n");
925 fprintf(rl_outstream, " Page-dn Search forward in history\n");
926 fprintf(rl_outstream, " Ctrl-left One word backward\n");
927 fprintf(rl_outstream, " Ctrl-right One word forward\n");
928 fprintf(rl_outstream, " Ctrl-d Quit\n");
929 fprintf(rl_outstream, " Ctrl-y Delete line\n");
930 fprintf(rl_outstream, " Alt-end/Ctrl-k Delete until the end of the line\n");
931 fprintf(rl_outstream, " F1 Toggle visibility of upper panel\n");
932 fprintf(rl_outstream, "\n");
933 fprintf(rl_outstream, " Default key-bindings are identical with your bash.\n");
934 fprintf(rl_outstream, "\n");
935 return true;
936}
937
938// --------------------------------------------------------------------------
939//
940//!
941//
942bool Readline::Process(const string &str)
943{
944 if (str.substr(0, 3)==".x ")
945 {
946 Execute(str.substr(3));
947 return true;
948 }
949
950 // ----------- Readline static -------------
951
952 if (str=="clear")
953 return ClearHistory();
954
955 if (str=="lh" || str=="history")
956 return DumpHistory();
957
958 if (str=="v" || str=="variables")
959 return DumpVariables();
960
961 if (str=="f" || str=="functions")
962 return DumpFunctions();
963
964 if (str=="m" || str=="funmap")
965 return DumpFunmap();
966
967 // ---------- Readline virtual -------------
968
969 if (str=="h" || str=="help")
970 return PrintGeneralHelp();
971
972 if (str=="c" || str=="commands")
973 return PrintCommands();
974
975 if (str=="k" || str=="keylist")
976 return PrintKeyBindings();
977
978 return false;
979}
980
981// --------------------------------------------------------------------------
982//
983//! This function is a wrapper around the call to readline. It encapsultes
984//! the return buffer into a std::string and deletes the memory allocated
985//! by readline. Furthermore, it removes leading and trailing whitespaces
986//! before return the result. The result is returned in the given
987//! argument containing the prompt. Before the function returns Shutdown()
988//! is called (as opposed to Startup when readline starts)
989//!
990//! @param str
991//! The prompt which is to be shown by the readline libarary. it is
992//! directly given to the call to readline. The result of the
993//! readline call is returned in this string.
994//!
995//! @returns
996//! true if the call succeeded as usual, false if EOF was detected
997//! by the readline call.
998//
999bool Readline::PromptEOF(string &str)
1000{
1001 char *buf = readline(str.c_str());
1002 Shutdown(buf);
1003
1004 // Happens when EOF is encountered
1005 if (!buf)
1006 return false;
1007
1008 str = Tools::Trim(buf);
1009
1010 free(buf);
1011
1012 return true;
1013}
1014
1015// --------------------------------------------------------------------------
1016//
1017//! This function is a wrapper around the call to readline. It encapsultes
1018//! the return buffer into a std::string and deletes the memory allocated
1019//! by readline. Furthermore, it removes leading and trailing whitespaces
1020//! before return the result. Before the function returns Shutdown() is
1021//! called (as opposed to Startup when readline starts)
1022//!
1023//! @param prompt
1024//! The prompt which is to be shown by the readline libarary. it is
1025//! directly given to the call to readline.
1026//!
1027//! @returns
1028//! The result of the readline call
1029//
1030string Readline::Prompt(const string &prompt)
1031{
1032 char *buf = readline(prompt.c_str());
1033
1034 Shutdown(buf ? buf : "");
1035
1036 const string str = !buf || (rl_done && rl_pending_input==4)
1037 ? ".q" : Tools::Trim(buf);
1038
1039 free(buf);
1040
1041 return str;
1042}
1043
1044// --------------------------------------------------------------------------
1045//
1046//! This implements a loop over readline calls. A prompt to issue can be
1047//! given. If it is NULL, the prompt is retrieved from GetUpdatePrompt().
1048//! It is updated regularly by means of calls to GetUpdatePrompt() from
1049//! EventHook(). If Prompt() returns with "quit" or ".q" the loop is
1050//! exited. If ".qqq" is entered exit(-1) is called. In case of ".qqqqqq"
1051//! abort(). Both ways to exit the program are not recommended. Empty
1052//! inputs are ignored. After that Process() with the returned string
1053//! is called. If Process returns true the input is not counted and not
1054//! added to the history, otherwise the line counter is increased
1055//! and the input is added to the history.
1056//!
1057//! @param prompt
1058//! The prompt to be issued or NULL if GetUPdatePrompt should be used
1059//! instead.
1060//!
1061void Readline::Run(const char *prompt)
1062{
1063 fLine = 0;
1064 while (1)
1065 {
1066 // Before we start we have to make sure that the
1067 // screen looks like and is ordered like expected.
1068 const string str = Prompt(prompt?prompt:GetUpdatePrompt());
1069 if (str.empty())
1070 continue;
1071
1072 if (str=="quit" || str==".q")
1073 break;
1074
1075 if (str==".qqq")
1076 exit(-1);
1077
1078 if (str==".qqqqqq")
1079 abort();
1080
1081 if (Process(str))
1082 continue;
1083
1084 fLine++;
1085
1086 AddToHistory(str);
1087 }
1088}
1089
1090// --------------------------------------------------------------------------
1091//
1092//! Executes commands read from an ascii file as they were typed in
1093//! the console. Empty lines and lines beginning with # are ignored.
1094//!
1095//! @param fname
1096//! Filename of file to read
1097//!
1098//! @returns
1099//! -1 if the file couldn't be read and the number of command for which
1100//! Process() was callled otherwise
1101//!
1102int Readline::Execute(const string &fname)
1103{
1104 int rc = 0;
1105
1106 ifstream fin(Tools::Trim(fname).c_str());
1107 if (!fin)
1108 return -1;
1109
1110 string buffer;
1111 while (getline(fin, buffer, '\n'))
1112 {
1113 buffer = Tools::Trim(buffer);
1114 if (buffer.empty())
1115 continue;
1116
1117 if (buffer[0]=='#')
1118 continue;
1119
1120 rc++;
1121
1122 if (Process(buffer))
1123 continue;
1124
1125 fLine++;
1126
1127 AddToHistory(buffer);
1128 }
1129
1130 return rc;
1131}
1132
1133void Readline::Stop()
1134{
1135 rl_done = 1;
1136 rl_pending_input = 4; // EOT (end of transmission, ctrl-d)
1137}
Note: See TracBrowser for help on using the repository browser.