summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2015-09-27 11:54:00 -0700
committerKaz Kylheku <kaz@kylheku.com>2015-09-27 11:54:00 -0700
commit609b0dd2146330e61d8ed024fca660158836d8c0 (patch)
tree576e0d3556a77a8608ad99cdc111568fb4a2cf3d
parentba911c661c4a3607c80dcd0c30d4313e558a9243 (diff)
downloadtxr-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.c65
-rw-r--r--txr.117
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;
+ }
}
}
diff --git a/txr.1 b/txr.1
index 6eb155c4..696a1b10 100644
--- a/txr.1
+++ b/txr.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