camspiers / snap

A fast finder system for neovim.
The Unlicense
483 stars 16 forks source link

nvim lsp attaching to preview buffers #5

Closed akinsho closed 3 years ago

akinsho commented 3 years ago

This is more of a guess, than a certainty but I've had a few errors such as

Error executing vim.schedule lua callback: /usr/local/share/nvim/runtime/lua/vim/uri.lua:83: Invalid buffer id: 51
Error executing vim.schedule lua callback: ...ck/packer/start/nvim-lspconfig/lua/lspconfig/configs.lua:141: Vim(autocmd):E680: <buffer=51>: invalid buffer number

Whilst using the grep functionality. It appears that the lsp might be trying to attach to files and I'm guessing it's the preview buffer or not sure if the plugin opens some files in some other way that triggers autocommands.

I remember dimly that telescope had to do a bit of a dance to avoid triggering things like the lsp for their buffer preview.

The config I'm using is.

use {
      "camspiers/snap",
      rocks = {"fzy"},
      config = function()
        local snap = require("snap")
        -- local limit = snap.get("consumer.limit")
        -- local fzf = snap.get("consumer.fzf")
        snap.register.map(
          {"n"},
          {"<leader>fs"},
          function()
            snap.run {
              prompt = "Grep",
              producer = snap.get("producer.ripgrep.vimgrep"),
              select = snap.get("select.vimgrep").select,
              multiselect = snap.get("select.vimgrep").multiselect,
              views = {snap.get("preview.vimgrep")}
            }
          end
        )
      end
    }

Apologies this isn't the most detailed bug report on earth just noting things as I go in case this is helpful for you.

camspiers commented 3 years ago

Thanks for the report! I will need to figure out a way to make lsp not auto attach to the preview buffers, as I agree that is undesirable.

astridlyre commented 3 years ago

This may be related to this issue, so I'll comment here:

If I call this function:

s.files = function()
    snap.run({
        prompt = 'Files',
        producer = fzf(producer_file),
        select = select_file.select,
        multiselect = select_file.multiselect,
        views = {preview_file}
    })
end

From my init.vim:

nnoremap <leader>ff <cmd>lua require'ml-snap'.files()<cr>

Everything works, however immediately I have 100% CPU usage, with Efm language server taking up a ton a CPU time, perhaps due to attaching to results? This does not seem to change once I select a result and the picker window closes. CPU usage remains at 100% until I close neovim.

camspiers commented 3 years ago

Hmm, that isn't good. I would suggest that is efm behaving badly, but of course it affect the usage of snap so it is my problem too :D. If possible I would love to see a minimal setup with efm that reproduces the issue, though if that is too involved I might need to get my hands dirty to investigate, which could take some time.

astridlyre commented 3 years ago

Here is a config that produces it for me, might be able to be more minimal though, but basically I just use efm for formatting and linting.

init.vim:

call plug#begin(expand('~/.config/nvim/plugged'))
Plug 'camspiers/snap'
Plug 'neovim/nvim-lspconfig'
call plug#end()
lua require('config')
let mapleader=' '
nnoremap <leader>ff <cmd>lua require('ml-snap').files()<cr>

config.lua:

