Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

PATCH: Re: .zshrc sanity check



Jean Chalard wrote:
> You bind history-beginning-search-backward on the up key. While I find
> this really useful (and I don't even imagine using my shell without
> this kind of binding, though I use history-search-backward), this has
> the drawback that the up arrow doesn't work as expected any more in
> zed sessions. It seems to me that many people like this binding, too.

A more general solution to this is to allow zed to use its own keymaps.
Then you can bind anything you like:

bindkey -N zed main
bindkey -M zed "\e[A" up-line-or-history
bindkey -M zed "\e[B" down-line-or-history

I added this to vared, since otherwise ensuring that the keymaps are
restored under all circumstances is rather hairy; plus it's generally
quite useful.

In case it's not clear, it's defined in such away that you can have both
a viins and a vicmd replacement.

I've also neatened bin_vared by making it use the normal option
handling; that didn't used to be possible because string argument
handling was weak.

Index: Doc/Zsh/contrib.yo
===================================================================
RCS file: /cvsroot/zsh/zsh/Doc/Zsh/contrib.yo,v
retrieving revision 1.30
diff -u -r1.30 contrib.yo
--- Doc/Zsh/contrib.yo	13 Oct 2003 16:50:19 -0000	1.30
+++ Doc/Zsh/contrib.yo	5 Apr 2004 17:26:12 -0000
@@ -1328,6 +1328,11 @@
 
 Without tt(-f), var(name) is the path name of the file to edit, which need
 not exist; it is created on write, if necessary.
+
+While editing, the function sets the main keymap to tt(zed) and the
+vi command keymap to tt(zed-vicmd).  These will be copied from the existing
+tt(main) and tt(vicmd) keymaps if they do not exist the first time tt(zed)
+is run.  They can be used to provide special key bindings used only in zed.
 )
 findex(zcp)
 findex(zln)
Index: Doc/Zsh/zle.yo
===================================================================
RCS file: /cvsroot/zsh/zsh/Doc/Zsh/zle.yo,v
retrieving revision 1.33
diff -u -r1.33 zle.yo
--- Doc/Zsh/zle.yo	15 Dec 2003 22:45:27 -0000	1.33
+++ Doc/Zsh/zle.yo	5 Apr 2004 17:26:12 -0000
@@ -265,7 +265,8 @@
 findex(vared)
 cindex(parameters, editing)
 cindex(editing parameters)
-item(tt(vared) [ tt(-Aache) ] [ tt(-p) var(prompt) ] [ tt(-r) var(rprompt) ] var(name))(
+xitem(tt(vared) [ tt(-Aache) ] [ tt(-p) var(prompt) ] [ tt(-r) var(rprompt) ])
+item(  [ -M var(main-keymap) ] [ -m var(vicmd-keymap) ] var(name))(
 The value of the parameter var(name) is loaded into the edit
 buffer, and the line editor is invoked.  When the editor exits,
 var(name) is set to the string value returned by the editor.
@@ -292,6 +293,10 @@
 tt(-h) flag is specified, the history can be accessed from ZLE. If the 
 tt(-e) flag is given, typing tt(^D) (Control-D) on an empty line
 causes tt(vared) to exit immediately with a non-zero return value.
+
+The tt(-M) option gives a keymap to link to the tt(main) keymap during
+editing, and the tt(-m) option gives a keymap to link to the tt(vicmd)
+keymap during editing.  On exit, the previous keymaps will be restored.
 )
 findex(zle)
 cindex(widgets, rebinding)
Index: Functions/Misc/zed
===================================================================
RCS file: /cvsroot/zsh/zsh/Functions/Misc/zed,v
retrieving revision 1.6
diff -u -r1.6 zed
--- Functions/Misc/zed	2 Apr 2001 13:04:05 -0000	1.6
+++ Functions/Misc/zed	5 Apr 2004 17:26:12 -0000
@@ -10,7 +10,7 @@
 # compctl -f -x 'w[1,-f]' -F -- zed
 #
 
-local var fun cleanup
+local var fun
 # We do not want timeout while we are editing a file
 integer TMOUT=0
 
@@ -24,20 +24,27 @@
 zstyle -m ":completion:zed:*" insert-tab '*' ||
     zstyle ":completion:zed:*" insert-tab yes
 
-# catch interrupts
-cleanup="$(bindkey -L "^M"; bindkey -L -M emacs "^X^W"; bindkey -aL "ZZ"
-    echo "trap - INT EXIT"; trap)"
-trap "return 130" INT
-trap "$cleanup" EXIT
+if ! bindkey -M zed >&/dev/null; then
+  # Make the zed keymap a copy of the current main.
+  bindkey -N zed main
+
+  # Assign some default keys.
+  # Depending on your stty's, you may be able to use ^J as accept-line, else:
+
+  # The following isn't useful if we are copying viins, but that's
+  # a nicety.
+  bindkey -M zed '^x^w' accept-line
+  bindkey -M zed '^M' self-insert-unmeta
+fi
+if ! bindkey -M zed-vicmd >&/dev/null; then
+  bindkey -N zed-vicmd vicmd
+
+  bindkey -M zed-vicmd "ZZ" accept-line
+fi
 
 # don't mangle !'s
 setopt localoptions nobanghist
 
