Enable Syntax highlighting in vim on a per-buffer basis - vim

I currently have to edit some very large XML files, which slows down syntax highlighting to a point where it's absolutely unusable - it takes multiple seconds to update the screen after a search operation, for example.
When disabling syntax highlighting (:syn off), the same operations happen instantaneously. Unfortunately, disabling syntax highlighting appears to happen globally, so all other files now have it disabled as well.
So: Is there a way to only disable syntax highlighting for a given buffer?

You can set :syntax manual and then enable it with set syntax=ON in the buffers you like. Also see :help :syn-manual.

Answering my own question: A simple hack would be to force the syntax of the file to something that vim doesn't know how to highlight: :set syntax=unknown
However, this seems a bit hacky - maybe there's another solution?

For large-file editing I usually use Chip's LargeFile plugin. It disables syntax highlighting, undo database and other features that give trouble with large files.

Old topic, but answer may be helpful to others.;)
This is what I lastly use for switching between syntax ON/OFF in the buffer. The change is local to the buffer. Works OK to me.
nnoremap <leader><leader> :call MyLocalSyntaxOnOff()<cr>
function! MyLocalSyntaxOnOff ()
if getbufvar("%", "&syntax") ==# "OFF"
setl syntax=ON
redraw | echo 'Syntax: ON - <space><space> to change.'
else
setl syntax=OFF
redraw | echo 'Syntax: OFF - <space><space> to change.'
endif
endfunction
Just add it to your .vimrc and You should by fine.
ADVISE: Set your leader key (my one is <space> currently), if not - the standard one should be slash (or backslash(?)) key - \.
Best regards.

Related

detect vrapper in .vimrc

In my .vimrc I have the following:
" Use j/k to navigate the word completion popup menu
inoremap <expr> j pumvisible() ? "\<C-N>" : "j"
inoremap <expr> k pumvisible() ? "\<C-P>" : "k"
This works perfect when using vim within a terminal, however this is not compatible with vrapper (eclipse vim plugin). Vrapper completely stops working when these settings are in my .vimrc. In my home directory I have a .vrapperrc file, which is simply a symobolic link pointing to my .vimrc file. Hence the vim settings which are loaded for vim / vrapper are equal.
Is there a way that in my .vimrc I can detect that the settings are loaded for vrapper instead of default (terminal) vim. That way I would like to disable these settings for vrapper and just load them when vim is used from the command line. Perhaps there is a different smart way to solve this issue. Of course I could create two .vimrc files, one for default vim and one for vrapper, however that way I would need to maintain two files which I would like to prevent.
I had a similar problem in which Vrapper executed the contents of my functions immediately because it didn't understand what they were.
I solved it by wrapping the vim only code with
if has("eval")
" vim only code
endif
which caused Vrapper to ignore it.
As #romainl noted, Vrapper only understands a limited set of Vim commands and features. Function definitions, ternaries and <expr> are definately not supported.
If you are willing to split your rc files, you could use the source command to at least reuse one of them.
For example, put these basic settings in your .vrapperrc:
set ignorecase
set hlsearch
Then you can do this in your .vimrc:
" Load common settings for Vim / Vrapper
source .vrapperrc
" ... Other Vim-specific settings
Note that Vrapper also has a source command, so you could in theory have 3 rc files with the "common" settings shared between the two:
Example .vrapperrc:
set novisualmouse
source .vimcommonrc
Example .vimrc
" Use j/k to naviage the word completion popup menu
inoremap <expr> j pumvisible() ? "\<C-N>" : "j"
inoremap <expr> k pumvisible() ? "\<C-P>" : "k"
source .vimcommonrc
And the common settings:
set hlsearch
set ignorecase
It's your choice.
I don't think you can detect Vrapper, but you can instead write a command that real Vim will process and Vrapper will ignore.
Example: mapping <KMinus>:
nnoremap <KMinus> q
If Vrapper runs that, it crashes. Let's make it ignore it. There are many ways:
if v:true
nnoremap <KMinus> q
endif
if v:true | nnoremap <KMinus> q | endif
exec 'nnoremap <KMinus> q'
There's also this more "aggressive" version, if the other ones don't work. It's useful for multiple commands:
if v:true |
\nmap <C-Bslash> gcc |
\vmap <C-Bslash> gc |
\imap <C-Bslash> <C-o><C-Bslash> |
\endif
You can even add a finish statement which Vim will treat as "I should stop reading this file" and Vrapper will probably ignore and keep executing the file, making it ideal to precede Vrapper-only commands:
if v:true
" Vim-only stuff
finish
endif
" Vrapper-only stuff
How do you think it would work?
Your ~/.vimrc is not a sentient being that can take decisions by itself: it needs to be sourced by a program that understands it and… that program is Vim.
Vrapper only supports a subset of Vim's vocabulary so it is not very reasonable to expect it to behave exactly like Vim. The main missing feature that would make possible the detection you are asking about is vimscript: since Vrapper doesn't support it you can't use an if-else-endif construction!
Because the two programs support vastly different sets of options and commands I'm afraid you will have to manage two separate files.
Did you try Vrapper's :source command?

Is there anyway to dynamically enable / disable the highlighting in Vim?

Ok so basically the way Vim highlights searches displeases me. Basically you do a search, then you have to type /asdf or have a shortcut like this in your vimrc:
nn <silent> <leader><space> :noh<CR>
Which is what I have. But it's still too much mental work. Basically, when I do a search, I want highlighting to enable (like it does now) but if I do anything other than cycle through the searches (with n/N) then I want highlighting to turn off. That's basically my workflow, so I'm wondering if I can automate it. Also if I search, do something other than n/N (which should turn highlighting off) and then press n/N again, it should re-enable.
Any ideas?
That's difficult. One idea is
:autocmd CursorHold * call feedkeys(":noh\<CR>")
(One needs to use feedkeys() because :nohlsearch is ineffective in functions and autocmds.) This clears the highlighting whenever you pause the cursor for some seconds. You can add other triggers like InsertEnter or CursorHoldI.
What does not work is CursorMoved, because the searches and n / N jump as well. You would need to overload those commands, store the cursor position after the jump, and modify the autocmd to only clear the highlighting when the position is different.
What I do: I have Enter mapped to :nohlsearch; it's quick and easy to reach.
you can turn it on or off with:
:set hls
or
:set nohls
I have F7 mapped to set hls!:
noremap <F7> :set hls!<CR>

Get Vim to open new blocks like Sublime Text 2

