zsh-workers
 help / color / mirror / code / Atom feed
* PATCH: zle recursive editing.
@ 2002-06-30 20:53 Peter Stephenson
  2002-06-30 21:19 ` Bart Schaefer
  0 siblings, 1 reply; 6+ messages in thread
From: Peter Stephenson @ 2002-06-30 20:53 UTC (permalink / raw)
  To: Zsh hackers list

This simple patch (only the trivial function recursiveedit is new, the
rest is just rearrangement, mostly to move the core functions from
zlemain to a new function zlecore) has a lot of mileage.  The widget
`recursive-edit' gives control to zle, then returns it to the widget in
question at the point the line would usually be accepted or aborted,
with status 0 or status 1 respectively.  This makes it easy to restore
status, and also to propagate the accept/break to the top level if you
want to.

The internal recursiveedit only handles the variables `errflag' and
`done' and redisplaying on entry.  There may be some other things I have
missed, though testing during the week suggests this covers the essentials.

Apart from the example in the manual entry, here are a few others I have
been playing with.  I hope there are lots more.


edit-file: a zed lookalike, except the file to be edited is a word on
the current command line.  When you have finished, the command line is
restored.

  # This function allows you to edit a small file mentioned on the command
  # line inside the shell.  Invoking the function when the cursor is on or
  # after a word containing the name of the file temporarily replaces the
  # contents of the line editor's buffer with the contents of the file, if
  # any.  Typing ^j (or ZZ in vicmd mode) saves the file, send-break (^G in
  # Emacs mode) aborts.  At this point the original command line is restored.

  emulate -L zsh
  setopt extendedglob

  local lbuffer=$LBUFFER rbuffer=$RBUFFER mark=$MARK
  local lwords words cleanup
  integer stat

  lwords=(${(z)LBUFFER})
  words=(${(z)BUFFER})

  local file=${(Q)words[${#lwords}]} msg

  if [[ ! -f $file ]]; then
    if [[ ! -d $file && -w ${file:h} ]]; then
      msg=Creating
      BUFFER=
    else
      zle -M "Can't create $file."
      return 1
    fi
  elif [[ ! -w $file ]]; then
    zle -M "File $file not writeable."
    return 1
  else
    msg=Editing
    BUFFER="$(<$file)"
  fi

  CURSOR=1

  # copied from zed
  cleanup="$(bindkey -L "^M"; bindkey -L -M emacs "^X^W"; bindkey -aL "ZZ")"
  bindkey '^m' self-insert-unmeta
  bindkey -M emacs "^X^W" accept-line
  bindkey -a "ZZ" accept-line

  zle -M "*** $msg ${file:t}, hit ^j to save, ^g to abort ***"

  if zle recursive-edit; then
    print $BUFFER >$file
  else
    zle -M "Aborted."
  fi

  LBUFFER=$lbuffer RBUFFER=$rbuffer MARK=$mark

  eval $cleanup


recursive-predict: another way of using the predict-on stuff provided
with the distribution.  Exercise for the user:  restore the original
command line if the mode is aborted instead of exited normally.

  # Provides an alternative and possibly more convenient interface
  # to the predict-on function, q.v.  You should not need to make special
  # arrangements for loading or binding the functions in that file.
  #
  # Predict mode is exited at any point the line would usually be accepted
  # or abandoned.  At that point, normal editing is restored.  Hence you
  # will require two `return's to accept a line from inside predict mode.

  autoload -U predict-on

  predict-on

  zle -M '[Recursive predict]'

  zle recursive-edit

  predict-off

  zle -M '[Recursive prediction off]'


list-select:  an example of a widget which allows you to select
something to be inserted from a list just by scrolling up and down it.
This particular example isn't useful.  Exercise for the reader:
retrieve the list from a function related to the name of the widget.

  local savel=$LBUFFER saver=$RBUFFER sel
  integer stat

  # Obviously, the following list should be something useful.
  # Generating this via a style might be appropriate.
  list=(hocus pocus magic crocus)

  local pretext="$LBUFFER$RBUFFER
  * Select one of the following *
  "

  LBUFFER="$pretext${list[1]}"
  RBUFFER="
  ${(F)list[2,-1]}"

  zle recursive-edit
  # No good if this returned non-zero
  stat=$?

  # No good if the cursor isn't in the list
  [[ $CURSOR -lt ${#pretext} ]] && stat=1

  sel="${LBUFFER##*$'\n'}${RBUFFER%%$'\n'*}"

  LBUFFER=$savel
  RBUFFER=$saver

  (( !$stat )) && LBUFFER+=$sel

  return $stat


Index: Doc/Zsh/zle.yo
===================================================================
RCS file: /cvsroot/zsh/zsh/Doc/Zsh/zle.yo,v
retrieving revision 1.22
diff -u -r1.22 zle.yo
--- Doc/Zsh/zle.yo	24 Jun 2002 09:52:01 -0000	1.22
+++ Doc/Zsh/zle.yo	30 Jun 2002 20:23:27 -0000
@@ -1620,6 +1620,48 @@
 construct into the editor buffer.
 The latter is equivalent to tt(push-input) followed by tt(get-line).
 )
+tindex(recursive-edit)
+item(tt(recursive-edit))(
+Only useful from a user-defined widget.  At this point in the function,
+the editor regains control until one of the standard widgets which would
+normally cause zle to exit (typically an tt(accept-line) caused by
+hitting the return key) is executed.  Instead, control returns to the
+user-defined widget.  The status returned is non-zero if the return was
+caused by an error, but the function still continues executing and hence
+may tidy up.  This makes it safe for the user-defined widget to alter
+the command line or key bindings temporarily.
+
+
+The following widget, tt(caps-lock), serves as an example.
+example(self-insert-ucase() {
+  LBUFFER+=${(U)KEYS[-1]}
+}
+
+integer stat
+
+zle -N self-insert self-insert-ucase
+zle -A caps-lock save-caps-lock
+zle -A accept-line caps-lock
+
+zle recursive-edit
+stat=$?
+
+zle -A .self-insert self-insert
+zle -A save-caps-lock caps-lock
+zle -D save-caps-lock
+
+(( stat )) && zle send-break
+
+return $stat
+)
+This causes typed letters to be inserted capitalised until either
+tt(accept-line) (i.e. typically the return key) is typed or the
+tt(caps-lock) widget is invoked again; the later is handled by saving
+the old definition of tt(caps-lock) as tt(save-caps-lock) and then
+rebinding it to invoke tt(accept-line).  Note that an error from the
+recursive edit is detected as a non-zero return status and propagated by
+using the tt(send-break) widget.
+)
 tindex(redisplay)
 item(tt(redisplay) (unbound) (^R) (^R))(
 Redisplays the edit buffer.
Index: Src/Zle/iwidgets.list
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Zle/iwidgets.list,v
retrieving revision 1.3
diff -u -r1.3 iwidgets.list
--- Src/Zle/iwidgets.list	12 Apr 2000 08:24:16 -0000	1.3
+++ Src/Zle/iwidgets.list	30 Jun 2002 20:23:27 -0000
@@ -85,6 +85,7 @@
 "quoted-insert", quotedinsert, ZLE_MENUCMP | ZLE_KEEPSUFFIX
 "quote-line", quoteline, 0
 "quote-region", quoteregion, 0
+"recursive-edit", recursiveedit, ZLE_MENUCMP | ZLE_KEEPSUFFIX | ZLE_LASTCOL
 "redisplay", redisplay, ZLE_MENUCMP | ZLE_KEEPSUFFIX | ZLE_LASTCOL
 "redo", redo, ZLE_KEEPSUFFIX
 "reverse-menu-complete", reversemenucomplete, ZLE_MENUCMP | ZLE_KEEPSUFFIX | ZLE_ISCOMP
Index: Src/Zle/zle_main.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Zle/zle_main.c,v
retrieving revision 1.24
diff -u -r1.24 zle_main.c
--- Src/Zle/zle_main.c	6 Jun 2002 09:04:47 -0000	1.24
+++ Src/Zle/zle_main.c	30 Jun 2002 20:23:36 -0000
@@ -89,10 +89,11 @@
 static int eofsent;
 static long keytimeout;
 
-#ifdef HAVE_SELECT
+#if defined(HAVE_SELECT) || defined(HAVE_POLL)
 /* Terminal baud rate */
 
 static int baud;
+static long costmult;
 #endif
 
 /* flags associated with last command */
@@ -631,6 +632,74 @@
     return ret;
 }
 
+/**/
+void
+zlecore(void)
+{
+#if !defined(HAVE_POLL) && defined(HAVE_SELECT)
+    struct timeval tv;
+    fd_set foofd;
+
+    FD_ZERO(&foofd);
+#endif
+
+    zrefresh();
+
+    while (!done && !errflag) {
+
+	statusline = NULL;
+	vilinerange = 0;
+	reselectkeymap();
+	selectlocalmap(NULL);
+	bindk = getkeycmd();
+	if (!ll && isfirstln && unset(IGNOREEOF) && c == eofchar) {
+	    eofsent = 1;
+	    break;
+	}
+	if (bindk) {
+	    if (execzlefunc(bindk, zlenoargs))
+		handlefeep(zlenoargs);
+	    handleprefixes();
+	    /* for vi mode, make sure the cursor isn't somewhere illegal */
+	    if (invicmdmode() && cs > findbol() &&
+		(cs == ll || line[cs] == '\n'))
+		cs--;
+	    if (undoing)
+		handleundo();
+	} else {
+	    errflag = 1;
+	    break;
+	}
+#ifdef HAVE_POLL
+	if (baud && !(lastcmd & ZLE_MENUCMP)) {
+	    struct pollfd pfd;
+	    int to = cost * costmult / 1000; /* milliseconds */
+
+	    if (to > 500)
+		to = 500;
+	    pfd.fd = SHTTY;
+	    pfd.events = POLLIN;
+	    if (!kungetct && poll(&pfd, 1, to) <= 0)
+		zrefresh();
+	} else
+#else
+# ifdef HAVE_SELECT
+	if (baud && !(lastcmd & ZLE_MENUCMP)) {
+	    FD_SET(SHTTY, &foofd);
+	    tv.tv_sec = 0;
+	    if ((tv.tv_usec = cost * costmult) > 500000)
+		tv.tv_usec = 500000;
+	    if (!kungetct && select(SHTTY+1, (SELECT_ARG_2_T) & foofd,
+				    NULL, NULL, &tv) <= 0)
+		zrefresh();
+	} else
+# endif
+#endif
+	    if (!kungetct)
+		zrefresh();
+    }
+}
+
 /* Read a line.  It is returned metafied. */
 
 /**/
@@ -641,14 +710,7 @@
     int old_errno = errno;
     int tmout = getiparam("TMOUT");
 
-#if defined(HAVE_SELECT) || defined(HAVE_POLL)
-    long costmult;
-# ifdef HAVE_POLL
-# else
-    struct timeval tv;
-    fd_set foofd;
-# endif
-
+#if defined(HAVE_POLL) || defined(HAVE_SELECT)
     baud = getiparam("BAUD");
     costmult = (baud) ? 3840000L / baud : 0;
 #endif
@@ -693,11 +755,6 @@
 
     zlereadflags = flags;
     histline = curhist;
-#ifndef HAVE_POLL
-# ifdef HAVE_SELECT
-    FD_ZERO(&foofd);
-# endif
-#endif
     undoing = 1;
     line = (unsigned char *)zalloc((linesz = 256) + 2);
     virangeflag = lastcmd = done = cs = ll = mark = 0;
@@ -732,60 +789,9 @@
     lastcol = -1;
     initmodifier(&zmod);
     prefixflag = 0;
-    zrefresh();
-    while (!done && !errflag) {
 
-	statusline = NULL;
-	vilinerange = 0;
-	reselectkeymap();
-	selectlocalmap(NULL);
-	bindk = getkeycmd();
-	if (!ll && isfirstln && unset(IGNOREEOF) && c == eofchar) {
-	    eofsent = 1;
-	    break;
-	}
-	if (bindk) {
-	    if (execzlefunc(bindk, zlenoargs))
-		handlefeep(zlenoargs);
-	    handleprefixes();
-	    /* for vi mode, make sure the cursor isn't somewhere illegal */
-	    if (invicmdmode() && cs > findbol() &&
-		(cs == ll || line[cs] == '\n'))
-		cs--;
-	    if (undoing)
-		handleundo();
-	} else {
-	    errflag = 1;
-	    break;
-	}
-#ifdef HAVE_POLL
-	if (baud && !(lastcmd & ZLE_MENUCMP)) {
-	    struct pollfd pfd;
-	    int to = cost * costmult / 1000; /* milliseconds */
+    zlecore();
 
-	    if (to > 500)
-		to = 500;
-	    pfd.fd = SHTTY;
-	    pfd.events = POLLIN;
-	    if (!kungetct && poll(&pfd, 1, to) <= 0)
-		zrefresh();
-	} else
-#else
-# ifdef HAVE_SELECT
-	if (baud && !(lastcmd & ZLE_MENUCMP)) {
-	    FD_SET(SHTTY, &foofd);
-	    tv.tv_sec = 0;
-	    if ((tv.tv_usec = cost * costmult) > 500000)
-		tv.tv_usec = 500000;
-	    if (!kungetct && select(SHTTY+1, (SELECT_ARG_2_T) & foofd,
-				    NULL, NULL, &tv) <= 0)
-		zrefresh();
-	} else
-# endif
-#endif
-	    if (!kungetct)
-		zrefresh();
-    }
     statusline = NULL;
     invalidatelist();
     trashzle();
@@ -1231,6 +1237,20 @@
     showmsg(ff.msg);
     zsfree(ff.msg);
     return 0;
+}
+
+/**/
+int
+recursiveedit(char **args)
+{
+    int locerror;
+
+    zlecore();
+
+    locerror = errflag;
+    errflag = done = 0;
+
+    return locerror;
 }
 
 /**/

-- 
Peter Stephenson <pws@pwstephenson.fsnet.co.uk>
Work: pws@csr.com
Web: http://www.pwstephenson.fsnet.co.uk


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: PATCH: zle recursive editing.
  2002-06-30 20:53 PATCH: zle recursive editing Peter Stephenson
@ 2002-06-30 21:19 ` Bart Schaefer
  2002-07-01  9:52   ` Peter Stephenson
  0 siblings, 1 reply; 6+ messages in thread
From: Bart Schaefer @ 2002-06-30 21:19 UTC (permalink / raw)
  To: zsh-workers

On Jun 30,  9:53pm, Peter Stephenson wrote:
} Subject: PATCH: zle recursive editing.
}
} This simple patch (only the trivial function recursiveedit is new, the
} rest is just rearrangement, mostly to move the core functions from
} zlemain to a new function zlecore) has a lot of mileage.

