saecki / crates.nvim

A neovim plugin that helps managing crates.io dependencies
MIT License
859 stars 29 forks source link

null-ls is archived #78

Closed Shadow53 closed 9 months ago

Shadow53 commented 1 year ago

null-ls.nvim has be archived citing maintenance concerns.

Commenters on the related issue have cited efm as a potential replacement, but I have not looked into that yet.

saecki commented 1 year ago

I know, but since we only use null-ls for code-actions, and there isn't any popular replacement for that, I don't see any reasonable path into the future yet. Since having something that still works is better than nothing at all, I think just leaving it as is for now is probably the best option.

lovesegfault commented 1 year ago

@Saecki it would be nice to, at least, remove the warning from checkhealth?

saecki commented 1 year ago

Do you mean this?

- Crates: cannot verify if the command is an executable.

I don't think there is any way around that one.

lovesegfault commented 1 year ago

I mean this:

==============================================================================
crates: require("crates.health").check()

Checking required plugins ~
- OK plenary.nvim installed
- WARNING null-ls.nvim not found

Checking external dependencies ~
- OK curl installed
- OK xdg-open installed
- OK open installed
saecki commented 1 year ago

Ah that one, seems reasonable.

Shadow53 commented 1 year ago

For anyone who comes across this issue, looks like null-ls got forked to none-ls. If I understand right, it's a drop-in replacement.

saecki commented 1 year ago

I will definitely keep an eye on that one. Maybe there should be a config option to select which one to use, similar to how nvim-cmp and coq_nvim sources work.

gh-liu commented 1 year ago

Maybe create in-process lsp server is another option, no other dependencies.

Just copy the code below to your config and reopen the Cargo.toml file.

local lsp = {}

---@class lsp.server.opts
---@field handlers? table<string, fun(method: string, params: any): any>
---@field on_request? fun(method: string, params)
---@field on_notify? fun(method: string, params)
---@field capabilities? table

--- Create a in-process LSP server that can be used as `cmd` with |vim.lsp.start|
--- Example:
--- <pre>lua
--- vim.lsp.start({
---   name = "my-in-process-server",
---   cmd = vim.lsp.server({
---   handlers = {
---
---   }
---   })
--- })
---
--- @param opts nil|lsp.server.opts
function lsp.server(opts)
    opts = opts or {}
    local capabilities = opts.capabilities or {}
    local on_request = opts.on_request or function(_, _) end
    local on_notify = opts.on_notify or function(_, _) end
    local handlers = opts.handlers or {}

    return function(dispatchers)
        local closing = false
        local srv = {}
        local request_id = 0

        function srv.request(method, params, callback)
            pcall(on_request, method, params)
            local handler = handlers[method]
            if handler then
                local response, err = handler(method, params)
                callback(err, response)
            elseif method == "initialize" then
                callback(nil, {
                    capabilities = capabilities,
                })
            elseif method == "shutdown" then
                callback(nil, nil)
            end
            request_id = request_id + 1
            return true, request_id
        end

        function srv.notify(method, params)
            pcall(on_notify, method, params)
            if method == "exit" then
                dispatchers.on_exit(0, 15)
            end
        end

        function srv.is_closing()
            return closing
        end

        function srv.terminate()
            closing = true
        end

        return srv
    end
end

lsp.enable_crates = function()
    local actions = {
        "update_crate",
        "upgrade_crate",
        "expand_crate_to_inline_table",
        "extract_crate_into_table",
        "remove_duplicate_section",
        "remove_original_section",
        "remove_invalid_dependency_section",
        "remove_duplicate_crate",
        "remove_original_crate",
        "rename_crate",
        "remove_duplicate_feature",
        "remove_original_feature",
        "remove_invalid_feature",
        "open_documentation",
        "open_crates.io",
        "update_all_crates",
        "upgrade_all_crates",
    }
    for _, value in ipairs(actions) do
        vim.lsp.commands[value] = function(cmd, ctx)
            local actions = require("crates.actions")
            local action = actions.get_actions()[cmd.command]
            vim.api.nvim_buf_call(ctx.bufnr, action)
        end
    end

    local api = vim.api
    local server = lsp.server({
        capabilities = {
            codeActionProvider = true,
        },
        handlers = {
            ---@param params lsp.CodeActionParams
            ["textDocument/codeAction"] = function(_, params)
                local actions = require("crates.actions")
                local function format_title(name)
                    return name:sub(1, 1):upper() .. name:gsub("_", " "):sub(2)
                end

                local code_actions = {}
                for key, action in pairs(actions.get_actions()) do
                    table.insert(code_actions, {
                        title = format_title(key),
                        kind = "refactor.rewrite",
                        command = key,
                    })
                end
                return code_actions
            end,
        },
    })
    vim.lsp.start({ name = "crates-ls", cmd = server })
end

vim.api.nvim_create_autocmd("BufEnter", {
    pattern = "Cargo.toml",
    callback = function()
        lsp.enable_crates()
    end,
})
saecki commented 1 year ago

Ooh I like that, it seems simple enough and could probably also be used to handle completion.

vanguard-bit commented 9 months ago

@gh-liu where do you paste that code you have given? init or crates.lua? or is just a function that i can require in init?

saecki commented 9 months ago

@gh-liu where do you paste that code you have given? init or crates.lua? or is just a function that i can require in init?

Afaik the PR hasn't been merged, so the snippet won't work yet, even on 0.10.

For now you can still use null_ls or none_ls. The latter could probably be added to the documentation, but it's a drop in replacement.

vanguard-bit commented 9 months ago

Ohhhh alright thanks....and making it a lsp seems better than using null or none

gh-liu commented 9 months ago

Afaik the PR hasn't been merged

Yes, the lsp.server funtion hasn't been merged,

so the snippet won't work yet, even on 0.10.

But the snippet works, Because the snippet contains the lsp.server funtion.

gh-liu commented 9 months ago

@gh-liu where do you paste that code you have given? init or crates.lua? or is just a function that i can require in init?

You can just require in init.lua, or copy the lsp.server funtion into a lua file, and use it in the crates config.

This is my config: lua file contains lsp.server funciton use lsp.server function in crates config

saecki commented 9 months ago

But the snippet works, Because the snippet contains the lsp.server funtion.

Huh, I definitely misread that. I'll see when I can implement a lsp server directly😄

saecki commented 9 months ago

I guess with #100 merged, and none_ls as an alternative, this issue is pretty much resolved.