Much to my surprise, this is doable, by combining TikZ and soul. I don't think I like how it looks (though to each their own), but it was a fun challenge. The idea is to use TikZ to draw the necessary boxes up to line breaks, and then restart each box on a new line. But how to do this? Well, it turns out that soul works by inserting things after every possible hyphenation point (which it calls "syllables", a terminology misuse I find irritating)—importantly, this includes the beginnings and ends of words. And the only time we ever see a line break is after a hyphenation point! This is good: we'll use soul to insert a TikZ node at each syllable break, and then draw them together. For this, we use TikZ's remember picture
and overlay
options; the former enables you to refer to nodes in the labeled picture from outside, and the latter makes the picture take up no space.
To implement this, we surround each hyphenation unit with two "marks" (TikZ pictures). The "start" mark checks to see if it's on a new line; if it is, it draws the highlighting rectangle from the last recorded start position to the last recorded end position, and then records the new start position. The "stop" mark just records the new stop position. We also have to make sure that at a hyphenation point, the stop position is after the hyphen. And of course, we surround the whole picture with a start position and a stop position. Note that due to the remember picture
machinery, you have to compile the document twice.
Here's a working document with ragged highlights:
\documentclass{minimal}
\usepackage{soul}
\usepackage{tikz}
\usetikzlibrary{calc}
\usetikzlibrary{decorations.pathmorphing}
\makeatletter
\newcommand{\defhighlighter}[3][]{%
\tikzset{every highlighter/.style={color=#2, fill opacity=#3, #1}}%
}
\defhighlighter{yellow}{.5}
\newcommand{\highlight@DoHighlight}{
\fill [ decoration = {random steps, amplitude=1pt, segment length=15pt}
, outer sep = -15pt, inner sep = 0pt, decorate
, every highlighter, this highlighter ]
($(begin highlight)+(0,8pt)$) rectangle ($(end highlight)+(0,-3pt)$) ;
}
\newcommand{\highlight@BeginHighlight}{
\coordinate (begin highlight) at (0,0) ;
}
\newcommand{\highlight@EndHighlight}{
\coordinate (end highlight) at (0,0) ;
}
\newdimen\highlight@previous
\newdimen\highlight@current
\DeclareRobustCommand*\highlight[1][]{%
\tikzset{this highlighter/.style={#1}}%
\SOUL@setup
%
\def\SOUL@preamble{%
\begin{tikzpicture}[overlay, remember picture]
\highlight@BeginHighlight
\highlight@EndHighlight
\end{tikzpicture}%
}%
%
\def\SOUL@postamble{%
\begin{tikzpicture}[overlay, remember picture]
\highlight@EndHighlight
\highlight@DoHighlight
\end{tikzpicture}%
}%
%
\def\SOUL@everyhyphen{%
\discretionary{%
\SOUL@setkern\SOUL@hyphkern
\SOUL@sethyphenchar
\tikz[overlay, remember picture] \highlight@EndHighlight ;%
}{%
}{%
\SOUL@setkern\SOUL@charkern
}%
}%
%
\def\SOUL@everyexhyphen##1{%
\SOUL@setkern\SOUL@hyphkern
\hbox{##1}%
\discretionary{%
\tikz[overlay, remember picture] \highlight@EndHighlight ;%
}{%
}{%
\SOUL@setkern\SOUL@charkern
}%
}%
%
\def\SOUL@everysyllable{%
\begin{tikzpicture}[overlay, remember picture]
\path let \p0 = (begin highlight), \p1 = (0,0) in \pgfextra
\global\highlight@previous=\y0
\global\highlight@current =\y1
\endpgfextra (0,0) ;
\ifdim\highlight@current < \highlight@previous
\highlight@DoHighlight
\highlight@BeginHighlight
\fi
\end{tikzpicture}%
\the\SOUL@syllable
\tikz[overlay, remember picture] \highlight@EndHighlight ;%
}%
\SOUL@
}
\makeatother
\begin{document}
Lorem ipsum \highlight{dolor sit amet, consectetur adipis-icing elit, sed do
eiusmod tempor} incididunt ut labore et dolore magna aliqua. Ut enim ad minim
veniam, quis nostrud exercitation \highlight[red]{ullamco $laboris$ nisi ut
aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit} in
voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint
occaecat \highlight[green, draw=blue]{cupidatat non proident,
suntinculpaquiofficiadeseruntmollitanimidestlaborum.
Loremipsumdolorsitametconsecteturadipisicingelitseddoeiusmodtemporincididuntutlabore-etdoloremagnaaliqua.}
I suppose I could write some more text here.
\end{document}
This produces the following output:
There are two formatting modes: \defhighlighter[misc]{color}{opacity}
, which sets the fill color to color
, the fill opacity to opacity
, and styles every highlighter block (via every highlighter
) with those plus the misc
options. Secondly, for a specific block of highlighted text, you can use \highlight[tikz-opts]{...}
to set options locally. These are both demonstrated in the above code.
There are currently four caveats. The first is that this will write one line to your aux file for each syllable break in the highlighted text, in addition to one for the beginning of each, one for the end of each, and one for each line break after a (real or inserted) hyphen. For instance, the example document wrote 222 lines to my aux file. This may or may not be a problem for you, but I'm not sure how to make it better. The second is that strange things happen if you let highlighting extend over a page break. (Although I might be able to fix this one….) The third is that I don't see a way to draw the highlighting in the background. (Because it's drawn so late, the pgfonlayer
environment doesn't work.) This is why the text looks faded. You can adjust the opacity value if you don't like this, but I don't see how to avoid it (suggestions?). And the fourth is that I guessed the height of the font, because while I figure this should be a dimension in TeX somewhere, I don't know where (again, suggestions?).
Short answer: I'm not aware of a single solution that will do all three languages, at least not without some work on your part. listings
will likely be easiest.
minted
uses the Pygments syntax highlighter. Pygments currently doesn't support Maple or Mathematica (at least, not unless you can track down someone's custom lexer). So the only way to proceed with minted
is probably to write your own lexer (might not be that difficult, but I've never tried).
listings
supports Mathematica and Python, but not Maple (but you might look at this). So if you go that route, you will need to define a language (this shouldn't be too difficult; you could start with the link above, and customize to your needs).
Regarding other options: The program highlight can highlight Maple and export a LaTeX version. It also does Python, but not Sage or Mathematica. GNU Source-highlight doesn't have Mathematica or Maple. I've never used either of these. I think that covers all the standard and fallback syntax highlighters (there's also t-vim, but that's for ConTeXt). There are also some language specific options, for example, evidently there's a maple2e
package (see this).
You should keep in mind that Sage and Python aren't completely identical (for example, ^
vs. **
for exponents). If you want a more Sage-specific solution, you might see the sagetex
package's approach to using Sage with listings
. Basically, it defines a new Sage language based on Python, for the Sage console (just search the sagetex
documentation for \lstdefinelanguage{Sage}
, and take a look at what follows).
Best Answer
Here'a an initial version using the
soul
,marginnote
andtikz
packages (and, as it has become customary, the ubiquitous\tikzmark
):This approach uses Ulrike Fischer's code of her answer to soul: broken highlighting with xcolor when using \selectcolormodel
Here's now a new version producing the border; this version contains a variation of the great code by Antal S-Z in his answer to Cool Text Highlighting in LaTeX. The main command
\MarkText
has the following syntax:It was defined using the
xparse
package. As can be seen in the image below, some work has still to be done when the highlighted text fits on one line.P.S.: I'll be improving this answer when I have time.