I am trying to create a few simple macros for B-Trees and one of these macros is supposed to create a multipart node tikz based on the number of arguments it gets. Therefore I used the g
argument specifier from xparse though tikz always shows the following error:
Package tikz Error: Giving up on this path. Did you forget a semicolon?. ;
Package tikz Error: Giving up on this path. Did you forget a semicolon?. ;
Undefined control sequence. ;
The macro works flawlessly when replacing the g
s with m
s though then it becomes impossible to differentiate between a multipart node with e.g. 4 segments two of which are empty and an 2 segment node which are all filled.
A kinda minimal working example:
\documentclass{article}
\usepackage{tikz}
\usepackage{xparse}
\usetikzlibrary{trees,shapes.multipart}
\NewDocumentCommand\test{m g}{
{#1 \IfValueT{#2}{B}}
}
\NewDocumentCommand\leaf{m m}{
node[leaf]{#1 \nodepart{two} #2}
}
\NewDocumentCommand\leafOptional{m g}{
node[leaf]{#1 \IfValueT{#2}{\nodepart{two} #2}}
}
\tikzset{
btree/.style={
nodes={rectangle split,rectangle split horizontal=true,draw},
leaf/.style={
rectangle split allocate boxes=2,
rectangle split parts=2,
rectangle split part fill=white}
},
}
\begin{document}
\test{a}\\ % this works
\test{a}{something}\\ % as does this
\begin{tikzpicture}[btree]
\node (root) {test}
child {\leaf{5}{}}
child {\leafOptional{5}} % however this fails
child {\leafOptional{5}{}} % and so does this
child {node[leaf]{1}}
;
\end{tikzpicture}
\end{document}
I already found this question TikZ path doesn't work with xparse generated macro which seems to be a similar problem though I am unable to use \DeclareDocumentCommand
as it does not allow one to use the g
/G
argument specifier
Addedum
Following @PhelypeOleinik's comment I changed the code to use \NewExpandableDocumentCommand
and the argument specifier o o o m
however when passing more than one optional argument this leads to tikz not determining the correct node bounding box and tikz draws the edge into the actual node shape.
\documentclass{article}
\usepackage{tikz}
\usepackage{xparse}
\usetikzlibrary{trees,shapes.multipart}
\NewExpandableDocumentCommand\leaf{o o o m}{
node[leaf]{
6\nodepart{two}8\nodepart{three}2\nodepart{four}#4
}
}
\tikzset{
btree/.style={
nodes={rectangle split,rectangle split horizontal=true,draw},
level 1/.style={sibling distance=\textwidth/4},
leaf/.style={rectangle split allocate boxes=4}
},
}
\begin{document}
\begin{tikzpicture}[btree]
\node (root) {test}
child {\leaf{5}}
child {\leaf[a]{5}}
child {\leaf[a][b]{5}}
child {\leaf[a][b][c]{5}}
;
\end{tikzpicture}
\end{document}
Adding leaf/.style={..., rectangle split part fill=white}
seems to fix the symptoms though not the root cause - any possibile solution to use this with transparent nodes?
g
: it's deprecated and it's bad practice. Apparently commands there need to be expandable, so you can use\NewExpandableDocumentCommand\leafOptional{o m}{node[leaf]{#2 \IfValueT{#1}{\nodepart{two} #1}}}
and then use\leafOptional{5}
or\leafOptional[opt]{5}
o m
and it worked for one and two part nodes thougho o m
and more optional arguments seemed to lead to tikz not correctly recognizing the resulting box in drawing the edge into the center of the node overlaying it.