VIM syntax highlighting of text files - vim

Vim used to syntax highlight plain text files(*.txt) as conf files if the first character of the file was a #. But after I updated to 8.0.3, this feature has disappeared.
Is there a way to fix this other than the solution mentioned here? i.e without modifying the file.

function SetConfType()
if !empty(matchstr(getline('1'), '^#\s.*'))
set filetype=conf
endif
endfunction
autocmd BufEnter *.txt call SetConfType()
Update:
This oneliner does not require a function. It is a little bit more elegant.
au BufRead * if getline(1) =~ '^#\s.*' | setlocal ft=javascript.flow | endif

Related

Using a file type plugin file (ftplugin) to change the file type in vim / neovim

To automate a step for creating multimarkdown notes. I'd like for neovim to change the filetype of a file based on the contents of first line. All of my multimarkdown notes begin with title E.g.
title: Euclidean Distance
Ideally i'd like to keep this out of my init.vim (.vimrc) file, however neovim does not update the buffer upon read/open when I place the following in my ../ftplugin/txt.vim file.
" Change the file type to markdown
if getline(1) =~ '^title:'
set ft=markdown
endif
How can I get neovim to check the first line of the file and change its type or at least change its syntax. Thx.
I understand that the runtime doesn't watch all the files. Is the only way to automatically check the file type and make changes is by using autocmd and source the ftplugin/txt.vim file via init.vim (.vimrc)
This blows into the same horn as #PeterRincker's answer, but I think you should follow :help new-filetype-scripts, as the description (if your filetype can only be detected by inspecting the contents of the file) matches your use case perfectly.
With that, you put the following contents into ~/.vim/scripts.vim:
if did_filetype() " filetype already set..
finish " ..don't do these checks
endif
if getline(1) =~ '^title:'
setfiletype markdown
endif
According to :h new-filetype part B you can do something like the following:
augroup txt_to_markdown
autocmd!
autocmd BufRead * if &filetype == 'text && getline(1) =~ '^title:' | set filetype=markdown | endif
augroup END

Vim colorscheme not loading when using autocommand BufNewFile

When trying to automatically open the corresponding .cpp or .h file using autocommand I encounter no colorscheme on the corresponding file that is opened.
I'm not too familiar with vimscript but I believe Vim is opening the file thinking it is of file type ".txt" and therefore using a default colorscheme.
Two autocommand lines in ~/.vimrc:
au BufRead,BufNewFile *.cpp exe "bel vsplit" fnameescape(expand("%:r").".h")
au BufRead,BufNewFile *.h exe "vsplit" fnameescape(expand("%:r").".cpp")
Any help would be appreciated.
Your answer is a workaround (though you should use :setlocal instead of :set to avoid that the syntax leaks out to new buffers that are opened from that one), but it doesn't attack the root cause, which you'll find explained at :help autocmd-nested:
By default, autocommands do not nest. If you use ":e" or ":w" in an autocommand, Vim does not execute the BufRead and BufWrite autocommands for those commands. If you do want this, use the "nested" flag for those commands in which you want nesting.
Syntax highlighting (you say colorscheme in your title, but that's actually just the color and font attributes that are then used by syntax highlighting) is based on :autocmd events (same goes for filetype plugins, so any C++-related settings you also wouldn't find in the split file, assuming you have :filetype plugin on in your ~/.vimrc). Without the nested attribute, the split file will be opened, but none of the usual actions will be run on them. Though nesting in general can be problematic, this is one of those cases where it is needed.
au BufRead,BufNewFile *.cpp nested exe "bel vsplit" fnameescape(expand("%:r").".h")
au BufRead,BufNewFile *.h nested exe "vsplit" fnameescape(expand("%:r").".cpp")
Unfortunately, this introduces another problem: The one autocmd will trigger the other one, and vice versa (up to a limit). You need to guard the actions so that a split is only done if the file isn't open yet. (This also improves on the usability in a general way, when you open a file with the other already open.) :help bufwinnr() checks whether the target buffer is already visible in a window:
au BufRead,BufNewFile *.cpp nested if bufwinnr("^" . expand("%:r").".h$") == -1 | exe "bel vsplit" fnameescape(expand("%:r").".h") | endif
au BufRead,BufNewFile *.h nested if bufwinnr("^" . expand("%:r").".cpp$") == -1 | exe "vsplit" fnameescape(expand("%:r").".cpp") | endif
If anyone cares to look at this in the future the solution was that Vim was loading the second file as syntax=none. So adding | set syntax=cpp at the end of each auto command fixed it.

