Search code examples
vimluaneovim

Why is Nvim default settings overriding my ftplugin settings? (Neovim)


When I open a PHP file, Neovim sets nosmartindent and indentexpr=GetPhpIndent().

This is a bummer, because GetPhpIndent() is completely broken and makes the editing experience a nightmare where I have to constantly fix the indentation of every line I type.

I created a file $RUNTIME/after/ftplugin/php.lua with this content inside:

vim.bo.indentexpr = nil
vim.bo.smartindent = true
print("I APPLIED SOME SETTINGS!")

I added the print statement just to confirm it gets loaded, and it does. Every time I open my PHP file, I see the text printed.

HOWEVER, my settings are unchanged. The settings are still being set by the runtime:

Screenshot 1 Screenshot 2

So it it because my lua file doesn't work? NOPE, if I source it after opening the file, my settings are updated correctly.

So it seems like Nvim's default settings are applied after my ftplugin file, in which case what the heck is the point of ftplugin?

Help!


Solution

  • Indent scripts are sourced after all filetype plugins, including those in after/, and syntax scripts are sourced after all indent scripts, including those in after/.

    In other words, the sourcing order is not "per-location":

    " first wave: root of user runtime
    ftplugin/foo.vim
    indent/foo.vim
    syntax/foo.vim
    
    " second wave: Vim runtime
    $VIMRUNTIME/ftplugin/foo.vim
    $VIMRUNTIME/indent/foo.vim
    $VIMRUNTIME/syntax/foo.vim
    
    " third wave: after in user runtime
    after/ftplugin/foo.vim
    after/indent/foo.vim
    after/syntax/foo.vim
    

    but "per-function":

    " first wave: filetype plugins
    ftplugin/foo.vim
    $VIMRUNTIME/ftplugin/foo.vim
    after/ftplugin/foo.vim
    
    " second wave: indent scripts
    indent/foo.vim
    $VIMRUNTIME/indent/foo.vim
    after/indent/foo.vim
    
    " third wave: syntax scripts
    syntax/foo.vim
    $VIMRUNTIME/syntax/foo.vim
    after/syntax/foo.vim
    

    So your settings from the first wave (ftplugin) are overridden by the second wave (indent).

    Since the settings you are trying to override come from an indent script, you must put your overrides in after/indent/php.vim.

    what the heck is the point of ftplugin?

    • The point of indent scripts is to deal with filetype-specific indenting matters.
    • The point of syntax scripts is to deal with filetype-specific syntax highlighting matters.
    • The point of filetype plugins is to deal with everything else filetype-specific.