Shougo / neosnippet.vim

neo-snippet plugin
Other
1.12k stars 108 forks source link

Inconsistent snippet load order #491

Closed i-sinister closed 4 years ago

i-sinister commented 4 years ago

I have following setup:

My local 'cs.snippets' has some snippets that have the same name as in neosnippet-snippets and this is intentional as I want to 'override default snippets'. However 'overriding' does not work and snippets from 'default collection' are always used.

I've monkey-patched neosnippet plugin to add some tracing and found that plugin does not honor directory order - when snippets for the filetype are defined in multiple directories (neosnippet#helpers#get_snippets_directory()) a snippet from directory that comes later does not always override snippet from the previous directory.

In my case path was:

/home/user/.cache/vim/plugged/neosnippet-snippets/neosnippets,/home/user/.config/vim/snippets

However snippets were cached (by neosnippet#commands#_make_cache in autoload/neosnippet/commands.vim) in the following order:

  1. /home/user/.config/vim/snippets/cs.snippets
  2. /home/user/.cache/vim/plugged/neosnippet-snippets/neosnippets/cs.snip

So my local snippets were overriden by default.

It turned out that in the function s:get_snippets_files in autoload/neosnippet/commands.vim snippets are search with the hardcoded file extension order - first .snip files and then .snippets. So in my case files found were:

  1. glob=cs.snip: /home/user/.cache/vim/plugged/neosnippet-snippets/neosnippets/cs.snip
  2. glob=cs.snippets: /home/user/.config/vim/snippets/cs.snippets

And the reverse call at the end of the function would place 'default snippets' after my local overrides.

To fix the issue I had to rename local snippets file to cs.snip and set g:neosnippet#snippets_directory just to make it appear in the path before the directory of neosnippet-snippets.

I'd expect snippets to be loaded in the order of directories in the path regardless of their extension for there can be multiple plugins providing snippets with conflicting names for the same filetype and I'd like to be able to manage conflicts by changing plugin load order or by setting g:neosnippet#snippets_directory.

Shougo commented 4 years ago

I've monkey-patched neosnippet plugin to add some tracing and found that plugin does not honor directory order - when snippets for the filetype are defined in multiple directories (neosnippet#helpers#get_snippets_directory()) a snippet from directory that comes later does not always override snippet from the previous directory.

It is true, but please read the code.

  for filename in neosnippet#helpers#get_snippets_files(filetype)
    " Clear cache file
    call s:Cache.deletefile(cache_dir, filename)
    let snippets[filetype] = extend(snippets[filetype],
          \ neosnippet#parser#_parse_snippets(filename))
  endfor

The later directory(and snippets) overwrites previous snippet. So I think the default snippets are overwritten.

Shougo commented 4 years ago

Your report is too long. I need to reproduce the problem.

Please create the minimal reproduce-able instruction.

Shougo commented 4 years ago

I have fixed the problem. Please use the latest version.

i-sinister commented 4 years ago

Thank you for the fast response. Problem still exists but now it is related to the order of directories only. I've been using outdated version of the plugin and current version is different in 2 important points:

So snippets files are discovered in the following order:

  1. /home/user/.config/vim/snippets/cs.snippets
  2. /home/user/.cache/vim/plugged/neosnippet-snippets/neosnippets/cs.snip

As a result 'default snippets' override local still.

Adding local directory to g:neosnippet#snippets_directory wont help because it is included in the neosnippet#variables#runtime_dir and files found for the second entry will be ignored. I've solved it by moving local snippets to the after directory so that plugins, but this is ugly.

Is it possible to implement loading in a way that local snippets are not overwritten?

Shougo commented 4 years ago

Your report is too long. I need to reproduce the problem.

Please create the minimal reproduce-able instruction.

Please read this.

Shougo commented 4 years ago

I need to reproduce the problem. So please upload the reproduce-able ways.

If not, I need to ignore your issue unfortunately.

Shougo commented 4 years ago

Why don't you upload reproduce-able instructions like this? https://github.com/Shougo/neosnippet.vim/issues/465

please explain it for me.

Shougo commented 4 years ago

I've been using outdated version of the plugin and current version is different in 2 important points:

I don't understand it. Why do you use the outdated version??

Shougo commented 4 years ago

Ah, I get it. It is neosnippet#variables#runtime_dir() problem.

But to change the behavior, breaks other snippets loading like this. https://github.com/honza/vim-snippets

Shougo commented 4 years ago

Please use other directory name instead of snippets. It is used for snipMate default snippets.

Shougo commented 4 years ago

So I won't fix the second problem to keep compatibility.

Shougo commented 4 years ago

Is it possible to implement loading in a way that local snippets are not overwritten?

neosnippet does not detect ~/.vim/snippets as local snippet. It is runtime snippet directory name. You need to change the snippet directory name.

i-sinister commented 4 years ago

I need to reproduce the problem. So please upload the reproduce-able ways.

Ok, sorry, will do next time - thought issue description is clear enough so that steps to reproduce are not necessary

I don't understand it. Why do you use the outdated version??

Installed quite a long time ago and did not have a need to update it because it was working for me.

But to change the behavior, breaks other snippets loading like this

Now I get it - my problem is that local snippets are under the vims runtimepath and they are discovered before snippets from plugins. It means you can not have snippets in snippets/neosnippets folder under the ~/.vim folders (in my case it is~/.config/vim). This could be added to the documentation.

Having 'local snippets' in the 'local vim configuration' folder would be nice, but I can live without it - I'll just keep using after folder. Another option is to put them to separate plugin. Moving snippets outside ~/.vim is not an option for I would like to have vim related configuration in one place.

Thank you.

Shougo commented 4 years ago

Ok, sorry, will do next time - thought issue description is clear enough so that steps to reproduce are not necessary

Sorry. The long description is hard to understand for me. And the code is very clear for me. I have studied Vim script than English :-)

Installed quite a long time ago and did not have a need to update it because it was working for me.

Hm. OK.

Now I get it - my problem is that local snippets are under the vims runtimepath and they are discovered before snippets from plugins. It means you can not have snippets in snippets/neosnippets folder under the ~/.vim folders (in my case it is~/.config/vim). This could be added to the documentation.

Yes. It may confuse users like you. So I have changed the documentation.

Note: I had set my snippets directory in ~/.vim/snippets. So I have changed it to ~/.vim/my-snippets.

Shougo commented 4 years ago

Having 'local snippets' in the 'local vim configuration' folder would be nice, but I can live without it - I'll just keep using after folder. Another option is to put them to separate plugin. Moving snippets outside ~/.vim is not an option for I would like to have vim related configuration in one place.

This workaround may be ugly. But I cannot change the behavior to keep compatibility... In deoppet plugin, the configuration will be more clearly than neosnippet. https://github.com/Shougo/deoppet.nvim