README.md

March 20, 2026 · View on GitHub

███    ██ ██    ██ ███    ███ ██████
████   ██ ██    ██ ████  ████ ██   ██
██ ██  ██ ██    ██ ██ ████ ██ ██████
██  ██ ██ ██    ██ ██  ██  ██ ██   ██
██   ████  ██████  ██      ██ ██   ██

CI

A text calculator for natural language expressions with a vim-style TUI.

Try it online →

numr TUI demo - calculations with variables, units, currencies, and continuation

Features

  • Natural language expressions: 20% of 150, $100 in euros, 2 hours + 30 min
  • Variables: tax = 15% then 100 + tax
  • Unit conversions: Length, weight, time, temperature, data sizes
  • Compound units: 5 m * 10 m = 50 m², 100 km / 2 h = 50 km/h
  • Currency conversions: USD, EUR, GBP, JPY, CHF, CNY, CAD, AUD, INR, KRW, RUB, ILS, PLN, UAH + crypto (BTC, ETH, SOL, and more)
  • Number base conversions: 22 to hex, 22 to bin
  • Live exchange rates: Fetched automatically on startup
  • Dual keybinding modes: Vim (modal) or Standard (direct input) - toggle with Shift+Tab
  • Mouse support: Scroll with mouse wheel or trackpad
  • File persistence: Save with Ctrl+S, supports custom files
  • Syntax highlighting: Numbers, operators, variables, units, and currencies
  • Comments: Lines starting with # or // are treated as comments
  • Continuation: Start a line with an operator (+ 10, * 2) to continue from the previous result
  • Wrap mode: Toggle text wrapping with bottom-aligned results
  • Grouped totals: Currencies and units summed separately in footer (respects exchange rates)

Installation

macOS (Homebrew)

brew tap nasedkinpv/tap
brew install numr

Installs both binaries: numr (opens the calculator file in the TUI) and numr-cli (CLI/REPL/server).

Arch Linux (AUR)

# Using yay
yay -S numr

# Using paru
paru -S numr

Installs both binaries: numr (opens the calculator file in the TUI) and numr-cli (CLI/REPL/server).

From source

# Install the TUI binary
cargo install --path crates/numr-tui

# Install the CLI binary
cargo install --path crates/numr-cli

# Or build both from source
cargo build --release

# Binaries will be available at target/release/numr and target/release/numr-cli

Release archives also contain both binaries: numr (opens the calculator file in the TUI) and numr-cli (CLI/REPL/server).

Usage

TUI Mode

# Open default file (stored in OS config directory)
numr

# Open specific file
numr example.numr

CLI Mode

# Single expression
numr-cli "20% of 150"

# Evaluate file (aligned "input = result" output)
numr-cli -f example.numr

# Interactive REPL
numr-cli -i

# Pipe mode
echo "100 + 200" | numr-cli

# Show running total
numr-cli -t -f example.numr

# Aligned output for any mode
numr-cli --verbose "20% of 150"

By default, numr-cli prints just the result. File mode (-f) uses aligned input = result output. Use --verbose to get aligned output in other modes. Use -t to show a running total at the end.

On Linux, use rlwrap numr-cli -i for readline-style history and editing in the REPL.

JSON-RPC Server Mode

Run numr as a backend for other tools (editors, launchers, scripts):

numr-cli --server

Send JSON-RPC 2.0 requests via stdin, receive responses via stdout:

echo '{"jsonrpc":"2.0","method":"eval","params":{"expr":"20% of 150"},"id":1}' | numr-cli --server
# {"jsonrpc":"2.0","result":{"type":"number","value":"30","display":"30"},"id":1}

Available methods:

MethodParamsDescription
eval{"expr": "..."}Evaluate expression
eval_lines{"lines": [...]}Evaluate multiple lines
clearnoneClear state
get_totalsnoneGet grouped totals
get_variablesnoneList variables
reload_ratesnoneRefresh exchange rates

Keybindings (TUI)

The TUI supports two keybinding modes: Vim (default) and Standard. Press Shift+Tab to toggle between them.

Vim Mode

Normal Mode

KeyAction
i / aEnter Insert mode at/after cursor
I / AEnter Insert mode at line start/end
o / ONew line below/above and enter Insert mode
sSubstitute character (delete and insert)
CChange to end of line
h / j / k / lMove left/down/up/right
w / b / eWord forward/backward/end
0 / $Line start/end
gg / GFirst/last line
SpaceMove right
PageUp/DownScroll page
x / XDelete char forward/backward
ddDelete line
DDelete to end of line
JJoin lines
W / N / HToggle wrap/line numbers/header
? / F1Toggle help
Ctrl+sSave
Ctrl+rRefresh rates
F12Toggle debug
Shift+TabSwitch to Standard mode
qQuit

Insert Mode

KeyAction
EscReturn to Normal mode
TypeInsert text
Backspace / DeleteDelete char backward/forward
EnterNew line
Arrows / PageUp/DownNavigate
Home / EndLine start/end
Ctrl+sSave

Standard Mode

Direct input like traditional editors - no modal switching required.

KeyAction
TypeInsert text directly
Arrow keysMove cursor
Home / EndLine start/end
PageUp/DownScroll page
Ctrl+a / Ctrl+eLine start/end
Ctrl+gGo to first line
Backspace / DeleteDelete char
Ctrl+kDelete line
EnterNew line
Ctrl+w/l/hToggle wrap/line numbers/header
? / F1Toggle help
Ctrl+sSave
Ctrl+rRefresh rates
Shift+TabSwitch to Vim mode
Ctrl+qQuit

Supported Operations

