diff --git a/.config/nvim/README.md b/.config/nvim/README.md index 3a5a1cc..00ca540 100644 --- a/.config/nvim/README.md +++ b/.config/nvim/README.md @@ -680,6 +680,7 @@ For non-Qubes systems, either: | Perl | perltidy | | Python | black | | Shell | shfmt | +| Terraform | terraform_fmt (shells out to the `terraform` CLI, installed via Mason) | | TeX | tex-fmt | | XML | xmlformatter | @@ -695,9 +696,13 @@ For non-Qubes systems, either: | Markdown | markdownlint | | Python | mypy, pylint, ruff | | Ruby/ERB | erb_lint | +| Terraform | tflint | > All linters above are auto-installed by `mason-tool-installer.nvim`, the > single source of truth for Mason tool provisioning. +> +> tflint runs with built-in rules by default; create a project-local +> `.tflint.hcl` (via `tflint --init`) to enable plugin rules. diff --git a/.config/nvim/lua/my/plugins/conform.lua b/.config/nvim/lua/my/plugins/conform.lua index 3d63a2d..194abcd 100644 --- a/.config/nvim/lua/my/plugins/conform.lua +++ b/.config/nvim/lua/my/plugins/conform.lua @@ -15,6 +15,8 @@ return { "perl", "python", "sh", + "terraform", + "terraform-vars", "tex", "xml", "yaml", @@ -33,6 +35,8 @@ return { perl = { "perltidy" }, python = { "black" }, sh = { "shfmt" }, + terraform = { "terraform_fmt" }, + ["terraform-vars"] = { "terraform_fmt" }, tex = { "tex-fmt" }, xml = { "xmlformatter" }, yaml = { "prettier" }, diff --git a/.config/nvim/lua/my/plugins/lspconfig.lua b/.config/nvim/lua/my/plugins/lspconfig.lua index 71ea96e..ce9a6af 100644 --- a/.config/nvim/lua/my/plugins/lspconfig.lua +++ b/.config/nvim/lua/my/plugins/lspconfig.lua @@ -160,11 +160,18 @@ local function setup_lsp_servers() }, }) -- bashls, rust_analyzer, cssls, html, jsonls, yamlls, stylelint_lsp, - -- marksman: use defaults; capabilities are injected via the '*' config - -- above, and mason-lspconfig.automatic_enable picks them up after setup. + -- marksman, terraformls: use defaults; capabilities are injected via the + -- '*' config above, and mason-lspconfig.automatic_enable picks them up + -- after setup. -- stylelint_lsp default filetypes include JS/TS which can duplicate ts_ls -- diagnostics on mixed projects; restrict reactively if friction surfaces. - require("mason-lspconfig").setup() + -- tflint is excluded: nvim-lint already runs tflint via linters_by_ft, and + -- both paths produce identical diagnostics — double-reporting otherwise. + require("mason-lspconfig").setup({ + automatic_enable = { + exclude = { "tflint" }, + }, + }) end return { diff --git a/.config/nvim/lua/my/plugins/mason-tool-installer.lua b/.config/nvim/lua/my/plugins/mason-tool-installer.lua index db86ccb..fd9a58a 100644 --- a/.config/nvim/lua/my/plugins/mason-tool-installer.lua +++ b/.config/nvim/lua/my/plugins/mason-tool-installer.lua @@ -23,6 +23,7 @@ return { "yamlls", "stylelint_lsp", "marksman", + "terraformls", -- Formatters (from conform.lua formatters_by_ft — Mason registry names) "stylua", @@ -32,6 +33,7 @@ return { "shfmt", "tex-fmt", "xmlformatter", + "terraform", -- ships the `terraform` CLI; conform's terraform_fmt shells to `terraform fmt -` -- Linters (from nvim-lint.lua linters_by_ft — Mason registry names) "revive", @@ -42,6 +44,7 @@ return { "pylint", "ruff", "erb-lint", + "tflint", }, auto_update = false, -- install-missing only, no silent drift run_on_start = true, -- async install on VimEnter diff --git a/.config/nvim/lua/my/plugins/nvim-lint.lua b/.config/nvim/lua/my/plugins/nvim-lint.lua index 301575e..3e7d1df 100644 --- a/.config/nvim/lua/my/plugins/nvim-lint.lua +++ b/.config/nvim/lua/my/plugins/nvim-lint.lua @@ -11,6 +11,7 @@ return { html = { "erb_lint" }, markdown = { "markdownlint" }, python = { "mypy", "pylint", "ruff" }, + terraform = { "tflint" }, } -- NOTE: by default, erb_lint cmd and args are expecting a diff --git a/.config/nvim/lua/my/plugins/treesitter.lua b/.config/nvim/lua/my/plugins/treesitter.lua index 5dc3faa..ac083fa 100644 --- a/.config/nvim/lua/my/plugins/treesitter.lua +++ b/.config/nvim/lua/my/plugins/treesitter.lua @@ -23,6 +23,7 @@ return { "diff", "gitcommit", "go", + "hcl", "html", "latex", "lua", @@ -30,6 +31,7 @@ return { "markdown", "python", "query", + "terraform", "vim", "vimdoc", "yaml", @@ -108,5 +110,10 @@ return { }, config = function(_, opts) require("nvim-treesitter.configs").setup(opts) + + -- `.tfvars` files get filetype `terraform-vars` (Neovim 0.11+ builtin), + -- but no dedicated treesitter parser exists. Reuse the `terraform` + -- parser for highlighting/text-objects on those buffers. + vim.treesitter.language.register("terraform", "terraform-vars") end, } diff --git a/.config/nvim/lua/my/settings/filetypes.lua b/.config/nvim/lua/my/settings/filetypes.lua new file mode 100644 index 0000000..c85718d --- /dev/null +++ b/.config/nvim/lua/my/settings/filetypes.lua @@ -0,0 +1,14 @@ +-- luacheck: globals vim + +-- Filetype overrides. Loaded eagerly via `lua/my/settings/init.lua` so +-- detection is in place before the first buffer is read. + +-- `.tf` files: Neovim's builtin detect.tf inspects content and falls back to +-- the legacy `tf` filetype on empty / comment-only buffers, which prevents +-- terraform-ls from attaching to fresh files. Force `terraform` unconditionally +-- (the `.tfvars` → `terraform-vars` mapping is unaffected and stays builtin). +vim.filetype.add({ + extension = { + tf = "terraform", + }, +}) diff --git a/.config/nvim/lua/my/settings/init.lua b/.config/nvim/lua/my/settings/init.lua index b196bca..b737779 100644 --- a/.config/nvim/lua/my/settings/init.lua +++ b/.config/nvim/lua/my/settings/init.lua @@ -1,3 +1,4 @@ require("my.settings.vim_env") require("my.settings.vim_opt") require("my.settings.vim_g") +require("my.settings.filetypes")