What
Set formatexpr in LspAttach to v:lua.vim.lsp.formatexpr() so that the gq operator delegates to the attached LSP (or conform, which the config already wires as LSP fallback) instead of the built-in line-breaking algorithm.
Where
lua/config/plugin_config.lua — LspAttach autocmd, lines 104–115.
Why it matters
The config already invests in formatting quality: conform.nvim with stylua, ruff_format, prettier; default_format_opts = { lsp_format = "fallback" }; and a custom <leader>lf keymap. But gq (reformat operator / motion) still falls back to Vim's dumb line-wrapper, ignoring all of that. For prose-heavy work (Markdown notes via obsidian.nvim, inline comments) gqq / gqip / gq<motion> are natural muscle-memory, and they currently produce inconsistent results vs <leader>lf.
Neovim 0.11+ ships vim.lsp.formatexpr() exactly for this purpose.
Suggested implementation
Inside the LspAttach callback (alongside the existing gd keymap):
vim.api.nvim_create_autocmd("LspAttach", {
callback = function(ev)
local client = vim.lsp.get_client_by_id(ev.data.client_id)
-- existing completion + gd setup …
vim.bo[ev.buf].formatexpr = "v:lua.vim.lsp.formatexpr()"
end,
})
vim.lsp.formatexpr() honours the LSP textDocument/rangeFormatting method when the attached server supports it; otherwise it falls back to the built-in algorithm — so there is no regression for buffers with no LSP attached.
Note: this interacts with formatoptions. If the t or c flags are set (they are currently absent, which is correct), the formatexpr fires on auto-wrap too. With the current rqnl1j flags, formatexpr only fires on explicit gq calls, which is the desired behavior.
What
Set
formatexprinLspAttachtov:lua.vim.lsp.formatexpr()so that thegqoperator delegates to the attached LSP (or conform, which the config already wires as LSP fallback) instead of the built-in line-breaking algorithm.Where
lua/config/plugin_config.lua—LspAttachautocmd, lines 104–115.Why it matters
The config already invests in formatting quality:
conform.nvimwithstylua,ruff_format,prettier;default_format_opts = { lsp_format = "fallback" }; and a custom<leader>lfkeymap. Butgq(reformat operator / motion) still falls back to Vim's dumb line-wrapper, ignoring all of that. For prose-heavy work (Markdown notes via obsidian.nvim, inline comments)gqq/gqip/gq<motion>are natural muscle-memory, and they currently produce inconsistent results vs<leader>lf.Neovim 0.11+ ships
vim.lsp.formatexpr()exactly for this purpose.Suggested implementation
Inside the
LspAttachcallback (alongside the existinggdkeymap):vim.lsp.formatexpr()honours the LSPtextDocument/rangeFormattingmethod when the attached server supports it; otherwise it falls back to the built-in algorithm — so there is no regression for buffers with no LSP attached.Note: this interacts with
formatoptions. If thetorcflags are set (they are currently absent, which is correct), the formatexpr fires on auto-wrap too. With the currentrqnl1jflags,formatexpronly fires on explicitgqcalls, which is the desired behavior.