tblcalc

package module
v0.9.6 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 28, 2026 License: Apache-2.0 Imports: 15 Imported by: 0

README

tblcalc(1) - Table Calculator

Core Functionality

tblcalc is a table calculation tool that applies formulas to CSV/TSV tables. Formulas can be embedded in the data file using special comment directives (e.g., #+TBLFM:) or placed in external files that are automatically discovered based on the data file's name. This functionality is inspired by Emacs Org-mode's table formulas and Miller scripts.

Key Features

Formula Processing:

  1. +TBLFM Directive - Applies table formulas specified in comment lines to CSV/TSV data files. Formulas use column references (e.g., $2, $3, $4) to perform calculations across table cells.

  2. +MLR Directive - Applies Miller commands specified in comment lines to CSV/TSV data files. For more details on Miller's DSL, refer to the official Miller documentation.

  3. Comment Preservation - Maintains all comment lines (lines starting with #) in their original positions while processing table data.

  4. Format Support - Supports both CSV (Comma-Separated Values) and TSV (Tab-Separated Values) formats for input and output.

  5. In-Place Editing - Allows direct file modification with the -i flag, preserving hard links.

Installation & Usage

Install via: go install github.com/knaka/tblcalc/cmd/tblcalc@latest

Basic commands:

  • Process CSV file: tblcalc input.csv >output.csv
  • In-place editing: tblcalc -i file.csv
  • Force format: tblcalc --icsv --ocsv file.txt
TBLFM Example

Input file (test.csv):

# Product list
#
#+TBLFM: $4=$2*$3
#
"Product","Unit Price",Stock,Total
Apple,100,50,
Banana,80,30,
Orange,120,20,

After processing with tblcalc test.csv:

# Product list
#
#+TBLFM: $4=$2*$3
#
"Product","Unit Price",Stock,Total
Apple,100,50,5000
Banana,80,30,2400
Orange,120,20,2400
Miller Example

Input file (mlr-test1.csv):

# Product list
#
#+MLR: ${Total}=${Unit Price}*${Stock}
#+MLR: ${Total2}=${Unit Price}*${Stock}
#
Product,Unit Price,Stock,Total,Total2
Apple,100,50,,
"Banana ""Cavendish"", Premium",80,30,,
# Another comment
Orange,120,20,,

After processing with tblcalc mlr-test1.csv:

# Product list
#
#+MLR: ${Total}=${Unit Price}*${Stock}
#+MLR: ${Total2}=${Unit Price}*${Stock}
#
Product,Unit Price,Stock,Total,Total2
Apple,100,50,5000,5000
"Banana ""Cavendish"", Premium",80,30,2400,2400
# Another comment
Orange,120,20,2400,2400
Automatic Formula/Script File Discovery

tblcalc can automatically discover and apply external script files (.tblfm, .mlr) or skip processing (.skip) based on the input CSV/TSV file's name. This allows for cleaner data files and enables applying the same rules to multiple data files that follow a naming convention.

When processing an input file (e.g., testdata/ledger-2025-01.csv), tblcalc will search for these special files in the same directory using a pattern matching mechanism. For instance, tblcalc will look for files like testdata/ledger-%.csv.tblfm or testdata/ledger-2025-01.csv.skip. The % acts as a wildcard, matching any string.

  • If a matching .skip file is found, tblcalc will perform no processing and simply output the original file content. This is useful for explicitly excluding certain files from calculations.
  • If a matching .tblfm or .mlr file is found, its content is treated as if the directives (e.g., #+TBLFM:, #+MLR:) were embedded in the input data file itself.

Consider the following input data and an external tblfm file:

Input file (testdata/ledger-2025-01.csv):

Date,Description,Amount,Category
2025-01-01,Groceries at local store,-5000,Food
2025-01-05,Monthly Salary,300000,Income
# This is a sample ledger data for January 2025.
2025-01-20,Electricity Bill,-8000,Utilities
2025-01-25,Freelance Project Payment,50000,Income
2025-01-28,Internet Service,-6500,Utilities
TOTAL,,0,

External formula file (testdata/ledger-%.csv.tblfm):

@>${Amount}=vsum(@2..@>>)

After processing with tblcalc testdata/ledger-2025-01.csv:

Date,Description,Amount,Category
2025-01-01,Groceries at local store,-5000,Food
2025-01-05,Monthly Salary,300000,Income
# This is a sample ledger data for January 2025.
2025-01-20,Electricity Bill,-8000,Utilities
2025-01-25,Freelance Project Payment,50000,Income
2025-01-28,Internet Service,-6500,Utilities
TOTAL,,330500,

In this example, tblcalc automatically finds testdata/ledger-%.csv.tblfm because it matches the input filename pattern. The formula @>${Amount}=vsum(@2..@>>) is then applied, calculating the sum of the Amount column and placing it in the TOTAL row.

Command-Line Options

  • -h, --help - Show help message
  • -i, --in-place - Edit file(s) in-place
  • -v, --verbose - Enable verbose output
  • --icsv - Force CSV for input format
  • --itsv - Force TSV for input format
  • --ocsv - Force CSV for output format
  • --otsv - Force TSV for output format

Formula Syntax

Cell Reference Notation

The +TBLFM directive uses Org-mode-style cell references:

  • $2, $3, $4 - Column references (1-indexed)
  • ${Header Name} - Column reference by header name (supports spaces)
  • @2 - Row 2 (first data row after header)
  • $> - Last column
  • @> - Last row
  • @>> - Second-to-last row
  • @< - First row (including header)
  • @2$3 - Cell at row 2, column 3
  • Ranges: @<<$>..@>>$> (range notation using ..)
Header Name References

Instead of numeric column indices, you can reference columns by their header names using ${Header Name} syntax. This makes formulas more readable and resilient to column reordering.

Note: Org-mode's "named field" syntax (e.g., $name) is not supported. Instead, tblcalc uses the ${Header Name} syntax to directly reference columns by their header values.

Input file (prices.csv):

# Price calculation
#
#+TBLFM: @2${Total}..@>> = ${Unit Price} * ${Qty}
#+TBLFM: @2${Tax}..@>>=${Total}*0.1
#+TBLFM: @2${Grand Total}..@>> = ${Total} + ${Tax}
#+TBLFM: @>${Grand Total}=vsum(@2..@>>)
#
Product,Unit Price,Qty,Total,Tax,Grand Total
Apple,100,5,,,
Orange,150,3,,,
Banana,80,10,,,
TOTAL,,,,,

After processing with tblcalc prices.csv:

# Price calculation
#
#+TBLFM: @2${Total}..@>> = ${Unit Price} * ${Qty}
#+TBLFM: @2${Tax}..@>>=${Total}*0.1
#+TBLFM: @2${Grand Total}..@>> = ${Total} + ${Tax}
#+TBLFM: @>${Grand Total}=vsum(@2..@>>)
#
Product,Unit Price,Qty,Total,Tax,Grand Total
Apple,100,5,500,50,550
Orange,150,3,450,45,495
Banana,80,10,800,80,880
TOTAL,,,,,1925

Header name references can also be used in range expressions: vsum(${Q1}..${Q4})

Lua-Based Formulas

Formulas are evaluated using Lua, providing flexible syntax for:

  • Arithmetic operations: $2*$3, $2+$3-10
  • String operations: String concatenation and manipulation
  • Conditional expressions: $2 > 100 and $2*0.9 or $2
  • All standard Lua built-in functions and libraries
Vector Functions

Available aggregation functions for ranges:

  • vsum(range) - Sum of values
  • vmean(range) - Average of values
  • vmedian(range) - Median of values
  • vmax(range) - Maximum value
  • vmin(range) - Minimum value

Example: vsum(@2$3..@>$3) calculates the sum of column 3 from row 2 to the last row.

Multiple Formulas

Multiple formulas can be specified with:

  • Multiple #+TBLFM: lines
  • Separated by :: in a single line: #+TBLFM: $4=$2*$3::$5=$2+$3
Important Note

Lua's string concatenation operator .. visually resembles the range operator ... To prevent confusion:

  • Add spaces around concatenation: $2 .. " items"
  • Use parentheses around cell references: ($2)..($3)

Editor Integration

VSCode Configuration

You can configure VSCode to automatically apply formulas when saving CSV/TSV files using the Run on Save extension.

Add this to your .vscode/settings.json:

{
  "emeraldwalk.runonsave": {
    "commands": [
      {
        "match": "\\.(csv|tsv)$",
        "cmd": "tblcalc -i ${file}"
      }
    ]
  }
}

This automatically processes files with +TBLFM directives whenever you save them.

If you use the Rainbow CSV extension for better CSV/TSV visualization, configure it to recognize comment lines:

{
  "rainbow_csv.comment_prefix": "#"
}

This ensures that comment lines (including +TBLFM directives) are properly displayed and not treated as data rows.

License

Released under the Apache 2.0 License.

Documentation

Overview

Package tblcalc provides table calculation.

Index

Constants

This section is empty.

Variables

View Source
var WithFormulas = funcopt.New(func(params *tblcalcParams, formulas []string) {
	params.formulas = append(params.formulas, formulas...)
})
View Source
var WithIgnoreExit = funcopt.New(func(params *tblcalcParams, ignoreExit bool) {
	params.ignoreExit = ignoreExit
})
View Source
var WithScripts = funcopt.New(func(params *tblcalcParams, scripts []string) {
	params.scripts = append(params.scripts, scripts...)
})

Functions

func ProcessFile added in v0.9.6

func ProcessFile(
	filePath string,
	inputFormat InputFormat,
	writer io.Writer,
	outputFormat OutputFormat,
	opts ...funcopt.Option[tblcalcParams],
) (
	err error,
)

ProcessFile reads data from filepath, applies table formulas found in comment lines, and writes the result to writer. Comment lines starting with "# +TBLFM:" contain formulas that are applied to the table data. The input and output formats are specified by inputFormat and outputFormat parameters. External files with extensions .skip, .tblfm, .mlr are searched in the same directory. The "%" character in these filenames acts as a wildcard (like SQL LIKE). For example, "foo%baz.csv.skip" matches "foo-bar-baz.csv". If a matching .skip file exists, no formulas or scripts are applied. If a matching .tblfm file exists, its contents are parsed as formulas (split by newlines and "::"). Similarly, if a matching .mlr file exists, its contents are used as a Miller script.

func ProcessStream added in v0.9.6

func ProcessStream(
	reader io.Reader,
	inputFormat InputFormat,
	writer io.Writer,
	outputFormat OutputFormat,
	opts ...funcopt.Option[tblcalcParams],
) error

ProcessStream reads data from reader, applies table formulas found in comment lines, and writes the result to writer. Comment lines starting with "# +TBLFM:" contain formulas that are applied to the table data. The input and output formats are specified by inputFormat and outputFormat parameters.

Types

type InputFormat

type InputFormat int

InputFormat represents the format of input data.

const (
	// InputFormatCSV indicates CSV (Comma-Separated Values) format.
	InputFormatCSV InputFormat = iota
	// InputFormatTSV indicates TSV (Tab-Separated Values) format.
	InputFormatTSV
)

type Options added in v0.9.5

type Options []funcopt.Option[tblcalcParams]

Options is a functional options type.

type OutputFormat

type OutputFormat int

OutputFormat represents the format of output data.

const (
	// OutputFormatCSV indicates CSV (Comma-Separated Values) format.
	OutputFormatCSV OutputFormat = iota
	// OutputFormatTSV indicates TSV (Tab-Separated Values) format.
	OutputFormatTSV
)

Directories

Path Synopsis
cmd
tblcalc command
Package tblfm handles table formulas using Lua for expression evaluation.
Package tblfm handles table formulas using Lua for expression evaluation.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL