Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

vim_configurable: unable to use plugin syntax files #39364

Closed
ivanbrennan opened this issue Apr 23, 2018 · 9 comments · Fixed by #78385
Closed

vim_configurable: unable to use plugin syntax files #39364

ivanbrennan opened this issue Apr 23, 2018 · 9 comments · Fixed by #78385

Comments

@ivanbrennan
Copy link
Member

Issue description

Using vim-configurable to bake plugins into a system-wide vim configuration, there doesn't appear to be a way to make a plugin's syntax files precede those in $VIMRUNTIME. Since most syntax files contain a guard-clause to avoid clobbering any previously-set syntax, such plugins can't have the desired effect.

I'm using Vim 8 packages to bake haskell-vim (plus some other plugins) into my system-wide vim configuration. I have an overlay that contains:

vim-configured = self.vim_configurable.customize {
  name = "vim";
  vimrcConfig = {
    packages.myPackage = with pkgs.vimPlugins; {
      start = [ haskell-vim foo bar baz ];
      opt = [];
    };
  };
};

The haskell-vim plugin contains a syntax file. A less feature-rich syntax file also exists at $VIMRUNTIME/syntax/haskell.vim. Both files begin with a guard-clause:

if exists("b:current_syntax")
  finish
endif

and end with

let b:current_syntax = "haskell"

so whichever runs first wins.

I want to use haskell-vim's syntax file, but the way vim_configurable works, I end up with a runtimepath like:

~/.vim
$VIMRUNTIME
~/.vim/after
/nix/store/xxxx-vim-pack-dir/pack/myPackage/start/haskell-vim

I'm trying to figure out how I could bump this particular plugin to an earlier position in runtimepath, whether it makes sense to bump the whole package (all plugins), or whether there's some other solution.

Technical details

nix-shell -p nix-info --run "nix-info -m"
 - system: `"x86_64-linux"`
 - host os: `Linux 4.14.33, NixOS, 18.09pre135256.6c064e6b1f3 (Jellyfish)`
 - multi-user?: `yes`
 - sandbox: `no`
 - version: `nix-env (Nix) 2.0`
 - channels(root): `"nixos-18.09pre135256.6c064e6b1f3"`
 - nixpkgs: `/nix/var/nix/profiles/per-user/root/channels/nixos/nixpkgs`
@ivanbrennan
Copy link
Member Author

I found a way to work around this. I added a symlink to the relevant syntax file in my user vim config:

ln -s \
    /run/current-system/sw/share/vim-plugins/haskell-vim/syntax/haskell.vim \
    ~/.vim/syntax/haskell.vim

This works because ~/.vim is earlier in Vims runtimepath than $VIMRUNTIME is.

I was mystified for a while as to why /run/current-system/sw/share/vim-plugins/ was empty despite all the plugins I've baked into my Vim derivation, but finally realized they only show up there if they're listed in environment.systemPackages. I previously had no need to include them in that list. Now, I've added the haskell-vim plugin to systemPackages and everything works.

@akavel
Copy link
Contributor

akavel commented Sep 28, 2018

