L3MON4D3 / LuaSnip

Snippet Engine for Neovim written in Lua.
Apache License 2.0
3.48k stars 245 forks source link

Add possibility to extend snippets to other filetypes #161

Closed lambtho12 closed 3 years ago

lambtho12 commented 3 years ago

With Ultisnips it is possible to create snippets for a specific filetype that builds on snippets existing for an other filetype (using the extends command).

A specific example where this is useful is for instance with vimwiki (which uses vimwiki filetype instead of regular markdown). In that case, it is useful to have specific snippets for vimwiki, but also activate normal markdown snippets.

Is that feature already possible with LuaSnip? Would that be possible to add it?

L3MON4D3 commented 3 years ago

Would either of #132 or #142 work for you?

lambtho12 commented 3 years ago

From #132, I tried that

require("luasnip").snippets={
  vimwiki ={}
}
require("luasnip").snippets.vimwiki = require("luasnip").snippets.markdown
require("luasnip/loaders/from_vscode").load({include = {"markdown"}})
require("luasnip/loaders/from_vscode").lazy_load()

but it does not seem to work. Not sure if #142 applies here as it is a completely different filetype and not just something like md.vimwiki

L3MON4D3 commented 3 years ago

132 should work if you do

require("luasnip").snippets.markdown = require("luasnip").snippets.vimwiki

instead, it's all about using the same table for vimwiki and markdown snippets.

You can make #142 work by manually setting ft to markdown.vimwiki(via autocmd or after/ftplugin/vimwiki.vim), but that may interfere with other plugins.

Both are rather hacky, so I'd also be open to support something like extend from Ultisnips.

lambtho12 commented 3 years ago

Indeed that kinda work if I write it in the correct way 😄

But now if I write my snippets for vimwiki as

require("luasnip").snippets={
  vimwiki ={
    s("test1", {
      t("this is my awesome text snippet")
    }),
  }
}

the snippets are also going to be present when I edit simple markdown files. Would it be possible to avoid that and have these extra snippets only work for vimwiki?

L3MON4D3 commented 3 years ago

That's the hackiness :P I'll add the extend, that should make it work properly. How does it work in ultisnips? Just extend(filetype, with_this_filetype)?

L3MON4D3 commented 3 years ago

Check out the proper_filetype_extend-branch, ~require("luasnip").filetype_extend("vimwiki", "markdown")~

require("luasnip").filetype_extend("vimwiki", {"markdown"})

should work.

lambtho12 commented 3 years ago

Does not seems to work. I have the following error when neovim starts:

Error detected while processing /home/lambtho/.dotfiles/nvim/.config/nvim/init.lua:
E5113: Error while calling lua chunk: vim/shared.lua:320: src: expected table, got string
stack traceback:
        vim/shared.lua:320: in function 'list_extend'
        ...nvim/site/pack/packer/start/LuaSnip/lua/luasnip/init.lua:377: in function 'filetype
_extend'
        /home/lambtho/.config/nvim/init.lua:32: in main chunk
lambtho12 commented 3 years ago

Error is fixed when using require("luasnip").filetype_extend({"vimwiki"}, {"markdown"})

Although it still does not work. I get mardown snippets in markdown, vimwiki specific snippets in vimwiki but no markdown in vimwiki.

My config is

require("luasnip").snippets={
  vimwiki ={
    s("test1", {
      t("this is my awesome text snippet")
    }),
  }
}

require("luasnip").filetype_extend({"vimwiki"}, {"markdown"})
require("luasnip/loaders/from_vscode").lazy_load()
L3MON4D3 commented 3 years ago

Could you try

require("luasnip").filetype_extend("vimwiki", {"markdown"})
lambtho12 commented 3 years ago

Could you try

luasnip.filetype_extend("vimwiki", {"markdown"})

No neovim error, but still not working as expected (i.e. markdown snippets in markdown, vimwiki specific snippets in vimwiki but no markdown snippets in vimwiki).

saadparwaiz1 commented 3 years ago

A bit off topic but here's how I accomplish this.

Main LuaSnip Config

