Line data Source code
1 : /* Copyright (C) 2000 The PARI group.
2 :
3 : This file is part of the PARI/GP package.
4 :
5 : PARI/GP is free software; you can redistribute it and/or modify it under the
6 : terms of the GNU General Public License as published by the Free Software
7 : Foundation; either version 2 of the License, or (at your option) any later
8 : version. It is distributed in the hope that it will be useful, but WITHOUT
9 : ANY WARRANTY WHATSOEVER.
10 :
11 : Check the License for details. You should have received a copy of it, along
12 : with the package; see the file 'COPYING'. If not, write to the Free Software
13 : Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
14 :
15 : /*******************************************************************/
16 : /* */
17 : /* TEXMACS-SPECIFIC STUFF */
18 : /* */
19 : /*******************************************************************/
20 : #include "pari.h"
21 :
22 : #include "paripriv.h"
23 : #include "gp.h"
24 :
25 : #define DATA_BEGIN ((char) 2)
26 : #define DATA_END ((char) 5)
27 : #define DATA_ESCAPE ((char) 27)
28 :
29 : /*******************************************************************/
30 : /* */
31 : /* READLINE INTERFACE */
32 : /* */
33 : /*******************************************************************/
34 : #ifdef READLINE
35 : static pari_rl_interface pari_rl;
36 : #endif
37 : static int did_complete = 0;
38 :
39 : #ifdef READLINE
40 : BEGINEXTERN
41 : #include <readline/readline.h>
42 : ENDEXTERN
43 :
44 : static void
45 0 : print_escape_string(char *s)
46 : {
47 0 : long l = strlen(s);
48 0 : char *t, *t0 = (char*)pari_malloc(l * 3 + 3);
49 :
50 0 : t = t0; *t++ = '"';
51 0 : for ( ;*s; *t++ = *s++)
52 0 : switch(*s)
53 : {
54 0 : case DATA_BEGIN:
55 : case DATA_END:
56 0 : case DATA_ESCAPE: *t++ = DATA_ESCAPE; continue;
57 :
58 0 : case '\\':
59 0 : case '"': *t++ = '\\'; continue;
60 : }
61 0 : *t++ = '"';
62 0 : *t = '\0'; puts(t0); pari_free(t0);
63 0 : }
64 :
65 : /* completion required, cursor on s + pos. Complete wrt strict left prefix */
66 : static void
67 0 : tm_completion(const char *s, long pos)
68 : {
69 : char **matches, *text;
70 : long w;
71 :
72 0 : matches = pari_completion_matches(&pari_rl, s, pos, &w);
73 0 : text = *pari_rl.line_buffer + w;
74 0 : printf("%cscheme:(tuple",DATA_BEGIN);
75 0 : if (matches)
76 : {
77 0 : long i, prelen = (rl_line_buffer+pos) - text;
78 0 : char *t = (char*)pari_malloc(prelen+1);
79 0 : strncpy(t, text, prelen); t[prelen] = 0; /* prefix */
80 0 : printf(" ");
81 0 : print_escape_string(t); pari_free(t);
82 0 : for (i = matches[1]? 1: 0; matches[i]; i++)
83 : {
84 0 : printf(" ");
85 0 : print_escape_string(matches[i] + prelen);
86 0 : pari_free(matches[i]);
87 : }
88 0 : pari_free(matches);
89 : }
90 0 : printf(")%c", DATA_END);
91 0 : fflush(stdout);
92 0 : }
93 : #else
94 : /* no-op */
95 : static void
96 : tm_completion(const char *s, long pos) { (void)s; (void)pos; }
97 : #endif
98 :
99 : typedef struct {
100 : char *cmd;
101 : long n; /* number of args */
102 : char **v; /* args */
103 : } tm_cmd;
104 :
105 : static void
106 0 : tm_parse_command(tm_cmd *c, const char *ch)
107 : {
108 0 : long l = strlen(ch);
109 0 : char *t, *s = (char*)ch, *send = s+l-1;
110 : char **A;
111 : pari_stack s_A;
112 :
113 0 : if (*s != DATA_BEGIN || *send-- != DATA_END)
114 0 : pari_err(e_MISC, "missing DATA_[BEGIN | END] in TeXmacs command");
115 0 : s++;
116 0 : if (strncmp(s, "special:", 8)) pari_err(e_MISC, "unrecognized TeXmacs command");
117 0 : s += 8;
118 0 : if (*s != '(' || *send-- != ')')
119 0 : pari_err(e_MISC, "missing enclosing parentheses for TeXmacs command");
120 0 : s++; t = s;
121 0 : pari_skip_alpha(&s);
122 0 : c->cmd = pari_strndup(t, s - t);
123 0 : pari_stack_init(&s_A,sizeof(*A),(void**)&A);
124 0 : for (c->n = 0; s <= send; c->n++)
125 : {
126 0 : char *u = (char*)pari_malloc(strlen(s) + 1);
127 0 : pari_skip_space(&s);
128 0 : if (*s == '"') s = pari_translate_string(s, u, t);
129 : else
130 : { /* read integer */
131 0 : t = s;
132 0 : while (isdigit((unsigned char)*s)) s++;
133 0 : strncpy(u, t, s - t); u[s-t] = 0;
134 : }
135 0 : pari_stack_pushp(&s_A, u);
136 : }
137 0 : c->v = A;
138 0 : }
139 :
140 : static void
141 0 : tm_free_cmd(tm_cmd *c)
142 : {
143 0 : while (c->n--) pari_free((void*)c->v[c->n]);
144 0 : pari_free((void*)c->v);
145 0 : }
146 :
147 : static void
148 0 : tm_handle_command(const char *s)
149 : {
150 : tm_cmd c;
151 0 : tm_parse_command(&c, s);
152 0 : if (strcmp(c.cmd, "complete"))
153 0 : pari_err(e_MISC,"Texmacs command %s not implemented", c.cmd);
154 0 : if (c.n != 2)
155 0 : pari_err(e_MISC,"was expecting 2 arguments for Texmacs command");
156 0 : tm_completion(c.v[0], atol(c.v[1]));
157 0 : tm_free_cmd(&c);
158 0 : did_complete = 1;
159 0 : }
160 :
161 : /****/
162 :
163 : int
164 0 : tm_is_interactive(void) { return 0; }
165 :
166 : static int tm_is_waiting = 0;
167 : /* tell TeXmacs GP will start outputing data */
168 : void
169 0 : tm_start_output(void)
170 : {
171 0 : if (!tm_is_waiting) { printf("%cverbatim:",DATA_BEGIN); fflush(stdout); }
172 0 : tm_is_waiting = 1;
173 0 : }
174 : /* tell TeXmacs GP is done and is waiting for new data */
175 : void
176 0 : tm_end_output(void)
177 : {
178 0 : if (tm_is_waiting) { printf("%c", DATA_END); fflush(stdout); }
179 0 : tm_is_waiting = 0;
180 0 : }
181 : char *
182 0 : tm_fgets(char *s, int n, FILE *f)
183 : {
184 0 : if (!did_complete)
185 : { /* we need input */
186 0 : tm_start_output();
187 0 : tm_end_output();
188 : }
189 0 : return fgets(s,n,f);
190 : }
191 :
192 : int
193 0 : tm_get_line(const char *prompt, const char *prompt_cont, filtre_t *F)
194 : {
195 0 : int res = get_line_from_file(prompt, F, pari_infile);
196 : (void)prompt_cont;
197 0 : if (res)
198 : {
199 0 : char *s = F->buf->buf;
200 0 : did_complete = 0;
201 0 : if (pari_infile == stdin && *s == DATA_BEGIN)
202 0 : { tm_handle_command(s); *s = 0; }
203 : else
204 0 : tm_start_output();
205 : }
206 0 : return res;
207 : }
208 :
209 : static void
210 0 : tm_output(long n)
211 : {
212 0 : char *sz = GENtoTeXstr(pari_get_hist(n));
213 0 : printf("%clatex:", DATA_BEGIN);
214 0 : printf("\\magenta\\%%%lu = ", n);
215 0 : printf("$\\blue %s$%c", sz,DATA_END);
216 0 : pari_free(sz); fflush(stdout);
217 0 : pari_flush();
218 0 : }
219 :
220 : void
221 0 : init_texmacs(void)
222 : {
223 : #ifdef READLINE
224 0 : printf("%ccommand:(cas-supports-completions-set! \"pari\")%c\n",
225 : DATA_BEGIN, DATA_END);
226 0 : pari_use_readline(pari_rl);
227 : #endif
228 0 : cb_pari_fgets_interactive = tm_fgets;
229 0 : cb_pari_get_line_interactive = tm_get_line;
230 :
231 0 : cb_pari_start_output = tm_start_output;
232 0 : cb_pari_end_output = tm_end_output;
233 0 : cb_pari_is_interactive = tm_is_interactive;
234 0 : cb_pari_display_hist = tm_output;
235 0 : disable_color = 1;
236 0 : tm_start_output();
237 0 : }
|