stevearc / conform.nvim

Lightweight yet powerful formatter plugin for Neovim
MIT License
2.72k stars 142 forks source link

bug: (almost certainly user error) conform won't format Vue files on write #347

Closed nexxai closed 4 months ago

nexxai commented 4 months ago

Neovim version (nvim -v)

NVIM v0.9.5

Operating system/version

macOS Sonoma 14.4

Add the debug logs

Log file

Log file: /Users/nexxai/.local/state/nvim/conform.log

Formatters for this buffer: LSP: null-ls, volar

Other formatters: black ready (python) /Users/nexxai/.local/share/nvim/mason/bin/black blade-formatter ready (blade) /Users/nexxai/.local/share/nvim/mason/bin/blade-formatter pint ready (php) /Users/nexxai/.local/share/nvim/mason/bin/pint prettierd ready (javascript) /Users/nexxai/.local/share/nvim/mason/bin/prettierd rustywind ready (blade) /Users/nexxai/.local/share/nvim/mason/bin/rustywind

Describe the bug

Even though I've tried to configure Conform to format on save, when I write out a buffer that requires formatting, nothing happens (the buffer is saved but is not formatted).

What is the severity of this bug?

minor (annoyance)

Steps To Reproduce

  1. Open a .vue file with various different tabs/spaces on lines
  2. Attempt to save the buffer

Expected Behavior

The file to be formatted correctly and then written

Minimal example file

<template>
                    <SpotlightCard
                        from="#1cd1c6"
                        via="#407cff"
                        size="300"   
                        class="rounded-[--radius] bg-white/10 p-6 [--radius:theme(borderRadius.xl)] print:p-0 print:rounded-none"
                        >
    ></SpotlightCard>
                        </template>

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

I can confirm the issue still happens using the provided minimal repro.lua.

When I run :ConformInfo in a .vue file, I get the following, which seems odd since I would assume prettierd should be loaded for this specific buffer

Log file: /Users/nexxai/.local/state/nvim/conform.log

Formatters for this buffer:
LSP: null-ls, volar

Other formatters:
black ready (python) /Users/nexxai/.local/share/nvim/mason/bin/black
blade-formatter ready (blade) /Users/nexxai/.local/share/nvim/mason/bin/blade-formatter
pint ready (php) /Users/nexxai/.local/share/nvim/mason/bin/pint
prettierd ready (javascript) /Users/nexxai/.local/share/nvim/mason/bin/prettierd
rustywind ready (blade) /Users/nexxai/.local/share/nvim/mason/bin/rustywind

Again, I am nearly 100% confident this is not actually a bug with Conform, but rather an issue with me, but I don't know where to even start looking to troubleshoot this.

Also, in case it matters, I'm using LazyVim and this is my lua/plugins/vue.lua file:

return {
  "stevearc/conform.nvim",
  lazy = true,
  event = { "BufReadPre", "BufNewFile", "BufWritePre", "BufWriteCmd" },
  optional = false,
  opts = {
    format_on_save = {
        -- These options will be passed to conform.format()
        timeout_ms = 500,
        lsp_fallback = true,
    },

    formatters_by_ft = {
      ["javascript"] = { "prettier" },
      ["javascriptreact"] = { "prettier" },
      ["typescript"] = { "prettier" },
      ["typescriptreact"] = { "prettier" },
      ["vue"] = { "prettier" },                      -- <-- loading vue here
      ["css"] = { "prettier" },
      ["scss"] = { "prettier" },
      ["less"] = { "prettier" },
      ["html"] = { "prettier" },
      ["json"] = { "prettier" },
      ["jsonc"] = { "prettier" },
      ["yaml"] = { "prettier" },
      ["markdown"] = { "prettier" },
      ["markdown.mdx"] = { "prettier" },
      ["graphql"] = { "prettier" },
      ["handlebars"] = { "prettier" },
    },
  },
}
stevearc commented 4 months ago

I believe that your vue.lua file may not be getting loaded. When looking at the "other formatters" list, each formatter should list all filetypes that it's active for in parentheses. I see prettierd ready (javascript), so prettierd is configured for javascript files only, and I don't see prettier listed at all. Another thing you can look at while debugging is :au BufWritePre. This will show you all of the autocmds that are configured to run on BufWritePre. If format-on-save is configured, we would expect to see an entry like

Conform  BufWritePre
    *         <Lua 373: ~/dotfiles/vimplugins/conform.nvim/lua/conform/init.lua:94> [Format on save]
nexxai commented 4 months ago

Interesting. All of my other plugins following that same pattern seem to be getting loaded normally, but this is the result of :au BufWritePre:

--- Autocommands ---
lazyvim_auto_create_dir  BufWritePre
*<Lua 275: ~/.local/share/nvim/lazy/LazyVim/lua/lazyvim/config/autocmds.lua:108>
LazyFormat  BufWritePre
*<Lua 506: ~/.local/share/nvim/lazy/LazyVim/lua/lazyvim/util/format.lua:155>
lsp_c_1_b_3_save  BufWritePre
<buffer=3><Lua 1207: /opt/homebrew/Cellar/neovim/0.9.5/share/nvim/runtime/lua/vim/lsp.lua:1652> [vim.lsp: textDocument/willSave]
gitsigns  BufWritePre
<buffer=3><Lua 1001: ~/.local/share/nvim/lazy/gitsigns.nvim/lua/gitsigns/attach.lua:368>

