我正在为全家人制作日历,但我遇到了一个问题自动化这个过程。我正在使用calendar
tikz 库。
我需要在日历中加入月相。我可以用以下代码来实现
\documentclass{scrartcl}
\usepackage{mathabx}
\usepackage{tikz}
\usetikzlibrary{calendar}
\usepackage{etoolbox}
\newcount\mooncounter
\mooncounter=1
\def\moon{%
\ifnum\mooncounter=1%
$\newmoon$\global\advance\mooncounter by 1\else
\ifnum\mooncounter=2%
$\rightmoon$\global\advance\mooncounter by 1\else
\ifnum\mooncounter=3%
$\fullmoon$\global\advance\mooncounter by 1\else
\ifnum\mooncounter=4%
$\leftmoon$\global\mooncounter=1
\fi%
\fi%
\fi%
\fi%
}
\begin{document}
\begin{tikzpicture}
\calendar [
dates = 2012-12-1 to 2012-12-last,
week list,
day xshift = 3em
] if (equals = 2012-12-27,
equals = 2012-12-2,
equals = 2012-12-7,
equals = 2012-12-6,
equals = 2012-12-8,
equals = 2012-12-9,
equals = 2012-12-12) [day text = \moon\%d-];
\end{tikzpicture}
\end{document}
首先,我不知道它是如何\newcount
工作的(只是从其他网站复制了代码),但我使用它,因为我找不到使用\newcounter
或执行它的方法\pgfmathtruncatemacro
(我无法让它们在 中工作\calendar
)。这就是为什么我有第一个问题:为什么命令在 之外不起作用\calendar
?我的意思是。如果我写
\begin{document}
\moon \moon
\end{document}
它没有像我预期的那样工作。我希望它是循环的,但它显示了两个连续的\newmoon
s。
无论如何,我希望能够输入有月亮的日子,然后让 LaTeX 完成剩下的工作。
我尝试过这个:
\newcommand*{\listofmoons}[1]{%
\edef\listmoons{#1}%
\def\moons{}%
\foreach \l in \listmoons {%
\xappto\moons{if (equals = 2012-12-\l) [day text=\moon\%d-]}
}%
}
然后使用
\begin{tikzpicture}
\listofmoons{2,6,7,8,9,12,27}
\calendar [
dates = 2012-12-1 to 2012-12-last,
week list,
day xshift = 3em
] \moons;
\end{tikzpicture}
但它不起作用。它再次无法正确循环(这就是我怀疑的原因\newcount
)。
实现此目的的最佳方法是什么? 可能是另一种完全不同的方法?
顺便问一下,有没有关于日历的大型问题/社区 wiki?也许开一个会比较好。
答案1
\ifcase
我用一个简单的测试替换了你的 if-if-if-if 结构。\moon
现在工作得很好。虽然实际问题是另一个。计数器分配\global\advance\<counter> by 1
应该以 结束\relax
。这也适用于\ifnum
但在这种情况下,它不是必需的,因为数学模式会立即引入。如果没有 TeX\relax
可能会找到更多的数字并吞下比它应该吞下的内容更多。有趣的是,\else
在下一行放入 也有效。
通过随后恢复原始宏(同一行上没有\relax
/ )并输出一整行来测试以下代码。\else
\moon \moon \moon \moon \moon \moon
\def\moon{%
\ifnum\mooncounter=1%
$\newmoon$\global\advance\mooncounter by 1
\else
\ifnum\mooncounter=2%
$\rightmoon$\global\advance\mooncounter by 1\relax\else
\ifnum\mooncounter=3%
$\fullmoon$\global\advance\mooncounter by 1
\else
\ifnum\mooncounter=4%
$\leftmoon$\global\mooncounter=1
\fi%
\fi%
\fi%
\fi%
}
无论如何,在这种情况下,我发现一个\ifcase
更清晰的结构:
\def\moon{%
\global\advance\mooncounter by 1\relax% needs \mooncounter to start with -1
\ifcase\mooncounter $\newmoon$% = 0
\or $\rightmoon$% = 1
\or $\fullmoon$% = 2
\or $\leftmoon$\global\mooncounter=-1\relax% = 3
\fi%
}
另外,我\moon
在 for-each 循环中添加了一个前缀\noexpand
,以便在实际排版时首先进行扩展。
代码
\documentclass{scrartcl}
\usepackage{mathabx}
\usepackage{tikz}
\usetikzlibrary{calendar}
\usepackage{etoolbox}
\newcount\mooncounter
\def\moonreset{\global\mooncounter=-1\relax}
\moonreset
\def\moon{%
\global\advance\mooncounter by 1\relax%
\ifcase\mooncounter $\newmoon$%
\or $\rightmoon$%
\or $\fullmoon$%
\or $\leftmoon$\global\mooncounter=-1\relax%
\fi%
}
\newcommand*{\listofmoons}[1]{%
\edef\listmoons{#1}%
\def\moons{}%
\foreach \l in \listmoons {%
\xappto\moons{if (equals = 2012-12-\l) [day text=\noexpand\moon\%d-]}
}%
}
\begin{document}
\moon \moon
\moonreset
\begin{tikzpicture}
\calendar [
dates = 2012-12-1 to 2012-12-last,
week list,
day xshift = 3em
] if (equals = 2012-12-27,
equals = 2012-12-2,
equals = 2012-12-7,
equals = 2012-12-6,
equals = 2012-12-8,
equals = 2012-12-9,
equals = 2012-12-12) [day text = \moon\%d-];
\end{tikzpicture}
\moonreset
\begin{tikzpicture}
\listofmoons{2,6,7,8,9,12,27}
\calendar [
dates = 2012-12-1 to 2012-12-last,
week list,
day xshift = 3em
] \moons;
\end{tikzpicture}
\end{document}