-- efm language server
local efm = function()
    -- Vim linting
    local vim_vint = {
        lintCommand = 'vint -',
        lintStdin = true,
        lintFormats = {'%f:%l:%c: %m'}
    }

    -- Markdown Lint & Formatting
    local markdown = {
        lintCommand = 'markdownlint -s',
        lintStdin = true,
        lintFormats = {'%f:%l %m', '%f:%l:%c %m', '%f: %l: %m'},
        formatCommand = 'prettier --parser markdown',
        formatStdin = true
    }

    -- Yaml Linting
    local yaml_lint = {lintCommand = 'yamllint -f parsable -', lintStdin = true}

    -- Shell formatting & linting
    local shell = {
        lintCommand = 'shellcheck -f gcc -x',
        lintSource = 'shellcheck',
        lintFormats = {
            '%f:%l:%c: %trror: %m', '%f:%l:%c: %tarning: %m',
            '%f:%l:%c: %tote: %m'
        },
        formatCommand = 'shfmt -ci -s -bn',
        formatStdin = true
    }

    -- Lua formatting
    local lua_fmt = {formatCommand = 'lua-format -i', formatStdin = true}

    -- Rust formatting
    local rust_fmt = {
        formatCommand = 'rustfmt --emit stdout',
        formatStdin = true
    }

    -- Python formatting & Linting
    local python_lint = {
        lintCommand = 'mypy --show-column-numbers',
        lintFormats = {
            '%f:%l:%c: %trror: %m', '%f:%l:%c: %tarning: %m',
            '%f:%l:%c: %tote: %m'
        },
        lintStdin = true
    }
    local python_fmt = {formatCommand = 'black --quiet -', formatStdin = true}
    local python_isort = {formatCommand = 'isort --quiet -', formatStdin = true}
    local python_flake = {
        lintCommand = 'flake8 --stdin-display-name ${INPUT} -',
        lintStdin = true,
        lintFormats = {'%f:%l:%c: %m'}
    }

    -- HTML Formatting
    local html_fmt = {
        formatCommand = 'prettier --parser html',
        formatStdin = true
    }

    -- CSS Formatting
    local css_fmt = {
        formatCommand = 'prettier --parser css',
        formatStdin = true
    }

    -- JSON Formatting
    local json = {
        formatCommand = 'fixjson',
        lintCommand = 'jq .',
        formatStdin = true,
        lintStdin = true
    }

    lspconfig.efm.setup {
        init_options = {
            documentFormatting = true,
            hover = false,
            documentSymbol = false,
            codeAction = false,
            completion = false
        },
        root_dir = function() return vim.fn.getcwd() end,
        filetypes = {
            "sh", "rust", "vim", "lua", "python", "yaml", "markdown", "html",
            "css", "sass", "json", "text"
        },
        settings = {
            rootMarkers = {".git/"},
            languages = {
                vim = {vim_vint},
                markdown = {markdown},
                yaml = {yaml_lint},
                sh = {shell},
                lua = {lua_fmt},
                rust = {rust_fmt},
                python = {python_lint, python_fmt, python_isort, python_flake},
                json = {json},
                html = {html_fmt},
                css = {css_fmt},
                sass = {css_fmt}
            }
        }
    }
end
efm()

ml-snap/init.lua:

local snap = require'snap'
local s = {}

local fzf = snap.get'consumer.fzf'
local producer_file = snap.get'producer.ripgrep.file'
local select_file = snap.get'select.file'
local preview_file = snap.get'preview.file'

s.files = function()
  snap.run({
    prompt = 'Files',
    producer = fzf(producer_file),
    select = select_file.select,
    multiselect = select_file.multiselect,
    views = {preview_file}
  })
end

return s
akinsho commented 3 years ago

I can't speak to efm, but to see the issues with the lsp and the preview buffer is fairly easy. Setup lspconfig for the filetype(s) in your project then grep in project making sure that several files the lsp is active for are shown in the preview in quick succession, this should quite quickly reproduce the issue.

I think the way telescope did it was making sure to open the buffer in such a way that it didn't trigger autocommands, I wonder if maybe you could use the new noautocmd key in the nvim_win_open to avoid this behaviour or if you will need the more subtle implementation from telescope

camspiers commented 3 years ago

I am not sure why yet, but I am not seeing lsp attach for previews, I am explicitly testing it with two lsp configs I have set up, lua and typescript. I don't know what accounts for the difference. Haven't checked efm yet.

camspiers commented 3 years ago

@akinsho With respect to noautocmd for nvim_open_win I don't think that will help as it only disables autocommands for when the window opens, not I general (I believe). The window opens before the content is ever loaded in the buffer, and before filetype detection is performed. But thanks for alerting me to the new option, I hadn't seen it.

camspiers commented 3 years ago

@akinsho @astridlyre I'm flying completely blind here because I can't seem to replicate the issue, but can you have a check of the branch https://github.com/camspiers/snap/tree/fixes/lsp-preview with your local setup?

With packer you should be able to go:

use { 'camspiers/snap', branch = 'fixes/lsp-preview' }
camspiers commented 3 years ago

(btw the above branch only contains the potential fix for the file previewer, not the vimgrep one.)

astridlyre commented 3 years ago

That has fixed the issue for me with efm! Tested with both the minimal setup and my normal setup. Cool!!

akinsho commented 3 years ago

@camspiers that branch seems to have worked 👍🏾 I'm going to use it for the rest of the day just to make sure, but initial usage seems good. Regarding the reproduction sorry I would have added minimal reproduction steps I had just assumed it was happening to anyone using a language server and would be easy to reproduce. FWIW I was seeing this in lua and dart the 2 languages I write the most of atm

akinsho commented 3 years ago

Ok haven't seen this at all today now, so think it's been resolved. Thanks @camspiers 👍🏾

camspiers commented 3 years ago

No problem @akinsho thanks to both of you for all the useful information!

camspiers commented 3 years ago

Fixed in https://github.com/camspiers/snap/commit/f90491bf029fac14458a6303fb9efc6aa1c5f0b2