astral-sh / ruff-lsp

A Language Server Protocol implementation for Ruff.
Other
1.31k stars 46 forks source link

ruff - formatter in neovim - how to FixAll? [question] #409

Open KamilKleina opened 7 months ago

KamilKleina commented 7 months ago

Hello good people, I am kinda new to ruff and neovim, so I could use some guidance how can i make sure that formatting is fixing all just like calling fixAll in ruff-lsp? what in ruff formatter I have to set to fixAll by default?

return {
    "nvimtools/none-ls.nvim",
    config = function()
        local null_ls = require("null-ls")
        null_ls.setup({
            sources = {
                null_ls.builtins.diagnostics.mypy,
                null_ls.builtins.formatting.ruff,
            },
        })
        vim.keymap.set('n', '<leader>gf', vim.lsp.buf.format, {})
        vim.cmd [[autocmd BufWritePre * lua vim.lsp.buf.format()]]
    end
}

It also does respect my ruff.toml but I cannot find anything about fixAll for formatter in here.

line-length = 120
target-version = "py312"
output-format = "json"
show-fixes = true

[lint]
select = [
    "ALL", # include all the rules, including new ones
]
ignore = [
    #### modules
    # "ANN", # flake8-annotations
    # "COM", # flake8-commas
    # "C90", # mccabe complexity
    # "DJ",  # django
    # "EXE", # flake8-executable
    # "T10", # debugger
    # "TID", # flake8-tidy-imports

    #### specific rules
    # "D100",   # ignore missing docs
    # "D101",
    # "D102",
    # "D103",
    # "D104",
    # "D105",
    # "D106",
    # "D107",
    # "D200",
    # "D205",
    # "D212",
    # "D400",
    # "D401",
    # "D415",
    # "E402",   # false positives for local imports
    # "E501",   # line too long
    # "TRY003", # external messages in exceptions are too verbose
    # "TD002",
    # "TD003",
    # "FIX002", # too verbose descriptions of todos
]

[format]
quote-style = "double"
indent-style = "space"
skip-magic-trailing-comma = false
line-ending = "auto"
docstring-code-format = true
docstring-code-line-length = "dynamic"

Any chance somebody could tell me what I need to change either in my none-ls file or in ruff.toml please?

Thank you very much for all the help.

tigion commented 7 months ago

Not directly for none-ls but from conform.nvim (ruff installed via mason), but maybe it helps to solve this similarly to call ruff with the needed arguments:

    conform.setup({
      formatters_by_ft = {
        ...
        python = {
          'ruff_fix', -- To fix lint errors. (ruff with argument --fix)
          'ruff_format', -- To run the formatter. (ruff with argument format)
        },
        ...
      },
    })
dhruvmanila commented 7 months ago

Hey, thanks for providing all the details. It helps in understanding the question :)

I think there's a confusion here between the formatter and what fixAll is. I'm assuming that by fixAll you mean the code action provided by the language server. Here, fixAll is related to the linter and not the formatter. What it does is apply all of the available fixes from the highlighted violations in the Python file.

Since you're using nvimtools/none-ls.nvim, it seems that they've deprecated the ruff configuration from diagnostics and formatting builtins: https://github.com/nvimtools/none-ls.nvim/discussions/81 because we've our own LSP implementation. I would suggest to either use ruff-lsp (preferred) or other alternatives such as conform.nvim mentioned above.

gegoune commented 7 months ago

I understand difference between fixAll code action and format command in ruff and have successfully configured ruff-lsp accompanied by conform.nvim's ruff_fix. It works, but would be very nice to have ruff-lsp as a one-stop solution.

Do you think it would be an acceptable addition to ruff-lsp to support invoking fixAll on save automatically?

I believe there are other LSPs that support that (stylelint-lsp, from top of my head) functionality.

GodefroyClair commented 6 months ago

+1 to be able to invoke fixAll on save!

MichaReiser commented 6 months ago

I'm not familiar with neovim but Ruff-lsp supports format on save, but this is an action that needs to be triggered by the editor on save.

I don't think there's even a way for us to implement fixAll on save automatically because the didSave action doesn't allow us to send back a changed buffer.

DanCardin commented 6 months ago

I feel like the ask is more like a setting that makes the behavior happening during "format on save" to instead be the equivalent of the "fixAll" action. And/or format + organize imports.

dhruvmanila commented 6 months ago

I understand difference between fixAll code action and format command in ruff and have successfully configured ruff-lsp accompanied by conform.nvim's ruff_fix. It works, but would be very nice to have ruff-lsp as a one-stop solution.

Do you think it would be an acceptable addition to ruff-lsp to support invoking fixAll on save automatically?

Do you mean to add a editor.codeActionOnSave feature from VS Code? If so, then that is something which can only be done from the client side which is the editor in our case. The feature in VS Code is implemented in the editor which then calls into the server to get the respective code actions and the editor applies the edit.

I believe there are other LSPs that support that (stylelint-lsp, from top of my head) functionality.

Can you expand on what styelint-lsp does? What kind of behavior are you recommending from the mentioned language server?

+1 to be able to invoke fixAll on save!

This should be possible by requesting the code action to the server and applying the edit. The following can possibly be run on BufWritePost:

vim.lsp.buf.code_action {
  context = {
    only = { 'source.fixAll.ruff' },
  },
  apply = true,
}

Refer to :h vim.lsp.buf.code_action

gegoune commented 6 months ago

Can you expand on what styelint-lsp does? What kind of behavior are you recommending from the mentioned language server?

stylelint-lsp has autoFixOnFormat and autoFixOnSave settings (https://github.com/bmatcuk/stylelint-lsp?tab=readme-ov-file#settings) which, when enabled, will fix all fixable issues on either format, save or both.

steakhutzeee commented 6 months ago

I have a keybinding to format:

['<leader>lf'] = {"<cmd>lua vim.lsp.buf.format({async = true, filter = function(client) return client.name ~= 'typescript-tools' end})<cr>", 'Format'

and one for the Code Actions:

['<leader>la'] = { '<cmd>lua vim.lsp.buf.code_action()<cr>', 'Code Action' }

But I have to select manually to sort the imports or fix all.

Is there a direct command I can call to only sort the imports instead?

dhruvmanila commented 6 months ago

@steakhutzeee I've replied to your query over at https://github.com/astral-sh/ruff-lsp/issues/387#issuecomment-2071745678