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

PATCH: argument-base, insert-unicode-char



I was fiddling again.  This adds:

- The internal widget argument-base which takes the current prefix
  argument (or an explicit string if called from a function) and turns
  it into a base for use with a new prefix argument.  I could have
  implemented the other widget without argument-base but it seemed
  generally useful for the type of thing and it fits quite naturally
  into the existing system.

- The add-on widget insert-unicode-char which allows you to enter a
  Unicode character by its hex number.

Index: Doc/Zsh/contrib.yo
===================================================================
RCS file: /cvsroot/zsh/zsh/Doc/Zsh/contrib.yo,v
retrieving revision 1.52
diff -u -r1.52 contrib.yo
--- Doc/Zsh/contrib.yo	25 Oct 2005 22:50:47 -0000	1.52
+++ Doc/Zsh/contrib.yo	23 Nov 2005 14:06:53 -0000
@@ -693,6 +693,9 @@
 (together with a newline) to standard output.  Input is still read from
 keystrokes.
 
+See tt(insert-unicode-char) for an alternative way of inserting Unicode
+characters using their hexadecimal character number.
+
 The set of accented characters is reasonably complete up to Unicode
 character U+0180, the set of special characters less so.  However, it it
 is very sporadic from that point.  Adding new characters is easy,
@@ -917,6 +920,17 @@
 zle recursive-edit
 narrow-to-region -R state)
 )
+tindex(insert-unicode-char)
+item(tt(insert-unicode-char))(
+When first executed, the user inputs a set of hexadecimal digits.
+This is terminated with another call to tt(insert-unicode-char).
+The digits are then turned into the corresponding Unicode character.
+For example, if the widget is bound to tt(^XU), the character sequence
+`tt(^XU 4 c ^XU)' inserts tt(L) (Unicode U+004c).
+
+See tt(insert-composed-char) for a way of inserting characters
+using a two-character mnemonic.
+)
 tindex(predict-on)
 tindex(predict-off)
 item(tt(predict-on))(
Index: Doc/Zsh/zle.yo
===================================================================
RCS file: /cvsroot/zsh/zsh/Doc/Zsh/zle.yo,v
retrieving revision 1.47
diff -u -r1.47 zle.yo
--- Doc/Zsh/zle.yo	9 Sep 2005 11:48:28 -0000	1.47
+++ Doc/Zsh/zle.yo	23 Nov 2005 14:06:55 -0000
@@ -1519,6 +1519,23 @@
 universal-argument) var(num)', the numerical argument will be set to
 var(num); this is equivalent to `tt(NUMERIC=)var(num)'.
 )
+tindex(argument-base)
+item(tt(argument-base))(
+Use the existing numeric argument as a numeric base, which must be in the
+range 2 to 36 inclusive.  Subsequent use of tt(digit-argument) and
+tt(universal-argument) will input a new prefix in the given base.
+The usual hexadecimal convention is used: the letter tt(a) or tt(A)
+corresponds to 10, and so on.  Arguments in bases requiring digits from 10
+upwards are more conveniently input with tt(universal-argument), since
+tt(ESC-a) etc. are not usually bound to tt(digit-argument).
+
+The function can be used with a command argument inside a user-defined
+widget.  The following code sets the base to 16 and lets the user input a
+hexadecimal argument until a key out of the digit range is typed:
+
+example(zle argument-base 16
+zle universal-argument)
+)
 enditem()
 texinode(Completion)(Miscellaneous)(Arguments)(Zle Widgets)
 subsect(Completion)
Index: Functions/Zle/.distfiles
===================================================================
RCS file: /cvsroot/zsh/zsh/Functions/Zle/.distfiles,v
retrieving revision 1.18
diff -u -r1.18 .distfiles
--- Functions/Zle/.distfiles	22 Sep 2005 22:23:45 -0000	1.18
+++ Functions/Zle/.distfiles	23 Nov 2005 14:06:55 -0000
@@ -9,6 +9,7 @@
 history-pattern-search         history-search-end
 incarg                         incremental-complete-word
 insert-composed-char           insert-files
