version 1.1, 2001/10/02 11:17:07 |
version 1.2, 2002/09/11 07:26:56 |
Line 23 Foundation, Inc., 59 Temple Place - Suite 330, Boston, |
|
Line 23 Foundation, Inc., 59 Temple Place - Suite 330, Boston, |
|
#include "gp.h" |
#include "gp.h" |
|
|
#ifdef READLINE |
#ifdef READLINE |
typedef char** (*CF)(char*, char* (*)()); /* completion function */ |
typedef char** (*CF)(char*, char* (*)(void)); /* completion function */ |
typedef char* (*GF)(char*, int); /* generator function */ |
typedef char* (*GF)(char*, int); /* generator function */ |
typedef int (*RLCI)(int, int); /* rl_complete and rl_insert functions */ |
typedef int (*RLCI)(int, int); /* rl_complete and rl_insert functions */ |
|
|
|
|
#endif |
#endif |
#ifdef READLINE_LIBRARY |
#ifdef READLINE_LIBRARY |
# include <readline.h> |
# include <readline.h> |
|
# include <history.h> |
#else |
#else |
# include <readline/readline.h> |
# include <readline/readline.h> |
|
# include <readline/history.h> |
#endif |
#endif |
#ifndef HAS_RL_MESSAGE |
#ifndef HAS_RL_MESSAGE |
extern int rl_message (const char *, ...); |
extern int rl_message (const char *, ...); |
Line 47 extern char *filename_completion_function(char *text,i |
|
Line 49 extern char *filename_completion_function(char *text,i |
|
extern char *username_completion_function(char *text,int state); |
extern char *username_completion_function(char *text,int state); |
#endif |
#endif |
char **pari_completion(char *text, int start, int end); |
char **pari_completion(char *text, int start, int end); |
extern int rl_completion_query_items; |
|
extern int rl_bind_key_in_map(); |
|
ENDEXTERN |
ENDEXTERN |
|
|
void print_fun_list(char **matches, int nbli); |
void print_fun_list(char **matches, int nbli); |
Line 103 change_state(char *msg, int *opt, int count) |
|
Line 103 change_state(char *msg, int *opt, int count) |
|
} |
} |
*opt = c; |
*opt = c; |
SAVE_PROMPT(); |
SAVE_PROMPT(); |
rl_message("%s: %s.", (long)msg, (long)(c? "on": "off")); |
rl_message("%s: %s.", msg, c? "on": "off"); |
c = rl_read_key(); |
c = rl_read_key(); |
RESTORE_PROMPT(); |
RESTORE_PROMPT(); |
rl_clear_message(); |
rl_clear_message(); |
Line 141 pari_rl_matched_insert(int count, int key) |
|
Line 141 pari_rl_matched_insert(int count, int key) |
|
if (count <= 0) |
if (count <= 0) |
return change_state("electric parens", &do_matched_insert, count); |
return change_state("electric parens", &do_matched_insert, count); |
while (paropen[i] && paropen[i] != key) i++; |
while (paropen[i] && paropen[i] != key) i++; |
if (!paropen[i] || !do_matched_insert || under_emacs) |
if (!paropen[i] || !do_matched_insert || GP_DATA->flags & EMACS) |
return ((RLCI)rl_insert)(count,key); |
return ((RLCI)rl_insert)(count,key); |
rl_begin_undo_group(); |
rl_begin_undo_group(); |
((RLCI)rl_insert)(count,key); |
((RLCI)rl_insert)(count,key); |
Line 262 add_paren(int end) |
|
Line 262 add_paren(int end) |
|
static void |
static void |
match_concat(char **matches, char *s) |
match_concat(char **matches, char *s) |
{ |
{ |
int i = strlen(matches[0]) + 1; |
matches[0] = (char*) gprealloc(matches[0], strlen(matches[0])+strlen(s)+1); |
matches[0] = (char*) gprealloc(matches[0], i+strlen(s), i); |
|
strcat(matches[0],s); |
strcat(matches[0],s); |
} |
} |
|
|
Line 303 get_matches(int end, char *text, char* f(char*,int)) |
|
Line 302 get_matches(int end, char *text, char* f(char*,int)) |
|
rl_completion_append_character = ' '; |
rl_completion_append_character = ' '; |
#endif |
#endif |
current_ep = NULL; |
current_ep = NULL; |
matches = COMPLETION_MATCHES(text, (char *(*)())f); |
matches = COMPLETION_MATCHES(text, (char *(*)(void))f); |
if (matches && !matches[1]) /* a single match */ |
if (matches && !matches[1]) /* a single match */ |
{ |
{ |
if (add_paren(end)) |
if (add_paren(end)) |
Line 320 get_matches(int end, char *text, char* f(char*,int)) |
|
Line 319 get_matches(int end, char *text, char* f(char*,int)) |
|
else if (add_comma(end)) |
else if (add_comma(end)) |
match_concat(matches,","); |
match_concat(matches,","); |
} |
} |
if (under_emacs) matches = matches_for_emacs(text,matches); |
if (GP_DATA->flags & EMACS) matches = matches_for_emacs(text,matches); |
return matches; |
return matches; |
} |
} |
#undef add_comma |
#undef add_comma |
Line 461 rl_print_aide(char *s, int flag) |
|
Line 460 rl_print_aide(char *s, int flag) |
|
|
|
rl_point = 0; rl_end = 0; pari_outfile = rl_outstream; |
rl_point = 0; rl_end = 0; pari_outfile = rl_outstream; |
SAVE_PROMPT(); |
SAVE_PROMPT(); |
rl_message("",0,0); |
rl_message("%s",""); /* rl_message("") ==> "zero length format" warning */ |
aide(s, flag); |
aide(s, flag); |
RESTORE_PROMPT(); |
RESTORE_PROMPT(); |
rl_point = p; rl_end = e; pari_outfile = save; |
rl_point = p; rl_end = e; pari_outfile = save; |
Line 538 pari_completion(char *text, int START, int END) |
|
Line 537 pari_completion(char *text, int START, int END) |
|
while (j <= END && isspace((int)rl_line_buffer[j])) j++; |
while (j <= END && isspace((int)rl_line_buffer[j])) j++; |
k = END; |
k = END; |
while (k > j && isspace((int)rl_line_buffer[k])) k--; |
while (k > j && isspace((int)rl_line_buffer[k])) k--; |
/* If we are in empty parens, insert arguments for the function: */ |
/* If we are in empty parens, output function help */ |
if (do_args_complete && k == j |
if (do_args_complete && k == j |
&& (rl_line_buffer[j] == ')' || !rl_line_buffer[j]) |
&& (rl_line_buffer[j] == ')' || !rl_line_buffer[j]) |
&& (iend - i < MAX_KEYWORD) |
&& (iend - i < MAX_KEYWORD) |
Line 546 pari_completion(char *text, int START, int END) |
|
Line 545 pari_completion(char *text, int START, int END) |
|
buf[iend - i] = 0, 1) |
buf[iend - i] = 0, 1) |
&& (ep = is_entry(buf)) && ep->help) |
&& (ep = is_entry(buf)) && ep->help) |
{ |
{ |
#if 0 |
|
char *s = ep->help; |
|
|
|
while (is_keyword_char(*s)) s++; |
|
if (*s++ == '(') |
|
{ /* Function, print arguments! */ |
|
char *endh = s; |
|
while (*endh && *endh != ')' && *endh != '(') endh++; |
|
if (*endh == ')') |
|
{ /* Well-formed help. */ |
|
char *str = strncpy((char*) gpmalloc(endh-s + 1), s, endh-s); |
|
char **ret = (char**)gpmalloc(sizeof(char*)*2); |
|
str[endh-s] = 0; |
|
ret[0] = str; ret[1] = NULL; |
|
if (under_emacs) ret = matches_for_emacs("",ret); |
|
return ret; |
|
} |
|
} |
|
#endif |
|
rl_print_aide(buf,h_RL); |
rl_print_aide(buf,h_RL); |
rl_attempted_completion_over = 1; |
rl_attempted_completion_over = 1; |
return NULL; |
return NULL; |
Line 621 rl_long_help(int count, int key) |
|
Line 601 rl_long_help(int count, int key) |
|
} |
} |
|
|
void |
void |
init_readline() |
init_readline(void) |
{ |
{ |
/* Allow conditional parsing of the ~/.inputrc file. */ |
/* Allow conditional parsing of the ~/.inputrc file. */ |
rl_readline_name = "Pari-GP"; |
rl_readline_name = "Pari-GP"; |
|
|
rl_attempted_completion_function = (rl_completion_func_t*) pari_completion; |
rl_attempted_completion_function = (rl_completion_func_t*) pari_completion; |
|
|
/* we always want the whole list of completions under emacs */ |
/* we always want the whole list of completions under emacs */ |
if (under_emacs) rl_completion_query_items = 0x8fff; |
if (GP_DATA->flags & EMACS) rl_completion_query_items = 0x8fff; |
|
|
#define Bind(a,b,c) (((void(*)(int,Function*,Keymap)) rl_bind_key_in_map)\ |
#define Bind(a,b,c) (((void(*)(int,Function*,Keymap)) rl_bind_key_in_map)\ |
((a), (Function*)(b), (c))) |
((a), (Function*)(b), (c))) |
|
|
Bind(155, pari_rl_backward_sexp, emacs_dos_keymap); /* Alt-Left */ |
Bind(155, pari_rl_backward_sexp, emacs_dos_keymap); /* Alt-Left */ |
Bind(157, pari_rl_forward_sexp, emacs_dos_keymap); /* Alt-Right*/ |
Bind(157, pari_rl_forward_sexp, emacs_dos_keymap); /* Alt-Right*/ |
#endif |
#endif |
|
} |
|
|
|
static int |
|
history_is_new(char *s) |
|
{ |
|
return (*s && (!history_length || |
|
strcmp(s, history_get(history_length)->line))); |
|
} |
|
|
|
static void |
|
gp_add_history(char *s) |
|
{ |
|
if (history_is_new(s)) add_history(s); |
|
} |
|
|
|
extern void fix_buffer(Buffer *b, long newlbuf); |
|
extern int input_loop(filtre_t *F, input_method *IM); |
|
|
|
/* Read line; returns a malloc()ed string of the user input or NULL on EOF. |
|
Increments the buffer size appropriately if needed; fix *endp if so. */ |
|
static char * |
|
gprl_input(Buffer *b, char **endp, input_method *IM) |
|
{ |
|
long used = *endp - b->buf; |
|
long left = b->len - used, l; |
|
char *s; |
|
|
|
if (! (s = readline(IM->prompt)) ) return NULL; /* EOF */ |
|
l = strlen(s); |
|
if ((ulong)left < l) |
|
{ |
|
long incr = b->len; |
|
|
|
if (incr < l) incr = l; |
|
fix_buffer(b, b->len + incr); |
|
*endp = b->buf + used; |
|
} |
|
gp_add_history(s); /* Makes a copy */ |
|
return s; |
|
} |
|
|
|
static void |
|
unblock_SIGINT(void) |
|
{ |
|
#ifdef USE_SIGRELSE |
|
sigrelse(SIGINT); |
|
#elif USE_SIGSETMASK |
|
sigsetmask(0); |
|
#endif |
|
} |
|
|
|
/* request one line interactively. |
|
* Return 0: EOF |
|
* 1: got one line from readline or infile */ |
|
int |
|
get_line_from_readline(char *prompt, filtre_t *F) |
|
{ |
|
const int index = history_length; |
|
char *s; |
|
input_method IM; |
|
|
|
IM.prompt = prompt; |
|
IM.getline= &gprl_input; |
|
IM.free = 1; |
|
if (! input_loop(F,&IM)) { pariputs("\n"); return 0; } |
|
|
|
s = ((Buffer*)F->data)->buf; |
|
if (*s) |
|
{ |
|
if (history_length > index+1) |
|
{ /* Multi-line input. Remove incomplete lines */ |
|
int i = history_length; |
|
while (i > index) { |
|
HIST_ENTRY *e = remove_history(--i); |
|
free(e->line); free(e); |
|
} |
|
gp_add_history(s); |
|
} |
|
|
|
/* update logfile */ |
|
if (logfile) fprintf(logfile, "%s%s\n",prompt,s); |
|
} |
|
unblock_SIGINT(); /* bug in readline 2.0: need to unblock ^C */ |
|
return 1; |
} |
} |
#endif |
#endif |