In sublime text 2 when you:
BLOCK { <Return>
It generates (where the pipe is the cursor):
BLOCK {
|
}
How can I get Vim to behave this way?
I have autoindent on, and smartindent off because with smartindent it does this on return:
BLOCK {
|}
To be more clear, I'm specifically looking for 2 returns, moving up a line, and tabbing in (2 soft tabs to be specific). I already have it auto-matching characters like {, (, [ etc.
A simple mapping will work for most purposes:
imap {<cr> {<cr>}<c-o>O
Depending on plugins, some users may need inoremap instead of imap.
Before it was with TextMate, now it's with ST2.
You have basically two paths before you.
The "dumb" path
One could come up with dozens of variations of this method: you simply create a mapping that executes the series of key presses needed to reach your goal:
inoremap {<CR> {<cr><cr>}<C-o>k<tab>
I called it "dumb" but it doesn't mean that you would be dumb to use it: it's low-tech, has no dependencies, is easy to customize and it can be mapped to anything you like.
The "smart" method
This method involves the use of a plugin. I use DelimitMate but there are many others, choose your poison.
I did some quick digging for vim addons (which are often the solution to this sort of problem). I don't think I've found what you want: there are a few addons that come close, but nothing that inserts the extra newline before the closing brace.
You could do something like
imap { {<return><return>}<up><tab>
but this will get awkward if you are working in a language that uses braces in other situations. You could instead react to the newline:
inoremap <return> <return><return>}<up><tab>
Of course this will trigger on EVERY entered newline, rather than just those following an opening brace. To get it to check that the brace is the last character of the current line, you can:
Have a function (in ~/.vimrc or somewhere in ~/.vim/plugin) that looks like
function! CloseBraceIfOpened()
if getline(".")[-1:] == '{'
" insert a space and then delete it to preserve autoindent level
exec "normal o "
normal x
normal o}
normal k
else
normal o
endif
endfunction
also do
inoremap <buffer> <enter> <esc>:call CloseBraceIfOpened()<enter>A
Note that this imap is buffer-specific, so that mapping will only apply to the buffer you are in when you run it. To have it apply to all buffers, remove <buffer>.
If you are really ambitious/particular, you can do tests in the function to see if the code in the current line really opens a block.
To get the indentation working the way you want it, turn on the 'autoindent' and 'smartindent' settings.
: set autoindent smartindent
To have it on by default, add
set autoindent smartindent
to ~/.vimrc.
I use the following map:
inoremap {{ {<CR><CR>}<ESC>kcc
so instead of using {<CR> I use this mapping. Besides that I also use the plugin mentioned by romainl, DelimitMate for other mappings with braces.
I had the same problem and delimitMate solves it. After installing it you can enable it with:
let g:delimitMate_expand_cr = 1
There are lot's of hacks that delivers the SublimeText experience. Because I got frustrated I've created a project that includes all those features in a single vim distribution (without the need of installing/compiling external plugins/tools).
You can check it out from here: https://github.com/fatih/subvim

How to prevent <Esc> from waiting for more input in Insert Mode

When I leave insert mode by pressing Esc, there is a half-second pause before Vim actually returns to normal mode.
Normally this wouldn't be an issue, since pressing a normal mode command like j after pressing Esc executes the normal-mode command immediately (without the above-mentioned wait), but I have the mapping inoremap <Esc> <Esc>:w<CR>, so that every time I leave insert mode the file is written. I would like the write to occur immediately when I press Esc, but instead there is that half-second pause.
I'm assuming that the pause is because Vim is waiting for more input before it decides that I just meant to type a single, simple Esc. This must be because there is a mapping somewhere who's first character is <Esc>, but I've looked in my .vimrc and there is no such mapping.
Furthermore, I even ran :map <Esc>, and it returned No such mapping. So, if there is no such mapping, why does Vim appear to be waiting for more input, and how can I avoid that behavior?
Extra Information
It appears that this is not reproduceable, so here is some more information in case anyone really wants to get to the bottom of this:
I am using Steve Francia's spf13 distribution of Vim, with my own .vimrc.local on top of it. I have also installed several additional plugins using Vundle.
Notes: .vimrc.local is sourced last in .vimrc.
UPDATE (3/19/2014)
I found a far better solution than trying to hunt down all the mappings that start with <Esc>, courtesy of Powerline, from the Tips & Tricks section of the docs. Put this somewhere in your .vimrc:
" leave insert mode quickly
if ! has('gui_running')
set ttimeoutlen=10
augroup FastEscape
autocmd!
au InsertEnter * set timeoutlen=0
au InsertLeave * set timeoutlen=1000
augroup END
endif
Note that this will make it impossible to use mappings that start with <Esc> while in insert mode, but there shouldn't be any of those anyway, because of the problem this solves.
I found the lines in spf13's .vimrc that were causing the problem:
" Fix home and end keybindings for screen, particularly on mac
" - for some reason this fixes the arrow keys too. huh.
map ^[F $
imap ^[F $
map ^[H g0
imap ^[H g0
The reason I couldn't find them before is because they weren't mapped using <Esc>, but ^[ instead. Very irritating! Hope this helps some equally disgruntled spf13 user :)
UPDATE:
If removing those mappings doesn't work, then it's probably a mapping from a plugin.
Type :verbose map <Esc> to get a list of all mappings involving Esc. The verbose part instructs Vim to print where the mapping was set. That should help find out what's causing the problem.
Also, the command unmap <Esc> might be useful—it removes any mappings for the Esc key.
Note that unmap does not remove mappings in all modes; type :h unmap for more info.
In my case, it was tmux injecting that delay (this came as a complete surprise for me!).
I fixed it by adding set -g escape-time 0 to my tmux.conf.
This may not strictly help the author, but this question comes up first when searching for this issue with many different keyword combinations, so I hope it helps someone.
Source: first comment from here.
I'm not exactly sure what the problem is with the mapping you describe, in my opinion it should be fine. However, I think that what you want to accomplish can be reached in a better way. Your mapping is basically an attempt at creating a InsertLeave event, which Vim actually already has built in!
Try adding something like this to your .vimrc:
au InsertLeave * if &mod && expand('%')!=''|write|endif
As an added bonus, this one only saves your buffer if it has a filename and was actually modified.
set timeoutlen=1000 ttimeoutlen=0
timeoutlen - mapping delays.
ttimeoutlen - key code delays.
Source

Vim: Resolve ambiguity of key mappings in a specific buffer to avoid timeout

I use plugin "Buffet", and there's local-to-buffer mapping "d" to delete buffer under cursor.
I also use plugun Surround, and there's global mapping "ds" that means "delete surround".
So, when i press "d" in the Buffet's window, Vim waits for a second before execute mapping "d". I know about &timeoutlen, but i don't want to change it. So that I want to resolve ambiguity of key mappings for "d" in the Buffet's window to avoid timeout to delete a buffer.
To resolve the problem, I want to unmap in Buffet window all the mappings that start with "d", but except Buffet's own mappings. How can i do that?
P.S. I have read about maparg() and mapcheck(), but they seem not to be what i need, unfortunately.
It seems like i found the solution myself:
au BufEnter buflisttempbuffer* nunmap ds
au BufLeave buflisttempbuffer* nmap ds <Plug>Dsurround
I hoped that there's more universal approach (to remove really all mappings starting from "d"), but at this moment i failed to find it.
Even if i found out how to get all these mappings, unfortunately i can't do unmap <buffer> ds, because ds is a global mapping. I'm sure that i should be able to disable global mapping for some buffer, though. Vim is great but not perfect.
Well, it works for me now.
Now that the question has been "rephrased", this solution is no longer relevant, but I'll post it anyway since I spent a few minutes on it.
Here's a function that grabs the output of map <letter> and extracts the individual maps. Then it unmaps them all.
function! Unmap(leader)
redir => maps
sil exe "map " . a:leader
redir END
let maps_list = split(strtrans(maps),'\^#')
if len(maps_list) > 1
for this in maps_list
let mapn = matchstr(this,"^\\w\\s*\\zsd\\w*\\>")
exe "unmap " . mapn
endfor
endif
endfunction
Example usage: call Unmap("d"). This will remove all mappings that begin with d, leaving only Vim's defaults.
Disclaimer: this has not been rigorously tested. In particular I don't know how portable the \^# character is, but that's how it looks on my (Win32) machine.
The easiest way to do it is:
:e /WHERE/YOU/HAD/INSTALLED/buffet.vim
:%s:map <buffer> <silent> d:"&:
:wq
$ vim # Restart Vim to take effect...
Generally you can't unmap based on a pattern.
If you want to use another key (e.g. with <leader>, just change this line in the plugin:
map <buffer> <silent> d :call <sid>deletebuffer(0)<cr>
This question is rather old, but if you're still interested, you might want to give Bufstop a try.
This issue is handled by the plugin, you can press the d key to delete a buffer, and you won't get any timeout if you installed other plugins which have global mappings.
A cheap trick that worked for me was to make the timeoutlen so short it becomes pretty much instantaneous. As long as you don't use multiple key mappings yourself, that will cover all plugins in one shot.
We don't want that setting to stay however, so we remove it every time we leave the buffer.
Add this so that it runs inside your custom buffer:
augroup no_map_chords
autocmd!
autocmd BufEnter <buffer> let g:bak_timeoutlen = &timeoutlen | set timeoutlen=1
autocmd BufLeave <buffer> let &timeoutlen = g:bak_timeoutlen | unlet g:bak_timeoutlen
augroup END
A similar technique could be used for a specific file type, or other such "global" settings.
Buffet is a very young plugin, I don't think it's used by as many people as Command-T or NERDTree so you may not receive lots of answers. Its author has been very responsive on the numerous threads he created there about it you should contact him directly or create an issue on Buffet's github.

Resources