-bindkey "^M" self-insert-unmeta
-# Depending on your stty's, you may be able to use ^J as accept-line, else:
-bindkey -M emacs "^X^W" accept-line
-bindkey -a "ZZ" accept-line
-
 if ((fun)) then
   var="$(functions $1)"
   # If function is undefined but autoloadable, load it
@@ -55,10 +62,10 @@
     var="$1() {
 }"
   fi
-  vared var && eval "$cleanup ;" function "$var"
+  vared -M zed -m zed-vicmd var && eval function "$var"
 else
   [[ -f $1 ]] && var="$(<$1)"
-  while vared var
+  while vared -M zed -m zed-vicmd var
   do
     (print -r -- "$var" >| $1) && break
     echo -n -e '\a'
Index: Src/Zle/zle_keymap.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Zle/zle_keymap.c,v
retrieving revision 1.13
diff -u -r1.13 zle_keymap.c
--- Src/Zle/zle_keymap.c	8 Mar 2004 11:44:14 -0000	1.13
+++ Src/Zle/zle_keymap.c	5 Apr 2004 17:26:13 -0000
@@ -169,8 +169,7 @@
     KeymapName kmn = (KeymapName) hn;
 
     zsfree(kmn->nam);
-    if(!--kmn->keymap->rc)
-	deletekeymap(kmn->keymap);
+    unrefkeymap(kmn->keymap);
     zfree(kmn, sizeof(*kmn));
 }
 
@@ -355,8 +354,7 @@
 	    return 1;
 	if(n->keymap == km)
 	    return 0;
-	if(!--n->keymap->rc)
-	    deletekeymap(n->keymap);
+	unrefkeymap(n->keymap);
 	n->keymap = km;
     } else {
 	n = makekeymapnamnode(km);
@@ -364,10 +362,23 @@
 	    n->flags |= KMN_IMMORTAL;
 	keymapnamtab->addnode(keymapnamtab, ztrdup(name), n);
     }
-    km->rc++;
+    refkeymap(km);
     return 0;
 }
 
+/**/
+void refkeymap(Keymap km)
+{
+    km->rc++;
+}
+
+/**/
+void unrefkeymap(Keymap km)
+{
+    if (!--km->rc)
+	deletekeymap(km);
+}
+
 /* Select a keymap as the current ZLE keymap.  Can optionally fall back *
  * on the guaranteed safe keymap if it fails.                           */
 