Cool.  Now if there were some way to get the various "minibuffer" commands
like execute-named-command to use recursive editing with a separate keymap,
we could really do some interesting stuff.

Who'll be the first to rewrite the zsh tetris game with recursive-edit?

-- 
Bart Schaefer                                 Brass Lantern Enterprises
http://www.well.com/user/barts              http://www.brasslantern.com

Zsh: http://www.zsh.org | PHPerl Project: http://phperl.sourceforge.net   


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: PATCH: zle recursive editing.
  2002-06-30 21:19 ` Bart Schaefer
@ 2002-07-01  9:52   ` Peter Stephenson
  2002-07-01 11:23     ` PATCH: $PREDISPLAY/$POSTDISPLAY Peter Stephenson
  0 siblings, 1 reply; 6+ messages in thread
From: Peter Stephenson @ 2002-07-01  9:52 UTC (permalink / raw)
  To: Zsh hackers list

"Bart Schaefer" wrote:
> On Jun 30,  9:53pm, Peter Stephenson wrote:
> } Subject: PATCH: zle recursive editing.
> }
> } This simple patch (only the trivial function recursiveedit is new, the
> } rest is just rearrangement, mostly to move the core functions from
> } zlemain to a new function zlecore) has a lot of mileage.
> 
> Cool.  Now if there were some way to get the various "minibuffer" commands
> like execute-named-command to use recursive editing with a separate keymap,
> we could really do some interesting stuff.

Another thing I thought of which might be useful is a way to protect
areas of the display, so for example if you are using a widget like
select-list you can't move off the list until you accept something or
break.  I think you could do something like this without too much
difficulty by using a special parameter like $PREDISPLAY (maybe also
$POSTDISPLAY, since this gives you more control than zle -M), which would
insert the given lines before (or after) $BUFFER.  This could probably
be done within zle_refresh (and zle_parameter, of course).  It would
probably have to be line-orientated to avoid weird interactions with the
normal buffer, although maybe even that restriction is avoidable.

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


**********************************************************************
The information transmitted is intended only for the person or
entity to which it is addressed and may contain confidential 
and/or privileged material. 
Any review, retransmission, dissemination or other use of, or
taking of any action in reliance upon, this information by 
persons or entities other than the intended recipient is 
prohibited.  
If you received this in error, please contact the sender and 
delete the material from any computer.
**********************************************************************


^ permalink raw reply	[flat|nested] 6+ messages in thread

* PATCH: $PREDISPLAY/$POSTDISPLAY
  2002-07-01  9:52   ` Peter Stephenson
