fixed x, added checks, enhanced doc

This commit is contained in:
Thomas von Dein
2020-04-13 18:13:15 +02:00
parent 5dd2bf8f4f
commit 0cba681c99
2 changed files with 106 additions and 13 deletions

View File

@@ -136,6 +136,31 @@ sub stack of before.
Every operation which modifies the stack can be reversed by entering Every operation which modifies the stack can be reversed by entering
the <kbd>u</kbd> command. There's only one level of undo and no redo. the <kbd>u</kbd> 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 ## Using STDIN via a PIPE
If the commandline includes any operator, commands will be read from If the commandline includes any operator, commands will be read from
@@ -150,18 +175,22 @@ Examples:
Both commands will print 4 to STDOUT. Both commands will print 4 to STDOUT.
## Complete list of all supported commands: ## Complete list of all supported commands:
* <kbd>c</kbd> clear stack ### Stack Management
* <kbd>s</kbd> show the stack * <kbd>s</kbd> show the stack
* <kbd>d</kbd> toggle debugging (current setting: 0) * <kbd>ss</kbd> show the whole stack
* <kbd>r</kbd> reverse the stack * <kbd>sc</kbd> clear stack
* <kbd>R</kbd> rotate the stack * <kbd>scx</kbd> clear last stack element
* <kbd>(</kbd> enter collect mode * <kbd>sr</kbd> reverse the stack
* <kbd>)</kbd> leave collect mode * <kbd>srt</kbd> rotate the stack
* <kbd>u</kbd> undo last operation
* <kbd>q</kbd> finish (<kbd>C-d</kbd> works as well) ## Configuration
* <kbd>?</kbd> print help
* <kbd>td</kbd> toggle debugging (-d)
* <kbd>ts</kbd> toggle display of the stack (-n)
## Supported mathematical operators: ## Supported mathematical operators:
@@ -171,10 +200,47 @@ Both commands will print 4 to STDOUT.
* <kbd>*</kbd> multiply * <kbd>*</kbd> multiply
* <kbd>^</kbd> expotentiate * <kbd>^</kbd> expotentiate
* <kbd>%</kbd> percent * <kbd>%</kbd> percent
* <kbd>%+</kbd> add percent
* <kbd>%-</kbd> substract percent
* <kbd>%d</kbd> percentual difference
* <kbd>&</kbd> bitwise AND * <kbd>&</kbd> bitwise AND
* <kbd>|</kbd> bitwise OR * <kbd>|</kbd> bitwise OR
* <kbd>x</kbd> bitwise XOR * <kbd>x</kbd> bitwise XOR
* <kbd>V</kbd> pull root (2nd if stack==1) * <kbd>m</kbd> median
* <kbd>a</kbd> average
* <kbd>v</kbd> pull root (2nd if stack==1)
* <kbd>(</kbd> enter collect mode
* <kbd>)</kbd> leave collect mode
## Register Commands
* <kbd>r</kbd> put element into register
* <kbd>rc</kbd> clear register
* <kbd>rcx</kbd> clear last register element
## Various Commands
* <kbd>u</kbd> undo last operation
* <kbd>q</kbd> finish (<kbd>C-d</kbd> works as well)
* <kbd>h</kbd> show history of past operations
* <kbd>?</kbd> print help
## Converters
* <kbd>tl</kbd> gallons to liters
* <kbd>tk</kbd> miles to kilometers
* <kbd>tm</kbd> yards to meters
* <kbd>tc</kbd> inches to centimeters
* <kbd>tkb</kbd> bytes to kilobytes
* <kbd>tmb</kbd> bytes to megabytes
* <kbd>tgb</kbd> bytes to gigabytes
* <kbd>ttb</kbd> bytes to terabytes
## Function Comands
* <kbd>f NAME CODE</kbd> define a functions (see ab above)
* <kbd>fs</kbd> show list of defined functions
## Copyleft ## Copyleft

33
rpnc
View File

@@ -106,6 +106,7 @@ my %func = (
return 0; return 0;
} }
}, },
'%d' => sub { '%d' => sub {
# percentual difference # percentual difference
if (scalar @_ == 2) { if (scalar @_ == 2) {
@@ -118,6 +119,7 @@ my %func = (
return 0; return 0;
} }
}, },
'%+' => sub { '%+' => sub {
# Y + (X $ of Y) # Y + (X $ of Y)
if (scalar @_ == 2) { if (scalar @_ == 2) {
@@ -130,6 +132,7 @@ my %func = (
return 0; return 0;
} }
}, },
'%-' => sub { '%-' => sub {
# Y - (X $ of Y) # Y - (X $ of Y)
if (scalar @_ == 2) { if (scalar @_ == 2) {
@@ -142,6 +145,7 @@ my %func = (
return 0; return 0;
} }
}, },
'v' => sub { 'v' => sub {
if (scalar @_ == 2) { if (scalar @_ == 2) {
my ($a, $b) = @_; my ($a, $b) = @_;
@@ -152,11 +156,13 @@ my %func = (
return "$a ** (1 / 2)"; return "$a ** (1 / 2)";
} }
}, },
'pr' => sub { 'pr' => sub {
# parallel resistance, maybe add ~/.rpncrc support # parallel resistance, maybe add ~/.rpncrc support
# where to add such custom functions... # where to add such custom functions...
return "1 / (" . join(' + ', map { "1 / $_"} @_) . ")"; return "1 / (" . join(' + ', map { "1 / $_"} @_) . ")";
}, },
'm' => sub { 'm' => sub {
# median # median
if (scalar @_ >= 2) { if (scalar @_ >= 2) {
@@ -175,10 +181,12 @@ my %func = (
undo(); return 0; undo(); return 0;
} }
}, },
'a' => sub { 'a' => sub {
# average # average
return "(" . join(' + ', @_) . ") / " . scalar @_; return "(" . join(' + ', @_) . ") / " . scalar @_;
}, },
# converters: # converters:
# gallons to liters # gallons to liters
'tl' => sub { return $_[-1] * 3.785 }, 'tl' => sub { return $_[-1] * 3.785 },
@@ -193,6 +201,9 @@ my %func = (
'tmb' => sub { return $_[-1] / 1000 / 1000}, 'tmb' => sub { return $_[-1] / 1000 / 1000},
'tgb' => sub { return $_[-1] / 1000 / 1000 / 1000 }, 'tgb' => sub { return $_[-1] / 1000 / 1000 / 1000 },
'ttb' => sub { return $_[-1] / 1000 / 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{} # math constants, always upper case letters, usable via eval{}
@@ -540,6 +551,21 @@ sub defun {
my $code = shift; my $code = shift;
my ($op, $name, @tokens) = split /\s\s*/, $code; 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"; $custom{$name} = "@tokens";
$func{$name} = sub { $func{$name} = sub {
@@ -549,13 +575,14 @@ sub defun {
# replace N1..NN with actual args # replace N1..NN with actual args
my @body; my @body;
foreach my $item (@tokens) { foreach my $item (@tokens) {
if ($item =~ /^N(\d+)$/) { if ($item =~ /^([A-Z])(\d+)$/) {
my $i = $1; my $letter = $1;
my $i = $2;
if ($i <= $max) { if ($i <= $max) {
push @body, $args[$i-1]; push @body, $args[$i-1];
} }
else { else {
print "undefined variable N$i!\n"; print "undefined variable ${letter}${i}!\n";
push @body, 0; push @body, 0;
} }
} }