tally/README.md

220 lines
13 KiB
Markdown

# tally
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.
![screen shot of tally showing monthly expenses vs income](tally.png)
## 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.
## Usage
_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.
### Running
To create a new spreadsheet, invoke _tally_ without any arguments:
``` sh
tally
```
To open an existing file, pass a filepath. Here are some examples:
``` sh
tally ~/my-tally-spreadsheet.tss
tally ~/my-cool-csv-file.csv
tally ~/my-awesome-tsv-file.tsv
```
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.
### Editing
When starting a new sheet from scratch the workbook will have one sheet with one cell (`A1`). If you load an existing `tss`, `csv`, or `tsv` file then thenumber of rows and columns, along with their values, will be present in the sheet shown by _tally_.
#### Movement
To move around the sheet, use vi-like keys:
- `h`, `j`, `k`, `l`, or _arrow keys_: Left, Down, Up, Right
- `^`, `$`, `home`, `end`: Move to First or Last column in current row
- `g`, `G`, `PageUp`, `PageDown`: Move to First or Last row in current column
#### Data
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, `"like so"`
- `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 `enter` or `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 `"` key.
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 `#Err`.
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_).
#### Deleting Data
To delete the contents of a cell, that is - to revert it to an empty state, press `d`, `Backspace`, or `Delete`
#### 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.
#### Cell Modifiers
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:
- `b`: Bold
- `f`: Faint/dim; if bold has been added to the cell then faint will have no effect
- `u`: Underline
- `i`: Italics
#### Zoom
You can zoom in or out with the `+` and `-` 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.
### Commands
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:
- `write` or `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 `write`)
- `write-csv` or `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 `csv`
- `write-tsv` or `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 `tsv`
- `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
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](https://git.rawtext.club/sloum/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 `A1` and `A2` get added together and the result is the value of the cell. Note that if either `A1` or `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 `+`, `-`, `\*`, and `/`. Additional operators that work with numbers are: `ROUND`, `MAX`, `MIN`, `FLOOR`, `CEIL`, and `POW`.
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 `MAX`. `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 `6.25` and `10.5` is found, which is `6.25`. This then gets rounded to one decimal place for the final value of `6.3`.
#### 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 `"Hello\\\_"`.
To then combine them, you could use the following expression (assuming `A2` to be something like `"world"`):
```
A1 A2
```
or since text can be entered into expression manually, the following would also work:
```
A1 "world"
```
Let's say you did not want to use `\\\_` to create a space. You could use the `SPC` function, like so:
```
A1 SPC A2
```
Assuming `A1` to be `"Hello"` and `A2` to be `"world"`, this would create the cell value `Hello world`. Without `SPC` the words would be shoved together and read as `Helloworld`.
#### 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:
```
21.75 "Hello"
```
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 `+` or `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).
#### Stack Manipulation
The number stack can be manipulated in a number of ways. You have seem mathematical operators and a few functions (`MIN`, `ROUND`, `MAX`, `.`). 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 `2`.
`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..
#### Ranges
_tally_ can accept ranges of cells for operation. However, _tally_ currently only supports summing the numerical values of those cells. The syntax is `A1:B3+`. The `+` at the end designates summing the range. Eventually there may be other range operations available. Locking rows and columns _can_ be used in ranges.
#### Errors
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). `.`, `DROP`, and `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.
## Related
_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](https://tildegit.org/sloum/chalk) - A line based text editor, a kind of less powerful but more friendly `ed`
- [hermes](https://tildegit.org/sloum/hermes) - A visual editor more akin to `vi`, based on `kilo` by antirez
- [bombadillo](https://bombadillo.colorfield.space) - An internet client supporting gopher, gemini, finger, file, telnet, and http(s)
- [nimf](https://rawtext.club/~sloum/nimf) - A concatenative programming language/interpreter
- [lid](https://tildegit.org/sloum/lid) - A lo-fi image ditherer
Forthcoming are drawing, calendar, slides, mail, and notes programs.