about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog6
-rw-r--r--Doc/Zsh/zle.yo13
-rw-r--r--Src/Zle/zle_keymap.c42
3 files changed, 57 insertions, 4 deletions
diff --git a/ChangeLog b/ChangeLog
index 53c8559b7..403340de7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2001-04-19  Peter Stephenson  <pws@pwstephenson.fsnet.co.uk>
+
+	* 14046: Doc/Zle/zle.yo, Src/Zle/zle_keymap.c: bindkey -rp removes
+	bindings with given prefix; minor bugfix for length of prefix with
+	bindkey -p.
+
 2001-04-19  Clint Adams  <schizo@debian.org>
 
 	* unposted: configure.in: make sure all the libraries are
diff --git a/Doc/Zsh/zle.yo b/Doc/Zsh/zle.yo
index 87e5182b3..46d604a0c 100644
--- a/Doc/Zsh/zle.yo
+++ b/Doc/Zsh/zle.yo
@@ -175,7 +175,20 @@ Only keys that are unbound or bound to tt(self-insert) are affected.
 item(tt(-r) var(in-string) ...)(
 Unbind the specified var(in-string)s in the selected keymap.
 This is exactly equivalent to binding the strings to tt(undefined-key).
+
 When tt(-R) is also used, interpret the var(in-string)s as ranges.
+
+When tt(-p) is also used, the var(in-string)s specify prefixes.  Any
+binding that has the given var(in-string) as a prefix, not including the
+binding for the var(in-string) itself, if any, will be removed.  For
+example,
+
+example(bindkey -rpM viins '^[')
+
+will remove all bindings in the vi-insert keymap beginning with an escape
+character (probably cursor keys), but leave the binding for the escape
+character itself (probably tt(vi-cmd-mode)).  This is incompatible with the
+option tt(-R).
 )
 item(tt(-s) var(in-string out-string) ...)(
 Bind each var(in-string) to each var(out-string).
diff --git a/Src/Zle/zle_keymap.c b/Src/Zle/zle_keymap.c
index 9a485a506..f820a758f 100644
--- a/Src/Zle/zle_keymap.c
+++ b/Src/Zle/zle_keymap.c
@@ -90,6 +90,14 @@ struct bindstate {
     int prefixlen;
 };
 
+/* This structure is used when scanning for prefix bindings to remove */
+
+struct remprefstate {
+    Keymap km;
+    char *prefix;
+    int prefixlen;
+};
+
 #define BS_LIST (1<<0)
 #define BS_ALL  (1<<1)
 
@@ -836,6 +844,19 @@ bin_bindkey_bind(char *name, char *kmname, Keymap km, char **argv, char *ops, ch
 	zwarnnam(name, "keymap `%s' is protected", kmname, 0);
 	return 1;
     }
+    if (func == 'r' && ops['p']) {
+	char *useq, *bseq;
+	int len;
+	struct remprefstate rps;
+	rps.km = km;
+	while ((useq = *argv++)) {
+	    bseq = getkeystring(useq, &len, 2, NULL);
+	    rps.prefix = metafy(bseq, len, META_USEHEAP);
+	    rps.prefixlen = strlen(rps.prefix);
+	    scankeymap(km, 0, scanremoveprefix, &rps);
+	}
+	return 0;
+    }
     do {
 	char *useq = *argv, *bseq, *seq, *str;
 	int len;
@@ -880,6 +901,20 @@ bin_bindkey_bind(char *name, char *kmname, Keymap km, char **argv, char *ops, ch
     return ret;
 }
 
+/* Remove bindings for key sequences which have the given (proper) prefix. */
+
+/**/
+static void
+scanremoveprefix(char *seq, Thingy bind, char *str, void *magic)
+{
+    struct remprefstate *rps = magic;
+
+    if (strncmp(seq, rps->prefix, rps->prefixlen) || !seq[rps->prefixlen])
+	return;
+
+    bindkey(rps->km, seq, refthingy(t_undefinedkey), NULL);
+}
+
 /* List key bindings.  If an argument is given, list just that one *
  * binding, otherwise list the entire keymap.  If the -L option is *
  * given, list in the form of bindkey commands.                    */
@@ -913,6 +948,7 @@ bin_bindkey_list(char *name, char *kmname, Keymap km, char **argv, char *ops, ch
 	    }
 	    bs.prefix = getkeystring(argv[0], &bs.prefixlen, 2, NULL);
 	    bs.prefix = metafy(bs.prefix, bs.prefixlen, META_HREALLOC);
+	    bs.prefixlen = strlen(bs.prefix);
 	} else {
 	    bs.prefix = NULL;
 	    bs.prefixlen = 0;
@@ -1067,11 +1103,9 @@ add_cursor_key(Keymap km, int tccode, Thingy thingy, int defchar)
 	/*
 	 * Sanity checking.  If the cursor key is zero-length (unlikely,
 	 * but this is termcap we're talking about), or it's a single
-	 * character which is already bound, then we don't bind it.
+	 * character, then we don't bind it.
 	 */
-	if (!buf[0] || (!buf[1] && km->first[STOUC(buf[0])] != t_undefinedkey))
-	    ok = 0;
-	else
+	if (buf[0] && buf[1] && (buf[0] != Meta || buf[2]))
 	    ok = 1;
     }
     if (!ok) {