{"id":33571666,"url":"https://github.com/nasedkinpv/numr","last_synced_at":"2026-03-08T16:11:35.503Z","repository":{"id":325965282,"uuid":"1102585883","full_name":"nasedkinpv/numr","owner":"nasedkinpv","description":"Text calculator inspired by Numi - natural language expressions, variables, unit conversions","archived":false,"fork":false,"pushed_at":"2025-12-29T00:24:41.000Z","size":2162,"stargazers_count":189,"open_issues_count":0,"forks_count":3,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-12-31T18:25:16.926Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nasedkinpv.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-11-23T18:12:57.000Z","updated_at":"2025-12-29T09:43:20.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/nasedkinpv/numr","commit_stats":null,"previous_names":["nasedkinpv/numr"],"tags_count":13,"template":false,"template_full_name":null,"purl":"pkg:github/nasedkinpv/numr","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nasedkinpv%2Fnumr","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nasedkinpv%2Fnumr/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nasedkinpv%2Fnumr/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nasedkinpv%2Fnumr/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nasedkinpv","download_url":"https://codeload.github.com/nasedkinpv/numr/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nasedkinpv%2Fnumr/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28381492,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-13T10:00:56.084Z","status":"ssl_error","status_checked_at":"2026-01-13T09:45:11.986Z","response_time":56,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-11-28T10:00:36.094Z","updated_at":"2026-01-13T10:33:08.896Z","avatar_url":"https://github.com/nasedkinpv.png","language":"Rust","funding_links":[],"categories":["💻 Apps","Table of Contents"],"sub_categories":["🚀 Productivity and Utilities"],"readme":"\u003cp align=\"center\"\u003e\n\u003cpre\u003e\n███    ██ ██    ██ ███    ███ ██████\n████   ██ ██    ██ ████  ████ ██   ██\n██ ██  ██ ██    ██ ██ ████ ██ ██████\n██  ██ ██ ██    ██ ██  ██  ██ ██   ██\n██   ████  ██████  ██      ██ ██   ██\n\u003c/pre\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://github.com/nasedkinpv/numr/actions/workflows/ci.yml\"\u003e\u003cimg src=\"https://github.com/nasedkinpv/numr/actions/workflows/ci.yml/badge.svg\" alt=\"CI\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\nA text calculator for natural language expressions with a vim-style TUI.\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"screenshots/numr_1.png\" width=\"49%\" alt=\"numr TUI - calculations with variables, units, and currencies\"\u003e\n  \u003cimg src=\"screenshots/numr_2.png\" width=\"49%\" alt=\"numr TUI - help popup with keybindings\"\u003e\n\u003c/p\u003e\n\n## Features\n\n- **Natural language expressions**: `20% of 150`, `$100 in euros`, `2 hours + 30 min`\n- **Variables**: `tax = 15%` then `100 + tax`\n- **Unit conversions**: Length, weight, time, temperature, data sizes\n- **Currency conversions**: USD, EUR, GBP, JPY, CHF, CNY, CAD, AUD, INR, KRW, RUB, ILS, PLN, UAH + crypto (BTC, ETH, SOL, and more)\n- **Live exchange rates**: Fetched automatically on startup\n- **Vim-style editing**: Normal and Insert modes with familiar keybindings\n- **Mouse support**: Scroll with mouse wheel or trackpad\n- **File persistence**: Auto-saves to config directory, supports custom files\n- **Syntax highlighting**: Numbers, operators, variables, units, and currencies\n- **Comments**: Lines starting with `#` are treated as comments\n- **Wrap mode**: Toggle text wrapping with bottom-aligned results\n- **Grouped totals**: Currencies and units summed separately in footer (respects exchange rates)\n\n## Installation\n\n### macOS (Homebrew)\n\n```bash\nbrew tap nasedkinpv/tap\nbrew install numr\n```\n\n### Arch Linux (AUR)\n\n```bash\n# Using yay\nyay -S numr\n\n# Using paru\nparu -S numr\n```\n\n### From source\n\n```bash\n# Install from source\ncargo install --path crates/numr-tui\n\n# Or build from source\ncargo build --release\n\n# Binary will be available at target/release/numr\n```\n\n## Usage\n\n### TUI Mode\n\n```bash\n# Open default file (~/.config/numr/default.numr)\nnumr\n\n# Open specific file\nnumr example.numr\n```\n\n### CLI Mode\n\n```bash\n# Single expression\nnumr-cli \"20% of 150\"\n\n# Evaluate file\nnumr-cli -f example.numr\n\n# Interactive REPL\nnumr-cli -i\n\n# Pipe mode\necho \"100 + 200\" | numr-cli\n```\n\n### JSON-RPC Server Mode\n\nRun numr as a backend for other tools (editors, launchers, scripts):\n\n```bash\nnumr-cli --server\n```\n\nSend JSON-RPC 2.0 requests via stdin, receive responses via stdout:\n\n```bash\necho '{\"jsonrpc\":\"2.0\",\"method\":\"eval\",\"params\":{\"expr\":\"20% of 150\"},\"id\":1}' | numr-cli --server\n# {\"jsonrpc\":\"2.0\",\"result\":{\"type\":\"number\",\"value\":30.0,\"display\":\"30\"},\"id\":1}\n```\n\n**Available methods:**\n\n| Method | Params | Description |\n|--------|--------|-------------|\n| `eval` | `{\"expr\": \"...\"}` | Evaluate expression |\n| `eval_lines` | `{\"lines\": [...]}` | Evaluate multiple lines |\n| `clear` | none | Clear state |\n| `get_totals` | none | Get grouped totals |\n| `get_variables` | none | List variables |\n| `reload_rates` | none | Refresh exchange rates |\n\n## Keybindings (TUI)\n\n### Normal Mode\n\n| Key | Action |\n|-----|--------|\n| `i` | Enter Insert mode |\n| `a` | Enter Insert mode after cursor |\n| `A` | Enter Insert mode at end of line |\n| `o` | New line below and enter Insert mode |\n| `h` / `←` | Move left |\n| `j` / `↓` | Move down |\n| `k` / `↑` | Move up |\n| `l` / `→` | Move right |\n| `PageUp` | Scroll page up |\n| `PageDown` | Scroll page down |\n| `0` / `Home` | Move to start of line |\n| `$` / `End` | Move to end of line |\n| `x` | Delete character under cursor |\n| `dd` | Delete current line |\n| `W` | Toggle wrap mode |\n| `N` | Toggle line numbers |\n| `H` | Toggle header (hidden by default) |\n| `?` / `F1` | Toggle help popup |\n| `q` | Quit |\n| `Ctrl+s` | Save file |\n| `Ctrl+r` | Refresh exchange rates |\n| `F12` | Toggle debug mode |\n\n### Insert Mode\n\n| Key | Action |\n|-----|--------|\n| `Esc` | Return to Normal mode |\n| `Enter` | New line |\n| `Backspace` | Delete character before cursor |\n| `Delete` | Delete character after cursor |\n| `Arrows` | Move cursor |\n| `PageUp/Down` | Scroll page |\n| `Home/End` | Move to start/end of line |\n| `Ctrl+s` | Save file |\n| `F12` | Toggle debug mode |\n\n## Supported Operations\n\n### Arithmetic\n```\n10 + 20           → 30\n100 - 25          → 75\n6 * 7             → 42\n100 / 4           → 25\n2 ^ 8             → 256\n```\n\n### Percentages\n```\n20% of 150        → 30\n100 + 15%         → 115\n$50 - 10%         → $45\n```\n\n### Variables\n```\nprice = $100\ntax = 8%\nprice + tax       → $108\n```\n\n### Comments\n```\n# This is a comment\nGroceries         $45.00\n# Comments are dimmed and ignored in calculations\n```\n\n### Functions\n```\nsum(10, 20, 30)   → 60\navg(10, 20, 30)   → 20\nmin(5, 3, 8)      → 3\nmax(5, 3, 8)      → 8\nsqrt(16)          → 4\nabs(-5)           → 5\nround(3.7)        → 4\nfloor(3.7)        → 3\nceil(3.2)         → 4\n```\n\n## Supported Units\n\n### Length\n`km`, `m`, `cm`, `mm`, `mi`/`miles`, `ft`/`feet`, `inches`\n\n### Weight\n`kg`, `g`, `mg`, `lb`/`lbs`, `oz`\n\n### Time\n`months`/`mo`, `weeks`/`wk`, `days`/`d`, `hours`/`hr`/`h`, `minutes`/`min`, `seconds`/`sec`/`s`\n\n### Temperature\n`C`/`Celsius`, `F`/`Fahrenheit`\n\n### Data\n`TB`, `GB`, `MB`, `KB`, `bytes`\n\n### Currencies\n\n**Fiat:** `$`/`USD`, `€`/`EUR`, `£`/`GBP`, `¥`/`JPY`, `CHF`, `CNY`/`RMB`, `CAD`, `AUD`, `₹`/`INR`, `₩`/`KRW`, `₽`/`RUB`, `₪`/`ILS`, `zł`/`PLN`, `₴`/`UAH`\n\n**Crypto:** `₿`/`BTC`, `Ξ`/`ETH`, `◎`/`SOL`, `₮`/`USDT`, `USDC`, `BNB`, `XRP`, `₳`/`ADA`, `Ð`/`DOGE`, `DOT`, `Ł`/`LTC`, `LINK`, `AVAX`, `MATIC`, `TON`\n\n## Architecture\n\n```mermaid\ngraph TB\n    subgraph Frontends\n        TUI[numr-tui\u003cbr/\u003eRatatui Terminal UI]\n        CLI[numr-cli\u003cbr/\u003eCommand Line]\n    end\n\n    subgraph Editor[numr-editor]\n        Highlight[Syntax Highlighting]\n    end\n\n    subgraph Core[numr-core]\n        Parser[Parser\u003cbr/\u003ePest PEG Grammar]\n        AST[AST Builder]\n        Eval[Evaluator]\n        Types[Types\u003cbr/\u003eValue, Currency, Unit]\n        Cache[Rate Cache]\n        Fetch[Fetch Module]\n    end\n\n    subgraph External APIs\n        Fiat[open.er-api.com\u003cbr/\u003eFiat Rates]\n        Crypto[CoinGecko API\u003cbr/\u003eCrypto Prices]\n    end\n\n    TUI --\u003e Highlight\n    TUI --\u003e Parser\n    CLI --\u003e Parser\n    Highlight --\u003e Types\n    Parser --\u003e AST\n    AST --\u003e Eval\n    Eval --\u003e Types\n    Eval --\u003e Cache\n    TUI -.-\u003e|fetch on startup| Fetch\n    CLI -.-\u003e|fetch if cache expired| Fetch\n    Fetch -.-\u003e Fiat\n    Fetch -.-\u003e Crypto\n    Fetch -.-\u003e Cache\n```\n\n```\nnumr/\n├── crates/\n│   ├── numr-core/     # Core evaluation engine (WASM-compatible by default)\n│   │   ├── parser/    # Pest PEG grammar and AST builder\n│   │   ├── eval/      # Expression evaluation with unit/currency handling\n│   │   ├── types/     # Value, Currency, Unit registries\n│   │   ├── cache/     # Exchange rate caching with BFS path finding\n│   │   └── fetch/     # HTTP fetching (optional \"fetch\" feature)\n│   ├── numr-editor/   # Shared editor logic (syntax highlighting)\n│   ├── numr-tui/      # Terminal UI (Ratatui) with vim modes\n│   └── numr-cli/      # Command-line interface and REPL\n```\n\nThe 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).\n\nExchange rates are cached to `~/.config/numr/rates.json` with 1-hour expiry. Both TUI and CLI share this cache:\n- **TUI**: Fetches fresh rates on startup\n- **CLI**: Fetches only if cache is expired\n\nRate sources:\n- **Fiat currencies**: [open.er-api.com](https://open.er-api.com) (152 currencies, free)\n- **Cryptocurrency**: [CoinGecko](https://www.coingecko.com/en/api) (15 tokens, free)\n\n## License\n\nMIT\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnasedkinpv%2Fnumr","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnasedkinpv%2Fnumr","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnasedkinpv%2Fnumr/lists"}