定义新的语言列表,仅在行首添加注释

定义新的语言列表,仅在行首添加注释

我正在尝试为自制语言创建列表(使用 \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=\%]

然后,在有问题的那一行,我使用了 %\#%黑色打印,所以不是注释。当然,这是一个比这里已经提供的解决方案更手动的解决方案,但也许有人会觉得这很有用。

相关内容