diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2015-09-27 11:54:00 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2015-09-27 11:54:00 -0700 |
commit | 609b0dd2146330e61d8ed024fca660158836d8c0 (patch) | |
tree | 576e0d3556a77a8608ad99cdc111568fb4a2cf3d | |
parent | ba911c661c4a3607c80dcd0c30d4313e558a9243 (diff) | |
download | txr-609b0dd2146330e61d8ed024fca660158836d8c0.tar.gz txr-609b0dd2146330e61d8ed024fca660158836d8c0.tar.bz2 txr-609b0dd2146330e61d8ed024fca660158836d8c0.zip |
linenoise: paren matching jump finds closes paren.
* linenoise/linenoise.c (find_nearest_paren): New static
function.
(edit_move_matching_paren): Use find_matching_paren to
usefully handle situations when the cursor is not on
a parenthesis, bracket or brace.
* txr.1: Documented.
-rw-r--r-- | linenoise/linenoise.c | 65 | ||||
-rw-r--r-- | txr.1 | 17 |
2 files changed, 72 insertions, 10 deletions
diff --git a/linenoise/linenoise.c b/linenoise/linenoise.c index e50eed2e..57797178 100644 --- a/linenoise/linenoise.c +++ b/linenoise/linenoise.c @@ -1105,6 +1105,48 @@ static size_t scan_fwd(const char *s, size_t i) } } +static size_t find_nearest_paren(const char *s, size_t i) +{ + static const char *ope = "([{"; + static const char *clo = ")]}"; + size_t pre = (size_t) -1, nxt = (size_t) -1; + size_t j; + + for (j = i; j != (size_t) -1; j--) { + if (s[j] && (strchr(ope, s[j]) || strchr(clo, s[j]))) { + pre = j; + break; + } + } + + for (j = i; s[j] != 0; j++) { + if (strchr(ope, s[j]) || strchr(clo, s[j])) { + nxt = j; + break; + } + } + + if (pre == (size_t) -1) + return nxt; + + if (nxt == (size_t) -1) + return pre; + + if (i - pre > nxt - i) + return nxt; + + if (i - pre < nxt - i) + return pre; + + if (strchr(ope, s[pre]) && strchr(ope, s[nxt])) + return nxt; + + if (strchr(clo, s[pre]) && strchr(clo, s[nxt])) + return pre; + + return nxt; +} + static void usec_delay(lino_t *l, long usec) { #if HAVE_POLL @@ -1316,15 +1358,22 @@ static void edit_move_eol(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); + size_t p = find_nearest_paren(l->data, l->dpos); - if (fw != (size_t) -1) { - l->dpos = fw; - l->need_refresh = 1; - } else if (re != (size_t) -1) { - l->dpos = re; - l->need_refresh = 1; + if (p != (size_t) -1) { + size_t fw = scan_fwd(l->data, p); + size_t re = scan_rev(l->data, p); + + if (fw != (size_t) -1) { + l->dpos = fw; + l->need_refresh = 1; + } else if (re != (size_t) -1) { + l->dpos = re; + l->need_refresh = 1; + } else { + l->dpos = p; + l->need_refresh = 1; + } } } @@ -33607,9 +33607,22 @@ edit buffer. .NP* Jump to Matching Parenthesis If the cursor is on an opening or closing parenthesis, brace or bracket, -the Ctrl-] command will jump to the matching character. The logic for +the Ctrl-] command tries to jump to the matching character. The logic for finding the matching character is identical to that of the Parenthesis Matching -feature. +feature. If no matching character is found, then no movement takes place. + +If the cursor is not on an opening or closing parenthesis, brace or bracket, +then the closest such character is found. The cursor is moved to that character +and then an attempt is made to jump to the matching one from that new +position. + +If the cursor is equidistant to two such characters, then one of them +is chosen as follows. If the two characters are oriented in the same way (both +are opening and closing), then that one is chosen whose convex side faces the +cursor position. Thus, effectively, an inner enclosure is favored over an +outer one. Otherwise, if the two characters have opposite orientation (one is +opening and the other closing), then the one which is to the right of the +cursor position is chosen. Note: the Ctrl-] character can be produced on some terminals using Ctrl-5 (using the keyboard home row 5, not the numeric keypad 5). This the same |