gdshader support (highlighting, tree-sitter, LSP)
This commit is contained in:
125
README.md
125
README.md
@@ -1,93 +1,84 @@
|
|||||||
# godotdev.nvim
|
# godotdev.nvim
|
||||||
|
|
||||||
A Neovim plugin for connecting to the Godot editor LSP server to provide code navigation, diagnostics, and LSP features for GDScript projects. Supports Windows, macOS, and Linux.
|
Batteries-included Neovim plugin for **Godot game development** (Godot 4.3+), using Neovim as an external editor. Provides LSP support for GDScript and Godot shaders, DAP debugging, and Treesitter syntax highlighting.
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
- Connect to a running Godot editor's TCP LSP server.
|
- Connect to Godot editor LSP over TCP (`127.0.0.1:6005` by default)
|
||||||
- LSP-based code navigation for GDScript (`gd`/`gdscript`).
|
- Full GDScript language support
|
||||||
- Diagnostics, hover documentation, workspace symbols, and more.
|
- `.gdshader` syntax highlighting via Treesitter
|
||||||
- Healthcheck to validate editor LSP and required tools.
|
- Debug GDScript with `nvim-dap` (`127.0.0.1:6006` by default)
|
||||||
- OS-aware handling for TCP connection (`ncat` required on Windows).
|
- Keymaps for common LSP actions
|
||||||
|
- Batteries included: everything you need for Godot development in Neovim
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
- Neovim 0.11+
|
- Neovim 0.9+
|
||||||
- Godot editor with TCP LSP server enabled (Editor Settings → Network → Enable TCP LSP server).
|
- Godot 4.3+ with TCP LSP enabled
|
||||||
- **Windows:** `ncat` must be installed (via Scoop or Chocolatey).
|
- `nvim-lspconfig`
|
||||||
- **macOS/Linux:** optional `nc` for port check; otherwise assumed reachable.
|
- `nvim-dap` and `nvim-dap-ui` for debugging
|
||||||
|
- `nvim-treesitter`
|
||||||
|
- Windows users must have [`ncat`](https://nmap.org/ncat/) in PATH
|
||||||
|
|
||||||
## Installation
|
## Installation (Lazy.nvim)
|
||||||
|
|
||||||
Using [Lazy.nvim](https://github.com/folke/lazy.nvim):
|
|
||||||
```lua
|
```lua
|
||||||
`return {
|
{
|
||||||
'Mathijs-Bakker/godotdev.nvim',
|
'Mathijs-Bakker/godotdev.nvim',
|
||||||
lazy = false,
|
lazy = false,
|
||||||
|
dependencies = { 'nvim-lspconfig', 'nvim-dap', 'nvim-dap-ui', 'nvim-treesitter' },
|
||||||
config = function()
|
config = function()
|
||||||
require("godotdev").setup {
|
require("godotdev").setup()
|
||||||
editor_port = 6005, -- optional, default is 6005
|
|
||||||
editor_host = "127.0.0.1" -- optional, default is localhost
|
|
||||||
}
|
|
||||||
end
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Quickstart
|
|
||||||
|
|
||||||
```lua
|
|
||||||
-- Lazy.nvim
|
|
||||||
return {
|
|
||||||
'Mathijs-Bakker/godotdev.nvim',
|
|
||||||
config = function()
|
|
||||||
require("godotdev").setup({
|
|
||||||
editor_host = "127.0.0.1", -- Default: 127.0.0.1
|
|
||||||
editor_port = 6005, -- GDScript language server, default: 6005
|
|
||||||
debug_port = 6006, -- Debug adapter server, default: 6006
|
|
||||||
})
|
|
||||||
end,
|
end,
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
## Quickstart
|
||||||
|
|
||||||
|
1. Open your Godot project in Neovim
|
||||||
|
1. Start Godot editor with TCP LSP enabled (Editor Settings → Network → Enable TCP LSP server)
|
||||||
|
1. Open a .gd or .gdshader file
|
||||||
|
1. LSP will automatically attach
|
||||||
|
1. Use <leader>rn to rename, gd to go to definition, gr for references, etc.
|
||||||
|
1. Start debugging with DAP (Launch scene configuration)
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
```lua
|
||||||
|
require("godotdev").setup({
|
||||||
|
editor_host = "127.0.0.1", -- Godot editor host
|
||||||
|
editor_port = 6005, -- LSP port
|
||||||
|
debug_port = 6006, -- DAP port
|
||||||
|
})
|
||||||
|
```
|
||||||
|
# Keymaps
|
||||||
|
|
||||||
### LSP
|
### LSP
|
||||||
|
`gd` → Go to definition
|
||||||
- Open any `.gd` or `.gdscript` file in your Godot project.
|
`gD` → Go to declaration
|
||||||
- The plugin connects automatically to the running Godot editor LSP.
|
`gy` → Type definition
|
||||||
- Keymaps for LSP features (definitions, references, symbols, etc.) are attached per buffer.
|
`gi` → Go to implementation
|
||||||
|
`gr` → List references
|
||||||
|
`K` → Hover
|
||||||
|
`<C-k>` → Signature help
|
||||||
|
`<leader>rn` → Rename symbol
|
||||||
|
`<leader>ca` → Code action
|
||||||
|
`<leader>f` → Format buffer
|
||||||
|
`gl` → Show diagnostics
|
||||||
|
`[d` / `]d` → Previous/next diagnostic
|
||||||
|
|
||||||
### DAP
|
### DAP
|
||||||
|
`F5` -> Continue/Start
|
||||||
|
`F10` -> Step over
|
||||||
|
`F11` -> Step into
|
||||||
|
`F12` -> Step out
|
||||||
|
`<leader>db` -> Toggle Breakpoint
|
||||||
|
`<leader>dB` -> Conditional breakpoint
|
||||||
|
|
||||||
- Requires `nvim-dap` and `nvim-dap-ui`.
|
### DAP UI
|
||||||
- Launch your game or scene directly from Neovim:
|
`<leader>du` -> , Toggle UI
|
||||||
1. Make sure Godot is running with the debugger server enabled.
|
`<leader>dr` -> , Open REPL
|
||||||
1. Open a `.gd` or `.gdscript` file.
|
|
||||||
1. Use DAP commands:
|
|
||||||
- `:DapContinue` – Start/Continue debugging
|
|
||||||
- `:DapStepOver`, `:DapStepInto`, `:DapStepOut`
|
|
||||||
1. The DAP UI automatically opens when debugging starts.
|
|
||||||
|
|
||||||
### Healthcheck
|
|
||||||
|
|
||||||
```
|
|
||||||
:checkhealth godotdev
|
|
||||||
```
|
|
||||||
- Checks if the Godot editor LSP port is reachable.
|
|
||||||
- On Windows, also checks if `ncat` is installed.
|
|
||||||
- Gives clear instructions to fix missing dependencies or misconfigured ports.
|
|
||||||
|
|
||||||
## Configuration Options
|
|
||||||
```lua
|
|
||||||
`require("godotdev").setup {
|
|
||||||
editor_host = "127.0.0.1", -- default
|
|
||||||
editor_port = 6005, -- default
|
|
||||||
}`
|
|
||||||
```
|
|
||||||
|
|
||||||
## Notes
|
|
||||||
|
|
||||||
- The plugin does **not** start a Godot instance automatically; the Godot editor must be running with TCP LSP enabled.
|
|
||||||
- On Windows, `ncat` is required for the TCP LSP connection. On macOS/Linux, the plugin assumes the port is reachable.
|
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
MIT License
|
MI
|
||||||
|
|||||||
5
ftdetect/gdshader.lua
Normal file
5
ftdetect/gdshader.lua
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
vim.filetype.add({
|
||||||
|
extension = {
|
||||||
|
gdshader = "gdshader",
|
||||||
|
},
|
||||||
|
})
|
||||||
@@ -23,6 +23,8 @@ function M.setup(opts)
|
|||||||
host = M.opts.editor_host,
|
host = M.opts.editor_host,
|
||||||
port = M.opts.debug_port,
|
port = M.opts.debug_port,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
require("godotdev.tree-sitter")
|
||||||
end
|
end
|
||||||
|
|
||||||
return M
|
return M
|
||||||
|
|||||||
32
lua/godotdev/tree-sitter.lua
Normal file
32
lua/godotdev/tree-sitter.lua
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
local ok, ts_configs = pcall(require, "nvim-treesitter.configs")
|
||||||
|
if not ok then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
ts_configs.setup({
|
||||||
|
ensure_installed = { "gdscript" },
|
||||||
|
highlight = {
|
||||||
|
enable = true,
|
||||||
|
additional_vim_regex_highlighting = false,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
vim.filetype.add({
|
||||||
|
extension = {
|
||||||
|
gdshader = "gdshader",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
local parsers_ok, ts_parsers = pcall(require, "nvim-treesitter.parsers")
|
||||||
|
if parsers_ok then
|
||||||
|
local parser_configs = ts_parsers.get_parser_configs()
|
||||||
|
parser_configs.gdshader = {
|
||||||
|
used_by = { "gdshader" }, -- filetype
|
||||||
|
install_info = {
|
||||||
|
url = "", -- no external parser
|
||||||
|
files = {}, -- no parser files
|
||||||
|
generate_requires_npm = false,
|
||||||
|
requires_generate_from_grammar = false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
end
|
||||||
55
queries/gdshader/highlights.scm
Normal file
55
queries/gdshader/highlights.scm
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
;; ===========================
|
||||||
|
;; Godot Shader (GDShader) Highlights
|
||||||
|
;; Extended: multi-line comments + preprocessor
|
||||||
|
;; ===========================
|
||||||
|
|
||||||
|
;; --- Shader types ---
|
||||||
|
((identifier) @type
|
||||||
|
(#match? @type "^(spatial|canvas_item|particles|sky)$"))
|
||||||
|
|
||||||
|
;; --- Shader stages ---
|
||||||
|
((identifier) @keyword
|
||||||
|
(#match? @keyword "^(vertex|fragment|light|start)$"))
|
||||||
|
|
||||||
|
;; --- Built-in functions ---
|
||||||
|
((identifier) @function.builtin
|
||||||
|
(#match? @function.builtin
|
||||||
|
"^(abs|acos|asin|atan|ceil|clamp|cos|cross|cross2d|distance|dot|exp|floor|fract|inverse|length|lerp|max|min|normalize|pow|reflect|refract|round|sign|sin|sqrt|step|tan|transpose)$"))
|
||||||
|
|
||||||
|
;; --- Godot-specific built-in functions ---
|
||||||
|
((identifier) @function.builtin
|
||||||
|
(#match? @function.builtin
|
||||||
|
"^(NODE_POSITION_WORLD|VIEWPORT_SIZE|VIEWPORT_TEXTURE|INV_CAMERA_MATRIX|CAMERA_MATRIX|NODE_MATRIX|NODE_MATRIX_INVERSE|WORLD_MATRIX|WORLD_MATRIX_INVERSE|CAMERA_DIRECTION|SCREEN_TEXTURE|TIME)$"))
|
||||||
|
|
||||||
|
;; --- Built-in constants / vars ---
|
||||||
|
((identifier) @constant.builtin
|
||||||
|
(#match? @constant.builtin
|
||||||
|
"^(TIME|PI|TAU|E|FRAGCOORD|VERTEX|NORMAL|UV|UV2|COLOR|INSTANCE_ID|POINT_COORD|SCREEN_UV|SCREEN_PIXEL_SIZE|FRONT_FACING)$"))
|
||||||
|
|
||||||
|
;; --- Keywords ---
|
||||||
|
((identifier) @keyword
|
||||||
|
(#match? @keyword "^(uniform|varying|const|if|else|elif|for|while|break|continue|return|discard|void|in|out|inout)$"))
|
||||||
|
|
||||||
|
;; --- Types ---
|
||||||
|
((identifier) @type
|
||||||
|
(#match? @type "^(bool|int|float|vec2|vec3|vec4|mat3|mat4|sampler2D|samplerCube)$"))
|
||||||
|
|
||||||
|
;; --- Operators ---
|
||||||
|
((operator) @operator
|
||||||
|
(#match? @operator "^[+\\-*/%=!<>&|^~]+$"))
|
||||||
|
|
||||||
|
;; --- Numbers ---
|
||||||
|
((number) @number
|
||||||
|
(#match? @number "^[0-9]+(\\.[0-9]+)?$"))
|
||||||
|
|
||||||
|
;; --- Single-line comments ---
|
||||||
|
((comment) @comment
|
||||||
|
(#match? @comment "^//.*$"))
|
||||||
|
|
||||||
|
;; --- Multi-line comments ---
|
||||||
|
((comment) @comment
|
||||||
|
(#match? @comment "^/\\*.*\\*/$"))
|
||||||
|
|
||||||
|
;; --- Preprocessor / directives ---
|
||||||
|
((preproc) @keyword
|
||||||
|
(#match? @preproc "^#(version|ifdef|ifndef|else|elif|endif|define|undef|extension|error|pragma)$"))
|
||||||
20
queries/gdshader/injections.scm
Normal file
20
queries/gdshader/injections.scm
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
;; ===========================
|
||||||
|
;; GDShader Injections
|
||||||
|
;; ===========================
|
||||||
|
|
||||||
|
;; Highlight expressions inside parentheses as code
|
||||||
|
((call_expression
|
||||||
|
function: (identifier) @function
|
||||||
|
arguments: (argument_list) @parameter))
|
||||||
|
|
||||||
|
;; Highlight numbers inside function calls
|
||||||
|
((number) @number
|
||||||
|
(#match? @number "^[0-9]+(\\.[0-9]+)?$"))
|
||||||
|
|
||||||
|
;; Highlight vector constructors like vec2, vec3, vec4
|
||||||
|
((identifier) @type
|
||||||
|
(#match? @type "^(vec2|vec3|vec4|mat3|mat4)$"))
|
||||||
|
|
||||||
|
;; Highlight boolean literals inside expressions
|
||||||
|
((true) @boolean)
|
||||||
|
((false) @boolean)
|
||||||
Reference in New Issue
Block a user