17

I am trying to get Vim to syntax highlight any file that ends with extension .Rtex in the following way:

  • All top level text is highlighted as TeX
  • Exception: any text enclosed in \begin{python}...\end{python} is highlighted as Python

I am able to achieve each of these criteria individually, but unable to achieve both simultaneously. I think that somehow the TeX highlighting overrides my Python-highlighted regions, or prevents them from taking effect, and I am stuck trying to figure out how.

First step: edit .vimrc to give files with extension .Rtex the filetype rtex:

  au BufRead *.Rtex setf rtex

Second step: create ~/.vim/syntax/rtex.vim. It is the contents of this file that will determine how to highlight .Rtex files.

Third step: enable general top-level TeX highlighting, by making rtex.vim look like this:

runtime! syntax/tex.vim

If I now open a .Rtex file, the entire file is highlighted as TeX, including any text within \begin{python}...\end{python}, as expected.

Fourth step: follow the instructions in Vim's :help syn-include to include python highlighting and apply it to all regions delimited by \begin{python} and \end{python}. My rtex.vim file now looks like this:

runtime! syntax/tex.vim
unlet! b:current_syntax
syntax include @Python syntax/python.vim
syntax region pythonCode start="\\begin{python}" end="\\end{python}" contains=@Python

The unlet! b:current_syntax command is meant to force the python.vim syntax file to execute even though an existing syntax (TeX) is already active.

Problem: If I now open a .Rtex file, the entire file is still highlighted only as TeX. The \begin{python}...\end{python} region seems to have no effect.

Experiment: If I remove or comment out the runtime! command, I do get python highlighting, within the \begin{python}...\end{python} regions, exactly as desired, but of course no TeX highlighting in the remainder of the document. I therefore conclude that the TeX highlighting is somehow responsible for preventing the python regions from taking effect.

Can a Master of Vim offer me any suggestions? I am currently stumped. I have looked at several pages and stackoverflow questions that seem relevant, but none of them have so far led to a solution:

Community
  • 1
  • 1
Maxy-B
  • 2,772
  • 1
  • 25
  • 33
  • Thanks, and hello from 2022! This question, the references you listed, and your answer helped me write [a syntax file](https://gist.github.com/ernstki/7bf7cef49705324121363133561400c9) for Alpine.js, which highlights JavaScript within specific HTML attributes such as `x-data`. – TheDudeAbides Jul 22 '22 at 23:11

2 Answers2

20

After some more study of the manual, and much more trial and error, I have finally answered my own question (a simultaneously embarrassing and sublime accomplishment), which I now preserve here for posterity.

Basically, I think the problem is that the python highlighting wouldn't take effect because the pythonCode region was itself contained in a region or highlight group defined by tex.vim, so it wasn't top-level. The solution is to also include (rather than just runtime) tex.vim, giving it a name like @TeX, and then add containedin=@TeX to my python region definition. So syntax/rtex.vim now looks like this:

let b:current_syntax = ''
unlet b:current_syntax
runtime! syntax/tex.vim

let b:current_syntax = ''
unlet b:current_syntax
syntax include @TeX syntax/tex.vim

let b:current_syntax = ''
unlet b:current_syntax
syntax include @Python syntax/python.vim
syntax region pythonCode matchgroup=Snip start="\\begin{python}" end="\\end{python}" containedin=@TeX contains=@Python

hi link Snip SpecialComment
let b:current_syntax = 'rtex'

And this works! I'm not sure if all of those unlet b:current_syntax commands are strictly necessary. I also gave the python region delimiters a matchgroup (Snip) so that they can be highlighted themselves (with the SpecialComment color), rather than left just plain, which is apparently what happens by default, since they are no longer considered part of the TeX.

Now it is a trivial thing to add more highlight regions for different languages (e.g., \begin{Scode}...\end{Scode}), which is great if you're getting into literate programming -- the original motivation for my question.

Edit: here is a screenshot showing how it works with Python and R code embedded in a TeX document: Screenshot: Python and R embedded in TeX

Maxy-B
  • 2,772
  • 1
  • 25
  • 33
  • Does this lead to LaTex compile time errors since `\begin{Python}` is unknown? – puk Feb 02 '12 at 21:04
  • 1
    Nope, notice the `\usepackage{python}` which defines the `python` environment. – Maxy-B Feb 04 '12 at 02:22
  • what if I want to use syntax based on `\begin{Puk'sSuperAmazingLanguage}` ? =P – puk Feb 04 '12 at 16:11
  • 1
    @puk, you'll need two things: a syntax file for Vim to do the syntax highlighting of this amazing language (`amazinglanguage.vim` or whatever), and you'll need to define the `Puk'sSuperAmazingLanguage` environment for LaTeX, whether there's a package you can use that defines it, or you have to code it yourself, or whatever. What LaTeX actually _does_ with the contents of that environment is also up to you or the package writer. – Maxy-B Feb 05 '12 at 18:16
  • @Maxy-B — Do you know if it is possible to also apply auto-indent rules to these Python blocks? It would be awesome if vim would somehow apply all the Python-filetype stuff to code in a {python}-environment; while applying LaTeX-filetype stuff to all the other code. The syntax highlighting is great; but auto-indent would also be really cool. – jmc Mar 30 '15 at 18:12
  • Struggling to use your answer, and borrowing from [the answer here](http://stackoverflow.com/questions/519753/embedded-syntax-highligting-in-vim), for reasons I do not comprehend, it was necessary to include the `keepend` between the `start` and `end` definitions; it would not switch back to my "containing" syntax once it got into a region otherwise.... Otherwise, great question and answer! –  Jun 23 '15 at 14:02
0

I don't know if it helps, but a hack I use with my Rnw files that use both tex and rnoweb features is as follows:

 au BufEnter *.Rnw set filetype=tex | set filetype=rnoweb 

Would an adapted version work in your case?

Jeromy Anglim
  • 33,939
  • 30
  • 115
  • 173
  • Right, so that gives the file both filetypes, causing both highlighters to apply everywhere -- only a partial solution, since I just want python highlighting within certain regions. I didn't know you could use a pipe like that (as opposed to `set filetype=tex.rnoweb`), though, so thanks! – Maxy-B Mar 03 '11 at 15:14
  • 1
    does the pipe differ from using dot notation like `setfiletype=js.php`? – puk Feb 05 '12 at 18:28