@ 2002-07-01 11:23     ` Peter Stephenson
  2002-07-04  7:57       ` Sven Wischnowsky
  0 siblings, 1 reply; 6+ messages in thread
From: Peter Stephenson @ 2002-07-01 11:23 UTC (permalink / raw)
  To: Zsh hackers list

Peter Stephenson wrote:
> Another thing I thought of which might be useful is a way to protect
> areas of the display, so for example if you are using a widget like
> select-list you can't move off the list until you accept something or
> break.  I think you could do something like this without too much
> difficulty by using a special parameter like $PREDISPLAY (maybe also
> $POSTDISPLAY, since this gives you more control than zle -M), which would
> insert the given lines before (or after) $BUFFER.  This could probably
> be done within zle_refresh (and zle_parameter, of course).  It would
> probably have to be line-orientated to avoid weird interactions with the
> normal buffer, although maybe even that restriction is avoidable.

This is what I had in mind.  zle_refresh is one of the few reasonably
modular parts of zle, so it turns out having only chunks of a line works
fine.

Note the way these parameters survive across invocations of zle.  This
was simply because it was the most natural way of writing it.  We can
make zleread() reinitialise them if it seems preferable.

Hmm, it would be nice to get bits of these optionally in inverse video.
In fact, it would be nice to get a lot of other stuff such as the region
between point and mark in inverse video.

