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

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