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

PATCH: CHR$(foo) => ${(#)foo}



I've always been frustrated that zsh couldn't turn an integer into a
character without some horrible hack like

  eval chr=\$\'\\x${foo[-2,-1]}\'

which assumes $foo contains a hex number.

There are lots of ways of turning a number into a character, but few the
other way round, none that I'm aware of convenient for use in general
substitutions.  This adds the (#) expansion flag to do that.  I couldn't
think of a better syntax, certainly none I was likely to remember.

I deliberately haven't tried to anything more sophisticated than the
printf %c form here.  Handling of multibyte character sets in parameter
substitution will need a lot more thought to do consistently and it
seemed pointless to jump the gun.  (A first guess of how to do would be
that, if the parameter expansion is in multibyte mode, which we don't
have yet, we treat the expression as a Unicode character and output the
same effect as the \U........ print escape.)

Index: Doc/Zsh/expn.yo
===================================================================
RCS file: /cvsroot/zsh/zsh/Doc/Zsh/expn.yo,v
retrieving revision 1.56
diff -u -r1.56 expn.yo
--- Doc/Zsh/expn.yo	23 Sep 2005 17:03:17 -0000	1.56
+++ Doc/Zsh/expn.yo	1 Nov 2005 14:25:34 -0000
@@ -632,6 +632,12 @@
 following flags are supported:
 
 startitem()
+item(tt(#))(
+Evaluate the parameter as a numeric expression, joining together array
+elements if necessary, and output the character corresponding to the
+resulting integer.  Note that this form is entirely distinct from
+use of the tt(#) without parentheses.
+)
 item(tt(%))(
 Expand all tt(%) escapes in the resulting words in the same way as in in
 prompts (see noderef(Prompt Expansion)). If this flag is given twice,
Index: Src/subst.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/subst.c,v
retrieving revision 1.42
diff -u -r1.42 subst.c
--- Src/subst.c	13 Oct 2005 16:30:14 -0000	1.42
+++ Src/subst.c	1 Nov 2005 14:25:35 -0000
@@ -915,6 +915,10 @@
      */
     int globsubst = isset(GLOBSUBST);
     /*
+     * Indicates ${(#)...}.
+     */
+    int evalchar = 0;
+    /*
      * Indicates ${#pm}, massaged by whichlen which is set by
      * the (c), (w), and (W) flags to indicate how we take the length.
      */
@@ -1320,6 +1324,11 @@
 		    unique = 1;
 		    break;
 
+		case '#':
+		case Pound:
+		    evalchar = 1;
+		    break;
+
 		default:
 		  flagerr:
 		    zerr("error in flags", NULL, 0);
@@ -2233,6 +2242,27 @@
     }
     if (errflag)
 	return NULL;
+    if (evalchar) {
+	/*
+	 * Evaluate the value numerically and output the result as
+	 * a character.
+	 *
+	 * Note this doesn't yet handle Unicode or multibyte characters:
+	 * that will need handling more generally probably by
+	 * an additional flag of some sort.
+	 */
+	zlong ires;
+
+	if (isarr) {
+	    val = sepjoin(aval, sep, 1);
+	    isarr = 0;
+	}
+	ires = mathevali(val);
+	if (errflag)
+	    return NULL;
+	val = zhalloc(2);
+	sprintf(val, "%c", (int)ires);
+    }
     /*
      * This handles taking a length with ${#foo} and variations.
      * TODO: again. one might naively have thought this had the

-- 
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