diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2015-09-22 05:59:05 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2015-09-22 05:59:05 -0700 |
commit | caca753c5fef9c52a3fda44f31ca86be0d36509e (patch) | |
tree | 69b2f887911c941e8944c17693a23a5ae2b82aba /linenoise | |
parent | 4331f6a3c3e83160044ad75bf6d8ffcc05edab34 (diff) | |
download | txr-caca753c5fef9c52a3fda44f31ca86be0d36509e.tar.gz txr-caca753c5fef9c52a3fda44f31ca86be0d36509e.tar.bz2 txr-caca753c5fef9c52a3fda44f31ca86be0d36509e.zip |
linenoise: jump to matching parenthesis
* linenoise/linenoise.c (scan_match_fwd, scan_fwd,
edit_move_matching_paren): New functions.
(edit): New Ctrl-] command implemented using
edit_move_matching_paren.
* txr.1: Documented.
Diffstat (limited to 'linenoise')
-rw-r--r-- | linenoise/linenoise.c | 62 |
1 files changed, 62 insertions, 0 deletions
diff --git a/linenoise/linenoise.c b/linenoise/linenoise.c index fedb7805..782fdfde 100644 --- a/linenoise/linenoise.c +++ b/linenoise/linenoise.c @@ -1046,6 +1046,51 @@ static size_t scan_rev(const char *s, size_t i) } } +static size_t scan_match_fwd(const char *s, size_t i, int mch) +{ + while (s[++i]) { + int ch = s[i]; + + if (ch == mch) + return i; + + switch (ch) { + case '(': + if ((i = scan_match_fwd(s, i, ')')) == -1) + return -1; + break; + case '[': + if ((i = scan_match_fwd(s, i, ']')) == -1) + return -1; + break; + case '{': + if ((i = scan_match_fwd(s, i, '}')) == -1) + return -1; + break; + case ')': case ']': case '}': + return -1; + default: + break; + } + } + + return -1; +} + +static size_t scan_fwd(const char *s, size_t i) +{ + switch (s[i]) { + case '(': + return scan_match_fwd(s, i, ')'); + case '[': + return scan_match_fwd(s, i, ']'); + case '{': + return scan_match_fwd(s, i, '}'); + default: + return -1; + } +} + static void usec_delay(lino_t *l, long usec) { #if HAVE_POLL @@ -1220,6 +1265,20 @@ static void edit_move_end(lino_t *l) { } } +static void edit_move_matching_paren(lino_t *l) +{ + size_t fw = scan_fwd(l->data, l->dpos); + size_t re = scan_rev(l->data, l->dpos); + + if (fw != -1) { + l->dpos = fw; + l->need_refresh = 1; + } else if (re != -1) { + l->dpos = re; + l->need_refresh = 1; + } +} + /* Substitute the currently edited line with the next or previous history * entry as specified by 'dir'. */ #define LINENOISE_HISTORY_NEXT 0 @@ -1828,6 +1887,9 @@ static int edit(lino_t *l, const char *prompt) case CTL('E'): edit_move_end(l); break; + case CTL(']'): + edit_move_matching_paren(l); + break; case CTL('L'): lino_clear_screen(l); l->need_refresh = 1; |