From 0cba681c99393653d6593c9b2ed6d476794313b1 Mon Sep 17 00:00:00 2001 From: Thomas von Dein Date: Mon, 13 Apr 2020 18:13:15 +0200 Subject: [PATCH] fixed x, added checks, enhanced doc --- README.md | 86 ++++++++++++++++++++++++++++++++++++++++++++++++------- rpnc | 33 +++++++++++++++++++-- 2 files changed, 106 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 4e2b14e..f825992 100644 --- a/README.md +++ b/README.md @@ -136,6 +136,31 @@ sub stack of before. Every operation which modifies the stack can be reversed by entering the u command. There's only one level of undo and no redo. +## Functions + +You can define functions anytime directly on the cli or in a file called +`~/.rpnc`. A function has a name (which must not collide with existing +functions and commands) and a body of commands. + +Example: + + f res2vcc 1.22 R1 R2 + R2 / 1 + * + +Which calculates: + + (((R1 + R2) / R2) + 1) * 1.22 = ?? + +To use it later, just enter the variables into the stack followed by the +function name: + + 470 + 220 + res2vcc + +You can also put the function definition in the config file +`~/.rpnc`. Empty lines and lines beginning with `#` will be ignored. + + ## Using STDIN via a PIPE If the commandline includes any operator, commands will be read from @@ -150,18 +175,22 @@ Examples: Both commands will print 4 to STDOUT. + ## Complete list of all supported commands: -* c clear stack +### Stack Management + * s show the stack -* d toggle debugging (current setting: 0) -* r reverse the stack -* R rotate the stack -* ( enter collect mode -* ) leave collect mode -* u undo last operation -* q finish (C-d works as well) -* ? print help +* ss show the whole stack +* sc clear stack +* scx clear last stack element +* sr reverse the stack +* srt rotate the stack + +## Configuration + +* td toggle debugging (-d) +* ts toggle display of the stack (-n) ## Supported mathematical operators: @@ -171,10 +200,47 @@ Both commands will print 4 to STDOUT. * * multiply * ^ expotentiate * % percent +* %+ add percent +* %- substract percent +* %d percentual difference * & bitwise AND * | bitwise OR * x bitwise XOR -* V pull root (2nd if stack==1) +* m median +* a average +* v pull root (2nd if stack==1) +* ( enter collect mode +* ) leave collect mode + +## Register Commands + +* r put element into register +* rc clear register +* rcx clear last register element + +## Various Commands + +* u undo last operation +* q finish (C-d works as well) +* h show history of past operations +* ? print help + +## Converters + +* tl gallons to liters +* tk miles to kilometers +* tm yards to meters +* tc inches to centimeters +* tkb bytes to kilobytes +* tmb bytes to megabytes +* tgb bytes to gigabytes +* ttb bytes to terabytes + +## Function Comands + +* f NAME CODE define a functions (see ab above) +* fs show list of defined functions + ## Copyleft diff --git a/rpnc b/rpnc index 3424361..e56ceb3 100755 --- a/rpnc +++ b/rpnc @@ -106,6 +106,7 @@ my %func = ( return 0; } }, + '%d' => sub { # percentual difference if (scalar @_ == 2) { @@ -118,6 +119,7 @@ my %func = ( return 0; } }, + '%+' => sub { # Y + (X $ of Y) if (scalar @_ == 2) { @@ -130,6 +132,7 @@ my %func = ( return 0; } }, + '%-' => sub { # Y - (X $ of Y) if (scalar @_ == 2) { @@ -142,6 +145,7 @@ my %func = ( return 0; } }, + 'v' => sub { if (scalar @_ == 2) { my ($a, $b) = @_; @@ -152,11 +156,13 @@ my %func = ( return "$a ** (1 / 2)"; } }, + 'pr' => sub { # parallel resistance, maybe add ~/.rpncrc support # where to add such custom functions... return "1 / (" . join(' + ', map { "1 / $_"} @_) . ")"; }, + 'm' => sub { # median if (scalar @_ >= 2) { @@ -175,10 +181,12 @@ my %func = ( undo(); return 0; } }, + 'a' => sub { # average return "(" . join(' + ', @_) . ") / " . scalar @_; }, + # converters: # gallons to liters 'tl' => sub { return $_[-1] * 3.785 }, @@ -193,6 +201,9 @@ my %func = ( 'tmb' => sub { return $_[-1] / 1000 / 1000}, 'tgb' => sub { return $_[-1] / 1000 / 1000 / 1000 }, 'ttb' => sub { return $_[-1] / 1000 / 1000 / 1000 / 1000 }, + + # alias + 'x' => sub { return join "^", @_ }, ); # math constants, always upper case letters, usable via eval{} @@ -540,6 +551,21 @@ sub defun { my $code = shift; my ($op, $name, @tokens) = split /\s\s*/, $code; + if ($name !~ /^[a-zA-Z0-9_]+$/) { + print "invalid function name (a-z0-9_)!\n"; + return; + } + + if (grep {$name eq $_} keys %commands) { + print "reserved function name (command)!\n"; + return; + } + + if (grep {$name eq $_} keys %func) { + print "reserved function name (function)!\n"; + return; + } + $custom{$name} = "@tokens"; $func{$name} = sub { @@ -549,13 +575,14 @@ sub defun { # replace N1..NN with actual args my @body; foreach my $item (@tokens) { - if ($item =~ /^N(\d+)$/) { - my $i = $1; + if ($item =~ /^([A-Z])(\d+)$/) { + my $letter = $1; + my $i = $2; if ($i <= $max) { push @body, $args[$i-1]; } else { - print "undefined variable N$i!\n"; + print "undefined variable ${letter}${i}!\n"; push @body, 0; } }