Here's a trivial example of how this works with recursive-edit.

pre-post-example () {
        PREDISPLAY="*** You can't edit this bit ***
" POSTDISPLAY="
*** Nor this bit ***"
        zle recursive-edit
        PREDISPLAY= POSTDISPLAY= 
}

Index: Src/Zle/zle_params.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Zle/zle_params.c,v
retrieving revision 1.4
diff -u -r1.4 zle_params.c
--- Src/Zle/zle_params.c	24 Jun 2002 09:52:01 -0000	1.4
+++ Src/Zle/zle_params.c	1 Jul 2002 11:05:24 -0000
@@ -85,6 +85,10 @@
 	unset_cutbuffer, NULL },
     { "killring", PM_ARRAY, FN(set_killring), FN(get_killring),
 	unset_killring, NULL },
+    { "PREDISPLAY", PM_SCALAR, FN(set_predisplay), FN(get_predisplay),
+	zleunsetfn, NULL },
+    { "POSTDISPLAY", PM_SCALAR, FN(set_postdisplay), FN(get_postdisplay),
+	zleunsetfn, NULL },
     { NULL, 0, NULL, NULL, NULL, NULL }
 };
 
@@ -461,4 +465,54 @@
 	set_killring(pm, NULL);
 	stdunsetfn(pm, exp);
     }