I encountered the same problem. As far as I understand the situation, this is a bug in vim-utils.nix (edit: in vim8/neovim's handling of packpath? see further below). Specifically, vim-utils.nix in nixpkgs currently contains the following fragment:

      ''
        set packpath-=~/.vim/after
        set packpath+=${packDir packages}
        set packpath+=~/.vim/after
      ''

where += means user plugins are appended at the end of packpath.

I checked the code of one of the top "classical" Vim plugin managers — Vundle — and it prepends the user plugins at the beginning of rtp, with ^= operator, as seen below:

  let paths = map(copy(g:vundle#bundles), 'v:val.rtpath')
  let prepends = join(paths, ',')
  let appends = join(paths, '/after,').'/after'
  exec 'set rtp^='.fnameescape(prepends)
  exec 'set rtp+='.fnameescape(appends)

(Only the explicitly named /after subdirectories of the plugins are appended to the list with +=; the default action is to prepend with ^=.)

The behavior of Vundle also matches the semantics of the default value of rtp (a.k.a. runtimepath) on Unix as specified in Vim manual:

default:
	Unix: "$HOME/.vim,
		$VIM/vimfiles,
		$VIMRUNTIME,
		$VIM/vimfiles/after,
		$HOME/.vim/after"

I was hit by this problem when trying to load the vim-go plugin into neovim. Unforutnately, its filetype plugin fails to load (disabling many important features of vim-go), because the ftplugin/go.vim file from $VIMRUNTIME is earlier in runtime path than vim-go's one, as a result of the above bug in vim_customizable a.k.a. vim-utils.nix.

EDIT: After some more digging, I believe this is actually just how neovim (and vim8?) behaves. I don't understand why it's so. I forked nixpkgs and changed the snippet to:

      ''
        set packpath^=${packDir packages}
      ''

but the plugin directories are still appended at the end of rtp, which makes them problematic to use for syntax and/or ftplugin functionality.

My current workaround is to add the following string at the beginning of my .vimrc:

    let
      loadPlugin = plugin: ''
          set rtp^=${plugin.rtp}
          set rtp+=${plugin.rtp}/after
        '';
    in ''
      " Workaround for broken handling of packpath by vim8/neovim for ftplugins
      filetype off | syn off
      ${builtins.concatStringsSep "\n"
        (map loadPlugin plugins)}
      filetype indent plugin on | syn on
    ''

@Azulinho
Copy link
Contributor

@akavel workaround works for me, I got caught by this when my python-mode vim plugin wasn't working

here is my config, which works file:
https://gitlab.com/myConfigs/nixpkgs/blob/master/home.nix

@timokau
Copy link
Member

timokau commented Dec 31, 2018

I created the issue #52722, which I now realize is a duplicate. I also created a report upstream, which may be interesting for the people here. If you have any additional info, please add it there: neovim/neovim#9390

@NickHu
Copy link
Contributor

NickHu commented Apr 24, 2019

I followed @akavel's workaround as per @Azulinho's example, but I kept getting errors about duplicate entries in the runtimepath. The fix is to not set packages.neovim-with-packages (it's unnecessary now anyway, as all we're building the runtimepath ourselves instead of relying on it to generate packpath).

@tqbl
Copy link

tqbl commented Jul 22, 2019

The problem here is that the default runtimepath includes $VIMRUNTIME already. Vim does appear to respect the order in packpath, but this doesn't matter because the paths will be appended to a runtimepath that is already non-empty. This is not a bug in vim (or neovim) as far as I'm concerned.

The good news is that directories can be included in the default runtimepath before $VIMRUNTIME: either via $VIM/vimfiles or RUNTIME_GLOBAL (and via ~/.vim, of course). RUNTIME_GLOBAL is not set by default, but can be during compile-time using the --with-global-runtime option. In any case, the set packpath code would no longer be needed in the vimrc.

I don't know if there's a clean way to do this if the interface is to be preserved. I managed to get things working with the --with-global-runtime option, but the code is ugly. I basically modified the configure function to first call vim.overrideAttrs before calling itself again with the result. I don't know how you would implement the 'vimfiles' approach; you would want to create a symlink in the original vim_configurable output path, but how?

Ultimately, I think breaking changes need to be made if we want clean code.

P.S. I believe this is also the cause of LnL7/vim-nix#11, to mentioned another issue.

@timokau
Copy link
Member

timokau commented Jul 22, 2019

This is not a bug in vim (or neovim) as far as I'm concerned

What do traditional plugin managers like vim-plug differently then?

@tqbl
Copy link

tqbl commented Jul 22, 2019

I'm not too familiar with the internals of these package managers, but, looking at vim-plug, it does quite a bit to ensure that the user-specified plugins are loaded correctly. The take-away is that it's modifying the runtimepath directly. If you want to go that route, akavel's solution (#39364 (comment)) is nice and simple.

@voidus
Copy link
Contributor

voidus commented Sep 3, 2022

As far as I can tell, the fix only applied to vim proper, not neovim. Should that be a separate issue or can we re-open this? (Or am I holding it wrong?)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants