Neovim plugin for the Dingo programming language - a meta-language for Go with enhanced type safety and modern syntax.
- LSP Integration: Full language server support via
dingo-lsp(wrapsgoplswith 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:
:DingoBuildand:DingoRunfor compilation and execution - Health Checks:
:checkhealth dingoto verify setup - Mason Support: Automatic tool installation via mason.nvim
{
"MadAppGang/dingo.nvim",
ft = "dingo",
config = function()
require("dingo").setup()
end,
}{
"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" },
},
}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,
},
}use {
"MadAppGang/dingo.nvim",
ft = "dingo",
requires = {
"williamboman/mason.nvim",
"williamboman/mason-lspconfig.nvim",
},
config = function()
require("dingo").setup()
end,
}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()
EOFFor 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,
}The plugin automatically registers a dingo_fmt formatter with conform.nvim if it's installed. No manual configuration needed!
When you call require("dingo").setup(), the plugin:
- Detects if conform.nvim is installed
- Registers
dingo_fmtformatter (usesdingo fmtvia stdin) - Maps the
dingofiletype to usedingo_fmt
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,
},
},
}If you see "Formatter 'gofumpt' timeout" when formatting .dingo files:
- Cause: conform.nvim's
lsp_fallback = truetriggers gopls formatting - Solution: Ensure dingo.nvim is loaded before you open
.dingofiles so the formatter registers
Check if the formatter is registered:
:ConformInfoYou should see dingo_fmt listed for the dingo filetype.
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,
})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@latestNote: Mason registry support for
dingoanddingo-lspis planned. Once available, you'll be able to install them with:MasonInstall dingo dingo-lsp.
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" },
},
})| 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 |
Ensure $GOPATH/bin is in your $PATH:
# In ~/.bashrc, ~/.zshrc, or equivalent
export PATH="$PATH:$(go env GOPATH)/bin"# Check all tools are available
which dingo dingo-lsp gopls
# Test each tool
dingo --version
gopls versionOr in Neovim:
:checkhealth dingorequire("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" },
},
})require("dingo").setup({
format = { enabled = false },
lint = { enabled = false },
})require("dingo").setup({
format = { on_save = false },
})require("dingo").setup({
lsp = { log_level = "debug" },
})require("dingo").setup({
lint = {
on_save = true,
on_insert_leave = true, -- Lint when leaving insert mode
},
})| 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 |
-- 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" })With dingo-lsp running, you get full IDE support:
- Go to Definition: Jump to symbol definitions (in
.dingoor.gofiles) - 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).
The plugin includes a tree-sitter grammar for Dingo, providing:
- Syntax highlighting for Dingo-specific features
- Code folding
- Indentation
- Text objects (future)
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 buildThen in Neovim:
:TSInstallFromGrammar dingoThe plugin automatically configures Dingo files (.dingo) with:
- Comment string:
// %s - Indentation: Tabs (like Go)
- Tab width: 4 spaces
- Smart indent enabled
:checkhealth dingoThis will verify:
- Neovim version (0.8+ required)
dingoexecutable is in PATHdingo-lspexecutable is in PATHgoplsis installed- Tree-sitter parser is available
-
Verify
dingo-lspis installed:which dingo-lsp
-
Check LSP logs:
:lua vim.cmd('e ' .. vim.lsp.get_log_path())
-
Enable debug logging:
require("dingo").setup({ lsp = { log_level = "debug" } })
-
Ensure
goplsis installed (required bydingo-lsp):which gopls # Or install via Mason :MasonInstall gopls
-
Verify
dingo fmtworks from command line:dingo fmt -w yourfile.dingo
-
Check file has a name (
:echo expand('%:p')) -
Disable and format manually:
:DingoFormat
-
Verify
dingo lintworks:dingo lint --json yourfile.dingo
-
Check lint is enabled in config
-
Run manually:
:DingoLint
-
Check parser is installed:
:TSInstallInfo dingo
-
Verify tree-sitter is loaded:
:lua =vim.treesitter.language.add("dingo", true)
-
Inspect parsed tree:
:InspectTree
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
# 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'}"Contributions welcome! Please:
- Follow existing code style
- Test with
:checkhealth dingo - Update documentation
- Add tests for new features
MIT License - see LICENSE for details.
- 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