diff options
Diffstat (limited to 'linenoise/linenoise.c')
-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; |