wbthomason / packer.nvim

A use-package inspired plugin manager for Neovim. Uses native packages, supports Luarocks dependencies, written in Lua, allows for expressive config
MIT License
7.84k stars 265 forks source link

ft = 'filetype' doesn't always work properly #93

Closed phantomion closed 3 years ago

phantomion commented 3 years ago

Like the title says the ft option doesn't always work e.g. when I do use {tpope/vim-fireplace, ft='clojure'} it seems to work properly, but when I do use {'slashmili/alchemist.vim', ft = 'elixir'} it won't load alchemist. Log file says Sourcing $HOME/path/to/opt/alchemist but it doesn't load. I also use vim-polyglot if it matters and I tried to load alchemist after polyglot, but the result is the same. My plugins.lua for reference:

vim.api.nvim_command('packadd packer.nvim')

return require('packer').startup(function()
    use {'wbthomason/packer.nvim', opt = true}
    use 'srcery-colors/srcery-vim'
    use 'dracula/vim'
    -------------langs-----------
    use 'sheerun/vim-polyglot' -- One for all
    --------------QoL------------
    use 'tpope/vim-surround' -- Surround everything
    use 'scrooloose/nerdcommenter' -- Smart comments
    use 'honza/vim-snippets'
    use 'SirVer/ultisnips'
    use 'jiangmiao/auto-pairs' -- Auto pairs
    use 'vimwiki/vimwiki'
    use {
        'luochen1990/rainbow',
        ft = {'clojure'},
    }
    use {
        'Yggdroot/indentLine',
        ft = {'nim'},
    }
    use 'easymotion/vim-easymotion'
    use 'romgrk/barbar.nvim' -- Best bufferline
    use 'glepnir/galaxyline.nvim'
    use 'farmergreg/vim-lastplace'
    -------------dev tools---------
    use 'majutsushi/tagbar' -- too good to be true
    use {'jaxbot/browserlink.vim', ft = { 'html','css','javascript' }} -- preview
    use {'tpope/vim-fireplace', ft =  'clojure' } -- enables clojure development
    use 'kyazdani42/nvim-tree.lua'
    use {'slashmili/alchemist.vim', ft = 'elixir'}
    ---------------git------------
    use 'tpope/vim-fugitive' -- this should be illegal
    use 'mhinz/vim-signify'
    use 'tpope/vim-rhubarb'
    --------nvim-lsp---------
    use 'neovim/nvim-lspconfig' 
    use 'nvim-lua/diagnostic-nvim'
    use 'nvim-lua/completion-nvim'
    use 'nvim-lua/lsp_extensions.nvim'
    use 'steelsojka/completion-buffers'
    use 'tjdevries/nlua.nvim'
    -------------telescope---------
    use {
        'nvim-lua/telescope.nvim',
        requires = {'nvim-lua/popup.nvim', 'nvim-lua/plenary.nvim'}
    }
    -------------lsputils---------
    use {
        'RishabhRD/nvim-lsputils',
        requires = 'RishabhRD/popfix'
    }
    --------------misc------------
    use {'ron-rs/ron.vim', ft = 'ron'}
    use 'nvim-treesitter/nvim-treesitter'
    use 'kyazdani42/nvim-web-devicons'
    use 'norcalli/nvim-colorizer.lua'
end)
wbthomason commented 3 years ago

Interesting. Given that you say it works for Clojure, I assume you're using PackerCompile correctly. Could you please post your compiled file here, and I'll take a look to see if I can figure out what's going on?

phantomion commented 3 years ago

This is the compiled file. I also checked the indentLine and ron.vim plugins which I use for nim and ron files respectively. They don't work either.

" Automatically generated packer.nvim plugin loader code

if !has('nvim')
  finish
endif

