17

Is there an elegant way to draw red squigglies under text, to emulate what a [source] code editor does when it detects errors (either spelling mistakes, syntactical errors or semantic errors)?

enter image description here

Here is now the sguiggly looks in a very popular editor zoomed in. As you can see it's not actually a wave.

enter image description here

4
  • I've added an extra screenshot to show how the sguiggly actually looks zoomed-in. I don't know if that's the normal look but that's how it looks in one of the most popular code editors. Commented Nov 4, 2012 at 19:26
  • \tikz anyone? Commented Nov 4, 2012 at 19:36
  • 1
    the twelfth edition of chicago (1979) specifies "Wavy underlining is used to indicate boldface type." red and other colors are recommended for indicating other alphabet styles, and the wavy underline for boldface is assumed to be black. obviously, adjustments are in order for screen usage; however, "wavy" traditionally means wavy. the more zig-zag appearance of the underlining in the screen shot appears to me to be taking an easy way out. Commented Nov 4, 2012 at 20:25
  • @barbarabeeton I don't know how appropriate the style is but in zoomed-in mode I find it looks better, subjectively speaking. Whether the developers choose this style to "cut corners" (excuse the pun) or not is an interesting question in and of itself. I don't have an answer for that. Commented Nov 4, 2012 at 21:04

3 Answers 3

7

Here's a variation using the soul package, tikz and the ubiquitous \tikzmark. The main command is \MarkText and uses a zigzag decoration; the syntax is:

\MarkText[<color>][<amplitude>][<segment length>]{<text>}

so the attributes for the decoration can be customized. The code:

\documentclass{article}
\usepackage{xparse}
\usepackage{marginnote}
\usepackage{soul}
\usepackage{lipsum}
\usepackage{tikz}
\usetikzlibrary{calc}
\usetikzlibrary{decorations.pathmorphing}

\newlength\LineWidth
\newlength\Amplitude
\newlength\SegLength

\setlength\LineWidth{0.4pt}
\setlength\Amplitude{1pt}
\setlength\SegLength{5pt}

\definecolor{HLcolor}{RGB}{240,0,0}

% The following code contains a variation of the great code by Antal S-Z
% in his answer to http://tex.stackexchange.com/a/6029/3954
%in TeX.SX

\newcommand\tikzmark[1]{%
  \tikz[overlay,remember picture] \node (#1) {};}

\makeatletter
\newcommand{\highlight@DoHighlight}{
  \draw[HLcolor,line width=\LineWidth,decorate,decoration={zigzag,amplitude=\Amplitude,segment length=\SegLength}]  ($(begin highlight)+(0,-2pt)$) -- ($(end highlight)+(0,-2pt)$) ;
}

\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][]{%
  \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

\DeclareDocumentCommand\MarkText{O{red}O{1pt}O{5pt}m}{%
  \colorlet{HLcolor}{#1}
  \setlength\Amplitude{#2}%
  \setlength\SegLength{#3}%
  \tikzmark{endquote}\tikzmark{beginquote}\highlight{#4}%
}

\begin{document}
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Ut purus elit,
vestibulum ut, placerat ac, adipiscing vitae, felis. Curabitur dictum gravida
mauris.\MarkText{Nam arcu libero, nonummy eget, consectetuer id, vulputate a, magna. Donec vehicula augue eu neque. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas.} Aenean
faucibus. Morbi dolor nulla, malesuada eu, pulvinar at, mollis ac, nulla. Cur-
abitur auctor semper nulla.\MarkText[olive][1pt][2pt]{Donec varius orci eget risus. Duis nibh mi, congue eu, accumsan eleifend, sagittis quis, diam. Duis eget orci sit amet orci dignissim} rutrum.

Nam dui ligula, fringilla a, euismod sodales, sollicitudin vel, wisi. Morbi
auctor lorem non justo. Nam lacus libero, pretium at, lobortis vitae, ultricies et,
tellus. Donec aliquet, tortor sed accumsan bibendum, erat ligula aliquet magna,
vitae ornare odio metus a mi. Morbi ac orci et nisl hendrerit mollis. Suspendisse
ut massa. Cras nec ante. Pellentesque a nulla.\MarkText[cyan!60!black][2pt][15pt]{Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.} Aliquam tincidunt urna. Nulla ullamcorper vestibulum turpis. Pellentesque cursus luctus mauris.

\MarkText{Model}

\end{document}

The result:

enter image description here

A zoom to the last word:

enter image description here

The code needs two or three runs to stabilize. Unfortunately, \MarkText won't work well if a page break occurs inside the text to which it is applied.

3
  • Thanks. This is the best answer so far. The only thing missing is that the path-segment join style is different. The peaks are cut off. This makes the sguiggly look more smooth, if you will. Commented Nov 4, 2012 at 20:07
  • This is lovely, but unfortunately if I put this into a lstlisting environment, I get a spurious space inserted before the highlighted word. I'll try to post a MWE...in the meantime, any ideas?
    – Roly
    Commented Apr 22, 2016 at 14:00
  • I think nowadays soulpos implements something similar (soul supports hyphenation, unlike ulem → text decorations - Strikeout - when which package ? ( ulem vs soul vs ...) - TeX - LaTeX Stack Exchange).
    – user202729
    Commented Sep 23, 2022 at 8:08
16

The package ulem has a macro that does the job.

\usepackage[normalem]{ulem} % [normalem] to set \emph{} to default behaviour (italic instead of underlining)
...
\uwave{to be underlined in a squiggly way}

How to get a red (or any other coloured) line is explained at: How to color just the wave produced by the ulem package

Here’s what Yiannis Lazarides suggested:

\documentclass[11pt]{article} 
\usepackage{xcolor}
\usepackage{ulem}
\makeatletter
\def\uwave{\bgroup \markoverwith{\lower3.5\p@\hbox{\sixly \textcolor{red}{\char58}}}\ULon}
\font\sixly=lasy6 % does not re-load if already loaded, so no memory problem.
\makeatother
\begin{document}
  \uwave{This is a long test}
\end{document}
2
  • Thanks! I've added a zoomed-in screenshot to show the sguiggly in great detail. It's actually not quite a wave. Commented Nov 4, 2012 at 19:36
  • @BentRasmussen After some googling I couldn’t find anything. I must admit, though, that I didn’t know what to search for, exactly. I guess it’s possible to have “jags” instead of the wave pattern but I wouldn’t know how (besides maybe using TikZ …) Commented Nov 4, 2012 at 19:46
14
\documentclass{article}
\usepackage[normalem]{ulem}
\usepackage{xcolor}
\makeatletter
\def\squiggly{\bgroup \markoverwith{\textcolor{red}{\lower3.5\p@\hbox{\sixly \char58}}}\ULon}
\makeatother

\begin{document}

\squiggly{words}

\end{document}

enter image description here

2
  • 1
    The wave looks misaligned with the test. It starts before the serif of the w, and ends before the right edge of the ascender of the d.
    – Timtro
    Commented Nov 4, 2012 at 15:49
  • Thanks Harish! I've added a zoomed-in screenshot to show the sguiggly in great detail. It's actually not quite a wave. Commented Nov 4, 2012 at 19:37

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .