about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Src/Zle/iwidgets.list1
-rw-r--r--Src/Zle/zle_move.c74
2 files changed, 75 insertions, 0 deletions
diff --git a/Src/Zle/iwidgets.list b/Src/Zle/iwidgets.list
index 2b2654c5d..183d75c17 100644
--- a/Src/Zle/iwidgets.list
+++ b/Src/Zle/iwidgets.list
@@ -83,6 +83,7 @@
 "list-choices", listchoices, ZLE_MENUCMP | ZLE_KEEPSUFFIX | ZLE_LASTCOL | ZLE_ISCOMP
 "list-expand", listexpand, ZLE_MENUCMP | ZLE_KEEPSUFFIX | ZLE_LASTCOL
 "magic-space", magicspace, ZLE_KEEPSUFFIX | ZLE_MENUCMP
+"match-bracket", matchbracket, ZLE_KEEPSUFFIX | ZLE_MENUCMP
 "menu-complete", menucomplete, ZLE_MENUCMP | ZLE_KEEPSUFFIX | ZLE_ISCOMP
 "menu-expand-or-complete", menuexpandorcomplete, ZLE_MENUCMP | ZLE_KEEPSUFFIX | ZLE_ISCOMP
 "neg-argument", negargument, ZLE_MENUCMP | ZLE_KEEPSUFFIX | ZLE_LASTCOL | ZLE_NOTCOMMAND
diff --git a/Src/Zle/zle_move.c b/Src/Zle/zle_move.c
index 155fda80d..1a2ab2e00 100644
--- a/Src/Zle/zle_move.c
+++ b/Src/Zle/zle_move.c
@@ -591,6 +591,80 @@ vigotocolumn(UNUSED(char **args))
 
 /**/
 int
+matchbracket(char **args)
+{
+    int ocs = zlecs, dir, ct;
+    unsigned char oth, me;
+
+    if (*args) {
+	char *end = NULL;
+        zlecs = zstrtol(*args, &end, 10);
+	if (end && end != *args && *end == '\0')
+	    args++;
+	else
+	    zlecs = ocs;
+    }
+
+    if (zlecs == zlell || zleline[zlecs] == '\n') {
+	zlecs = ocs;
+	return 1;
+    }
+    switch (me = zleline[zlecs]) {
+    case '{':
+	dir = 1;
+	oth = '}';
+	break;
+    case /*{*/ '}':
+	dir = -1;
+	oth = '{'; /*}*/
+	break;
+    case '(':
+	dir = 1;
+	oth = ')';
+	break;
+    case ')':
+	dir = -1;
+	oth = '(';
+	break;
+    case '[':
+	dir = 1;
+	oth = ']';
+	break;
+    case ']':
+	dir = -1;
+	oth = '[';
+	break;
+    default:
+	zlecs = ocs;
+	return 1;
+    }
+    ct = 1;
+    while (zlecs >= 0 && zlecs < zlell && ct) {
+	if (dir < 0)
+	    DECCS();
+	else
+	    INCCS();
+	if (zleline[zlecs] == oth)
+	    ct--;
+	else if (zleline[zlecs] == me)
+	    ct++;
+    }
+    if (zlecs < 0 || zlecs >= zlell) {
+	zlecs = ocs;
+	return 1;
+    }
+
+    if (*args) {
+	char digs[100];
+	sprintf(digs, "%d", zlecs);
+	zlecs = ocs;
+	setsparam(*args, ztrdup(digs));
+    }
+    return 0;
+}
+
+/**/
+int
 vimatchbracket(UNUSED(char **args))
 {
     int ocs = zlecs, dir, ct;