Open dannd4 opened 6 months ago
Great idea! Feel free to open up a PR. :)
I'm running into this problem at the moment with biome and eslint+prettier bumping into each other. I'll try and sort out the config on my end and then contribute it back here.
This is a bit annoying as the 95% of use cases is that you're either in a project that uses biome OR eslint+prettier, which is fine to configure, but it's possible that some people may want something like eslint with biome for formatting or some other configuration.
There's even the argument about HOW we run the LSP. I'd say we expect it to be in the projects dependencies and invoke it via npx/yarn/pnpm biome lsp-proxy
, but they COULD use mason...
Do you guys want to cover all use cases or just go for the most common one?
I'm in two projects currently where we're using biome as the formatter and eslint as the linter while migrating a bunch of stuff.
Could we check for the existence of a biome.json
config and use that to make decisions? It might be short-sighted but in my head any project where biome has "formatter": { "enabled": true }
turned on I think would be the true formatter even if prettier is still in node modules somewhere, since you have to manually opt-into Biome formatting by declaring it. Same thing in reverse for "linter": { "enabled": true }
(thought I can't think of many scenarios where you'd use biome as a linter and prettier as a formatter)
This is a bit annoying as the 95% of use cases is that you're either in a project that uses biome OR eslint+prettier, which is fine to configure, but it's possible that some people may want something like eslint with biome for formatting or some other configuration.
There's even the argument about HOW we run the LSP. I'd say we expect it to be in the projects dependencies and invoke it via
npx/yarn/pnpm biome lsp-proxy
, but they COULD use mason...Do you guys want to cover all use cases or just go for the most common one?
Go for the most common one, and install it trough mason for now.
I've started work on this here: https://github.com/AstroNvim/astrocommunity/pull/1006/files
Having everything supported is pretty finicky :/
That PR was closed, so I'll like to continue on this, but before that I'd like to investigate what approach we can take to suit everyone's needs.
@taskylizard Sure. I'd say copy the approach done with the ruff pack would be a great starting point. @willparsons What was the bits that were finicky?
Sure thing, it's been a long while since I last contributed here, so it will take me a bit. I'll look around the different packs and see what solution we can apply.
Great!
I decided to kang @willparsons's work on their PR and improve on bit, seems I'm a bit lost on conform support and the first task on the PR todo. I'll send a draft PR soon though.
The awkward bits were just deciding when to switch biome on and off, when it should take precedency over eslint or prettier in a repo with both, how do you determine if it's 'configured' to run, etc. Not to mention doing it for null-ls, conform and nvim-lint.
There's even the argument about HOW we run the LSP. I'd say we expect it to be in the projects dependencies and invoke it via
npx/yarn/pnpm biome lsp-proxy
, but they COULD use mason...
I found the answer for this one, so to resolve the location of the biome
binary, the pack can look into the following places in order:
node_modules
)As for 1: the vscode extension seems to determine by the package manager lockfile present in the project and executing it with that respective package manager, however I'm not sure if this is the appropriate approach to take.
@taskylizard I like that idea. I believe prettierd does that internally(i.e nodemodules vs the bundled option) As for 2: Is that a field in the biome json config?
Nope, it's something we will provide from the pack, if the user wants to use a downloaded biome binary or something, as you can install biome from homebrew or manually.
How will you do that? Is that an opt that will be passed to the pack?
The preferred way to install biome is to have it in your project. I think we should do that and only that for now.
Yeah biome is prone to changing lints on version changes (not major version), so if your biome lsp differs from the installed version you will get 2 different results that can conflict.
You can go around using the package manager by going straight into the node_modules and running the binary.
I use this for biome / prettier
local function biome_lsp_or_prettier(bufnr)
local has_biome_lsp = vim.lsp.get_clients({
bufnr = bufnr,
name = "biome",
})[1]
if has_biome_lsp then return {} end
local has_prettier = vim.fs.find({
".prettierrc",
".prettierrc.json",
".prettierrc.yml",
".prettierrc.yaml",
".prettierrc.json5",
".prettierrc.js",
".prettierrc.cjs",
".prettierrc.toml",
"prettier.config.js",
"prettier.config.cjs",
}, { upward = true })[1]
if has_prettier then return { "prettier", "prettierd" } end
return { "biome" }
end
return {
"stevearc/conform.nvim",
event = "User AstroFile",
cmd = "ConformInfo",
specs = {
{ "AstroNvim/astrolsp", optional = true, opts = { formatting = { disabled = true } } },
{ "jay-babu/mason-null-ls.nvim", optional = true, opts = { methods = { formatting = false } } },
},
dependencies = {
{ "williamboman/mason.nvim", optional = true },
{
"AstroNvim/astrocore",
opts = {
options = { opt = { formatexpr = "v:lua.require'conform'.formatexpr()" } },
commands = {
Format = {
function(args)
local range = nil
if args.count ~= -1 then
local end_line = vim.api.nvim_buf_get_lines(0, args.line2 - 1, args.line2, true)[1]
range = {
start = { args.line1, 0 },
["end"] = { args.line2, end_line:len() },
}
end
require("conform").format { async = true, lsp_format = "fallback", range = range }
end,
desc = "Format buffer",
range = true,
},
},
mappings = {
n = {
["<Leader>lf"] = { function() vim.cmd.Format() end, desc = "Format buffer" },
["<Leader>uf"] = {
function()
if vim.b.autoformat == nil then
if vim.g.autoformat == nil then vim.g.autoformat = true end
vim.b.autoformat = vim.g.autoformat
end
vim.b.autoformat = not vim.b.autoformat
require("astrocore").notify(
string.format("Buffer autoformatting %s", vim.b.autoformat and "on" or "off")
)
end,
desc = "Toggle autoformatting (buffer)",
},
["<Leader>uF"] = {
function()
if vim.g.autoformat == nil then vim.g.autoformat = true end
vim.g.autoformat = not vim.g.autoformat
vim.b.autoformat = nil
require("astrocore").notify(
string.format("Global autoformatting %s", vim.g.autoformat and "on" or "off")
)
end,
desc = "Toggle autoformatting (global)",
},
},
},
},
},
},
opts = {
format_on_save = function(bufnr)
if vim.g.autoformat == nil then vim.g.autoformat = true end
local autoformat = vim.b[bufnr].autoformat
if autoformat == nil then autoformat = vim.g.autoformat end
if autoformat then return { timeout_ms = 5000, lsp_format = "fallback" } end
end,
formatters_by_ft = {
typescript = biome_lsp_or_prettier,
javascript = biome_lsp_or_prettier,
javascriptreact = biome_lsp_or_prettier,
typescriptreact = biome_lsp_or_prettier,
json = { "biome" },
jsonc = { "biome" },
markdown = { "biome" },
toml = { "biome" },
},
},
}
How does your config work?
Is your feature related to a problem?
No response
Describe the new feature
Enable biome lsp for lspconfig and null-ls when project has @biomejs/biome dependency or has biome.json
Additional context
No response