Skip to content

remifan/lf.nvim

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

61 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

lf.nvim

Comprehensive Neovim plugin for Lingua Franca with syntax highlighting, LSP support, and interactive diagram viewing.

lf.nvim demo

✨ Features

🎨 Syntax Highlighting (Always Available)

  • Tree-sitter powered - Accurate highlighting from a grammar auto-generated from upstream Xtext
  • Zero-config install - Parser and queries are downloaded automatically on first open of a .lf file (requires curl)
  • Embedded language support - Proper highlighting for C/C++, Python, TypeScript, and Rust code blocks
  • Automatic target detection - Detects target language from target declarations
  • Textobjects ready - Ships textobjects.scm queries for use with nvim-treesitter-textobjects
  • Cross-platform - Pre-built parsers for Linux, macOS, and Windows (x64 + ARM64)

πŸš€ LSP Features (Mac/Linux Only)

Note: LSP features require Mac or Linux as Lingua Franca doesn't support Windows

  • Full LSP Support - Diagnostics, completion, hover, go-to-definition, references
  • Build Integration - Build and run LF programs from Neovim with progress reporting
  • Interactive Diagrams - View and interact with KLighD reactor diagrams in browser
  • Jump to Source - Click diagram elements to jump to code locations
  • Library Browser - Browse and import reactor libraries with Telescope
  • AST Viewer - Inspect abstract syntax tree
  • Real-time Validation - Auto-validate on save with quickfix integration

πŸ“¦ Installation

Minimal (Syntax Only)

For users who only want syntax highlighting. No dependencies required β€” the parser and queries are downloaded automatically on first open of a .lf file (requires curl):

-- lazy.nvim
{
  "remifan/lf.nvim",
  ft = "lf",
  config = function()
    require("lf").setup({
      enable_lsp = false,  -- Disable LSP features
      syntax = {
        auto_detect_target = true,
        indent = { size = 4, use_tabs = false },
      },
    })
  end,
}

Full Setup (Syntax + LSP + Diagrams)

For the complete experience with LSP, diagrams, and all features (Mac/Linux):

-- lazy.nvim
{
  "remifan/lf.nvim",
  ft = "lf",
  dependencies = {
    "nvim-telescope/telescope.nvim",    -- Optional: enhanced library browser
  },
  -- Note: Diagram dependencies build automatically on first use
  -- No need to specify build command!
  config = function()
    require("lf").setup({
      enable_lsp = true,

      -- Syntax highlighting
      syntax = {
        auto_detect_target = true,
        target_language = nil,  -- or "C", "Cpp", "Python", "Rust", "TypeScript"
        indent = { size = 4, use_tabs = false },
      },

      -- LSP configuration
      lsp = {
        -- Auto-detected if nil. Priority order:
        -- 1. Environment variable: LF_LSP_JAR
        -- 2. Explicit jar_path config below
        -- 3. Common locations (~/lingua-franca/lsp/build/libs/, etc.)
        jar_path = nil,  -- or vim.fn.expand("~/lingua-franca/lsp/build/libs/lsp-*-all.jar")
        java_cmd = "java",
        java_args = { "-Xmx2G" },
        auto_start = true,
      },

      -- Build settings
      build = {
        auto_validate = true,
        show_progress = true,
        open_quickfix = true,
      },

      -- Keymaps
      keymaps = {
        build = "<leader>lb",
        run = "<leader>lr",
        diagram = "<leader>ld",
        library = "<leader>ll",
        show_ast = "<leader>la",
      },

      -- Diagram settings
      diagram = {
        no_browser = true,   -- Default: show URL without auto-opening browser (good for SSH)
                             -- Set to false to auto-open browser locally
        auto_update = true,  -- Auto-refresh diagram when switching between LF files
      },
    })
  end,
}

🌳 Tree-sitter Setup

The tree-sitter parser is automatically installed the first time you open a .lf file (requires curl). You can also install or reinstall manually:

