[Tex/LaTex] Drawing a directory listing a la the tree command in TikZ

tikz-treestrees

Good day everyone –

Is there a fast and efficient way to draw directory tree structures (aka depth-indented listings) like the unix's tree command, that is, is there a way to draw the following using TikZ?

root
  |
  |--- dir1
  |     |
  |     |-- a1
  |     |-- a2
  |--- dir2
  |--- dir3

I've checked tikz-tree and tikz-qtree, but the packages always want to grow the tree balanced and not down then to the right.

Any advice is truly appreciated.

Thanks.

Best Answer

I just came across this thanks to the duplicate at Vertical trees with TikZ. The following code seems to work, though I will admit to not testing it fully and making up the numbers so that it just works.

Let's start with some output:

TikZ version of dirtree

Here's the code:

\documentclass[border=10]{standalone}
\usepackage{tikz}

\makeatletter
\newcount\dirtree@lvl
\newcount\dirtree@plvl
\newcount\dirtree@clvl
\def\dirtree@growth{%
  \ifnum\tikznumberofcurrentchild=1\relax
  \global\advance\dirtree@plvl by 1
  \expandafter\xdef\csname dirtree@p@\the\dirtree@plvl\endcsname{\the\dirtree@lvl}
  \fi
  \global\advance\dirtree@lvl by 1\relax
  \dirtree@clvl=\dirtree@lvl
  \advance\dirtree@clvl by -\csname dirtree@p@\the\dirtree@plvl\endcsname
  \pgf@xa=1cm\relax
  \pgf@ya=-1cm\relax
  \pgf@ya=\dirtree@clvl\pgf@ya
  \pgftransformshift{\pgfqpoint{\the\pgf@xa}{\the\pgf@ya}}%
  \ifnum\tikznumberofcurrentchild=\tikznumberofchildren
  \global\advance\dirtree@plvl by -1
  \fi
}

\tikzset{
  dirtree/.style={
    growth function=\dirtree@growth,
    every node/.style={anchor=north},
    every child node/.style={anchor=west},
    edge from parent path={(\tikzparentnode\tikzparentanchor) |- (\tikzchildnode\tikzchildanchor)}
  }
}
\makeatother
\begin{document}
\begin{tikzpicture}[dirtree]
\node {toplevel} 
    child { node {Foo}
            child { node {foo} }
            child { node {bar} }
            child { node {baz} }
    }
    child { node {Bar}
        child { node {foo} }
        child { node {foo} }
        child { node {foo} }
        child { node {foo} }
        child { node {bar} }
        child { node {baz} }
    }
    child { node {Baz}
        child { node {foo} }
        child { node {bar} }
        child { node {baz} }
    };
\end{tikzpicture}
\end{document}

We define a new growth function. The idea is that we have a global counter that keeps track of how many nodes we've processed so far and position the children according to this. The main problem is that the way trees are built: the origin for each branch is the parent node. So we want to apply an absolute transformation (the total height from the root) but have to take into account the relative transformation first. This takes a bit of bookkeeping, but once that's figured out then the rest is ... plain sailing.

The edges are the easy bit - we simply define them to be |-, ie vertical and then horizontal.

Related Question