setmetatable(require('luasnip').snippets, {
   __index = function(_, v)
       return require('snippets.' .. v)
   end
})

markdown.lua in lua/snippets directory

return {
  -- snippets here
}

vimwiki.lua in lua/snippets directory

local markdown_snippets = require('snippets.markdown')
-- add custom snippets
return markdown_snippets
L3MON4D3 commented 3 years ago

Ouh, that's sick :ok_hand: I pushed a fix, it should work properly now

lambtho12 commented 3 years ago

Almost there.. :smile:

In markdown: it is working as expected, but all markdown snippets appear twice in nvim-cmp. In vimwiki: Vimwiki snippets appear once in nvim-cmp, markdown snippets work but do not show in nvim-cmp

although, maybe this should be fixed in https://github.com/saadparwaiz1/cmp_luasnip

L3MON4D3 commented 3 years ago

Jup, the cmp-integration will have to be updated as soon as this is merged into master

L3MON4D3 commented 3 years ago

I'll have time to do a PR tomorrow or so

lambtho12 commented 3 years ago

Awesome! Thank your for such a quick update!

saadparwaiz1 commented 3 years ago

Almost there.. 😄

In markdown: it is working as expected, but all markdown snippets appear twice in nvim-cmp. In vimwiki: Vimwiki snippets appear once in nvim-cmp, markdown snippets work but do not show in nvim-cmp

although, maybe this should be fixed in https://github.com/saadparwaiz1/cmp_luasnip

@lambtho12 can you try out this pr it should fix the nvim-cmp issue

lambtho12 commented 3 years ago

Ok. I will report on the tests on the PR directly to keep things separate

L3MON4D3 commented 3 years ago

Almost there.. 😄 In markdown: it is working as expected, but all markdown snippets appear twice in nvim-cmp. In vimwiki: Vimwiki snippets appear once in nvim-cmp, markdown snippets work but do not show in nvim-cmp although, maybe this should be fixed in https://github.com/saadparwaiz1/cmp_luasnip

@lambtho12 can you try out this pr it should fix the nvim-cmp issue

Ha, beat me to it :D

lambtho12 commented 3 years ago

Finally, it seems that there is still an issue... Not sure if it is from here or cmp_luasnip. As explained on cmp_luasnip, when I want to use a snippet in vimwiki, I get the following

E5108: Error executing lua .../pack/packer/start/LuaSnip/lua/luasnip/nodes/snippet.lua:774: Vi
m:E492: Not an editor command: VimtexEventInitPost call vimtex#syntax#core#init_post()

(and I really do not know why it references vimtex here...)

L3MON4D3 commented 3 years ago

Seems like it happens while running the autocommands for snippet events, do you have an autocommand on them?

lambtho12 commented 3 years ago

These are the only autocommand I have:

local cmd = vim.cmd
cmd 'au TextYankPost * lua vim.highlight.on_yank {on_visual = false}'  -- disabled in visual mode
cmd 'autocmd BufRead,BufNewFile *.tex,*.dtx,*.md setlocal textwidth=80'
cmd 'autocmd FileType beancount,tex,markdown autocmd BufWritePre <buffer> %s/\\s\\+$//e'
L3MON4D3 commented 3 years ago

Hmmm, weird.. Did you expand the snippet via nvim_cmp or directly via trigger?

lambtho12 commented 3 years ago

Same thing if I expand it by nvim_cmp or via direct trigger. In any case, the snippet expand, but I still get the error message. If I expand it by pressing on the nvim_cmp menu, it breaks nvim_cmp menu and it will not show it anymore after that (in any buffer). If I close the cmp menu and expand the snippet via direct trigger, the cmp menu continues working

L3MON4D3 commented 3 years ago

Did the reinstall you mentioned in nvim_cmp also fix this error?

lambtho12 commented 3 years ago

Yes! Sorry, I forgot to mention it here as well. I still have no idea about what was the underlying issue.

L3MON4D3 commented 3 years ago

Nice :ok_hand: Soooo... everything works? :eyes: :P

lambtho12 commented 3 years ago

I haven't written much yet, but it seems to be good for now. Thank you again for your quick solution. I will reopen this issue if I stumble across an issue with a bit more use.

