[Tex/LaTex] Code highlighting in ConTeXt

contexthighlighting

What is the best way to highlight code when using ConTeXt? I am aware of support for specific languages, as described on the ConTeXt wiki, but it seems rather limited at present. I know that we could also rely on vim, through the t-vim module.

Now, I wonder if there exists more automated ways to deal with other languages like R, Python, Lisp, Asymptote? Also, I would like to be able to combine verbatim and mathematical notations, as it is currently available in Minted, for example.

A working example would be very appreciated.

Best Answer

If you are willing to use an external tool, then t-vim provides highlighting for many languages. You can use it as follows: define a typing

\usemodule[vim]
\definevimtyping [RUBY]  [syntax=ruby]

and then use it either as an evnironment

    \startRUBY
      ...
    \stopRUBY

or inline

    \inlineRUBY{...}

This module does not support math escape, but with luatex, it is easy to support. Here is a complete example.


\newcatcodetable\minimalmathtable

\startcatcodetable \minimalmathtable
    \catcode\backslashasciicode  = \escapecatcode
    \catcode\leftbraceasciicode  = \begingroupcatcode  
    \catcode\rightbraceasciicode = \endgroupcatcode
    \catcode\endoflineasciicode  = \activecatcode
    \catcode\formfeedasciicode   = \activecatcode
    \catcode\spaceasciicode      = \activecatcode
    \catcode\dollarasciicode     = \mathshiftcatcode
\stopcatcodetable 

\unprotect
\starttexdefinition mathescaped #1
  \pushcatcodetable
  \setcatcodetable \minimalmathtable
  \ctxcommand{parsemath(\!!bs #1 \!!es)}
  \popcatcodetable
\stoptexdefinition
\protect

\startluacode
  local function unescape(content)
      local s = string.gsub(content, '\\\\', '\\')
      s = string.gsub(s, '\\{', '{')
      s = string.gsub(s, '\\}', '}')
      return s
  end

  local dollar = lpeg.P("$")
  local nodollar = (1 - dollar)
  local math = lpeg.Cs(dollar * nodollar^0 * dollar) / unescape
  local any = lpeg.P(1)
  local match = lpeg.Cs( (math + any)^0 )

  function commands.parsemath(content)
    local s = lpeg.match(match, content)
    tex.sprint(s)
  end

\stopluacode

\usemodule[vim]

\startcolorscheme[pscolor]
    \definesyntaxgroup 
        [Comment]
        [command=\mathescaped]
\stopcolorscheme

\definevimtyping[python][syntax=python]

\starttext

\startpython
# Returns $\sum_{i=1}^{n}i$
def sum_upto(n)
    r = range(1, n+1)
    return sum(r)
\stoppython

\stoptext

The same restrictions as the listings package apply, i.e., spaces are active, so you should avoid spaces in math mode.

EDIT: The new (2012.12.17) version of t-vim module supports math escape in the Comment region. To active it you need to pass escape=on to \definevimtyping and use \m{...} or \math{...} for math mode. Thus, instead of the above kludge, you can use

\definevimtyping[python][syntax=python, escape=on]

\startpython
# Returns \m{\sum_{i=1}^{n}i}
def sum_upto(n)
    r = range(1, n+1)
    return sum(r)
\stoppython