• Stars
    star
    350
  • Rank 121,229 (Top 3 %)
  • Language
    C
  • License
    BSD 2-Clause "Sim...
  • Created over 7 years ago
  • Updated about 3 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Command-line, stack-based calculator with postfix notation

Clac

A command line, stack-based calculator with postfix notation that displays the stack contents at all times. As you type, the stack changes are reflected immediately.

clac in action

In a stack-based postfix calculator, entering a number pushes it on a stack, and arithmetic operations pop their arguments from the stack and push the result. As all the operations take a fix number of arguments, there's no room for ambiguity: parenthesis and operator precedence are not needed. Postfix notation is also known as reverse Polish notation, or RPN.

Why?

I like Forth and other stack based, concatenative languages, and I've used the dc calculator a lot. Once I got used to dc, other calculators seemed to be less powerful. While it has been extremely useful for me, I've always found the UI a bit lacking. That's why I decided to try this idea of an always-visible stack with realtime updates.

Installation

Download the latest release or check the available packages. You can also compile the source code in the master branch.

Install clac into /usr/local/bin with the following command:

$ make install

You can use make PREFIX=/some/other/directory install if you wish to use a different destination. If you want to remove clac from your system, use make uninstall.

Commands

When a command requires an argument, it pops a value from the stack. If the stack is empty, a zero is provided instead. In the descriptions below, the top of the stack (and thus the first value popped) is represented by the letter a, while the second value popped is represented by the letter b. For example, if the stack is composed of the number 1, 2 and 3 (with 3 at the top of the stack), when we describe the sum then a will be 3 and b will be 2. It is important to note that subtraction and division invert the order of the arguments before performing the operation: with 1, 2 and 3 in the stack, when you type - it will pop the values 3 and 2 and push the result of 2 - 3. This is in the tradition of other postfix calculators and programming languages.

Here's a description of the available commands:

Arithmetic operations

+ Pop two values a and b and push the result of a + b.

- Pop two values a and b and push the result of b - a.

* Pop two values a and b and push the result of a * b.

/ Pop two values a and b and push the result of b / a.

Modulo operation

% Pop two values a and b and push the remainder of the Euclidean division of b by a.

Exponentiation

^ Pop two values a and b and push the result of b ^ a.

Logarithm

ln Pop the value a and push its natural logarithm.

log Pop the value a and push its logarithm to base 10.

Factorial

! Pop the value a and push its factorial.

Trigonometry

sin Pop the value a and push its sine.

cos Pop the value a and push its cosine.

tan Pop the value a and push its tangent.

asin Pop the value a and push its arc sine.

acos Pop the value a and push its arc cosine.

atan Pop the value a and push its arc tangent.

atan2 Pop two values a and b and push the arc tangent of b / a, using the signs of a and b to determine the quadrant.

Error function

erf Pop the value a and push its error function.

Summation

sum Pop all the values in the stack and push their sum.

add Pop the value a and remove that many items from the stack. Push their sum.

Rounding

ceil Pop the value a and push the smallest integer value greater than or equal to a.

floor Pop the value a and push the largest integer value less than or equal to a.

round Pop the value a and push the integer value closest to a.

Absolute value

abs Pop the value a and push the non-negative value of a.

Stack manipulation

swap Pop two values a and b and push the values a, b.

dup Pop the value a and push the values a, a.

roll Pop two values a and b and rotate b elements in the stack a times.

drop Remove the top of the stack.

clear Remove all the elements in the stack.

count Push the number of items in the stack.

_ Push on the stack the result of the last operation.

Stashing

stash Pop the value a and move that many items to the stash.

fetch Pop the value a and move that many items from the stash.

. Stash the top of the stack.

, Fetch one stashed item.

: Stash all the items in the stack.

; Fetch all stashed items.

History

Use <C-p>/<C-n> or the <Up>/<Down> arrow keys to navigate the history.

User defined operations

It is possible to define operations (or words, as they are usually called in stack based programming languages) by editing the words configuration file. It is not created by default, but clac will use some environment variables in order to search for word definitions.

$CLAC_WORDS If set, it should point to a file containing word definitions.

$XDG_CONFIG_HOME If set, clac will search for $XDG_CONFIG_HOME/clac/words.

$HOME If set, clac will search for $HOME/.config/clac/words.

How to define words

Words are defined as aliases, with one alias on each line. Empty lines are ignored. Here are some examples:

pi 3.14159265358979323846
# this is a comment
tau "pi 2 *"
sqrt "0.5 ^"

Note that an alias has two parts: a word to be defined and its meaning. That's why the tau and sqrt definitions are enclosed in double quotes. If the double quotes are removed, clac will complain that it can't parse the command. For example, if we remove the double quotes from sqrt and start clac, we will get this error message:

Incorrect definition: sqrt 0.5 ^
(~/.config/clac/words:3)

User defined words can be used as if they were built-in commands:

$ clac "42 dup * pi *"
5541.76944093239

Comments

Any lines that begin with # are considered comments and are ignored. There are no inline comments, and any # characters that are not the first character of a line are interpreted literally. To define # as a word, wrap it in double quotes in the definition:

# This is a comment.
"#" count

The first line is ignored, and the second line assigns # to the operation count.

How to list defined words

If you type words and hit enter, clac will list the defined words.

How to reload defined words

If you type reload and hit enter, clac will reload the words file.

Non-interactive mode

While the most interesting aspect of clac is the ability to visualize the stack as it is updated with each key press, at some point you may want use clac just to get a quick result or call it from a script. For that reason, clac can be used in non-interactive mode by invoking it with an argument.

Examples

Here are some examples of non-interactive invocations:

$ clac "3 4 +"
7

$ clac "2 3 4 +"
7
2

