Vim - ftplugin settings changes not updating for existing file - vim

It seems like there's some odd caching-like behavior going on for files that I have already opened once in Vim. I have a file foo.txt that I opened, and then I change some of the settings in ~/.vim/after/ftplugin/text.vim, but those new settings do not appear in foo.txt. I can quit vim and reopen foo.txt, or reload with :e, or even :so ~/.vim/after/ftplugin/text.vim, but none of these seem to have an effect on foo.txt's settings. If I mv foo.txt bar.txt, the settings show up for bar.txt with no issues.
EDIT
It seems I can force the settings to reload for foo.txt with the following sequence:
:so ~/.vimrc
:so ~/.vim/after/ftplugin/text.vim
Questions:
Why is this necessary / why were the other settings not picked up?
Why was sourcing ~/.vimrc not enough? It applied settings that were directly specified in ~/.vimrc, but shouldn't the ftplugins have been loaded at the line filetype plugin indent on? Why was sourcing text.vim afterwards necessary?

Vim runtime consists of a few hundred files, I'm not sure why you expect Vim to monitor them continuously. It doesn't. These files are loaded at some well-defined (and documented) points, that's all there is to it.
In particular there is no safe way to reload your configuration. You can do things like :so ~/.vimrc, but unless you specifically wrote your vimrc to take that into account, there will be drawbacks (such as autocmds piling up). If you want to be safe you have to quit Vim and start it again. That's how Vim works.
Now, for ftplugins you might get away with something like this:
:setf text
(use the actual filetype instead of text). This works for simple set fubar options. It works because under the hood setf is actually a carefully written autocmd. It still breaks for more complicated constructs (such as autocmds or file-scoped variables), for the same reasons :so ~/.vimrc has drawbacks.

A few more precisions:
.vimrc is loaded once -> for defining global stuff
same thing with .gvimrc, loaded only with gvim after the .vimrc
plugins are loaded once as well, after the vimrc files -> for global stuff as well
autoloaded plugins are loaded on demand, once, whenever a function they define is invoked
ftplugins are loaded once per buffer (and possibly multiple times! as there may be multiple buffers requiring them to be sourced) -> for definitions that shall apply only to the current buffer that triggered its loading
there are also langmap scripts, syntax scripts, indentation scripts, and even the old macros/ scripts (loaded explicitly/manually)
some plugins provides local vimrcs (basically identical to ftplugins, but loaded depending on the current directory of a buffer, instead of its filetype).
As you see, all things are loaded once, only. If you want to load them several times, you'll have to do it manually and explicitly. That's why a few of us have a :Reload command that simplifies reloading any kind of script - mine is hidden in my collection of scripts: lh-misc -> plugin/vim-maintain.vim

Related

How to set a VimScript to be executed last?

Problem
A setting in my vimrc (set noshowmode) is being overridden by a plugin later in the loading process.
Goal
Have a VimScript file be executed last (or at least after plugins).
What I Know
Plugin VimScripts are executed after the vimrc (Source).
The after-directory is run close to last and holds user overrides
(Source: :h after-directory).
Vim's runtimepath determines the order of what is run.
Failed Attempts
I tried appending a VimScript file (containing set noshowmode) to the
end of $VIMRUNTIME with
set runtimepath=$VIMRUNTIME,~/.vim/nosmd.vim, but this method ended up
messing up other plugins (namely vim-airline, which did not load).
I also tried creating the ~/.vim/after directory and putting my
VimScript in there, but this had no effect.
Your attempts
set runtimepath=$VIMRUNTIME,~/.vim/nosmd.vim
That cannot work. 'runtimepath' contains a list of root configuration directories; you cannot directly place script files in there. Instead, point to a directory that contains plugin/yours.vim.
I also tried creating the ~/.vim/after directory and putting my VimScript in there, but this had no effect.
You can check with :scriptnames to see whether your script was executed (and at the end of the plugin load sequence!)
Solutions
An ounce of prevention is better than any workaround. I would first try to locate the culprit who changes the 'showmode' option; a plugin shouldn't do this (or at least have a configurable option to disable it).
:verbose set showmode?
might already tell you who changed this setting.
As #romainl already commented, ~/.vim/after/plugin/myplugin.vim should work for undoing this. If it doesn't try the following autocmd (in your ~/.vimrc) as a last resort:
autocmd VimEnter * set noshowmode

Pathogen and Neocomplete, Supertab, Youcompleteme; how to enable disable bundles?