+}
+
+static void
+set_prepost(unsigned char **textvar, int *lenvar, char *x)
+{
+    if (*lenvar) {
+	zfree(*textvar, *lenvar);
+	*textvar = NULL;
+	*lenvar = 0;
+    }
+    if (x) {
+	unmetafy(x, lenvar);
+	*textvar = (unsigned char *)zalloc(*lenvar);
+	memcpy((char *)*textvar, x, *lenvar);
+	free(x);
+    }
+}
+
+static char *
+get_prepost(unsigned char *text, int len)
+{
+    return metafy((char *)text, len, META_HEAPDUP);
+}
+
+/**/
+static void
+set_predisplay(Param pm, char *x)
+{
+    set_prepost(&predisplay, &predisplaylen, x);
+}
+
+/**/
+static char *
+get_predisplay(Param pm)
+{
+    return get_prepost(predisplay, predisplaylen);
+}
+
+/**/
+static void
+set_postdisplay(Param pm, char *x)
+{
+    set_prepost(&postdisplay, &postdisplaylen, x);
+}
+
+/**/
+static char *
+get_postdisplay(Param pm)
+{
+    return get_prepost(postdisplay, postdisplaylen);
 }
Index: Src/Zle/zle_refresh.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Zle/zle_refresh.c,v
retrieving revision 1.6
diff -u -r1.6 zle_refresh.c
--- Src/Zle/zle_refresh.c	19 Feb 2002 00:06:54 -0000	1.6
+++ Src/Zle/zle_refresh.c	1 Jul 2002 11:05:24 -0000
@@ -81,6 +81,16 @@
 /**/
 int trashedzle;
 
+/*
+ * Information used by PREDISPLAY and POSTDISPLAY parameters which
+ * add non-editable text to that being displayed.
+ */
+/**/
+unsigned char *predisplay, *postdisplay;
+/**/
+int predisplaylen, postdisplaylen;
+
+
 #ifdef HAVE_SELECT
 /* cost of last update */
 /**/
@@ -278,6 +288,10 @@
 	*sen,			/* pointer to end of the video buffer (eol)  */
 	*scs;			/* pointer to cursor position in real buffer */
     char **qbuf;		/* tmp					     */