:LFTSInstall

Pre-built parser binaries are downloaded from GitHub for Linux, macOS, and Windows (x64 and ARM64). Falls back to local compilation if the download fails.

Textobjects: The parser ships textobjects.scm queries at tree-sitter-lf/queries/textobjects.scm, usable with nvim-treesitter-textobjects (@function.*, @class.*, @parameter.*, @block.*, @assignment.*, etc.).

πŸ› οΈ LSP Setup (Optional)

LSP features require the Lingua Franca LSP server JAR and Java 17+.

Download Pre-built JAR (Recommended)

:LFLspInstall

This downloads a pre-built JAR from the lf.nvim releases and stores it in ~/.local/share/nvim/lf-lsp/. The plugin auto-detects it on next startup.

Build from Source

git clone --recursive https://github.com/lf-lang/lingua-franca.git
cd lingua-franca
./gradlew :lsp:shadowJar

# JAR location: lsp/build/libs/lsp-VERSION-all.jar

Configuration Methods

The plugin finds the LSP JAR in this priority order:

1. Environment Variable

# In ~/.bashrc, ~/.zshrc, or shell config
export LF_LSP_JAR="$HOME/.local/share/nvim/lf-lsp/lsp-*-all.jar"

2. Explicit Configuration

lsp = {
  jar_path = vim.fn.expand("~/lingua-franca/lsp/build/libs/lsp-*-all.jar"),
}

3. Auto-Detection

If neither above is set, searches common locations:

  • ~/.local/share/nvim/lf-lsp/lsp-*-all.jar (downloaded by :LFLspInstall)
  • ~/lingua-franca/lsp/build/libs/lsp-*-all.jar
  • ./lsp/build/libs/lsp-*-all.jar (current directory)
  • ../lingua-franca/lsp/build/libs/lsp-*-all.jar (parent directory)

Verify Installation

:checkhealth lf

πŸš€ Usage

LSP Commands

Available when LSP is enabled (Mac/Linux):

Command Description
:LFBuild [args] Build current LF program
:LFRun [args] Build and run current LF program
:LFCancel Cancel current build
:LFValidate Validate current file (no compilation)
:LFInfo Show LSP server status and capabilities
:LFStart Start LSP server
:LFStop Stop LSP server
:LFRestart Restart LSP server

Diagram Commands

Command Description
:LFDiagramOpen Open interactive KLighD diagram in browser
:LFDiagram Alias for :LFDiagramOpen
:LFDiagramClose Close diagram viewer
:LFDiagramToggle Toggle diagram viewer on/off
:LFDiagramBuild Manually build diagram dependencies
:LFDiagramExport Generate and view static diagram
:LFExportDiagram [file] [format] Export diagram to file (svg, png, pdf)

Install Commands

Command Description
:LFLspInstall Download pre-built LSP server jar from GitHub releases
:LFLspStatus Show LSP server installation status
:LFTSInstall Install LF tree-sitter parser and queries
:LFTSInstall! Force reinstall (with bang)
:LFTSUninstall Remove LF tree-sitter parser
:LFTSStatus Show tree-sitter installation status

Other Commands

Command Description
:LFShowAST Show abstract syntax tree
:LFExportAST [file] Export AST to file (default: <filename>.sexp)
:LFLibrary Browse reactor library (uses Telescope if available)
:LFTargetPosition Jump to target declaration

Default Keybindings (LSP Mode)

When in a .lf buffer with LSP enabled:

  • <leader>lb - Build current file
  • <leader>lr - Build and run
  • <leader>ld - View interactive diagram
  • <leader>ll - Browse reactor library
  • <leader>la - Show AST

Standard LSP keybindings:

  • gd - Go to definition
  • gr - Show references
  • K - Hover documentation

Interactive Diagrams

