bug: treefmt seems to remove whole file in nix files
Neovim version (nvim -v)
NVIM v0.12.0-nightly+cf48741 Build type: Release LuaJIT 2.1.1741730670 Run "nvim -V1 -v" for more info
Operating system/version
nixos
Read debugging tips
- [x] I have read through the debugging tips.
Add the debug logs
- [x] I have set
log_level = vim.log.levels.DEBUGand pasted the log contents below.
Log file
treefmt root directory not found.
However, it seems that nixd formatter runs for God knows what reason, even though it is the exact same command.
Describe the bug
I made this beast, I am more asking if anybody else is able to reproduce it. whenever using treefmt on nix files+ nixd as lsp server. treefmt or something freaks the fuck out, and deletes the whole file.
What is the severity of this bug?
tolerable (can work around it)
Steps To Reproduce
- use treefmt as your everything formatter
- have this after/lsp/nixd.lua:
---@type vim.lsp.ClientConfig
return {
root_markers = { "flake.nix", ".git" },
cmd = {
"nixd",
},
filetypes = { "nix" },
settings = {
nixd = {
inlay_hints = true,
formatting = {
command = { "treefmt" },
},
nixpkgs = {
expr = "(builtins.getFlake (builtins.toString ./.)).inputs.nixpkgs {}",
},
options = {
nixOptions = {
expr = '(builtins.getFlake "/home/cdockter/Documents/myNixOS").nixosConfigurations.nixos.options',
},
home_manager = {
expr = '(builtins.getFlake "/home/cdockter/Documents/myNixOS").homeConfigurations."cdockter".options',
},
flake_parts = {
expr = "(builtins.getFlake (builtins.toString ./.)).debug.options",
},
perSystem = {
expr = "(builtins.getFlake (builtins.toString ./.)).currentSystem.options",
},
},
},
},
}
as well as this conform option set:
formatters_by_ft = {
markdown = { "injected" },
["*"] = { "treefmt" },
},
- write seemingly to any nix file
- file is now blank
Expected Behavior
I would like treefmt(the module I introduced, so I will have to fix this sometime if it is not a massive skill issue) to not delete my entire nix file. I am using treefmt-nix so that might be the issue, I will try and use treefmt proper and see if it still occurs.
Minimal example file
No response
Minimal init.lua
-- DO NOT change the paths and don't remove the colorscheme
local root = vim.fn.fnamemodify("./.repro", ":p")
-- set stdpaths to use .repro
for _, name in ipairs({ "config", "data", "state", "cache" }) do
vim.env[("XDG_%s_HOME"):format(name:upper())] = root .. "/" .. name
end
-- bootstrap lazy
local lazypath = root .. "/plugins/lazy.nvim"
if not vim.loop.fs_stat(lazypath) then
vim.fn.system({
"git",
"clone",
"--filter=blob:none",
"--single-branch",
"https://github.com/folke/lazy.nvim.git",
lazypath,
})
end
vim.opt.runtimepath:prepend(lazypath)
-- install plugins
local plugins = {
"folke/tokyonight.nvim",
{
"stevearc/conform.nvim",
config = function()
require("conform").setup({
log_level = vim.log.levels.DEBUG,
-- add your config here
})
end,
},
-- add any other plugins here
}
require("lazy").setup(plugins, {
root = root .. "/plugins",
})
vim.cmd.colorscheme("tokyonight")
-- add anything else here
Additional context
as far as I know conform calls the command; yet when I call the command, treefmt works w/o a hitch. it is possible that treefmt made it no longer possible to do it one file at a time. In which case I would remove the formatter, as I assume that running treefmt on your entire repo(even though it is very fast) can be a little annoying to have all the files change on a single write.
edit: I tested it and it seems to be a treefmt-nix issue. which makes no sense to me. I have exposed the treefmt config to the shell properly. the error that I do get is this: RPC[Error] code_name = UnknownErrorCode, message = "formatting treefmt command exited with 256"
I think it might have to do with how I am passing in formatting to treefmt, I will get back to you "tommorow" (even though it is already 01:26) when I sleep a tad bit more
I think I might know what is going on, the most recent commit to this formatter added a check for treefmt-toml, I think this is causing the issue with treefmt-nix. As in this case(as well as simply using the nixpkgs version) the toml is in the nix store
Fun fact -- after my previous PR was merged I later set up treefmt-nix for my personal dotfiles flake and did notice that, of course, not having an explicit treefmt.toml file in-source caused that flake-provided treefmt binary to not be called. However, that change still feels appropriate as the default behavior (as opposed to throwing errors).
I think there are two paths forward, and I'm not sure which is preferred from the perspective of this project.
- You (and anyone else that has treefmt set up using treefmt-nix or similar so that it doesn't need an in-source config file) can tweak the definition of treefmt [1]. Most simply, that would just be overriding
require_cwdto be false:
{
"stevearc/conform.nvim",
-- [other fields]
---@module "conform"
---@type conform.setupOpts
opts = {
formatters_by_ft = {
["*"] = { "treefmt" },
},
formatters = {
treefmt = {
require_cwd = false,
},
},
},
}
- As you suggest in https://github.com/stevearc/conform.nvim/pull/777#issuecomment-3436644113, check whether treefmt is able to run successfully rather than using
require_cwd. This is similar to what I ended up with in my own config, but felt a little specific for upstream since this is baking in specifics related to flake.nix still:
formatters = {
treefmt = (function()
local cache = {}
local function treefmt_works(cwd)
local ok, handle = pcall(
vim.system,
{ "treefmt", "--stdin", "fake.txt" },
{ cwd = cwd, stdin = "" }
)
if not ok then
return false
end
local result = handle:wait()
return result.code == 0
end
return function()
return {
cwd = require("conform.util").root_file({ "treefmt.toml", ".treefmt.toml", "flake.nix" }),
condition = function(_, ctx)
local cwd = vim.fs.root(ctx.dirname, { "treefmt.toml", ".treefmt.toml" })
if cwd then
return true
end
cwd = vim.fs.root(ctx.dirname, { "flake.nix" })
if not cwd then
return false
end
if cache[cwd] == nil then
cache[cwd] = treefmt_works(cwd)
end
return cache[cwd]
end,
}
end
end)(),
},
Perhaps that could be adapted to make sense in upstream, though.
[1]: the fact that the whole file is disappearing on you seems indicative of some larger bug somewhere else in your toolchain. While a severe side effect, I suspect it's not one that should drive the default behavior decision here?
I think that nixd's treefmt is broken.(typical of nixd in my experience) I am trying to find a way to disable nixd's formatting entirely.