Skip to content

MadAppGang/dingo.nvim

Repository files navigation

dingo.nvim

Neovim plugin for the Dingo programming language - a meta-language for Go with enhanced type safety and modern syntax.

Features

  • LSP Integration: Full language server support via dingo-lsp (wraps gopls with source map translation)
  • Tree-sitter Syntax: Superior syntax highlighting for Dingo-specific features (enum, match, ? operator, lambdas)
  • Format on Save: Automatic formatting with dingo fmt
  • Lint Integration: Real-time diagnostics with dingo lint
  • Build Commands: :DingoBuild and :DingoRun for compilation and execution
  • Health Checks: :checkhealth dingo to verify setup
  • Mason Support: Automatic tool installation via mason.nvim

Installation

Using lazy.nvim (Recommended)

Basic Installation

{
  "MadAppGang/dingo.nvim",
  ft = "dingo",
  config = function()
    require("dingo").setup()
  end,
}

Full-Featured Setup

{
  "MadAppGang/dingo.nvim",
  ft = "dingo",
  config = function()
    require("dingo").setup({
      lsp = {
        enabled = true,
        log_level = "info",
      },
      format = {
        enabled = true,
        on_save = true,
      },
      lint = {
        enabled = true,
        on_save = true,
      },
    })
  end,
  keys = {
    { "<leader>db", "<cmd>DingoBuild<cr>", desc = "Dingo Build" },
    { "<leader>dr", "<cmd>DingoRun<cr>", desc = "Dingo Run" },
    { "<leader>df", "<cmd>DingoFormat<cr>", desc = "Dingo Format" },
    { "<leader>dl", "<cmd>DingoLint<cr>", desc = "Dingo Lint" },
    { "<leader>dt", "<cmd>DingoTranspile<cr>", desc = "Dingo Transpile" },
  },
}

LazyVim Distribution

If you're using LazyVim, add this to your plugins:

-- lua/plugins/dingo.lua
return {
  {
    "MadAppGang/dingo.nvim",
    ft = "dingo",
    opts = {
      lsp = { enabled = true },
      format = { on_save = true },
      lint = { on_save = true },
    },
    keys = {
      { "<leader>cB", "<cmd>DingoBuild<cr>", desc = "Build (Dingo)" },
      { "<leader>cR", "<cmd>DingoRun<cr>", desc = "Run (Dingo)" },
      { "<leader>cT", "<cmd>DingoTranspile<cr>", desc = "Transpile (Dingo)" },
    },
  },

  -- Ensure gopls is installed via Mason
  {
    "williamboman/mason.nvim",
    opts = function(_, opts)
      opts.ensure_installed = opts.ensure_installed or {}
      vim.list_extend(opts.ensure_installed, { "gopls" })
    end,
  },
}

Using packer.nvim

use {
  "MadAppGang/dingo.nvim",
  ft = "dingo",
  requires = {
    "williamboman/mason.nvim",
    "williamboman/mason-lspconfig.nvim",
  },
  config = function()
    require("dingo").setup()
  end,
}

Using vim-plug

Plug 'williamboman/mason.nvim'
Plug 'williamboman/mason-lspconfig.nvim'
Plug 'MadAppGang/dingo.nvim', { 'for': 'dingo' }

lua << EOF
require("mason").setup()
require("mason-lspconfig").setup({
  ensure_installed = { "gopls" },
})
require("dingo").setup()
EOF

Local Development Installation

For contributing or testing local changes:

-- lazy.nvim with local path
{
  dir = "~/projects/dingo.nvim",  -- Your local path
  ft = "dingo",
  config = function()
    require("dingo").setup()
  end,
}

conform.nvim Integration

The plugin automatically registers a dingo_fmt formatter with conform.nvim if it's installed. No manual configuration needed!

How It Works

When you call require("dingo").setup(), the plugin:

  1. Detects if conform.nvim is installed
  2. Registers dingo_fmt formatter (uses dingo fmt via stdin)
  3. Maps the dingo filetype to use dingo_fmt

Manual Configuration (Optional)

If you prefer explicit control or automatic registration doesn't work, add this to your conform config:

-- lua/configs/conform.lua
return {
  formatters_by_ft = {
    dingo = { "dingo_fmt" },
    -- your other formatters...
  },

  formatters = {
    dingo_fmt = {
      command = "dingo",
      args = { "fmt" },
      stdin = true,
    },
  },
}

Troubleshooting Format Issues

If you see "Formatter 'gofumpt' timeout" when formatting .dingo files:

  1. Cause: conform.nvim's lsp_fallback = true triggers gopls formatting
  2. Solution: Ensure dingo.nvim is loaded before you open .dingo files so the formatter registers

Check if the formatter is registered:

:ConformInfo

You should see dingo_fmt listed for the dingo filetype.

Mason Integration

Automatic gopls Installation

The dingo-lsp language server requires gopls to work. Mason can automatically install it:

require("mason").setup()
require("mason-lspconfig").setup({
  ensure_installed = { "gopls" },
  automatic_installation = true,
})

Manual Dingo Tools Installation

Currently, dingo and dingo-lsp need to be installed manually via Go:

# Install dingo CLI
go install github.com/MadAppGang/dingo/cmd/dingo@latest

# Install dingo-lsp (Language Server)
go install github.com/MadAppGang/dingo/cmd/dingo-lsp@latest

Note: Mason registry support for dingo and dingo-lsp is planned. Once available, you'll be able to install them with :MasonInstall dingo dingo-lsp.

Custom Tool Paths with Mason

If Mason installs tools to a custom location, configure the paths:

require("dingo").setup({
  lsp = {
    cmd = { vim.fn.stdpath("data") .. "/mason/bin/dingo-lsp" },
  },
  format = {
    cmd = { vim.fn.stdpath("data") .. "/mason/bin/dingo", "fmt", "-w" },
  },
  lint = {
    cmd = { vim.fn.stdpath("data") .. "/mason/bin/dingo", "lint", "--json" },
  },
})

Prerequisites

Required Tools

Tool Purpose Installation
dingo CLI for building/formatting/linting go install github.com/MadAppGang/dingo/cmd/dingo@latest
dingo-lsp Language Server go install github.com/MadAppGang/dingo/cmd/dingo-lsp@latest
gopls Go Language Server (used internally) go install golang.org/x/tools/gopls@latest or :MasonInstall gopls

Environment Setup

Ensure $GOPATH/bin is in your $PATH:

# In ~/.bashrc, ~/.zshrc, or equivalent
export PATH="$PATH:$(go env GOPATH)/bin"

Verify Installation

# Check all tools are available
which dingo dingo-lsp gopls

# Test each tool
dingo --version
gopls version

Or in Neovim:

:checkhealth dingo

Configuration

Default Configuration

require("dingo").setup({
  lsp = {
    enabled = true,
    cmd = { "dingo-lsp" },
    filetypes = { "dingo" },
    root_patterns = { "go.mod", ".git" },
    settings = {},
    log_level = "info",  -- trace, debug, info, warn, error
  },

  format = {
    enabled = true,
    on_save = true,
    timeout_ms = 2000,
    cmd = { "dingo", "fmt", "-w" },
  },

  lint = {
    enabled = true,
    on_save = true,
    on_insert_leave = false,
    cmd = { "dingo", "lint", "--json" },
    virtual_text = true,
    signs = true,
  },

  build = {
    cmd = { "dingo", "build", "--no-mascot" },
    run_cmd = { "dingo", "run" },
  },
})

Common Configurations

Minimal (LSP only)

require("dingo").setup({
  format = { enabled = false },
  lint = { enabled = false },
})

Disable Format on Save

require("dingo").setup({
  format = { on_save = false },
})

Debug LSP Issues

require("dingo").setup({
  lsp = { log_level = "debug" },
})

Aggressive Linting

require("dingo").setup({
  lint = {
    on_save = true,
    on_insert_leave = true,  -- Lint when leaving insert mode
  },
})

Commands

Command Description
:DingoBuild Build the current Dingo project
:DingoBuild! Build only the current file
:DingoRun [args] Run the current Dingo file with optional arguments
:DingoTranspile Transpile to Go and open the generated .go file
:DingoFormat Format the current buffer
:DingoLint Lint the current buffer
:DingoLintClear Clear lint diagnostics

Suggested Keybindings

-- In your Neovim config
vim.keymap.set("n", "<leader>db", "<cmd>DingoBuild<cr>", { desc = "Dingo Build" })
vim.keymap.set("n", "<leader>dr", "<cmd>DingoRun<cr>", { desc = "Dingo Run" })
vim.keymap.set("n", "<leader>df", "<cmd>DingoFormat<cr>", { desc = "Dingo Format" })
vim.keymap.set("n", "<leader>dl", "<cmd>DingoLint<cr>", { desc = "Dingo Lint" })
vim.keymap.set("n", "<leader>dt", "<cmd>DingoTranspile<cr>", { desc = "Dingo Transpile" })

LSP Features

With dingo-lsp running, you get full IDE support:

  • Go to Definition: Jump to symbol definitions (in .dingo or .go files)
  • Hover Documentation: View type information and docs
  • Completion: Intelligent code completion
  • Diagnostics: Real-time error checking from gopls
  • Rename: Refactor symbol names across files
  • References: Find all usages of a symbol
  • Signature Help: Function parameter hints

All LSP features work seamlessly because dingo-lsp translates positions between .dingo and .go files using source maps (.dmap files).

Tree-sitter

The plugin includes a tree-sitter grammar for Dingo, providing:

  • Syntax highlighting for Dingo-specific features
  • Code folding
  • Indentation
  • Text objects (future)

Installing the Parser

If you use nvim-treesitter:

require("nvim-treesitter.configs").setup({
  ensure_installed = { "dingo" },  -- After parser is published
})

For local development:

cd /path/to/dingo/editors/nvim/tree-sitter-dingo
npm install
npm run build

Then in Neovim:

:TSInstallFromGrammar dingo

File Type Settings

The plugin automatically configures Dingo files (.dingo) with:

  • Comment string: // %s
  • Indentation: Tabs (like Go)
  • Tab width: 4 spaces
  • Smart indent enabled

Troubleshooting

Check Plugin Health

:checkhealth dingo

This will verify:

  • Neovim version (0.8+ required)
  • dingo executable is in PATH
  • dingo-lsp executable is in PATH
  • gopls is installed
  • Tree-sitter parser is available

LSP Not Starting

  1. Verify dingo-lsp is installed:

    which dingo-lsp
  2. Check LSP logs:

    :lua vim.cmd('e ' .. vim.lsp.get_log_path())
  3. Enable debug logging:

    require("dingo").setup({
      lsp = { log_level = "debug" }
    })
  4. Ensure gopls is installed (required by dingo-lsp):

    which gopls
    # Or install via Mason
    :MasonInstall gopls

Format Not Working

  1. Verify dingo fmt works from command line:

    dingo fmt -w yourfile.dingo
  2. Check file has a name (:echo expand('%:p'))

  3. Disable and format manually:

    :DingoFormat

Lint Diagnostics Not Showing

  1. Verify dingo lint works:

    dingo lint --json yourfile.dingo
  2. Check lint is enabled in config

  3. Run manually:

    :DingoLint

Tree-sitter Highlighting Not Working

  1. Check parser is installed:

    :TSInstallInfo dingo
  2. Verify tree-sitter is loaded:

    :lua =vim.treesitter.language.add("dingo", true)
  3. Inspect parsed tree:

    :InspectTree

Development

Project Structure

editors/nvim/
├── ftdetect/dingo.lua       # Filetype detection
├── ftplugin/dingo.lua       # Filetype settings
├── lua/dingo/
│   ├── init.lua             # Main entry point
│   ├── config.lua           # Configuration management
│   ├── lsp.lua              # LSP client setup
│   ├── format.lua           # Formatter integration
│   ├── lint.lua             # Linter integration
│   ├── commands.lua         # User commands
│   ├── health.lua           # Health checks
│   └── treesitter.lua       # Parser registration
├── queries/dingo/           # Tree-sitter queries
│   ├── highlights.scm       # Syntax highlighting
│   ├── folds.scm            # Code folding
│   └── indents.scm          # Indentation
├── doc/dingo.txt            # Vim help documentation
└── tree-sitter-dingo/       # Tree-sitter grammar

Running Tests

# Test tree-sitter grammar
cd tree-sitter-dingo
npm test

# Test in Neovim
nvim --headless -u minimal_init.lua -c "PlenaryBustedDirectory tests/ {minimal_init = 'minimal_init.lua'}"

Contributing

Contributions welcome! Please:

  1. Follow existing code style
  2. Test with :checkhealth dingo
  3. Update documentation
  4. Add tests for new features

License

MIT License - see LICENSE for details.

Related Projects

  • Dingo - The Dingo language transpiler
  • dingo-lsp - Language Server Protocol implementation
  • mason.nvim - Package manager for Neovim
  • tree-sitter - Parser generator and incremental parsing library

Resources

About

Neovim plugin for Dingo language

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 2

  •  
  •