Open RobertBrunhage opened 1 year ago
I second this, it would be great to have a require("formatter.filetypes.any").lsp
or something similar.
I tested the following workaround:
["*"] = {
vim.lsp.buf.format
},
This sort of worked, but in some scenarios it would give me the following error message:
"src/main.rs" 107L, 2933B written
Error detected while processing BufWritePost Autocommands for "*":
E5108: Error executing lua .../share/nvim/lazy/formatter.nvim/lua/formatter/format.lua:61: Index out of bounds
stack traceback:
[C]: in function 'get_lines'
.../share/nvim/lazy/formatter.nvim/lua/formatter/format.lua:61: in function 'start_task'
.../share/nvim/lazy/formatter.nvim/lua/formatter/format.lua:49: in function 'format'
[string ":lua"]:1: in main chunk
It will also output this if there's no matching lsp:
[LSP] Format request failed, no matching language servers.
Edit: It seems like when vim.lsp.buf.format
is ran by formatter.nvim
it freaks out whenever the number of lines changes after formatting, it works fine if the number of lines stays the same.
I second this, it would be great to have a
require("formatter.filetypes.any").lsp
or something similar.I tested the following workaround:
["*"] = { vim.lsp.buf.format },
You can do the following I believe, but that would end up running both my formatting in the specific language and then this the lsp formatter which would potentially do the same.
["*"] = {
function()
vim.lsp.buf.format
end
},
I would want something that would run only on languages that is not configured
As a workaround I've come up with the following solution:
local settings = {
lua = { require("formatter.filetypes.lua").stylua },
typescript = { require("formatter.filetypes.typescript").prettier },
json = { require("formatter.filetypes.json").fixjson },
["*"] = {
require("formatter.filetypes.any").remove_trailing_whitespace,
},
}
require("formatter").setup({
logging = false,
log_level = vim.log.levels.WARN,
filetype = settings,
})
vim.keymap.set("n", "<leader>f", function()
if settings[vim.bo.filetype] ~= nil then
vim.cmd([[Format]])
else
vim.lsp.buf.format()
end
end)
@nlsnightmare this works perfectly for me, thanks!
I will still leave this commit open in case there is a more integrated solution, otherwise close it if auther feels like that is the recommended approach.
i'm trying something similar, checking if the lsp has native formatting enabled if not then use the plugin.
Something like this in my lsp config on_attach
ignore the print statements... just for me to know which lsp has it
vim.api.nvim_buf_create_user_command(bufnr, "Format", function(_)
if vim.lsp.buf.formatting then
print("using native formatter")
vim.lsp.buf.formatting({ async = true })
else
print("using 3rd party formatter")
require('formatter.format').format({async=true})
end
end, { desc = "Format current buffer with LSP" })
end
Then call it with nmap("<leader>f", vim.cmd.Format, "Format Document")
im struggling to make it work with the require tho so i need to research more on how to call it properly :)
I also have the same problem. For example, I mentioned in my lua
settings that file "keymap.lua" shouldn't be formatted and it works fine, but in the ["*"]
part the vim.lsp.buf.format
doesn't know the condition and it formats the "keymap.lua" file.
local util = require("formatter.util")
require("formatter").setup({
logging = true,
log_level = vim.log.levels.ERROR,
filetype = {
lua = {
function()
-- Ignore files.
if
util.get_current_buffer_file_name() == "keymap.lua" or util.get_current_buffer_file_name() == "theme.lua"
then
return nil
end
return {
exe = "stylua",
args = {
"--column-width",
"120",
"--indent-type",
"Spaces",
"--indent-width",
"2",
"--search-parent-directories",
"--stdin-filepath",
util.escape_path(util.get_current_buffer_file_path()),
"--",
"-",
},
stdin = true,
}
end,
},
["*"] = {
require("formatter.filetypes.any").remove_trailing_whitespace,
function()
vim.lsp.buf.format({ async = true })
end,
},
},
})
I could fix it by this way:
["*"] = {
require("formatter.filetypes.any").remove_trailing_whitespace,
function()
-- Ignore already configured types.
local defined_types = require("formatter.config").values.filetype
if defined_types[vim.bo.filetype] ~= nil then
return nil
end
vim.lsp.buf.format({ async = true })
end,
},
But it would be great if we have something for this situation, or at least having a util function for validation like this. I can send a PR if it's acceptable approach by you.
@mortymacs' solution works great! I think adding this or a similar option as a default any-filetype-config could be great.
@mortymacs I wanted to add support for selection format, if in selection mode, by calling:
vim.lsp.buf.format({
range = {
["start"] = vim.api.nvim_buf_get_mark(0, "<"),
["end"] = vim.api.nvim_buf_get_mark(0, ">"),
}
})
But I still want to allow doing normal format if nothing is selected. But I cant find a way to find if it was in visual mode to decide what command version to call. Calling vim.api.nvim_get_mode().mode
always returns "n". I think it is because when it reaches that function it already ran exited visual mode.
vim.api.nvim_get_mode().mode
@abmantis the function and the attribute you mentioned vim.api.nvim_get_mode().mode
, works exactly as you want. I tested in different modes and it returned the correct value.
function PrintCurrentMode()
if vim.api.nvim_get_mode().mode == "v" then
print("VISUAL")
else
print("OTHER")
end
end
So, in your case, it would be something like this:
["*"] = {
-- other functions before it
function()
if vim.api.nvim_get_mode().mode == "v" then
vim.lsp.buf.format({
range = {
["start"] = vim.api.nvim_buf_get_mark(0, "<"),
["end"] = vim.api.nvim_buf_get_mark(0, ">"),
}
})
else
vim.lsp.buf.format({ async = true })
end
end,
-- other functions after it
},
@mortymacs For some reason mine always returns 'n'. It seems that the buffer returns to normal before reaching that part of the code. This is what I have:
require("formatter").setup {
filetype = {
["*"] = {
function()
print(vim.api.nvim_get_mode().mode)
if vim.api.nvim_get_mode().mode == "v" then
vim.lsp.buf.format({
range = {
["start"] = vim.api.nvim_buf_get_mark(0, "<"),
["end"] = vim.api.nvim_buf_get_mark(0, ">"),
}
})
else
vim.lsp.buf.format({ async = true })
end
end,
},
},
}
EDIT: It seems that if I use a key map instead of calling the command :Format
, it works! Thanks!
A simple integration I did for wgsl_analyzer
:
require("formatter").setup {
filetype = {
wgsl = {
function()
vim.lsp.buf.format()
end,
},
},
}
I don't mind duplicating code for other LSP formatters if they come along.
Is it possible to run the
vim.lsp.buf.format()
on all languages that is not configured withformatter
?Example usecase would be that I don't want to configure every single language to have formatting work. In my case I have a prisma file that I would like to use the normal builtin formatting from neovim/lsp vs setting up the formatting manually.
Which configuration? Type (custom or builtin): Filetype: builtin Formatter: builtin
Expected behavior Be able to run a method on all languages that are not configured, such as:
Actual behaviour Not sure how to achieve it