lua << END
local plugins = {
  ["alchemist.vim"] = {
    loaded = false,
    only_sequence = false,
    only_setup = false,
    path = "/home/kwstas/.local/share/nvim/site/pack/packer/opt/alchemist.vim"
  },
  ["browserlink.vim"] = {
    loaded = false,
    only_sequence = false,
    only_setup = false,
    path = "/home/kwstas/.local/share/nvim/site/pack/packer/opt/browserlink.vim"
  },
  indentLine = {
    loaded = false,
    only_sequence = false,
    only_setup = false,
    path = "/home/kwstas/.local/share/nvim/site/pack/packer/opt/indentLine"
  },
  ["packer.nvim"] = {
    loaded = false,
    only_sequence = false,
    only_setup = false,
    path = "/home/kwstas/.local/share/nvim/site/pack/packer/opt/packer.nvim"
  },
  rainbow = {
    loaded = false,
    only_sequence = false,
    only_setup = false,
    path = "/home/kwstas/.local/share/nvim/site/pack/packer/opt/rainbow"
  },
  ["ron.vim"] = {
    loaded = false,
    only_sequence = false,
    only_setup = false,
    path = "/home/kwstas/.local/share/nvim/site/pack/packer/opt/ron.vim"
  },
  ["vim-fireplace"] = {
    loaded = false,
    only_sequence = false,
    only_setup = false,
    path = "/home/kwstas/.local/share/nvim/site/pack/packer/opt/vim-fireplace"
  }
}

local function handle_bufread(names)
  for _, name in ipairs(names) do
    local path = plugins[name].path
    for _, dir in ipairs({ 'ftdetect', 'ftplugin', 'after/ftdetect', 'after/ftplugin' }) do
      if #vim.fn.finddir(dir, path) > 0 then
        vim.cmd('doautocmd BufRead')
        return
      end
    end
  end
end

_packer_load = nil

local function handle_after(name, before)
  local plugin = plugins[name]
  plugin.load_after[before] = nil
  if next(plugin.load_after) == nil then
    _packer_load({name}, {})
  end
end

_packer_load = function(names, cause)
  local some_unloaded = false
  for _, name in ipairs(names) do
    if not plugins[name].loaded then
      some_unloaded = true
      break
    end
  end

  if not some_unloaded then return end

  local fmt = string.format
  local del_cmds = {}
  local del_maps = {}
  for _, name in ipairs(names) do
    if plugins[name].commands then
      for _, cmd in ipairs(plugins[name].commands) do
        del_cmds[cmd] = true
      end
    end

    if plugins[name].keys then
      for _, key in ipairs(plugins[name].keys) do
        del_maps[key] = true
      end
    end
  end

  for cmd, _ in pairs(del_cmds) do
    vim.cmd('silent! delcommand ' .. cmd)
  end

  for key, _ in pairs(del_maps) do
    vim.cmd(fmt('silent! %sunmap %s', key[1], key[2]))
  end

  for _, name in ipairs(names) do
    if not plugins[name].loaded then
      vim.cmd('packadd ' .. name)
      if plugins[name].config then
        for _i, config_line in ipairs(plugins[name].config) do
          loadstring(config_line)()
        end
      end

      if plugins[name].after then
        for _, after_name in ipairs(plugins[name].after) do
          handle_after(after_name, name)
          vim.cmd('redraw')
        end
      end

      plugins[name].loaded = true
    end
  end

  handle_bufread(names)

  if cause.cmd then
    local lines = cause.l1 == cause.l2 and '' or (cause.l1 .. ',' .. cause.l2)
    vim.cmd(fmt('%s%s%s %s', lines, cause.cmd, cause.bang, cause.args))
  elseif cause.keys then
    local keys = cause.keys
    local extra = ''
    while true do
      local c = vim.fn.getchar(0)
      if c == 0 then break end
      extra = extra .. vim.fn.nr2char(c)
    end

    if cause.prefix then
      local prefix = vim.v.count and vim.v.count or ''
      prefix = prefix .. '"' .. vim.v.register .. cause.prefix
      if vim.fn.mode('full') == 'no' then
        if vim.v.operator == 'c' then
          prefix = '' .. prefix
        end

        prefix = prefix .. vim.v.operator
      end

      vim.fn.feedkeys(prefix, 'n')
    end

    -- NOTE: I'm not sure if the below substitution is correct; it might correspond to the literal
    -- characters \<Plug> rather than the special <Plug> key.
    vim.fn.feedkeys(string.gsub(string.gsub(cause.keys, '^<Plug>', '\\<Plug>') .. extra, '<[cC][rR]>', '\r'))
  elseif cause.event then
    vim.cmd(fmt('doautocmd <nomodeline> %s', cause.event))
  elseif cause.ft then
    vim.cmd(fmt('doautocmd <nomodeline> %s FileType %s', 'filetypeplugin', cause.ft))
    vim.cmd(fmt('doautocmd <nomodeline> %s FileType %s', 'filetypeindent', cause.ft))
  end
