From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 21403 invoked from network); 25 Sep 1999 18:50:00 -0000 Received: from sunsite.auc.dk (130.225.51.30) by ns1.primenet.com.au with SMTP; 25 Sep 1999 18:50:00 -0000 Received: (qmail 11283 invoked by alias); 25 Sep 1999 18:49:09 -0000 Mailing-List: contact zsh-users-help@sunsite.auc.dk; run by ezmlm Precedence: bulk X-No-Archive: yes X-Seq: 2616 Received: (qmail 11265 invoked from network); 25 Sep 1999 18:49:07 -0000 From: "Bart Schaefer" Message-Id: <990925184831.ZM30850@candle.brasslantern.com> Date: Sat, 25 Sep 1999 18:48:31 +0000 X-Mailer: Z-Mail (5.0.0 30July97) To: zsh-users@sunsite.auc.dk Subject: "cat -v" in zsh (and a minor bug) MIME-Version: 1.0 Content-Type: text/plain; charset=iso-8859-1 Content-Transfer-Encoding: 8bit A friend recently asked me how to get the equivalent of visible=$(echo "$string" | cat -v) without requiring the extra processes. Entirely coincidentally, a patch for 3.1.6 was just posted to make ${(V)var} return the value of $var in "visible" format; so after the next release, the following will be moot. However, there's a cute trick below that's of some interest; read on past the end of the function (the bug report is there too). In the meanwhile, or in 3.0.x, the following makes $visible from $string. # function string-to-visible { # emulate -LR zsh 2>/dev/null || emulate -R zsh && setopt localoptions # typeset string="$*" typeset a q z typeset -i i=0 typeset -i8 oct z=('' '') # Prepare for cute trick visible=() while (( i <= $#string )) do a="$string[i]" q='' if (( #a < 0 || #a > 127 )); then (( oct = #a & 127 )) q='M-' else (( oct = #a )) fi if (( oct < 32 )); then (( oct = oct + #\A - 1 )) q="$q^" # Replace ^ with C- for emacs-style fi if (( $#q )); then a=${(e)q::='${(pj:'"$q\\${oct#*#}"':)z}'} # Cute trick! fi visible[i]=$a (( ++i )) done visible="${(j::)visible}" # } About that trick ... a few weeks ago Sven posted a patch for ${(%)var} to cause prompt expansion to happen on $var. Someone remarked that it would be nice to have "print" command escapes interpreted similarly. That's what the cute trick, above, accomplishes: The (p) flag causes print escapes to be recognized in the rest of the flags. The $z array provides two empty strings that can be joined. So the trick is to stick the value, in which you want print escapes expanded, between the colons in ${(pj::)z}. But parameter expansion doesn't happen inside the flags of another expansion, so we have to construct the whole ${(pj:...:)z} string that we want as a new value, and then evaluate that with ${(e)...}. The rest of the function is just conversion of each ascii character to the appropriate octal value for "print" to turn into a printable character. The bug is demonstrated by: a='å' # That's meta-a, or 228 decimal (( #a == #\å )) || echo oops The problem is that #a is unsigned but #\a is signed, so for values above 127 decimal the #\a form returns a negative number. -- Bart Schaefer Brass Lantern Enterprises http://www.well.com/user/barts http://www.brasslantern.com