我正在一个包中工作并且想要创建库,例如tikz
及其usetikzlibrary
。
但是,当我@
在私有宏名中使用时,当一个库使用另一个宏名时我会出现错误。
这是我的 MWE(说明如下):
\documentclass[12pt,a4paper]{article}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage[brazilian]{babel}
% hack to make filecontents overwrite
\makeatletter
\let\oldfilec@ntents\filec@ntents
\gdef\filec@ntents{\filec@ntents@overwrite\oldfilec@ntents}
\makeatother
\begin{filecontents}{libraryone.tex}
\def\@libonevar{lib 1 variable with @}
\def\libonefunction{\@libonevar}
\def\libonevar{lib 1 variable without @}
\def\liboneotherfunction{\libonevar}
\end{filecontents}
\begin{filecontents}{librarytwo.tex}
\loadlibrary{libraryone}
\def\@libtwovar{lib 2 variable}
\def\libtwofunction{\libonefunction}
\def\libtwootherfunction{\liboneotherfunction}
\end{filecontents}
\begin{filecontents}{mypackage.sty}
\def\@pkgvar{pkg variable}
\def\pkgfuncion{\@pkgvar}
\newcommand{\loadlibrary}[1]{
\input{#1}
}
\end{filecontents}
\usepackage{mypackage}
\begin{document}
From package: \pkgfuncion
\loadlibrary{libraryone}
From library one: \libonefunction\ and \liboneotherfunction
\loadlibrary{librarytwo}
From library one: \libonefunction\ and \liboneotherfunction % \libonefunction fails!
\end{document}
如果我加载libraryone
,我能够同时使用\libonefunction
和liboneotherfunction
。但是,如果我加载librarytwo
,加载的libraryone
会\liboneotherfunctions
停止工作,并显示类似“@ 的使用与其定义不符。来自库一:\libonefunction。”\liboneotherfunction
一直运转良好。
如果我删除所有@
问题就会消失,现在,我真的更喜欢继续使用它@
来处理私人事务。
我读过类似这样的文章何时应使用 \input 和 \include?但我没有发现@
其中存在宏名的问题。
有没有什么办法可以避免这个问题?
编辑
即使在@egreg 和@Ulrich Diez 回答之后,我的问题仍然存在。
这是我当前的实际代码(由于我认为\IfFileExists
可能存在另一个问题,因此使用了 TeX 原语):
% usedslibrary: load libraries
\newcommand{\ds@loadlibrary}[1]{%
\ifcsname ds@library#1loaded\endcsname%
%\PackageWarning{dsdraw}{Library '#1' already loaded.}%
\else%
\openin15={#1.code.tex}%
\ifeof15%
\PackageWarning{dsdraw}{Couldn't find any library named '#1'.}%
\else%
\closein15%
\makeatletter%
\input{#1.code.tex}%
%\makeatother%
\expandafter\def\csname ds@library#1loaded\endcsname{defined}%
\fi%
\fi%
}
答案1
只需将 -command 嵌套在..\input
之间:\makeatletter
\makeatother
\documentclass[12pt,a4paper]{article}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage[brazilian]{babel}
\begin{filecontents*}[overwrite,nosearch]{libraryone.tex}
\def\@libonevar{lib 1 variable with @}%
\def\libonefunction{\@libonevar}%
\def\libonevar{lib 1 variable without @}%
\def\liboneotherfunction{\libonevar}%
\end{filecontents*}
\begin{filecontents*}[overwrite,nosearch]{librarytwo.tex}
\loadlibrary{libraryone}%
\def\@libtwovar{lib 2 variable}%
\def\libtwofunction{\libonefunction}%
\def\libtwootherfunction{\liboneotherfunction}%
\end{filecontents*}
\begin{filecontents*}[overwrite,nosearch]{mypackage.sty}
\def\@pkgvar{pkg variable}%
\def\pkgfuncion{\@pkgvar}%
\newcommand{\loadlibrary}[1]{%
\makeatletter\input{#1}\makeatother %<-------
}%
\end{filecontents*}
\usepackage{mypackage}
\begin{document}
From package: \pkgfuncion
\loadlibrary{libraryone}
From library one: \libonefunction\ and \liboneotherfunction
\loadlibrary{librarytwo}
From library one: \libtwofunction\ and \libtwootherfunction
\end{document}
答案2
当 TeX 处理时\usepackage{mypackage}
,它将执行以下\makeatletter
操作\input{mypackage.sty}
:
这确实不是发生\input
。由于\loadlibrary{libraryone}
只是这样做\input{libraryone}
,TeX 将解释第一条指令
\def\@libonevar{lib 1 variable with @}
作为控制符号的定义\@
。此定义需要紧接着\@
。libonevar
接下来\libonefunction
定义为 扩展为\@libonevar
。
当您也执行 时\loadlibrary{librarytwo}
,\@
会得到不同的定义,现在它要求libtwovar
跟在它后面。当您现在尝试 时 \libonefunction
,TeX 会将其替换为\@libonevar
并想要扩展\@
,而 后面跟着错误的标记。
解决方案:如果您的库文件想要在@
其中定义命令名称,请执行
\newcommand{\loadlibrary}[1]{%
\makeatletter
\input{#1}%
\makeatother
}
顺便说一句,进行覆盖的 hackfilecontents
不再是必要的;只需调用
\begin{filecontents}[overwrite]{<filename>}
完整示例。
\documentclass[12pt,a4paper]{article}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage[brazilian]{babel}
\begin{filecontents}[overwrite]{libraryone.tex}
\def\@libonevar{lib 1 variable with @}
\def\libonefunction{\@libonevar}
\def\libonevar{lib 1 variable without @}
\def\liboneotherfunction{\libonevar}
\end{filecontents}
\begin{filecontents}[overwrite]{librarytwo.tex}
\loadlibrary{libraryone}
\def\@libtwovar{lib 2 variable}
\def\libtwofunction{\libonefunction}
\def\libtwootherfunction{\liboneotherfunction}
\end{filecontents}
\begin{filecontents}[overwrite]{mypackage.sty}
\def\@pkgvar{pkg variable}
\def\pkgfuncion{\@pkgvar}
\newcommand{\loadlibrary}[1]{%
\makeatletter
\input{#1}%
\makeatother
}
\end{filecontents}
\usepackage{mypackage}
\begin{document}
From package: \pkgfuncion
\loadlibrary{libraryone}
From library one: \libonefunction\ and \liboneotherfunction
\loadlibrary{librarytwo}
From library one: \libonefunction\ and \liboneotherfunction % \libonefunction fails!
\end{document}