使用字符来分隔命令(如 markdown)

使用字符来分隔命令(如 markdown)

我最近遇到\DefineShortVerbfancyvrb包的命令,它可以让你“定义一个特殊字符作为缩写来包含逐字文本",例如:

\documentclass{article}
\usepackage{fancyvrb}
\DefineShortVerb{\|}
\begin{document}
|this is verbatim|
\end{document}

我想知道是否可以以及如何对任何其他字符和任何其他命令执行此操作。例如,假设我希望字符括起来的文本`以斜体显示:

\documentclass{article}
% some code
\begin{document}
`this` and \textit{this} should be the same.
\end{document}

我怎样才能做到这一点?

答案1

的基本思想\DefineShortVerb是使论证中的人物变得活跃(\catcode`#1=\active ),以便该字符的行为类似于宏。然后它使用“小写技巧”。您可以将其更改为将字符定义为自定义宏。

这是一个\DefineShortCommand<char>{<definition>}宏,它定义了<char>要扩展为<definition>。这最终会执行类似于 的操作\def<char>#1<char>{<definition>},其中<char>是活动字符标记。在 中<definition>#1是参数,在第一个和下一个(括号平衡) 之间抓取<char>

\documentclass{article}
\def\DefineShortCommand#1{%
  \catcode`#1=\active
  \begingroup
    \lccode`\~=`#1
    \lowercase{\endgroup
  \def~##1~}}
\begin{document}

\DefineShortCommand\`{\textit{#1}}
`this` and \textit{this} should be the same.

\end{document}

注意不要激活“危险”的字符,并警惕可能出现的冲突babel


与 一起使用时Verbatim,字符`特别麻烦,因为该字符被 LaTeX 重置\@noligs以避免它在逐字模式下形成连字。在用户的 catcode 设置之后fancyvrb使用\@noligs,因此您对字符所做的任何更改都`将被覆盖。您需要将其从逐字连字列表中删除:

\documentclass{article}
\usepackage{fancyvrb}
\def\DefineShortCommand#1{%
  \catcode`#1=\active
  \begingroup
    \lccode`\~=`#1
    \lowercase{\endgroup
  \def~##1~}}
\begin{document}

\makeatletter
\def\verbatim@nolig@list{\do\<\do\>\do\,\do\'\do\-}
\def\backtickit{\DefineShortCommand\`{\textit{##1}}}
\makeatother

\begin{Verbatim}[codes={\backtickit}]
  x=1/sqrt(z**2) <- This is an `equation`
\end{Verbatim}

\end{document}

正如 Mico 所指出的,当`使用两个字符时(例如``should''),您通常不想应用特殊格式。要检测这种情况,您可以检查 active- 的参数`是否为空,然后改用原始`字符。

假设您有一个\tlifempty{<token list>}{<empty>}{<not empty>}(如下所示)条件,那么可以通过以下方式实现:

\DefineShortCommand\`{%
  \tlifempty{#1}
    {\char96\char96\relax}
    {\textit{#1}}}

( 96 是 的 ASCII 码`)。

为了更进一步,允许最终在仅扩展的上下文中使用 `(或您碰巧与 一起使用的其他字符\DefineShortCommand),您需要保存 的原始含义 `,然后稍后使用辅助宏检索它。

在下面的代码中,\DefineShortCommand将参数的原始含义保存为(例如 `\the@char@96。稍后您可以使用检索它\thechar{`}。为了额外的安全性,代码进行了一些规范化,以便`\`检索相同的字符:

\documentclass{article}
\makeatletter
\def\DefineShortCommand#1{%
  \expandafter\edef\csname the@char@\number`#1\endcsname
    {\unless\if\@backslashchar\string#1%
       \string#1\else\expandafter\@gobble\string#1\fi}%
  \catcode`#1=\active
  \begingroup
    \lccode`\~=`#1
    \lowercase{\endgroup
  \def~##1~}}
\def\thechar#1{\csname the@char@\number`#1\endcsname}
% Checking if the argument is empty
\def\tlifempty#1{%
  \if\relax\detokenize{#1}\relax
    \expandafter\@firstoftwo
  \else
    \expandafter\@secondoftwo
  \fi}
\makeatother
\begin{document}
\DefineShortCommand\`{%
  \tlifempty{#1}
    {\thechar{`}\thechar{\`}}
    {\textit{#1}}}

`this` and \textit{this} ``should'' be the same.
\end{document}

答案2

我希望 [反引号] 字符括起来的文本以斜体显示

这是一个基于 LuaLaTeX 的解决方案。它不需要将反引号字符 设为`“活动”。

在此处输入图片描述

观察“正常”使用双倍的反引号,``如 中的``that'',不受成对单个反引号括起来的材料的处理影响。

% !TEX TS-program = lualatex
\documentclass{article}
\usepackage{luacode}  
%% Lua-side code:
\begin{luacode}
function backtick2textit ( s )
   s = s:gsub ( "``(.-)''" , "@@@@@%1@@@@@" ) -- save ``...'' cases
   s = s:gsub ( "`(..-)`", "\\textit{%1}" )   -- ignore consecutive backticks
   s = s:gsub ( "@@@@@(.-)@@@@@" , "``%1''" ) -- restore ``...'' cases
   return s
end
\end{luacode}    
%% LaTeX-side code:
\AtBeginDocument{\directlua{luatexbase.add_to_callback( 
   "process_input_buffer", backtick2textit , 
   "backtick2textit" )}}

\begin{document}
\dots\ and `this` and ``that'' and ``why'' and `who` and \dots
\end{document}

附录解释该解决方案的工作原理:

  • Lua 函数backtick2textit被分配给process_input_buffer回调,它在非常早期的阶段运行,即在 TeX 执行其通常的扩展宏等工作之前。

  • 该函数backtick2textit采用 Lua 函数string.gsub(我认为“gsub”代表“全局替换”)来执行其工作。

    • 首先,用双反引号/双撇号(非贪婪匹配)括起来的字符串被放在一边。

    • 如果遇到一个反引号,后面跟着一个或多个任意字符(非贪婪匹配),后面跟着另一个反引号,则会发生模式匹配。如果匹配成功,则反引号括起来的内容将被封装在指令中\textit

    • 最后恢复双引号中要渲染的素材。

  • 如果同时使用单引号和双引号字符来引用材料,Lua 函数将无法正确执行。上面发布的代码无法防止这种情况发生,因为我假设您提到使用反引号字符只是作为示例。

相关内容