end

-- Runtimepath customization

-- Pre-load configuration
-- Setup for: indentLine
loadstring("\27LJ\2\0023\0\0\2\0\4\0\0056\0\0\0009\0\1\0'\1\3\0=\1\2\0K\0\1\0\6|\20indentLine_char\6g\bvim\0")()
-- Setup for: rainbow
loadstring("\27LJ\2\0020\0\0\2\0\3\0\0056\0\0\0009\0\1\0)\1\1\0=\1\2\0K\0\1\0\19rainbow_active\6g\bvim\0")()
-- Post-load configuration
-- Conditional loads
-- Load plugins in order defined by `after`
END

function! s:load(names, cause) abort
call luaeval('_packer_load(_A[1], _A[2])', [a:names, a:cause])
endfunction

" Command lazy-loads

" Keymap lazy-loads

augroup packer_load_aucmds
  au!
  " Filetype lazy-loads
  au FileType javascript ++once call s:load(['browserlink.vim'], { "ft": "javascript" })
  au FileType css ++once call s:load(['browserlink.vim'], { "ft": "css" })
  au FileType clojure ++once call s:load(['vim-fireplace', 'rainbow'], { "ft": "clojure" })
  au FileType elixir ++once call s:load(['alchemist.vim'], { "ft": "elixir" })
  au FileType ron ++once call s:load(['ron.vim'], { "ft": "ron" })
  au FileType nim ++once call s:load(['indentLine'], { "ft": "nim" })
  au FileType html ++once call s:load(['browserlink.vim'], { "ft": "html" })
  " Event lazy-loads
augroup END
wbthomason commented 3 years ago

Interesting - the FileType commands seem to be uniformly and correctly generated. Could you please tell me what :set filetype reports in an Elixir/Ron/Nim file with this configuration? I suspect that the FileType event is never triggering, but alchemist.vim doesn't look like it defines a ftdetect script, and you said you tried loading polyglot first, so I'm not sure why that would happen...

phantomion commented 3 years ago

The filetypes for elixir and nim are correct. The filetype for ron is empty which I guess makes sense since it needs the plugin, but when I used vim-plug and did Plug 'ron-rs/ron.vim', {'for': 'ron'} it worked fine. I'm not sure I loaded polyglot first correctly though. I tried using the after option like after = 'sheerun/vim-polyglot' and after = 'vim-polyglot', but none of them worked.

nanotee commented 3 years ago

I have tested this with a clean instance of Neovim (no plugins or config) and... this looks like it could be a quirk of :packadd?

This works:

This doesn't:

It only seems to affect files in after/plugin. I have no idea if this is the intended behavior or not.

phantomion commented 3 years ago

Yeah when I tried without the ft option everything worked fine. Maybe I should fine another workaround.

wbthomason commented 3 years ago

@bfredl is there any chance the recent changes to native packages could be affecting this?

@nanotee thanks for testing that!

