I my ~/.vimrc I use this syn for long lines
augroup longLines
au!
au! filetype zsh,sh,python,vim,c,cpp
\ syn match ColorColumn /\%>80v.\+/ containedin=ALL
augroup END
but this overwrite other syn, with
without
Why the synoverwrite other highlight?
this is notorious in the last lines
sys.exit(1)
import settings
have different colors, with syn, the lines lost normal highlight
I use the following code:
highlight TooLongLine term=reverse ctermfg=Yellow ctermbg=Red
autocmd BufEnter,WinEnter * if &tw && !exists('b:DO_NOT_2MATCH') |
\ execute '2match TooLongLine /\S\%>'.(&tw+1).'v/' |
\ endif
autocmd BufLeave,WinLeave * 2match
command -nargs=0 -bar Dm let b:DO_NOT_2MATCH=1 | 2match
command -nargs=0 -bar Sm execute '2match TooLongLine /\S\%>'.(&tw+1).'v/' |
\ silent! unlet b:DO_NOT_2MATCH
If you don’t want to be able to remove this highlighting, depend on textwidth and insist on highlighting spaces that go beyond the limit, then you can truncate this to just
2match TooLongLine /.\%>80v/
This solution uses match-highlight that does not scrap syntax highlighting, but always overrides it.
I realize you asked this quite some time ago, but in case if other people ask too, perhaps you could try using the matchadd() function, instead, like this:
hi def longLine gui=reverse "or guibg=pink, or whatever you prefer
augroup longLines
au!
au! filetype zsh,sh,python,vim,c,cpp
\ call matchadd("longLine", "\\%>80v", 0, 9999)
augroup END
Most importantly, make sure that you do NOT set the guifg of whatever highlight group you decide to use. That would overwrite your syntax highlighting.
Another important part (for me, at least) is to use matchadd with 0 as the third parameter so that your Search highlighting remains effective and doesn't get overtaken by the longLine highlighting.
The fourth parameter can be omitted. It's just a constant so that you can :call matchdelete(9999) to easily remove the highlighting again later, if you want.
See :h matchadd and :h matchdelete
Related
in my vimrc I have a script that transform a text in bold when banded between * * double stars * * (like it does in this editor actually), but i don't want it to apply on my js or c or any programming files of course, so i tried to make it run only when it's a .txt file :
if (&filetype=='text')
set concealcursor=n
set conceallevel=3
hi AsteriskBold ctermfg=Green cterm=bold
autocmd BufEnter * syn match Asterisks contained "**" conceal
autocmd BufEnter * syn match AsteriskBold "\*\*.*\*\*" contains=Asterisks
endif
but obviously the condition of the "if" doesn't work since this rules doesn't apply anymore in none of my file, text or not
EDIT => SOLUTION
after reading the answers I choose this solution, in my vimrc (even though it's not the best way vim works as explaind by ingo)
au BufEnter *.txt setf text "(set a filetype unless it already exist)
au filetype text set cocu=n cole=3
au filetype text hi AsteriskBold ctermfg=Green cterm=bold
au filetype text syn match Asterisks contained "**" conceal
au filetype text syn match AsteriskBold "\*\*.*\*\*" contains=Asterisks
Filetypes
Filetype-specific settings go into ~/.vim/after/ftplugin/text.vim. (This requires that you have :filetype plugin on; use of the after directory allows you to override any default filetype settings done by $VIMRUNTIME/ftplugin/text.vim.) Alternatively, you could define an :autocmd FileType text ... directly in your ~/.vimrc, but this tends to become unwieldy once you have many customizations.
Syntaxes
For :syntax commands, there's a corresponding directory ~/.vim/after/syntax/text.vim. (Vim currently doesn't ship with a dedicated text syntax; you could drop the after part, and make your syntax the main one.)
By syntax script convention, your syntax groups should be prefixed with the filetype; e.g. textAsterisks. The :hi group has to be renamed as well; however, usually syntax scripts use :hi def link to link the syntax group to a (more generic) highlight group: hi def link textAsteriskBold AsteriskBold. More information at the end of usr_44.txt.
Highlight groups
These are global, you can put your :hi command(s) directly into your ~/.vimrc and define it just once.
Conceal
The conceal settings are window-local, but filetypes and syntaxes apply to buffers. And by using :set (instead of :setlocal), those settings will be inherited by any new window opened from the one that shows a text file. Depending on your workflow (and whether other filetypes you edit use concealing at all), you may never notice this, and there's no good workaround (only a huge mess of :autocmd could try to adapt those). Just be aware of this.
You're looking for an augroup.
See :help augroup and :help filetype.
For instance:
augroup asteriskbold
au!
au BufNewFile,BufRead *.txt,*.md,*.mkd,*.markdown,*.mdwn set concealcursor=n conceallevel=3
au BufNewFile,BufRead *.txt,*.md,*.mkd,*.markdown,*.mdwn hi AsteriskBold ctermfg=Green cterm=bold
au BufNewFile,BufRead *.txt,*.md,*.mkd,*.markdown,*.mdwn syn match Asterisks contained "**" conceal
au BufNewFile,BufRead *.txt,*.md,*.mkd,*.markdown,*.mdwn syn match AsteriskBold "\*\*.*\*\*" contains=Asterisks
augroup end
I have the following code inside my vimrc
hi CurrentWordUL cterm=underline gui=underline
hi Search cterm=underline ctermfg=124 gui=underline guifg=#af0000
augroup MyHighlighter
autocmd!
" autocmd User IncSearchEnter MatchHighlighter 0
" autocmd User IncSearchExecute MatchHighlighter 1
set updatetime=700
autocmd CursorHold * if (get(g:, 'matchhl', 1) && (&ft !~ join(g:ft_blacklist, '\|')))
\ | silent! exe printf('match CurrentWordUL /\<%s\>/', expand('<cword>'))
\ | endif
autocmd CursorMoved * if (get(g:, 'matchhl', 1) && (&ft !~ join(g:ft_blacklist, '\|')))
\ | silent! exe printf('match none')
\ | endif
augroup END
nnoremap <silent> <f4> :MatchHighlighter<CR>
command! -nargs=? MatchHighlighter
\ call ToggleSetMatchHL(
\ empty(<q-args>) ? !get(g:, 'matchhl', 1) : expand(<q-args>))
function! ToggleSetMatchHL(arg) abort
match none | diffupdate | syntax sync fromstart
let g:matchhl = a:arg
endfunction
The purpose of this is to highlight (underline) matching word under the cursor.
The issue I have is when I'm searching with /, ?, *, # etc. The matching highlight overwrite the search highlight.
Is there anyway I can know "end of search" (I don't know the definition of "end of search" but maybe someone can suggest something) or "nohlsearch" was called?
Thanks in advance.
If you switch from :match to :call matchadd(...), you can specify a {priority}. A negative one will put the highlighting below the search highlighting (which has prio 0; default is 10).
There's no event for "end of search". You could override all search-related commands (/, ?, *, etc); that would detect a start of search. For / and ?, you could define a cmap <CR> with a check of getcmdtype() =~# '[/?]' to detect the conclusion of a search. I wouldn't recommend this approach; the mappings may interfere with other plugins.
Instead of using :match (which is window-local, so the highlighting also behaves differently than the built-in search highlighting), you could automatically adapt the current search pattern (register /) instead. My SearchHighlighting plugin chooses this approach with its :SearchAutoHighlighting command. (The plugin page has links to many alternative plugins you may want to check out; I would prefer a well-maintained plugin over a custom code snippet in my ~/.vimrc.)
I'm trying to write a snippet of VimL to allow the user to toggle the hilighting of unwanted trailing whitespace with a hotkey. (This is my first-ever Vim script, beyond copy-pasting things into my .vimrc, so … grain of salt :P)
I wish for the ‘are we currently hilighting trailing whitespace?’ to be buffer-specific state; but I'm having a lot of trouble figuring out how autocommands interact with buffers.
For instance, here's my first stab at an augroup of buffer-local autocmds:
augroup ExtraWhitespace
au!
au BufEnter <buffer=abuf> match ExtraWhitespace /\s\+$/
au InsertEnter <buffer=abuf> match ExtraWhitespace /\s\+\%#\#<!$/
au InsertLeave <buffer=abuf> match ExtraWhiteSpace /\s\+$/
augroup END
… unfortunately, this immediately trips up when invoked:
Error detected while processing function ToggleExtraWhitespace:
line 19:
E680: <buffer=0>: invalid buffer number
line 20:
E680: <buffer=0>: invalid buffer number
line 21:
E680: <buffer=0>: invalid buffer number
No matching autocommands
I don't understand why <abuf> is 0, when bufnr('%') is 1, or how to get the autocommands to execute for buffer 1 instead. (Of course 0 is invalid!)
For the moment, I've swapped out <buffer=abuf> for *; but this screws up the functionality of this function when there are multiple buffers loaded, and That Is Bad. So, any help figuring this out is welcome. /=
First, I don't know how <buffer=abuf> works. The documentation for it seems to be conflicting. It appears the the behavior for <buffer=abuf> was changed/fixed with patch 7.4.637, before It was causing problems even if used correctly. <buffer=abuf> must only be used when an autocmd is running. So your function would probably have worked if you called it in VimEnter or BufAdd.
The following a modified version of what you attempted which doesn't use <buffer=abuf>
augroup ExtraWhitespace
autocmd! * <buffer>
autocmd BufEnter <buffer> match ExtraWhitespace /\s\+$/
autocmd InsertEnter <buffer> match ExtraWhitespace /\s\+\%#\#<!$/
autocmd InsertLeave <buffer> match ExtraWhitespace /\s\+$/
augroup END
The first things you should notice is that au! has been replaced with autocmd! * <buffer>. au! shouldn't be there since this will remove all autocmd in the ExtraWhitespace group from all buffers. This means that you can only define it in one buffer. (autocmd! * <buffer> only deletes the autocmds in the current buffer)
The second thing you should notice is that <buffer> is used. This means that the autocmd will be created only for the current buffer when when the function is called. Buffer local autocmd must be called for each buffer that you want to define.
Other miscellaneous comments
You have
fun! HighlightExtraWhitespace()
if exists('b:ews') && b:ews == 1
"echom "-- Adding ExtraWhitespace hilighting"
highlight ExtraWhitespace ctermbg=red guibg=red
else
"echom "-- Removing ExtraWhitespace hilighting"
highlight clear ExtraWhitespace
endif
endfun
au ColorScheme * call HighlightExtraWhitespace()
Highlighting is global, so clearing it in one buffer is going to remove the highlight group everywhere. So its better to just leave the highlighting in place and redefine it every time the colorscheme changes.
autocmd ColorScheme * highlight ExtraWhitespace ctermbg=red guibg=red
It is recommended to use the long form of command names in scripts. (Short form used only for typing). The long form is more readable and easily identifiable, so au would be come autocmd.
I am using these lines in my .vimrc file, to highlight leading whitespace (which includes spaces):
highlight ExtraWhitespace ctermbg=darkgreen guibg=darkcyan
autocmd BufWinEnter * match ExtraWhitespace /^\s* \s*\|\s\+$
So, this works fine in most cases. Except in help buffers, where it highlights a lot of indentation from the help files. I find this annoying, so I tried this as a workaround:
autocmd FileType help highlight clear ExtraWhitespace
But unfortunately, as soon as a help buffer is opened, it seems that the highlighting in all my buffers disappears.
Any ideas on how to improve this?
This seems to be working:
highlight ExtraWhitespace ctermbg=darkgreen guibg=darkcyan
autocmd BufEnter * if &ft != 'help' | match ExtraWhitespace /\s\+$/ | endif
autocmd BufEnter * if &ft == 'help' | match none /\s\+$/ | endif
[edit] The above code works for trailing spaces since my Vim couldn't understand your pattern. So just :%s/ubstitute the pattern to fit your needs.
If you only need the whitespace errors for C/C++ files you can always use:
let c_space_errors=1
There are other languages that have similar support.
Worst case, if you need it for other types of files, you could always switch your file type to C and fix your errors then.
Change the autocommand disabling custom highlighting in help buffers
as follows:
:autocmd FileType help match none
I am getting 'trailing whitespace' errors trying to commit some files in Git.
I want to remove these trailing whitespace characters automatically right before I save Python files.
Can you configure Vim to do this? If so, how?
I found the answer here.
Adding the following to my .vimrc file did the trick:
autocmd BufWritePre *.py :%s/\s\+$//e
The e flag at the end means that the command doesn't issue an error message if the search pattern fails. See :h :s_flags for more.
Compilation of above plus saving cursor position:
function! <SID>StripTrailingWhitespaces()
if !&binary && &filetype != 'diff'
let l:save = winsaveview()
keeppatterns %s/\s\+$//e
call winrestview(l:save)
endif
endfun
autocmd FileType c,cpp,java,php,ruby,python autocmd BufWritePre <buffer> :call <SID>StripTrailingWhitespaces()
If you want to apply this on save to any file, leave out the second autocmd and use a wildcard *:
autocmd BufWritePre,FileWritePre,FileAppendPre,FilterWritePre *
\ :call <SID>StripTrailingWhitespaces()
I also usually have a :
match Todo /\s\+$/
in my .vimrc file, so that end of line whitespace are hilighted.
Todo being a syntax hilighting group-name that is used for hilighting keywords like TODO, FIXME or XXX. It has an annoyingly ugly yellowish background color, and I find it's the best to hilight things you don't want in your code :-)
I both highlight existing trailing whitespace and also strip trailing whitespace.
I configure my editor (vim) to show white space at the end, e.g.
with this at the bottom of my .vimrc:
highlight ExtraWhitespace ctermbg=red guibg=red
match ExtraWhitespace /\s\+$/
autocmd BufWinEnter * match ExtraWhitespace /\s\+$/
autocmd InsertEnter * match ExtraWhitespace /\s\+\%#\#<!$/
autocmd InsertLeave * match ExtraWhitespace /\s\+$/
autocmd BufWinLeave * call clearmatches()
and I 'auto-strip' it from files when saving them, in my case *.rb for ruby files, again in my ~/.vimrc
function! TrimWhiteSpace()
%s/\s\+$//e
endfunction
autocmd BufWritePre *.rb :call TrimWhiteSpace()
Here's a way to filter by more than one FileType.
autocmd FileType c,cpp,python,ruby,java autocmd BufWritePre <buffer> :%s/\s\+$//e
I saw this solution in a comment at
VIM Wikia - Remove unwanted spaces
I really liked it. Adds a . on the unwanted white spaces.
Put this in your .vimrc
" Removes trailing spaces
function TrimWhiteSpace()
%s/\s*$//
''
endfunction
set list listchars=trail:.,extends:>
autocmd FileWritePre * call TrimWhiteSpace()
autocmd FileAppendPre * call TrimWhiteSpace()
autocmd FilterWritePre * call TrimWhiteSpace()
autocmd BufWritePre * call TrimWhiteSpace()
Copied and pasted from http://blog.kamil.dworakowski.name/2009/09/unobtrusive-highlighting-of-trailing.html (the link no longer works, but the bit you need is below)
"This has the advantage of not highlighting each space you type at the end of the line, only when you open a file or leave insert mode. Very neat."
highlight ExtraWhitespace ctermbg=red guibg=red
au ColorScheme * highlight ExtraWhitespace guibg=red
au BufEnter * match ExtraWhitespace /\s\+$/
au InsertEnter * match ExtraWhitespace /\s\+\%#\#<!$/
au InsertLeave * match ExtraWhiteSpace /\s\+$/
This is how I'm doing it. I can't remember where I stole it from tbh.
autocmd BufWritePre * :call <SID>StripWhite()
fun! <SID>StripWhite()
%s/[ \t]\+$//ge
%s!^\( \+\)\t!\=StrRepeat("\t", 1 + strlen(submatch(1)) / 8)!ge
endfun
A solution which simply strips trailing whitespace from the file is not acceptable in all circumstances. It will work in a project which has had this policy from the start, and so there are no such whitespace that you did not just add yourself in your upcoming commit.
Suppose you wish merely not to add new instances of trailing whitespace, without affecting existing whitespace in lines that you didn't edit, in order to keep your commit free of changes which are irrelevant to your work.
In that case, with git, you can can use a script like this:
#!/bin/sh
set -e # bail on errors
git stash save commit-cleanup
git stash show -p | sed '/^\+/s/ *$//' | git apply
git stash drop
That is to say, we stash the changes, and then filter all the + lines in the diff to remove their trailing whitespace as we re-apply the change to the working directory. If this command pipe is successful, we drop the stash.
The other approaches here somehow didn't work for me in MacVim when used in the .vimrc file. So here's one that does and highlights trailing spaces:
set encoding=utf-8
set listchars=trail:·
set list
For people who want to run it for specific file types (FileTypes are not always reliable):
autocmd BufWritePre *.c,*.cpp,*.cc,*.h,*.hpp,*.py,*.m,*.mm :%s/\s\+$//e
Or with vim7:
autocmd BufWritePre *.{c,cpp,cc,h,hpp,py,m,mm} :%s/\s\+$//e
If you trim whitespace, you should only do it on files that are already clean. "When in Rome...". This is good etiquette when working on codebases where spurious changes are unwelcome.
This function detects trailing whitespace and turns on trimming only if it was already clean.
The credit for this idea goes to a gem of a comment here: https://github.com/atom/whitespace/issues/10 (longest bug ticket comment stream ever)
autocmd BufNewFile,BufRead *.test call KarlDetectWhitespace()
fun! KarlDetectWhitespace()
python << endpython
import vim
nr_unclean = 0
for line in vim.current.buffer:
if line.rstrip() != line:
nr_unclean += 1
print "Unclean Lines: %d" % nr_unclean
print "Name: %s" % vim.current.buffer.name
cmd = "autocmd BufWritePre <buffer> call KarlStripTrailingWhitespace()"
if nr_unclean == 0:
print "Enabling Whitespace Trimming on Save"
vim.command(cmd)
else:
print "Whitespace Trimming Disabled"
endpython
endfun
fun! KarlStripTrailingWhitespace()
let l = line(".")
let c = col(".")
%s/\s\+$//e
call cursor(l, c)
endfun
autocmd BufWritePre *.py execute 'norm m`' | %s/\s\+$//e | norm g``
This will keep the cursor in the same position as it was just before saving
autocmd BufWritePre * :%s/\s\+$//<CR>:let #/=''<CR>