Vim In-File Commands - vim

I'm after a means by which I can add additional commands to a text file via vim. For example, just as you can do something like this:
# vim:syntax=foo
I'd like to do something like:
# vim:option call matchadd('Special', '\(REQUIRED\|OPTIONAL\)')
Any ideas? I know I can write a syntax file, but this is not what I'm after for now.

Vim modeline syntax (see :help modeline) is not intended to specify commands
to execute during file opening. That is exactly what autocommands is for (see
:help autocommand). What you are trying to do should be an autocommand
similar the following.
autocmd FileType foo call matchadd('Special', '\(REQUIRED\|OPTIONAL\)')
or
autocmd BufReadPost *.foo call matchadd('Special', '\(REQUIRED\|OPTIONAL\)')
(Here instead of *.foo you can use any pattern that matches path or filename
(or both) of the target file.)
If the configuration you are setting up is local to some files or a project,
and you don't want to pollute your .vimrc with those autocmds, use
localvimrc plugin. It allows you to have a "local" .vimrc file next to
your target file or project folder. Script stored in that .lvimrc is
executed when you open files in the same directory where the "local" .vimrc
is, or in its subdirectories. Autocommands shown above (or any other
configurations) can be stored in a .lvimrc file local the project. For
details about localvimrc configuration see the homepage of the plugin.

This isn't an answer to your question, but I have also searched for Truth, and this question here is the closest one to it:
Vim: How to execute selected text as vim commands
It isn't automatic, but potentially only one keypress away it's close enough. :)

My ModelineCommands plugin extends Vim's built-in modelines to execute any Ex command(s) when a file is opened. A set of configurable validators examine the commands and can verify the correctness of an optional command digest, in order to prevent the execution of potentially malicious commands from unknown sources. (That's the main reason why Vim doesn't offer this feature!) This way, you could restrict the commands to only simple :let, or have the plugin query you to confirm execution of anything that isn't signed with your own secret key.

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

How to execute a file everytime before opening Vim

I have recently started using vim and I really like it. I have added a few easy mappings in my vimrc file.
But the problem is I get to use a lot of remote machines a lot of time and I can't copy my vimrc on to them but most of the times I won't have enough permissions to do that.
So, I was wondering if there is any way I can put all my vim mappings in a file and tell vim to run it every time it loads, just like a vimrc?
The action that is "parsing" the .vimrc is called source.
In runtime, you can reapply/reparse your .vimrc by using
:source ~/.vimrc
So if you can somehow copy your .vimrc, even if not in your home, but a folder like /tmp you should be able to source it from there, with
:source /tmp/.vimrc
This question has more details and solutions.
One option would be to specify an alternative .vimrc file while launching the program.
The vim man pages has this to say about specifying a vimrc file:
-u {vimrc}
Use the commands in the file {vimrc} for initializations. All the other initializations are skipped. Use this
to edit a special kind of files. It can also be used to skip all
initializations by giving the name "NONE".
See ":help initialization" within vim for more details.
Note that this option overrides the default vimrc file, so you'll have to specify all of your settings/options in this file.
As was mentioned in another answer, you can place your custom vimrc file anywhere you want (or have access to) and then specify the the -u option with the path to your vimrc file.
You could even combine this method with managing your custom vimrc file in an online version control system (like github) - this way you will be able to wget your file from the web instead of having to manually copy it from machine to machine.

Vim script to browse for a directory and retrieve the directory name

I'm attempting to write a plugin to ease my personal workflow. I'd like to be able to configure/reconfigure the plugin to refer to different directories (containing program outputs) - but without changing the vim working directory. In order to do I'd like that whenever I need to point my plugin at a different directory, e.g. by calling the a "reconfigure" function, a convenient interface pops up which allow me to browse through the filesystem and pick the directory using some shortcuts.
My first thought was to use netrw, configured to hide non-directories, but once I'm inside a directory how can I then obtain the current netrw directory path for use in my script? Is there a better way of doing this?
What if I want to pick a file instead of a directory? Is there an easy way to change the Enter key in netrw so that it changes into directories but when the selected item is a file it will call my custom callback function (for example).
Is there a better way of prompting the user for a file directory?
Without knowing the exact background, I would recommend triggering your Vim script via a custom command, and pass the file / directory as a command argument. If you define the command like this:
:command -nargs=1 -complete=file MyCommand call MyFunction(<q-args>)
you'll get Vim's file / directory (cp. :help :command-complete) completion in the command line for free.
There's :browse built-in, but it only works for file-related commands like :edit or :write; you cannot put the value into a variable.
There's inputdialog(), which allows you to query for any string; unfortunately, without (file-) completion.
It would be possible to hook into plugins like netrw, overriding the plugin's mappings for file selection (e.g. :nnoremap <buffer> <CR> ..., but this will entangle your plugin deeply with it.
Summary
Don't forget, Vim is a text editor, so excessive passing of filenames / directories should not be necessary. Depending on your use case, this might be better handled by an external tool (invoked by Vim).
The current netrw directory path is in the variable
b:netrw_curdir
Note that it will track vim's current directory if g:netrw_keepdir is zero.

.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.

Executing vim command based on filetype?

I'm trying to have the command
let b:match_words='<:>,<\#<=\([^/][^ \t>]*\)[^>]*\%(>\|$\):<\#<=/\1>'
run every time I open an html file. I tried putting the line
autocmd FileType html let b:match_words='<:>,<\#<=\([^/][^ \t>]*\)[^>]*\%(>\|$\):<\#<=/\1>'
in a file named html.vim in both my ftdetect and ftplugin folders and nothing happened. How do I have the command run everytime I'mm in an html file?
The command is to change the matching behavior of matchit btw.
In general, your autocmd is alright; the problem is that you're trying to redefine the b:match_words definition done in $VIMRUNTIME/ftplugin/html.vim, so the execution order becomes important.
The place for these customizations is in the after directory, i.e. ~/.vim/after/ftplugin/html.vim; just create a new file and put the :let command in there.
You can observe the sequence of sourced scripts via :scriptnames. In other cases, when you're not overriding default behavior, the :autocmd FileType is alright, but I prefer putting these (e.g. custom mappings) into ~/.vim/ftplugin/html_mymappings.vim, as it provides better separation and helps keeping your .vimrc short and understandable.
The ftdetect subdirectory is for filetype detection, i.e. inspecting file path / name / contents to determine the correct filetype. It doesn't apply here, as the filetype is html.

Resources