Ilya Zakharevich on Thu, 17 Oct 2002 12:08:40 -0700 |
[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]
[PATCH CVS] Readline improvements |
[Some time ago F1/M-h did not work before parentheses of function() Apparently, it was recently fixed. However, in between somebody noticed this lack of functionallity, and switched off an important feature of TAB - to make TAB work as F1 in this situation. Thus currently F1 and TAB do the same between parentheses (as above).] This patch: a) Restores the historic behaviour of TAB (insert the template for function arguments), if one wants help, press F1 or M-h; b) make default(readline,4) and default(readline,2) etc. switch the electric TAB (as above) and electric-parens settings; c) Better formatting of the message when one switches the two setting above (by giving non-positive arguments to TAB or "("); d) Colors now work with default(readline,0) too; e) Beginning of support for Mouse-Editing in xterm (see http://groups.google.com/groups?selm=ani7hg%24bmf%241%40agate.berkeley.edu&output=gplain). Currently we support the 2004 setting by interpreting F200/F201 as signals to switch off/back electric parens. In particular, one can have default(readline,2) *and* cut-and-paste in new xterm without bad interactions (if one enables 2004 before entering gp). This probably is not 100%-proof in vi-mode. However, I cannot fix it, since I'm vi-ignorant. Enjoy, Ilya --- ./src/gp/gp_rl.c-pre3 Tue Oct 15 20:26:50 2002 +++ ./src/gp/gp_rl.c Thu Oct 17 03:08:46 2002 @@ -61,8 +61,6 @@ static entree *current_ep = NULL; static int pari_rl_back; extern RLCI rl_last_func; -static int do_args_complete = 1; -static int do_matched_insert = 0; static int did_init_matched = 0; #ifdef HAS_RL_SAVE_PROMPT @@ -88,22 +86,32 @@ static int did_init_matched = 0; # define USER_COMPLETION ((GF)username_completion_function) #endif -#define ELECTRIC_PAREN 1 -#define ARGS_COMPLETE 2 static int -change_state(char *msg, int *opt, int count) +change_state(char *msg, ulong flag, int count) { - int c; + int c = (readline_state & flag) != 0; + ulong o_readline_state = readline_state; switch(count) { default: c = 0; break; /* off */ case -1: c = 1; break; /* on */ - case -2: c = 1 - *opt; /* toggle */ + case -2: c = 1 - c; /* toggle */ + } + if (c) + readline_state |= flag; + else { + readline_state &= ~flag; + if (!readline_state && o_readline_state) + readline_state = 1; } - *opt = c; SAVE_PROMPT(); - rl_message("%s: %s.", msg, c? "on": "off"); +#if 0 /* Does not work well... */ + rl_message("%s[%s: %s] %s", term_get_color(c_PROMPT), + msg, c? "on": "off", term_get_color(c_INPUT)); +#else + rl_message("[%s: %s] ", msg, c? "on": "off"); +#endif c = rl_read_key(); RESTORE_PROMPT(); rl_clear_message(); @@ -118,7 +126,7 @@ pari_rl_complete(int count, int key) pari_rl_back = 0; if (count <= 0) - return change_state("complete args", &do_args_complete, count); + return change_state("complete args", DO_ARGS_COMPLETE, count); rl_begin_undo_group(); if (rl_last_func == pari_rl_complete) @@ -129,6 +137,28 @@ pari_rl_complete(int count, int key) rl_end_undo_group(); return ret; } +static int did_matched_insert; + +static int +pari_rl_matched_insert_suspend(int count, int key) +{ + ulong o_readline_state = readline_state; + + did_matched_insert = (readline_state & DO_MATCHED_INSERT); + readline_state &= ~DO_MATCHED_INSERT; + if (!readline_state && o_readline_state) + readline_state = 1; + return 1; +} + +static int +pari_rl_matched_insert_restore(int count, int key) +{ + if (did_matched_insert) + readline_state |= DO_MATCHED_INSERT; + return 1; +} + static const char paropen[] = "([{"; static const char parclose[] = ")]}"; @@ -139,9 +169,9 @@ pari_rl_matched_insert(int count, int ke int i = 0, ret; if (count <= 0) - return change_state("electric parens", &do_matched_insert, count); + return change_state("electric parens", DO_MATCHED_INSERT, count); while (paropen[i] && paropen[i] != key) i++; - if (!paropen[i] || !do_matched_insert || GP_DATA->flags & EMACS) + if (!paropen[i] || !(readline_state & DO_MATCHED_INSERT) || GP_DATA->flags & EMACS) return ((RLCI)rl_insert)(count,key); rl_begin_undo_group(); ((RLCI)rl_insert)(count,key); @@ -155,7 +185,7 @@ pari_rl_default_matched_insert(int count { if (!did_init_matched) { did_init_matched = 1; - do_matched_insert = 1; + readline_state |= DO_MATCHED_INSERT; } return pari_rl_matched_insert(count, key); } @@ -537,17 +567,37 @@ pari_completion(char *text, int START, i while (j <= END && isspace((int)rl_line_buffer[j])) j++; k = END; while (k > j && isspace((int)rl_line_buffer[k])) k--; - /* If we are in empty parens, output function help */ - if (do_args_complete && k == j + /* If we are in empty parens, insert the default arguments */ + if ((readline_state & DO_ARGS_COMPLETE) && k == j && (rl_line_buffer[j] == ')' || !rl_line_buffer[j]) && (iend - i < MAX_KEYWORD) && ( strncpy(buf, rl_line_buffer + i, iend - i), buf[iend - i] = 0, 1) && (ep = is_entry(buf)) && ep->help) { +#if 1 + char *s = ep->help; + + while (is_keyword_char(*s)) s++; + if (*s++ == '(') + { /* Function, print arguments! */ + char *endh = s; + while (*endh && *endh != ')' && *endh != '(') endh++; + if (*endh == ')') + { /* Well-formed help. */ + char *str = strncpy((char*) gpmalloc(endh-s + 1), s, endh-s); + char **ret = (char**)gpmalloc(sizeof(char*)*2); + str[endh-s] = 0; + ret[0] = str; ret[1] = NULL; + if (GP_DATA->flags & EMACS) ret = matches_for_emacs("",ret); + return ret; + } + } +#else /* Why duplicate F1 (and emit a bell)?! */ rl_print_aide(buf,h_RL); rl_attempted_completion_over = 1; return NULL; +#endif } } for(i=END-1;i>=start;i--) @@ -631,6 +681,8 @@ init_readline(void) Defun("long-help", rl_long_help, -1); Defun("pari-complete", pari_rl_complete, '\t'); Defun("pari-matched-insert", pari_rl_default_matched_insert, -1); + Defun("pari-matched-insert-suspend", pari_rl_matched_insert_suspend, -1); + Defun("pari-matched-insert-restore", pari_rl_matched_insert_restore, -1); Defun("pari-forward-sexp", pari_rl_forward_sexp, -1); Defun("pari-backward-sexp", pari_rl_backward_sexp, -1); @@ -645,6 +697,13 @@ init_readline(void) KSbind("[11~", rl_short_help, emacs_meta_keymap); /* f1, xterm */ KSbind("OP", rl_short_help, vi_movement_keymap); /* f1, vt100 */ KSbind("[11~", rl_short_help, vi_movement_keymap); /* f1, xterm */ + /* XTerm may signal start/end of paste by eming F200/F201 */ + /* XXXX For vi mode something more intelligent is needed - to switch to the + insert mode - and back when restoring. */ + KSbind("[200~", pari_rl_matched_insert_suspend, emacs_meta_keymap); /* pre-paste xterm */ + KSbind("[200~", pari_rl_matched_insert_suspend, vi_movement_keymap); /* pre-paste xterm */ + KSbind("[201~", pari_rl_matched_insert_restore, emacs_meta_keymap); /* post-paste xterm */ + KSbind("[201~", pari_rl_matched_insert_restore, vi_movement_keymap); /* post-paste xterm */ # endif Bind('(', pari_rl_matched_insert, emacs_standard_keymap); Bind('[', pari_rl_matched_insert, emacs_standard_keymap); --- ./src/gp/gp.c-pre3 Tue Oct 15 20:26:00 2002 +++ ./src/gp/gp.c Thu Oct 17 02:51:42 2002 @@ -637,16 +637,31 @@ static GEN sd_debug(char *v, int flag) { return sd_ulong(v,flag,"debug",&DEBUGLEVEL, 0,20,NULL); } +#ifdef READLINE +ulong readline_state = DO_ARGS_COMPLETE; +#endif + static GEN sd_rl(char *v, int flag) { #ifdef READLINE + static const char * const msg[] = {NULL, + "(bits 0x2/0x4 control matched-insert/arg-complete)"}; + ulong o_readline_state; + GEN res; + if (!readline_init && *v && *v != '0') { init_readline(); readline_init = 1; } + o_readline_state = readline_state; + res = sd_ulong(v,flag,"readline", &readline_state, 0, 3, (char**)msg); + if (o_readline_state != readline_state) + sd_gptoggle(readline_state ? "1" : "0", d_SILENT, "readline", USE_READLINE); + return res; +#else + sd_gptoggle(v, flag, "readline", USE_READLINE); #endif - return sd_gptoggle(v,flag,"readline", USE_READLINE); } static GEN @@ -2209,10 +2224,13 @@ brace_color(char *s, int c, int force) { if (disable_color || (gp_colors[c] == c_NONE && !force)) return; #ifdef RL_PROMPT_START_IGNORE - *s++ = RL_PROMPT_START_IGNORE; + if (GP_DATA->flags & USE_READLINE) + *s++ = RL_PROMPT_START_IGNORE; #endif strcpy(s, term_get_color(c)); #ifdef RL_PROMPT_START_IGNORE + if (!(GP_DATA->flags & USE_READLINE)) + return; s+=strlen(s); *s++ = RL_PROMPT_END_IGNORE; *s = 0; #endif --- ./src/gp/gp.h-pre3 Tue Jun 11 17:24:10 2002 +++ ./src/gp/gp.h Thu Oct 17 02:38:18 2002 @@ -30,6 +30,10 @@ extern ulong init_opts; extern char *current_logfile; extern jmp_buf environnement; +extern ulong readline_state; +#define DO_MATCHED_INSERT 2 +#define DO_ARGS_COMPLETE 4 + /* for do_time() */ enum { ti_NOPRINT, ti_REGULAR, ti_LAST, ti_INTERRUPT };