If this is "working as intended" for packadd, then perhaps I should add a manual check + sourcing for after/* files...

bfredl commented 3 years ago

dunno, someone else had a similar problem and then it turned out something else was a problem. after/ behaviour is not changed by my recent changes at least :D

bfredl commented 3 years ago

Hmm it is a little bit suspicious that packer.nvim is manually doing after/ stuff at all. the core plugin code (already the code inherited from vim) is supposed to handle all that (if it does not I will fix it)

wbthomason commented 3 years ago

So, unless I'm forgetting something I implemented, we currently aren't doing anything manually with after/. It's just that we might have to add something to manually source files in if this problem reproduces and isn't an issue with packadd.

bfredl commented 3 years ago

I was just reading what the "Automatically generated packer.nvim plugin loader code" was doing but maybe I misunderstood it.

wbthomason commented 3 years ago

Ah - if you're referring to the handle_after function, that's for handling packer's sequence loading keyword, which is (confusingly) also after.

nanotee commented 3 years ago

Looks like this is the intended behavior: https://github.com/vim/vim/issues/1994

wbthomason commented 3 years ago

Unfortunate (but thanks @nanotee for the find!)

packer could add manual handling of after/plugin/, but, as @bfredl mentions, that seems fishy/like maybe a bad idea. Still, given that I disagree with the reasoning in https://github.com/vim/vim/issues/1994 (it may be an anti-pattern, but plugins should still be sourced the same whether or not they're in start or opt), this might be the best way to go.

bfredl commented 3 years ago

We (neovim core) are not bound by unfortunate desicions made by vim. We should change opt/ handling in neovim core to respect the existing after/ pattern properly handled by all plugin/package solutions other than brampackages.

bfredl commented 3 years ago

Hmm, opt/xx/after/plugin/xx.vim actually work for me when packadd! xx. Is there a complete minimal example of a config where it does not work?

wbthomason commented 3 years ago

I think the config @nanotee describes here is probably the closest to a complete minimal config demonstrating the behavior.

nanotee commented 3 years ago

@bfredl Interestingly, packadd xx on its own in init.vim seems to work, but the following doesn't source files in after/plugin:

autocmd VimEnter * packadd xx
Iron-E commented 3 years ago

I just ran into an issue with whonore/Coqtail#162 that might also fall under the scope of this issue. Precisely, it is a syntax file which does not get sourced when restricted to only load on its own filetype (using :scriptnames confirms this):

use {'whonore/Coqtail', ft='coq'}
nvim foo.v   # no syntax highlighting
nvim foo.coq # no syntax highlighting

But, if I run :setf coq one more time, the highlighting happens.

To compare, doing:

Plug 'whonore/Coqtail', {'for': 'coq'}

works.


To workaround this issue, I created the following file:

" ~/.config/nvim/ftplugin/coq/filetype.vim
setf coq

And it works.

wbthomason commented 3 years ago

Do you also encounter this error when packadding the plugin manually? i.e. does this seem to be an issue with how packer implements ft vs. how vim-plug implements for, or with how Neovim/Vim implement native packages?

Iron-E commented 3 years ago

Yeah, packadding manually makes it work. This is what I did:

  1. Comment out the use for Coqtail:
    -- use {'whonore/Coqtail', ft='coq'}
  2. :PackerCompile
  3. Modify ~/.config/nvim/ftplugin/coq/filetype.vim:
    packadd Coqtail

That makes it work.


Edit: to clarify, it seems this is not an issue with the Neo/vim package implementation. Rather, a load order issue.

wbthomason commented 3 years ago

Well, that's unfortunate.

It looks like vim-plug does some explicit sourcing to handle this case (https://github.com/junegunn/vim-plug/blob/master/plug.vim#L387); perhaps packer needs something similar...

Iron-E commented 3 years ago

Should I make a separate issue for that?

wbthomason commented 3 years ago

I added a mechanism to fix a related issue in #215; I should be able to extend it to also handle this case.

wbthomason commented 3 years ago

@Iron-E: I think 993eaad fixes this (at least, I can no longer reproduce your Coqtail issue). Please reopen if you're still seeing problems, and thanks for your patience on this!

Iron-E commented 3 years ago

Awesome! Glad to see this fixed.