The diagram viewer provides an interactive browser-based view of your reactors:

  1. Open a .lf file
  2. Run :LFDiagramOpen
  3. First time only: Dependencies build automatically (may take a few minutes)
  4. Browser opens with interactive diagram at http://localhost:8765/
  5. Click elements to jump to source code in Neovim
  6. Switch files in Neovim - diagram auto-updates (with auto_update = true)
  7. Zoom, pan, and explore reactor structure

Features:

  • Interactive KLighD diagram rendering in browser
  • Diagram β†’ Code: Click reactor instances to jump to definition in Neovim
  • Auto-refresh diagram when switching between LF files
  • Code β†’ Diagram: Sync cursor position to highlight elements in diagram
  • Diagram element search/filter

Requirements: Node.js must be installed for diagram features.

Troubleshooting: If auto-build fails, run :LFDiagramBuild manually to retry.

Architecture: Uses Node.js sidecar to bridge browser ↔ Neovim communication. The browser connects to a singleton server, and diagrams reactively update as you navigate files.

SSH/Remote Work

By default, diagrams show a URL without auto-opening the browser. Use SSH port forwarding:

# On your local machine
ssh -L 8765:localhost:8765 user@remote-server

When you run :LFDiagramOpen, Neovim displays the URL. Open it in your local browser at http://localhost:8765/

The diagram will show the current file and auto-update as you switch between files (no file parameter needed in the URL).

To auto-open browser locally (disable no-browser mode):

require("lf").setup({
  diagram = {
    no_browser = false,  -- Auto-open browser
  },
})

πŸ“– Documentation

Comprehensive help documentation:

:help lf

Topics include:

  • Installation and configuration
  • Syntax highlighting groups
  • LSP features and commands
  • Diagram interaction
  • Target language detection
  • Troubleshooting

🀝 Contributing

Contributions welcome! This plugin combines:

A weekly GitHub Action checks for upstream grammar changes, regenerates the tree-sitter grammar, validates against all upstream test files, and opens a PR automatically.

Reporting Issues

If you encounter:

  • Missing keyword highlighting
  • Incorrect syntax highlighting
  • LSP connection issues
  • Diagram rendering problems

Please open an issue with:

  1. Example .lf file demonstrating the problem
  2. Expected vs actual behavior
  3. Neovim version (:version)
  4. Platform (Mac/Linux/Windows)
  5. For LSP issues: output of :checkhealth lf and :LspLog

Development

# Clone the repository
git clone https://github.com/remifan/lf.nvim.git
cd lf.nvim

# Regenerate tree-sitter grammar from upstream Xtext
python -m xtext2ts \
  --xtext /path/to/LinguaFranca.xtext \
  --output tree-sitter-lf/grammar.js
cd tree-sitter-lf && tree-sitter generate

# Test locally (syntax only)
nvim -u NONE -c "set rtp+=." test.lf

# Install diagram dependencies (for LSP features)
cd diagram-server && npm install

πŸ”§ Troubleshooting

Syntax Highlighting Not Working

  1. Verify filetype is detected: :set ft? should show filetype=lf
  2. Check tree-sitter status: :LFTSStatus
  3. Try reinstalling tree-sitter: :LFTSInstall!
  4. Check for conflicting plugins

LSP Server Not Starting

  1. Verify Java is installed: java -version (requires Java 17+)
  2. Install or check JAR: :LFLspInstall or :LFLspStatus
  3. Check health: :checkhealth lf
  4. Manually test server: java -jar /path/to/lsp-*-all.jar
  5. Check Neovim LSP logs: :LspLog

Diagrams Not Opening

  1. Ensure Node.js is installed: node --version
  2. Install dependencies: cd diagram-server && npm install
  3. Check sidecar logs in :messages

Performance Issues

  1. Increase JVM heap: java_args = {"-Xmx4G"}
  2. Disable auto-validation: build.auto_validate = false

πŸ“– Resources

πŸ“„ License

MIT License - see LICENSE file for details.

πŸ™ Acknowledgments

About

lf-lang vibes, now in Neovim.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors