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

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