% \CheckSum{236} % \iffalse meta-comment % forest-libs.dtx %% `forest-libs' is a collection of libraries for package `forest'. %% %% Copyright (c) 2012-2017 Saso Zivanovic %% (Sa\v{s}o \v{Z}ivanovi\'{c}) %% saso.zivanovic@guest.arnes.si %% %% This work may be distributed and/or modified under the %% conditions of the LaTeX Project Public License, either version 1.3 %% of this license or (at your option) any later version. %% The latest version of this license is in %% %% http://www.latex-project.org/lppl.txt %% %% and version 1.3 or later is part of all distributions of LaTeX %% version 2005/12/01 or later. %% %% This work has the LPPL maintenance status `author-maintained'. %% %% This file is a part of package `forest'. For the list of files %% constituting the package see main source file of the package, %% `forest.dtx', or the derived `forest.sty'. %% % \fi % % \section{Libraries} % % This chapter contains not only the reference of commands found in libraries and some examples of % their usage, but also their definitions. This is done in the hope that these definitions, being % mostly styles, will be useful as examples of the core features of the package. I even managed to % comment them a bit \dots % % \paragraph{Disclaimer.} At least in the initial stages of a library's development, the function % and interface of macros and keys defined in a library might change without backwards compatibility % support! Though I'll try to keep this from happening \dots % % \begin{macrocode} \RequirePackage{forest} % \end{macrocode} % %\iffalse %<*linguistics> %\fi % \librarysection{linguistics} % \begin{macrocode} \ProvidesForestLibrary{linguistics}[2017/07/14 v0.1.2] % \end{macrocode} % % Defaults: % \begin{macrocode} \forestset{ linguistics@set@baseline/.style={ if phantom={for next node=linguistics@set@baseline}{baseline} }, libraries/linguistics/defaults/.style={ default preamble={ % \end{macrocode} % Edges of the children will ``meet'' under the node: % \begin{macrocode} sn edges, % \end{macrocode} % The root of the tree will be aligned with the text \dots\ or, more commonly, the example number. % More precisely, we actually align the first (in linear order) non-phantom node. This covers the % common case of side-by-side trees joined with a phantom root. % \begin{macrocode} before drawing tree={ if nodewalk valid={name=forest@baseline@node}{}{linguistics@set@baseline}, }, % \end{macrocode} % Enable (centered) multi-line nodes. % \begin{macrocode} for tree={align=center}, }, }, } % \end{macrocode} % % There's no linguistics without c-command\footnote{The definition of c-command is as follows: a node c-commands its siblings and their descendants.} \dots % \begin{syntax} % \indexitem{step>c-commanded} Visit all the nodes c-commanded by the current node. % \indexitem{step>c-commanders} Visit all the c-commanders of the current node, starting from the closest. % % \begin{forestexample}[tree bin=minipage,index={branch',c-commanded}] % \begin{forest} % [VP % [DP[John]] % [V' % [V, draw, for c-commanded={draw,circle} % [sent] % ] % [DP[Mary]] % [DP[D[a]][NP[letter]]] % ] % ] % \end{forest} % \end{forestexample} % % See how \indexex{branch'} is used to define |c-commanded|, and how \indexex{while nodewalk valid} and \indexex{nodewalk key>fake} are combined in the definition of |c-commanders|. % \begin{macrocode} \forestset{ define long step={c-commanded}{style}{branch'={siblings,descendants}}, define long step={c-commanders}{style}{while nodewalk valid={parent}{siblings,fake=parent}}, } % \end{macrocode} % % |c-commanders| could also be defined using \indexex{branch}: % \begin{lstlisting} % branch={current and ancestors, siblings} % \end{lstlisting} % % \indexitem{node key>sn edges} % % In linguistics, most people want the parent-child edge to go from the \emph{s}outh of the parent % to the \emph{n}orth of the child. This is achieved by this (badly named) style, which makes the % entire (sub)tree have such edges. % % \begin{forestexample} % \begin{forest} % sn edges % [VP % [DP] % [V' % [V] % [DP] % ] % ] % \end{forest} % \end{forestexample} % % \begin{macrocode} \forestset{ sn edges/.style={ for tree={ parent anchor=children, child anchor=parent } }, } % \end{macrocode} % % A note on implementation. Despite its name, this style does not refer to the |south| and |north| % anchor of the parent and the child node directly. If it did so, it would only work for trees with % standard linguistic \index{grow}|=-90|. So we rather use \FoRest;'s growth direction based % anchors: \index{anchor>children} always faces the children and \index{anchor>parent} always faces % the parent, so the edge will always be between them, and the normal, upward growing trees will % look good as well. % % \begin{forestexample}[index={anchor>south,anchor>north,option>parent anchor,option>child anchor}] % \begin{forest} % [bad![VP,no edge, for tree={grow=90, edge=red}, % for tree={parent anchor=south, child anchor=north} % bad % [DP][V'[V][DP]]]] % \end{forest} % \begin{forest} % [good![VP, no edge, for tree={grow=90, edge=green}, % ~sn edges~ % good! % [DP][V'[V][DP]]]] % \end{forest} % \end{forestexample} % % \indexitem{node key>roof} Makes the edge to parent a triangular roof. % \begin{macrocode} \forestset{ roof/.style={edge path'={% (.parent first)--(!u.children)--(.parent last)--cycle } }, } % \end{macrocode} % % \indexitem{node key>nice empty nodes} % % We often need empty nodes: tree (\ref{ex:niceemptynodes}a) shows how they look like by default: % ugly. % % First, we don't want the gaps: we change the shape of empty nodes to coordinate. We get tree % (\ref{ex:niceemptynodes}b). % % Second, the empty nodes seem too close % to the other (especially empty) nodes (this is a result of a small % default |s_sep|). We could use a greater \index{s sep}, but a better solution seems % to be to use |calign=fixed_angles|. The result is shown in (\ref{ex:niceemptynodes}c). % % However, at the transitions from empty to non-empty nodes, tree (\ref{ex:niceemptynodes}c) % seems to zigzag (although the base points of the spine nodes % are perfectly in line), and the edge to the empty node left to VP % seems too long (it reaches to the level of VP's base, while we'd % prefer it to stop at the same level as the edge to VP itself). The % first problem is solved by substituting |fixed_angles| for % |fixed_edge_angles|; the second one, by anchoring siblings of % empty nodes at north. VoilĂ , (\ref{ex:niceemptynodes}d)! % % \begin{forestexample}[label=ex:niceemptynodes,layout=tree on bottom,index={fixed angles,fixed edge angles,calign,tree,delay,where option,content,for step,step>parent,step>children,option>anchor}] % \forestset{ % xlist/.style={ % phantom, % for children={no edge,replace by={[,append, % delay={content/.wrap pgfmath arg={\csname @alph\endcsname{##1}.}{n()+#1}} % ]}} % }, % xlist/.default=0 % } % \begin{forest} % [,~xlist~, % for tree={after packing node={s+=0.1pt}}, % hack!!! % [CP, %(a) % [][[][[][VP[DP[John]][V'[V[loves]][DP[Mary]]]]]]] % [CP, delay={where content={}{shape=coordinate}{}} %(b) % [][[][[][VP[DP[John]][V'[V[loves]][DP[Mary]]]]]]] % [CP, for tree={calign=fixed angles}, %(c) % delay={where content={}{shape=coordinate}{}} % [][[][[][VP[DP[John]][V'[V[loves]][DP[Mary]]]]]]] % [CP, ~nice empty nodes~ %(d) % [][[][[][VP[DP[John]][V'[V[loves]][DP[Mary]]]]]]] % ] % \end{forest} % \end{forestexample} % % \begin{macrocode} \forestset{ nice empty nodes/.style={ for tree={calign=fixed edge angles}, delay={where content={}{shape=coordinate, for current and siblings={anchor=north}}{}} }, } % \end{macrocode} % % \indexitem{node key>draw brackets} Outputs the bracket representation of the tree. % \indexitem{node key>draw brackets compact} % \itemnosep % \indexitem{node key>draw brackets wide} These keys control whether the brackets have extra % spaces around them (|wide|) or not (|compact|). % \begin{macrocode} \providecommand\text[1]{\mbox{\scriptsize#1}} \forestset{ draw brackets compact/.code={\let\drawbracketsspace\relax}, draw brackets wide/.code={\let\drawbracketsspace\space}, draw brackets/.style={ % \end{macrocode} % There's stuff to do both before (output the opening bracket and the content) and after (output the % closing bracket) processing the children, so we use \indexex{for tree'}. % \begin{macrocode} for tree'={ TeX={[% % \end{macrocode} % Complication: \index{content format} must be expanded in advance, to correctly process tabular environments implicitely loaded by \index{align}|=|\index{value of=align>center}, which is the default in this library. (Not that one would want a multiline output in the bracket representation, but it's better than crashing.) % \begin{macrocode} \edef\forestdrawbracketscontentformat{\foresteoption{content format}}% }, if n children=0{ TeX={\drawbracketsspace\forestdrawbracketscontentformat\drawbracketsspace} }{ TeX={\textsubscript{\text{\forestdrawbracketscontentformat}}\drawbracketsspace} }, }{ TeX={]\drawbracketsspace}, } }, draw brackets wide } % \end{macrocode} % \end{syntax} % % \subsubsection{GP1} % % \begin{syntax} % \indexitem{node key>GP1} % % For Government Phonology (v1) representations. Here, the big trick % is to evenly space $\times$s by having a large enough |outer_xsep| % (adjustable), and then, before drawing (timing control option % |before_drawing_tree|), setting |outer_xsep| back to 0pt. The last step % is important, otherwise the arrows between $\times$s won't draw! % % An example of an ``embedded'' |GP1| style: % \begin{forestexample}[layout=tree on bottom,index={where option,tier,for step,step>children,content,tikz,option>l,dimen+,no edge},index>={!}] % \begin{forest} % myGP1/.style={ % ~GP1~, % delay={where tier={x}{ % for children={content=\textipa{##1}}}{}}, % tikz={\draw[dotted](.south)-- % (!1.north west)--(!l.north east)--cycle;}, % for children={l+=5mm,no edge} % } % [VP[DP[John,tier=word,myGP1 % [O[x[dZ]]] % [R[N[x[6]]]] % [O[x[n]]] % [R[N[x]]] % ]][V'[V[loves,tier=word,myGP1 % [O[x[l]]] % [R[N[x[a]]]] % [O[x[v]]] % [R[N[x]]] % [O[x[z]]] % [R[N[x]]] % ]][DP[Mary,tier=word,myGP1 % [O[x[m]]] % [R[N[x[e]]]] % [O[x[r]]] % [R[N[x[i]]]] % ]]]] % \end{forest}% % \end{forestexample} % % And an example of annotations. % \begin{forestexample} % \begin{forest}[,phantom,s sep=1cm % [{[ei]}, GP1 % [R[N[x[A,~el~[I,~head~,~associate=N~]]][x]]] % ] % [{[mars]}, GP1 % [O[x[m]]] % [R[N[x[a]]][x,~encircle~,densely dotted[r]]] % [O[x,~encircle~,~govern=<~[s]]] % [R,~fen~[N[x]]] % ] % ]\end{forest} % \end{forestexample} % % \begin{macrocode} \newbox\standardnodestrutbox \setbox\standardnodestrutbox=\hbox to 0pt{\phantom{\forestOve{standard node}{content}}} \def\standardnodestrut{\copy\standardnodestrutbox} \forestset{ GP1/.style 2 args={ for n={1}{baseline}, s sep=0pt, l sep=0pt, for descendants={ l sep=0pt, l={#1}, anchor=base,calign=first,child anchor=north, inner xsep=1pt,inner ysep=2pt,outer sep=0pt,s sep=0pt, }, delay={ if content={}{phantom}{for children={no edge}}, for tree={ if content={O}{tier=OR}{}, if content={R}{tier=OR}{}, if content={N}{tier=N}{}, if content={x}{ tier=x,content={$\times$},outer xsep={#2}, for tree={calign=center}, for descendants={content format={\noexpand\standardnodestrut\forestoption{content}}}, before drawing tree={outer xsep=0pt,delay={typeset node}}, s sep=4pt }{}, }, }, before drawing tree={where content={}{parent anchor=center,child anchor=center}{}}, }, GP1/.default={5ex}{8.0pt}, associate/.style={% tikz+={\draw[densely dotted](!)--(!#1);}}, spread/.style={ before drawing tree={tikz+={\draw[dotted](!)--(!#1);}}}, govern/.style={ before drawing tree={tikz+={\draw[->](!)--(!#1);}}}, p-govern/.style={ before drawing tree={tikz+={\draw[->](.north) to[out=150,in=30] (!#1.north);}}}, no p-govern/.style={ before drawing tree={tikz+={\draw[->,loosely dashed](.north) to[out=150,in=30] (!#1.north);}}}, encircle/.style={before drawing tree={circle,draw,inner sep=0pt}}, fen/.style={pin={[font=\footnotesize,inner sep=1pt,pin edge=<-]10:\textsc{Fen}}}, el/.style={content=\textsc{\textbf{##1}}}, head/.style={content=\textsc{\textbf{\underline{##1}}}} } % \end{macrocode} % \end{syntax} %\iffalse % %\fi % % % %\iffalse %<*edges> %\fi % \librarysection{edges} % \begin{macrocode} \ProvidesForestLibrary{edges}[2016/12/05 v0.1.1] % \end{macrocode} % % \begin{syntax} % % \indexitem{node key>forked edge'} % % Sets a forked edge to the current node. Arbitrary growth direction and node rotation are % supported. % % \indexitem{node key>forked edge} % % Like \index{forked edge'}, but it also sets \index{option>parent anchor} and \index{option>child % anchor} to the likely values of \index{anchor>children} and \index{anchor>parent}, respectively. % % \indexitem(tree){node key>forked edges}|=|\meta{nodewalk} % % Invokes \index{forked edge} for all nodes in the \meta{nodewalk}, by default the entire (sub)tree % rooted in the current node. % % \indexitem{option>fork sep} The \index{forest cs>l}-distance between the parent anchor and the % fork. % % \end{syntax} % % \begin{forestexample}[index={for step,tree,grow',forked edges}] % \begin{forest} % for tree={grow'=0,draw}, % forked edges, % [/ % [home % [saso % [Download] % [TeX] % ] % [alja] % [joe] % ] % [usr % [bin] % [share] % ] % ] % \end{forest} % \end{forestexample} % % See how growth direction based anchors \indexex{anchor>children} and \indexex{anchor>parent} are % used in the definition below to easily take care of arbitrary \index{grow} and % \index{rotate}. % \begin{macrocode} \forestset{ declare dimen={fork sep}{0.5em}, forked edge'/.style={ edge={rotate/.option=!parent.grow}, edge path'={(!u.parent anchor) -- ++(\forestoption{fork sep},0) |- (.child anchor)}, }, forked edge/.style={ on invalid={fake}{!parent.parent anchor=children}, child anchor=parent, forked edge', }, forked edges/.style={for nodewalk={#1}{forked edge}}, forked edges/.default=tree, } % \end{macrocode} % % \begin{syntax} % \indexitem{node key>folder} The children of the node are drawn like folders. % % All growth directions are supported (well, cardinal directions work perfectly; the others await % the sensitivity of packing to \index{edge path}), as well as node rotation and \index{reversed} % order of children. % % The outlook of the folder can be influenced by setting standard \foRest;'s options \index{l sep} % and \index{s sep} any time before packing, or \index{option>l} and \index{option>s} after % packing. Setting \index{option>l} and \index{option>s} before packing will have no influence on % the layout of the tree. % % \begin{syntax} % \indexitem(.45em){register>folder indent}|=|\meta{dimen} % % Specifies the shift of the parent's side of the edge in the \index{forest cs>l}-direction. % \end{syntax} % % \end{syntax} % % \begin{forestexample}[index={for step,tree,grow',folder}] % \begin{forest} % for tree={grow'=0,~folder~,draw} % [/ % [home % [saso % [Download] % [TeX] % ] % [alja] % [joe] % ] % [usr % [bin] % [share] % ] % ] % \end{forest} % \end{forestexample} % \begin{macrocode} \forestset{ declare dimen register=folder indent, folder indent=.45em, folder/.style={ parent anchor=-children last, anchor=parent first, calign=child, calign primary child=1, for children={ child anchor=parent, anchor=parent first, edge={rotate/.option=!parent.grow}, edge path'/.expanded={ ([xshift=\forestregister{folder indent}]!u.parent anchor) |- (.child anchor) }, }, after packing node={ if n children=0{}{ tempdiml=l_sep()-l("!1"), tempdims={-abs(max_s("","")-min_s("",""))-s_sep()}, for children={ l+=tempdiml, s+=tempdims()*(reversed()-0.5)*2, }, }, }, } } % \end{macrocode} %\iffalse % %\fi % \forestset{every index end/.style={}} % \endinput % Local Variables: % mode: doctex % TeX-command-default: "sty" % fill-column: 100 % TeX-master: "forest" % End: