我怎样才能根据嵌套级别为括号着色(像 emacs 的彩虹分隔符)?

我怎样才能根据嵌套级别为括号着色(像 emacs 的彩虹分隔符)?

是否可以自定义设置列表对于类似 LISP 的语言,并且匹配的括号是否用从调色板中获取的相同颜色着色?

我正在寻找的是类似小模式的东西彩虹分隔符对于 Emacs,请看这里: 在此处输入图片描述

假设您有一个 5 种颜色的调色板,那么嵌套的括号将通过循环遍历此调色板来着色,并以相同顺序交替显示 5 种颜色。

更新 我提供了一点 MWE,只是展示了一些类似 lisp 的语言(即 CLIPS)的列表设置,我不知道从哪里开始用彩色括号。

\documentclass{report}

\usepackage[utf8]{inputenc}

\usepackage{listings}
\usepackage{xcolor}

\definecolor{color_1}{RGB}{247, 247, 247}
\definecolor{color_2}{RGB}{186, 33, 33}
\definecolor{color_3}{RGB}{0, 128, 0}
\definecolor{color_4}{RGB}{64, 128, 128}
\definecolor{color_5}{RGB}{170, 34, 255}

\lstdefinelanguage{clips}
{
  morekeywords ={deffunction, deftemplate, defrule, deffacts, run,
    clear, reset, facts, agenda, nil, initial-fact, assert, retract,
    watch, ppdefrule, unwatch, crlf},
  sensitive=true,
  morecomment=[l]{;},
   morestring=[b]",
  basicstyle=\ttfamily\small,
  numbers=left,
  numberstyle=\tiny,
}

\lstnewenvironment{clips-code}
{\lstset{language=clips, 
  }}
{}

\begin{document}

\begin{clips-code}
  (deffunction (a b)
  ``Simple function''
  (if (< a b)
      then (printout t a)
      else (printout t b)))
\end{clips-code}

\end{document}

答案1

listings软件包本身不提供此功能;您需要对其进行一些破解。

我不会在这里详细说明,因为我已经在代码中留下了注释,但基本思想是使用计数器来跟踪嵌套级别,并用与该计数器的当前值相对应的颜色排版每个括号(在您的情况下为模数 5)。

我在我的matlab-prettifier包,以便正确突出显示 MATLAB 的上下文敏感end关键字。

参考

截屏

在此处输入图片描述

在此处输入图片描述

代码

\documentclass{report}

\usepackage{listings}
\usepackage{xcolor}

\definecolor{color0}{RGB}{147, 147, 147} %<--- I've changed this to make it more visible
\definecolor{color1}{RGB}{186, 033, 033}
\definecolor{color2}{RGB}{000, 128, 000}
\definecolor{color3}{RGB}{064, 128, 128}
\definecolor{color4}{RGB}{170, 034, 255}

\lstdefinelanguage{clips}{
  morekeywords = {deffunction, deftemplate, defrule, deffacts, run,
    clear, reset, facts, agenda, nil, initial-fact, assert, retract,
    watch, ppdefrule, unwatch, crlf},
  sensitive        = true,
  morecomment      = [l]{;},
  morestring       = [b]",
  basicstyle       = \ttfamily\small,
  numbers          = left,
  numberstyle      = \tiny,
  showstringspaces = false,
}

% egreg's modulo macro (see https://tex.stackexchange.com/a/34449/21891)
\def\truncdiv#1#2{((#1-(#2-1)/2)/#2)}
\def\moduloop#1#2{(#1-\truncdiv{#1}{#2}*#2)}
\def\modulo#1#2{\number\numexpr\moduloop{#1}{#2}\relax}


\makeatletter

% a TeX counter to keep track of the nesting level
\newcount\netParensCount@clisp

% Modify how ( and ) get typeset depending on the value of the counter
% (Based on Ulrike Fischer's approach to modifying characters in listings;
% see https://tex.stackexchange.com/a/231927/21891)
\lst@CCPutMacro
\lst@ProcessOther{`(}{{%
  \ifnum\lst@mode=\lst@Pmode\relax%
    \rainbow@clisp{(}%
    \global\advance\netParensCount@clisp by \@ne%
  \else
    (%
  \fi
}}%
\lst@ProcessOther{`)}{{%
  \ifnum\lst@mode=\lst@Pmode\relax%
    \global\advance\netParensCount@clisp by \m@ne%
    \rainbow@clisp{)}%
  \else
    )%
  \fi
}}%
\@empty\z@\@empty

% Color its argument based on the value of the \netParensCount@clisp counter
% (modulo 5)
\newcommand\rainbow@clisp[1]{%
  \ifcase\modulo\netParensCount@clisp 5\relax%
    \textcolor{color0}{#1}%
  \or
    \textcolor{color1}{#1}%
  \or
    \textcolor{color2}{#1}%
  \or
    \textcolor{color3}{#1}%
  \else
    \textcolor{color4}{#1}%
  \fi
}

% Alternatively, you could simplify the definition of \rainbow@clisp to...
% \newcommand\rainbow@clisp[1]{%
%   \textcolor{color\modulo\netParensCount@clisp 5}{#1}%
% }
% ... but this assumes that the colours have names of the form color<i>,
% where <i> is a positive integer

% reset the counter at the beginning of each listing
% (just in case there were unmatched parentheses in a previous listing)
\lst@AddToHook{PreInit}{%
  \global\netParensCount@clisp 0\relax%
}

\makeatother


\lstnewenvironment{clips-code}
  {\lstset{language=clips}}
  {}


\begin{document}

\begin{clips-code}
  (def function (a b)
  ``Simple function''
  (if (< a b)
      then (printout t a)
      else (printout t b)))
\end{clips-code}

\begin{clips-code}
  (define (collatz n)
    " generate the Collatz sequence (for N until it ends in 1)"
    (if (n n 1)
        '(1) ;; stop
        (cons n
            (if (= (modulo n 2) 0)
                (collatz (/ n 2))
                (collatz (1+ (* 3 n)))))))
\end{clips-code}

\end{document}

相关内容