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