gegoune commented 3 years ago

Apologies for digging this out, thought it might be more fitting than crating new issue but can do that if you prefer it that way.

friendly-snippets just merged conventional commit snippets (for git). I am trying to get them to work with Neogit, which sets its own filetype instead of gitcommit. I am lazy loading snippets like this (I have no lazy loading of any plugins, etc):

local ls = require 'luasnip'
require('luasnip.loaders.from_vscode').lazy_load {}
ls.filetype_extend('NeogitCommitMessage', { 'gitcommit' })

but it does not show those snippets. It works when I use load() instead of lazy_load(). Is that expected or an issue? Would rather not load all snippets (continue using lazy_load()).

saadparwaiz1 commented 3 years ago

@gegoune do the snippets show up if you try to list them?

L3MON4D3 commented 3 years ago

It's alright to continue in this issue :) Thats definitely not expected, especially because it works with load(). "Not show" as in no entry in cmps completion? Do they work when triggered manually?

gegoune commented 3 years ago

Thanks! :)

Just checked. They are not loaded:

{
  NeogitCommitMessage = {},
  all = {},
  gitcommit = {}
}

Confirming: filetype=NeogitCommitMessage for buffer.

Does not show up with compe and typing in feat and pressing tab which is my expand key does not expand it.

L3MON4D3 commented 3 years ago

~Weird, I cannot reproduce :/~

" don't have Neogit, so try this
:!echo "vim: ft=NeogitCommitMessage" > ngcm
:lua ls.filetype_extend("NeogitCommmitMessage", {"gitcommit"})
:lua require("luasnip.loaders.from_vscode").lazy_load()
:e ngcm
"feat<Tab> expands

~(I'm not on the most current version of friendly-snippets where this specific issue is fixed)~

~We load snippets on BufEnter, so if the correct filetype isn't set by then, it fails. Can you verify that it works with explicitly setting the filetype and doesn't with actual Neogit?~

gegoune commented 3 years ago

I tried what you did above but it still doesn't show nor expand those snippets.

gegoune commented 3 years ago

What's weird is that it doesn't even work with https://github.com/rafamadriz/friendly-snippets/commit/ea9434138da3a3c926b8abdb49de3206dac60f97 in.

L3MON4D3 commented 3 years ago

Could you git apply this patch, open the buffer with lazy-loading enabled and show the output?

diff --git a/lua/luasnip/loaders/from_vscode.lua b/lua/luasnip/loaders/from_vscode.lua
index 21d6726..a4678cc 100644
--- a/lua/luasnip/loaders/from_vscode.lua
+++ b/lua/luasnip/loaders/from_vscode.lua
@@ -222,6 +222,7 @@ function M.load(opts)
 end

 function M._luasnip_vscode_lazy_load()
+   print(vim.bo.filetype)
    local fts = util.get_snippet_filetypes(vim.bo.filetype)
    for _, ft in ipairs(fts) do
        if not caches.lazy_loaded_ft[ft] then
gegoune commented 3 years ago

Interesting, it does not print anything. When I open another buffer (lua for example) it prints the filetype as expected.

L3MON4D3 commented 3 years ago

Oh, yeah no wonder no snippets are loaded then :D We could probably change the events on which lazy-load snippets are added, right now it's BufEnter (which could also be BufNew), if we add FileType it will work for Neogit (although I'm not sure why BufEnter isn't triggered, we should look into that before changing anything). What do you think @leiserfg?

L3MON4D3 commented 3 years ago

Also, what is printed when you do what I tried earlier, with setting ft via modeline?

gegoune commented 3 years ago

Also nothing, but ft is set properly.

L3MON4D3 commented 3 years ago

Oh no, mb with the example, I had a load() in my config that I didn't notice :|

L3MON4D3 commented 3 years ago

Okay, I implemented what I described earlier in #196, could you check out that branch and try if the snippets load now?

gegoune commented 3 years ago

It works now. :) No need to extend snippets, latest change in friendly-snippets is enough.

Great thanks! ❤️ Will wait for that PR to merge.