stevearc / conform.nvim

Lightweight yet powerful formatter plugin for Neovim
MIT License
2.92k stars 153 forks source link

bug: astyle windows range formatting #311

Open Noneangel opened 6 months ago

Noneangel commented 6 months ago

Neovim version (nvim -v)

v0.9.5

Operating system/version

windows 11

Add the debug logs

Log file

17:48:58[DEBUG] Running formatters on C:\hello_world\main.cpp: { "astyle" }
17:48:58[INFO] Run astyle on C:\hello_world\main.cpp
17:48:58[TRACE] Input lines: { "#include <iostream>", "", "int main(int argc, char** argv){", '\tstd::cout << "Hello World" << std::endl;', "\treturn 0;", "}", "", "", "  const int toto = 0;", "" }
17:48:58[DEBUG] Run command: { "astyle", "--project", "--quiet" }
17:48:58[DEBUG] Run CWD: C:/hello_world
17:48:58[DEBUG] astyle exited with code 0
17:48:58[TRACE] Output lines: { "#include <iostream>\r", "\r", "int main(int argc, char** argv)\r", "{\r", '    std::cout << "Hello World" << std::endl;\r', "    return 0;\r", "}\r", "\r", "\r", "const int toto = 0;\r", "\r" }
17:48:58[TRACE] astyle stderr: { "" }
17:48:58[TRACE] Applying formatting to C:\hello_world\main.cpp
17:48:58[TRACE] Comparing lines { "#include <iostream>", "", "int main(int argc, char** argv){", '\tstd::cout << "Hello World" << std::endl;', "\treturn 0;", "}", "", "", "  const int toto = 0;", "" } and { "#include <iostream>\r", "\r", "int main(int argc, char** argv)\r", "{\r", '    std::cout << "Hello World" << std::endl;\r', "    return 0;\r", "}\r", "\r", "\r", "const int toto = 0;\r", "\r" }
17:48:58[TRACE] Diff indices { { 1, 10, 1, 11 } }
17:48:58[TRACE] Applying text edits: { {
    newText = '\r\n\r\nint main(int argc, char** argv)\r\n{\r\n    std::cout << "Hello World" << std::endl;\r\n    return 0;\r\n}\r\n\r\n\r\nconst int toto = 0;\r\n\r',
    range = {
      ["end"] = {
        character = 0,
        line = 9
      },
      start = {
        character = 19,
        line = 0
      }
    }
  } }
17:48:58[TRACE] Done formatting C:\hello_world\main.cpp

Describe the bug

Range formatting isn't working with astyle on Windows. Instead, the entire file is formatted.

What is the severity of this bug?

tolerable (can work around it)

Steps To Reproduce

  1. nvim -u repro.lua hello_world.cpp
  2. select the main function
  3. type cf to call the conform.nvim
  4. the entire file is formated (including the const int toto line

Expected Behavior

Only the selection should have been formatted.

Minimal example file

#include <iostream>

int main(int argc, char** argv){ // space before { missing
    std::cout << "Hello World" << std::endl;
    return 0;
}

  const int toto = 0; // leading space to remove

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_by_ft = {cpp = {"astyle"}},
      })
    end,
  },
  -- add any other plugins here
}
require("lazy").setup(plugins, {
  root = root .. "/plugins",
})

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

vim.keymap.set({ "n", "v" }, "<space>cf", function()
    require("conform").format({})
end, { desc = "Format" })

Additional context

In the log, Output lines: { "#include <iostream>\r", did you notice the \r ? It is not in the input line, so the minimal diff will detect the entire file as different. The additional \r is due to this line https://github.com/stevearc/conform.nvim/blob/192a6d2ddace343f1840a8f72efe2315bd392243/lua/conform/runner.lua#L322 I think this is due to [jobstart](https://neovim.io/doc/user/builtin.html#jobstart()), on_stdout,

{data} Raw data ([readfile()](https://neovim.io/doc/user/builtin.html#readfile())-style list of strings) read from the channel. EOF is a single-item list: ['']. First and last items may be partial lines!

in readfile() doc

When the last line ends in a NL an extra empty list item is added. No CR characters are removed. Otherwise: CR characters that appear before a NL are removed. Whether the last line ends in a NL or not does not matter.

But I don't understand it as the two bold sentences seems contradictory.

In any case, replacing https://github.com/stevearc/conform.nvim/blob/192a6d2ddace343f1840a8f72efe2315bd392243/lua/conform/runner.lua#L330 with

stdout = vim.tbl_map(function (item) return item:gsub("\r$", "") end, data)

Fix the bug.

spawnie-no-oni commented 6 months ago

Formatting a file with astyle was moving all diagnostics from my lsp to the bottom of the file when the option squeeze-line was on. It was also adding a new line at the bottom of the file every time when squeeze-line was off. Applying the suggested fix fixed both.

I'm running nvim 0.9.5 on windows 11 as well.