Nothing about conform. I will keep digging in to see what else I can find.

nexxai commented 4 months ago

Ok, so interesting development. I actually misstated my original bug report; the file wasn't called vue.lua, it was called js-and-vue.lua. Your asking about vue.lua made me realize that there was technically an incongruency between my report and reality, so I wondered: "What if the dashes in the file name are causing a problem?"

I renamed the file to vue.lua and now, the first time I try to save a .vue file, I get this error (which was not happening before):

Don't set `opts.format_on_save` for `conform.nvim`.
**LazyVim** will use the conform formatter automatically

Ok fine, I'll remove that opt in my config.

I'm still getting this for :au BufWritePre when inside a .vue file

--- Autocommands ---
lazyvim_auto_create_dir  BufWritePre
*<Lua 275: ~/.local/share/nvim/lazy/LazyVim/lua/lazyvim/config/autocmds.lua:108>
LazyFormat  BufWritePre
*<Lua 582: ~/.local/share/nvim/lazy/LazyVim/lua/lazyvim/util/format.lua:155>
lsp_c_1_b_3_save  BufWritePre
<buffer=3><Lua 614: /opt/homebrew/Cellar/neovim/0.9.5/share/nvim/runtime/lua/vim/lsp.lua:1652> [vim.lsp: textDocument/willSave]
gitsigns  BufWritePre
<buffer=3><Lua 887: ~/.local/share/nvim/lazy/gitsigns.nvim/lua/gitsigns/attach.lua:368>

But still, progress is progress?

nexxai commented 4 months ago

Also just checked, now :ConformInfo shows:

Log file: /Users/nexxai/.local/state/nvim/conform.log

Formatters for this buffer:
LSP: null-ls, volar
prettier ready (typescript, markdown, graphql, markdown.mdx, less, scss, css, vue, typescriptreact, javascriptreact, html, javascript, jsonc, yaml, handlebars, json) /Users/nexxai/code/dev.nexxai.dev-vue/node_modules/.bin/prettier

Other formatters:
black ready (python) /Users/nexxai/.local/share/nvim/mason/bin/black
blade-formatter ready (blade) /Users/nexxai/.local/share/nvim/mason/bin/blade-formatter
pint ready (php) /Users/nexxai/.local/share/nvim/mason/bin/pint
rustywind ready (blade) /Users/nexxai/.local/share/nvim/mason/bin/rustywind

Prettier is listed as ready there now for vue files so I feel like that's a good thing. It's still not formatting on save, but I feel like I'm getting closer.

nexxai commented 4 months ago

And for posterity's sake, the prettier that it's referring to definitely exists:

9:46:29 PM in dev.nexxai.dev-vue on  main [!] via 🍞 v1.0.30 via  v21.7.0
🔋 99% ➜ pwd
/Users/nexxai/code/dev.nexxai.dev-vue

9:46:34 PM in dev.nexxai.dev-vue on  main [!] via 🍞 v1.0.30 via  v21.7.0
🔋 99% ➜ ls -al node_modules/.bin/prettier
lrwxr-xr-x@ - nexxai 22 Mar 19:16 node_modules/.bin/prettier -> ../prettier/bin/prettier.cjs
stevearc commented 4 months ago

Great, the config all looks good to me! I think you won't see the exact same Conform augroup since LazyVim wraps it and does some custom logic. This entry should be the LazyVim formatting on save:

LazyFormat  BufWritePre
*<Lua 582: ~/.local/share/nvim/lazy/LazyVim/lua/lazyvim/util/format.lua:155>

Is there any output whatsoever in the conform log file? Remember to set log_level = vim.log.levels.DEBUG in the opts. You should also try a manual format (I think LazyVim has some binding for this) to see if that formats/produces log output.

nexxai commented 4 months ago

So I saw in the recipes/ folder in this repo that there was a recommended LazyVim config, and in there you have a keys table:

  keys = {
    {
      -- Customize or remove this keymap to your liking
      "<leader>f",
      function()
        require("conform").format({ async = true, lsp_fallback = true })
      end,
      mode = "",
      desc = "Format buffer",
    },
  },

So after adding the log_level in opts, and that keys table, I can now successfully do <leader>f and it will format the open file, but no logs are being created anywhere and the auto-formatting still isn't happening.

At this point, I feel like I'm so close I can taste it, but there's just like one or two more things that need to happen to make this work lol

nexxai commented 4 months ago

Sorry I lied, I wasn't looking in the right place for the log.

Here's what was output to it:

