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

Re: pushing a string in the cut&paste stack



Peter Stephenson <pws@xxxxxxx> wrote:
> If you want to manipulate the editing stack (save the old value of the
> the cut buffer onto the kill ring in the way the kill commands do) you
> will need to use the array kill_ring.  See the function kill-word-match
> distributed with the shell for an example.  (One day I should make it so
> that copy-region-as-kill can take a string argument when called from an
> editor widget.)

Easy to do, and useful, so here it is.  Most of the changes in the
function are reindentation to the usual two spaces.

Index: Doc/Zsh/zle.yo
===================================================================
RCS file: /cvsroot/zsh/zsh/Doc/Zsh/zle.yo,v
retrieving revision 1.55
diff -u -r1.55 zle.yo
--- Doc/Zsh/zle.yo	10 Dec 2006 23:27:02 -0000	1.55
+++ Doc/Zsh/zle.yo	17 Apr 2007 13:28:15 -0000
@@ -663,7 +663,10 @@
 item(tt(CUTBUFFER) (scalar))(
 The last item to be cut using one of the `tt(kill-)' commands; the
 string which the next yank would insert in the line.  Later entries in
-the kill ring are in the array tt(killring).
+the kill ring are in the array tt(killring).  Note that the
+command `tt(zle copy-region-as-kill) var(string)' can be used to
+set the text of the cut buffer from a shell function and cycle the kill
+ring in the same way as interactively killing text.
 )
 vindex(HISTNO)
 item(tt(HISTNO) (integer))(
@@ -1296,6 +1299,11 @@
 tindex(copy-region-as-kill)
 item(tt(copy-region-as-kill) (ESC-W ESC-w) (unbound) (unbound))(
 Copy the area from the cursor to the mark to the kill buffer.
+
+If called from a ZLE widget function in the form `tt(zle
+copy-region-as-kill) var(string)' then var(string) will be taken as the
+text to copy to the kill buffer.  The cursor, the mark and the text on the
+command line are not used in this case.
 )
 tindex(copy-prev-word)
 item(tt(copy-prev-word) (ESC-^_) (unbound) (unbound))(
@@ -1498,8 +1506,8 @@
 )
 tindex(yank-pop)
 item(tt(yank-pop) (ESC-y) (unbound) (unbound))(
-Remove the text just yanked, rotate the kill-ring,
-and yank the new top.  Only works following
+Remove the text just yanked, rotate the kill-ring (the history of
+previously killed text) and yank the new top.  Only works following
 tt(yank) or tt(yank-pop).
 )
 tindex(vi-yank)
Index: Functions/Zle/backward-kill-word-match
===================================================================
RCS file: /cvsroot/zsh/zsh/Functions/Zle/backward-kill-word-match,v
retrieving revision 1.1
diff -u -r1.1 backward-kill-word-match
--- Functions/Zle/backward-kill-word-match	28 Mar 2003 11:34:30 -0000	1.1
+++ Functions/Zle/backward-kill-word-match	17 Apr 2007 13:28:15 -0000
@@ -8,29 +8,28 @@
 integer count=${NUMERIC:-1}
 
 if (( count < 0 )); then
-    (( NUMERIC = -count ))
-    zle ${WIDGET##backward-}
-    return
+  (( NUMERIC = -count ))
+  zle ${WIDGET##backward-}
+  return
 fi
 
 while (( count-- )); do
 
-    match-words-by-style
+  match-words-by-style
 
-    word="$matched_words[2]$matched_words[3]"
+  word="$matched_words[2]$matched_words[3]"
 
-    if [[ -n $word ]]; then
-	if [[ -n $done || $LASTWIDGET = *kill* ]]; then
-	    CUTBUFFER="$word$CUTBUFFER"
-	else
-	    killring=("$CUTBUFFER" "${(@)killring[1,-2]}")
-	    CUTBUFFER=$word
-	fi
-	LBUFFER=$matched_words[1]
+  if [[ -n $word ]]; then
+    if [[ -n $done || $LASTWIDGET = *kill* ]]; then
+      CUTBUFFER="$word$CUTBUFFER"
     else
-	return 1
+      zle copy-region-as-kill "$word"
     fi
-    done=1
+    LBUFFER=$matched_words[1]
+  else
+    return 1
+  fi
+  done=1
 done
 
 return 0
Index: Functions/Zle/delete-whole-word-match
===================================================================
RCS file: /cvsroot/zsh/zsh/Functions/Zle/delete-whole-word-match,v
retrieving revision 1.2
diff -u -r1.2 delete-whole-word-match
--- Functions/Zle/delete-whole-word-match	13 Oct 2003 17:23:15 -0000	1.2
+++ Functions/Zle/delete-whole-word-match	17 Apr 2007 13:28:15 -0000
@@ -49,8 +49,7 @@
   if [[ $LASTWIDGET = *kill* ]]; then
     CUTBUFFER="$CUTBUFFER$word"
   else
-    killring=("$CUTBUFFER" "${(@)killring[1,-2]}")
-    CUTBUFFER=$word
+    zle copy-region-as-kill "$word"
   fi
 fi
 BUFFER="${BUFFER[1,pos1]}${BUFFER[pos2,-1]}"
Index: Functions/Zle/kill-word-match
===================================================================
RCS file: /cvsroot/zsh/zsh/Functions/Zle/kill-word-match,v
retrieving revision 1.2
diff -u -r1.2 kill-word-match
--- Functions/Zle/kill-word-match	7 Jul 2003 14:43:24 -0000	1.2
+++ Functions/Zle/kill-word-match	17 Apr 2007 13:28:15 -0000
@@ -8,29 +8,27 @@
 integer count=${NUMERIC:-1}
 
 if (( count < 0 )); then
-    (( NUMERIC = -count ))
-    zle backward-$WIDGET
-    return
+  (( NUMERIC = -count ))
+  zle backward-$WIDGET
+  return
 fi
 
 while (( count-- )); do
+  match-words-by-style
 
-    match-words-by-style
+  word="${(j..)matched_words[4,5]}"
 
-    word="${(j..)matched_words[4,5]}"
-
-    if [[ -n $word ]]; then
-	if [[ -n $done || $LASTWIDGET = *kill* ]]; then
-	    CUTBUFFER="$CUTBUFFER$word"
-	else
-	    killring=("$CUTBUFFER" "${(@)killring[1,-2]}")
-	    CUTBUFFER=$word
-	fi
-	RBUFFER=${(j..)matched_words[6,7]}
+  if [[ -n $word ]]; then
+    if [[ -n $done || $LASTWIDGET = *kill* ]]; then
+      CUTBUFFER="$CUTBUFFER$word"
     else
-	return 1
+      zle copy-region-as-kill $word
     fi
-    done=1
+    RBUFFER=${(j..)matched_words[6,7]}
+  else
+    return 1
+  fi
+  done=1
 done
 
 return 0
Index: Src/Zle/zle_misc.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Zle/zle_misc.c,v
retrieving revision 1.41
diff -u -r1.41 zle_misc.c
--- Src/Zle/zle_misc.c	10 Sep 2006 18:10:49 -0000	1.41
+++ Src/Zle/zle_misc.c	17 Apr 2007 13:28:15 -0000
@@ -337,14 +337,21 @@
 
 /**/
 int
-copyregionaskill(UNUSED(char **args))
+copyregionaskill(char **args)
 {
-    if (mark > zlell)
-	mark = zlell;
-    if (mark > zlecs)
-	cut(zlecs, mark - zlecs, 0);
-    else
-	cut(mark, zlecs - mark, 1);
+    if (*args) {
+        int len;
+        ZLE_STRING_T line = stringaszleline(*args, 0, &len, NULL, NULL);
+	cuttext(line, len, -1);
+	free(line);
+    } else {
+	if (mark > zlell)
+	    mark = zlell;
+	if (mark > zlecs)
+	    cut(zlecs, mark - zlecs, 0);
+	else
+	    cut(mark, zlecs - mark, 1);
+    }
     return 0;
 }
 
Index: Src/Zle/zle_utils.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Zle/zle_utils.c,v
retrieving revision 1.41
diff -u -r1.41 zle_utils.c
--- Src/Zle/zle_utils.c	30 Oct 2006 14:13:39 -0000	1.41
+++ Src/Zle/zle_utils.c	17 Apr 2007 13:28:15 -0000
@@ -420,10 +420,35 @@
     shiftchars(i, ct);
 }
 
+
+/*
+ * Put the ct characters starting at zleline + i into the
+ * cutbuffer, circling the kill ring if necessary (it's
+ * not if we're dealing with vi buffers, which is detected
+ * internally).  The text is not removed from zleline.
+ *
+ * dir indicates how the text is to be added to the cutbuffer,
+ * if the cutbuffer wasn't zeroed (this depends on the last
+ * command being a kill).  If dir is 1, the new text goes
+ * to the front of the cut buffer.  If dir is -1, the cutbuffer
+ * is completely overwritten.
+ */
+
 /**/
 void
 cut(int i, int ct, int dir)
 {
+  cuttext(zleline + i, ct, dir);
+}
+
+/*
+ * As cut, but explicitly supply the text together with its length.
+ */
+
+/**/
+void
+cuttext(ZLE_STRING_T line, int ct, int dir)
+{
     if (!ct)
 	return;
 
@@ -434,7 +459,7 @@
 	if (!(zmod.flags & MOD_VIAPP) || !b->buf) {
 	    free(b->buf);
 	    b->buf = (ZLE_STRING_T)zalloc(ct * ZLE_CHAR_SIZE);
-	    ZS_memcpy(b->buf, zleline + i, ct);
+	    ZS_memcpy(b->buf, line, ct);
 	    b->len = ct;
 	    b->flags = vilinerange ? CUTBUFFER_LINE : 0;
 	} else {
@@ -448,7 +473,7 @@
 			* ZLE_CHAR_SIZE);
 	    if (b->flags & CUTBUFFER_LINE)
 		b->buf[len++] = ZWC('\n');
-	    ZS_memcpy(b->buf + len, zleline + i, ct);
+	    ZS_memcpy(b->buf + len, line, ct);
 	    b->len = len + ct;
 	}
 	return;
@@ -459,7 +484,7 @@
 	for(n=34; n>26; n--)
 	    vibuf[n] = vibuf[n-1];
 	vibuf[26].buf = (ZLE_STRING_T)zalloc(ct * ZLE_CHAR_SIZE);
-	ZS_memcpy(vibuf[26].buf, zleline + i, ct);
+	ZS_memcpy(vibuf[26].buf, line, ct);
 	vibuf[26].len = ct;
 	vibuf[26].flags = vilinerange ? CUTBUFFER_LINE : 0;
     }
@@ -467,7 +492,7 @@
 	cutbuf.buf = (ZLE_STRING_T)zalloc(ZLE_CHAR_SIZE);
 	cutbuf.buf[0] = ZWC('\0');
 	cutbuf.len = cutbuf.flags = 0;
-    } else if (!(lastcmd & ZLE_KILL)) {
+    } else if (!(lastcmd & ZLE_KILL) || dir < 0) {
 	Cutbuffer kptr;
 	if (!kring) {
 	    kringsize = KRINGCTDEF;
@@ -485,7 +510,7 @@
     if (dir) {
 	ZLE_STRING_T s = (ZLE_STRING_T)zalloc((cutbuf.len + ct)*ZLE_CHAR_SIZE);
 
-	ZS_memcpy(s, zleline + i, ct);
+	ZS_memcpy(s, line, ct);
 	ZS_memcpy(s + ct, cutbuf.buf, cutbuf.len);
 	free(cutbuf.buf);
 	cutbuf.buf = s;
@@ -493,7 +518,7 @@
     } else {
 	cutbuf.buf = realloc((char *)cutbuf.buf,
 			     (cutbuf.len + ct) * ZLE_CHAR_SIZE);
-	ZS_memcpy(cutbuf.buf + cutbuf.len, zleline + i, ct);
+	ZS_memcpy(cutbuf.buf + cutbuf.len, line, ct);
 	cutbuf.len += ct;
     }
     if(vilinerange)


-- 
Peter Stephenson <pws@xxxxxxx>                  Software Engineer
CSR PLC, Churchill House, Cambridge Business Park, Cowley Road
Cambridge, CB4 0WZ, UK                          Tel: +44 (0)1223 692070


To access the latest news from CSR copy this link into a web browser:  http://www.csr.com/email_sig.php

To get further information regarding CSR, please visit our Investor Relations page at http://ir.csr.com/csr/about/overview



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