Can you have different localleaders for different Vim plugins? - vim

I started using a plugin that conflicts with my existing maps, but instead of remapping all of it's maps, I just want to add a prefix. I thought I'd be able to do this with LocalLeader.
Vimdoc says:
<LocalLeader> is just like <Leader>, except that it uses
"maplocalleader" instead of "mapleader". <LocalLeader> is to be used
for mappings which are local to a buffer.
It seems that the only way to set localleader is to set a global variable (the docs don't mention this, but b:maplocalleader didn't work):
let maplocalleader = '\\'
And I don't see how I'd cleanly unset that variable (an autocmd that clears it after plugins are setup!?)
Is there a way to do this? Or is LocalLeader only to give one global prefix and one filetype-specific prefix?

Your last hunch is correct. If the plugin uses <Leader> (and it should unless it's a filetype plugin), there's no use in messing with maplocalleader.
Remapping is canonically done via <Plug> mappings, which the plugin hopefully offers. Some plugins do define a lot of similar mappings, some of those define a g:pluginname_mappingprefix (or so) variable to save you from having to remap all mappings individually. If your plugin doesn't, maybe write a suggestion / patch to the plugin author.

While #IngoKarkat solution is a prefered one, there is a hack which lets you do what you want: the SourcePre event:
autocmd SourcePre * :let maplocalleader='\\'
autocmd SourcePre plugin-name.vim :let maplocalleader='_'
. This works for <Leader> as well. There are lots of cases when this won’t work though. You can as well use SourceCmd for this job, using something like
function s:Source(newmll)
try
let oldmll=g:maplocalleader
let g:maplocalleader=a:newmll
source <amatch>
finally
let g:maplocalleader=oldmll
endtry
endfunction
let maplocalleader='\\'
autocmd SourceCmd plugin-name.vim :call s:Source('_')
in SourceCmd is the only way I see to restore maplocalleader after plugin was sourced, but SourceCmd event here won’t be launched for any file sourced inside plugin-name.vim. For some poorly written plugins (I mean, those that emit errors while sources) putting :source inside a :try block will break execution at the point where error occurs. Should not happen most of time though. You may also want to use */ftplugin/plugin-name.vim as a pattern instead of plugin-name.vim.

Related

vim execute command depending on file type

How can I get vim to execute a command depending on the file type?
Recently I have been editing a lot of Python files and comments autoindent to the 0th column.
One way to fix this is to run the command inoremap # X#<left><backspace><right>
How can I get this command to run every time I open a python (*.py) file for editing?
TL;DR
Use vim's filetype plugin mechanism.
File-type specific code
There are (at least) two solutions to this, with one preferable to the other.
autocmd FileType
This has already been posted as an answer, but the general form is
augroup your_group
autocmd!
autocmd FileType python your good code
augroup END
This works, and has the advantage of grouping code in your vimrc.
But there is a second, more powerful, probably more performant alternative. It
is my preferred
solution.
after/ftplugin
I've written
extensively about using filetype
plugins in vim.
The gist of it is that you need filetype detection and plugins (filetype plugin
on at a minimum, though you may want filetype plugin indent on). Then you
drop filetype specific code in ~/.vim/after/ftplugin/<filetype>.vim (or a few
variants, see :h add-filetype-plugin, :h ftplugin-name, :h ftplugin).
So ultimately,
" ~/.vim/after/ftplugin/python.vim
inoremap # X#<left><backspace><right>
A few notes
It is a good practice to set b:undo_ftplugin properly: it helps (trust me).
You can borrow my undo script on
Github.
Consider using <buffer>, -buffer, setlocal, and <LocalLeader> where
possible. This is for local stuff, after all.
On power
A script gives you more flexibility than a single line of autocommands. You have
to jump through more hoops to do anything complex in autocommands, where in a
script they can just sit. Besides, you feel more like you're writing a program
(which you are) than a one off config.
The modularity is also perfect for organization: all your python customization
code is in one place.
And it's a lot less typing :)
On performance
I have not measured anything. Don't shoot me.
Having lots of autocommands can slow down vim, because they have to be checked
when their events fire. Rather than clog up the autocommands with filetype
stuff, use a file that is already going to be sourced for you (an ftplugin).
By piggybacking on an existing customization mechanic, you get all the benefit
and none of the risk. Again, it is almost certainly more efficient to let vim
source a file on demand for you then to try to reimplement it's ftplugin wheel.
Does this solve your issue?
au FileType python inoremap # X#<left><backspace><right>
This autocommand runs your mapping for filetype python

How do you turn off syntax highlighting for new vim windows without a filename or file type?

After I installed the 'artesanal' theme for vim and turned syntax highlighting on, every vim window has syntax highlighting including brand new empty windows [No Name], without a name or file type. I'm wondering if any of you know how to keep syntax highlighting on for every file with an extension but have it disabled for any file without a name or file extension.
This should not happen. I don't know artesanal (and "theme" is an undefined term inside Vim; it has colorschemes, filetype plugins, and syntax scripts; I hope it's not a full Vim "distribution" like spf-13 and Janus, which lure you with a quick install and out-of-the-box settings, but you pay the price with increased complexity (you need to understand both Vim's runtime loading scheme and the arbitrary conventions of the distribution) and inflexibility (the distribution may make some things easier, but other things very difficult)).
It looks like a syntax is active even for plain files. Usually, the syntax is determined by the filetype, so check :verbose setlocal filetype? first. If this returns a value, you need to look into the detection of :help filetypes.
If this is empty, it could also be that something sets 'syntax' directly. You can check in the same way: :verbose setlocal syntax?.
Now, if that also is empty, and :syntax list doesn't show something, the highlighting could also come from :match or :call matchadd() commands; :call clearmatches() would remove this then. (And you still would need to find the source that defines those matches.)
You can check to see if a filetype has been set
if &filetype != ""
syntax enable
endif

vim map confliction between vimrc and plugin

I'm using jedi-vim. It defines key map <Leader>n as some commands while I also defines it in .vimrc file like following.
nnoremap <Leader>n <C-w><C-w>
But when I typed <Leader>n in python file, jedi#usages() command was executed.
:map <Leader>n returns:
n <Space>n *#:call jedi#usages()<CR>
n <Space>n * <C-W><C-W>
I also tried to unmap <Leader>n before I defined the map. However, it raised an error saying nothing was defined.
How to avoid this conflict?
I know the problem will be fixed when I define g:jedi#usages_command to another command. I'd like to know the way to avoid overlapping mapping.
I know the problem will be fixed when I define g:jedi#usages_command to another command. I'd like to know the way to avoid overlapping mapping.
Defining g:jedi#usages_command is "the way to avoid overlapping mapping".
Plugin mappings always take precedence over yours because they define their mappings after you have defined yours.
There are solutions at the script level, like using <unique>, or checking if the mapping already exists, or simply not defining any user-level mapping… but that's the responsibility of the developer, not yours.
--- edit ---
To expand on Christian's comment… the last mapping always wins, that's how it works and nothing can be done by the user to protect his mappings.
Plugin developers, though, have a few mechanisms at their disposal for preventing their plugins to overwrite user mappings and user settings so it is not unreasonable to expect them to use those mechanisms to respect your mappings.

Buffer-local value of global variable?

Many Vim's plugin's settings are specified by let g:something = value. I have a need for setting buffer-local values of some variables (actually with vim-localvimrc)
I know there's a way to outwit by using a condition (Setting buffer specific variables in Vim). But not all these autocmds are under my control, since some are set by other plugins. Is there anything like setlocal for global variable?
There are many ways to do to what you actually want (strip trailing whitespace for some projects) but I don't think there is anyway to shadow a global variable with a buffer local one (which is what you asked).
One way to do this is to add
autocmd BufWritePre /path/to/project/* call StripTrailingWhitespace()
the following to your vimrc. Which will call the function StripTrailingWhitespace for any file under /path/to/project (including subdirectories). StripTailingWhitespace is defined in spf13.
You can probably generate the path to the project dynamically by looking at the path to the local vimrc file.
Another way would be to change the condition spf13 uses to call StripTrailingWhitespace
The StripTrailingWhitespace autocmd in spf13 is defined as the following. (I added newlines so I'm not sure if this will work.)
autocmd FileType c,cpp,java,go,php,javascript,python,twig,xml,yml,perl
\ autocmd BufWritePre <buffer>
\ if !exists('g:spf13_keep_trailing_whitespace') |
\ call StripTrailingWhitespace() |
\ endif
So you would change it to !exists('g:spf13_keep_trailing_whitespace') to some other condition like checking if in whitelisted projects or check a buffer local variable.
General recommendation would be to get rid of any vim distribution. It is very hard to understand what is in them when you are first starting out. It then becomes very hard to modify them. It is generally better to start from scratch and add plugins and mappings when you find something lacking. It will take longer but you will understand everything in your vim configuration.
In your case, the plugin you are using shall accept overriding global variables with buffer local variables. Indeed it can be done by changing the condition -- in lh-vim-lib there is a lh#option#get() function that'll be easy to adapt to spf13. If you think it makes sense, contact spf13 maintainers or open an issue in the project bug tracker.
Another solution would rely on defining a local_vimrc script for each project you are working on. In some projects you'll have a :let g:spf13_keep_trailing_whitespace = 1, in other you'll have a :silent! unlet g:spf13_keep_trailing_whitespace -- usually it is accomplished with a :let g:var=0, but the current condition ignores the variable value.

Reading efficiently PATHs in Vim

How can you open the following PATH by ctrl-w-f to a new window?
Path
/usr/masi/codes/11
The PATH refers to a file 11.tex.
I need to use 11 instead of 11.tex
because my LaTeX or pdflatex does not understand PATHs with tex
when I input/include the file.
Possible solutions are
to add something to .vimrc
to use perhaps differently pdflatex
In Vim 7.2, you can set the suffixesadd to .txt as below:
:set suffixesadd=.tex,.latex,.java
see :help suffixesadd
It seems you'll need to override CTRL-W_f to add a extension.
For instance, you could add the following in a tex-ftplugin:
nnoremap <buffer> <c-w>f :exe ':sp '.globpath('.', expand('<cfile>').'.*')<cr>
NB: this mapping is far from perfection. It's still need to glob on , and .*, to keep only one file (or none) if several match. And to support the no-match case.
I don't know about latex to answer from its side, but I don't see a setting to make Vim look for the path with extensions, so you will have to create a custom mapping. Unfortunately, there are no command-line equivalents to the gf and f style of commands, so you have to mimic something equivalent (sorry, untested).
function! OpenFile()
try
exec "normal! \<C-W>f"
except
if filereadable(expand('<cfile>').'.tex')
split <cfile>.tex
endif
endtry
endfunction
nnoremap <silent> <C-W>f :call OpenFile()<CR>
You can put this in an ftplugin (with option for nnoremap) to restrict it to your latex files only.
Note: If you want to cover different cases such as gf, F, you will need a more sophisticated function, or just write different functions for each.
I use vim 7.2 and it really works with default settings. If i understand the problem well.
It works with soft link and hard link both.

Resources