Skip to content

bug: Selection formatting doesn't work as expected with fallback LSP #63

Description

@jborbik

Neovim version (nvim -v)

NVIM v0.8.3

Operating system/version

MacOS 13.5.2

Output of :ConformInfo

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

Formatters for this buffer:
LSP: clangd

Other formatters:

Describe the bug

I tried following this example to set up the formatting of selection: #40

The selection formatting with require("conform").format({ async = true, lsp_fallback = true }) doesn't work as expected with LSP fallback formatting clangd - the whole file is being formatted instead of just the selection and the visual mode stays active. The formatting of the selection works fine though with the other solution: Format user command suggested in the same post.

Steps To Reproduce

  1. nvim -u repro.lua example.cpp
  2. select some lines
  3. press space -> f
  4. whole file is being reformatted instead of just selection <--- not expected
  5. undo with u
  6. select some line
  7. run :Format
  8. only the selected lines are being formatted <--- as expected

Expected Behavior

In both cases the selection formatting works as expected as suggested in the post #40

Minimal example file

       #include <iostream>

    int main() {
  int test = 123;
     std::cout << "Hello World!" << test << std::endl;
      return 0;
}

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,
      })
    end,
  },
  {
    {'VonHeikemen/lsp-zero.nvim', branch = 'v3.x'},

    -- LSP Support
    {'neovim/nvim-lspconfig'},
    {'williamboman/mason.nvim'},
    {'williamboman/mason-lspconfig.nvim'},

    -- Autocompletion
    {'hrsh7th/nvim-cmp'},
    {'hrsh7th/cmp-nvim-lsp'},
    {'L3MON4D3/LuaSnip'},
  },
}
require("lazy").setup(plugins, {
  root = root .. "/plugins",
})

vim.cmd.colorscheme("tokyonight")

-- add anything else here

-- set up Format and <leader>f commands which should behave equivalently
vim.api.nvim_create_user_command("Format", function(args)
  local range = nil
  if args.count ~= -1 then
    local end_line = vim.api.nvim_buf_get_lines(0, args.line2 - 1, args.line2, true)[1]
    range = {
      start = { args.line1, 0 },
      ["end"] = { args.line2, end_line:len() },
    }
  end
  require("conform").format({ async = true, lsp_fallback = true, range = range })
end, { range = true })
vim.keymap.set('', '<leader>f', function ()
  require("conform").format({async = true, lsp_fallback = true })
end)

-- set up LSP with clangd

local lsp_zero = require('lsp-zero')
lsp_zero.on_attach(function(client, bufnr)
  lsp_zero.default_keymaps({buffer = bufnr})
end)

require('mason').setup({})
require('mason-lspconfig').setup({
  ensure_installed = {'clangd'},
  handlers = {
    lsp_zero.default_setup,
    lua_ls = function()
      local lua_opts = lsp_zero.nvim_lua_ls()
      require('lspconfig').lua_ls.setup(lua_opts)
    end,
  }
})

local cmp = require('cmp')
local cmp_format = lsp_zero.cmp_format()

cmp.setup({
  formatting = cmp_format
})

Additional context

I tried fixing the issue but am not versatile in neovim API. If there is an easy workaround that would help too! The problem is that even setting something like:

vim.keymap.set('', '<leader>F', "<cmd>Format<cr>")

results in the unexpected behavior with selection formatting, but if I manually type :Format everything works as expected.

Activity

  1. changed the title [-]bug: [/-] [+]bug: Selection formatting doesn't work as expected with fallback LSP[/+] on Sep 19, 2023
  2. stevearc commented on Sep 19, 2023

    @stevearc
    Owner

    Thanks for the report! There was indeed a bug with range formatting and LSP. Should be fixed!

  3. jborbik commented on Sep 19, 2023

    @jborbik
    Author

    That was an extremely fast fix! Thank you :)

  4. jborbik commented on Sep 20, 2023

    @jborbik
    Author

    Hmm if I test it locally i still get the unexpected behavior on <leader>f - whole file is being formatted instead of just the selection. Could you please check that?

  5. stevearc commented on Sep 20, 2023

    @stevearc
    Owner

    Using the repro steps

    1. nvim -u repro.lua test.cpp
    2. Vjj to highlight the first three lines
    3. <leader>f

    The first three lines get de-indented, and the rest of the file is unaffected.

    Can you double check that you're on the most recent version of conform? And if your process is different, could you give me exact repro steps for the problem?

  6. jborbik commented on Sep 20, 2023

    @jborbik
    Author

    Oh, right. I'm sorry for not being specific. My steps are:

    1. nvim -u repro.lua test.cpp
    2. jjVj to select lines 3-4.
    3. <leader>f

    As the result not only lines 3-4 are being formatted but all lines starting from the 3rd line. Besides the visual selection stays active.

  7. stevearc commented on Sep 20, 2023

    @stevearc
    Owner

    Ah, this is just the behavior of the LSP server. It's likely formatting the entirety of the main function because you have part of it selected. There's not much we can do about that, since it's just how range formatting works for clangd. You can verify that this is just the built-in LSP behavior by changing the mapping to call vim.lsp.buf.format({ async = true }) instead.

  8. stevearc commented on Sep 20, 2023

    @stevearc
    Owner

    Oh, and if you want to not be in visual mode after the formatting, you can add this line after the call to format() (again, this would also be necessary for vim.lsp.buf.format)

    vim.api.nvim_feedkeys(vim.api.nvim_replace_termcodes("<ESC>", true, true, true), "n", true)
  9. jborbik commented on Sep 20, 2023

    @jborbik
    Author

    You are right, sorry for the confusion and thank you for your patience! I'll tweak it with the command above :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions