source: trunk/FACT++/src/RemoteControl.h@ 13296

Last change on this file since 13296 was 13286, checked in by tbretz, 13 years ago
Changed # to be a real comment and > to be a comment writting to the log-files.
File size: 9.8 KB
Line 
1#ifndef FACT_RemoteControl
2#define FACT_RemoteControl
3
4// **************************************************************************
5/** @class RemoteControlImp
6
7@brief This implements the basic functions of a remote control via dim
8
9Through a ServiceList object this object subscribes to all available
10SERVICE_LISTs in the dim network. This allows to keep an up-to-date
11list of all servers and services. Its ProcessCommand member function
12allows to emit commands according to the services found in the network.
13Its infoHandler() is called as an update notifier from the ClientList
14object.
15
16**/
17// **************************************************************************
18#include "DimNetwork.h"
19
20class RemoteControlImp : public DimNetwork
21{
22protected:
23 std::ostream &lout; /// Output stream for local synchrounous output
24
25 std::string fCurrentServer; /// The server to which we currently cd'ed
26
27protected:
28 // Redirect asynchronous output to the output window
29 RemoteControlImp(std::ostream &out, std::ostream &in) :
30 DimNetwork(out), lout(in)
31 {
32 }
33 bool ProcessCommand(const std::string &str);
34};
35
36
37
38// **************************************************************************
39/** @class RemoteControl
40
41@brief Implements a remote control based on a Readline class for the dim network
42
43This template implements all functions which overwrite any function from the
44Readline class. Since several derivatives of the Readline class implement
45different kind of Readline access, this class can be derived by any of them
46due to its template argument. However, the normal case will be
47deriving it from either Console or Shell.
48
49@tparam T
50 The base class for RemoteControl. Either Readlien or a class
51 deriving from it. This is usually either Console or Shell.
52
53**/
54// **************************************************************************
55#include "WindowLog.h"
56#include "ReadlineColor.h"
57#include "tools.h"
58
59template <class T>
60class RemoteControl : public T, public RemoteControlImp
61{
62private:
63 MessageImp *fImp;
64
65 int32_t fLabel;
66
67 int Write(const Time &time, const std::string &txt, int qos=kMessage)
68 {
69 return fImp ? fImp->Write(time, txt, qos) : MessageImp::Write(time, txt, qos);
70 }
71
72 static void append(std::string &str)
73 {
74 str.append("/");
75 }
76 static void chop(std::string &str)
77 {
78 const size_t p = str.find_first_of('/');
79 if (p!=string::npos)
80 str = str.substr(p+1);
81 }
82
83 // This funtion defines which generator should be called.
84 // If it returns 0 the standard reaqdline generator are called.
85 // Otherwise set the right generator with rl_completion_matches.
86 char **Completion(const char *text, int start, int)
87 {
88 // Get the whole buffer before the tab-position
89 const string b = string(T::GetBuffer());
90 const string s = b.substr(0, start);
91 const string l = Tools::Trim(s.c_str());
92 if (l.empty())
93 {
94 if (fCurrentServer.empty())
95 {
96 const size_t p1 = b.find_first_of(' ');
97 const size_t p2 = b.find_first_of('/');
98
99 if (p1==string::npos && p2!=string::npos)
100 return T::Complete(GetCommandList(), text);
101
102 std::vector<std::string> v = GetServerList();
103 for_each(v.begin(), v.end(), RemoteControl::append);
104 return T::Complete(v, text);
105 }
106 else
107 {
108 std::vector<std::string> v = GetCommandList(fCurrentServer);
109 for_each(v.begin(), v.end(), RemoteControl::chop);
110 return T::Complete(v, text);
111 }
112 }
113 return T::Complete(GetCommandList(l), text);
114 }
115
116 void infoHandler()
117 {
118 RemoteControlImp::infoHandler();
119 if (!fCurrentServer.empty() && !HasServer(fCurrentServer))
120 {
121 fCurrentServer = "";
122 T::UpdatePrompt();
123 }
124 }
125
126public:
127 // Redirect asynchronous output to the output window
128 RemoteControl(const char *name) : T(name),
129 RemoteControlImp(T::GetStreamOut(), T::GetStreamIn()), fImp(0), fLabel(-1)
130 {
131 }
132
133 bool PrintGeneralHelp()
134 {
135 T::PrintGeneralHelp();
136 lout << " " << kUnderline << "Specific commands:\n";
137 lout << kBold << " h,help <arg> " << kReset << "List help text for given server or command.\n";
138// lout << kBold << " s,servers " << kReset << "List all servers which are connected." << endl;
139 lout << kBold << " svc,services " << kReset << "List all services in the network.\n";
140 lout << kBold << " st,states " << kReset << "List all states in the network.\n";
141 lout << kBold << " > <text> " << kReset << "Echo <text> to the output stream\n";
142 lout << kBold << " .s " << kReset << "Wait for the state-machine to change to the given state.\n";
143 lout << " " " .s <server> [<state> [<timeout> [<label>]]]\n";
144 lout << " " "<server> The server for which state to wait (e.g. FTM_CONTROL)\n";
145 lout << " " "<state> The state id (see 'states') for which to wait (e.g. 3)\n";
146 lout << " " "<imeout> A timeout in millisenconds how long to wait (e.g. 500)\n";
147 lout << " " "<label> A label until which everything is skipped in case of timeout\n";
148 lout << endl;
149 return true;
150 }
151
152 bool PrintCommands()
153 {
154 lout << endl << kBold << "List of commands:" << endl;
155 PrintDescription(lout, true);
156 return true;
157 }
158
159 // returns whether a command should be put into the history
160 bool Process(const std::string &str)
161 {
162 if (str.substr(0, 2)=="h " || str.substr(0, 5)=="help ")
163 {
164 const size_t p1 = str.find_first_of(' ');
165 const string svc = str.substr(p1+1);
166
167 const size_t p3 = svc.find_first_of('/');
168 const string s = svc.substr(0, p3);
169 const string c = p3==string::npos?"":svc.substr(p3+1);
170
171 lout << endl;
172 if (!fCurrentServer.empty())
173 {
174 if (PrintDescription(lout, true, fCurrentServer, svc)==0)
175 lout << " " << svc << ": <not found>" << endl;
176 }
177 else
178 {
179 if (PrintDescription(lout, true, s, c)==0)
180 lout << " <no matches found>" <<endl;
181 }
182
183 return true;
184 }
185
186 if (str.substr(0, 3)==".s ")
187 {
188 istringstream in(str.substr(3));
189
190 int state=-100, ms=0;
191 string server;
192
193 in >> server >> state >> ms;
194 if (state==-100)
195 {
196 lout << kRed << "Couldn't parse state id in '" << str.substr(3) << "'" << endl;
197 return true;
198 }
199
200 const ClientList::const_iterator l = fClientList.find(server);
201 if (l==fClientList.end())
202 {
203 lout << kRed << "Server '" << server << "' not found." << endl;
204 return true;
205 }
206
207 const Time timeout = ms<=0 ? Time(Time::none) : Time()+boost::posix_time::millisec(ms);
208
209 T::GetStreamOut().Display(true);
210 T::GetStreamOut().SetBacklog(false);
211 T::GetStreamOut().SetNullOutput(false);
212 while (l->second->GetState()!=state && timeout>Time())
213 usleep(1);
214 T::GetStreamOut().SetNullOutput(true);
215 T::GetStreamOut().SetBacklog(true);
216
217 if (l->second->GetState()!=state)
218 {
219 int label = -1;
220 in >> label;
221 T::SetLabel(label);
222 }
223
224 return true;
225 }
226
227 if (str[0]=='#')
228 return true;
229
230 if (str[0]=='>')
231 {
232 fImp->Comment(Tools::Trim(str.substr(1)));
233 return true;
234 }
235
236 if (ReadlineColor::Process(lout, str))
237 return true;
238
239 if (T::Process(str))
240 return true;
241
242 if (str=="services" || str=="svc")
243 {
244 PrintDescription(lout, false);
245 return true;
246 }
247
248 if (str=="states" || str=="st")
249 {
250 PrintStates(lout);
251 return true;
252 }
253
254 return ProcessCommand(str);
255 }
256
257 void SetReceiver(MessageImp &imp) { fImp = &imp; }
258};
259
260
261
262// **************************************************************************
263/** @class RemoteConsole
264
265@brief Derives the RemoteControl from Control and adds a proper prompt
266
267This is basically a RemoteControl, which derives through the template
268argument from the Console class. It enhances the functionality of
269the remote control with a proper updated prompt.
270
271 */
272// **************************************************************************
273#include "Console.h"
274
275class RemoteConsole : public RemoteControl<Console>
276{
277public:
278 RemoteConsole(const char *name, bool continous=false) :
279 RemoteControl<Console>(name)
280 {
281 SetContinous(continous);
282 }
283 string GetUpdatePrompt() const;
284};
285
286// **************************************************************************
287/** @class RemoteShell
288
289@brief Derives the RemoteControl from Shell and adds colored prompt
290
291This is basically a RemoteControl, which derives through the template
292argument from the Shell class. It enhances the functionality of
293the local control with a proper updated prompt.
294
295 */
296// **************************************************************************
297#include "Shell.h"
298
299class RemoteShell : public RemoteControl<Shell>
300{
301public:
302 RemoteShell(const char *name, bool = false) :
303 RemoteControl<Shell>(name)
304 {
305 }
306 string GetUpdatePrompt() const;
307};
308
309#endif
Note: See TracBrowser for help on using the repository browser.