summaryrefslogtreecommitdiffstats
path: root/linenoise
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 /linenoise
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.
Diffstat (limited to 'linenoise')
-rw-r--r--linenoise/linenoise.c62
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;