* a calculator for zsh-4.x
@ 2003-01-29 16:03 Clifford Caoile
2003-01-29 16:18 ` Phil Pennock
2003-01-29 19:43 ` kwong
0 siblings, 2 replies; 3+ messages in thread
From: Clifford Caoile @ 2003-01-29 16:03 UTC (permalink / raw)
To: zsh-users
Dear zsh-users:
In my excitement over zsh-4.x, I bring to you some sample calculator
functions to enhance your zsh experience. However, I haven't searched this
mailing list for similar subjects at all, and I am ignorant of this mailing
list past posts. Perhaps I'm duplicating suggestions here, but I hope this
is helpful.
I don't know about you, but I reach for zsh when I want to calculate
addition in hexadecimal (like whenever I have read a linux ksymoops
message). With the following .zshrc snippet, my shell becomes a
convenient-to-type calculator:
Code Snippet:
# -----------------------------------------------------------------begin
# calculator - paste me into your .zshrc
# ----------------------------------------------------------------------
# Here are some quick calculators that output in integer
# hexadecimal, decimal, and binary.
zcalc () { print $(( ans = ${1:-ans} )) }
zcalch () { print $(( [#16] ans = ${1:-ans} )) }
zcalcd () { print $(( [#10] ans = ${1:-ans} )) }
zcalco () { print $(( [#8] ans = ${1:-ans} )) }
zcalcb () { print $(( [#2] ans = ${1:-ans} )) }
# A key binding that will allow you to quickly get into zcalc
bindkey -s '\C-xd' "zcalc \'"
# this last one lets you calculate the ascii value of a single character
zcalcasc () { print $(( [#16] ans = ##${1:-ans} )) }
# -------------------------------------------------------------------end
Usage example:
%> zcalc '23 / 3' # integer math
7
%> zcalc '23.0 / 3' # forced floating point math
7.666666666666667
%> zcalc '23 % 3' # programmers love to mod
2
%> zcalc 'ans + 2' # your last answer is still there
4
%> zcalc '0xCD & 0x23' # uh, why are you bit masking?
1
%> zcalc '0xCD | 0x23' # or you like "or"?
239
%> zcalcb ; zcalco ; zcalcd ; zcalch # I want it in a readable format
please.
2#11101111
8#357
239
16#EF
%> zcalch '2#11101111 & 0211' # mix the input bases
16#C3
Recommended convenience feature:
Try the bindkey Control-X d. It's a quick jump into zsh-based calculator.
You only need to worry about adding the last quotation mark. (Ugh)
Call for advice:
Actually, I'm most interested in enhancing the bindkey definition. Placing
just one quotation mark on the command line seems to be sloppy. I wish I was
able to set the position of the cursor at any arbitrary point of the
inserted string, just like in emacs. Anybody have any suggestions? I guess
this is just the whole reason for posting...
Instead of putting this in my .zshrc file, is it better to make it a zsh
module?
HTH, HAND
,-~-.
< ^ ; ~, Clifford Escobar CAOILE (aka "Piyo-kun")
(_ _,
J~~> _.___...:.__..__.: __.:_. .:_.__::_..:._::._... _____ p(^_^)q
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: a calculator for zsh-4.x
2003-01-29 16:03 a calculator for zsh-4.x Clifford Caoile
@ 2003-01-29 16:18 ` Phil Pennock
2003-01-29 19:43 ` kwong
1 sibling, 0 replies; 3+ messages in thread
From: Phil Pennock @ 2003-01-29 16:18 UTC (permalink / raw)
To: Clifford Caoile; +Cc: zsh-users
On 2003-01-30 at 01:03 +0900, Clifford Caoile wrote:
> I don't know about you, but I reach for zsh when I want to calculate
> addition in hexadecimal
I also tend to do this; messing around with graphical calculators is a
pain.
> # -----------------------------------------------------------------begin
> # calculator - paste me into your .zshrc
> # ----------------------------------------------------------------------
>
> # Here are some quick calculators that output in integer
> # hexadecimal, decimal, and binary.
> zcalc () { print $(( ans = ${1:-ans} )) }
> zcalch () { print $(( [#16] ans = ${1:-ans} )) }
> zcalcd () { print $(( [#10] ans = ${1:-ans} )) }
> zcalco () { print $(( [#8] ans = ${1:-ans} )) }
> zcalcb () { print $(( [#2] ans = ${1:-ans} )) }
>
> # A key binding that will allow you to quickly get into zcalc
> bindkey -s '\C-xd' "zcalc \'"
>
> # this last one lets you calculate the ascii value of a single character
> zcalcasc () { print $(( [#16] ans = ##${1:-ans} )) }
> # -------------------------------------------------------------------end
I like it. :^) But with one modification: for the first five
functions, replace ${1:-ans} with ${@:-ans} so that the quotes are
unnecessary unless you're using characters interpreted by the shell.
> Call for advice:
> Actually, I'm most interested in enhancing the bindkey definition. Placing
> just one quotation mark on the command line seems to be sloppy.
I just bypass the need for the bindkey for most of the things I'd use
these functions for.
Thanks,
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: a calculator for zsh-4.x
2003-01-29 16:03 a calculator for zsh-4.x Clifford Caoile
2003-01-29 16:18 ` Phil Pennock
@ 2003-01-29 19:43 ` kwong
1 sibling, 0 replies; 3+ messages in thread
From: kwong @ 2003-01-29 19:43 UTC (permalink / raw)
To: Clifford Caoile; +Cc: zsh-users
Dear Clifford,
I think your snippet is very clever and provides a quick and
easy way to get a good calculator.
My own solution to the need of a calculator is less elegant
but seems to be a more general and flexible solution. It is
extendable (if you know how to tamper with the perl code)
and has many more capabilities. It also can be used
anywhere perl is available, not necessarily under zsh.
I have been using this calculator for a while and it seems
to be quite all right (I won't guarantee there are no bugs).
It took me a while to get it into this shape, but if any one
wants to try it out, it won't require much effort.
To enable the calculator
------------------------
1. Cut out the perl code attached below, save it in
a file, e.g. called "pcal.s" (or any other name you
like) somewhere that your $PATH can access.
2. chmod +x pcal.s (to make the file executable).
3. Put "alias pcal='noglob pcal.s' in your .zshrc.
This line makes it possible to type commands such as
pcal 3*7
without using quotes around 3*7.
DISCLAIMER
----------
The program was written strictly for personal use and is
definitely not of industrial production grade. My
real-work load simply won't allow me to spend too much
time on such "frivolous" activities :(. There is not much
error checking or error recovery for user input. So use
the program at your OWN RISK :)
Also the code includes more stuffs than are really needed
right now - I put those in there with the intention of
future extension - I simply never could find time for that.
You can use the calculator in two modes:
Non-interactive
---------------
pcal 3 * 7 # spaces are optional
pcal 3 * (sin(3.14159/4) + 1.2)
pcal dh 12345 # convert dec -> hex
pcal hd 123ab # convert hex -> dec
pcal h 123a + abc # compute in hex
pcal b 110111 * 1111 # compute in binary
When used in this mode, the answer is not saved in
a variable as nicely as Clifford's zcal function. If you
really want it that way, you have to do a little more work.
Instead of defining pcal an alias to pcal.s as before, you
can define (put these lines in .zshrc)
pcal.s2() {
if [[ -n "$*" ]]
then
_x=`echo $* | sed "s/ans/$ans/g"`
ans=`noglob pcal.s $_x`; print ans = $ans
else
pcal.s2
fi
}
alias pcal='noglob pcal.s2'
But if you need the answer for further computation, you may
as well use the interactive mode.
Interactive - just type
-----------
pcal
You will see a prompt
pcal>
Then you can type in any math expression or any expression
allowable in the non-Interactive mode. In addition, you can
assign values or results of expressions to variables
* You have to use the perl convention of starting
* a variable name with $ - sorry, if you are not a perl
* fan, you may not like this. If you are as lazy as
* I am, you may type ; instead of $.
pcal> $a = 123 + 5
'0 = 128
pcal> ;a + 789
'1 = 917
pcal> ;a + '1
'2 = 1045
pcal> h abc * a
If you assign a value to a variable, you can use the
variable in subsequent calculations. If you do not assign
an expression to a variable, you can still use the answer in
subsequent calculations using the symbol '0, '1, etc.
Use any one of theses commands to quit: q x quit exit
There are other features hidden in the code. Explore as you
want to. Let me know if you find any bugs.
One thing you may object about using such a perl script
instead of directly using zsh functions is that once you get
into the interactive mode you lose the capability of command
line editing. This is true but if you are a more advanced
perl user who can add command line capability in your perl
script, e.g. using the CPAN ReadLine module.
mk kwong
********************************************************************
Code Snippet:
#!/usr/bin/env perl
# ----------------------------------------------------------------------
# perl calculator - paste me into a file called e.g. pc.s in your $PATH
# chmod +x pc.s
# put "alias pc='noglob pc.s' in .zshrc
# ----------------------------------------------------------------------
sub isint { $_[0] =~ /^\s*[+-]?\d*\s*$/; }
sub isfloat { $_[0] =~ /^\s*[+-]?(\d*\.\d+)([eE]+[+-]*\d+)*\s*$/; }
sub isefloat { my ($n) = &abs($_[0]);
&isfloat($n) && ($n > 1e8 || $n < 1e-8); }
sub isstr { !&isint($_[0]) && !&isfloat($_[0]); }
sub round { for (@_) { $_ = sprintf("%.0f",$_); } @_; }
sub roundf { my ($p) = &isefloat($_[0])? "e" : "f";
sprintf("%.$_[1]$p",$_[0]); }
sub floor { for $n (@_) { if ($n =~ /\./) {
if ($n >= 0 || $n =~ /\.0*$/) { $n =~ s/\.\d*//; }
else { $n =~ s/\.\d*//; $n--; } } }
@_; }
sub ceil { for $n (@_) { ($n) = &floor(-$n); $n = -$n;} @_; }
sub nsort { return sort {$a <=> $b} @_; }
sub pr {
## In my own environment, I have command line editing capability
## REPLACE by subroutine to enable command line editing, e.g. using
## the CPAN modules of Term::ReadLine and Term::ReadLine::Gnu
print $prompt; $_ = <>;
}
####################################################################
($_p = $0) =~ s/.*\///;
$_argvs = join(" ",@ARGV);
if (@ARGV) {
$non_int = 1; #// non-interactive
$_ = join(" ",@ARGV);
proc();
exit;
}
$prompt ||= "pcal> ";
$quit = '(q|x|quit|exit)';
####################################################################
sub loop {
pr(); # $_nopr = 1 means no initial prompt
while (1) {
if (/^$quit$/) { exit; }
exec "$_p $_argvs" if /^\.{1,}$/; # ... new version of program
proc();
pr();
} }
####################################################################
$_debug = 1;
$_OFMT = "%.6g";
loop();
####################################################################
sub proc { $_a = $_s = 0;
$_db && db('=xxx,');
if (/^db$/) { $_db = !$_db; return; } # toggle debug
if (/^fmt\s*(\d+)$/) { $_OFMT = "%.$1g"; return; } # float output format
if (/^,\s*(.*)/) { system($1); return; } # , shell
if (/^\.+$/) { system "pe"; exit; } # . rerun
if (/^\. \s*(.*)/) { eval($1); return; } # . perl
s/\`\`/\$_ans[0]/; s/\`(\d+)/\$_ans[$1]/g; # `` => $_ans
s/;(\w)/\$\1/g; # ;a => $a
$_db && db('=yyy,');
if (/^\.(\w+)$/) { $_ = "print join(\", \",\@$1)"; # .a => print @a
eval; print ",\n"; return; }
if (/^\/(\w+)$/) { eval "\%_a = \%$1"; # /a => print %a
for $_i (sort(keys(%_a))) { print "$_i => $_a{$_i}, "; }
print "\n"; return; }
math();
}
sub math { #// math mode
s/\'\'/$_ans[$_nans]/g;
s/\'(\d+)/$_ans[$1]/g;
s/\'([a-zA-Z])/\$$1/g;
if (s/^hd\s*//) { print " " x 4; #// hex to dec
if (/[^\w\s]/) { s/(\w+)/h2d($1)/ge; print eval, "\n"; }
else { for $_x (split(/\s+/)) { $_x and print h2d($_x)," "; } print "\n"; } return; }
if (s/^dh\s*//) { print " " x 4; #// dec to hex
if (/[^\w\s]/) { print d2h(eval), "\n"; }
else { for $_x (split(/\s+/)) { $_x and print d2h($_x)," "; } print "\n"; } return; }
if (s/^bd\s*//) { print " " x 4; #// bin to dec
if (/[^\w\s]/) { s/(\w+)/b2d($1)/ge; print eval, "\n"; }
else { for $_x (split(/\s+/)) { $_x and print b2d($_x)," "; } print "\n"; } return; }
if (s/^db\s*//) { print " " x 4; #// dec to bin
if (/[^\w\s]/) { print d2b(eval), "\n"; }
else { for $_x (split(/\s+/)) { $_x and print d2b($_x)," "; } print "\n"; } return; }
if (s/^hb\s*//) { print " " x 4; #// hex to bin
if (/[^\w\s]/) { s/(\w+)/h2d($1)/ge; print d2b(eval), "\n"; }
else { for $_x (split(/\s+/)) { $_x and print d2b(h2d($_x))," "; } print "\n"; } return; }
if (s/^bh\s*//) { print " " x 4; #// bin to hex
if (/[^\w\s]/) { s/(\w+)/b2d($1)/ge; print d2h(eval), "\n"; }
else { for $_x (split(/\s+/)) { $_x and print d2h(b2d($_x))," "; } print "\n"; } return; }
if (s/^h\s+//) { #// hex calculations
s/(\w+)/h2d($1)/ge;
$_ans = d2h(eval);
push(@_ans,$_ans); $_nans = $#_ans;
$non_int or print "'$_nans = "; print $_ans, "\n";
$non_int or print "\n";
return; }
if (s/^b\s+//) { #// bin calculations
s/(\w+)/b2d($1)/ge;
$_ans = d2b(eval);
push(@_ans,$_ans); $_nans = $#_ans;
$non_int or print "'$_nans = "; print $_ans, "\n";
$non_int or print "\n";
return; }
if (/;\s*$/) { eval; return; }
eval "\$_ans = $_";
push(@_ans,$_ans); $_nans = $#_ans;
$non_int or print "'$_nans = "; print $_ans, "\n";
$non_int or print "\n";
}
sub d2h($) { local($a,$b,$c) = $_[0]; while ($a > 0) { $c = $a % 16; $a = ($a-$c)/16;
if ($c == 10) { $c = "a"; } elsif ($c == 11) { $c = "b"; }
elsif ($c == 12) { $c = "c"; } elsif ($c == 13) { $c = "d"; }
elsif ($c == 14) { $c = "e"; } elsif ($c == 15) { $c = "f"; }
$b = "$c$b" } return "$b"; }
sub h2d($) { hex($_[0]); }
sub d2b($) { local($a,$b,$c) = $_[0]; while ($a > 0) { $c = $a % 2; $a = ($a-$c)/2;
$b = "$c$b" } return "$b"; }
sub b2d($) { local($a,$b) = $_[0]; while ($a =~ s/.//) { $b = 2*$b + $&; } return $b; }
# -----------------------------------------------------------------end
>
> Dear zsh-users:
>
> In my excitement over zsh-4.x, I bring to you some sample calculator
> functions to enhance your zsh experience. However, I haven't searched this
> mailing list for similar subjects at all, and I am ignorant of this mailing
> list past posts. Perhaps I'm duplicating suggestions here, but I hope this
> is helpful.
>
> I don't know about you, but I reach for zsh when I want to calculate
> addition in hexadecimal (like whenever I have read a linux ksymoops
> message). With the following .zshrc snippet, my shell becomes a
> convenient-to-type calculator:
>
> Code Snippet:
> # -----------------------------------------------------------------begin
> # calculator - paste me into your .zshrc
> # ----------------------------------------------------------------------
>
> # Here are some quick calculators that output in integer
> # hexadecimal, decimal, and binary.
> zcalc () { print $(( ans = ${1:-ans} )) }
> zcalch () { print $(( [#16] ans = ${1:-ans} )) }
> zcalcd () { print $(( [#10] ans = ${1:-ans} )) }
> zcalco () { print $(( [#8] ans = ${1:-ans} )) }
> zcalcb () { print $(( [#2] ans = ${1:-ans} )) }
>
> # A key binding that will allow you to quickly get into zcalc
> bindkey -s '\C-xd' "zcalc \'"
>
> [... omitted]
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2003-01-29 19:45 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-01-29 16:03 a calculator for zsh-4.x Clifford Caoile
2003-01-29 16:18 ` Phil Pennock
2003-01-29 19:43 ` kwong
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).