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

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