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

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

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

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