• Main Page
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

/Users/magix/mmx/mmxlight/src/input.cpp

Go to the documentation of this file.
00001 
00002 /******************************************************************************
00003 * MODULE     : input.cpp
00004 * DESCRIPTION: mathemagix shell input and completion functions
00005 * COPYRIGHT  : (C) 2007  Gregoire Lecerf
00006 *******************************************************************************
00007 * This software falls under the GNU general public license and comes WITHOUT
00008 * ANY WARRANTY WHATSOEVER. See the file $TEXMACS_PATH/LICENSE for more details.
00009 * If you don't have this file, write to the Free Software Foundation, Inc.,
00010 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00011 ******************************************************************************/
00012 
00013 #include <string.h>
00014 #include <mmxlight/base_evaluator.hpp>
00015 #include <mmxlight/shell.hpp>
00016 #include <basix/system.hpp>
00017 #include <basix/string.hpp>
00018 #include <basix/table.hpp>
00019 #include <basix/math_syntax.hpp>
00020 
00021 #ifdef MMXLIGHT_HAVE_READLINE
00022 #  if defined(MMXLIGHT_HAVE_READLINE_READLINE_H)
00023 #    include <readline/readline.h>
00024 #  else
00025 #    include <readline.h>
00026 #  endif
00027 #  if defined(MMXLIGHT_HAVE_READLINE_HISTORY_H)
00028 #    include <readline/history.h>
00029 #  else
00030 #    include <history.h>
00031 #  endif
00032 #endif
00033 
00034 namespace mmx {
00035   
00036   /*
00037    * Read line and manage history
00038    */
00039 
00040 static bool
00041 raw_read_line (string& line) {
00042   char c;
00043   line = "";
00044   while (busy (mmin)) {
00045     mmin >> c;
00046     if (c == '\n' || c == '\r')
00047       return true;
00048     line << c;
00049   }
00050   return false;
00051 }
00052 
00053 #ifdef MMXLIGHT_HAVE_READLINE
00054 
00055 static bool
00056 read_line (string prompt, string& sline) {
00057   char* line;
00058   char* _prompt= as_charp (prompt);
00059   line = readline (_prompt);
00060   free_charp (_prompt);
00061   if (line == NULL) {
00062     sline = "";
00063     return false;
00064   }
00065   sline = string(line);
00066   free (line);
00067   return true;
00068 }
00069 
00070 void
00071 shell_save_history () {
00072   string dir= user_dir ();
00073   if (dir == "") return;
00074   string file_name = dir * "/var/history";
00075   char* _f = as_charp (file_name);
00076   write_history (_f);
00077   history_truncate_file (_f, history_size);
00078   free_charp (_f);
00079 }
00080   
00081 void
00082 shell_load_history () {
00083   string dir = user_dir ();
00084   if (dir == "") return;
00085   string file_name = dir * "/var/history";
00086   char* _f = as_charp (file_name);
00087   history_truncate_file (_f, history_size);
00088   read_history (_f);
00089   free_charp (_f);
00090 }
00091 
00092 #else
00093 
00094 static bool
00095 shell_read_line (string prompt, string& line) {
00096   mmout << prompt << flush_now;
00097   return raw_read_line (line);
00098 }
00099 
00100 void
00101 shell_save_history () {}
00102   
00103 void
00104 shell_load_history () {}
00105   
00106 #endif // MMXLIGHT_HAVE_READLINE
00107 
00108 void
00109 shell_save_session (void) {
00110   nat i;
00111   string dir = user_dir ();
00112   string contents = "";
00113   char z = 0;
00114   if (dir == "") return;
00115   string file_name = dir * "/var/session";
00116   for (i = 0; i < get_interactive_number (); ++i) {
00117     contents << get_interactive_source (i);
00118     contents << z << "\n";
00119   }
00120   save (file_name, contents);
00121 }
00122   
00123 vector<string>
00124 shell_restore_session (void) {
00125   string dir = user_dir ();
00126   string file_name = dir * "/var/session";
00127   string data;
00128   load (file_name, data);
00129   store_interactive_number (0);
00130   string sep= "\n\n"; sep[0]= '\0';
00131   vector<string> inputs= tokenize (data, sep);
00132   vector<string> v;
00133   for (nat i=0; i<N(inputs); i++) {
00134     v << tokenize (inputs[i], "\n", true);
00135     store_interactive_source (inputs[i]);
00136   }
00137   return v;
00138 }
00139   
00140   /*
00141    * Completion for Readline mode
00142    */
00143 
00144 #ifdef MMXLIGHT_HAVE_READLINE
00145   
00146 static char*
00147 duplicate (char *s) {
00148   // strdup does not work on some platforms.
00149   char* r= (char*) malloc (strlen (s) + 1);
00150   strcpy (r, s);
00151   return r;
00152 }
00153 
00154 /* Generator function for command completion. STATE lets us know whether
00155    to start from scratch; without any state (i.e. STATE == 0), then we
00156    start at the top of the list. */
00157 static char *
00158 completion_generator (const char* text, int state) {
00159   static nat text_len;
00160   static list<string> current_list;
00161   iterator<string> iter;
00162   string name;
00163   char *tmp, *copiedname;
00164 
00165   /* If this is a new word to complete, initialize now.  This includes
00166      saving the length of TEXT for efficiency, and initializing the index
00167      variable to 0. */
00168   if (!state) {
00169     current_list = identifiers_for_completion 
00170       * strings_for_completion (get_environment (current_ev));
00171     text_len = strlen (text);
00172   }
00173   
00174   /* Return the next name which partially matches from the command list. */
00175   while (!is_nil(current_list)) {
00176     name = car (current_list);
00177     current_list = cdr (current_list);
00178     tmp = as_charp (name);
00179     if (strncmp (tmp, text, text_len) == 0) {
00180       // Alloc memory for copiedname with malloc
00181       copiedname = duplicate (tmp);
00182       free_charp (tmp);
00183       // Readline frees the strings when it has finished with them.
00184       return copiedname;
00185     }
00186     else { // Completion of members of a class, such as z.re
00187       int dot;
00188       for (dot= text_len-1; dot>=0 && text[dot] != '.'; dot--);
00189       if (dot >= 0 && strncmp (text + dot, tmp, text_len - dot) == 0) {
00190         char* r= (char*) malloc (dot + strlen (tmp) + 1);
00191         strncpy (r, text, dot);
00192         strcpy  (r + dot, tmp);
00193         free_charp (tmp);
00194         return r;
00195       }
00196       else free_charp (tmp);
00197     }
00198   }
00199 
00200   /* If no names matched, then return NULL. */
00201   return ((char *)NULL);
00202 }
00203 
00204 /* Attempt to complete on the contents of TEXT.  START and END bound
00205    the region of rl_line_buffer that contains the word to complete.
00206    TEXT is the word to complete. We can use the entire contents of
00207    rl_line_buffer in case we want to do some simple parsing.  Return
00208    the vector of matches, or NULL if there aren't any. */
00209 static char **
00210 complete (const char *text, int start, int end) {
00211   char **matches;
00212 
00213 #if defined(RL_VERSION_MAJOR) && RL_VERSION_MAJOR >= 4
00214   rl_completion_append_character = '\0';
00215 #endif
00216   matches = (char **)NULL;
00217   matches = rl_completion_matches(text, completion_generator);
00218   return (matches);
00219 }
00220 #endif // MMXLIGHT_HAVE_READLINE
00221 
00222   /*
00223    * Read input
00224    */
00225 
00226 #ifdef MMXLIGHT_HAVE_READLINE
00227 
00228 static bool fed;
00229   
00230 static int
00231 passive_newline(int a, int b) {
00232   (void) a;
00233   (void) b;
00234   rl_crlf ();
00235   rl_on_new_line ();
00236   fed = false;
00237   rl_done = 1;
00238   return 0;
00239 }
00240 
00241 static int
00242 active_newline(int a, int b) {
00243   (void) a;
00244   (void) b;
00245   rl_crlf ();
00246   rl_on_new_line ();
00247   fed = true;
00248   rl_done = 1;
00249   return 0;
00250 }
00251 
00252 #endif // MMXLIGHT_HAVE_READLINE
00253 
00254 #ifdef MMXLIGHT_HAVE_READLINE
00255 
00256 bool
00257 shell_terminal_input (string& buffer) {
00258   string prompt, promptc;
00259   string s;
00260   bool b;
00261   nat i, size;
00262   vector<string> v;
00263   char* tmp;
00264   buffer = "";
00265   fed = false;
00266   size = 0;
00267 
00268   HIST_ENTRY* last_entry;
00269   HISTORY_STATE* history = history_get_history_state ();
00270 
00271   if (quiet_mode) {
00272     prompt = "";
00273     promptc= "";
00274   }
00275   else {
00276     string next= as_string (get_interactive_number () + 1);
00277     prompt = next * "] ";
00278     promptc = "";
00279     for (i=0; i < N(next); i++)
00280       promptc << " ";
00281     promptc << "] ";
00282   }
00283 
00284   // entering interactive input
00285   while (true) {
00286     if (completion_mode)
00287       rl_attempted_completion_function = complete;
00288     rl_bind_key (RETURN, active_newline);
00289     rl_bind_key (META(RETURN), passive_newline);
00290 
00291     b = read_line (prompt, s);
00292     v << s;
00293     size += N(s);
00294     buffer << s << "\n";
00295     if (N(s) > 0) {
00296       tmp = as_charp(s);
00297       if (history->length == 0)
00298         last_entry = NULL;
00299       else
00300         last_entry = history -> entries[history->length-1];
00301       if ((last_entry == NULL) ||
00302           ((last_entry != NULL) && (strcmp (tmp, last_entry->line) != 0))) {
00303         add_history (tmp);
00304         shell_save_history ();
00305         shell_save_session ();
00306       }
00307       free_charp (tmp);
00308     }
00309     if (fed || !b) {
00310       if (size > 0)
00311         store_interactive_source (recompose (v, "\n"));
00312       else
00313         buffer = "";
00314       shell_save_history ();
00315       shell_save_session ();
00316       return b;
00317     }
00318     prompt = promptc;
00319   }
00320 }
00321 
00322 #else
00323 
00324 bool
00325 shell_terminal_input (string& buffer) {
00326   vector<string> v;
00327   string prompt;
00328   bool b;
00329   buffer = "";
00330 
00331   // entering interactive input
00332   if (quiet_mode)
00333     prompt = "";
00334   else
00335     prompt = as_string (get_interactive_number () + 1) * "] ";
00336   b = shell_read_line (prompt, buffer);
00337   if (N(buffer) != 0) {
00338     v << buffer;
00339     store_interactive_source (recompose (v, "\n"));
00340     buffer << "\n";
00341   }
00342   return b;
00343 }
00344 #endif // MMXLIGHT_HAVE_READLINE
00345 
00346 bool
00347 shell_terminal_batch_input (string& buffer) {
00348   string s;
00349   bool b;
00350   vector<string> v;
00351   buffer = "";
00352   while (true) {
00353     b = raw_read_line (s);
00354     buffer << s << "\n";
00355     v << s;
00356     if (!b) {
00357       store_interactive_source (recompose (v, "\n"));
00358       return b;
00359     }
00360   }
00361 }
00362 
00363 } // namespace mmx

Generated on Mon May 2 2011 17:04:34 for mmxlight:doc by  doxygen 1.7.2