This is a work in progress spreadsheet program with a semi-limited feature set. For fun, all expressions use postfix notation similar to Forth in style. It is made available under the terms of the Floodgap Free Software License (see the file 'LICENSE').
In general the use case for tally is small spreadsheets, notes, shopping lists, bills, little bits of relational data. It is not meant to do what Excel, or Calc, or Lotus123 do. It is meant to be a small and simple alternative for small and simple use cases.
Building / Installing
You will need a Go compiler. Testing on eary versions has not been done, but suffice to say you should likely not need the latest cutting edge Go version to compile tally.
A makefile is forthcoming. Until then a simple
go build or
go install from within the repo directory should work fine.
tally uses its own file format, but can import most csv and tsv files (any that are in the format described by RFC 4180). At present most basic features are available with the exception of actions upon ranges (
A1:C3 SUM, for example). These are hopefully coming soon.
To create a new spreadsheet, invoke tally without any arguments:
To open an existing file, pass a filepath. Here are some examples:
To quit tally at any time press
Q. If you have unsaved changes you will be asked if you are sure you want to quit without saving.
When starting a new sheet from scratch the workbook will have one sheet with one cell (
A1). If you load an existing
tsv file then thenumber of rows and columns, along with their values, will be present in the sheet shown by tally.
To move around the sheet, use vi-like keys:
l, or arrow keys: Left, Down, Up, Right
end: Move to First or Last column in current row
PageDown: Move to First or Last row in current column
You can enter data into cells in a few different ways. Cells accept the following types of values:
number: Positive, negative, integer, or decimal. Internally tally thinks of all numbers as decimals
text: A string of characters. All strings must be surrounded by double quotes,
expression: Any combination of the above two types, as well as references to cell in the form of column then row:
A2, for example.
To enter data into a cell you can press the
space key. If you are going to be entering text into the cell, there is a shortcut that allows you to enter the text without needing to quote it (the quoting will be done for you): press the
If tally understood what you entered you will see a value. If it did not, or there is a problem with your expression, you will see
When referencing a cell in an expressions, such as
A2, you may optionally "lock" the row or column while leaving the other to be used as a relative reference. To lock a column use the following syntax:
$A2. To lock a row use the following syntax:
A$2. You can lock both,
$A$2, but it is likely easier to just do a non-relative paste using the p key (rather than P).
To delete the contents of a cell, that is - to revert it to an empty state, press
Yank / Paste
You can copy a cell with
y. To paste it you have two options. The difference between these options is how they deal with cell references in expressions. Pressing
p will paste the cell and will not change any references from when it was copied. Pressing
P will update the cell references to be relative. In this case that means they will change based on the distance (in rows and columns) between where they were copied from and where they are being pasted. This allows for dynamic expressions that can be moved around a sheet conveniently. Cells can have their column or row reference locked. If locking is performed then a relative paste will respect that lock and keep the row or column that was locked as it was and the other will be handled relatively.
You can change the appearance of a cell through the use of modifiers. All modifiers work as toggles, so turning on and off is done with the same key. The available modifiers are:
f: Faint/dim; if bold has been added to the cell then faint will have no effect
You can zoom in or out with the
- keys. This has the effect of controlling how many columns you see on the screen at a given time. At present all columns have the same width.
In addition to the editing keys, there are a few commands that can be issued. To enter command mode press
: and then enter your command.
The following commands are available:
w: Will write the current spreadsheet to a file. If no filepath is passed (
write ~/my-file.tss) tally will save the current file, using a default name and the execution directory if necessary (ie. if tally was run without a file and no path has yet been passed to
wc: Will write the current spreadsheet to a csv file. If no filepath is passed tally will save to the current file path, but with the file type
wt: Will write the current spreadsheet to a csv file. If no filepath is passed tally will save to the current file path, but with the file type
trim: Removes empty rows/columns at the end of the file. It does this recursively starting with the bottom-most row and right-most column until it encounters a row or column (each working independently) with data in it
recalculate: Forces a recalculation of the entire sheet. This should generally not be needed, but is avialable should you encounter the need
Expressions in tally do not follow the Excel style expression methodology. Instead, expressions use a stack for execution and use postfix notation. This is similar to nimf, the concatenative language written by the author of tally.
Working with numbers and cell references
A1 A2 +
In the above example the values of
A2 get added together and the result is the value of the cell. Note that if either
A2 is a text value, rather than a number, this will result in `#Err: Stack underflow. We will cover mixing text and numbers further into the examples.
Basic math operators exist for
/. Additional operators that work with numbers are:
There are also functions to do a few basic things:
A1 2 ROUND
The above would round the numerical value at
A1 to two decimal places.
A1 A2 MAX
The above would find the greater of the two values that come before
MIN is also available.
You can combine cell references and hard coded numbers as well:
A1 2 * 10.5 MIN 1 ROUND
In the above, lets assume
A1 is currently
3.125. If so, then
A1 gets multiplied by
2, resulting in
6.25. Then the minimum value between
10.5 is found, which is
6.25. This then gets rounded to one decimal place for the final value of
Working with text and cell references
Text is pretty easy to work with. No operators are required in most cases. Since tally splits expressions on whitespace, consecutive whitespace in strings should be entered as
\\\_. So, a cell with the value
"Hello" that is intended to be combined with another cell and result in a space in between may need to be written as
To then combine them, you could use the following expression (assuming
A2 to be something like
or since text can be entered into expression manually, the following would also work:
Let's say you did not want to use
\\\_ to create a space. You could use the
SPC function, like so:
A1 SPC A2
A1 to be
A2 to be
"world", this would create the cell value
Hello world. Without
SPC the words would be shoved together and read as
Combining text and numbers
To concatenate a numerical and text value, you can enter the values as if they were both strings, but it may not work out like you would think:
The above results in
Hello21.75. If you want the
21.75 to appear before
"Hello", you need to use a special function:
.. This lets tally know that you would like the number on the top of the stack to be appended to the current string value and dropped from the stack
. So the above could be rewritten as:
21.72 . SPC "Hello"
With the result being
21.72 Hello. Of course, either the number value or the text value could have been a cell reference, such as
B25 of the like.
You may be asking yourself, why do we need
.? The answer is that it allows you to have numbers before and after text and choose when to put numbers into the text value. This gives a fine grained control of both the number stack as well as the string buffer.
For a more complicated example, we could do something like the following:
23 5 + . "hello" 3 1 -
This produces the result:
28hello2. If you remove the
. that comes after the plus, you would get the output:
hello228. Now, that may seem strange. Why is that happening? It is happening for the same reason you saw a 2 at the end in the first result: at the end of the expression, the stack is flushed and added to the string from top of stack down. So since
2 was the last number on the stack it is the first off. Then
28 gets added to the end.
There are a few words that affect the stack, but do not necessarily modify the output in a transformative way like
MIN do, for example. The next section will cover these. The important thing to take away from the above paragraph is that
. can help you control where numbers go, and any numbers left on the stack at the end of an expression that involves text will be flushed to the text buffer (this is not true of purely numerical expressions, where the cell value is always just represented by the top of the stack).
The number stack can be manipulated in a number of ways. You have seem mathematical operators and a few functions (
.). There are a few more options for dealing with numbers on the stack:
DUP will copy the number on the top of the stack and place the copy on top. So if the stack starts empty and you enter
2 DUP, the stack will contain
2 and then another
DROP will remove the top value on the stack and throw it away.
CLEAR will wipe out all values from the stack. This, in theory, could be useful to prevent a stack flush at the end of a field containing numbers and text. However, be wary of doing so as it likely indicates that some refactoring could prevent the need to use it.
SWAP will swap the position of the top two values on the stack.
OVER will copy the number underneath the top value on the stack and place the copy on the top of the stack without removing any numbers from the stack..
tally can accept ranges of cells for operation. However, tally currently only supports summing the numerical values of those cells. The syntax is
+ at the end designates summing the range. Eventually there may be other range operations available. Locking rows and columns can be used in ranges.
If there is a problem in your expression, the cell will report
#Err, likely followed by a message about the nature of the problem. If you try to reference a stack value that doesn't exist, for example... or even a cell that does not exist.
Some functions require certain things to be in place on the stack. All of the math operators, for example, require at least two numbers to be on the stack (the two will be replaced by the result of the operation).
DUP only require one item on the number stack. If the minimum number of items on the stack is not met, an error will be the result.
tally is intended to be a part of a suite of office/productivity applications written by tally's developer for personal use. Building your own tools, even when they lack some features of program x, is a rewarding experience and can be quite educational. It also can produce highly hackable and editable software for personal use. That having been said, if you get utility from any of these programs, tally included: awesome! Here are some of the other applications related to tally:
- chalk - A line based text editor, a kind of less powerful but more friendly
- hermes - A visual editor more akin to
vi, based on
- bombadillo - An internet client supporting gopher, gemini, finger, file, telnet, and http(s)
- nimf - A concatenative programming language/interpreter
- lid - A lo-fi image ditherer
Forthcoming are drawing, calendar, slides, mail, and notes programs.