\cslet{} 内的环境行为有所不同

\cslet{} 内的环境行为有所不同

请向下滚动查看编辑内容和最新版本


这不是一个好标题,但我没有想出更好的标题。

我有一个应该像这样使用的环境(看起来必须是这样的):

\begin{Lied}{A}{1}
\setAuthor{Author1}
Content A1
\end{Lied}
\begin{Lied}{A}{2}
\setAuthor{Author2}
Conten A2
\end{Lied}
\begin{Lied}{B}{1}
\setAuthor{Author3}
Content B1
\end{Lied}

我想通过命令调用环境的内容,以便将它们放入文本中。存储作者、来源和作曲家等内容。这些内容应根据样式围绕内容放置。因此,我可以使用命令调用环境的内容,它们的外观取决于定义的样式。

内容应该这样调用\csuse{lied;A;1}:例如,应该插入作者,然后插入 Lied-A-1 的内容。

因此我可以用命令调用预定义数据库的内容。

这是一个运行良好的例子:

\documentclass[12pt,a4paper]{article}
\usepackage[utf8]{inputenc}
\usepackage[german]{babel}
\usepackage{environ}
\usepackage{etoolbox}

\begin{document}

\NewEnviron{Lied}[2]{{
%to save a string
\def\Author{leer}
%to change the string
\def\setAuthor##1{##1}
\long\def\temp{} 
\long\def\test{{\Author \temp}} 
\let\temp\BODY 
%"write" the content of setAuthor to Author
\let\Author\setAuthor
%make output
\test
}}

\begin{Lied}{A}{1}
\setAuthor{Maestro}
Hallo

Absatz1
\end{Lied}

\csuse{lied;A;1}

Absatz2\\
Zeile

Absatz3

\end{document}

它给出以下输出:

输出.pdf

如果我\cslet这样使用,就会出现错误:

\documentclass[12pt,a4paper]{article}
\usepackage[utf8]{inputenc}
\usepackage[german]{babel}
\usepackage{environ}
\usepackage{etoolbox}

\begin{document}

