summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2015-09-22 05:59:05 -0700
committerKaz Kylheku <kaz@kylheku.com>2015-09-22 05:59:05 -0700
commitcaca753c5fef9c52a3fda44f31ca86be0d36509e (patch)
tree69b2f887911c941e8944c17693a23a5ae2b82aba
parent4331f6a3c3e83160044ad75bf6d8ffcc05edab34 (diff)
downloadtxr-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.
-rw-r--r--linenoise/linenoise.c62
-rw-r--r--txr.112
2 files changed, 74 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;
diff --git a/txr.1 b/txr.1
index 53d7e32a..76fda8f6 100644
--- a/txr.1
+++ b/txr.1
@@ -33588,6 +33588,18 @@ such that the last character of the line is to the left of the cursor
position. On terminals which have the Home and End keys, these may also
be used instead of Ctrl-A and Ctrl-E.
+.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
+finding the matching character is identical to that of the Parenthesis Matching
+feature.
+
+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
+key which produces the % character when Shift is used. The % character is
+used in the Vi editor for parenthesis matching.
+
.NP* Character Swap
The Ctrl-T (twiddle) command exchanges the character under the cursor with the