Category tags
Package:
TAGS_PACKAGE. Registered bycreateEngine(); for a slimmer engine, register it explicitly (see choosing packages).
A running note often groups its numbers by hand: a shopping list, a set of
expenses, a few figures that belong together. A #tag written mid-line labels a
line as belonging to a category, and the aggregates gather every line carrying
that tag, wherever they sit in the document.
The tag itself is dropped from the line it annotates, so a tagged line still calculates to its own number:
40 + 15 #grocery // 55The aggregates
Section titled “The aggregates”Four forms read the whole document and collect the lines that carry a tag. Each reads the same set; they differ only in what they do with it.
| Expression | Meaning |
|---|---|
total of #grocery | the sum of every line tagged #grocery |
sum of #grocery | the same, sum is a synonym for total |
average of #grocery | the mean of the tagged lines |
count of #grocery | how many lines carry the tag |
A worked note. The tagged lines need not be adjacent; lines carrying other tags, untagged lines, and blank lines between them are all ignored:
40 + 15 #grocery30 #transport
12.50 #grocerytotal of #grocery // 67.50Asking is not joining
Section titled “Asking is not joining”A #tag after one of those four openers names the group; it does not join it.
So a tag can answer as many questions as you like, and each answers as though it
were the only one:
40 #grocery12.50 #grocerytotal of #grocery // 52.50average of #grocery // 26.25count of #grocery // 2A line can do both at once, because the rule is about each # rather than about
the line: the tag being asked about is a question, and any other tag on the line
is still a mark.
40 #grocery #reviewed12.50 #grocery9 #reviewedtotal of #grocery // 52.50total of #reviewed // 49The first line is counted in both totals, and neither aggregate line is counted in either.
count answers presence rather than value: it counts every line that carries the
tag, and a non-numeric tagged line (a note to yourself) counts too, where total
and average would reject it.
40 #grocery12.50 #grocerycount of #grocery // 2Money and units carry through. A tag whose lines are all in dollars totals to dollars:
$40 #food$25 #foodtotal of #food // $65.00Boundaries
Section titled “Boundaries”A few boundaries, each deliberate:
- A tag that is a line’s first token is a heading, not a data line, so
#grocery listat the top of a note is a title rather than a tagged figure. - The match is on the whole tag, so a prefix does not collide:
#housingdoes not gather#housingcost. Tag names are matched case-insensitively. - The
#must sit at a boundary. A#glued to the end of a word or number is not a tag:100#foodanda#foodare left whole and the#reads as an ordinary comment; only100 #food, with a space, tags the line. This keeps the tag the reader sees and the tag the totals count the same one. - A tag may be named after an ordinary word, even one the grammar uses
elsewhere.
#columnor#assumingis a category like any other, on a data line and in an aggregate alike:
1200 #assuming800 #assumingtotal of #assuming // 2,000- One aggregate line per tag per note. An aggregate line carries the tag it sums, so a second one would try to include the first, and each would wait on the other. The query line always skips itself; a second query is left out of scope rather than guessed at.
- A clear error, never a silent figure. Mixing units under one tag, or
tagging a line that is not a number then asking for its
total, is an error rather than a guessed number. No tagged lines at all is an error fortotalandaverage, and zero forcount.
A tag name must start with a letter, which keeps it clear of the colour
literals: #grocery is a tag, #c0ffee is a colour, and
#12a (all hex digits) is a colour too, not a tag. A # followed by a space is
still an ordinary heading or comment.
Like line references, these forms only work inside a document, since they read other lines. They return an error through the single-expression entry point, which has no document to gather from.