Vim Tips Wiki
mNo edit summary
No edit summary
Line 83: Line 83:
   
 
==Comments==
 
==Comments==
  +
  +
Is this also possible for indentation? Lets say C inside of an XML file?

Revision as of 12:09, 13 April 2010

Tip 857 Printable Monobook Previous Next

created January 21, 2005 · complexity advanced · author Ivan Tishchenko · version 6.0


In many cases, you may want to apply different syntax highlighting from the rest of the file on specific sections of the file. Examples where this would be useful would be including C code snippets in a text file, or including Vim script inside <pre> sections on a web page or wiki entry. Vim allows you to do this! Try the following, in a new text file:

:syntax on
:syntax include @CPP syntax/cpp.vim
:syntax region cppSnip matchgroup=Snip start="@begin=cpp@" end="@end=cpp@" contains=@CPP
:hi link Snip SpecialComment

Now type in the following text:

This is simple text, and following is C++:
@begin=cpp@
  int q;
  struct w { double e };
@end=cpp@

Now you have text between @begin=cpp@ and @end=cpp@ highlighted as C++, though filetype is not 'cpp'.

Here is a more useful version, which should work on any file, even those with a pre-existing syntax (i.e. not just text files):

function! TextEnableCodeSnip(filetype,start,end,textSnipHl) abort
  let ft=toupper(a:filetype)
  let group='textGroup'.ft
  if exists('b:current_syntax')
    let s:current_syntax=b:current_syntax
    " Remove current syntax definition, as some syntax files (e.g. cpp.vim)
    " do nothing if b:current_syntax is defined.
    unlet b:current_syntax
  endif
  execute 'syntax include @'.group.' syntax/'.a:filetype.'.vim'
  try
    execute 'syntax include @'.group.' after/syntax/'.a:filetype.'.vim'
  catch
  endtry
  if exists('s:current_syntax')
    let b:current_syntax=s:current_syntax
  else
    unlet b:current_syntax
  endif
  execute 'syntax region textSnip'.ft.'
  \ matchgroup='.a:textSnipHl.'
  \ start="'.a:start.'" end="'.a:end.'"
  \ contains=@'.group
endfunction

Now we can write something like:

call TextEnableCodeSnip(  'c',   '@begin=c@',   '@end=c@', 'SpecialComment')
call TextEnableCodeSnip('cpp', '@begin=cpp@', '@end=cpp@', 'SpecialComment')
call TextEnableCodeSnip('sql', '@begin=sql@', '@end=sql@', 'SpecialComment')

to enable highlighting of code pieces for c, cpp and sql. The begin and end markers are arbitrary; you can use whatever you want. For example, it might be useful is to use fold markers in the begin and end patterns, like this:

call TextEnableCodeSnip('html' ,'#{{{html' ,'#html}}}', 'SpecialComment')

This will allow you to fold snippet sections if you :set foldmethod=marker.

Setting up these function calls in your after/syntax directory will allow you to automatically allow such snippet sections in every file of a given type.

Notes

  • If highlighting gets out of sync, try executing :syn sync fromstart to fix it.
  • If you want this highlighting within other syntax items (like strings), you may need to tweak the syntax rules here or in the syntax file using contains and/or containedin. :help :syn-contains :help :syn-containedin

References

Comments

Is this also possible for indentation? Lets say C inside of an XML file?