CategoryExamples
Arithmetic10 + 20, 6 * 7, 2 ^ 8
Percentages20% of 150, $50 - 10%, 100 + 15%
Variablestax = 8% then price + tax
Continuation$100+ \$50* 2 (chains from previous)
Functionssum(), avg(), min(), max(), sqrt(), abs(), round(), floor(), ceil()
Base conversion22 to hex0x16, 22 to bin0b10110
Unit conversion5 km in miles, 22 C in F, 1 TB in GB
Compound units5 m * 10 m50 m², 100 km / 2 h50 km/h
Currency$100 in eur, 1 BTC in USD
Comments# comment or // comment
Reference previous_ or ANS for last result

Compound unit aliases: kph (km/h), mph (mi/h), mps (m/s), m2 (m²), km2 (km²), ft2 (ft²)

Full examples

Arithmetic

10 + 20           → 30
100 - 25          → 75
6 * 7             → 42
100 / 4           → 25
2 ^ 8             → 256

Number Base Conversions

22 to hex         → 0x16
22 to bin         → 0b10110
-42 to hex        → -0x2a

Percentages

20% of 150        → 30
100 + 15%         → 115
\$50 - 10%         → \$45

Variables

price = \$100
tax = 8%
price + tax       → \$108

Comments

# This is a comment
// This is also a comment
Groceries         \$45.00

Continuation

\$100              → \$100
+ \$50             → \$150 (continues from previous)
* 2               → \$300
- 10%             → \$270
total = _         → \$270 (_ or ANS references previous result)

Functions

sum(10, 20, 30)   → 60
avg(10, 20, 30)   → 20
min(5, 3, 8)      → 3
max(5, 3, 8)      → 8
sqrt(16)          → 4
abs(-5)           → 5
round(3.7)        → 4
floor(3.7)        → 3
ceil(3.2)         → 4

Compound Units

5 m * 10 m        → 50 m²
100 km / 2 h      → 50 km/h
50 kph * 2 h      → 100 km
50 kph in mps     → 13.89 m/s
25 km / 100 km    → 0.25 (dimensionless)

Supported Units

CategoryUnits
Lengthkm, m, cm, mm, mi/miles, ft/feet, in/inches
Area/m2, km²/km2, ft²/ft2, acre, hectare/ha
Speedm/s/mps, km/h/kph, mph, knot
Weightkg, g, mg, lb/lbs, oz, ton
VolumeL, mL, gal, /m3
Timemonths/mo, weeks/wk, days/d, hours/hr/h, minutes/min, seconds/sec/s
EnergyJ, kJ, cal, kcal, kWh
PowerW, kW
TemperatureK/Kelvin, C/Celsius, F/Fahrenheit
DataTB, GB, MB, KB, bytes
Fiat$/USD, /EUR, £/GBP, ¥/JPY, CHF, CNY, CAD, AUD, /INR, /KRW, /RUB, /ILS, /PLN, /UAH
Crypto/BTC, Ξ/ETH, /SOL, /USDT, USDC, BNB, XRP, /ADA, Ð/DOGE, DOT, Ł/LTC, LINK, AVAX, MATIC, TON

Architecture

graph TB
    subgraph Frontends
        CLI[numr-cli<br/>CLI · REPL · JSON-RPC]
        TUI[numr-tui<br/>Terminal UI · Vim/Standard]
        Web[numr-web<br/>WASM web app]
    end

    Editor[numr-editor<br/>Syntax highlighting]

    subgraph Core[numr-core]
        Engine[Engine]
        Engine --> Parser[PEG Parser]
        Parser --> Eval[Evaluator]
        Eval --> Types[Currency · Units · Values]
        Eval --> Cache[(Rate Cache)]
    end

    Fiat[open.er-api.com]
    Crypto[CoinGecko]

    CLI --> Engine
    TUI --> Engine
    TUI --> Editor
    Web --> Engine
    Web --> Editor
    Cache -.-> Fiat
    Cache -.-> Crypto
numr/
├── crates/
│   ├── numr-core/      # Core evaluation engine (WASM-compatible)
│   │   ├── parser/     # Pest PEG grammar and AST builder
│   │   ├── eval/       # Expression evaluation with unit/currency handling
│   │   ├── types/      # Value, Currency, Unit registries
│   │   ├── cache/      # Exchange rate caching with BFS path finding
│   │   ├── fetch.rs    # HTTP rate fetching (optional "fetch" feature)
│   │   └── wasm.rs     # WASM bindings (optional "wasm" feature)
│   ├── numr-editor/    # Syntax highlighting and text buffer (WASM-compatible)
│   ├── numr-tui/       # Terminal UI (Ratatui) with vim/standard modes
│   └── numr-cli/       # CLI, interactive REPL, and JSON-RPC server

The core library (numr-core) is UI-agnostic and can be embedded in CLI, TUI, GUI, or WASM contexts. The fetch feature flag enables HTTP fetching (adds reqwest dependency, not WASM-compatible).

Config and cache are stored in the OS config directory (~/.config/numr/ on Linux, ~/Library/Application Support/numr/ on macOS). Settings persist automatically when toggled in the TUI.

Example config.toml:

[preferences]
keybinding_mode = "vim"   # "vim" or "standard"
wrap_mode = false
show_line_numbers = false
show_header = false

[files]
default_path = "~/Documents/calculations.numr"

[api]
fiat_rates_url = "https://open.er-api.com/v6/latest/USD"
crypto_rates_url = "https://api.coingecko.com/api/v3/simple/price"

[api.keys]
coingecko_api_key = "your-key-here"

CoinGecko API key header (demo vs pro) is selected automatically based on the URL host.

Exchange rates are cached to rates.json in the same config directory with 1-hour expiry. Both TUI and CLI share this cache:

  • TUI: Fetches fresh rates on startup
  • CLI: Fetches only if cache is expired

Rate sources:

Integrations

License

MIT