+insert-unicode-char
 keeper                         kill-word-match
 match-words-by-style           narrow-to-region
 narrow-to-region-invisible     predict-on
Index: Functions/Zle/insert-unicode-char
===================================================================
RCS file: Functions/Zle/insert-unicode-char
diff -N Functions/Zle/insert-unicode-char
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Functions/Zle/insert-unicode-char	23 Nov 2005 14:06:55 -0000
@@ -0,0 +1,17 @@
+# Make hex integers appear as 0x...
+setopt localoptions cbases
+
+if [[ $LASTWIDGET = insert-unicode-char ]]; then
+  # Second call; we should have a usable prefix.
+  # If we don't, give up.
+  (( ${+NUMERIC} )) || return 1
+  # Convert it back to hex, padded with zeroes to 8 digits plus the 0x...
+  local -i 16 -Z 10 arg=$NUMERIC
+  # ...and use print to turn this into a Unicode character.
+  LBUFFER+="$(print -n "\U${arg##0x}")"
+else
+  # Set the base to 16...
+  zle argument-base 16
+  # ...wait for user to type hex keys then call this widget again.
+  zle universal-argument
+fi
Index: Src/Zle/iwidgets.list
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Zle/iwidgets.list,v
retrieving revision 1.7
diff -u -r1.7 iwidgets.list
--- Src/Zle/iwidgets.list	7 Nov 2005 09:37:34 -0000	1.7
+++ Src/Zle/iwidgets.list	23 Nov 2005 14:06:55 -0000
@@ -13,6 +13,7 @@
 "accept-and-menu-complete", acceptandmenucomplete, ZLE_MENUCMP | ZLE_KEEPSUFFIX
 "accept-line", acceptline, 0
 "accept-line-and-down-history", acceptlineanddownhistory, 0
+"argument-base", argumentbase, ZLE_MENUCMP | ZLE_KEEPSUFFIX | ZLE_LASTCOL | ZLE_NOTCOMMAND
 "backward-char", backwardchar, 0
 "backward-delete-char", backwarddeletechar, ZLE_KEEPSUFFIX
 "backward-delete-word", backwarddeleteword, ZLE_KEEPSUFFIX
Index: Src/Zle/zle.h
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Zle/zle.h,v
retrieving revision 1.25
diff -u -r1.25 zle.h
--- Src/Zle/zle.h	15 Nov 2005 08:44:26 -0000	1.25
+++ Src/Zle/zle.h	23 Nov 2005 14:06:56 -0000
@@ -205,6 +205,7 @@
     int mult;		/* repeat count */
     int tmult;		/* repeat count actually being edited */
     int vibuf;		/* vi cut buffer */
+    int base;		/* numeric base for digit arguments (usually 10) */
 };
 
 #define MOD_MULT  (1<<0)   /* a repeat count has been selected */
Index: Src/Zle/zle_main.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Zle/zle_main.c,v
retrieving revision 1.80
diff -u -r1.80 zle_main.c
--- Src/Zle/zle_main.c	15 Nov 2005 08:44:28 -0000	1.80
+++ Src/Zle/zle_main.c	23 Nov 2005 14:06:57 -0000
@@ -1153,6 +1153,7 @@
     mp->mult = 1;
     mp->tmult = 1;
     mp->vibuf = 0;