How to negate an autocmd pattern [duplicate]

I have a Vim autocmd that removes trailing whitespace in files before write. I want this almost 100% of the time, but there are a few filetypes that I'd like it disabled. Conventional wisdom is to list the filetypes you want an autocmd to run against in a comma-separated list, eg:
autocmd BufWritePre *.rb, *.js, *.pl
But in this case that would be onerous.
Is there a way to match an autocmd pattern against all files EXCEPT those matching the pattern? I cannot find the equivalent to a NOT matcher in the docs.
*.rb isn't a filetype. It's a file pattern. ruby is the filetype and could even be set on files that don't have a .rb extension. So, what you most likely want is a function that your autocmd calls to both check for filetypes which shouldn't be acted on and strips the whitespace.
fun! StripTrailingWhitespace()
" Don't strip on these filetypes
if &ft =~ 'ruby\|javascript\|perl'
return
endif
%s/\s\+$//e
endfun
autocmd BufWritePre * call StripTrailingWhitespace()
Building on evan's answer, you could check for a buffer-local variable and determine whether to do the strip using that. This would also allow you to do one-off disabling if you decided that you don't want to strip a buffer that's a filetype you normally would strip.
fun! StripTrailingWhitespace()
" Only strip if the b:noStripeWhitespace variable isn't set
if exists('b:noStripWhitespace')
return
endif
%s/\s\+$//e
endfun
autocmd BufWritePre * call StripTrailingWhitespace()
autocmd FileType ruby,javascript,perl let b:noStripWhitespace=1
Another choice of one line way:
let blacklist = ['rb', 'js', 'pl']
autocmd BufWritePre * if index(blacklist, &ft) < 0 | do somthing you like | endif
Then you can do something you like for all filetypes except those in blacklist.
A good way would be to set a local variable for the one filetype to true. Then set the automcommand if that variable is false (if set for everything else) or if it exists at all (no need to preset it).
autocmd BufWritePre *.foo let b:foo=true
if !exists("b:foo")
autocmd ...
endif
changed variable prefixes based on comment
You can do the except on the same regexp:
autocmd BufWritePre *\(.out\|.diffs\)\#<! <your_command>
That will do <your_command> for all files extensions except for .out or .diffs.
This works for Syntax autocommands, where the pattern (<match>) is just the filetype. It excludes any rst files:
au Syntax *\(^rst\)\#<! …
Our .vimrc config file runs only once on startup. So if you put an if test at this time, it won't work, because no python file is then currently being edited.
But you can use .vimrc to set up an automatic behaviour: something that vim will do each time it encounters a special condition. The condition can be in your case: "A new file is being editing, and its file type is 'python'". See :h :au

Syntax highlighting not looking at shebang line on known filetypes

I have a Perl file with an atypical naming convention (e.g. file = test.cfg) and *.cfg is a known file extension for an existing filetype in my vim install. Is there a vimrc setting that will tell vim to use the shebang value, regardless of the file extension? I know I can put # vim: set filetype=perl : in the file itself as an alternate solution. I want vim to look # the shebang value first, then the file extension.
#!/usr/bin/perl
my $var = "please highlight me";
Usually, the static file pattern comparison (in filetype.vim) is run before the detection based on contents (in scripts.vim), but since it's all Vimscript, nothing prevents you from messing with that order.
If this is just about the .cfg extension and Perl scripts, put the following into ~/.vim/filetype.vim:
if exists('did_load_filetypes')
finish
endif
augroup filetypedetect
autocmd BufNewFile,BufRead *.cfg if getline(1) =~# '^#!/usr/bin/perl\>' | setf perl | endif
augroup END