21:58:19[DEBUG] Running formatters on /Users/nexxai/code/dev.nexxai.dev-vue/src/views/CVView.vue: { "prettier" }
21:58:19[INFO] Run prettier on /Users/nexxai/code/dev.nexxai.dev-vue/src/views/CVView.vue
21:58:19[DEBUG] Run command: { "/Users/nexxai/code/dev.nexxai.dev-vue/node_modules/.bin/prettier", "--stdin-filepath", "/Users/nexxai/code/dev.nexxai.dev-vue/src/views/CVView.vue" }
21:58:19[DEBUG] Run CWD: /Users/nexxai/code/dev.nexxai.dev-vue
21:58:20[DEBUG] prettier exited with code 0
21:58:22[DEBUG] Running formatters on /Users/nexxai/code/dev.nexxai.dev-vue/src/views/CVView.vue: {}
21:58:22[DEBUG] No formatters found for /Users/nexxai/code/dev.nexxai.dev-vue/src/views/CVView.vue
21:58:28[DEBUG] Running formatters on /Users/nexxai/code/dev.nexxai.dev-vue/src/views/CVView.vue: {}
21:58:28[DEBUG] No formatters found for /Users/nexxai/code/dev.nexxai.dev-vue/src/views/CVView.vue
21:58:31[DEBUG] Running formatters on /Users/nexxai/code/dev.nexxai.dev-vue/src/views/CVView.vue: { "prettier" }
21:58:31[INFO] Run prettier on /Users/nexxai/code/dev.nexxai.dev-vue/src/views/CVView.vue
21:58:31[DEBUG] Run command: { "/Users/nexxai/code/dev.nexxai.dev-vue/node_modules/.bin/prettier", "--stdin-filepath", "/Users/nexxai/code/dev.nexxai.dev-vue/src/views/CVView.vue" }
21:58:31[DEBUG] Run CWD: /Users/nexxai/code/dev.nexxai.dev-vue
21:58:31[DEBUG] prettier exited with code 0
21:58:32[DEBUG] Running formatters on /Users/nexxai/code/dev.nexxai.dev-vue/src/views/CVView.vue: {}
21:58:32[DEBUG] No formatters found for /Users/nexxai/code/dev.nexxai.dev-vue/src/views/CVView.vue
22:03:22[DEBUG] Running formatters on /Users/nexxai/code/dev.nexxai.dev-vue/src/views/CVView.vue: {}
22:03:22[DEBUG] No formatters found for /Users/nexxai/code/dev.nexxai.dev-vue/src/views/CVView.vue
22:03:24[DEBUG] Running formatters on /Users/nexxai/code/dev.nexxai.dev-vue/src/views/CVView.vue: { "prettier" }
22:03:24[INFO] Run prettier on /Users/nexxai/code/dev.nexxai.dev-vue/src/views/CVView.vue
22:03:24[DEBUG] Run command: { "/Users/nexxai/code/dev.nexxai.dev-vue/node_modules/.bin/prettier", "--stdin-filepath", "/Users/nexxai/code/dev.nexxai.dev-vue/src/views/CVView.vue" }
22:03:24[DEBUG] Run CWD: /Users/nexxai/code/dev.nexxai.dev-vue
22:03:24[DEBUG] prettier exited with code 0
22:04:08[DEBUG] Running formatters on /Users/nexxai/dotfiles/.config/nvim/lua/plugins/vue.lua: {}
22:04:08[DEBUG] No formatters found for /Users/nexxai/dotfiles/.config/nvim/lua/plugins/vue.lua
nexxai commented 4 months ago

When I just do a :w this is what appears in the log:

22:12:35[DEBUG] Running formatters on /Users/nexxai/code/dev.nexxai.dev-vue/src/views/CVView.vue: {}
22:12:35[DEBUG] No formatters found for /Users/nexxai/code/dev.nexxai.dev-vue/src/views/CVView.vue

If I do a <leader>f, this is what shows up:

22:14:08[DEBUG] Running formatters on /Users/nexxai/code/dev.nexxai.dev-vue/src/views/CVView.vue: { "prettier" }
22:14:08[INFO] Run prettier on /Users/nexxai/code/dev.nexxai.dev-vue/src/views/CVView.vue
22:14:08[DEBUG] Run command: { "/Users/nexxai/code/dev.nexxai.dev-vue/node_modules/.bin/prettier", "--stdin-filepath", "/Users/nexxai/code/dev.nexxai.dev-vue/src/views/CVView.vue" }
22:14:08[DEBUG] Run CWD: /Users/nexxai/code/dev.nexxai.dev-vue
22:14:08[DEBUG] prettier exited with code 0

I have no idea why auto-save is working differently than when I manually call it.

nexxai commented 4 months ago

Ok, I have no idea why this worked but adding the event table didn't, but adding

vim.api.nvim_create_autocmd("BufWritePre", {
  pattern = "*",
  callback = function(args)
    require("conform").format({ bufnr = args.buf })
  end,
})

At the top of my vue.lua seems to have FINALLY fixed this issue. Thank you so much @stevearc for being a sounding board and for such a great plugin!

stevearc commented 4 months ago

Glad it's working now! I will say that though it works, it's probably not "best practice". The LazyVim definition for formatting in general and format-on-save in particular are in this file https://github.com/LazyVim/LazyVim/blob/9e07a6615a16fafca37a6def86aa8344c09d289a/lua/lazyvim/util/format.lua You might be able to find the root cause by digging in there.