X-Git-Url: http://git.shiar.net/descalc.git/blobdiff_plain/905da7ac2077425ebb7ed7507f2ae8d00f4a5beb:/sdc.pl..ce0d29d8a852b8bf7dcad717390a4ad8efb59263:/dct.pl diff --git a/sdc.pl b/dct.pl similarity index 75% rename from sdc.pl rename to dct.pl index f1692ed..f3cdcc9 100755 --- a/sdc.pl +++ b/dct.pl @@ -1,15 +1,24 @@ #!/usr/bin/perl -### SDC - small desktop calculator ### +# DCT - desktop calculator thingy + # reverse polish notition calculator using curses # by Shiar -# 1.01 06-18 - start -# 1.03 06-25 - +# 1.01 06-18 - start (curses, some basic commands) +# 1.02 06-20 - function keys select command/submenu from (sub)menu +# - backspace to undo last digit +# 1.03 06-25 - values displayable in arbitrary base +# - can enter fractions (.) and negative values (_) # 1.04 08-04 14:45 - error dialog (don't mess up screen) +# - manual command input using capital letters +# - ^L redraws screen +# pre 09-09 22:00 - overhaul in stack handling # 1.05 09-10 19:45 - hp48-like drop (backspace but not editing value) -# - argument checking +# - error on insufficient arguments for command # - command backspacing +# - some unit conversion (mostly lengths) from menu +# - q for sq(rt) (formerly quit, now only ^D/quit) # 1.06 09-15 23:10 - menu contents in module # - new commands: a?(sin|cos|tan)h, inv, !, rand # - x and v shortkeys @@ -17,6 +26,13 @@ # - action undo: last stack alteration can be undone # - enter on no value repeats last val on stack # - new commands: sr/sr, shortkeys ( ) +# 1.08 09-26 22:10 - additional digits were not correctly applied to negative values +# - negative numbers displayed correctly in different bases +# - second undo redoes +# - fixed % +# - stack command (cursor up) cycles through values in stack +# 09-27 00:57 - all key aliases moved to module DCT::Bindings +our $VERSION = 1.008; use strict; use warnings; @@ -24,7 +40,8 @@ use utf8; use Term::ReadKey; use Curses; -use SDC::Menu 1.006; +use DCT::Menu 1.006; +use DCT::Bindings 1.008; initscr; ReadMode 3; # cbreak mode @@ -33,107 +50,26 @@ END { endwin; } # restore terminal on quit -my $height = $LINES<3 ? 4 : $LINES-3; # stack depth (lines of stack plus one) -my $width = $COLS || 42; # limit value precision, stetch menu - my %val = qw(i 0 frac 0); # i, frac my @stack; my %var; -my @menu; -my $menumin; + my %set = ( - base => 10, + base => 10, # decimal; set using commands bin/oct/dec/hex/base numb => 0, # fixed scientific engineering card => 1, # degrees radians grades coord => 0, # cartesian polar spherical complex => 0, # real complex - menushow => 12, + + height => $LINES<3 ? 4 : $LINES-3, # stack depth (lines of stack plus one) + width => $COLS || 42, # limit value precision, stetch menu + menushow => 12, # menu items to show simultaneously ); # %set -@menu = @{$menus[0]}; -$menumin = 0; - -my %falias = ( - "\033" => 0, # esc - "\033\117\120" => 1, # f1 - "\033\133\061\061\176" => 1, # f1 - "\033\133\061\062\176" => 2, # f2 - "\033\133\061\063\176" => 3, # f3 - "\033\133\061\064\176" => 4, # f4 - "\033\117\121" => 2, # f2 - "\033\117\122" => 3, # f3 - "\033\117\123" => 4, # f4 - "\033\133\061\065\176" => 5, # f5 - "\033\133\061\067\176" => 6, # f6 - "\033\133\061\070\176" => 7, # f7 - "\033\133\061\071\176" => 8, # f8 - "\033\133\062\060\176" => 9, # f9 - "\033\133\062\061\176" => 10, # f10 - "\033\133\062\063\176" => 11, # f11/F1 - "\033\133\062\064\176" => 12, # f12/F2 - "\033\133\062\065\176" => 13, # F3 - "\033\133\062\066\176" => 14, # F4 - "\033\133\062\070\176" => 15, # F5 - "\033\133\062\071\176" => 16, # F6 - "\033\133\063\061\176" => 17, # F7 - "\033\133\063\062\176" => 18, # F8 - "\033\133\063\063\176" => 19, # F9 - "\033\133\063\064\176" => 20, # F10 - "\033\133\062\063\073\062\176" => 21, # F11 - "\033\133\062\064\073\062\176" => 22, # F12 -); # %falias - -my %alias = ( - chr 4 => 'quit', # ^D - chr 9 => 'more', # tab - '_' => 'chs', # change sign; 48: y - 'e' => 'eex', # exponent; 48: z - "\033\133\062\176" => 'eex', # ins - "\033\133\063\176" => "clear", # del - chr 127 => 'drop', # backspace - chr 8 => 'drop', # backspace - chr 13 => 'enter', # enter - ' ' => 'enter', # space - "\014" => 'refresh', # ^L -# "\033\133\110" => 'refresh', # home - -# "\033\133\101" => '', # up; 48: k (stack) - "\033\133\104" => 'undo', # left; 48: p (picture) -# "\033\133\102" => '', # down; 48: q (view) - "\033\133\103" => 'swap', # right; 48: r (swap) - - '&' => 'and', - '|' => 'or', - '#' => 'xor', - '~' => 'not', - '(' => 'sl', - ')' => 'sr', - - "s" => "sin", - "\033s" => "asin", - "c" => "cos", - "\033c" => "acos", - "t" => "tan", - "\033t" => "atan", - "l" => "log", - "\033l" => "alog", - "n" => "ln", - "\033n" => "exp", - "q" => "sq", - "\033q" => "sqrt", - "x" => "^", - "\033x" => "xroot", - "\033^" => "xroot", - "v" => "inv", -); # %alias - -=cut -HP48 keys: - S T U V W X - - sin cos tan sqrt ^ 1/x - < asin acos atan sq alog exp - > [a] ∫ ∑ xroot log ln -=cut +#%alias = (' '=>'enter', "\004"=>'quit', 'q'=>'quit') unless %alias; # rudimentary defaults + +my @menu = @{$menus[0]}; +my $menumin = 0; my %action = ( 'more' => [-1, sub { @@ -151,7 +87,16 @@ my %action = ( %val = (i=>undef, frac=>0); }], # duplication +# 'undo' => [0, sub {@stack = @{ $var{undo} }}], # undo + 'undo' => [0, sub {($var{undo}, @stack) = ([@stack], @{ $var{undo} }) }], # undo 'swap' => [1, sub {@stack[0, 1] = @stack[1, 0]}], # swap x<->y + 'stack'=> [0, sub { + $var{stackpos} = 0 unless $var{stackpos}; # initialize + $var{stackpos} %= @stack; # cycle + $val{i} = $stack[$var{stackpos}++]; + }], # stack + + 'version' => [0, sub{error("Desktop Calculator Thingy $VERSION by Shiar")}], # version '=' => [1, sub {$var{a} = $stack[0]}], # copy '?' => [1, sub {$var{a} = shift @stack}], # assign @@ -189,7 +134,7 @@ my %action = ( 'acosh'=> [1, sub {$stack[0] = log( sqrt($stack[0]**2-1)+$stack[0] )}], # inverse hyperbolic cosine 'atanh'=> [1, sub {$stack[0] = log( (1+$stack[0]) / (1-$stack[0]) )/2}], # inverse hyperbolic tangent - '%' => [2, sub {$stack[0] /= shift @stack}], # percentage + '%' => [2, sub {$stack[0] = shift(@stack)/$stack[0]}], # percentage '%ch' => [2, sub {$val{i} = 100*(shift(@stack)-$val{i})/$val{i}}], # percentage change '%t' => [2, sub {$val{i} = 100*$val{i}/shift(@stack)}], # percentage total @@ -221,8 +166,6 @@ my %action = ( '!' => [1, sub {local $_ = $stack[0]; $stack[0] *= $_ while --$_>1}], # factor 'rand' => [0, sub {unshift @stack, rand}], # random value <1 - - 'undo' => [0, sub {@stack = @{ $var{undo} }}], # undo ); # %action my %unit; @@ -271,11 +214,14 @@ sub showval($$) { return '' unless defined $val; return $val if $base==10; + my $sign = $val<0; + $val = abs $val; my $int = int $val; my $frac = $val-$int; my $exp = 0; my $txt = ''; + while ($int>$base**10) { $int /= $base; $exp++; @@ -287,13 +233,14 @@ sub showval($$) { } # integer part $txt .= '.' if $frac>0; - for (my $i = 0; length $txt<$width-2 && $frac>0; $i++) { + for (my $i = 0; length $txt<$set{width}-2 && $frac>0; $i++) { $frac *= $base; my $char = int $frac; $frac -= $char; $txt .= $char<10 ? $char : chr($char+55); } # fraction part + $txt = "-".$txt if $sign; $txt .= 'e'.showval($exp, $base) if $exp; return $txt; @@ -301,18 +248,18 @@ sub showval($$) { sub showstack() { for (0..@stack-1) { - addstr($height-$_, 1, "$_: ".showval($stack[$_], $set{base})); + addstr($set{height}-$_, 1, "$_: ".showval($stack[$_], $set{base})); clrtoeol; } # show stack - clrtoeol($height-$#stack-1, 1); + clrtoeol($set{height}-$#stack-1, 1); } # showstack sub showmenu() { - clrtoeol($height+2, 1); + clrtoeol($set{height}+2, 1); my $nr = 0; for (grep exists $menu[$_], $menumin+1..$menumin+$set{menushow}) { my $sub = (my $s = $menu[$_]) =~ s/>\d+$//; - addstr($height+2, $width/$set{menushow}*($nr++), $_); + addstr($set{height}+2, $set{width}/$set{menushow}*($nr++), $_); attron(A_REVERSE); addstr($s); attroff(A_REVERSE); @@ -325,10 +272,10 @@ DRAW: clear; showmenu(); showstack(); -addstr($height+1, 0, "> "); # prompt +addstr($set{height}+1, 0, "> "); # prompt while (1) { - addstr($height+1, 2, showval($val{i}, $set{base})); + addstr($set{height}+1, 2, showval($val{i}, $set{base})); addstr('_'.$val{unit}{name}) if exists $val{unit}; addstr($val{bla}) if exists $val{bla}; clrtoeol; @@ -374,6 +321,7 @@ while (1) { elsif (/^\d$/) { $val{i} = 0 unless defined $val{i}; + $_ = -$_ if $val{i}<0; $val{i} = ($val{frac} *= 10) ? $val{i}+$_/$val{frac} : $val{i}*10+$_; } elsif ($_ eq '.') { @@ -427,7 +375,7 @@ while (1) { }} # conversion else { - error("* error: ".join(' ', map ord, split //, $_)." *"); + error("* unrecognised command: ".join(' ', map ord, split //, $_)." *"); goto DRAW; # screen messed up } # error } # input loop