stevearc / conform.nvim

Lightweight yet powerful formatter plugin for Neovim
MIT License
2.89k stars 150 forks source link

bug: conform.formatexpr(opts) not honoured #336

Closed NickHu closed 5 months ago

NickHu commented 5 months ago

Neovim version (nvim -v)

NVIM v0.9.5

Operating system/version

NixOS unstable

Add the debug logs

Log file

<empty>

Describe the bug

Selecting a specific configured formatter via conform.formatexpr({ formatters = { 'myformatter' } }) does not work, even though conform.format({ formatters = { 'myformatter' } }) does.

What is the severity of this bug?

breaking (some functionality is broken)

Steps To Reproduce

  1. nvim -u repro.lua
  2. gqG

Expected Behavior

ocamlformat runs, i.e. the same effect of running :lua require'conform'.format({formatters = {'ocamlformat'}}) which works fine. Should work on ranges too.

However, what I actually get is equal to the result of gwG, which suggests that somehow the option is not passed correctly via setting formatexpr.

Minimal example file

   let rec split = function
    | [] -> ([], [])
    | h :: t ->
        let ss, gs = split t in
          match h with
          | `Sheep _ as s -> (s :: ss, gs)
          | `Goat _ as g -> (ss, g :: gs);;

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
        formatters = {
          ["ocp-indent"] = {
            command = "ocp-indent",
          },
        },
        formatters_by_ft = {
          ocaml = { { "ocp-indent", "ocamlformat" } },
        },
      })
    end,
  },
  -- add any other plugins here
}
require("lazy").setup(plugins, {
  root = root .. "/plugins",
})

vim.cmd.colorscheme("tokyonight")
-- add anything else here
vim.o.formatexpr = "v:lua.require'conform'.formatexpr({ formatters = { 'ocamlformat' }})"

Additional context

I want to use both ocp-indent and ocamlformat; the latter is more aggressive, so I don't want it triggering automatically on save, only manually via formatexpr.

stevearc commented 5 months ago

What is the information from :ConformInfo?

NickHu commented 5 months ago
Log file: /home/nick/.repro/state/nvim/conform.log

Formatters for this buffer:
ocp-indent ready (ocaml) /nix/store/kxyvrkc322fk2cmwyrfs2kdc37im5rb8-ocp-indent-1.8.1/bin/ocp-indent
ocamlformat ready (ocaml) /nix/store/bsp4gasg8qvzfk9p7igwc236hsq2s8xf-ocamlformat-0.26.1/bin/ocamlformat

Other formatters:
stevearc commented 5 months ago

What I was trying to get from that was contents from the logfile, which will show up in the :ConformInfo window. If there truly is no log contents in that window, and as you say the log file is completely empty, then something is horribly wrong.

Using the minimal repro file, ensure that the log level is set to DEBUG, reproduce this behavior, and then check the log file. Is it empty? Is it present? Is it not there at all? Are there any other files in that directory? Do you have any error messages in Neovim?

NickHu commented 5 months ago

Yes, it really is empty. No error messages, and formatting works as expected if I just don't pass the argument, i.e. replace the final line with

vim.o.formatexpr = "v:lua.require'conform'.formatexpr()"

Of course, this doesn't achieve what I want, which is to select a specific formatter on formatexpr (ocamlformat).

(In doing so, conform.log has the following.

          17:39:17[INFO] Run ocp-indent on /tmp/conform.nvim/foo.ml
          17:39:17[DEBUG] Run command: { "ocp-indent" }
          17:39:17[DEBUG] ocp-indent exited with code 0

)

stevearc commented 5 months ago

Ah, I think I got it. The formatexpr is specified as vimscript, not lua. Try this:

vim.o.formatexpr = "v:lua.require'conform'.formatexpr({ 'formatters': [ 'ocamlformat' ]})"
NickHu commented 5 months ago

Bingo! That's great, thanks. Perhaps this should be noted in the documentation/with an example.