Vim Tips Wiki
Advertisement
Tip 857 Printable Monobook Previous Next

created January 21, 2005 · complexity basic · 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.

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.

Note, if highlighting gets out of sync, try executing :syn sync fromstart to fix it.

Comments

 TO DO 
Clean up for July featured tip. Ben A. says it works, and I verified by using it to include vimscript inside <pre> tags in a wiki filetype.

I recommend deleting both the comments below. I don't think the first is needed anymore, and the external link in the second is NOT to a well-known Vim site. According to our posted policies we don't tend to keep these. However, it does claim to solve a problem with the current script...perhaps we should provide a "see also" link instead of deleting.

--Fritzophrenic 04:05, 13 May 2009 (UTC)


In my after/syntax/python.vim the first call TextEnableCodeSnip does not work so I stuck one in that I really would not need so that it looks like:

"I have no idea why but this needs a "dummy" call to work, so I stuck in c
call TextEnableCodeSnip('c' ,'#{{{c' ,'#c}}}')
call TextEnableCodeSnip('sql' ,'#{{{sql' ,'#sql}}}')
call TextEnableCodeSnip('xml' ,'#{{{xml' ,'#xml}}}')
call TextEnableCodeSnip('html' ,'#{{{html' ,'#html}}}')

That one for c is apparently ignored or somehow fails and the rest work great. Go figure.


When you're in Python and you generate TeX or HTML code you have to set the 'contains' flag of string highlighting appropriate to get it inside strings.

In Ruby, you don't need to say '@begin=sth@' when you're using here documents. An appropriate delimiter should suffice.

I made these solutions available at http://projects.bertram-scharpf.de/vimsyn

Advertisement