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

Re: change color depending on vi-mode

On Mon, 23 Jan 2006 16:17:18 +0000
Bart Schaefer <schaefer@xxxxxxxxxxxxxxxx> wrote:
> The short answer is that the only way to do it is to create your own
> widget functions for all of the vi commands that change modes.  There
> is no "callback" associated with changing the keymap that can be used
> to update the prompt.

It's easy to add, however (redirected to zsh-workers).

The following function provides a simple example, but I'm sure there's a
better one for inclusion with the supplied Zle functions.  (Bits of
could be included; it looks like that works perfectly well but
redefining every vi widget is a bit heavy going and this is more
general.)  I tried it with "/" within vi command mode and it looks like
the mechanism is fairly robust, although I wouldn't be surprised if
there were gotchas.

I'm not prepared to hold my breath until we have get and set advice
functions for variables...

By the way, this is partly because I realise I've been extremely slow
getting out another 4.3 test release and there's nothing really hindering
it.  I've been fairly busy.

zle-keymap-select() {
  local showcmd="<C>"

  if [[ $KEYMAP = vicmd ]]; then
    if [[ $PS1 != "<C>"* ]]; then
      zle reset-prompt
    if [[ $PS1 = "<C>"* ]]; then
      zle reset-prompt
zle -N zle-keymap-select

The name chosen isn't entirely to be illogical, it's because I expect
functions of this sort to have a vaguely object-oriented naming
convention along the lines of <module>-<object>-<action>.  Compare
zsh-mime-handler and zsh-mime-setup.

Index: Doc/Zsh/zle.yo
RCS file: /cvsroot/zsh/zsh/Doc/Zsh/zle.yo,v
retrieving revision 1.48
diff -u -r1.48 zle.yo
--- Doc/Zsh/zle.yo	24 Nov 2005 10:25:34 -0000	1.48
+++ Doc/Zsh/zle.yo	24 Jan 2006 20:46:27 -0000
@@ -763,8 +763,8 @@
 subsect(Special Widget)
-There is one user-defined widget which is special to the shell.
-If it does not exist, no special action is taken.  The environment
+There are a few user-defined widgets which are special to the shell.
+If they do not exist, no special action is taken.  The environment
 provided is identical to that for any other editing widget.
@@ -780,6 +780,19 @@
 (The command inside the function sets the keymap directly; it is
 equivalent to tt(zle vi-cmd-mode).)
+Executed every time the keymap changes, i.e. the special parameter
+tt(KEYMAP) is set to a different value, while the line editor is active.
+Initialising the keymap when the line editor starts does not cause the
+widget to be called.
+The value tt($KEYMAP) within the function reflects the new keymap.  The
+old keymap is passed as the sole argument.
+This can been used for detecting switches between the vi command
+(tt(vicmd)) and insert (usually tt(main)) keymaps.
 sect(Standard Widgets)
Index: Src/Zle/zle_keymap.c
RCS file: /cvsroot/zsh/zsh/Src/Zle/zle_keymap.c,v
retrieving revision 1.23
diff -u -r1.23 zle_keymap.c
--- Src/Zle/zle_keymap.c	28 Oct 2005 17:42:07 -0000	1.23
+++ Src/Zle/zle_keymap.c	24 Jan 2006 20:46:28 -0000
@@ -400,8 +400,24 @@
 	km = openkeymap(name = ".safe");
     if(name != curkeymapname) {
-	zsfree(curkeymapname);
+	char *oname = curkeymapname;
+	Thingy chgthingy;
 	curkeymapname = ztrdup(name);
+	if (oname && zleactive && strcmp(oname, curkeymapname) &&
+	    (chgthingy = rthingy_nocreate("zle-keymap-select"))) {
+	    char *args[2];
+	    int saverrflag = errflag, savretflag = retflag;
+	    args[0] = oname;
+	    args[1] = NULL;
+	    errflag = retflag = 0;
+	    execzlefunc(chgthingy, args);
+	    unrefthingy(chgthingy);
+	    errflag = saverrflag;
+	    retflag = savretflag;
+	}
+	zsfree(oname);
     curkeymap = km;
     return 0;

Peter Stephenson <p.w.stephenson@xxxxxxxxxxxx>
Web page still at http://www.pwstephenson.fsnet.co.uk/

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