When clac finishes evaluating the expression "2 3 4 +", there are two elements in the stack: the number 7 at the top of the stack and the number 2 at the bottom of the stack. The elements are printed in order, one per line, starting from the top of the stack.

This other example uses the stashing features. Let's say we want to push two numbers and get the result of their multiplication plus the square of the second number.

$ clac "4 3 dup dup * . * , +"
21

Another example that uses the stash would be to get the average of all the elements in the stack:

$ clac "1 2 3 4 count . sum , /"
2.5

In fact, if you find yourself calculating averages very often, you can define the word avg as "count . sum , /".

Contributing

If you find a bug, please create an issue detailing the ways to reproduce it. If you have a suggestion, create an issue detailing the use case.

More Repositories

1

cuba

Rum based microframework for web development.
Ruby
1,438
star
2

ohm

Object-Hash Mapping for Redis
Ruby
1,390
star
3

micromachine

Minimal Finite State Machine
Ruby
522
star
4

map

Map lines from stdin to commands
C
221
star
5

mote

Minimum Operational Template
Ruby
217
star
6

nest

Generate nested namespaced keys for key-value databases.
Ruby
185
star
7

ost

Redis based queues and workers.
Ruby
166
star
8

toro

Tree oriented routing
Crystal
144
star
9

syro

Simple router for web applications
Ruby
135
star
10

cargo

Require libraries without cluttering your namespace.
Ruby
127
star
11

scrivener

Validation frontend for models.
Ruby
124
star
12

clap

Command line argument parsing
Ruby
90
star
13

ohm-crystal

Ohm for Crystal
Crystal
71
star
14

disque-rb

Disque client for Ruby
Ruby
68
star
15

gs

Gemset management
Ruby
67
star
16

totp

Time-based One-Time Passwords
Ruby
44
star
17

mailcat

Fake SMTP server that prints emails to stdout
C
38
star
18

chen

Change directory entries with your text editor
C
37
star
19

spawn

A ridiculously simple fixtures replacement for your web framework of choice.
Ruby
36
star
20

finist

Redis based Finite State Machine
Ruby
36
star
21

redisurl

Connect to Redis using a REDIS_URL and the redigo client.
Go
33
star
22

hart

Hash router
Ruby
24
star
23

stal-ruby

Set algebra solver for Redis
Ruby
22
star
24

redisent

Sentinels aware Redis client.
Ruby
22
star
25

relay

Relay commands over SSH
Ruby
21
star
26

resp

Lightweight RESP client for Lua
Lua
21
star
27

lomo

Apply a lomo filter to your pictures from the command line using ImageMagick.
Ruby
19
star
28

terco

Obstinate DNS
Ruby
16
star
29

override

The as-simple-as-possible-but-not-simpler stubbing library.
Ruby
16
star
30

ox

Skeleton for a Cuba-based JSON API.
Ruby
16
star
31

nido

Structured keys helper
Ruby
14
star
32

syro-demo

Demo application with Syro
Ruby
14
star
33

resp-crystal

Lightweight RESP client
Crystal
14
star
34

mt

Mail tester daemon.
Ruby
13
star
35

stringent

Generate a string with a target entropy
Ruby
12
star
36

rediscan

Scanner for Redis keyspace
Ruby
12
star
37

hypertext

Hypertext authoring with Ruby
Ruby
11
star
38

filmo

A single page presentation tool.
11
star
39

cuba-book

Cuba Book
11
star
40

sc

List of HTTP status codes.
Ruby
11
star
41

finist.lua

Redis based Finite State Machine
Lua
10
star
42

drawer

Ultra slim file-based cache
Ruby
10
star
43

nest-crystal

Object Oriented Keys for Redis
Crystal
9
star
44

basica

Basic authentication library.
Ruby
8
star
45

rino

Remove a file by its inode number
C
7
star
46

seg.rb

Segment matcher for paths
Ruby
7
star
47

seg

Segment matcher for paths
Crystal
7
star
48

trim

Read from stdin and remove a prefix from each line
C
7
star
49

tas

Trees as strings
Ruby
6
star
50

stal

Set algebra solver for Redis
Lua
6
star
51

pac

Package management for Lua libraries.
Shell
6
star
52

prep

Read from stdin and prepend a string to each line while preserving identation.
C
6
star
53

m4s2

Static Site Generator
HTML
5
star
54

contract

Contract helper
Ruby
5
star
55

stal-crystal

Set algebra solver for Redis
Crystal
5
star
56

loco

Lines of code counter
C
4
star
57

ook

Object Oriented Keys for Redis
Ruby
4
star
58

walk

Walk a directory tree and print the name of every regular file
C
4
star
59

rel

Ruby client for the Bandicoot database.
Ruby
4
star
60

textorama

Text slides for the terminal
Shell
4
star
61

homebrew-tools

Formulae for Homebrew
Ruby
4
star
62

rediscan.lua

Scanner for Redis keyspace in Lua
Lua
3
star
63

seg.go

Segment matcher for paths
Go
3
star
64

look

Add a vendor directory to your load path.
Ruby
3
star
65

app

Cuba application template for gn, the file generator.
Ruby
2
star
66

packer

Require different versions of the same Cargo-compatible gem
Ruby
2
star
67

tele.sh

2
star
68

ers

AWK script easy replacements in templates
Awk
2
star
69

soveran.github.io

2
star
70

filter

Workflow template for gn.
Ruby
1
star
71

remoto

Ruby
1
star
72

gem

Gem template for gn, the file generator.
Ruby
1
star
73

ohm-scripts

Lua scripts for Ohm compatible libraries
Lua
1
star
74

ostgo

Ost client.
Go
1
star
75

miga

Breadcrumb name of the working directory
C
1
star