+    mp->base = 10;
 }
 
 /* Reset command modifiers, unless the command just executed was a prefix. *
Index: Src/Zle/zle_misc.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Zle/zle_misc.c,v
retrieving revision 1.36
diff -u -r1.36 zle_misc.c
--- Src/Zle/zle_misc.c	15 Nov 2005 09:34:00 -0000	1.36
+++ Src/Zle/zle_misc.c	23 Nov 2005 14:06:58 -0000
@@ -518,12 +518,9 @@
 	return selfinsert(args);
 }
 
-/**/
-int
-digitargument(UNUSED(char **args))
+static int
+parsedigit(int inkey)
 {
-    int sign = (zmult < 0) ? -1 : 1;
-
 #ifdef MULTIBYTE_SUPPORT
     /*
      * It's too dangerous to allow metafied input.  See
@@ -531,23 +528,48 @@
      * of digits.  We are assuming ASCII is a subset of the multibyte
      * encoding.
      */
-    if (!idigit(lastchar))
-	return 1;
 #else
     /* allow metafied as well as ordinary digits */
-    if (!idigit(lastchar & 0x7f))
-	return 1;
+    inkey &= 0x7f;
 #endif
 
+    /* remember lastchar is not a wide character */
+    if (zmod.base > 10)
+    {
+	if (lastchar >= 'a' && lastchar < 'a' + zmod.base - 10)
+	    return lastchar - 'a' + 10;
+	else if (lastchar >= 'A' && lastchar < 'A' + zmod.base - 10)
+	    return lastchar - 'A' + 10;
+	else if (idigit(lastchar))
+	    return lastchar - '0';
+	else
+	    return -1;
+    }
+    else if (lastchar >= '0' && lastchar < '0' + zmod.base)
+	return lastchar - '0';
+    else
+	return -1;
+}
+
+/**/
+int
+digitargument(UNUSED(char **args))
+{
+    int sign = (zmult < 0) ? -1 : 1;
+    int newdigit = parsedigit(lastchar);
+
+    if (newdigit < 0)
+	return 1;
+
     if (!(zmod.flags & MOD_TMULT))
 	zmod.tmult = 0;
     if (zmod.flags & MOD_NEG) {
 	/* If we just had a negative argument, this is the digit, *
 	 * rather than the -1 assumed by negargument()            */
-	zmod.tmult = sign * (lastchar & 0xf);
+	zmod.tmult = sign * newdigit;
 	zmod.flags &= ~MOD_NEG;
     } else
-	zmod.tmult = zmod.tmult * 10 + sign * (lastchar & 0xf);
+	zmod.tmult = zmod.tmult * zmod.base + sign * newdigit;
     zmod.flags |= MOD_TMULT;
     prefixflag = 1;
     return 0;
@@ -594,12 +616,16 @@
 	if (gotk == '-' && !digcnt) {
 	    minus = -1;
 	    digcnt++;
-	} else if (idigit(gotk)) {
-	    pref = pref * 10 + (gotk & 0xf);
-	    digcnt++;
 	} else {
-	    ungetbyte(gotk);
-	    break;
+	    int newdigit = parsedigit(gotk);
+
+	    if (newdigit >= 0) {
+		pref = pref * zmod.base + newdigit;
+		digcnt++;
+	    } else {
+		ungetbyte(gotk);
+		break;
+	    }
 	}
     }
     if (digcnt)
@@ -611,6 +637,36 @@
     return 0;
 }
 
+/* Set the base for a digit argument. */
+
+/**/
+int
+argumentbase(char **args)
+{
+    int multbase;
+
+    if (*args)
+	multbase = (int)zstrtol(*args, NULL, 0);
+    else
+	multbase = zmod.mult;
+
+    if (multbase < 2 || multbase > ('9' - '0' + 1) + ('z' - 'a' + 1))
+	return 1;
+
+    zmod.base = multbase;
+
+    /* reset modifier, apart from base... */
+    zmod.flags = 0;
+    zmod.mult = 1;
+    zmod.tmult = 1;
+    zmod.vibuf = 0;
+
+    /* ...but indicate we are still operating on a prefix argument. */
+    prefixflag = 1;
+
+    return 0;
+}
+
 /**/
 int
 copyprevword(UNUSED(char **args))

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


This message has been scanned for viruses by BlackSpider MailControl - www.blackspider.com



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