我正在尝试为自制语言创建列表(使用 \lstdefinelanguage)。问题是该语言中的注释有些含糊不清。例如,以下代码是有效的:
* This is a comment
a = 4 /* This is a comment as well */
********** This is a comment ********
a = a + 1 /* So is this */
* And Surprisingly This is a comment
* And This
* AND THIS!
a = a * 100500 /* Star here is not a comment! */
因此,我需要确保当且仅当在行首时将 '*' 视为注释(前面可能有空格),但不在中间,因为那里是乘法。
到目前为止我所拥有的是以下内容:
\lstdefinelanguage{HOMEBREW}{
alsoletter = {\$},
comment = [l]{*},
keywords = {
*,
command,
eval,
if, elseif, else, endif,
include,
open, close,
print, printf,
set, reset,
while, endwhile,
},
sensitive = false,
string = [b]",
% MORE:
% morecomment = [l]{**},
% moredelim = [l]{(}{)},
}
这可能吗?
答案1
我必须做类似的事情我的一个包裹。这里我没有详细解释,而是在代码中留下了一些注释,以便您了解我的做法。
笔记:由于修改内容是全局性的,如果您打算使用同一文档\lst@AddToHook
之外的其他语言来列出列表,则需要采取额外的预防措施。请告诉我。HOMEBREW
编辑:不幸的是,这个解决方案并不完美。您发布的示例代码运行正常,但如果您在已经包含的行上开始块注释,*
并在以下行之一关闭该块注释,则该块注释将无法正确突出显示。
\documentclass{article}
\usepackage[dvipsnames]{xcolor}
\usepackage{listings}
\makeatletter
% --- a couple of switches to keep track of the context ---
% this switch will be set if we have encountered visible character on the current line
\newif\ifVisCharOccured@homebrew@
% this switch will be set when we're inside a one-line comment
\newif\ifinlcom@homebrew@
% flip the switch if visible characters occur on the line
\lst@AddToHook{PostOutput}
{%
\lst@ifwhitespace%
\else
\global\VisCharOccured@homebrew@true%
\fi
}
% reset switches at the end of each line
\lst@AddToHook{InitVarsEOL}
{%
\global\inlcom@homebrew@false%
\global\VisCharOccured@homebrew@false%
}
% reset switches at the beginning of each listing
\lst@AddToHook{PreInit}
{%
\VisCharOccured@homebrew@false
\inlcom@homebrew@false
}
% helper macro to handle instances of `*'
\newcommand\processlcom@homebrew
{%
% if we're already inside a comment, we keep applying the comment style
\ifinlcom@homebrew@%
\lst@commentstyle%
\else
% Otherwise, we apply the comment style only if no visible characters have
% been encountered before the `*' on the current line.
\ifVisCharOccured@homebrew@%
\else
\global\inlcom@homebrew@true%
\lst@commentstyle%
\fi
\fi
}
\lstdefinelanguage{HOMEBREW}{
alsoletter = {\$},
moredelim = *[l][\processlcom@homebrew]{*}, %<--- we handle to-end-of-line comments here
keywords = {
command,
eval,
if, elseif, else, endif,
include,
open, close,
print, printf,
set, reset,
while, endwhile,
},
sensitive = false,
string = [b]",
morecomment = [s]{/*}{*/},
% moredelim = [l]{(}{)},
}
\makeatother
\lstdefinestyle{myHOMEBREWstyle}
{
language = HOMEBREW,
basicstyle = \ttfamily,
commentstyle = \color{ForestGreen},
}
\begin{document}
\begin{lstlisting}[style=myHOMEBREWstyle]
* This is a comment
a = 4 /* This is a comment as well */
********** This is a comment ********
a = a + 1 /* So is this */
* And Surprisingly This is a comment
* And This
* AND THIS!
a = a * 100500 /* Star here is not a comment! */
\end{lstlisting}
\end{document}
答案2
我刚刚遇到了类似的事情。我定义了一种非常简单的语言,可以将所有注释打印为绿色。注释是以井号 (#) 开头的行。
morecomment=[l]{\#},
但是,我有一行中间有井号,这也被认为是注释,但它不是。我现在通过在列表内切换到仅针对井号的正常 Latex 模式来修复它。
在我的列表开头我使用了 escapechar=\%
\begin{lstlisting}[basicstyle=\ttfamily, backgroundcolor=\color{shadecolor}, escapechar=\%]
然后,在有问题的那一行,我使用了 %\#%
黑色打印,所以不是注释。当然,这是一个比这里已经提供的解决方案更手动的解决方案,但也许有人会觉得这很有用。