我很喜欢这里的系统,其中*...*
是斜体,**...**
是粗体,***...***
是粗体斜体。在 (La)TeX 中可以做到这一点吗?
实现第一个的 MWE:
\documentclass{article}
\begin{document}
\begingroup
\catcode`*\active
\def*#1*{\emph{#1}}
*italic text*
\endgroup
\end{document}
但是另外两个呢?关于让两个字符活跃起来的问题还存在,但在命令的开头和结尾都使用两个字符听起来更难。而且不要让我开始三人物。
附带一个问题:我一直在想:\catcode`*\active
和之间有什么区别\catcode`\*\active
? (请注意\
第二个例子中的 。)
答案1
这里的好处是,您可以用 打开该功能,并用(默认条件)\starON
将其关闭。\starOFF
这是 MWE。
\documentclass{article}
\makeatletter
\def\starparse{\@ifnextchar*{\bfstarx}{\itstar}}
\def\bfstarx#1{\@ifnextchar*{\bfitstar\@gobble}{\bfstar}}
\makeatother
\def\itstar#1*{\textit{#1}\starON}
\def\bfstar#1**{\textbf{#1}\starON}
\def\bfitstar#1***{\textbf{\textit{#1}}\starON}
\def\starON{\catcode`\*=\active}
\def\starOFF{\catcode`\*=12}
\starON
\def*{\starOFF \starparse}
\starOFF
\begin{document}
\starON Turn feature on:\par
This is a test of *italic*, and **bold**, as well as ***bold, italic*** text.
\starOFF Turn feature off:\par
This is a test of *italic*, and **bold**, as well as ***bold, italic*** text.
\end{document}
答案2
以下解决方案使用 LuaLaTeX 的功能来定义一个名为的函数allstars
,它将对将星号组 -- ***...***
、**...**
和*...*
-- 转换为“传统” LaTeX 代码:{\bfseries\itshape ...}
、{\bfseries ...}
和{\itshape ...}
。代码假设基于星号的 markdown 确实不是跨越换行符。代码不会使*
“活动” (在 TeX 意义上)。因此,*
不会出现因活动而导致的各种并发症。
使用带星号的 LaTeX 宏(例如\section*
)和带星号的 LaTeX 环境(例如equation*
)是可以的 - 也就是说,它们将不是导致编译崩溃——如果相应的输入行上没有其他星号。为了更加通用,代码提供了两个宏——名为\markdownoff
和\markdownon
——用于关闭和打开函数的操作allstars
。该allstars
函数是未激活默认情况下——必须通过执行来打开它\markdownon
。
markdown 指令可以嵌套,也就是说斜体字符串可以包含 加粗斜体 子字符串还有粗体字符串可以包含 加粗斜体 子字符串。
该allstars
函数被分配给 LuaTeX 的process_input_buffer
回调,使其在编译的早期阶段运行(在 TeX 的“眼睛”开始工作之前)。该函数allstars
使用 Lua 的函数对每行输入执行三次“扫描”或“传递” string.gsub
。在第一次传递期间,它会搜索对在第一次扫描中,它会查找字符***
;在第二次扫描中,它会查找**
字符对;在第三次也是最后一次扫描中,它会查找字符对*
。
为了充分理解该allstars
函数的工作原理,有必要检查一下如果输入行包含四个或更多连续星号的情况(尽管“常规”markdown 不应包含此类情况)。例如,如果输入行包含七个星号序列
a*******b
并且输入行上没有其他星号,则输出将是“ab”:单个““a”和“b”之间有一个字符,但没有斜体或粗体字符。发生了什么?函数将中的前六个星号*******
解释allstars
为一对字符串***
,*******
因此被转换为{\bfseries\itshape}
;因此它们最终什么都不做,至少就 TeX 而言。不过,第七个星号是不是由函数修改allstars
,因此由 TeX 排版。
或者,考虑字符串
a*******b********c
(“a”和“b”之间有七个星号,“b”和“c”之间有八个星号)。在第一遍中string.gsub
,输入行被转换为
a{\bfseries\itshape}*b{\bfseries\itshape}**c
就我们的目的而言,这相当于
a*b**c
该函数的第二遍没有做任何事,因为没有一对字符数**
出现在输入行中。函数的第三遍查找一个一对字符*
,因此将输入行转换为
a{\itshape b}*c
这就是 (Lua)TeX 引擎排版的内容。
最后考虑一下如果输入行包含以下内容会发生什么情况
\section*{A New* Hope}
(并且没有其他星号)。该函数的第三遍allstars
在此输入行中找到一对单个星号,因此将其转换为
\section{\itshape {A New} Hope}
相当于
\section{\itshape A New Hope}
因此,我们得到一个编号节,节标题(但不是节号)以粗斜体排版。可能不是预期或预期的...如果您确实需要*
直接排版,则应发出\markdownoff
暂停allstars
函数操作的命令。
% !TEX TS-program = lualatex
\documentclass{article}
\usepackage{amsmath} % for 'equation*' environment
\usepackage{luacode,luatexbase}
\begin{luacode}
-- Use Lua captures to extract material affected by markdown
function allstars (line)
line = string.gsub( line, "(%*%*%*)(.-)(%*%*%*)", "{\\bfseries\\itshape %2}")
line = string.gsub( line, "(%*%*)(.-)(%*%*)", "{\\bfseries %2}" )
line = string.gsub( line, "(%*)(.-)(%*)", "{\\itshape %2}" )
return line
end
\end{luacode}
\newcommand\markdownon{%
\directlua{luatexbase.add_to_callback( "process_input_buffer", allstars, "allstars" )}}
\newcommand\markdownoff{%
\directlua{luatexbase.remove_from_callback( "process_input_buffer", "allstars" )}}
\begin{document}
\markdownon
normal
*italic*, **bold**, normal, *more italic*
**bold**, *italic*, **more bold**
***bold italic***, normal, ***more bold italic text***,
**bold text containing a *bold italic* substring**
*italic text with **bold italic** substring*
normal again
\markdownoff % not actually required, as each of the following lines contains exactly one asterisk
\medskip
an \texttt{equation*} environment:
\begin{equation*}
a = b
\end{equation*}
\markdownon
more **bold text with a *bold italic* substring**
\end{document}
答案3
如果您不反对使用'
而不是*
,那么该wiki
包就是简单的解决方案。
这样就不会与带星号的宏发生冲突。此外,它使用常见的 Wikipedia 语法,另一方面,粗体和斜体可以嵌套甚至重叠:
\documentclass[border=1cm]{standalone}
\usepackage{wiki}
\begin{document}
\wikimarkup
normal,
'''bold''',
''italic'',
'''''bold italic'''''
and
''over'''lap''ping'''
style.
\end{document}