背景

背景

背景

代码在启动/停止环境中生成一本书的标题和作者。我想重新定义内容将这些环境作为宏来使用,这样就可以在其他地方重复使用。例如:

\startbooktitle

Famous Novel Title

\stopbooktitle

代码

以下代码(以及它的无数变体)无法创建名为 的BookTitleFamous Novel Title

  \definestartstop[booktitle][
    before={\define\BookTitle\bgroup},
    after={\egroup},
  ]

问题

无论使用bgroup/egroup还是begingroup/ endgroup,错误都是:

 ["lasttexerror"]="! Too many }'s",

使用startbufferendbuffer结果看起来像无限递归。

删除编译define内部的bgroups,但\BookTitle宏在其他地方不可用,即使可用,startbooktitle/之间的内容stopbooktitle也不会被捕获:

before={\bgroup\define\BookTitle},

问题

如何使用命令中的before/选项定义宏,以便在调用时捕获启动/停止命令的全部内容?afterdefinestartstop

换句话说,你如何转码:

\startbooktitle

Famous Novel Title

\stopbooktitle

进入:

\define\BookTitle{Famous Novel Title}

before还有其他比/更可取的可能性吗after

答案1

TeX 中的宏定义需要显式括号,即

\def\foo{...}

隐式括号,如\bgroupand\egroup或任何其他标记,这些标记应\let起作用{}不起作用。以下是无效的

\def\foo\bgroup...\egroup

TeX 中有几个命令允许隐式括号作为分隔符,例如\hboxbut\def不是其中之一。由于 TeX 中不能有不匹配的显式括号(除了一些\halign相关的技巧),因此您无法从 中获取环境的内容\definestartstop。但是,TeX 为您提供支持,您可以使用分隔宏来实现此目的

\unexpanded\def\stopbooktitle{\stopbooktitle} % Don't expand me, I only delimit things
\unexpanded\def\startbooktitle#1\stopbooktitle{\define\BookTitle{#1}}

\starttext

\startbooktitle

Famous Novel Title

\stopbooktitle

\meaning\BookTitle

\stoptext

在此处输入图片描述

不幸的是,正如您所看到的,这不会修剪空格,空行会转换为\par空格,单词“Title”后面的行尾字符会转换为空格。您现在可以构建一些带有扭曲扩展的复杂宏机制来删除这些标记,但由于我很懒,所以我只在 Lua 中执行此操作。

\startluacode
function userdata.booktitle()
    local t = token.scan_toks()

    -- trim from the start
    for n = 1, #t do
        local cur_tok = t[n].cmdname 
        if cur_tok == "par_end" or cur_tok == "spacer" then
            table.remove(t, n)
        else
            break
        end
    end

    -- trim from the end
    for n = #t, 1, -1 do
        local cur_tok = t[n].cmdname 
        if cur_tok == "par_end" or cur_tok == "spacer" then
            table.remove(t, n)
        else
            break
        end
    end

    token.put_next(t)
end
\stopluacode

\unexpanded\def\stopbooktitle{\stopbooktitle} % Don't expand me, I only delimit things
\unexpanded\def\startbooktitle#1\stopbooktitle{%
  \expandafter\define\expandafter\BookTitle\expandafter{\ctxlua{userdata.booktitle()}{#1}}}

\starttext

\startbooktitle

Famous Novel Title

\stopbooktitle

\meaning\BookTitle

\stoptext

在此处输入图片描述

相关内容