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 }