| 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