+    unsigned char *tmpline;	/* line with added pre/post text */
+    int tmpcs, tmpll;		/* ditto cursor position and line length */
+    int tmpalloced;		/* flag to free tmpline when finished */
+	
 
     /* If this is called from listmatches() (indirectly via trashzle()), and *
      * that was called from the end of zrefresh(), then we don't need to do  *
@@ -286,6 +300,25 @@
     if (inlist)
 	return;
 
+    if (predisplaylen || postdisplaylen) {
+	/* There is extra text to display at the start or end of the line */
+	tmpline = zalloc(ll + predisplaylen + postdisplaylen);
+	if (predisplaylen)
+	    memcpy(tmpline, predisplay, predisplaylen);
+	if (ll)
+	    memcpy(tmpline+predisplaylen, line, ll);
+	if (postdisplaylen)
+	    memcpy(tmpline+predisplaylen+ll, postdisplay, postdisplaylen);
+	tmpcs = cs + predisplaylen;
+	tmpll = predisplaylen + ll + postdisplaylen;
+	tmpalloced = 1;
+    } else {
+	tmpline = line;
+	tmpcs = cs;
+	tmpll = ll;
+	tmpalloced = 0;
+    }
+
     if (clearlist && listshown > 0) {
 	if (tccan(TCCLEAREOD)) {
 	    int ovln = vln, ovcs = vcs;
@@ -392,18 +425,18 @@
    width comparisons can be made with winw, height comparisons with winh */
 
     if (termflags & TERM_SHORT) {
-	singlerefresh();
+	singlerefresh(tmpline, tmpll, tmpcs);
 	goto singlelineout;
     }
 
-    if (cs < 0) {
+    if (tmpcs < 0) {
 #ifdef DEBUG
 	fprintf(stderr, "BUG: negative cursor position\n");
 	fflush(stderr); 
 #endif
-	cs = 0;
+	tmpcs = 0;
     }
-    scs = line + cs;
+    scs = tmpline + tmpcs;
     numscrolls = 0;
 
 /* first, we generate the video line buffers so we know what to put on
@@ -414,9 +447,9 @@
 	*nbuf = (char *)zalloc(winw + 2);
 
     s = (unsigned char *)(nbuf[ln = 0] + lpromptw);
-    t = line;
+    t = tmpline;
     sen = (unsigned char *)(*nbuf + winw);
-    for (; t < line+ll; t++) {
+    for (; t < tmpline+tmpll; t++) {
 	if (t == scs)			/* if cursor is here, remember it */
 	    nvcs = s - (unsigned char *)(nbuf[nvln = ln]);
 
@@ -459,7 +492,7 @@
 	nvln++;
     }
 
-    if (t != line + ll)
+    if (t != tmpline + tmpll)
 	more_end = 1;
 
     if (statusline) {
@@ -646,6 +679,9 @@
 singlelineout:
     fflush(shout);		/* make sure everything is written out */
 
+    if (tmpalloced)
+	zfree(tmpline, tmpll);
+
     /* if we have a new list showing, note it; if part of the list has been
     overwritten, redisplay it. */
     if (showinglist == -2 || (showinglist > 0 && showinglist < nlnct)) {
@@ -1082,7 +1118,7 @@
 
 /**/
 static void
-singlerefresh(void)
+singlerefresh(unsigned char *tmpline, int tmpll, int tmpcs)
 {
     char *vbuf, *vp,		/* video buffer and pointer    */
 	**qbuf,			/* tmp			       */
@@ -1093,19 +1129,19 @@
 
     nlnct = 1;
 /* generate the new line buffer completely */
-    for (vsiz = 1 + lpromptw, t0 = 0; t0 != ll; t0++, vsiz++)
-	if (line[t0] == '\t')
+    for (vsiz = 1 + lpromptw, t0 = 0; t0 != tmpll; t0++, vsiz++)
+	if (tmpline[t0] == '\t')
 	    vsiz = (vsiz | 7) + 1;
-	else if (icntrl(line[t0]))
+	else if (icntrl(tmpline[t0]))
 	    vsiz++;
     vbuf = (char *)zalloc(vsiz);
 
-    if (cs < 0) {
+    if (tmpcs < 0) {
 #ifdef DEBUG
 	fprintf(stderr, "BUG: negative cursor position\n");
 	fflush(stderr); 
 #endif
-	cs = 0;
+	tmpcs = 0;
     }
 
     /* only use last part of prompt */
@@ -1113,25 +1149,25 @@
     vbuf[lpromptw] = '\0';
     vp = vbuf + lpromptw;
 
-    for (t0 = 0; t0 != ll; t0++) {
-	if (line[t0] == '\t')
+    for (t0 = 0; t0 != tmpll; t0++) {
+	if (tmpline[t0] == '\t')
 	    for (*vp++ = ' '; (vp - vbuf) & 7; )
 		*vp++ = ' ';
-	else if (line[t0] == '\n') {
+	else if (tmpline[t0] == '\n') {
 	    *vp++ = '\\';
 	    *vp++ = 'n';
-	} else if (line[t0] == 0x7f) {
+	} else if (tmpline[t0] == 0x7f) {
 	    *vp++ = '^';
 	    *vp++ = '?';
-	} else if (icntrl(line[t0])) {
+	} else if (icntrl(tmpline[t0])) {
 	    *vp++ = '^';
-	    *vp++ = line[t0] | '@';
+	    *vp++ = tmpline[t0] | '@';
 	} else
-	    *vp++ = line[t0];
-	if (t0 == cs)
+	    *vp++ = tmpline[t0];
+	if (t0 == tmpcs)
 	    nvcs = vp - vbuf - 1;
     }
-    if (t0 == cs)
+    if (t0 == tmpcs)
 	nvcs = vp - vbuf;
     *vp = '\0';
 
Index: Doc/Zsh/zle.yo
===================================================================
RCS file: /cvsroot/zsh/zsh/Doc/Zsh/zle.yo,v
retrieving revision 1.23
diff -u -r1.23 zle.yo
--- Doc/Zsh/zle.yo	1 Jul 2002 09:54:48 -0000	1.23
+++ Doc/Zsh/zle.yo	1 Jul 2002 11:05:24 -0000
@@ -662,6 +662,22 @@
 contains the contents of the lines before the one the cursor is
 currently in.
 )
+vindex(PREDISPLAY)
+item(tt(PREDISPLAY) (scalar))(
+Text to be displayed before the start of the editable text buffer.  This
+does not have to be a complete line; to display a complete line, a newline
+must be appended explicitly.  Note that the text survives between calls to zle
+and hence must be removed explicitly by assigning an empty value to the
+parameter.
+)
+vindex(POSTDISPLAY)
+item(tt(POSTDISPLAY) (scalar))(
+Text to be displayed after the end of the editable text buffer.  This
+does not have to be a complete line; to display a complete line, a newline
+must be prepended explicitly.  Note that the text survives between calls to
+zle and hence must be removed explicitly by assigning an empty value to the
+parameter.
+)
 vindex(RBUFFER)
 item(tt(RBUFFER) (scalar))(
 The part of the buffer that lies to the right of the cursor position.

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


**********************************************************************
The information transmitted is intended only for the person or
entity to which it is addressed and may contain confidential 
and/or privileged material. 
Any review, retransmission, dissemination or other use of, or
taking of any action in reliance upon, this information by 
persons or entities other than the intended recipient is 
prohibited.  
If you received this in error, please contact the sender and 
delete the material from any computer.
**********************************************************************


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: PATCH: $PREDISPLAY/$POSTDISPLAY
  2002-07-01 11:23     ` PATCH: $PREDISPLAY/$POSTDISPLAY Peter Stephenson
@ 2002-07-04  7:57       ` Sven Wischnowsky
  2002-07-04  9:57         ` Peter Stephenson
  0 siblings, 1 reply; 6+ messages in thread
From: Sven Wischnowsky @ 2002-07-04  7:57 UTC (permalink / raw)
  To: zsh-workers


Peter Stephenson wrote:

> ...
> 
> Note the way these parameters survive across invocations of zle.  This
> was simply because it was the most natural way of writing it.  We can
> make zleread() reinitialise them if it seems preferable.

I can see that it's more powerful, but it's really rather irritating,
isn't it? Especially since you can't make them go away from the
(normal) command line. Although with well-behaved widgets...

> Hmm, it would be nice to get bits of these optionally in inverse video.
> In fact, it would be nice to get a lot of other stuff such as the region
> between point and mark in inverse video.

In any kind of mode/colour. It could also be nice if we could restrict
the allowed movement-range in recursive edits (kind of like
narrow-to-region in emacs). And then allow to display more than two
extra strings at any place (I don't have an example in mind, though).

Ultimately, this could get us to enable highlighting of command lines,
as requested several times already. But that's a whole lot more
complicated, obviously.

But it's a nice patch, Peter.


Bye
  Sven

-- 
Sven Wischnowsky                          wischnow@berkom.de


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: PATCH: $PREDISPLAY/$POSTDISPLAY
  2002-07-04  7:57       ` Sven Wischnowsky
@ 2002-07-04  9:57         ` Peter Stephenson
  0 siblings, 0 replies; 6+ messages in thread
From: Peter Stephenson @ 2002-07-04  9:57 UTC (permalink / raw)
  To: Zsh hackers list

Sven Wischnowsky wrote:
> Peter Stephenson wrote:
> > Note the way these parameters survive across invocations of zle.  This
> > was simply because it was the most natural way of writing it.  We can
> > make zleread() reinitialise them if it seems preferable.
> 
> I can see that it's more powerful, but it's really rather irritating,
> isn't it? Especially since you can't make them go away from the
> (normal) command line. Although with well-behaved widgets...

Yes, I came to that conclusion, too.

> It could also be nice if we could restrict
> the allowed movement-range in recursive edits (kind of like
> narrow-to-region in emacs).

You can already do this bit, with the same limitation as the Emacs
function, i.e. the editable region is always the bit in the middle.

narrow-to-region() {
  # Restrict the start of the editable line to the position
  # between MARK and CURSOR

  local lbuffer rbuffer
  integer start=$MARK end=$CURSOR swap

  if (( start == end )); then
    return 1
  elif (( start > end )); then
    swap=start
    start=end
    end=swap
  fi

  (( end++ ))

  PREDISPLAY=${BUFFER[1,start]}
  lbuffer=$PREDISPLAY
  POSTDISPLAY=${BUFFER[end,-1]}
  rbuffer=$POSTDISPLAY
  BUFFER=${BUFFER[start+1,end-1]}
  if (( swap )); then 
    CURSOR=0 
    MARK=${#BUFFER}
  else
    MARK=0
    CURSOR=${#BUFFER}
  fi

  zle recursive-edit

  PREDISPLAY=
  POSTDISPLAY=
  LBUFFER="$lbuffer$LBUFFER"
  RBUFFER="$RBUFFER$rbuffer"
}

Obviously, you can easily modify this to make the text outside the
region display as "...", and so on.  You might want to make accept-line
a dummy during this and define a widget `widen' which calls
.accept-line, or make the normal accept-line set a flag that
restrict-start will propagate the accept-line upwards, or something.

To be consistent, it would be better not to assume PREDISPLAY and
POSTDISPLAY are empty, i.e. we should really set predisplay=$PREDISPLAY,
PREDISPLAY+=... before and PREDISPLAY=$predisplay after, but I got bored
at that point.

There could be lurking off-by-one errors, but it seemed to do roughly
what I expected.

Index: Doc/Zsh/zle.yo
===================================================================
RCS file: /cvsroot/zsh/zsh/Doc/Zsh/zle.yo,v
retrieving revision 1.24
diff -u -r1.24 zle.yo
--- Doc/Zsh/zle.yo	1 Jul 2002 16:50:43 -0000	1.24
+++ Doc/Zsh/zle.yo	4 Jul 2002 09:28:36 -0000
@@ -666,17 +666,15 @@
 item(tt(PREDISPLAY) (scalar))(
 Text to be displayed before the start of the editable text buffer.  This
 does not have to be a complete line; to display a complete line, a newline
-must be appended explicitly.  Note that the text survives between calls to zle
-and hence must be removed explicitly by assigning an empty value to the
-parameter.
+must be appended explicitly.    The text is reset on each new invocation
+(but not recursive invocation) of zle.
 )
 vindex(POSTDISPLAY)
 item(tt(POSTDISPLAY) (scalar))(
 Text to be displayed after the end of the editable text buffer.  This
 does not have to be a complete line; to display a complete line, a newline
-must be prepended explicitly.  Note that the text survives between calls to
-zle and hence must be removed explicitly by assigning an empty value to the
-parameter.
+must be prepended explicitly.  The text is reset on each new invocation
+(but not recursive invocation) of zle.
 )
 vindex(RBUFFER)
 item(tt(RBUFFER) (scalar))(
Index: Src/Zle/zle_main.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Zle/zle_main.c,v
retrieving revision 1.25
diff -u -r1.25 zle_main.c
--- Src/Zle/zle_main.c	1 Jul 2002 09:54:48 -0000	1.25
+++ Src/Zle/zle_main.c	4 Jul 2002 09:28:36 -0000
@@ -752,6 +752,7 @@
     pmpt_attr = txtchange;
     rpromptbuf = promptexpand(rp, 1, NULL, NULL);
     rpmpt_attr = txtchange;
+    free_prepostdisplay();
 
     zlereadflags = flags;
     histline = curhist;
Index: Src/Zle/zle_params.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Zle/zle_params.c,v
retrieving revision 1.5
diff -u -r1.5 zle_params.c
--- Src/Zle/zle_params.c	1 Jul 2002 16:50:43 -0000	1.5
+++ Src/Zle/zle_params.c	4 Jul 2002 09:28:36 -0000
@@ -516,3 +516,13 @@
 {
     return get_prepost(postdisplay, postdisplaylen);
 }
+
+/**/
+void
+free_prepostdisplay(void)
+{
+    if (predisplaylen)
+	set_prepost(&predisplay, &predisplaylen, NULL);
+    if (postdisplaylen)
+	set_prepost(&postdisplay, &postdisplaylen, NULL);
+}

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


**********************************************************************
The information transmitted is intended only for the person or
entity to which it is addressed and may contain confidential 
and/or privileged material. 
Any review, retransmission, dissemination or other use of, or
taking of any action in reliance upon, this information by 
persons or entities other than the intended recipient is 
prohibited.  
If you received this in error, please contact the sender and 
delete the material from any computer.
**********************************************************************


^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2002-07-04 10:02 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2002-06-30 20:53 PATCH: zle recursive editing Peter Stephenson
2002-06-30 21:19 ` Bart Schaefer
2002-07-01  9:52   ` Peter Stephenson
2002-07-01 11:23     ` PATCH: $PREDISPLAY/$POSTDISPLAY Peter Stephenson
2002-07-04  7:57       ` Sven Wischnowsky
2002-07-04  9:57         ` Peter Stephenson

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).