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

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

Go to the documentation of this file.
00001 
00002 /******************************************************************************
00003 * MODULE     : texmacs.cpp
00004 * DESCRIPTION: mathemagix texmacs interface
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 <mmxlight/base_evaluator.hpp>
00014 #include <mmxlight/shell.hpp>
00015 #include <basix/math_syntax.hpp>
00016 #include <basix/list.hpp>
00017 #include <basix/dynamic.hpp>
00018 
00019 namespace mmx {
00020 
00021 #define DATA_BEGIN   ((char) 2)
00022 #define DATA_END     ((char) 5)
00023 #define DATA_ESCAPE  ((char) 27)
00024 #define DATA_COMMAND '\20'
00025 
00026 // Completion
00027 
00028 static void
00029 output_completion (const string& text, const list<string>& matches2) {
00030   list<string> matches= matches2;
00031   mmout << DATA_BEGIN << "scheme:(tuple ";
00032   mmout << '\"' << text << '\"';
00033   while (!is_nil (matches)) {
00034     if (N (car (matches)) >0)
00035       mmout << " \"" << car (matches) << '\"';
00036     matches = cdr (matches);
00037   }
00038   mmout << ')';
00039   mmout << DATA_END << flush_now;
00040 }
00041 
00042 static void
00043 complete (const string& text) {
00044   list<string> matches, tomatch;
00045   string name;
00046   tomatch = identifiers_for_completion 
00047     * strings_for_completion (get_environment (current_ev));
00048   while (!is_nil (tomatch)) {
00049     name = car (tomatch);
00050     tomatch = cdr (tomatch);
00051     if (starts (name, text))
00052       matches = cons (name (N(text), N(name)), matches);
00053   }
00054   output_completion (text, matches);
00055 }
00056 
00057 /*
00058  * texmacs request parser
00059  */
00060 
00061 static bool
00062 parse_char (const string& text, char c, nat& pos) {
00063   if ((pos >= N(text)) || (text[pos]!=c)) return false;
00064   ++pos;
00065   return true;
00066 }
00067 
00068 static bool
00069 parse_blanks (const string& text, nat& pos) {
00070   nat beg= pos;
00071   while (pos < N(text) &&
00072          (text[pos] == ' ' || text[pos] == '\t' || text[pos] == '\n'))
00073     ++pos;
00074   return (pos > beg);
00075 }
00076 
00077 static bool
00078 parse_nat (const string& text, nat& pos, nat& out) {
00079   nat beg= pos;
00080   while (pos < N(text) && text[pos] >= '0' && text[pos] <= '9')
00081     ++pos;
00082   out= as_int (text (beg, pos));
00083   return (pos > beg);
00084 }
00085 
00086 static bool
00087 parse_identifier (const string& text, const string& id, nat& pos) {
00088   nat beg = pos;
00089   for(nat j=0; j < N(id); pos++,j++)
00090     if ((pos >= N(text)) || (text[pos]!=id[j])) {
00091       pos = beg;
00092       return false;
00093     }
00094   return true;
00095 }
00096 
00097 static bool
00098 parse_string (const string& text, nat& pos, string& out) {
00099   bool esc= false;
00100   nat i= pos;
00101   if (!parse_char(text, '\"', i)) return false;
00102   while ((i < N(text)) && (esc || text[i]!='\"')) {
00103     esc = (!esc) && (text[i]=='\\');
00104     ++i;
00105   }
00106   out = text(pos+1,i);
00107   if (!parse_char(text,'\"',i)) return false;
00108   pos = i;
00109   return true;
00110 }
00111 
00112 static bool
00113 parse_completion_request (const string& text, nat& pos, string& s, nat& p) {
00114   nat i=pos;
00115   if (!parse_char(text, '(', i)) return false;
00116   parse_blanks(text, i);
00117   if (!parse_identifier(text, "complete", i)) return false;
00118   parse_blanks(text, i);
00119   if (!parse_string(text, i, s)) return false;
00120   parse_blanks(text, i);
00121   if (!parse_nat(text, i, p)) return false;
00122   parse_blanks(text, i);
00123   if (!parse_char(text, ')', i)) return false;
00124   pos = i;
00125   return true;
00126 }
00127 
00128 static void
00129 handle_completion_request (const string& request) {
00130   string text;
00131   nat pos, i, p;
00132   p = 0;
00133   pos = 0;
00134   if (!parse_completion_request (request, pos, text, p)
00135       || p < 1 || p >= N(request)) {
00136     output_completion ("", list<string>());
00137     mmerr << "mmx warning: ignoring texmacs request" << "\n";
00138     return;
00139   }
00140   i=p-1;
00141   while (i+1 > 0 && ((text[i] >= 'a' && text[i] <= 'z')
00142                      || (text[i] >= 'A' && text[i] <= 'Z')
00143                      || text[i] == '_'))
00144     i--;
00145   complete (text (i+1, p));
00146 }
00147 
00148 // readline
00149 
00150 void
00151 shell_texmacs_initialize () {
00152   dynamic_event= texmacs_dynamic_event;
00153   mmout << DATA_BEGIN << "verbatim:";
00154   if (completion_mode) {
00155     mmout << DATA_BEGIN << "command:";
00156     mmout << "(plugin-configure mathemagix (:tab-completion #t))";
00157     mmout << DATA_END;
00158   }
00159 }
00160 
00161 bool
00162 shell_texmacs_input (string& line) {
00163   static nat nr= 1;
00164   string next= "\"" * as_string (nr++) * "\"";
00165   mmout << DATA_BEGIN << "channel:prompt" << DATA_END;
00166   mmout << DATA_BEGIN << "scheme:(mmx-prompt " << next << ")" << DATA_END;
00167   mmout << texmacs_flush_commands ();
00168   mmout << DATA_END << flush_now;
00169   string in;
00170   string request;
00171   char c;
00172   nat discard=0;
00173   while (busy (mmin)) {
00174     mmin >> c;
00175     if (c==DATA_COMMAND) {
00176       discard++;
00177       continue;
00178     }
00179     if (c=='\n' && discard) {
00180       discard--;
00181       if (discard==0) {
00182         if (completion_mode)
00183           handle_completion_request(request);
00184         request = string("");
00185       }
00186       continue;
00187     }
00188     if (discard) {
00189       request << c;
00190       continue;
00191     }
00192     if (c=='\n' && !discard) break;
00193     in << c;
00194   }
00195   mmout << DATA_BEGIN << "verbatim:";
00196   if (N(in)==0 && c==EOF) {
00197     mmout << DATA_END << flush_now;
00198     return false;
00199   }
00200   line = recompose (tokenize (in, "/{CR}/"), "\n", true);
00201   store_interactive_source (line);
00202   return true;
00203 }
00204 
00205 // Output
00206 
00207 void
00208 shell_texmacs_output (const generic& g, const generic& t) {
00209   if (math_mode) {
00210     mmout << DATA_BEGIN << "scheme:";
00211     mmout << flatten_as_texmacs_scheme (g);
00212     mmout << DATA_END;
00213   }
00214   else
00215     mmout << g;
00216   if (exact_neq (t, "None") && exact_neq (t, "Document"))
00217     mmout << ": " << t;
00218   mmout << "\n";
00219 }
00220 
00221 } // namespace mmx

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