我更喜欢 latex 而不是 markdown,但 markdown 的一些功能会让写作更愉快。特别是,我很乐意写
\section{My List}
* List A
- List A.1
* List B
我尝试了这个markdown.sty
包(混合选项),但我既没有真正设法让它工作(缩进的版本被忽略),也没有喜欢启用 shell 访问。
'^\*'
有没有更轻量级的解决方案?TeX 是否具有将and'^\s\s\-'
和'^\s\s\s\s.'
(perl 正则表达式) 转换为正确隔离的 itemize 的内在能力?
我认为答案是否定的,但是我过去曾对乳胶的功能感到惊讶。
答案1
这是一个基于 LuaLaTeX 的解决方案。它由 (a) 一个 Lua 函数组成,该函数完成大部分工作;以及 (b) 几个 LaTeX 实用程序宏(称为\ListMarkdownOn
和\ListMarkdownOff
),用于激活和停用 Lua 函数。我所说的“激活”是指将 Lua 函数分配给 LuaTeX 的process_input_buffer
回调,这使其充当输入流上的预处理器,前TeX 开始进行常规处理。因此,如果有效, TeX 将无法“看到”*
和-
markdown 元素。\ListMarkdownOn
关于输入流的主要假设是:
如果
*
出现在输入行的最开始,则该行是一级列表项如果输入行以两个或多个空格开头,后跟
-
,则该行是二级列表项。二级列表仅出现在一级列表中。(在下面的 Lua 代码中,这个假设意味着如果
InLevel2
布尔变量为真,则布尔变量也为真InLevel1
。)列表环境中没有空行。换句话说:如果 或
InLevel1
为InLevel2
真,则全空行将被解释为终止所有列表级别。
以下材料应存储在名为 的 LaTeX 样式文件中listmarkdown.sty
。主 tex 文件应listmarkdown
通过\usepackage
语句加载包。
%% listmarkdown.sty
\ProvidesPackage{listmarkdown}[2020-10-26]
%% Create a bespoke two-level itemize-type list environment
\RequirePackage{enumitem}
\newlist{myitemize}{itemize}{2}
\setlist[myitemize,1]{label=\textasteriskcentered} % marker: asterisk
\setlist[myitemize,2]{label=\textendash} % marker: endash
%% Now the Lua code
\RequirePackage{luacode}
\begin{luacode}
-- Create two Boolean variables
local InLevel1 = false
local InLevel2 = false
-- Create two string variables, with beginnings of Level-1 and -2 lines
-- ["^" denotes start of line; "%s" denotes "whitespace char."]
-- [must escape literal uses of "*" and "-".]
local Level1Line = "^%*"
local Level2Line = "^%s%s%s-%-"
function listmarkdown ( s )
if InLevel2==true then
if s:find ( Level2Line ) then
s = s:gsub ( Level2Line , "\\item " )
elseif s:find ( Level1Line ) then
InLevel2=false -- fall back one list level
s = s:gsub ( Level1Line , "\\end{myitemize} \\item " )
else -- line doesn't start with either '*' or ' -';
-- hence, terminate both list levels
InLevel2=false
InLevel1=false
s = "\\end{myitemize}\\end{myitemize}" .. s
end
elseif InLevel1==true then
if s:find ( Level2Line ) then -- start a level-2 list
InLevel2=true
s = s:gsub ( Level2Line , "\\begin{myitemize}\\item " )
elseif s:find ( Level1Line ) then -- line starts with "*"
s = s:gsub ( Level1Line , "\\item " )
else -- line doesn't start with either '*' or ' -'
-- hence, terminate the level-1 list
InLevel1=false
s = "\\end{myitemize}" .. s
end
-- What to do if 'InLevel2' and 'InLevel1' are both 'false'
elseif s:find ( Level1Line ) then -- start a level-1 list
InLevel1=true
s = s:gsub ( Level1Line , "\\begin{myitemize}\\item" )
end
return s -- return 's', for further processing by TeX
end
\end{luacode}
% Finally, two LaTeX macros to activate and deactivate the Lua function
\newcommand\ListMarkdownOn{\directlua{luatexbase.add_to_callback
( "process_input_buffer", listmarkdown , "listmarkdown" )}}
\newcommand\ListMarkdownOff{\directlua{luatexbase.remove_from_callback
( "process_input_buffer", "listmarkdown" )}}
以下是在 tex 文件中使用代码的方法listmarkdown.sty
——请注意,必须使用 LuaLaTeX。
% !TEX TS-program = lualatex
\documentclass{article}
\usepackage{listmarkdown}
\begin{document}
\noindent
Hello.\strut
%% Show expected look of two-level list:
\hrule
\begin{myitemize}
\item Item A
\begin{myitemize}
\item Item A.1
\end{myitemize}
\item Item B
\begin{myitemize}
\item Item B.1
\item Item B.2
\end{myitemize}
\end{myitemize}
\h rule
% Lua function not yet activated, hence no prettification
* Item A
- Item A.1
* Item B
- Item B.1
- Item B.2
\hrule
\ListMarkdownOn % Activate the Lua function -- prettification will kick in
* Item A
- Item A.1
* Item B
- Item B.1
- Item B.2
\hrule
\ListMarkdownOff
% Lua function is de-activated -- no more prettification
* Item A
- Item A.1
* Item B
- Item B.1
- Item B.2
\hrule
% Say goodbye.
\noindent
Goodbye.\strut
\end{document}