00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 #include <basix/system.hpp>
00014 #include <basix/string.hpp>
00015 #include <basix/list.hpp>
00016 #include <basix/table.hpp>
00017 #include <basix/math_syntax.hpp>
00018 #include <basix/parse_tools.hpp>
00019 #include <basix/basix-config.hpp>
00020 
00021 #ifdef BASIX_HAVE_UNISTD_H
00022 #include <unistd.h>
00023 #endif
00024 
00025 #ifdef BASIX_HAVE_READLINE
00026 #  if defined(BASIX_HAVE_READLINE_READLINE_H)
00027 #    include <readline/readline.h>
00028 #  else
00029 #    include <readline.h>
00030 #  endif
00031 #  if defined(BASIX_HAVE_READLINE_HISTORY_H)
00032 #    include <readline/history.h>
00033 #  else
00034 #    include <history.h>
00035 #  endif
00036 #endif
00037 
00038 namespace mmx {
00039 #define DATA_BEGIN   ((char) 2)
00040 #define DATA_END     ((char) 5)
00041 
00042 
00043 
00044 
00045 
00046 bool script_mode = false;
00047 bool quiet_mode = false;
00048 bool debug_mode = false;
00049 bool type_mode = false;
00050 bool time_mode = false;
00051 nat  history_size = 100;
00052   
00053 bool completion_mode = true;
00054 bool batch_mode = false;
00055 
00056 
00057 
00058 
00059 
00060 void
00061 batch_mode_initialize () {
00062   batch_mode = !isatty(STDIN_FILENO) && !texmacs_mode;
00063 }
00064 
00065 
00066 
00067 
00068 
00069 #ifdef BASIX_HAVE_READLINE
00070 
00071 static bool
00072 read_line (string prompt, string& sline) {
00073   char* line;
00074   string buf = "";
00075   port p = formatting_port (output_string_port (buf));
00076   p << charcode_as_string (RL_PROMPT_START_IGNORE)
00077     << bold << blue_foreground
00078     << charcode_as_string (RL_PROMPT_END_IGNORE)
00079     << prompt
00080     << charcode_as_string (RL_PROMPT_START_IGNORE)
00081     << reset_attributes
00082     << cyan_foreground
00083     << charcode_as_string (RL_PROMPT_END_IGNORE);
00084   char* _prompt = as_charp (buf);
00085   line = readline (_prompt);
00086   free_charp (_prompt);
00087   mmout << reset_attributes << flush_now;
00088   if (line == NULL) {
00089     sline = "";
00090     return false;
00091   }
00092   sline = string(line);
00093   free (line);
00094   return true;
00095 }
00096 
00097 void
00098 shell_save_history () {
00099   string dir= user_dir ();
00100   if (dir == "") return;
00101   string file_name = dir * "/var/history";
00102   char* _f = as_charp (file_name);
00103   write_history (_f);
00104   history_truncate_file (_f, history_size);
00105   free_charp (_f);
00106 }
00107   
00108 void
00109 shell_load_history () {
00110   string dir = user_dir ();
00111   if (dir == "") return;
00112   string file_name = dir * "/var/history";
00113   char* _f = as_charp (file_name);
00114   history_truncate_file (_f, history_size);
00115   read_history (_f);
00116   free_charp (_f);
00117 }
00118 
00119 #else
00120 
00121 static bool
00122 raw_read_line (string& line) {
00123   char c;
00124   line = "";
00125   while (busy (mmin)) {
00126     mmin >> c;
00127     if (c == '\n' || c == '\r')
00128       return true;
00129     line << c;
00130   }
00131   return false;
00132 }
00133 
00134 static bool
00135 shell_read_line (string prompt, string& line) {
00136   mmout << bold << blue_foreground << prompt << reset_attributes << flush_now;
00137   mmout << cyan_foreground << flush_now;
00138   bool r= raw_read_line (line);
00139   mmout << reset_attributes << flush_now;
00140   return r;
00141 }
00142 
00143 void
00144 shell_save_history () {}
00145   
00146 void
00147 shell_load_history () {}
00148   
00149 #endif // BASIX_HAVE_READLINE
00150 
00151 void
00152 shell_save_session (void) {
00153   nat i;
00154   string dir = user_dir ();
00155   string contents = "";
00156   char z = 0;
00157   if (dir == "") return;
00158   string file_name = dir * "/var/session";
00159   for (i = 0; i < get_interactive_number (); ++i) {
00160     contents << get_interactive_source (i);
00161     contents << z << "\n";
00162   }
00163   save (file_name, contents);
00164 }
00165   
00166 vector<string>
00167 shell_load_session (void) {
00168   string dir = user_dir ();
00169   string file_name = dir * "/var/session";
00170   string data;
00171   load (file_name, data);
00172   store_interactive_number (0);
00173   string sep= "\n\n"; sep[0]= '\0';
00174   vector<string> inputs= tokenize (data, sep);
00175   vector<string> v;
00176   for (nat i=0; i<N(inputs); i++) {
00177     v << tokenize (inputs[i], "\n", true);
00178     store_interactive_source (inputs[i]);
00179   }
00180   return inputs;
00181 }
00182   
00183   
00184 
00185 
00186 
00187 #ifdef BASIX_HAVE_READLINE
00188 
00189 
00190 list<string> identifiers_for_completion = 
00191   list<string> ("case", "continue", "else", "error") *
00192   list<string> ("exists", "for", "generate", "in") *
00193   list<string> ("operator", "postfix", "prefix", "step") *
00194   list<string> ("then", "until", "while", "help");
00195 
00196 table<generic,generic> strings_for_completion;
00197 
00198 static char*
00199 duplicate (char *s) {
00200   
00201   char* r= (char*) malloc (strlen (s) + 1);
00202   strcpy (r, s);
00203   return r;
00204 }
00205 
00206 
00207 
00208 
00209 static char *
00210 completion_generator (const char* text, int state) {
00211   static nat text_len;
00212   static list<string> current_list;
00213   iterator<string> iter;
00214   string name;
00215   char *tmp, *copiedname;
00216   
00217 
00218 
00219   if (!state) {
00220     rl_special_prefixes = "$";
00221     current_list = identifiers_for_completion
00222       * as<list<string> > (list<generic> (entries (strings_for_completion)));
00223     text_len = strlen (text);
00224   }
00225   
00226   
00227   while (!is_nil(current_list)) {
00228     name = car (current_list);
00229     current_list = cdr (current_list);
00230     tmp = as_charp (name);
00231     if (strncmp (tmp, text, text_len) == 0) {
00232       
00233       copiedname = duplicate (tmp);
00234       free_charp (tmp);
00235       
00236       return copiedname;
00237     }
00238     else { 
00239       int dot;
00240       for (dot= text_len-1; dot>=0 && text[dot] != '.'; dot--);
00241       if (dot >= 0 && strncmp (text + dot, tmp, text_len - dot) == 0) {
00242         char* r= (char*) malloc (dot + strlen (tmp) + 1);
00243         strncpy (r, text, dot);
00244         strcpy  (r + dot, tmp);
00245         free_charp (tmp);
00246         return r;
00247       }
00248       else free_charp (tmp);
00249     }
00250   }
00251 
00252   
00253   return ((char *)NULL);
00254 }
00255 
00256 
00257 
00258 
00259 
00260 
00261 static char **
00262 complete (const char *text, int start, int end) {
00263   char **matches;
00264 
00265 #if defined(RL_VERSION_MAJOR) && RL_VERSION_MAJOR >= 4
00266   rl_completion_append_character = '\0';
00267 #endif
00268   matches = (char **)NULL;
00269   matches = rl_completion_matches(text, completion_generator);
00270   return (matches);
00271 }
00272 #endif // BASIX_HAVE_READLINE
00273 
00274   
00275 
00276 
00277 
00278 #ifdef BASIX_HAVE_READLINE
00279 
00280 static bool fed;
00281   
00282 static int
00283 passive_newline(int a, int b) {
00284   (void) a;
00285   (void) b;
00286   rl_crlf ();
00287   rl_on_new_line ();
00288   fed = false;
00289   rl_done = 1;
00290   return 0;
00291 }
00292 
00293 static int
00294 active_newline(int a, int b) {
00295   (void) a;
00296   (void) b;
00297   rl_crlf ();
00298   rl_on_new_line ();
00299   fed = true;
00300   rl_done = 1;
00301   return 0;
00302 }
00303 
00304 #endif // BASIX_HAVE_READLINE
00305 
00306 #ifdef BASIX_HAVE_READLINE
00307 
00308 bool
00309 shell_terminal_input (string& buffer) {
00310   string prompt, promptc;
00311   string s;
00312   bool b;
00313   nat i, size;
00314   vector<string> v;
00315   char* tmp;
00316   buffer = "";
00317   fed = false;
00318   size = 0;
00319 
00320   HIST_ENTRY* last_entry;
00321   HISTORY_STATE* history = history_get_history_state ();
00322 
00323   if (quiet_mode) {
00324     prompt = "";
00325     promptc= "";
00326   }
00327   else {
00328     string next= as_string (get_interactive_number () + 1);
00329     prompt = next * "] ";
00330     promptc = "";
00331     for (i=0; i < N(next); i++)
00332       promptc << " ";
00333     promptc << "] ";
00334   }
00335 
00336   
00337   while (true) {
00338     if (completion_mode)
00339       rl_attempted_completion_function = complete;
00340     rl_bind_key (RETURN, active_newline);
00341     rl_bind_key (META(RETURN), passive_newline);
00342 
00343     b = read_line (prompt, s);
00344     v << s;
00345     size += N(s);
00346     buffer << s << "\n";
00347     if (N(s) > 0) {
00348       tmp = as_charp(s);
00349       if (history->length == 0)
00350         last_entry = NULL;
00351       else
00352         last_entry = history -> entries[history->length-1];
00353       if ((last_entry == NULL) ||
00354           ((last_entry != NULL) && (strcmp (tmp, last_entry->line) != 0))) {
00355         add_history (tmp);
00356         shell_save_history ();
00357         shell_save_session ();
00358       }
00359       free_charp (tmp);
00360     }
00361     if (fed || !b) {
00362       if (size > 0)
00363         store_interactive_source (recompose (v, "\n"));
00364       else
00365         buffer = "";
00366       shell_save_history ();
00367       shell_save_session ();
00368       return b;
00369     }
00370     prompt = promptc;
00371   }
00372 }
00373 
00374 #else
00375 
00376 bool
00377 shell_terminal_input (string& buffer) {
00378   vector<string> v;
00379   string prompt;
00380   bool b;
00381   buffer = "";
00382 
00383   
00384   if (quiet_mode)
00385     prompt = "";
00386   else
00387     prompt = as_string (get_interactive_number () + 1) * "] ";
00388   b = shell_read_line (prompt, buffer);
00389   if (N(buffer) != 0) {
00390     v << buffer;
00391     store_interactive_source (recompose (v, "\n"));
00392     buffer << "\n";
00393   }
00394   return b;
00395 }
00396 #endif // BASIX_HAVE_READLINE
00397 
00398 }