我正在編寫一份很長的文檔,為了讓我的生活更輕鬆,我喜歡定義用作巨集的數量,這樣當它們發生變化時我只需在一個地方更新它們。對我來說,在我的文件中與它們最相關的部分中定義這些是有意義的。然而,有時我想在其他章節中使用這些命令,有時甚至在前面的章節中。
因此,我想添加一個宏,它將命令的定義寫入乳膠.aux
檔案中,以便命令一旦定義就可以在任何地方使用。到目前為止我已經得到了這個:
% Make a command which defines a macro with \providecommand but in the aux file,
% so it's accessible to all other chapters
\makeatletter
\newcommand{\doccommand}[2]{%
\protected@write\@auxout{}{\protect\providecommand\protect#1{#2}}%
}
\makeatother
這會將以下內容放入 aux 檔案中
\providecommand \tester {123}
對於這樣的章節:
\chapter{Test chapter}
This is a test chapter!
Tester is \tester{}.
\doccommand{\tester}{123}
不幸的是,它不起作用。即使在測試章節中使用命令也會給我“未定義的控制序列”,在其他章節中也是如此。
最初我認為這可能與文件中最終出現的空格有關.aux
,但我手動刪除了它們並使用\includeonly{a_different_chapter}
仍然給出相同錯誤的編譯。
是什麼賦予了?
更新:
感謝這裡的所有幫助,我得到了這個工作並將其寫入一個小包中。如果您有興趣,可以在 CTAN 上找到它:https://ctan.org/pkg/globalvals
答案1
我會使用不同的策略:使用包裝器命令,而不是直接定義巨集。
\documentclass{article}
\makeatletter
\newcommand{\usevalue}[1]{%
\ifcsname usevalue@#1\endcsname
\csname usevalue@#1\endcsname
\else
??%
\fi
}
\newcommand{\definevalue}[2]{%
\write\@auxout{%
\unexpanded{\global\@namedef{usevalue@#1}{#2}}%
}
}
\makeatother
\begin{document}
Something with \usevalue{tester}.
Something else.
Now we can define \texttt{tester} and use again it: \usevalue{tester}.
\definevalue{tester}{42}
\end{document}
第一次運行的輸出
第二次運行的輸出
答案2
你可以寫
\makeatletter
\newcommand{\doccommand}[2]{%
\immediate\write\@auxout{\gdef\noexpand#1{\unexpanded{#2}}}%
\gdef#1{#2}%
}
\makeatother
這將進行全域定義而不擴展替換文字。我添加了一個額外的直接命令,\gdef
以便可以在不重新運行 TeX 的情況下使用該命令。
但這不是一個好主意:如果您在定義該命令之前從未使用過該命令,那麼在 aux 檔案中定義它是沒有用的。如果您在定義命令之前使用該命令,LaTeX 永遠不會到達您寫入 aux 文件條目的位置。
因此,只有在定義但未使用指令的情況下執行一次 TeX 後才能使用該指令。如果您刪除了 aux 文件,您的文件就會損壞。如果您只包含不同的章節,則不會寫入輔助文件條目,因此您的文件已損壞。
相反,您可以使用前言中包含的定義來建立一個單獨的檔案。雖然工作量更大,但文件更加穩定。
答案3
感謝@egreg 提供了一個聰明的方法。如果在同一個文檔中進行了兩個定義,我對他的程式碼進行了輕微的修改以添加錯誤訊息:
\documentclass{article}
\usepackage{siunitx}
\makeatletter
\newcommand{\useVal}[1]{%
\ifcsname useVal@#1\endcsname
\csname useVal@#1\endcsname
\else
??%
\fi
}
\newcommand{\defVal}[2]{%
\ifcsname useVal@#1@defined\endcsname
\PackageError{useVal}{Value "#1" already defined}{}
\else
\write\@auxout{%
\unexpanded{\global\@namedef{useVal@#1}{#2}}%
}
\global\@namedef{useVal@#1@defined}{}
\fi
}
\makeatother
\begin{document}
Testval is \useVal{testVal}.
Now defining testval...
\defVal{testVal}{\SI{123}{\meter}}
Now it's \useVal{testVal}.
% This would throw an error:
% \defVal{testVal}{Not this please!}
\end{document}