
Я хочу создать бинарное дерево, где в каждом узле я буду вводить пару (например, $(8,16)$ или $(S_2,M_2)$), а второй компонент будет окрашен в красный цвет. Как использовать макрос \forestset
(излесной пакет) сделать это автоматически, так что когда я пишу дерево, я могу писать в узле eg {{S_2}{M_2}}}
(или что-то подобное) вместо {$(S_2,{\color{red} M_2})$ }
? В частности, как мне сделать так, чтобы содержимое каждого узла автоматически находилось в математическом режиме, без необходимости писать $...$
каждый раз?
А еще лучше, если макрос также это укажет,еслиЯ ввожу 3 аргумента, затем третий окрашивается в синий цвет, чтобы я мог написать eg {{S_2}{M_2}{A_2}}
(или что-то подобное) вместо{$(S_2,{\red M_2},{\color{blue} A_2})$ }
решение1
Чтобы узел был набран в математическом режиме, используйте ключ math content
, например:
\documentclass{article}
\usepackage{forest}
\begin{document}
\begin{forest}
[2^{42}, math content
[A]
[A, math content]
]
\end{forest}
\end{document}
На самом деле, math content
это просто оболочка для content format
. Она обволакивает \ensuremath
содержимое при его наборе. Но ее можно использовать для украшения содержимого (без его изменения) любым способом:
\documentclass{article}
\usepackage{forest}
\forestset{
quote/.style={
content format={``\forestoption{content}''}
},
bold/.style={
content format={\noexpand\textbf{\forestoption{content}}}
},
}
\begin{document}
\begin{forest}
[A
[B, quote]
[C, bold]
]
\end{forest}
\end{document}
Иметьвсеузлы в дереве автоматически набираются в математическом режиме, используются math content
внутри пространственного пропагатора for tree
. for tree
на самом деле это немного неправильное название, так как оно фактически применяет заданные параметры ко всем узлам всубдерево, но, ах, ну... оно соответствует своему названию, если используется в корневом узле или в преамбуле дерева, как показано ниже.
\documentclass{article}
\usepackage{forest}
\begin{document}
\begin{forest}
for tree={math content}
[S_1
[S_2]
[S_3]
]
\end{forest}
\end{document}
Заставить разные вещи происходить с разными частями контента немного сложнее, но Forest оснащен всем необходимым для этой работы. Семейство split
ключей берет некоторый текст, разделяет его по заданному разделителю и применяет (возможно, разные) ключи к каждой части. Я проиллюстрирую это через минуту, но позвольте мне сначала перечислить членов семейства: split
применяется к заданному тексту; split option
берет текст из некоторого (лесного) параметра; и split register
берет текст из некоторого (лесного) регистра. Ниже мы будем использовать split option
, и он будет действовать на параметр content
, где хранится содержимое узла (то, что находится между скобками до первой запятой).
А теперь, без лишних слов, решение проблемы ОП.
\documentclass{article}
\usepackage{forest}
\forestset{
1st/.style={content'={#1}},
2nd/.style={content+'={,{\color{red}#1}}},
rest/.style={content+'={,{\color{blue}#1}}},
autocolored math/.style={
delay={
for tree={
math content,
split option={content}{;}{1st,2nd,rest},
content={(##1)},
}
}
}
}
\begin{document}
\begin{forest} autocolored math
[S_1;M_1
[S_2;M_2]
[S_3;M_3;A_3
[S_4;M_4;A_4]
[S_5;M_5;A_5;B_5]
]
]
\end{forest}
\end{document}
Ядром стиля, autocolored math
конечно, является вызов split option
. Он берет текст из option content
(первый аргумент) и разбивает его по вхождениям ;
(второй аргумент). Пока все хорошо. А что насчет третьего аргумента, 1st,2nd,rest
?
Третий аргумент перечисляет некоторые имена стилей. Первый стиль ( 1st
) получит первую часть содержимого в качестве своего аргумента ( S_1
, S_2
, и т.д.). Второй стиль ( 2nd
) получит первую часть содержимого в качестве своего аргумента ( M_1
, M_2
, и т.д.). Третий стиль ( rest
) получит ... но подождите, что, если нет третьего аргумента? Нет проблем: в таком случае (1 и 2 в дереве) rest
никогда не вызывается. И как следует из названия rest
, аргументов может быть больше трех, и последний стиль будет вызываться для каждого дополнительного аргумента (5 в дереве). (Кстати, имена стилей, очевидно, могут быть любыми.)
Несколько слов о content
(см. ниже split option
) против content'
(в определении 1st
). content
Ключ немного особенный. content=...
"автооборачивает" значение опции content
, т. е. ##1
в content={(##1)}
ссылается на текущее значение опции content
(а затем заключает его в скобки). (Удвоение ##
присутствует, потому что мы находимся в определении autocolored math
.) content'
ведет себя "нормально", поэтому в 1st/.style={content'={#1}}
, #1
ссылается на аргумент 1st
(в нашем случае это будет первая часть выражения split).
content+
добавляет заданный текст к текущему значению опции. Ну, в приведенном выше коде я на самом деле использовал версию без автопереноса content+'
.
Наконец, обратите внимание, что я поставил math content
выше split option
, хотя можно было бы ожидать, что он должен быть после content={(##1)}
. Это было сделано просто для того, чтобы продемонстрировать, что это будет работать где угодно (в пределах for tree
). Дело в том, что это вообще math content
не влияет на значение option . Оно скорее определяет (через ), как это значение используется.content
content format
И последнее, но не менее важное: почему delay
? По умолчанию параметры родителя обрабатываются до параметров дочерних элементов; это включает в себя установку содержимого узла с помощью [...]
. Так что autocolored math
, который происходит в корневом узле (ну, в преамбуле, которая немного отличается в принципе ...), применяется до установки содержимого любого узла! Если бы не было delay
, то и разделять было бы нечего.