昨天,我对 TeX 文档的布局做了一些更改。直到我打开文件.sty
并修改了部分代码后,我才完成这些更改。我确信这不是最好的主意。原因之一是,在软件包更新后,我将不得不再次(一次又一次)修改文件。
另一种方法是创建该.sty
文件的我自己的版本并调用它而不是原始版本,但这也可能不是最好的主意。(再次:至少更新反对它)
如何通过向当地的文件(例如我的.tex
序言)而不是改变全球的文件(如包.sty
文件)?
我想更改以下几行ledmac.sty
:
\def\printlines#1|#2|#3|#4|#5|#6|#7|{\begingroup
\setprintlines{#1}{#2}{#3}{#4}{#5}{#6}%
\ifl@d@pnum #1\fullstop\fi
\ifledplinenum \linenumrep{#2}\else \symplinenum\fi %% #2 into: \arabtxt{\n{#2}}
\ifl@d@ssub \fullstop \sublinenumrep{#3}\fi
\ifl@d@dash \endashchar\fi
\ifl@d@pnum #4\fullstop\fi
\ifl@d@elin \linenumrep{#5}\fi
\ifl@d@esl \ifl@d@elin \fullstop\fi \sublinenumrep{#6}\fi
\endgroup}
第二件事是一行ledpar.sty
:
\newcommand*{\l@dlinenumR}{%
\numlabfont\linenumrepR{\line@numR}\Rlineflag% %% numlabfont into: numlabfontR
\ifsublines@
\ifnum\subline@num>\z@
\unskip\fullstop\sublinenumrepR{\subline@numR}%
\fi
\fi}
(在后一种情况下,仅添加\renewcommand
修改后的代码是不起作用的。)
答案1
许可注意事项
该ledmac
软件包以及 LaTeX 世界中的许多其他软件包均在LaTeX 项目公共许可证(LPPL)。这意味着你可以使用代码,也可以修改它,但修改时必须遵守一些规则。最重要的一条是
如果您不是作品的当前维护者,您可以分发衍生作品,前提是作品的每个组成部分都满足以下条件,除非该组成部分在版权声明中明确说明不受该条件限制。只有当前维护者才可以在作品的组成部分中添加此类豁免声明。
(a)如果在与基础解释器一起使用时,本衍生作品的某个组件能够直接替换作品的某个组件,那么,在与该基础解释器交互使用时,无论作品的此组件如何向用户标识自己,本衍生作品的替换组件在与该基础解释器交互使用时,也应向用户清楚、明确地标识自己是此组件的修改版本。
简而言之,这意味着无论何时进行更改,您都会以一种方式进行更改,以便其他任何使用您修改过的文件的用户都能立即知道它已被修改(而不仅仅是通过在包内的一些注释中进行搜索)。在 TeX 世界中,典型的做法是简单地重命名文件,因为名称是界面的一部分,例如,你说\usepackage{ledmac}
。
LPPL 提出这一要求的原因是 LaTeX 是一种用于交流的语言,而不仅仅是一种排版系统,为了能够进行交流,双方必须对该语言有共同的理解。有关更多信息,请参阅关于 LPPL 历史的文章出现在 TUGboat 中。
因此,LPPL 是为了保护您和社区,即使您从未打算分发您的修改,最好也不要违反 LPPL。毕竟您的更改可能会轻易泄露(这是现实情况)。LPPL 在此提出以下建议:
最好不要修改作品的某个组件,即使是为了您个人使用,也不要同时满足上述分发修改后组件的条件。尽管您可能希望永远不分发此类修改,但这种情况经常会意外发生 — 您可能忘记了您已经修改了该组件;或者在允许其他人访问修改版本时您可能没有意识到您这样分发它并违反了本许可证的条件,这可能会产生法律影响,更糟的是,会给社区带来问题。因此,通常最符合您的利益的是让您的作品副本与公开的副本保持一致。许多作品都提供了在不改变其任何许可组件的情况下控制作品行为的方法。
修改方法
已经讨论了修改包的合适方法,但为了将所有内容放在一个答案中,这里是从我的角度进行快速总结:
一次改变
仅针对单个文档进行的修改最好放在文档的序言中。在大多数情况下,您必须用\makeatletter
和包围您的重新定义\makeatother
,以便能够访问或修改@
名称中包含符号的命令。
重新定义的一个可能的替代方法是使用\patchcmd
包中的代码etoolbox
,该包允许您用其他代码替换命令的某些代码,例如来自您的问题
\usepackage{etoolbox}
\makeatletter
\patchcmd{\l@dlinenumR}{\numlabfont}{\numlabfontR}%
{\typeout{*** SUCCESS ***}}%
{\ERRORpatchfailed} % stop with error (undefined csname) if patch fails
\makeatother
您仍然需要,\makeatletter
因为您修改了名称中的命令@
,但您将修改限制在必要的位置,这通常是有帮助的。
旨在重复用于多个文档的修改
在这种情况下,使用文档前言不一定是个好主意,因为这意味着你要一遍又一遍地重复相同的代码。在这种情况下,最好的解决方案是将修改放入一个小包中,并在主包之后加载它(当然,除非包本身没有提供一些配置可能性,而有些包有)。
请注意,如果您使用包方法,那么请执行不是内部使用\makeatletter
:在样式文件中,该@
符号自动可用于命令名称。
Bug修复
最后,如果您的更改更多的是错误修复而不是配置,请联系作者提供软件包的官方更新。当然,只要错误仍然存在,您就需要使用上述其他方法之一。在这种情况下,我总是建议使用\patchcmd
序言中的解决方案,因为这样如果软件包最终发生变化(因为您的补丁失败),您将自动收到警报。
答案2
每当你要执行当地的重新定义,如果修改很小,最好在.tex
序言中执行此修改;如果修改很大或很全面,最好在本地.sty
文件中执行此修改。这种划分使解码更容易,并使主要.tex
源保持干净。
由于您的两个示例更改似乎很小,我建议只需将代码添加到.tex
源序言中。以下是针对您的情况的指导原则:
- 第一个例子:包含此代码,按原样并用
\makeatletter
...包装\makeatother
,后加载\usepackage{ledmac}
。否则ledmac
将覆盖您的定义; - 第二个示例:包含此代码,用
\renewcommand
代替并用...\newcommand
包裹,\makeatletter
\makeatother
后加载\usepackage{ledpar}
(原因与上述类似)。使用包装器的原因(在两种情况下)是因为@
被区别对待并且通常不构成控制序列的一部分(因为它不是字母,而控制序列通常仅由字母组成)。包装器消除了这一限制。
答案3
只需完成所有操作(Frank 的修改旨在在多个文档上重复使用)。如果您想在新文档中重复使用更改并遵守 LPPL 许可要求,您可以制作自己的修改.sty
文件,然后ledmac-mod.sty
将ledpar-mod.sty
它们保存到本地 texmf 树中的正确位置并更新您的 Tex 文件名数据库。之后,您可以将它们用作
\usepackage[<options]{ledmac-mod}
\usepackage[<options]{ledpar-mod}
ledmac-mod.sty
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{ledmac-mod}[2012/03/09 v1.0 Modified ledmac (Clint Eastwood)]
\DeclareOption*{\PassOptionsToPackage{\CurrentOption}{ledmac}}
\ProcessOptions\relax
\RequirePackage{ledmac}
\def\printlines#1|#2|#3|#4|#5|#6|#7|{%
\begingroup
\setprintlines{#1}{#2}{#3}{#4}{#5}{#6}%
\ifl@d@pnum #1\fullstop\fi
\ifledplinenum \linenumrep{#2}\else \symplinenum\fi %% #2 into: \arabtxt{\n{#2}}
\ifl@d@ssub \fullstop \sublinenumrep{#3}\fi
\ifl@d@dash \endashchar\fi
\ifl@d@pnum #4\fullstop\fi
\ifl@d@elin \linenumrep{#5}\fi
\ifl@d@esl \ifl@d@elin \fullstop\fi \sublinenumrep{#6}\fi
\endgroup}
\endinput
ledpar-mod.sty
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{ledpar-mod}[2012/03/09 v1.0 Modified ledpar (Clint Eastwood)]
\DeclareOption*{\PassOptionsToPackage{\CurrentOption}{ledpar}}
\ProcessOptions\relax
\RequirePackage{ledpar}
\renewcommand*{\l@dlinenumR}{%
\numlabfont\linenumrepR{\line@numR}\Rlineflag% %% numlabfont into: numlabfontR
\ifsublines@
\ifnum\subline@num>\z@
\unskip\fullstop\sublinenumrepR{\subline@numR}%
\fi
\fi}
\endgroup}
\endinput