\NewEnviron{Lied}[2]{{
\def\Author{leer}
\def\setAuthor##1{##1}
\long\def\temp{} 
\long\def\test{{\Author \temp}} 
\let\temp\BODY 
\let\Author\setAuthor
\global\cslet{lied;#1;#2}\test
}}

\begin{Lied}{A}{1}
\setAuthor{Maestro}
Hallo

Absatz1
\end{Lied}

\csuse{lied;A;1}

Absatz2\\
Zeile

Absatz3

\end{document}

如果我只使用

\NewEnviron{Lied}[2]{\global\cslet{lied;#1;#2}\BODY}

它工作正常,但没有\Author-part


编辑:

以下代码已简化,以更清楚地显示目的。一般来说,它应该在稍后发布的包中使用。如果它有效,可以以非常简单的方式生成歌本。从这些歌本中,可以通过一个简单的命令将歌曲插入现有文档中。样式应描述它们在导入时的外观。


以下代码可以正常工作,并且 100% 按照应有的方式工作,但如果我\\在环境中使用,它就会中断:

\documentclass[12pt,a4paper]{article}
\usepackage[utf8]{inputenc}
\usepackage[german]{babel}
\usepackage{environ}
\usepackage{etoolbox}


%%%The following code defines my default style. Right now, it only contains only the author
\def\stylehead{\Author}
\def\stylefoot{}

%%%This would redefine the commands stylehead and stylefoot. Casual would be some external .sty-file
%\usestyle{casual}

%This code maybe changed.
\NewEnviron{Lied}[2]{{
\def\Author{leer}
\def\setAuthor##1{##1}
\long\def\temp{} 
\long\def\test{{\stylehead \BODY \stylefoot}}
\let\Author\setAuthor %This applies setAuthor (defined in \BODY) to Author (used in \stylehead)
\global\csedef{lied;#1;#2}{\test}
}}

%%%This code may not be changed. That is a contraint of the project
\begin{Lied}{A}{1}
\setAuthor{Maestro}
%uncommenting the next line breaks the code
Hallo%\\ this is in a new line

Absatz1
\end{Lied}

%%%document for testing
\begin{document}

\csuse{lied;A;1}

Absatz2\\
Zeile

Absatz3

\end{document}

答案1

如果你添加

\global\cslet{lied;#1;#2}\test
\show\test

你会看到,\test所以lied;..;..定义为

> \test=\long macro:
->{\Author \temp }.

但是\Author\temp仅在本地定义,因此在您尝试使用它的组之外没有定义。

我无法弄清楚预期的行为,但这没有错误。

\documentclass[12pt,a4paper]{article}
\usepackage[utf8]{inputenc}
\usepackage[german]{babel}
\usepackage{environ}
\usepackage{etoolbox}

\begin{document}

\NewEnviron{Lied}[2]{{%
\def\Author{leer}%%%
\def\setAuthor##1{##1}%%%
\let\Author\setAuthor
\csxdef{lied;#1;#2}%
{{%
\expandafter\unexpanded\expandafter{\Author{??}} % space intended here?
\expandafter\unexpanded\expandafter{\BODY}}}%%%
}}

\begin{Lied}{A}{1}
Hallo

Absatz1
\end{Lied}

\csuse{lied;A;1}

Absatz2\\
Zeile

Absatz3

\end{document}

原文的注释版本

\def\stylehead{\Author}

这定义了\stylehead\Author取决于您何时进行评估)固定字符串leer或具有定义的宏,\def\Author#1{#1}在这种情况下它将抓取并复制下一个标记\stylehead\BODY此处的示例)。

\def\stylefoot{}

这定义\stylefoot为空

%%%This would redefine the commands stylehead and stylefoot. Casual would be some external .sty-file
%\usestyle{casual}

好的

%This code maybe changed.
\NewEnviron{Lied}[2]{{

这将在环境组之外启动一个附加组,并由于%在行尾之前缺少空格标记而添加一个空格标记。

\def\Author{leer}

这定义\Authorleer然后插入一个空格标记

\def\setAuthor##1{##1}

this(可能超出定义范围)定义\SetAuthor为与\@firstofoneso\SetAuthor{anything}扩展为相同anything,因此该命令不会执行任何非常有用的操作。然后插入一个空格标记。

\long\def\temp{} 

定义\temp为空(\long没有做太多事情)然后插入一个空格标记。

\long\def\test{{\stylehead \BODY \stylefoot}}

定义\temp\stylehead \BODY \stylefoot在一个组内。(\long没做什么)。然后插入一个空格标记。

\let\Author\setAuthor %This applies setAuthor (defined in \BODY) to Author (used in \stylehead)

该评论似乎是错误的,这只是使其\Author具有相同的定义,因此\SetAuthor就像\newcommand\Author[1]{#1}

\global\csedef{lied;#1;#2}{\test}

这全局定义了 \lied'..;.. 但不支持将 edef 应用于任意乳胶标记,您将破坏大多数命令(\\仅仅是一个例子)再次由于缺少而插入空格标记%

您需要使用\unexpanded原始或\expandonceetoolbox 或 控制扩展\expandafter\protected@xdef\csname lied;#1;#2\endcsname{\test}%

}}

这样就结束了内部组和定义。

\begin{Lied}{A}{1}
\setAuthor{Maestro}

这与

\begin{Lied}{A}{1}
Maestro

就像\SetAuthor只是复制它的参数。

答案2

您无法实现这一点;诸如必须在扩展\setAuthor之前评估之类的设置才能将其存储在宏中。您可以在进行设置时添加第三个参数。但您可能使用了错误的方法:键值方法会更好。\BODYlied

\documentclass[12pt,a4paper]{article}
\usepackage[utf8]{inputenc}
\usepackage[german]{babel}
\usepackage{environ}
\usepackage{etoolbox}

\newcommand{\setAuthor}[1]{\def\Author{#1}}
\setAuthor{leer} % default

\NewEnviron{Lied}[3]{%
  \par#3
  \csxdef{lied;#1;#2}{\expandonce{\Author} \expandonce{\BODY}}%
}

\begin{document}

\begin{Lied}{A}{1}{
  \setAuthor{Maestro}
}
Hallo

Absatz1
\end{Lied}

\csuse{lied;A;1}

\end{document}

在此处输入图片描述

我相信这样的语法

\begin{Lied}{
  class=A,
  number=1,
  author=Author,
  title=Title,
  publisher=Publisher,
}
Text of the lied\\
with line breaks
\end{Lied}

将会更加容易管理。

相关内容