I use Pathogen to load my plugins at startup.
Sometimes I use Neocomplete plugin, sometimes YouCompleteMe plugin and sometimes Supertab to complete words and sometimes I use no completer at all.
These plugins do not work together if they are all loaded in Pathogen.
That's why I decided to create a little menu at then end of my vimrc where I can chose which completer to use (the one that I want to use is the one I disable in pathogen). I can launch it with a shortcut key.
The list g:PATHO contains the plugins to disable in pathogen:
If I chose to use Supertab --> remove Supertab from g:PATHO, save g:PATHO and reload vimrc.
If I chose to use Neocomplete --> remove Neocomplete from g:PATHO, save g:PATHO and reload vimrc.
If I chose to use Youcompleteme --> remove Youcompleteme from g:PATHO, save g:PATHO and reload vimrc.
This is what I have at the start of my _vimrc
if !exists("g:PATHO")
let g:PATHO = ['YouCompleteMe','neocomplete.vim','supertab']
endif
let g:pathogen_disabled = g:PATHO
below in my _vimrc I have this command to save global variables in my viminfo file:
set viminfo+=!
(thanks to Ingo Karkat)
g:PATHO is written in viminfo but when I reload vimrc, the variable g:PATHO is not found because viminfo is not yet read at the start of _vimrc.
When is viminfo read in _vimrc?
How can I let pathogen read g:PATHO at vimrc startup?
(hope I made myself clear)
Did you read :help startup?
Your viminfo file is read very late in the initialization process, after your vimrc and all your plugins are sourced, so pathogen won't be able to compare the default g:PATHO that you hardcoded in your vimrc with the one in your viminfo.
Your viminfo file is read only once, late in the initialization process, and will never be re-read again during the life span of your session. Reloading your vimrc will never trigger that re-read and neither pathogen nor any other plugin will notice the change you hoped to persist.
You can try :rviminfo to re-read that file manually and autocmds on VimEnter or some other event but…
…modifying the g:pathogen_disabled variable during a session won't have the effect you want: it doesn't remove a plugin from your runtimepath and it doesn't "unsource" it either. You can reload your vimrc all you want with different values for that option, the result will always be the same: nothing.
What you need — beyond coming up with a convincing justification for such a weird idea or even for the fact that you have three freaking completion plugins in your config — is to find a way to effectively make the functions and variables and whatever of a specific plugin completely disappear from Vim's memory. And I believe you won't find it here.
As a side note, only one of the three plugins provides built-in commands to enable/disable it. That is a sensible design choice that, if it was more universally available, would make the life of plugin hoarders a lot easier.

Apply changes to .vimrc to source file

Im currently making a lot of changes in my .vimrc. At the same time Im also coding away on a project. To fix the new indentation and tabstop rules, and so on, I have to go through every line and re-indent them. This seems a little bit tedious.
Is there any way to apply the newest changes in my .vimrc to the whole source file?
Your problem seems to be that existing buffers do not get the updated (global) values of e.g. 'tabstop', because these are buffer-local options. Therefore, a simple :so % after editing the ~/.vimrc isn't sufficient.
There are several possible approaches:
Use sessions
With the current Vim state persisted via :mksession, you can safely :quit Vim, restart it, :so session.vim, and have the identical editing state, but with the new settings applied (this requires that you :set sessionoptions-=options)
Manually apply
You can e.g. :yank the changed :set tabstop=... commands that you've edited and reapply them to all existing buffers, e.g. by moving there and :#", or (if there are many) with the help of :bufdo.
Note that especially the indent settings can also be set from ftplugins, so your global settings may not be effective. You can check that for a buffer with :verbose set tabstop?.

Why does my Vim always save a file, no matter what?

Whenever I quit a file, even using :q!, Vim will save it. What could possibly be causing this?
In init:
ack.vim
keybindings.vim
nerdcommenter.vim
nerdtree.vim
options.vim
supertab.vim
syntastic.vim
tabline.vim
vcomments.vim
vim-fugitive.vim
vim-powerline.vim
in plugin:
EasyMotion.vim
mru.vim
Often, a binary search where you disable half of your plugins, then only one half of that (when the problem is still there), or the other half (when the problem vanished) lets you get to the problematic script quickly. The same can be done with the configuration in your ~/.vimrc (by commenting out blocks).
Also, you can capture a full log of a Vim session with vim -V20vimlog. After quitting Vim, examine the vimlog log file for appropriate commands. In your case, that would be :write commands.

.vimrc overridden by sys admins settings

I have a mapping in my .vimrc file to map F2 to save a file. Have done this for years. However now the system administrator has decided to override my setting with one of their mappings. If I run :scriptnames I see the order and I know which one is the offending script.
Is there a way to just ignore one startup script? I also tried creating a .vim/after/fixit.vim file which re-did the mapping but that file does not get read.
I know I could ignore all files and just load my .vimrc but I do want some of the administrator's defaults, just not all.
You can only avoid sourcing of a script if it uses the canonical inclusion guard:
:if exists('g:loaded_pluginname') | finish | endif
But it probably doesn't.
Your idea with .vim/after/fixit.vim is a good one (you haven't posted your :scriptnames output, so I can't tell for sure), but you need to include the plugin subdirectory there, too:
.vim/after/plugin/fixit.vim
Finally, as a last resort, you can define an :autocmd VimEnter (in your ~/.vimrc). That autocmd will fire after all other initializations, so you can definitely change the offending mapping in there.

Resources