FACT++  1.0
Readline.cc
Go to the documentation of this file.
1 // **************************************************************************
55 // **************************************************************************
56 #include "Readline.h"
57 
58 #include <sstream>
59 #include <fstream>
60 #include <iostream>
61 
62 #include <sys/ioctl.h>
63 #include <readline/readline.h>
64 #include <readline/history.h>
65 
66 #include <boost/version.hpp>
67 #include <boost/filesystem.hpp>
68 
69 #include "tools.h"
70 #include "Time.h"
71 
72 namespace fs = boost::filesystem;
73 
74 using namespace std;
75 
77 bool Readline::fStopScript = false;
79 std::string Readline::fScript;
80 std::string Readline::fExternalInput;
81 
82 // --------------------------------------------------------------------------
83 //
104 //
105 Readline::Readline(const char *prgname) :
106  fMaxLines(500), fLine(0), fSection(-4), fLabel(-1), fCompletion(0)
107 {
108  if (This)
109  {
110  cout << "ERROR - Readline can only be instatiated once!" << endl;
111  exit(-1);
112  }
113 
114  This = this;
115 
116  // Alternative completion function
117  rl_attempted_completion_function = rl_ncurses_completion_function;
118 
119  // Program name
120 #if BOOST_VERSION < 104600
121  static const string fname = boost::filesystem::path(prgname).filename();
122 #else
123  static const string fname = boost::filesystem::path(prgname).filename().string();
124 #endif
125  rl_readline_name = fname.c_str();
126 
127  // Compile filename for history file
128  fName = string(prgname)+".his";
129 
130  // Read history file
131  read_history(fName.c_str());
132  //if (read_history(fName.c_str()))
133  // cout << "WARNING - Reading " << fName << ": " << strerror(errno) << endl;
134 
135  fCommandLog.open(string(prgname)+".evt");
136 
137  // Setup the readline callback which are needed to redirect
138  // the otuput properly to our ncurses panel
139  rl_getc_function = rl_ncurses_getc;
140  rl_startup_hook = rl_ncurses_startup;
141  rl_redisplay_function = rl_ncurses_redisplay;
142  rl_event_hook = rl_ncurses_event_hook;
143  rl_completion_display_matches_hook = rl_ncurses_completion_display;
144 
145  // Bind delete, page up, page down
146  rl_bind_keyseq("\e[1~", rl_named_function("beginning-of-line"));
147  rl_bind_keyseq("\e[3~", rl_named_function("delete-char"));
148  rl_bind_keyseq("\e[4~", rl_named_function("end-of-line"));
149  rl_bind_keyseq("\e[5~", rl_named_function("history-search-backward"));
150  rl_bind_keyseq("\e[6~", rl_named_function("history-search-forward"));
151  rl_bind_keyseq("\033[1;3F", rl_named_function("kill-line"));
152  rl_bind_keyseq("\033[1;5D", rl_named_function("backward-word"));
153  rl_bind_keyseq("\033[1;5C", rl_named_function("forward-word"));
154  rl_bind_key(25, rl_named_function("kill-whole-line"));
155 
156  //for (int i=0; i<10; i++) cout << (int)getchar() << endl;
157 }
158 
159 // --------------------------------------------------------------------------
160 //
166 //
168 {
169  // Write current history to file
170  if (write_history(fName.c_str()))
171  cout << "WARNING - Write " << fName.c_str() << ": " << strerror(errno) << endl;
172 
173  // Truncate file
174  if (fMaxLines>0 && history_truncate_file(fName.c_str(), fMaxLines))
175  cout << "WARNING - Truncate " << fName.c_str() << ": " << strerror(errno) << endl;
176 }
177 
178 // --------------------------------------------------------------------------
179 //
191 //
192 bool Readline::RedirectionWrapper(ostream &out, bool (*function)())
193 {
194  FILE *save = SetStreamOut(tmpfile());
195  const bool rc = function();
196  FILE *file = SetStreamOut(save);
197 
198  const bool empty = ftell(file)==0;
199 
200  rewind(file);
201 
202  if (empty)
203  {
204  out << " <empty>" << endl;
205  fclose(file);
206  return rc;
207  }
208 
209  while (1)
210  {
211  const int c = getc(file);
212  if (feof(file))
213  break;
214  out << (char)c;
215  }
216  out << endl;
217 
218  fclose(file);
219 
220  return rc;
221 }
222 
223 // --------------------------------------------------------------------------
224 //
226 //
228 {
229  return This->Getc(f);
230 }
231 
232 // --------------------------------------------------------------------------
233 //
236 //
238 {
239  This->Startup();
240  return 0; // What is this for?
241 }
242 
243 // --------------------------------------------------------------------------
244 //
248 //
250 {
251  This->Redisplay();
252 }
253 
254 // --------------------------------------------------------------------------
255 //
261 {
262  This->EventHook();
263  return 0;
264 }
265 
266 // --------------------------------------------------------------------------
267 //
280 //
281 void Readline::rl_ncurses_completion_display(char **matches, int num, int max)
282 {
283  This->CompletionDisplay(matches, num, max);
284 }
285 
286 char **Readline::rl_ncurses_completion_function(const char *text, int start, int end)
287 {
288  return This->Completion(text, start, end);
289 }
290 
291 // --------------------------------------------------------------------------
292 //
294 //
295 int Readline::Getc(FILE *f)
296 {
297  return rl_getc(f);
298 }
299 
300 // --------------------------------------------------------------------------
301 //
303 //
305 {
306 }
307 
308 // --------------------------------------------------------------------------
309 //
315 void Readline::EventHook(bool newline)
316 {
317  const string cpy = fExternalInput;
318  fExternalInput = "";
319 
320  if (!cpy.empty())
321  {
322  rl_replace_line(cpy.c_str(), 1);
323  rl_done = 1;
324  }
325 
326  string p = GetUpdatePrompt();
327  if (p.empty())
328  p = rl_prompt;
329 
330  if (newline)
331  rl_on_new_line();
332 
333  if (rl_prompt==p && !newline)
334  return;
335 
336  UpdatePrompt(p);
337 
338  int w, h;
339  rl_get_screen_size(&h, &w);
340  cout << '\r' << string(w+1, ' ') << '\r';
341  rl_forced_update_display();
342 }
343 
344 // --------------------------------------------------------------------------
345 //
352 //
353 void Readline::Shutdown(const char *)
354 {
355 }
356 
357 // --------------------------------------------------------------------------
358 //
360 //
361 
363 {
364  static int W=-1, H=-1;
365 
366  int w, h;
367  rl_get_screen_size(&h, &w);
368  if (W==w && h==H)
369  {
370  rl_redisplay();
371  return;
372  }
373 
374  cout << '\r' << string(w+1, ' ') << '\r';
375 
376  W=w;
377  H=h;
378 
379  rl_forced_update_display();
380 }
381 
382 // --------------------------------------------------------------------------
383 //
385 //
386 void Readline::CompletionDisplay(char **matches, int num, int max)
387 {
388  rl_display_match_list(matches, num, max);
389  rl_forced_update_display();
390 }
391 
392 // --------------------------------------------------------------------------
393 //
408 //
409 char *Readline::Compare(const string &str, const string &txt)
410 {
411  /*return strncmp(str.c_str(), txt.c_str(), txt.length())==0 ? */
412  return strncasecmp(str.c_str(), txt.c_str(), txt.length())==0 ?
413  strndup(str.c_str(), str.length()) : 0;
414 }
415 
416 char **Readline::CompletionMatches(const char *text, char *(*func)(const char*, int))
417 {
418  return rl_completion_matches(text, func);
419 }
420 
421 // --------------------------------------------------------------------------
422 //
439 char **Readline::Complete(const vector<string> &v, const char *text)
440 {
441  const vector<string> *save = fCompletion;
442 
443  fCompletion = &v;
444  char **rc = rl_completion_matches(const_cast<char*>(text), CompleteImp);
445  fCompletion = save;
446 
447  return rc;
448 }
449 
450 // --------------------------------------------------------------------------
451 //
476 //
477 char *Readline::Complete(const char* text, int state)
478 {
479  if (fCompletion==0)
480  return rl_filename_completion_function(text, state);
481 
482  static vector<string>::const_iterator pos;
483  if (state==0)
484  pos = fCompletion->begin();
485 
486  while (pos!=fCompletion->end())
487  {
488  char *rc = Compare(*pos++, text);
489  if (rc)
490  return rc;
491  }
492 
493  return 0;
494 }
495 
496 // --------------------------------------------------------------------------
497 //
499 //
500 char *Readline::CompleteImp(const char* text, int state)
501 {
502  return This->Complete(text, state);
503 }
504 
505 // --------------------------------------------------------------------------
506 //
540 //
541 char **Readline::Completion(const char *text, int /*start*/, int /*end*/)
542 {
543  // To do filename completion call
544  return rl_completion_matches((char*)text, CompleteImp);
545 }
546 
547 // --------------------------------------------------------------------------
548 //
561 //
562 void Readline::AddToHistory(const string &str, int skip)
563 {
564  if (skip==1 && fLastLine==str)
565  return;
566 
567  if (str.empty())
568  return;
569 
570  int p = -1;
571  while (skip==2)
572  {
573  p = history_search_pos(str.c_str(), 0, p+1);
574  if (p<0)
575  break;
576 
577  HIST_ENTRY *e = remove_history(p--);
578 
579  free(e->line);
580  free(e);
581  }
582 
583  add_history(str.c_str());
584  fLastLine = str;
585 }
586 
587 // --------------------------------------------------------------------------
588 //
591 //
593 {
594  ostringstream str;
595  str << '[' << fLine << ']';
596  return str.str();
597 }
598 
599 // --------------------------------------------------------------------------
600 //
607 //
608 void Readline::UpdatePrompt(const string &prompt) const
609 {
610  rl_set_prompt(prompt.c_str());
611 }
612 
613 // --------------------------------------------------------------------------
614 //
647 //
648 void Readline::BindKeySequence(const char *seq, int (*func)(int, int))
649 {
650  rl_bind_keyseq(seq, func);
651 }
652 
653 // --------------------------------------------------------------------------
654 //
666 //
668 {
669  rl_variable_dumper(1);
670  return true;
671 }
672 
673 // --------------------------------------------------------------------------
674 //
686 //
688 {
689  rl_function_dumper(1);
690  return true;
691 }
692 
693 // --------------------------------------------------------------------------
694 //
703 //
705 {
706  rl_list_funmap_names();
707  return true;
708 }
709 
710 // --------------------------------------------------------------------------
711 //
720 //
722 {
723  FILE *rc = rl_outstream;
724  rl_outstream = f;
725  return rc;
726 }
727 
728 // --------------------------------------------------------------------------
729 //
738 //
739 FILE *Readline::SetStreamIn(FILE *f)
740 {
741  FILE *rc = rl_instream;
742  rl_instream = f;
743  return rc;
744 }
745 
746 // --------------------------------------------------------------------------
747 //
750 //
752 {
753  return rl_display_prompt;
754 }
755 
756 // --------------------------------------------------------------------------
757 //
767 //
769 {
770  return string(rl_line_buffer, rl_end);
771 }
772 
773 // --------------------------------------------------------------------------
774 //
776 //
778 {
779  return rl_point;
780 }
781 
782 // --------------------------------------------------------------------------
783 //
785 //
787 {
788  return strlen(rl_display_prompt) + rl_point;
789 }
790 
791 // --------------------------------------------------------------------------
792 //
796 //
798 {
799  return rl_end;
800 }
801 
802 // --------------------------------------------------------------------------
803 //
805 //
807 {
808  return strlen(rl_display_prompt) + rl_end;
809 }
810 
811 // --------------------------------------------------------------------------
812 //
815 //
817 {
818  rl_resize_terminal();
819 }
820 
821 // --------------------------------------------------------------------------
822 //
831 //
832 void Readline::Resize(int width, int height)
833 {
834  rl_set_screen_size(height, width);
835 }
836 
837 // --------------------------------------------------------------------------
838 //
840 //
841 int Readline::GetCols() const
842 {
843  int rows, cols;
844  rl_get_screen_size(&rows, &cols);
845  return cols;
846 }
847 
848 // --------------------------------------------------------------------------
849 //
851 //
852 int Readline::GetRows() const
853 {
854  int rows, cols;
855  rl_get_screen_size(&rows, &cols);
856  return rows;
857 }
858 
859 // --------------------------------------------------------------------------
860 //
862 //
863 vector<const char*> Readline::GetHistory() const
864 {
865  HIST_ENTRY **next = history_list();
866 
867  vector<const char*> v;
868 
869  for (; *next; next++)
870  v.push_back((*next)->line);
871 
872  return v;
873 }
874 
875 // --------------------------------------------------------------------------
876 //
881 //
883 {
884  clear_history();
885  return true;
886 }
887 
888 // --------------------------------------------------------------------------
889 //
896 //
898 {
899  HIST_ENTRY **next = history_list();
900 
901  if (!next)
902  return true;
903 
904  for (; *next; next++)
905  fprintf(rl_outstream, "%s\n", (*next)->line);
906 
907  return true;
908 }
909 
910 // --------------------------------------------------------------------------
911 //
919 //
920 bool Readline::ExecuteShellCommand(const string &cmd)
921 {
922  FILE *pipe = popen(cmd.c_str(), "r");
923  if (!pipe)
924  {
925  fprintf(rl_outstream, "ERROR - Could not create pipe '%s': %m\n", cmd.c_str());
926  return true;
927  }
928 
929  while (1)
930  {
931  char buf[1024];
932 
933  const size_t sz = fread(buf, 1, 1024, pipe);
934 
935  fwrite(buf, 1, sz, rl_outstream);
936 
937  if (feof(pipe) || ferror(pipe))
938  break;
939  }
940 
941  if (ferror(pipe))
942  fprintf(rl_outstream, "ERROR - Reading from pipe '%s': %m\n", cmd.c_str());
943 
944  pclose(pipe);
945 
946  fprintf(rl_outstream, "\n");
947 
948  return true;
949 }
950 
951 // --------------------------------------------------------------------------
952 //
960 //
961 //
963 {
964  fprintf(rl_outstream, "\n");
965  fprintf(rl_outstream, " Commands:\n");
966  fprintf(rl_outstream, " No application specific commands defined.\n");
967  fprintf(rl_outstream, "\n");
968  return true;
969 }
970 
971 // --------------------------------------------------------------------------
972 //
981 //
982 //
984 {
985  fprintf(rl_outstream, "\n");
986  fprintf(rl_outstream, " General help:\n");
987  fprintf(rl_outstream, " h,help Print this help message\n");
988  fprintf(rl_outstream, " clear Clear history buffer\n");
989  fprintf(rl_outstream, " lh,history Dump the history buffer to the screen\n");
990  fprintf(rl_outstream, " v,variables Dump readline variables\n");
991  fprintf(rl_outstream, " f,functions Dump readline functions\n");
992  fprintf(rl_outstream, " m,funmap Dump readline funmap\n");
993  fprintf(rl_outstream, " c,commands Dump available commands\n");
994  fprintf(rl_outstream, " k,keylist Dump key bindings\n");
995  fprintf(rl_outstream, " .! command Execute a shell command\n");
996  fprintf(rl_outstream, " .w n Sleep n milliseconds\n");
997  fprintf(rl_outstream, " .x file .. Execute a script of commands (+optional argumnets)\n");
998  fprintf(rl_outstream, " .x file:N .. Execute a script of commands, start at label N\n");
999  fprintf(rl_outstream, " .j N Forward jump to label N\n");
1000  fprintf(rl_outstream, " .lt f0 f1 N If float f0 lower than float f1, jump to label N\n");
1001  fprintf(rl_outstream, " .gt f0 f1 N If float f0 greater than float f1, jump to label N\n");
1002  fprintf(rl_outstream, " .eq i0 i1 N If int i0 equal int i1, jump to label N\n");
1003  fprintf(rl_outstream, " : N Defines a label (N=number)\n");
1004  fprintf(rl_outstream, " # comment Ignored\n");
1005  fprintf(rl_outstream, " .q,quit Quit\n");
1006  fprintf(rl_outstream, "\n");
1007  fprintf(rl_outstream, " The command history is automatically loaded and saves to\n");
1008  fprintf(rl_outstream, " and from %s.\n", GetName().c_str());
1009  fprintf(rl_outstream, "\n");
1010  return true;
1011 }
1012 
1013 // --------------------------------------------------------------------------
1014 //
1023 //
1024 //
1026 {
1027  fprintf(rl_outstream, "\n");
1028  fprintf(rl_outstream, " Key bindings:\n");
1029  fprintf(rl_outstream, " Page-up Search backward in history\n");
1030  fprintf(rl_outstream, " Page-dn Search forward in history\n");
1031  fprintf(rl_outstream, " Ctrl-left One word backward\n");
1032  fprintf(rl_outstream, " Ctrl-right One word forward\n");
1033  fprintf(rl_outstream, " Home Beginning of line\n");
1034  fprintf(rl_outstream, " End End of line\n");
1035  fprintf(rl_outstream, " Ctrl-d Quit\n");
1036  fprintf(rl_outstream, " Ctrl-y Delete line\n");
1037  fprintf(rl_outstream, " Alt-end/Ctrl-k Delete until the end of the line\n");
1038  fprintf(rl_outstream, " F1 Toggle visibility of upper panel\n");
1039  fprintf(rl_outstream, "\n");
1040  fprintf(rl_outstream, " Default key-bindings are identical with your bash.\n");
1041  fprintf(rl_outstream, "\n");
1042  return true;
1043 }
1044 
1045 // --------------------------------------------------------------------------
1046 //
1048 //
1049 bool Readline::PreProcess(const string &str)
1050 {
1051  // ----------- Labels -------------
1052 
1053  if (str[0]==':')
1054  {
1055  try
1056  {
1057  fSection = stoi(str.substr(1));
1059 
1060  if (fLabel!=fSection)
1061  return true;
1062  }
1063  catch (const logic_error &e)
1064  {
1065  fCommandLog << "# ERROR[" << fScriptDepth << "] - Inavlid label '" << str.substr(1) << "'" << endl;
1066  fLabel = -2;
1067  return true;
1068  }
1069 
1070  fLabel=-1;
1071  return false;
1072  }
1073 
1074  if (fLabel>=0)
1075  {
1076  fCommandLog << "# SKIP[" << fScriptDepth << "]: " << fLabel << " - " << str << endl;
1077  return true;
1078  }
1079 
1080  if (str.substr(0, 3)==".j ")
1081  {
1082  fLabel = atoi(str.substr(3).c_str());
1083  return false;
1084  }
1085 
1086  return Process(str);
1087 
1088 }
1089 
1090 // --------------------------------------------------------------------------
1091 //
1093 //
1094 bool Readline::Process(const string &str)
1095 {
1096  // ----------- Common commands -------------
1097 
1098  if (str.substr(0, 3)==".w ")
1099  {
1100  usleep(stoi(str.substr(3))*1000);
1101  return true;
1102  }
1103 
1104  if (str.substr(0, 3)==".x ")
1105  {
1106  string opt(str.substr(3));
1107 
1108  map<string,string> data = Tools::Split(opt);
1109  if (opt.size()==0)
1110  {
1111  if (data.size()==0)
1112  PrintReadlineError("Filename missing.");
1113  else
1114  PrintReadlineError("Equal sign missing in argument '"+data.begin()->first+"'");
1115 
1116  return true;
1117  }
1118 
1119  const string save = fScript;
1120  const int save_sec = fSection;
1121  Execute(opt, data);
1122  fScript = save;
1123  if (save_sec!=-4)
1124  {
1125  fSection = save_sec;
1126  SetSection(save_sec);
1127  }
1128 
1129  return true;
1130  }
1131 
1132  if (str.substr(0, 2)==".!")
1133  {
1134  ExecuteShellCommand(str.substr(2));
1135  return true;
1136  }
1137 
1138  if (str.substr(0, 4)==".gt ")
1139  {
1140  istringstream in(str.substr(4));
1141 
1142  float v0, v1;
1143  int label;
1144 
1145  in >> v0 >> v1 >> label;
1146  if (in.fail())
1147  {
1148  PrintReadlineError("Couldn't parse '"+str+"'");
1149  fLabel = -2;
1150  return true;
1151  }
1152 
1153  if (v0 > v1)
1154  fLabel = label;
1155 
1156  return true;
1157  }
1158 
1159  if (str.substr(0, 4)==".lt ")
1160  {
1161  istringstream in(str.substr(4));
1162 
1163  float v0, v1;
1164  int label;
1165 
1166  in >> v0 >> v1 >> label;
1167  if (in.fail())
1168  {
1169  PrintReadlineError("Couldn't parse '"+str+"'");
1170  fLabel = -2;
1171  return true;
1172  }
1173 
1174  if (v0 < v1)
1175  fLabel = label;
1176 
1177  return true;
1178  }
1179 
1180  if (str.substr(0, 4)==".eq ")
1181  {
1182  istringstream in(str.substr(4));
1183 
1184  int v0, v1, label;
1185 
1186  in >> v0 >> v1 >> label;
1187  if (in.fail())
1188  {
1189  PrintReadlineError("Couldn't parse '"+str+"'");
1190  fLabel = -2;
1191  return true;
1192  }
1193 
1194  if (v0==v1)
1195  fLabel = label;
1196 
1197  return true;
1198  }
1199 
1200 
1201  // ----------- Readline static -------------
1202 
1203  if (str=="clear")
1204  return ClearHistory();
1205 
1206  if (str=="lh" || str=="history")
1207  return DumpHistory();
1208 
1209  if (str=="v" || str=="variables")
1210  return DumpVariables();
1211 
1212  if (str=="f" || str=="functions")
1213  return DumpFunctions();
1214 
1215  if (str=="m" || str=="funmap")
1216  return DumpFunmap();
1217 
1218  // ---------- Readline virtual -------------
1219 
1220  if (str=="h" || str=="help")
1221  return PrintGeneralHelp();
1222 
1223  if (str=="c" || str=="commands")
1224  return PrintCommands();
1225 
1226  if (str=="k" || str=="keylist")
1227  return PrintKeyBindings();
1228 
1229  return false;
1230 }
1231 
1232 // --------------------------------------------------------------------------
1233 //
1249 //
1251 {
1252  char *buf = readline(str.c_str());
1253  Shutdown(buf);
1254 
1255  // Happens when EOF is encountered
1256  if (!buf)
1257  return false;
1258 
1259  str = Tools::Trim(buf);
1260 
1261  free(buf);
1262 
1263  return true;
1264 }
1265 
1266 // --------------------------------------------------------------------------
1267 //
1280 //
1281 string Readline::Prompt(const string &prompt)
1282 {
1283  char *buf = readline(prompt.c_str());
1284 
1285  Shutdown(buf ? buf : "");
1286 
1287  const string str = !buf || (rl_done && rl_pending_input==4)
1288  ? ".q" : Tools::Trim(buf);
1289 
1290  free(buf);
1291 
1292  return str;
1293 }
1294 
1295 // --------------------------------------------------------------------------
1296 //
1303 void Readline::StaticPushHistory(const string &fname="")
1304 {
1305  fs::path his = fs::path(This->fName).parent_path();
1306  his /= fname;
1307 
1308  write_history(This->fName.c_str());
1309  stifle_history(0);
1310  unstifle_history();
1311  read_history(his.string().c_str());
1312 }
1313 
1314 // --------------------------------------------------------------------------
1315 //
1322 void Readline::StaticPopHistory(const string &fname="")
1323 {
1324  fs::path his = fs::path(This->fName).parent_path();
1325  his /= fname;
1326 
1327  write_history(his.string().c_str());
1328  history_truncate_file(his.string().c_str(), 1000);
1329 
1330  stifle_history(0);
1331  unstifle_history();
1332  read_history(This->fName.c_str());
1333 }
1334 
1335 // --------------------------------------------------------------------------
1336 //
1346 string Readline::StaticPrompt(const string &prompt)
1347 {
1348  char *buf = readline(prompt.c_str());
1349  if (!buf)
1350  return ".q";
1351 
1352  const string str(buf);
1353  if (Tools::Trim(str)!=".q" && !Tools::Trim(str).empty())
1354  if (history_length==0 || history_search_pos(str.c_str(), -1, history_length-1)!=history_length-1)
1355  add_history(buf);
1356 
1357  free(buf);
1358 
1359  return str;
1360 }
1361 
1362 // --------------------------------------------------------------------------
1363 //
1369 //
1370 void Readline::ProcessLine(const string &str)
1371 {
1372  const string cmd = Tools::Uncomment(str);
1373 
1374  if (!cmd.empty())
1375  {
1376  const bool rc = PreProcess(cmd);
1377 
1378  AddToHistory(cmd);
1379 
1380  if (rc)
1381  return;
1382 
1383  fLine++;
1384  }
1385 
1386  fCommandLog << str << endl;
1387 }
1388 
1389 // --------------------------------------------------------------------------
1390 //
1406 void Readline::Run(const char *prompt)
1407 {
1408  fLine = 0;
1409  while (1)
1410  {
1411  // Before we start we have to make sure that the
1412  // screen looks like and is ordered like expected.
1413  const string str = Prompt(prompt?prompt:GetUpdatePrompt());
1414  if (str.empty())
1415  continue;
1416 
1417  if (str=="quit" || str==".q")
1418  break;
1419 
1420  if (str==".qqq")
1421  exit(128);
1422 
1423  if (str==".qqqqqq")
1424  abort();
1425 
1426  ProcessLine(str);
1427  }
1428 }
1429 
1430 // --------------------------------------------------------------------------
1431 //
1446 int Readline::Execute(const string &fname, const map<string,string> &args)
1447 {
1448  // this could do the same:
1449  // rl_instream = fopen(str.c_str(), "r");
1450 
1451  if (IsStopped())
1452  return 0;
1453 
1454  string name = Tools::Trim(fname);
1455  fScript = name;
1456 
1457  fSection = -3;
1458  SetSection(-3);
1459  fLabel = -1;
1460 
1461  const size_t p = name.find_last_of(':');
1462  if (p!=string::npos)
1463  {
1464  fLabel = atoi(name.substr(p+1).c_str());
1465  name = name.substr(0, p);
1466  }
1467 
1468  ifstream fin(name.c_str());
1469  if (!fin)
1470  {
1471  fSection = -4;
1472  SetSection(-4);
1473  return -1;
1474  }
1475 
1476  if (fScriptDepth++==0)
1477  fStopScript = false;
1478 
1479  fCommandLog << "# " << Time() << " - " << name << " (START[" << fScriptDepth<< "]";
1480  if (fLabel>=0)
1481  fCommandLog << ':' << fLabel;
1482  fCommandLog << ")" << endl;
1483 
1484  fSection = -1;
1485  SetSection(-1);
1486 
1487  int rc = 0;
1488 
1489  string buffer;
1490  while (getline(fin, buffer, '\n') && !fStopScript)
1491  {
1492  buffer = Tools::Trim(buffer);
1493  if (buffer.empty())
1494  continue;
1495 
1496  rc++;
1497 
1498  if (buffer=="quit" || buffer==".q")
1499  {
1500  Stop();
1501  break;
1502  }
1503 
1504  // find and replace arguments
1505  for (auto it=args.begin(); it!=args.end(); it++)
1506  {
1507  const string find = "${"+it->first+"}";
1508  for (size_t pos=0; (pos=buffer.find(find, pos))!=string::npos; pos+=find.length())
1509  buffer.replace(pos, find.size(), it->second);
1510  }
1511 
1512  // process line
1513  ProcessLine(buffer);
1514  }
1515 
1516  fCommandLog << "# " << Time() << " - " << name << " (FINISHED[" << fScriptDepth<< "])" << endl;
1517 
1518  if (--fScriptDepth==0)
1519  fStopScript = false;
1520 
1521  fLabel = -1;
1522  fSection = -4;
1523  SetSection(-4);
1524 
1525  return rc;
1526 }
1527 
1528 // --------------------------------------------------------------------------
1529 //
1535 {
1536  rl_done = 1;
1537  rl_pending_input = 4; // EOT (end of transmission, ctrl-d)
1538 }
1539 
1540 // --------------------------------------------------------------------------
1541 //
1549 {
1550  return rl_done==1 && rl_pending_input==4;
1551 };
1552 
1553 void Readline::PrintReadlineError(const std::string &str)
1554 {
1555  fprintf(rl_outstream, "%s\n", str.c_str());
1556 }
int start(int initState)
Definition: feeserver.c:1740
Return to feeserver c CVS log Up to[MAIN] dcscvs FeeServer feeserver src Wed FeeServer_v0 v0 FeeServer_v0 v0 FeeServer_v0 v0 FeeServer_v0 v0 FeeServer_v0 v0 FeeServer_v0 v0
Definition: feeserver.c:5
static char * Compare(const std::string &str, const std::string &txt)
Definition: Readline.cc:409
void UpdatePrompt() const
Definition: Readline.h:98
static void Resize()
Definition: Readline.cc:816
virtual ~Readline()
Definition: Readline.cc:167
static Readline * This
Definition: Readline.h:19
virtual void Redisplay()
Default: call rl_redisplay()
Definition: Readline.cc:362
static std::string StaticPrompt(const std::string &prompt)
Definition: Readline.cc:1346
static char * CompleteImp(const char *text, int state)
Calls Complete()
Definition: Readline.cc:500
const std::vector< std::string > * fCompletion
Pointer to a list of possible matched for auto-completion.
Definition: Readline.h:63
static int rl_ncurses_event_hook()
Definition: Readline.cc:260
virtual bool PrintCommands()
Definition: Readline.cc:962
static int GetLineLength()
return the length of the prompt plus the length of the line buffer
Definition: Readline.cc:806
static bool DumpHistory()
Definition: Readline.cc:897
static int fScriptDepth
Definition: Readline.h:32
Adds some functionality to boost::posix_time::ptime for our needs.
Definition: Time.h:30
char str[80]
Definition: test_client.c:7
int GetRows() const
Get the number of rows readline assumes the screen size to be.
Definition: Readline.cc:852
static int GetBufferLength()
Definition: Readline.cc:797
static bool RedirectionWrapper(std::ostream &out, bool(*function)())
Definition: Readline.cc:192
STL namespace.
virtual bool Process(const std::string &str)
Definition: Readline.cc:1094
Readline(const char *prgname)
Definition: Readline.cc:105
std::ofstream fCommandLog
Maximum number of lines in the history file.
Definition: Readline.h:25
void BindKeySequence(const char *seq, int(*func)(int, int))
Definition: Readline.cc:648
int fMaxLines
Filename for the history file compiled in the constructor.
Definition: Readline.h:23
virtual std::string GetUpdatePrompt() const
Definition: Readline.h:102
static void Stop()
Definition: Readline.cc:1534
static char ** CompletionMatches(const char *text, char *(*func)(const char *, int))
Definition: Readline.cc:416
virtual void PrintReadlineError(const std::string &str)
Definition: Readline.cc:1553
static int rl_ncurses_startup()
Definition: Readline.cc:237
virtual void SetSection(int)
Definition: Readline.h:68
static void StaticPopHistory(const std::string &fname)
Definition: Readline.cc:1322
std::vector< const char * > GetHistory() const
Return a list of pointer to the history contents.
Definition: Readline.cc:863
virtual std::string Prompt(const std::string &prompt)
Definition: Readline.cc:1281
virtual bool ExecuteShellCommand(const std::string &cmd)
Definition: Readline.cc:920
virtual void Shutdown(const char *buf)
Definition: Readline.cc:353
std::string fName
Definition: Readline.h:22
static std::string GetBuffer()
Definition: Readline.cc:768
static void StaticPushHistory(const std::string &fname)
Definition: Readline.cc:1303
virtual void Run(const char *prompt=0)
Definition: Readline.cc:1406
static bool DumpFunctions()
Definition: Readline.cc:687
static std::string fExternalInput
Definition: Readline.h:35
static std::string GetPrompt()
Definition: Readline.cc:751
std::string fLastLine
Definition: Readline.h:27
int Execute(const std::string &fname, const std::map< std::string, std::string > &args=std::map< std::string, std::string >())
Definition: Readline.cc:1446
int GetCols() const
Get the number of cols readline assumes the screen size to be.
Definition: Readline.cc:841
static char ** rl_ncurses_completion_function(const char *text, int start, int end)
Definition: Readline.cc:286
virtual void Startup()
Default: Do nothing.
Definition: Readline.cc:304
std::map< std::string, std::string > Split(std::string &, bool=false)
Definition: tools.cc:230
int fSection
Definition: Readline.h:30
double end
static void rl_ncurses_completion_display(char **matches, int num, int max)
Definition: Readline.cc:281
static int GetAbsCursor()
return strlen(rl_display_prompt) + rl_point
Definition: Readline.cc:786
int buffer[BUFFSIZE]
Definition: db_dim_client.c:14
float height
Definition: HeadersGPS.h:26
virtual void CompletionDisplay(char **matches, int num, int max)
Default: call rl_completion_display_matches()
Definition: Readline.cc:386
virtual char ** Completion(const char *text, int start, int end)
Definition: Readline.cc:541
static int rl_ncurses_getc(FILE *)
Static member function which are used to adapt readline to ncurses.
Definition: Readline.cc:227
static std::string fScript
Definition: Readline.h:48
virtual char * Complete(const char *text, int state)
Functions dealing with auto completion.
Definition: Readline.cc:477
float data[4 *1440]
virtual bool PromptEOF(std::string &str)
Definition: Readline.cc:1250
static bool ClearHistory()
Definition: Readline.cc:882
void free(void *mem)
void ProcessLine(const std::string &str)
Definition: Readline.cc:1370
int fLine
Last line adde to history.
Definition: Readline.h:29
virtual int Getc(FILE *)
The non static implementations of the callback funtions above.
Definition: Readline.cc:295
static int GetCursor()
return rl_point (the current cursor position within the line buffer)
Definition: Readline.cc:777
std::string GetName() const
Definition: Readline.h:88
std::string Uncomment(const std::string &opt)
Definition: tools.cc:292
std::string Trim(const std::string &str)
Definition: tools.cc:68
static FILE * SetStreamIn(FILE *f)
Definition: Readline.cc:739
function save()
Definition: index.js:502
virtual bool PreProcess(const std::string &str)
Definition: Readline.cc:1049
bool IsStopped() const
Definition: Readline.cc:1548
virtual void EventHook(bool newline=false)
Definition: Readline.cc:315
C++ wrapper for GNU&#39;s readline library.
Definition: Readline.h:10
static bool DumpFunmap()
Definition: Readline.cc:704
void AddToHistory(const std::string &str, int skip=2)
Definition: Readline.cc:562
static bool DumpVariables()
Definition: Readline.cc:667
static void rl_ncurses_redisplay()
Definition: Readline.cc:249
virtual std::string GetLinePrompt() const
Definition: Readline.cc:592
int fLabel
Definition: Readline.h:31
virtual bool PrintGeneralHelp()
Definition: Readline.cc:983
static FILE * SetStreamOut(FILE *f)
Definition: Readline.cc:721
virtual bool PrintKeyBindings()
Definition: Readline.cc:1025
static bool fStopScript
Definition: Readline.h:33