[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     ! 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>