I've been mildly irritated by that lack of a calculator that I liked. This sort of thing is a matter of taste, of course, and I doubt very many peoples' tastes will exactly track mine. But on those rare occasions when I want to do a little arithmetic, I haven't found a calculator that I really enjoyed using. I've periodically dreamed of writing one, but somehow never got around to it; partially because I didn't have a vision of a user interface that _really_ appealed to me, and partly because something I need so rarely, I didn't feel like investing a massive amount of time in U-I coding. Last night I got an idea, and it came out so simple and clean that I had to try it out. I really, really like the result. I'm thinking about how to extend it; right now I'm considering what sort of stack ops to add, and how to rig easy interaction with external programs. But right now it's at a special state where the genuine Fun With Perl factor seems to be at a local maximum: there's so little perl doing so much of the basic functionality; that ratio will probably drop steeply as soon as I touch it again. So I attach the first prototype. -Bennett
#!/usr/bin/perl -w use strict; use Getopt::Long; my $linemode = 0; my $syntax = "syntax: $0 [--[no]linemode]\n"; GetOptions("linemode!" => \$linemode) || die "syntax"; $| = 1; my $cd = "\e[J"; # clear to end of screen my $ce = "\e[K"; # clear to end of line my $ho = "\e[H"; # go home my @s; my $done = 0; while (1) { if ($linemode) { print "@{[reverse @s]} " if @s; } else { print $ho; print $_,$ce,"\n" for reverse @s; print $cd; } pop @s if @s and $s[-1] =~ /^Unknown character: /; if ($done) { print "\n" if $linemode; exit 0; } $_ = <>; while (length) { next if s/^\s+//; if (s/^0[0-9a-fx]+//) { unshift @s, oct($1); next; } if (s/^(-?\d+(?:\.\d+)?)// or s/^(-?\.\d+)//) { unshift @s, $1; next; } if (s/^\+//) { splice @s, 0, 2, $s[1]+$s[0]; next; } if (s/^\*//) { splice @s, 0, 2, $s[1]*$s[0]; next; } if (s/^\-//) { splice @s, 0, 2, $s[1]-$s[0]; next; } if (s/^\///) { splice @s, 0, 2, $s[1]/$s[0]; next; } if (s/^\^//) { splice @s, 0, 2, $s[1]**$s[0]; next; } if (s/^q//) { $done++; next; } push @s, "Unknown character: $_"; last; } }