Skip to content

rafacvs/vimath.nvim

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

24 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

📑 vimath.nvim – A Text-Based Calculator for Neovim

Project Summary

vimath.nvim is a Neovim plugin inspired by NoteCalc that allows you to write plain text containing assignments and expressions, and automatically view the calculated results aligned in a column inside Neovim.

Unlike a traditional calculator, the original text remains untouched. The plugin displays results as virtual text annotations, keeping the buffer clean while still giving immediate feedback.

This project is intentionally overengineered for the relatively simple problem of "calculate expressions in text".
The real goal is learning by building:

  • Designing a mini language (syntax + semantics).
  • Implementing a lexer, parser, and evaluator.
  • Integrating the language engine into Neovim via a plugin.

Motivation

  • Inspiration: This project is heavily inspired by NoteCalc. NoteCalc is a web-based notepad calculator. The idea here is to build a personal, Neovim-native alternative.
  • Personal Goal: I’ve always liked the idea of mixing text and calculations. It feels natural and helps in day-to-day tasks (budgets, quick notes, project estimations).
  • Learning Focus:
    • Understand the mechanisms of compilers/interpreters (lexer → parser → evaluator).
    • Explore plugin development in Neovim.
    • Learn Go for the core engine and Lua for Neovim integration

⚠️ Important Disclaimer:
This project is not about the output itself (calculating numbers in text).
The project is about the process of creating a small language and integrating it into Neovim.
The end result is a by-product — the real product is the learning journey.

Demonstration (Markdown Example)

Input written in a Neovim buffer:

valor1 = 5.50
valor2 = 10.50
valor3 = (valor1 * 0.99) - (valor2 * 1.2)

What you would see in Neovim (virtual text aligned to the right):

valor1 = 5.50                                 ▏5.50
valor2 = 10.50                                ▏10.50
valor3 = (valor1 * 0.99) - (valor2 * 1.2)     ▏-7.155

The marker represents the virtual text column — results are not saved in the file.

Stack & Technologies

Layer Technology Purpose
Core Engine Go Implementation of lexer, parser, evaluator.
Plugin Layer Lua (Neovim API) Extract expressions from buffer, call Go engine, render results.

Architecture Overview

Current Architecture

flowchart LR
  A[Text in Neovim Buffer] --> B[Lua Plugin Layer]
  B --> C[Call Go Engine]
  C --> D[Lexer]
  D --> E[Parser]
  E --> F[Evaluator]
  F --> G[Results]
  G --> B
  B --> H[Neovim Virtual Text Rendering]
Loading

Components:

  1. Lexer (Go)

    • Reads raw text line by line.
    • Converts it into tokens (identifiers, operators, numbers, parentheses).
  2. Parser (Go)

    • Converts token streams into an AST (abstract syntax tree).
    • Handles precedence rules, parenthesis, assignment.
  3. Evaluator (Go)

    • Walks the AST and computes values.
    • Stores variables in a symbol table.
  4. Lua Plugin (Neovim)

    • Monitors buffer changes.
    • Sends expressions to Go engine.
    • Displays results using nvim_buf_set_extmark (virtual text).

🚀 Roadmap

V1 - Core Implementation

Phase 1: Core Interpreter (Go)

Component Tasks
Lexer Tokenize identifiers, numbers, operators
Parser Basic expressions, precedence handling
Evaluator Symbol table, arithmetic, variables

Phase 2: Neovim Plugin (Lua)

Feature Description
Buffer Extraction Extract relevant lines from buffer
Engine Integration Call Go engine
Virtual Text Display Align results to the right

Next Features (Planned)

Multiple Variable Assignments

Goal: Support multiple variable assignments in a single line for improved productivity.

Current Grammar:

assignment = identifier "=" expression ;
x = 5
y = 10
z = x + y

Planned Grammar:

assignment_list = assignment { "," assignment } ;
assignment      = identifier "=" expression ;
x = 5, y = 10, z = x + y

🚀 Running the Code

Prerequisites

  • Go 1.19+ installed on your system

Command Line Usage

The core interpreter can be run from the project root directory using:

go run core/*.go --file <filename>

The --file parameter specifies which file to parse from the examples/ directory.

Examples:

go run core/*.go --file example1.txt
go run core/*.go --file parser1.txt
go run core/*.go --file evaluator1.txt

Available Test Files:

  • example1.txt - Real-world usage example with comments and complex expressions
  • parser1.txt - Basic arithmetic operations (addition, subtraction)
  • parser2.txt - Operator precedence testing (multiplication, mixed operations)
  • parser3.txt - Edge cases and complex scenarios (unary operators, division, nested parentheses)
  • parser4.txt - Error cases and boundary conditions
  • evaluator1.txt - Basic evaluator functionality tests
  • evaluator2.txt - Variable dependencies and complex calculations
  • evaluator3.txt - Edge cases and error handling (division by zero, unary operators)
  • evaluator4.txt - Mathematical functions and complex scenarios

📂 Repository Structure

vimath.nvim/
├── core/                # Core interpreter (Go)
│   ├── lexer.go
│   ├── parser.go
│   ├── evaluator.go
│   └── main.go
├── plugin/              # Neovim plugin (Lua)
│   ├── init.lua
│   └── utils.lua
├── examples/            # Example input files
│   ├── example1.txt
│   ├── parser1.txt
│   ├── parser2.txt
│   ├── parser3.txt
│   ├── parser4.txt
│   ├── evaluator1.txt
│   ├── evaluator2.txt
│   ├── evaluator3.txt
│   └── evaluator4.txt
├── docs/                # Documentation
└── README.md            # This document

📖 Relevant Notes

  • Integration Model: Initially, Go will be compiled into a binary that Lua calls via jobstart().

  • Overengineering Acknowledged: The project’s main function (evaluate expressions in text) could be solved with simpler tools (like Lua load()), but the deliberate choice is to overengineer for learning purposes.

  • Career Relevance: This project showcases both practical problem solving and deep technical exploration. It balances immediate utility (plugin) with long-term educational value (language implementation).

📌 Final Thoughts

This project's expected output is to learn:

  • How interpreters work.
  • How Neovim plugins integrate with external tools.
  • How different languages (Go vs Zig) change the way you think about performance and memory.

It solves a real workflow pain point (calculations inline in notes), but more importantly, it builds the foundation for deeper system-level knowledge.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages