███ ██ ██ ██ ███ ███ ██████ ████ ██ ██ ██ ████ ████ ██ ██ ██ ██ ██ ██ ██ ██ ████ ██ ██████ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ████ ██████ ██ ██ ██ ██
A text calculator for natural language expressions with a vim-style TUI.
- Natural language expressions:
20% of 150,$100 in euros,2 hours + 30 min - Variables:
tax = 15%then100 + 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: Auto-saves to config directory, 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)
brew tap nasedkinpv/tap
brew install numrInstalls both binaries: numr (opens the calculator file in the TUI) and numr-cli (CLI/REPL/server).
# Using yay
yay -S numr
# Using paru
paru -S numrInstalls both binaries: numr (opens the calculator file in the TUI) and numr-cli (CLI/REPL/server).
# 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-cliRelease archives also contain both binaries: numr (opens the calculator file in the TUI) and numr-cli (CLI/REPL/server).
# Open default file (~/.config/numr/default.numr)
numr
# Open specific file
numr example.numr# Single expression
numr-cli "20% of 150"
# Evaluate file
numr-cli -f example.numr
# Interactive REPL
numr-cli -i
# Pipe mode
echo "100 + 200" | numr-cli
# Result only
numr-cli -q "20% of 150"By default, numr-cli prints aligned output in the form input = result. Use -q / --quiet to print only the result.
numr-cli -i is a simple interactive REPL. If you want readline-style history and editing on Linux, use:
rlwrap numr-cli -iRun numr as a backend for other tools (editors, launchers, scripts):
numr-cli --serverSend 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.0,"display":"30"},"id":1}Available methods:
| Method | Params | Description |
|---|---|---|
eval |
{"expr": "..."} |
Evaluate expression |
eval_lines |
{"lines": [...]} |
Evaluate multiple lines |
clear |
none | Clear state |
get_totals |
none | Get grouped totals |
get_variables |
none | List variables |
reload_rates |
none | Refresh exchange rates |
The TUI supports two keybinding modes: Vim (default) and Standard. Press Shift+Tab to toggle between them.
| Key | Action |
|---|---|
i / a |
Enter Insert mode at/after cursor |
I / A |
Enter Insert mode at line start/end |
o / O |
New line below/above and enter Insert mode |
s |
Substitute character (delete and insert) |
C |
Change to end of line |
h / j / k / l |
Move left/down/up/right |
w / b / e |
Word forward/backward/end |
0 / $ |
Line start/end |
gg / G |
First/last line |
Space |
Move right |
PageUp/Down |
Scroll page |
x / X |
Delete char forward/backward |
dd |
Delete line |
D |
Delete to end of line |
J |
Join lines |
W / N / H |
Toggle wrap/line numbers/header |
? / F1 |
Toggle help |
Ctrl+s |
Save |
Ctrl+r |
Refresh rates |
F12 |
Toggle debug |
Shift+Tab |
Switch to Standard mode |
q |
Quit |
| Key | Action |
|---|---|
Esc |
Return to Normal mode |
| Type | Insert text |
Backspace / Delete |
Delete char backward/forward |
Enter |
New line |
Arrows / PageUp/Down |
Navigate |
Home / End |
Line start/end |
Ctrl+s |
Save |
Direct input like traditional editors - no modal switching required.
| Key | Action |
|---|---|
| Type | Insert text directly |
Arrow keys |
Move cursor |
Home / End |
Line start/end |
PageUp/Down |
Scroll page |
Ctrl+a / Ctrl+e |
Line start/end |
Ctrl+g |
Go to first line |
Backspace / Delete |
Delete char |
Ctrl+k |
Delete line |
Enter |
New line |
Ctrl+w/l/h |
Toggle wrap/line numbers/header |
? / F1 |
Toggle help |
Ctrl+s |
Save |
Ctrl+r |
Refresh rates |
Shift+Tab |
Switch to Vim mode |
Ctrl+q |
Quit |
10 + 20 → 30
100 - 25 → 75
6 * 7 → 42
100 / 4 → 25
2 ^ 8 → 256
22 to hex → 0x16
22 to bin → 0b10110
-42 to hex → -0x2a
20% of 150 → 30
100 + 15% → 115
$50 - 10% → $45
price = $100
tax = 8%
price + tax → $108
# This is a comment
// This is also a comment
Groceries $45.00
# Comments are dimmed and ignored in calculations
$100 → $100
+ $50 → $150 (continues from previous)
* 2 → $300
- 10% → $270
total = _ → $270 (_ or ANS references previous result)
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
# Area from multiplication
5 m * 10 m → 50 m²
# Speed from division
100 km / 2 h → 50 km/h
# Distance from speed × time
50 kph * 2 h → 100 km
# Unit conversions
50 kph in mps → 13.89 m/s
# Mixed operations
25 km / 100 km → 0.25 (dimensionless)
Compound unit aliases: kph (km/h), mph (mi/h), mps (m/s), m2 (m²), km2 (km²), ft2 (ft²)
km, m, cm, mm, mi/miles, ft/feet, in/inches
m²/m2, km²/km2, ft²/ft2, acre, hectare/ha
m/s/mps, km/h/kph, mph, knot
kg, g, mg, lb/lbs, oz, ton
L, mL, gal, m³/m3
months/mo, weeks/wk, days/d, hours/hr/h, minutes/min, seconds/sec/s
J, kJ, cal, kcal, kWh
W, kW
K/Kelvin, C/Celsius, F/Fahrenheit
TB, GB, MB, KB, bytes
Fiat: $/USD, €/EUR, £/GBP, ¥/JPY, CHF, CNY/RMB, CAD, AUD, ₹/INR, ₩/KRW, ₽/RUB, ₪/ILS, zł/PLN, ₴/UAH
Crypto: ₿/BTC, Ξ/ETH, ◎/SOL, ₮/USDT, USDC, BNB, XRP, ₳/ADA, Ð/DOGE, DOT, Ł/LTC, LINK, AVAX, MATIC, TON
graph TB
subgraph Frontends
TUI[numr-tui<br/>Ratatui Terminal UI]
CLI[numr-cli<br/>Command Line]
end
subgraph Editor[numr-editor]
Highlight[Syntax Highlighting]
end
subgraph Core[numr-core]
Parser[Parser<br/>Pest PEG Grammar]
AST[AST Builder]
Eval[Evaluator]
Types[Types<br/>Value, Currency, Unit]
Cache[Rate Cache]
Fetch[Fetch Module]
end
subgraph External APIs
Fiat[open.er-api.com<br/>Fiat Rates]
Crypto[CoinGecko API<br/>Crypto Prices]
end
TUI --> Highlight
TUI --> Parser
CLI --> Parser
Highlight --> Types
Parser --> AST
AST --> Eval
Eval --> Types
Eval --> Cache
TUI -.->|fetch on startup| Fetch
CLI -.->|fetch if cache expired| Fetch
Fetch -.-> Fiat
Fetch -.-> Crypto
Fetch -.-> Cache
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/ # HTTP fetching (optional "fetch" feature)
│ ├── numr-editor/ # Syntax highlighting (WASM-compatible)
│ ├── numr-tui/ # Terminal UI (Ratatui) with vim modes
│ └── numr-cli/ # Command-line interface and REPL
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).
User preferences are stored in ~/.config/numr/config.toml (created on first run). Toggle settings persist automatically.
Example configuration:
[preferences]
keybinding_mode = "standard"
wrap_mode = true
show_line_numbers = true
[files]
default_path = "~/Documents/default.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"If crypto_rates_url points to CoinGecko, numr automatically uses the correct demo/pro API key header based on the host.
Exchange rates are cached to ~/.config/numr/rates.json 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:
- Fiat currencies: open.er-api.com (152 currencies, free)
- Cryptocurrency: CoinGecko (15 tokens, free)
- elephant-numr — Provider for Walker/Elephant launcher
MIT