Index: Src/Zle/zle_main.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Zle/zle_main.c,v
retrieving revision 1.41
diff -u -r1.41 zle_main.c
--- Src/Zle/zle_main.c	22 Mar 2004 19:51:17 -0000	1.41
+++ Src/Zle/zle_main.c	5 Apr 2004 17:26:13 -0000
@@ -987,6 +987,45 @@
 	initmodifier(&zmod);
 }
 
+/**/
+static int
+savekeymap(char *cmdname, char *oldname, char *newname, Keymap *savemapptr)
+{
+    Keymap km = openkeymap(newname);
+
+    if (km) {
+	*savemapptr = openkeymap(oldname);
+	/* I love special cases */
+	if (*savemapptr == km)
+	    *savemapptr = NULL;
+	else {
+	    /* make sure this doesn't get deleted. */
+	    if (*savemapptr)
+		refkeymap(*savemapptr);
+	    linkkeymap(km, oldname, 0);
+	}
+	return 0;
+    } else {
+	zwarnnam(cmdname, "no such keymap: %s", newname, 0);
+	return 1;
+    }
+}
+
+/**/
+static void
+restorekeymap(char *cmdname, char *oldname, char *newname, Keymap savemap)
+{
+    if (savemap) {
+	linkkeymap(savemap, oldname, 0);
+	/* we incremented the reference count above */
+	unrefkeymap(savemap);
+    } else if (newname) {
+	/* urr... can this happen? */
+	zwarnnam(cmdname,
+		 "keymap %s was not defined, not restored", oldname, 0);
+    }
+}
+
 /* this exports the argument we are currently vared'iting if != NULL */
 
 /**/
@@ -1002,9 +1041,10 @@
     struct value vbuf;
     Value v;
     Param pm = 0;
-    int create = 0, ifl;
+    int ifl;
     int type = PM_SCALAR, obreaks = breaks, haso = 0;
-    char *p1 = NULL, *p2 = NULL;
+    char *p1, *p2, *main_keymapname, *vicmd_keymapname;
+    Keymap main_keymapsave = NULL, vicmd_keymapsave = NULL;
     FILE *oshout = NULL;
 
     if ((interact && unset(USEZLE)) || !strcmp(term, "emacs")) {
@@ -1016,61 +1056,23 @@
 	return 1;
     }
 
