This plugin is a processor that takes a Reverse Polish Notation expression as input and inserts the results in the current buffer. It operates in two different ways.
1. As a completion source for the nvim-cmp completion plugin
If nvim-cmp is installed, then while an RPN expression is being typed, two completion options will be presented. For example, when typing:
1 2 3 ** +
nvim-cmp will present these two strings that can be insert in the expression's place:
9
1 2 3 ** + == 9
This is the only method that works when nvim-cmp is not installed. The :RPN command's various syntaxes are as follows:
-
:RPN- replace the current line's RPN expression with its result. The entire line will be treated as the RPN expression. Any text that is not a valid number or operator will cause an error. -
:<range>RPN- replace the selected lines with the result of their concatenated RPN expression. The selection will always be treated as a linewise selection. The entire concatenation will be treated as the RPN expression. Any text that is not a valid number or operator will cause an error. -
:RPN <expression>- treat all arguments as an RPN expression and insert the result in a new line above the current line.
Adding the bang operator, ie. :RPN!, to any of the syntaxes above will cause the expression to be inserted along with the result, like so:
30 rad sin == 0.5
Use mappings like the following examples to call :RPN in Normal or Visual mode.
" Vimscript example
nnoremap <F7> :RPN<CR>
nnoremap <S-F7> :RPN!<CR>
xnoremap <F7> :<C-U>'<,'>RPN<CR>
xnoremap <S-F7> :<C-U>'<,'>RPN!<CR>-- Lua example
vim.api.nvim_set_keymap("n", "<F7>", ":RPN<CR>", {noremap=true})
vim.api.nvim_set_keymap("n", "<S-F7>", ":RPN!<CR>", {noremap=true})
vim.api.nvim_set_keymap("x", "<F7>", ":<C-U>'<,'>RPN<CR>", {noremap=true})
vim.api.nvim_set_keymap("x", "<S-F7>", ":<C-U>'<,'>RPN!<CR>", {noremap=true})Use your favorite plugin manager. If you don't have one, try one of these: vim-pathogen, vim-plug, Packer.nvim or lazy.nvim. Alternatively, you can use packages and submodules, as Greg Hurrell (@wincent) describes in his excellent Youtube video: Vim screencast #75: Plugin managers
There is no setup required specifically for this plugin; however, when using it as a source for nvim-cmp, you need to add rpncalc to its list of sources in your nvim-cmp setup function call. The following snippet shows how to do that.
require'cmp'.setup {
sources = {
{ name = 'rpncalc' } -- Add this to the sources list.
}
}RPN is a mathematical notation in which an operator follows its operand(s). This means there is no need for parentheses. Here are some examples, comparing algebraic notation to RPN.
| Algebraic | This plugin's version of RPN |
|---|---|
73 37 + |
|
462 11 / |
|
1 2 + 3 4 * - 5 ** abs |
|
1 3 sqrt / atan deg or 3 sqrt \ atan deg
|
|
| For |
7 sqrt 4 / sto 2 ** 48 * 98 rcl 4 ** / - |
| Euler's Identity: |
e i pi * ** 1 +Round-off error gives an answer that's almost exact: |
An RPN expression is a space-delimited list of tokens. Reading the tokens from left to right, numbers are placed on a stack. The top four numbers are labeled
Expression: 12 2 -3 ** +
Tokens: 12 2 -3 ** +
| Token | Stack Before | Stack After Pop | Calculation | Stack After Push |
|---|---|---|---|---|
12 |
empty | n/a | n/a | |
2 |
n/a | n/a |
|
|
-3 |
|
n/a | n/a |
|
** |
|
|
||
+ |
|
empty |
|
Operands can take on any of these forms:
- Decimal (base 10): integer
42, float-3.14, or scientific notation6.02e23 - Binary (base 2):
0bprefix, followed by digits0and1. - Hexadecimal (base 16):
0xprefix, followed by digits0-9or lettersa-forA-F. - Complex: an ordered pair of numbers in any of the prior formats. For example,
1.2e-4,0x43equates to0.00012+67iin decimal notation.
Most of the operators will work on complex numbers. The following Wikipedia pages were used as reference for some of the more arcane complex number calculations: logarithms, exponentiation, ordinary trig functions, inverse trig functions, hyperbolic trig functions, inverse hyperbolic trig functions. Where the complete answer is an infinte number of values, only the principal value is given.
The Domain column in the following table indicates the types of numbers that are valid for each operator. The possible domains are:
- ℕatural - non-negative integers
- ℝeal - real numbers (includes ℕatural)
- ℂomplex - complex numbers (includes ℝeal and ℕatural)
| Operator | Function | Domain |
|---|---|---|
|
Basic Arithmetic |
||
| + | Addition | ℂomplex |
| - | Subtraction | ℂomplex |
| * | Multiplication | ℂomplex |
| / | Division | ℂomplex |
| div | Integer division | ℂomplex |
| % | Modulus (not well-defined for negatives) | ℝeal |
| abs | Absolute value | ℂomplex |
| arg | Argument (the angle between $X$ and the positive real axis) | ℂomplex |
| chs | Change Sign (negation) | ℂomplex |
|
Powers & Logs |
||
| ** | Raise |
ℂomplex |
| \ | Reciprocal | ℂomplex |
| exp | Raise e to the |
ℂomplex |
| ln | Natural Log of |
ℂomplex |
| log | Log (base 10) of |
ℂomplex |
| log2 | Log (base 2) of |
ℂomplex |
| sqrt | Square Root | ℂomplex |
|
Trigonometry Variations are: a... for inverse and ...h for hyperbolic |
||
| sin | Sine, asin, sinh, asinh | ℂomplex |
| cos | Cosine, acos, cosh, acosh | ℂomplex |
| tan | Tangent, atan, tanh, atanh | ℂomplex |
| csc | Cosecant, acsc, csch, acsch | ℂomplex |
| sec | Secant, asec, sech, asech | ℂomplex |
| cot | Cotangent, acot, coth, acoth | ℂomplex |
|
Rounding |
||
| floor | Round down to nearest integer | ℂomplex |
| ceil | Round up to nearest integer | ℂomplex |
| round | Round up or down to nearest integer | ℂomplex |
| trunc | Round toward zero to nearest integer | ℂomplex |
|
Bitwise Non-integer operands will be truncated. |
||
| & | AND |
ℕatural |
| | | OR |
ℕatural |
| ^ | XOR |
ℕatural |
| ~ | NOT All bits are flipped, and a two's complement conversion of the result is displayed. |
ℕatural |
| << | Left Shift ( |
ℕatural |
| >> | Right Shift ( |
ℕatural |
|
Statistics |
||
| ! | Factorial of |
ℕatural |
| perm | Permutation of |
ℕatural |
| comb | Combination of |
ℕatural |
| n | Sample size (size of the stack) | ℂomplex |
| mean | Average of all numbers on the stack. |
ℂomplex |
| sum | Sum of all numbers on the stack |
ℂomplex |
| ssq | Sum of squares of all numbers on the stack |
ℂomplex |
| std | Sample standard deviation of all numbers on the stack |
ℝeal |
|
Miscellaneous |
||
| hrs | Convert ( |
ℝeal |
| hms | Convert |
ℝeal |
| gcd | Greatest Common Divisor of |
ℕatural |
| lcm | Least Common Multiple of |
ℕatural |
| dec | Print result in decimal (base 10) | ℂomplex |
| hex | Print result in hexadecimal (base 16) |
ℂomplex |
| bin | Print result in binary (base 2) |
ℂomplex |
|
as opposed to |
||
|
Constants |
||
| pi | Ratio of a circle's circumference to its diameter |
ℝeal |
| e | Euler's number |
ℝeal |
| phi | The golden ratio |
ℝeal |
| i | The imaginary unit number |
ℂomplex |
|
Memory and Stack Manipulation |
||
| sto | Store the value of |
ℂomplex |
| rcl | Recall the value in memory to the stack | ℂomplex |
| m+ | Add |
ℂomplex |
| m- | Subtract |
ℂomplex |
| xy | Swap |
ℂomplex |
| x | Place the value of |
ℂomplex |
| drop | Remove |
ℂomplex |
The author of this plugin makes no warranties about the completeness, reliability or accuracy of this calculator. Any action you take upon the results you get from it is strictly at your own risk. The author will not be liable for any losses and/or damages in connection with the use of this calculator.
This was mainly an exercise to learn lua, and to write a Neovim plugin by porting my prior Ruby and Erlang rpn calculators. It's quite possible that computational errors made their way in, despite all efforts to ensure the plugin's accuracy. If you spot any errors, or have suggestions for improvements, new operators, etc., create an issue or a pull request.
Finally, I don't know how useful some of the complex number functions are. It was a fun exercise implementing them, but was it just that - an exercise? Leave a comment if you know of any real-world use (pun intended) for perhaps, the inverse hyperbolic cotangent of a complex number.