How to draw markup language structure?

I want to highlight the structure of a formatting language that uses tags somewhat related to HTML, but with different capabilities regarding the closing tags. I'm thinking of something like this:

What options do I have to draw the brackets that explain the structure without the help of additional graphics software?

(I'm using pdflatex...)

-

Updated

A TikZ solution.

The implementation relies on a pair of commands \open and \close for the HTML syntax (and \openvar, \closevar for the other syntax). The commands are defined as follows:

\newcommand\open[1]{
\tikz[remember picture,baseline=(open#1.base)]{\node(open#1){<#1>};}
}

\newcommand\close[3][red]{
\tikz[remember picture,baseline=(close#2.base)]{
\node(close#2){</#2>};
\draw[#1,overlay](open#2)to[ncbar=#3](close#2);
}
}


The -var version of the commands for the second syntax are similarly defined.

The \open command takes one argument, i.e. the name of the open tag. The \close command takes 3 arguments:

1. the first optional argument sets the color of the "bracket" connected the open and close tags (with default set to red);
2. the second argument is the name of the close tag;
3. the third argument determines the height of the "bracket". Note that the bracket is implemented by the ncbar style, provided by Jake's answer here.

Full code

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{calc}

% ncbar style - http://tex.stackexchange.com/a/55069/18228
\tikzset{
ncbar angle/.initial=90,
ncbar/.style={
to path=(\tikztostart)
-- ($(\tikztostart)!#1!\pgfkeysvalueof{/tikz/ncbar angle}:(\tikztotarget)$)
-- ($(\tikztotarget)!($(\tikztostart)!#1!\pgfkeysvalueof{/tikz/ncbar angle}:(\tikztotarget)$)!\pgfkeysvalueof{/tikz/ncbar angle}:(\tikztostart)$)
-- (\tikztotarget)
},
ncbar/.default=0.5cm,
}

\tikzset{every node/.style={inner sep=0pt, outer sep=0pt}} % remove unnecessary space

% HTML syntax
\newcommand\open[1]{
\tikz[remember picture,baseline=(open#1.base)]{\node(open#1){<#1>};}
}
\newcommand\close[3][red]{
\tikz[remember picture,baseline=(close#2.base)]{
\node(close#2){</#2>};
\draw[#1,overlay](open#2)to[ncbar=#3](close#2);
}
}

% second 'unknown' syntax
\newcommand\openvar[1]{
\tikz[remember picture,baseline=(open#1.base)]{\node(open#1){<\uppercase{#1}>};}
}
\newcommand\closevar[3][red]{
\tikz[remember picture,baseline=(close#2.base)]{
\node(close#2){</>};
\draw[#1,overlay](open#2)to[ncbar=#3](close#2);
}
}

\begin{document}

\ttfamily

\open{b} nur fett \open{i} fett kursiv \close[green]{b}{.5cm} nur kursiv \close{i}{.7cm}

\bigskip\bigskip

\openvar{b} nur Fett \openvar{i} fett kursiv \closevar{i}{.5cm}\closevar[green]{b}{.7cm}\openvar{i} nur kursiv \closevar{i}{.5cm}

\end{document}


Update 2

A slightly more efficient way of defining the \close command, which has only two arguments:

\newcommand\close[2][red]{
\tikz[remember picture,baseline=(close#2.base)]{
\node(close#2){</#2>};
\draw[ncbar,#1,overlay](open#2)to(close#2);
}
}


Now it only takes two arguments:

1. The first, optional argument controls the line style of the "bracket". The default is currently set to red, and maybe changed to [red,thick] to produce a red and thick line if the optional argument is not given.

• Note also that the ncbar option is now given to the \draw operation, so by default, the height of the bracket is .5cm. If a bracket of height .7cm needs to be drawn, just use \close[ncbar=.7cm,<other options>]{<tag name>}.
2. The second argument is the same as before: the name of the close tag.

With \closevar similarly modified, the above two examples can be implemented as

\open{b} nur fett \open{i} fett kursiv \close[green]{b} nur kursiv \close[red,ncbar=.7cm]{i}


and

\openvar{b} nur Fett \openvar{i} fett kursiv \closevar{i}\closevar[green,ncbar=.7cm]{b}\openvar{i} nur kursiv \closevar{i}

-
Related comment: I like your easy naming scheme of the nodes, but how do you implement the second example? –  Daniel Oct 14 '13 at 18:56
@Daniel. That's quite easy: change the defined commands: to \newcommand\open[2][]{ \tikz[remember picture,baseline=(open#2#1.base)]{\node(open#2#1){<#2>};} } (and similar for the other one). You should then be able to place the nodes using \open{i} (which makes the openi node) or \open[A]{i} which makes an openiA node. You can use the second syntax to point out ambiguities as in the second example, i.e. \open[A]{b} \open[B]{b} \close[B]{b} \close[A]{b}. Perhaps it would even possible to use LaTeX counters to do the grouping for you. –  Egon Oct 14 '13 at 20:26
Awesome, thanks a lot. I just need one more pointer: For printing, I need to use slightly thicker lines of the same color, but with different line styles - I'm sorry I didn't think about this when preparing the example. I noticed the red and green in your coding, but I don't understand how this is actually used by the commands. There's some magic going on that appears to be beyond my current knowledge - what do I need to read to catch up? –  vwegert Oct 15 '13 at 20:28
@vwegert: You're welcome. Notice that the first argument of the \close command controls the options to the \draw operation. Thus, if you want add more styles to the line, you can add more options to the first argument, and separate them using commas. For example, \close[green,dashed,very thick]{b}{.5cm} will connect the pair of b tags with a green, dashed, and very thick line; \close[red,ultra thick,<->]{i}{.7cm} will connect the pair of i tags with a red, "ultra thick" line with arrow tips on both ends. –  Herr K. Oct 16 '13 at 0:36
@vwegert: To learn about other options available to the \draw operation, the TikZ/PGF Manual is a well-written and authoritative source (though it's quite long). This question on TeX.SX also contains links to other (shorter) summaries of the commands used in TikZ –  Herr K. Oct 16 '13 at 0:42

With PSTricks just for fun. Compile it with latex-dvips-ps2pdf or xelatex (slower).

\documentclass[preview,border=24pt]{standalone}
\usepackage[T1]{fontenc}
\usepackage{pst-node}

\begin{document}
\tt
\Rnode{A}{<tag>} contents \Rnode{B}{</tag>}
\ncbar[angle=90,arm=12pt,linecolor=red]{A}{B}
\end{document}


PDFLaTeX version

\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage{auto-pst-pdf}
\usepackage{pst-node}

\begin{document}
This is a language:
\begin{postscript}
\tt
\Rnode{A}{<tag>} contents \Rnode{B}{</tag>}
\ncbar[angle=90,arm=12pt,linecolor=red,nodesep=6pt]{A}{B}
\end{postscript}
\end{document}


-
Maybe one should add something like \rule{0pt}{\dimexpr1em+12pt\relax}? Otherwise the \ncbar will protrude in other content. –  Qrrbrbirlbel Oct 14 '13 at 18:27
@Marienplatz: Cool, but for now I'm not really prepared to switch (back?) to XeLaTeX or DVI, coming from pdflatex... –  vwegert Oct 14 '13 at 18:29
Unrelated comment: \tt is not a LaTeX command, \ttfamily is correct. (\tt isn't even defined in the LaTeX kernel, it is provided by the class for compatibility reasons, try the same with memoir...) –  clemens Oct 14 '13 at 18:55
@cgnieder: by the way: memoir has an option oldfontcommands –  Herbert Oct 14 '13 at 20:42
@Herbert I know :) I think it's still a good example... –  clemens Oct 14 '13 at 20:45