-    /* all options are handled as arguments */
-    while (*args && **args == '-') {
-	while (*++(*args))
-	    switch (**args) {
-	    case 'c':
-		/* -c option -- allow creation of the parameter if it doesn't
-		yet exist */
-		create = 1;
-		break;
-	    case 'a':
-		type = PM_ARRAY;
-		break;
-	    case 'A':
-		type = PM_HASHED;
-		break;
-	    case 'p':
-		/* -p option -- set main prompt string */
-		if ((*args)[1])
-		    p1 = *args + 1, *args = "" - 1;
-		else if (args[1])
-		    p1 = *(++args), *args = "" - 1;
-		else {
-		    zwarnnam(name, "prompt string expected after -%c", NULL,
-			     **args);
-		    return 1;
-		}
-		break;
-	    case 'r':
-		/* -r option -- set right prompt string */
-		if ((*args)[1])
-		    p2 = *args + 1, *args = "" - 1;
-		else if (args[1])
-		    p2 = *(++args), *args = "" - 1;
-		else {
-		    zwarnnam(name, "prompt string expected after -%c", NULL,
-			     **args);
-		    return 1;
-		}
-		break;
-	    case 'h':
-		/* -h option -- enable history */
-		ops->ind['h'] = 1;
-		break;
-	    case 'e':
-		/* -e option -- enable EOF */
-		ops->ind['e'] = 1;
-		break;
-	    default:
-		/* unrecognised option character */
-		zwarnnam(name, "unknown option: %s", *args, 0);
-		return 1;
-	    }
-	args++;
+    if (OPT_ISSET(ops,'A'))
+    {
+	if (OPT_ISSET(ops, 'a'))
+	{
+	    zwarnnam(name, "specify only one of -a and -A", NULL, 0);
+	    return 1;
+	}
+	type = PM_HASHED;
     }
-    if (type && !create) {
+    else if (OPT_ISSET(ops,'a'))
+	type = PM_ARRAY;
+    p1 = OPT_ARG_SAFE(ops,'p');
+    p2 = OPT_ARG_SAFE(ops,'r');
+    main_keymapname = OPT_ARG_SAFE(ops,'M');
+    vicmd_keymapname = OPT_ARG_SAFE(ops,'m');
+
+    if (type != PM_SCALAR && !OPT_ISSET(ops,'c')) {
 	zwarnnam(name, "-%s ignored", type == PM_ARRAY ? "a" : "A", 0);
     }
 
@@ -1082,9 +1084,9 @@
     /* handle non-existent parameter */
     s = args[0];
     queue_signals();
-    v = fetchvalue(&vbuf, &s, (!create || type == PM_SCALAR),
+    v = fetchvalue(&vbuf, &s, (!OPT_ISSET(ops,'c') || type == PM_SCALAR),
 		   SCANPM_WANTKEYS|SCANPM_WANTVALS|SCANPM_MATCHMANY);
-    if (!v && !create) {
+    if (!v && !OPT_ISSET(ops,'c')) {
 	unqueue_signals();
 	zwarnnam(name, "no such variable: %s", args[0], 0);
 	return 1;
@@ -1156,6 +1158,13 @@
     /* edit the parameter value */
     zpushnode(bufstack, s);
 
+    if (main_keymapname &&
+	savekeymap(name, "main", main_keymapname, &main_keymapsave))
+	main_keymapname = NULL;
+    if (vicmd_keymapname &&
+	savekeymap(name, "vicmd", vicmd_keymapname, &vicmd_keymapsave))
+	vicmd_keymapname = NULL;
+
     varedarg = *args;
     ifl = isfirstln;
     if (OPT_ISSET(ops,'h'))
@@ -1167,6 +1176,10 @@
 	hend(NULL);
     isfirstln = ifl;
     varedarg = ova;
+
+    restorekeymap(name, "main", main_keymapname, main_keymapsave);
+    restorekeymap(name, "vicmd", vicmd_keymapname, vicmd_keymapsave);
+
     if (haso) {
 	fclose(shout);	/* close(SHTTY) */
 	shout = oshout;
@@ -1182,7 +1195,7 @@
     if (t[strlen(t) - 1] == '\n')
 	t[strlen(t) - 1] = '\0';
     /* final assignment of parameter value */
-    if (create) {
+    if (OPT_ISSET(ops,'c')) {
 	unsetparam(args[0]);
 	createparam(args[0], type);
     }
@@ -1353,7 +1366,7 @@
 
 static struct builtin bintab[] = {
     BUILTIN("bindkey", 0, bin_bindkey, 0, -1, 0, "evaM:ldDANmrsLRp", NULL),
-    BUILTIN("vared",   0, bin_vared,   1,  7, 0, NULL,             NULL),
+    BUILTIN("vared",   0, bin_vared,   1,  7, 0, "aAchM:m:p:r:", NULL),
     BUILTIN("zle",     0, bin_zle,     0, -1, 0, "aAcCDFgGIKlLmMNRU", NULL),
 };
 

-- 
Peter Stephenson <pws@xxxxxxx>                  Software Engineer
CSR Ltd., Science Park, Milton Road,
Cambridge, CB4 0WH, UK                          Tel: +44 (0)1223 692070


**********************************************************************
This email and any files transmitted with it are confidential and
intended solely for the use of the individual or entity to whom they
are addressed. If you have received this email in error please notify
the system manager.

This footnote also confirms that this email message has been swept by
MIMEsweeper for the presence of computer viruses.

www.mimesweeper.com
**********************************************************************



Messages sorted by: Reverse Date, Date, Thread, Author