The function vim.lsp.buf.format({ async = true })
formats the entire buffer. However, In most cases, I’m interested in formatting only a small part of it. Is there a way to format only a text object instead? E.g. I would like gfip
to format an inner paragraph, where gf
is the formatting action and ip
the text object.
There is the " range formatting " option in vim.lsp.buf.format()
;
format({options}) *vim.lsp.buf.format()*
Formats a buffer using the attached (and optionally filtered) language
server clients.
Parameters:
{options} table|nil Optional table which holds the following optional
fields:
.....
• range (table|nil) Range to format. Table must contain
`start` and `end` keys with {row, col} tuples using (1,0)
indexing. Defaults to current selection in visual mode
Defaults to `nil` in other modes, formatting the full
buffer
Does it work for you?
Thanks @kay-adamof . This is just what I need to create the text-object myself. However, I’ve only created text-objects in vimscript. I’ll try to do it in Lua this time.
Edit: for reference, here is an amazing guide on how to code text-objects in Lua: How to Create Vim Text-Objects in Lua
Edit 2: I realized that rather than writing a “text-object”, what I actually need is to write an operator (:h map-operator).
Edit 3: This problem has been solved here:
and here:
Edit 4: the solution in the links above generates a warning because vim.lsp.buf.range_formatting
has been deprecated. I will replace it with @kay-adamof’s suggestion and post the code.
function format_range_operator()
local old_func = vim.go.operatorfunc
_G.op_func_formatting = function()
local opts = {
range = {
['start'] = vim.api.nvim_buf_get_mark(0, '['),
['end'] = vim.api.nvim_buf_get_mark(0, ']'),
}
}
vim.lsp.buf.format(opts)
vim.go.operatorfunc = old_func
_G.op_func_formatting = nil
end
vim.go.operatorfunc = 'v:lua.op_func_formatting'
vim.api.nvim_feedkeys('g@', 'n', false)
end
vim.keymap.set("n", "gf", "<Cmd>lua format_range_operator()<Cr>")
This works, but the support of the range
argument of the different LSP servers is not that good at the moment. Hopefully, it will improve with time.
I am not sure if I am getting this right.
formatexpr
is already mapped to vim.lsp.formatexpr()
which leverages the vim.lsp.buf.format(opts)
So why not just do gqip
or gq
and any textobject?
I had no idea this was the case. You are right, there was no need to implement a custom format operator . But ok, at least I learned something. Thanks, @ranjithshegde.