Ilya Zakharevich on Sat, 25 Apr 1998 06:21:12 +0200 |
[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]
Yet another readline update |
a) I'm using _rl_save/restore_prompt() when I need to change prompt; b) Giving 0-arg to ([{ makes them non-electric from this point on; c) Giving negative-arg to ([{ makes them electric from this point on; d) Giving 0-arg to TAB makes it to not insert args from this point on; e) Giving negative-arg to TAB makes it insert args from this point on; f) Forward/backward-sexp implemented (put on Alt-Left/Right and C-M-F/B); Difference of Forward/backward-sexp from the Emacs ones: if you are after `(' and go sexp-back, you go one char back (and ding()), similar with forward (Emacs just ding()). When you change the state of electricity, you get a message what happened. This is an incremental diff -pu with what I sent before (2.0.5). Enjoy, Ilya --- ./src/gp/gp_rl.c.pre-arg Sun Apr 19 14:57:08 1998 +++ ./src/gp/gp_rl.c Sat Apr 25 00:01:56 1998 @@ -34,6 +34,7 @@ typedef char* (*GF)(char*,int); /* gener static int pari_rl_back; extern Function *rl_last_func; +static int do_args_complete = 1; /* Wrapper around rl_complete to allow insertion of () with a point in between. */ @@ -43,6 +44,19 @@ pari_rl_complete(int count, int key) int ret; pari_rl_back = 0; + if (count <= 0) { /* Change the state */ + int c; + + do_args_complete = (count != 0); + _rl_save_prompt(); + rl_message( "complete args: %s. %s" , + ( do_args_complete ? "on" : "off"), rl_prompt); + c = rl_read_key(); + _rl_restore_prompt(); + rl_clear_message(); + rl_stuff_char (c); + return 1; + } rl_begin_undo_group(); if (rl_last_func == pari_rl_complete) rl_last_func = rl_complete; /* Make repeated TABs different */ @@ -55,16 +69,30 @@ pari_rl_complete(int count, int key) static const char paropen[] = "([{"; static const char parclose[] = ")]}"; +static int do_matched_insert = 1; /* To allow insertion of () with a point in between. */ static int pari_rl_matched_insert(int count, int key) { int i = 0, ret; - + + if (count <= 0) { /* Change the state */ + int c; + + do_matched_insert = (count != 0); + _rl_save_prompt(); + rl_message( "electric parens: %s. %s" , + ( do_matched_insert ? "on" : "off"), rl_prompt); + c = rl_read_key(); + _rl_restore_prompt(); + rl_clear_message(); + rl_stuff_char (c); + return 1; + } while (paropen[i] && paropen[i] != key) i++; - if (!paropen[i]) + if (!paropen[i] || !do_matched_insert) return rl_insert(count,key); rl_begin_undo_group(); rl_insert(count,key); @@ -74,6 +102,85 @@ pari_rl_matched_insert(int count, int ke return ret; } +static int +pari_rl_forward_sexp(int count, int key) +{ + int i = 0, deep = 0, dir = (count >= 0 ? 1 : -1), move_point, lfail; + + if (count < 0) + count = -count; + if (dir < 0) { + if (rl_point) + rl_point--; + else + goto fail; + } + while (count || deep) { + move_point = 1; /* Need to move point if moving left. */ + lfail = 0; /* Do not need to fail left movement yet. */ + while ( !is_keyword_char(rl_line_buffer[rl_point]) + && !strchr("\"([{}])",rl_line_buffer[rl_point]) + && !( (dir == 1) + ? (rl_point >= rl_end) + : (rl_point <= 0 && (lfail = 1)))) + rl_point += dir; + if (lfail) + goto fail; + if (!rl_line_buffer[rl_point]) { + goto fail; + } else if (is_keyword_char(rl_line_buffer[rl_point])) { + while ( is_keyword_char(rl_line_buffer[rl_point]) + && (!((dir == 1) ? (rl_point >= rl_end) : (rl_point <= 0)) + || (move_point = 0))) + rl_point += dir; + if (!deep) + count--; + } else if (strchr(paropen,rl_line_buffer[rl_point])) { + if (deep == 0 && dir == -1) /* We are already out of pars. */ + goto fail; + rl_point += dir; + deep += 1; + if (!deep) + count--; + } else if (strchr(parclose,rl_line_buffer[rl_point])) { + if (deep == 0 && dir == 1) { + rl_point++; /* Get out of pars. */ + goto fail; + } + rl_point += dir; + deep -= 1; + if (!deep) + count--; + } else if (rl_line_buffer[rl_point] == '\"') { + int bad = 1; + + rl_point += dir; + while ( ((rl_line_buffer[rl_point] != '\"') || (bad = 0)) + && (!((dir == 1) ? (rl_point >= rl_end) : (rl_point <= 0)) + || (move_point = 0)) ) + rl_point += dir; + if (bad) + goto fail; + rl_point += dir; /* Skip the other delimiter */ + if (!deep) + count--; + } else { /* Hit boundary. */ + fail: + ding(); + return 1; + } + } + if (dir != 1 && move_point) + rl_point++; + return 1; +} + +static int +pari_rl_backward_sexp(int count, int key) +{ + return pari_rl_forward_sexp(-count, key); +} + /* Attempt to complete on the contents of TEXT. START and END show the * region of TEXT that contains the word to complete. We can use the * entire line in case we want to do some simple parsing. Return the @@ -341,6 +448,7 @@ pari_completion (char *text, int start, while (j && isspace(rl_line_buffer[j])) j++; /* If we are in empty parens, insert arguments for the function: */ if ( (rl_line_buffer[j] == ')' || !rl_line_buffer[j] ) + && do_args_complete && (iend - i < MAX_KEYWORD) && ( strncpy(buf, rl_line_buffer + i, iend - i), buf[iend - i] = 0, 1) @@ -386,14 +494,19 @@ rl_short_help(int count, int key) while (off && is_keyword_char(rl_line_buffer[off-1])) off--; rl_point = 0; rl_end = 0; outfile = rl_outstream; if (count < 0) flag |= h_LONG; /* long help */ + _rl_save_prompt(); ((void(*)(const char*))rl_message)(""); + +#if 0 /* _rl_save/restore_prompt does it. */ /* Erase prompt. */ pariputs("\r"); while (l--) pariputs(" "); pariputs("\r"); +#endif aide(rl_line_buffer + off, flag); + _rl_restore_prompt(); rl_point = p; rl_end = e; outfile = save; rl_clear_message(); rl_refresh_line(); return 0; @@ -433,9 +546,13 @@ init_readline(int i) Defun("long-help", (Function*) rl_long_help, -1); Defun("pari-complete", (Function*) pari_rl_complete, '\t'); Defun("pari-matched-insert", (Function*) pari_rl_matched_insert, -1); + Defun("pari-forward-sexp", (Function*) pari_rl_forward_sexp, -1); + Defun("pari-backward-sexp", (Function*) pari_rl_backward_sexp, -1); Bind('h', (Function*) rl_short_help, emacs_meta_keymap); Bind('H', (Function*) rl_long_help, emacs_meta_keymap); + Bind(6, (Function*) pari_rl_forward_sexp, emacs_meta_keymap); /* M-C-f */ + Bind(2, (Function*) pari_rl_backward_sexp, emacs_meta_keymap); /* M-C-b */ Bind('h', (Function*) rl_short_help, vi_movement_keymap); Bind('H', (Function*) rl_long_help, vi_movement_keymap); Bind('(', (Function*) pari_rl_matched_insert, emacs_standard_keymap); @@ -445,6 +562,8 @@ init_readline(int i) # ifdef EMACS_DOS_KEYMAP Bind(';', (Function*) rl_short_help, emacs_dos_keymap); /* F1 */ Bind('T', (Function*) rl_long_help, emacs_dos_keymap); /* Shift-F1 */ + Bind(155, (Function*) pari_rl_backward_sexp, emacs_dos_keymap); /* Alt-Left */ + Bind(157, (Function*) pari_rl_forward_sexp, emacs_dos_keymap); /* Alt-Right */ # endif } #endif