stevearc / conform.nvim

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

bug: isort adds additional newline to end of file #365

Closed tanj closed 3 months ago

tanj commented 4 months ago

Neovim version (nvim -v)

NVIM v0.10.0-dev-2752+g35239e977

Operating system/version

Windows 11 Pro

Add the debug logs

Log file

15:35:45[DEBUG] Running formatters on C:\src\test.py: { "isort" }
15:35:45[INFO] Run isort on C:\src\test.py
15:35:45[DEBUG] Run command: { "isort", "--stdout", "--filename", "C:\\\\src\\test.py", "-" }
15:35:45[DEBUG] Run CWD: C:/src/
15:35:45[DEBUG] isort exited with code 0

Describe the bug

When saving a python file with isort as one of the formatters the file will end up with an extra newline (\n) at the end of the file.

What is the severity of this bug?

minor (annoyance)

Steps To Reproduce

  1. nvim --clean test.py
  2. insert print("hello")
  3. :wq
  4. nvim -u repro.lua test.py
  5. :w

Expected Behavior

No extra newline added to file

Minimal example file

example input file xxd

00000000: 7072 696e 7428 2268 656c 6c6f 2229 0a    print("hello").

after isort run by conform xxd

00000000: 7072 696e 7428 2268 656c 6c6f 2229 0a0a  print("hello")..

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({
                format_on_save = function(bufnr)
                    return {
                        timeout_ms = 1500,
                    }
                end,
                log_level = vim.log.levels.DEBUG,
                -- add your config here
                formatters_by_ft = {
                    python = { "isort" },
                },
            })
        end,
    },
    -- add any other plugins here
}
require("lazy").setup(plugins, {
    root = root .. "/plugins",
})

vim.cmd.colorscheme("tokyonight")
-- add anything else here

Additional context

No response

msyavuz commented 3 months ago

I couldn't reproduce this in Linux. It may very well be the default behavior of isort on Windows. Either way conform calls isort with some default arguments nothing more. Here

tanj commented 3 months ago

If I run isort directly on the file (not through stdin/stdout) then no extra line at the end occurs. If, however, I pipe the input through and back out via stdin/stdout then the line endings of the file get changed from \n to \r\n. I wonder if this may be a bug in neovim where if the replacement text has \r\n line endings in a \n buffer it ends up with the extra \n at the end of the file.

msyavuz commented 3 months ago

It can also be an intended effect with the fixeol setting. You can try turning it off.

tanj commented 3 months ago

I added a simple dos2unix formatter to my formatter pipeline and it fixes this. I created a pull request if it is wanted. #383

Format pipline: python = { 'isort', 'dos2unix' },

this fixes the issue for me.