source: trunk/FACT++/src/Console.cc@ 16881

Last change on this file since 16881 was 16869, checked in by tbretz, 11 years ago
When we output something ourselves before the event hook is called in readline, we have to signal readline that we have started a new row, so that readline can properly update the prompt. I hope this finally solves the flickering issue on my laptop and/or the problematic display in the fadctrl.
File size: 7.0 KB
Line 
1// **************************************************************************
2/** @class Console
3
4@brief This is an extension to the Readline class provding buffered output
5
6This in an extension to the Readline class. It's purpose is to keep a
7buffered output stream and flush the stream either between readline entries
8(non continous mode) or continously, keeping the readline prompt as
9intact as possible.
10
11 */
12// **************************************************************************
13#include "Console.h"
14
15#include <sstream>
16#include <iostream>
17
18#include "tools.h"
19
20#include "ReadlineColor.h"
21
22using namespace std;
23
24// --------------------------------------------------------------------------
25//
26//! Instantiate a console stream. It will create a WindowLog object
27//! and immediatel switch off its output to the console. The default more
28//! is non-continous.
29//!
30//! @param name
31//! The name of the program passed to the Readline constructor
32//!
33Console::Console(const char *name) : Readline(name), fContinous(false)
34{
35 fLogO.SetNullOutput();
36 fLogI.SetNullOutput();
37 fLogO.SetBacklog(true);
38 fLogI.SetBacklog(true);
39}
40
41// --------------------------------------------------------------------------
42//
43//! Flush the contents of the buffer before it is destroyed.
44//
45Console::~Console()
46{
47 // flush buffer to display before it is destroyed in its destructor
48 fLogO.Display();
49 fLogI.Display();
50}
51
52void Console::PrintReadlineError(const std::string &str)
53{
54 fLogI << kRed << str << endl;
55}
56
57// --------------------------------------------------------------------------
58//
59//! Wrapper to call the correspnding function from ReadlineColor
60//
61bool Console::PrintGeneralHelp()
62{
63 return ReadlineColor::PrintGeneralHelp(fLogI, GetName());
64}
65
66// --------------------------------------------------------------------------
67//
68//! Wrapper to call the correspnding function from ReadlineColor
69//
70bool Console::PrintCommands()
71{
72 return ReadlineColor::PrintCommands(fLogI);
73}
74
75// --------------------------------------------------------------------------
76//
77//! Wrapper to call the correspnding function from ReadlineColor
78//
79bool Console::PrintKeyBindings()
80{
81 return ReadlineColor::PrintKeyBindings(fLogI);
82}
83
84void Console::Lock()
85{
86 // FIXME: Check missing
87 fLogO.Display(true);
88 fLogO.SetBacklog(false);
89 fLogO.SetNullOutput(false);
90}
91
92void Console::Unlock()
93{
94 // FIXME: Check missing
95 fLogO.SetNullOutput(true);
96 fLogO.SetBacklog(true);
97}
98
99// --------------------------------------------------------------------------
100//
101//! Processes the command provided by the Shell-class.
102//!
103//! @returns
104//! whether a command was successfully processed or could not be found
105//
106bool Console::Process(const string &str)
107{
108 if (ReadlineColor::Process(fLogI, str))
109 return true;
110
111 if (str.substr(0, 3)==".w ")
112 {
113 Lock();
114 usleep(stoul(str.substr(3))*1000);
115 Unlock();
116 return true;
117 }
118
119 if (Readline::Process(str))
120 return true;
121
122 return false;
123}
124
125// --------------------------------------------------------------------------
126//
127//! Before readline starts flush the buffer to display all stuff which was
128//! buffered since the last readline call returned.
129//
130void Console::Startup()
131{
132 // Call readline's startup (just in case, it is empty)
133 Readline::Startup();
134
135 // First flush the buffer of the stream which is synchronous
136 // with the prompt
137 fLogI.Display(true);
138
139 // Now flush the stream which is asychronous
140 fLogO.Display(true);
141
142 // The order has the advantage that output initiated by the prompt
143 // is not interrupter by the synchronous stream
144}
145
146// --------------------------------------------------------------------------
147//
148//! Flush the buffer if we are in continous mode, and call Readline's
149//! EventHook to update the prompt.
150//
151void Console::EventHook(bool)
152{
153 // If the output is continous and we are going to output something
154 // first jump back to the beginning of the line (well, that
155 // doesn't work well if the input line is already two lines)
156 // and then flush the buffer.
157 const bool newline = fContinous && fLogO.GetSizeBacklog()>0;
158 if (newline)
159 {
160 // Clear the line we are going to overwrite
161 std::cout << "\r\033[0K";
162 fLogO.Display(true);
163 }
164
165 // Call Readline's EventHook to update the prompt
166 Readline::EventHook(newline);
167}
168
169string Console::GetLinePrompt() const
170{
171 const string siz = fLogO.GetSizeStr();
172
173 ostringstream str;
174 str << '[' << GetLine();
175 return fContinous ? str.str()+']' : str.str()+':'+siz+']';
176}
177
178// --------------------------------------------------------------------------
179//
180//! Before Readline::Run() is called the buffer is flushed as well as
181//! after the Run() loop has exited.
182//! command processing. This keeps things as seperated as possible,
183//! although there is no gurantee.
184//
185void Console::Run(const char *)
186{
187 // Flush the buffer before we print the boot message
188 fLogO.Display(true);
189
190 ReadlineColor::PrintBootMsg(fLogI, GetName());
191
192 // Flush the buffer before we start out readline loop
193 fLogI.Display(true);
194 fLogO.Display(true);
195
196 // Now run readlines main loop
197 Readline::Run();
198
199 // flush buffer to display
200 fLogI.Display(true);
201 fLogO.Display(true);
202}
203
204// **************************************************************************
205/** @class ConsoleStream
206
207@brief This is an extension to the Readline class provding a colored output
208
209This in an extension to the Readline class. It's purpose is just to have a
210colored output stream available. It's main idea is that it is used in
211environments without user interaction as a replacement the Console class.
212This is interesting to be able to do everything identical as if Console
213would be used, but Run() does not prompt but just wait until Stop()
214was called. The advantage is that some functions of Readline can be used
215like Execute and the history (just for Execute() commands of course)
216
217 */
218// **************************************************************************
219
220ConsoleStream::~ConsoleStream()
221{
222 fLogO.Display();
223}
224
225// --------------------------------------------------------------------------
226//
227//! Instantiate a console stream. It will create a single WindowLog object
228//! which is returned as input and output stream.
229//!
230//! @param name
231//! The name of the program passed to the Readline constructor
232//!
233ConsoleStream::ConsoleStream(const char *name) : Readline(name)
234{
235 fLogO.SetBacklog(false);
236 fLogO.SetNullOutput(false);
237 ReadlineColor::PrintBootMsg(fLogO, GetName(), false);
238}
239
240void ConsoleStream::PrintReadlineError(const std::string &str)
241{
242 fLogO << kRed << str << endl;
243}
244
245// --------------------------------------------------------------------------
246//
247//! Just usleep until Stop() was called.
248//
249void ConsoleStream::Run(const char *)
250{
251 while (!IsStopped())
252 {
253 const string buf = GetExternalInput();
254 SetExternalInput("");
255 if (!buf.empty())
256 ProcessLine(buf);
257
258 usleep(100000);
259 }
260}
Note: See TracBrowser for help on using the repository browser.