[BACK]Return to gp_rl.c CVS log [TXT][DIR] Up to [local] / OpenXM_contrib / pari-2.2 / src / gp

Annotation of OpenXM_contrib/pari-2.2/src/gp/gp_rl.c, Revision 1.1.1.1

1.1       noro        1: /* $Id: gp_rl.c,v 1.11 2001/09/27 09:47:51 karim Exp $
                      2:
                      3: Copyright (C) 2000  The PARI group.
                      4:
                      5: This file is part of the PARI/GP package.
                      6:
                      7: PARI/GP is free software; you can redistribute it and/or modify it under the
                      8: terms of the GNU General Public License as published by the Free Software
                      9: Foundation. It is distributed in the hope that it will be useful, but WITHOUT
                     10: ANY WARRANTY WHATSOEVER.
                     11:
                     12: Check the License for details. You should have received a copy of it, along
                     13: with the package; see the file 'COPYING'. If not, write to the Free Software
                     14: Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
                     15:
                     16: /*******************************************************************/
                     17: /*                                                                 */
                     18: /*                 INTERFACE TO READLINE COMPLETION                */
                     19: /*                                                                 */
                     20: /*******************************************************************/
                     21: #include "pari.h"
                     22: #include "../language/anal.h"
                     23: #include "gp.h"
                     24:
                     25: #ifdef READLINE
                     26: typedef char** (*CF)(char*, char* (*)()); /* completion function */
                     27: typedef char* (*GF)(char*, int); /* generator function */
                     28: typedef int (*RLCI)(int, int); /* rl_complete and rl_insert functions */
                     29:
                     30: BEGINEXTERN
                     31: #ifdef HAS_RL_MESSAGE
                     32: #  define USE_VARARGS
                     33: #  define PREFER_STDARG
                     34: #endif
                     35: #ifdef READLINE_LIBRARY
                     36: #  include <readline.h>
                     37: #else
                     38: #  include <readline/readline.h>
                     39: #endif
                     40: #ifndef HAS_RL_MESSAGE
                     41: extern int rl_message (const char *, ...);
                     42: extern int rl_clear_message();
                     43: extern int rl_begin_undo_group(), rl_end_undo_group();
                     44: extern int rl_read_key();
                     45: extern int rl_stuff_char();
                     46: extern char *filename_completion_function(char *text,int state);
                     47: extern char *username_completion_function(char *text,int state);
                     48: #endif
                     49: char **pari_completion(char *text, int start, int end);
                     50: extern int rl_completion_query_items;
                     51: extern int rl_bind_key_in_map();
                     52: ENDEXTERN
                     53:
                     54: void print_fun_list(char **matches, int nbli);
                     55: void aide(char *s, int flag);
                     56:
                     57: extern default_type gp_default_list[];
                     58: extern char *keyword_list[];
                     59: static int add_help_keywords;
                     60: static entree *current_ep = NULL;
                     61:
                     62: static int pari_rl_back;
                     63: extern RLCI rl_last_func;
                     64: static int do_args_complete = 1;
                     65: static int do_matched_insert = 0;
                     66: static int did_init_matched = 0;
                     67:
                     68: #ifdef HAS_RL_SAVE_PROMPT
                     69: #  define SAVE_PROMPT() rl_save_prompt()
                     70: #  define RESTORE_PROMPT() rl_restore_prompt()
                     71: #else
                     72: #  ifdef HAS_UNDERSCORE_RL_SAVE_PROMPT
                     73: #    define SAVE_PROMPT() _rl_save_prompt()
                     74: #    define RESTORE_PROMPT() _rl_restore_prompt()
                     75: #  else
                     76: #    define SAVE_PROMPT()
                     77: #    define RESTORE_PROMPT()
                     78: #  endif
                     79: #endif
                     80:
                     81: #ifdef HAS_RL_COMPLETION_MATCHES
                     82: #  define COMPLETION_MATCHES ((CF)rl_completion_matches)
                     83: #  define FILE_COMPLETION ((GF)rl_filename_completion_function)
                     84: #  define USER_COMPLETION ((GF)rl_username_completion_function)
                     85: #else
                     86: #  define COMPLETION_MATCHES ((CF)completion_matches)
                     87: #  define FILE_COMPLETION ((GF)filename_completion_function)
                     88: #  define USER_COMPLETION ((GF)username_completion_function)
                     89: #endif
                     90:
                     91: #define ELECTRIC_PAREN 1
                     92: #define ARGS_COMPLETE  2
                     93: static int
                     94: change_state(char *msg, int *opt, int count)
                     95: {
                     96:   int c;
                     97:
                     98:   switch(count)
                     99:   {
                    100:     default: c = 0; break; /* off */
                    101:     case -1: c = 1; break; /* on  */
                    102:     case -2: c = 1 - *opt; /* toggle */
                    103:   }
                    104:   *opt = c;
                    105:   SAVE_PROMPT();
                    106:   rl_message("%s: %s.", (long)msg, (long)(c? "on": "off"));
                    107:   c = rl_read_key();
                    108:   RESTORE_PROMPT();
                    109:   rl_clear_message();
                    110:   rl_stuff_char(c); return 1;
                    111: }
                    112:
                    113: /* Wrapper around rl_complete to allow toggling insertion of arguments */
                    114: static int
                    115: pari_rl_complete(int count, int key)
                    116: {
                    117:   int ret;
                    118:
                    119:   pari_rl_back = 0;
                    120:   if (count <= 0)
                    121:     return change_state("complete args", &do_args_complete, count);
                    122:
                    123:   rl_begin_undo_group();
                    124:   if (rl_last_func == pari_rl_complete)
                    125:     rl_last_func = (RLCI) rl_complete; /* Make repeated TABs different */
                    126:   ret = ((RLCI)rl_complete)(count,key);
                    127:   if (pari_rl_back && (pari_rl_back <= rl_point))
                    128:     rl_point -= pari_rl_back;
                    129:   rl_end_undo_group(); return ret;
                    130: }
                    131:
                    132: static const char paropen[] = "([{";
                    133: static const char parclose[] = ")]}";
                    134:
                    135: /* To allow insertion of () with a point in between. */
                    136: static int
                    137: pari_rl_matched_insert(int count, int key)
                    138: {
                    139:   int i = 0, ret;
                    140:
                    141:   if (count <= 0)
                    142:     return change_state("electric parens", &do_matched_insert, count);
                    143:   while (paropen[i] && paropen[i] != key) i++;
                    144:   if (!paropen[i] || !do_matched_insert || under_emacs)
                    145:     return ((RLCI)rl_insert)(count,key);
                    146:   rl_begin_undo_group();
                    147:   ((RLCI)rl_insert)(count,key);
                    148:   ret = ((RLCI)rl_insert)(count,parclose[i]);
                    149:   rl_point -= count;
                    150:   rl_end_undo_group(); return ret;
                    151: }
                    152:
                    153: static int
                    154: pari_rl_default_matched_insert(int count, int key)
                    155: {
                    156:     if (!did_init_matched) {
                    157:        did_init_matched = 1;
                    158:        do_matched_insert = 1;
                    159:     }
                    160:     return pari_rl_matched_insert(count, key);
                    161: }
                    162:
                    163: static int
                    164: pari_rl_forward_sexp(int count, int key)
                    165: {
                    166:   int deep = 0, dir = 1, move_point = 0, lfail;
                    167:
                    168:   (void)key;
                    169:   if (count < 0)
                    170:   {
                    171:     count = -count; dir = -1;
                    172:     if (!rl_point) goto fail;
                    173:     rl_point--;
                    174:   }
                    175:   while (count || deep)
                    176:   {
                    177:     move_point = 1;    /* Need to move point if moving left. */
                    178:     lfail = 0;         /* Do not need to fail left movement yet. */
                    179:     while ( !is_keyword_char(rl_line_buffer[rl_point])
                    180:             && !strchr("\"([{}])",rl_line_buffer[rl_point])
                    181:             && !( (dir == 1)
                    182:                   ? (rl_point >= rl_end)
                    183:                   : (rl_point <= 0 && (lfail = 1))))
                    184:         rl_point += dir;
                    185:     if (lfail || !rl_line_buffer[rl_point]) goto fail;
                    186:
                    187:     if (is_keyword_char(rl_line_buffer[rl_point]))
                    188:     {
                    189:       while ( is_keyword_char(rl_line_buffer[rl_point])
                    190:               && (!((dir == 1) ? (rl_point >= rl_end) : (rl_point <= 0))
                    191:                   || (move_point = 0)))
                    192:         rl_point += dir;
                    193:       if (!deep) count--;
                    194:     }
                    195:     else if (strchr(paropen,rl_line_buffer[rl_point]))
                    196:     {
                    197:       if (deep == 0 && dir == -1) goto fail; /* We are already out of pars. */
                    198:       rl_point += dir;
                    199:       deep++; if (!deep) count--;
                    200:     }
                    201:     else if (strchr(parclose,rl_line_buffer[rl_point]))
                    202:     {
                    203:       if (deep == 0 && dir == 1)
                    204:       {
                    205:         rl_point++; goto fail; /* Get out of pars. */
                    206:       }
                    207:       rl_point += dir;
                    208:       deep--; if (!deep) count--;
                    209:     }
                    210:     else if (rl_line_buffer[rl_point] == '\"')
                    211:     {
                    212:       int bad = 1;
                    213:
                    214:       rl_point += dir;
                    215:       while ( ((rl_line_buffer[rl_point] != '\"') || (bad = 0))
                    216:               && (!((dir == 1) ? (rl_point >= rl_end) : (rl_point <= 0))
                    217:                   || (move_point = 0)) )
                    218:         rl_point += dir;
                    219:       if (bad) goto fail;
                    220:       rl_point += dir; /* Skip the other delimiter */
                    221:       if (!deep) count--;
                    222:     }
                    223:     else
                    224:     {
                    225:       fail: ding(); return 1;
                    226:     }
                    227:   }
                    228:   if (dir != 1 && move_point) rl_point++;
                    229:   return 1;
                    230: }
                    231:
                    232: static int
                    233: pari_rl_backward_sexp(int count, int key)
                    234: {
                    235:   return pari_rl_forward_sexp(-count, key);
                    236: }
                    237:
                    238: /* do we add () at the end of completed word? (is it a function?) */
                    239: static int
                    240: add_paren(int end)
                    241: {
                    242:   entree *ep;
                    243:   char *s;
                    244:
                    245:   if (end < 0 || rl_line_buffer[end] == '(')
                    246:     return 0; /* not from command_generator or already there */
                    247:   ep = do_alias(current_ep); /* current_ep set in command_generator */
                    248:   if (EpVALENCE(ep) < EpUSER)
                    249:   { /* is it a constant masked as a function (e.g Pi)? */
                    250:     s = ep->help; if (!s) return 1;
                    251:     while (is_keyword_char(*s)) s++;
                    252:     return (*s != '=');
                    253:   }
                    254:   switch(EpVALENCE(ep))
                    255:   {
                    256:     case EpUSER:
                    257:     case EpINSTALL: return 1;
                    258:   }
                    259:   return 0;
                    260: }
                    261:
                    262: static void
                    263: match_concat(char **matches, char *s)
                    264: {
                    265:   int i = strlen(matches[0]) + 1;
                    266:   matches[0] = (char*) gprealloc(matches[0], i+strlen(s), i);
                    267:   strcat(matches[0],s);
                    268: }
                    269:
                    270: static char **
                    271: matches_for_emacs(char *text, char **matches)
                    272: {
                    273:   if (!matches) printf("@");
                    274:   else
                    275:   {
                    276:     int i;
                    277:     printf("%s@", matches[0] + strlen(text));
                    278:     if (matches[1]) print_fun_list(matches+1,0);
                    279:
                    280:    /* we don't want readline to do anything, but insert some junk
                    281:     * which will be erased by emacs.
                    282:     */
                    283:     for (i=0; matches[i]; i++) free(matches[i]);
                    284:     free(matches);
                    285:   }
                    286:   matches = (char **) gpmalloc(2*sizeof(char *));
                    287:   matches[0] = gpmalloc(2); sprintf(matches[0],"_");
                    288:   matches[1] = NULL; printf("@E_N_D"); pariflush();
                    289:   return matches;
                    290: }
                    291:
                    292: #define add_comma(x) (x==-2) /* from default_generator */
                    293:
                    294: /* Attempt to complete on the contents of TEXT. END points to the end of the
                    295:  * word to complete. Return the array of matches, or NULL if there aren't any.
                    296:  */
                    297: static char **
                    298: get_matches(int end, char *text, char* f(char*,int))
                    299: {
                    300:   char **matches;
                    301:
                    302: #ifdef HAS_COMPLETION_APPEND_CHAR
                    303:   rl_completion_append_character = ' ';
                    304: #endif
                    305:   current_ep = NULL;
                    306:   matches = COMPLETION_MATCHES(text, (char *(*)())f);
                    307:   if (matches && !matches[1]) /* a single match */
                    308:   {
                    309:     if (add_paren(end))
                    310:     {
                    311:       match_concat(matches,"()");
                    312:       pari_rl_back = 1;
                    313:       if (rl_point == rl_end)
                    314: #ifdef HAS_COMPLETION_APPEND_CHAR
                    315:         rl_completion_append_character = '\0'; /* Do not append space. */
                    316: #else
                    317:         pari_rl_back = 2;
                    318: #endif
                    319:     }
                    320:     else if (add_comma(end))
                    321:       match_concat(matches,",");
                    322:   }
                    323:   if (under_emacs) matches = matches_for_emacs(text,matches);
                    324:   return matches;
                    325: }
                    326: #undef add_comma
                    327:
                    328: static char *
                    329: add_junk(char *name, char *text, long junk)
                    330: {
                    331:   char *s = strncpy((char*) gpmalloc(strlen(name)+1+junk),text,junk);
                    332:   strcpy(s+junk,name); return s;
                    333: }
                    334:
                    335: /* Generator function for command completion.  STATE lets us know whether
                    336:  * to start from scratch; without any state (i.e. STATE == 0), then we
                    337:  * start at the top of the list.
                    338:  */
                    339: static char *
                    340: hashtable_generator (char *text, int state, entree **hash)
                    341: {
                    342:   static int hashpos, len, junk, n;
                    343:   static entree* ep;
                    344:   static char *TEXT;
                    345:
                    346:  /* If this is a new word to complete, initialize now:
                    347:   *  + indexes hashpos (GP hash list) and n (keywords specific to long help).
                    348:   *  + file completion and keyword completion use different word boundaries,
                    349:   *    have TEXT point to the keyword start.
                    350:   *  + save the length of TEXT for efficiency.
                    351:   */
                    352:   if (!state)
                    353:   {
                    354:     n = hashpos = 0; ep=hash[hashpos];
                    355:     len=strlen(text); junk=len-1;
                    356:     while (junk >= 0 && is_keyword_char(text[junk])) junk--;
                    357:     junk++; len -= junk; TEXT = text + junk;
                    358:   }
                    359:
                    360:   /* First check the keywords list */
                    361:   if (add_help_keywords)
                    362:   {
                    363:     for ( ; keyword_list[n]; n++)
                    364:       if (!strncmp(keyword_list[n],TEXT,len))
                    365:       {
                    366:         text = add_junk(keyword_list[n],text,junk);
                    367:         n++; return text;
                    368:       }
                    369:   }
                    370:
                    371:   /* Return the next name which partially matches from the command list. */
                    372:   for(;;)
                    373:     if (!ep)
                    374:     {
                    375:       if (++hashpos >= functions_tblsz) return NULL; /* no names matched */
                    376:       ep = hash[hashpos];
                    377:     }
                    378:     else if (strncmp(ep->name,TEXT,len))
                    379:       ep = ep->next;
                    380:     else
                    381:       break;
                    382:   current_ep = ep;
                    383:   text = add_junk(ep->name,text,junk);
                    384:   ep=ep->next; return text;
                    385: }
                    386:
                    387: static char *
                    388: command_generator (char *text, int  state)
                    389: {
                    390:   return hashtable_generator(text,state, functions_hash);
                    391: }
                    392: static char *
                    393: member_generator (char *text, int  state)
                    394: {
                    395:   return hashtable_generator(text,state, members_hash);
                    396: }
                    397:
                    398: #define DFLT 0
                    399: #define ENTREE 1
                    400:
                    401: static char *
                    402: generator(void *list, char *text, int *nn, int len, int typ)
                    403: {
                    404:   char *def = NULL, *name;
                    405:   int n = *nn;
                    406:
                    407:   /* Return the next name which partially matches from list.*/
                    408:   switch(typ)
                    409:   {
                    410:     case DFLT :
                    411:       do
                    412:        def = (((default_type *) list)[n++]).name;
                    413:       while (def && strncmp(def,text,len));
                    414:       break;
                    415:
                    416:     case ENTREE :
                    417:       do
                    418:        def = (((entree *) list)[n++]).name;
                    419:       while (def && strncmp(def,text,len));
                    420:   }
                    421:
                    422:   *nn = n;
                    423:   if (def)
                    424:   {
                    425:     name = strcpy((char*) gpmalloc(strlen(def)+1), def);
                    426:     return name;
                    427:   }
                    428:   return NULL; /* no names matched */
                    429: }
                    430:
                    431: static char *
                    432: old_generator(char *text,int state)
                    433: {
                    434:   static int n,len;
                    435:   static char *res;
                    436:
                    437:   if (!state) { res = "a"; n=0; len=strlen(text); }
                    438:   if (res)
                    439:   {
                    440:     res = generator((void *)oldfonctions,text,&n,len,ENTREE);
                    441:     if (res) return res;
                    442:     n=0;
                    443:   }
                    444:   return generator((void *)functions_oldgp,text,&n,len,ENTREE);
                    445: }
                    446:
                    447: static char *
                    448: default_generator(char *text,int state)
                    449: {
                    450:   static int n,len;
                    451:
                    452:   if (!state) { n=0; len=strlen(text); }
                    453:   return generator(gp_default_list,text,&n,len,DFLT);
                    454: }
                    455:
                    456: static void
                    457: rl_print_aide(char *s, int flag)
                    458: {
                    459:   int p = rl_point, e = rl_end;
                    460:   FILE *save = pari_outfile;
                    461:
                    462:   rl_point = 0; rl_end = 0; pari_outfile = rl_outstream;
                    463:   SAVE_PROMPT();
                    464:   rl_message("",0,0);
                    465:   aide(s, flag);
                    466:   RESTORE_PROMPT();
                    467:   rl_point = p; rl_end = e; pari_outfile = save;
                    468:   rl_clear_message();
                    469: #ifdef RL_REFRESH_LINE_OLDPROTO
                    470:   rl_refresh_line();
                    471: #else
                    472:   rl_refresh_line(0,0);
                    473: #endif
                    474: }
                    475:
                    476: char **
                    477: pari_completion(char *text, int START, int END)
                    478: {
                    479:   int i, first=0, start=START;
                    480:
                    481: /* If the line does not begin by a backslash, then it is:
                    482:  * . an old command ( if preceded by "whatnow(" ).
                    483:  * . a default ( if preceded by "default(" ).
                    484:  * . a member function ( if preceded by "." within 4 letters )
                    485:  * . a file name (in current directory) ( if preceded by "read(" )
                    486:  * . a command
                    487:  */
                    488:   if (start >=1 && rl_line_buffer[start] != '~') start--;
                    489:   while (start && is_keyword_char(rl_line_buffer[start])) start--;
                    490:   if (rl_line_buffer[start] == '~')
                    491:   {
                    492:     for(i=start+1;i<=END;i++)
                    493:       if (rl_line_buffer[i] == '/')
                    494:        return get_matches(-1,text,FILE_COMPLETION);
                    495:     return get_matches(-1,text,USER_COMPLETION);
                    496:   }
                    497:
                    498:   while (rl_line_buffer[first] && isspace((int)rl_line_buffer[first])) first++;
                    499:   switch (rl_line_buffer[first])
                    500:   {
                    501:     case '\\':
                    502:       if (first == start) text = rl_line_buffer+start+2;
                    503:       return get_matches(-1,text,FILE_COMPLETION);
                    504:     case '?':
                    505:       if (rl_line_buffer[first+1] == '?') add_help_keywords = 1;
                    506:       return get_matches(-1,text,command_generator);
                    507:   }
                    508:
                    509:   while (start && rl_line_buffer[start] != '('
                    510:                && rl_line_buffer[start] != ',') start--;
                    511:   if (rl_line_buffer[start] == '(' && start)
                    512:   {
                    513: #define MAX_KEYWORD 200
                    514:     int iend, j,k;
                    515:     entree *ep;
                    516:     char buf[MAX_KEYWORD];
                    517:
                    518:     i = start;
                    519:
                    520:     while (i && isspace((int)rl_line_buffer[i-1])) i--;
                    521:     iend = i;
                    522:     while (i && is_keyword_char(rl_line_buffer[i-1])) i--;
                    523:
                    524:     if (iend - i == 7)
                    525:     {
                    526:       if (strncmp(rl_line_buffer + i,"default",7) == 0)
                    527:        return get_matches(-2,text,default_generator);
                    528:       if (strncmp(rl_line_buffer + i,"whatnow",7) == 0)
                    529:        return get_matches(-1,text,old_generator);
                    530:     }
                    531:     if (iend - i >= 4)
                    532:     {
                    533:       if (strncmp(rl_line_buffer + i,"read",4) == 0)
                    534:        return get_matches(-1,text,FILE_COMPLETION);
                    535:     }
                    536:
                    537:     j = start + 1;
                    538:     while (j <= END && isspace((int)rl_line_buffer[j])) j++;
                    539:     k = END;
                    540:     while (k > j && isspace((int)rl_line_buffer[k])) k--;
                    541:     /* If we are in empty parens, insert arguments for the function: */
                    542:     if (do_args_complete && k == j
                    543:          && (rl_line_buffer[j] == ')' || !rl_line_buffer[j])
                    544:         && (iend - i < MAX_KEYWORD)
                    545:         && ( strncpy(buf, rl_line_buffer + i, iend - i),
                    546:              buf[iend - i] = 0, 1)
                    547:         && (ep = is_entry(buf)) && ep->help)
                    548:      {
                    549: #if 0
                    550:       char *s = ep->help;
                    551:
                    552:       while (is_keyword_char(*s)) s++;
                    553:       if (*s++ == '(')
                    554:       { /* Function, print arguments! */
                    555:         char *endh = s;
                    556:         while (*endh && *endh != ')' && *endh != '(') endh++;
                    557:         if (*endh == ')')
                    558:         { /* Well-formed help.  */
                    559:           char *str = strncpy((char*) gpmalloc(endh-s + 1), s, endh-s);
                    560:           char **ret = (char**)gpmalloc(sizeof(char*)*2);
                    561:           str[endh-s] = 0;
                    562:           ret[0] = str; ret[1] = NULL;
                    563:           if (under_emacs) ret = matches_for_emacs("",ret);
                    564:           return ret;
                    565:         }
                    566:       }
                    567: #endif
                    568:       rl_print_aide(buf,h_RL);
                    569:       rl_attempted_completion_over = 1;
                    570:       return NULL;
                    571:     }
                    572:   }
                    573:   for(i=END-1;i>=start;i--)
                    574:     if (!is_keyword_char(rl_line_buffer[i]))
                    575:     {
                    576:       if (rl_line_buffer[i] == '.')
                    577:         return get_matches(-1,text,member_generator);
                    578:       break;
                    579:     }
                    580:   add_help_keywords = 0;
                    581:   return get_matches(END,text,command_generator);
                    582: }
                    583:
                    584: /* long help if count < 0 */
                    585: static int
                    586: rl_short_help(int count, int key)
                    587: {
                    588:   int flag = (count < 0 || rl_last_func == rl_short_help)? h_RL|h_LONG: h_RL;
                    589:   int off = rl_point;
                    590:
                    591:   /* func() with cursor on ')' following completion */
                    592:   if (off && rl_line_buffer[off-1] == '('
                    593:           && !is_keyword_char(rl_line_buffer[off])) off--;
                    594:
                    595:   while (off && is_keyword_char(rl_line_buffer[off-1])) off--;
                    596:
                    597:   /* Check for \c type situation.  Could check for leading whitespace too... */
                    598:   if (off == 1 && rl_line_buffer[off-1] == '\\') off--;
                    599:   if (off >= 8) {              /* Check for default(whatever) */
                    600:     int t = off - 1;
                    601:
                    602:     while (t >= 7 && isspace((int)rl_line_buffer[t])) t--;
                    603:     if (rl_line_buffer[t--] == '(') {
                    604:       while (t >= 6 && isspace((int)rl_line_buffer[t])) t--;
                    605:       t -= 6;
                    606:       if (t >= 0
                    607:          && strncmp(rl_line_buffer + t, "default", 7) == 0
                    608:          && (t == 0 || !is_keyword_char(rl_line_buffer[t-1])))
                    609:        off = t;
                    610:     }
                    611:   }
                    612:   rl_print_aide(rl_line_buffer + off, flag);
                    613:   return 0;
                    614: }
                    615:
                    616: static int
                    617: rl_long_help(int count, int key)
                    618: {
                    619:   (void)count;
                    620:   return rl_short_help(-1,key);
                    621: }
                    622:
                    623: void
                    624: init_readline()
                    625: {
                    626:   /* Allow conditional parsing of the ~/.inputrc file. */
                    627:   rl_readline_name = "Pari-GP";
                    628:
                    629:   /* added ~, ? and , */
                    630:   rl_basic_word_break_characters = " \t\n\"\\'`@$><=;|&{(?,~";
                    631:   rl_special_prefixes = "~";
                    632:
                    633:   /* custom completer */
                    634: #ifndef HAS_RL_COMPLETION_FUNC_T
                    635: # ifndef CPPFunction_defined
                    636: #   define CPPFunction Function
                    637: # endif
                    638: # define rl_completion_func_t CPPFunction
                    639: #endif
                    640:   rl_attempted_completion_function = (rl_completion_func_t*) pari_completion;
                    641:
                    642:   /* we always want the whole list of completions under emacs */
                    643:   if (under_emacs) rl_completion_query_items = 0x8fff;
                    644:
                    645: #define Bind(a,b,c) (((void(*)(int,Function*,Keymap)) rl_bind_key_in_map)\
                    646:   ((a), (Function*)(b), (c)))
                    647: #define Defun(a,b,c) (((void(*)(const char*,Function*,int)) rl_add_defun)\
                    648:   ((a), (Function*)(b), (c)))
                    649:
                    650:   Defun("short-help", rl_short_help, -1);
                    651:   Defun("long-help", rl_long_help, -1);
                    652:   Defun("pari-complete", pari_rl_complete, '\t');
                    653:   Defun("pari-matched-insert", pari_rl_default_matched_insert, -1);
                    654:   Defun("pari-forward-sexp", pari_rl_forward_sexp, -1);
                    655:   Defun("pari-backward-sexp", pari_rl_backward_sexp, -1);
                    656:
                    657:   Bind('h', rl_short_help, emacs_meta_keymap);
                    658:   Bind('H', rl_long_help,  emacs_meta_keymap);
                    659:   Bind('h', rl_short_help, vi_movement_keymap);
                    660:   Bind('H', rl_long_help,  vi_movement_keymap);
                    661: #  ifdef HAS_RL_GENERIC_BIND
                    662: #define KSbind(s,f,k) rl_generic_bind(ISFUNC, (s), (char*)(f), (k))
                    663:
                    664:   KSbind("OP",   rl_short_help,  emacs_meta_keymap); /* f1, vt100 */
                    665:   KSbind("[11~", rl_short_help,  emacs_meta_keymap); /* f1, xterm */
                    666:   KSbind("OP",   rl_short_help,  vi_movement_keymap); /* f1, vt100 */
                    667:   KSbind("[11~", rl_short_help,  vi_movement_keymap); /* f1, xterm */
                    668: #  endif
                    669:   Bind('(', pari_rl_matched_insert, emacs_standard_keymap);
                    670:   Bind('[', pari_rl_matched_insert, emacs_standard_keymap);
                    671:   Bind(6, pari_rl_forward_sexp,  emacs_meta_keymap); /* M-C-f */
                    672:   Bind(2, pari_rl_backward_sexp, emacs_meta_keymap); /* M-C-b */
                    673:
                    674: #ifdef EMACS_DOS_KEYMAP
                    675:   Bind(';', rl_short_help, emacs_dos_keymap); /* F1 */
                    676:   Bind('T', rl_long_help,  emacs_dos_keymap); /* Shift-F1 */
                    677:   Bind(155, pari_rl_backward_sexp, emacs_dos_keymap); /* Alt-Left */
                    678:   Bind(157, pari_rl_forward_sexp,  emacs_dos_keymap); /* Alt-Right*/
                    679: #endif
                    680: }
                    681: #endif

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>