Vim remove whitespace for specific files

I've been using the following technique in my .vimrc to remove extra whitespace at the end of a line...
autocmd BufWritePre * :%s/\s\+$//e
But I realised I didn't want that to happen with Markdown files (e.g. either .md or .markdown) so I have the following VimScript...
fun! StripTrailingWhiteSpace()
" don't strip on these filetypes
if &ft =~ 'md\|markdown'
return
endif
%s/\s\+$//e
endfun
autocmd bufwritepre * :call StripTrailingWhiteSpace()
But that still removes the whitespace for all files.
So I then tried the following (which seemed better as it was shorter)...
let blacklist = ['md', 'markdown']
autocmd BufWritePre * if index(blacklist, &ft) < 0 | :%s/\s\+$//e
But, again, that still removes the whitespace for all files?
Neither of these techniques seem to work? They leave the whitespace still in the file?
Any ideas on how I can do this (at the moment I'm having to edit Markdown files in a separate writing app rather than Vim and that's quite annoying).
The first function should work except you should not be looking for md. ft is short for filetype which is markdown for Markdown files.
By changing it as follows it works fine. (Tested on Vim 7.4)
fun! StripTrailingWhiteSpace()
" don't strip on these filetypes
if &ft =~ 'markdown'
return
endif
%s/\s\+$//e
endfun
autocmd bufwritepre * :call StripTrailingWhiteSpace()
Thanks Kevin Sjoberg for the initial response, but it turns out I have a bigger issue.
Which is if I run :set filetype? from within my Markdown file then it reports back that Vim thinks the filetype is modula2
I'm not sure how I can fix this, so if any one knows then please do comment!
As a temp fix I've used the following work around...
fun! StripTrailingWhitespace()
" don't strip on these filetypes
if &ft =~ 'modula2\|markdown'
return
endif
%s/\s\+$//e
endfun
autocmd BufWritePre * call StripTrailingWhitespace()
...so it checks for both modula2 (whatever that is?) AND markdown files.
UPDATE: well it seems this is a known issue https://github.com/tpope/vim-markdown/issues/15 so I tried the suggested fix...
au BufRead,BufNewFile *.md set syntax=markdown
...but that didn't help, Vim still interpreted the file as modular2
Also tried adding the following into my vimrc file...
au! BufNewFile,BufRead *.md setf markdown
...but that didn't work to change the format.
UPDATE 2
Fixed it, the suggestion by both https://github.com/tpope/vim-markdown/issues/15 and Kevin Sjoberg were almost there.
I just added into my vimrc file a modified version of their suggestion au Bufread,BufNewFile *.md set filetype=markdown
Your implementation is simple, but has some shortcomings (e.g. it clobbers the last search pattern / search history). If you're not against installing a plugin, you can try my DeleteTrailingWhitespace plugin. With it, you can exclude certain buffers by setting a flag, e.g.:
autocmd FileType markdown let b:DeleteTrailingWhitespace = 0
I realize you solved the problem which was more than just the function you were trying to setup.
However, I liked your initial "blacklist" approach with a filetypes list. So for anyone else landing here that likes that, this is what I have.
It also saves your cursor position, and puts it back after running the removal of whitespace.
function! StripTrailingWhitespace()
" Preparation: save last search, and cursor position.
let _s=#/
let l = line(".")
let c = col(".")
" do the business:
%s/\s\+$//e
" clean up: restore previous search history, and cursor position
let #/=_s
call cursor(l, c)
endfunction
let noStripWhiteSpaceTypes = ['markdown']
autocmd BufWritePre * if index(noStripWhiteSpaceTypes, &ft) < 0 | call StripTrailingWhitespace() | endif

Categories

Resources