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

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