Minted:交替(斑马)背景颜色线条

Minted:交替(斑马)背景颜色线条

尽管我对环境的了解不够充分,我还是能够根据自己的喜好(没什么特别的)为现代 JavaScript 设计列表样式。

最让人头疼的是,我需要语法高亮 React.js,但无法通过 正确呈现listing。我非常喜欢能够对线条的背景颜色、行号、字体等进行斑马线/交替显示,但无法识别 jsx 语言。我广泛搜索了让它工作的方法,显然建议是完全切换到 Minted 包,并安装单独的第三方 jsx 词法分析器。

它可以起作用,但我还没有找到以斑马线方式交替每条线的背景颜色的方法。

截屏

任何关于如何将 Minted 输出转换为更接近列表示例的建议(包括行突出显示以及(如果可能的话)行号等)都将不胜感激。

MWE(需要--shell-escapejsx-词法分析器):

\documentclass[]{scrbook}

\usepackage{xcolor}
\usepackage[]{cleveref}
\usepackage{listings}

\definecolor{listing-background}{HTML}{FFFFFF}
\definecolor{listing-background-alternate}{HTML}{F8F8F8}
\definecolor{listing-rule}{HTML}{B3B2B3}
\definecolor{listing-numbers}{HTML}{B3B2B3}
\definecolor{listing-text-color}{HTML}{000000}
\definecolor{listing-keyword}{HTML}{007F00}
\definecolor{listing-keyword-2}{HTML}{1284CA} 
\definecolor{listing-keyword-3}{HTML}{9137CB} 
\definecolor{listing-keyword-4}{HTML}{407F7F} 
\definecolor{listing-identifier}{HTML}{000000}
\definecolor{listing-identifier}{HTML}{435489}
\definecolor{listing-string}{HTML}{BA2121}
\definecolor{listing-comment}{HTML}{8E8E8E}

\lstdefinelanguage{es6}{
  morekeywords=[1]{break, continue, delete, else, for, function, if, in,
    new, return, this, typeof, var, void, while, with, await, async, case, catch, class, const, default, do, enum, export, extends, finally, from, implements, import, instanceof, let, static, super, switch, throw, try },
  morekeywords=[2]{false, null, true, boolean, number, undefined,
    Array, Boolean, Date, Math, Number, String, Object },
  morekeywords=[3]{eval, parseInt, parseFloat, escape, unescape },
  otherkeywords = {+,-},
  sensitive,
  morecomment=[s]{/*}{*/},
  morecomment=[l]//,
  morecomment=[s]{/**}{*/},
  morestring=[b]',
  morestring=[b]"
}[keywords, comments, strings]


\makeatletter
\let\old@lstKV@SwitchCases\lstKV@SwitchCases
\def\lstKV@SwitchCases#1#2#3{}
\makeatother
\usepackage{lstlinebgrd}
\makeatletter
\let\lstKV@SwitchCases\old@lstKV@SwitchCases

\lst@Key{numbers}{none}{%
    \def\lst@PlaceNumber{\lst@linebgrd}%
    \lstKV@SwitchCases{#1}%
    {none:\\%
     left:\def\lst@PlaceNumber{\llap{\normalfont
                \lst@numberstyle{\thelstnumber}\kern\lst@numbersep}\lst@linebgrd}\\%
     right:\def\lst@PlaceNumber{\rlap{\normalfont
                \kern\linewidth \kern\lst@numbersep
                \lst@numberstyle{\thelstnumber}}\lst@linebgrd}%
    }{\PackageError{Listings}{Numbers #1 unknown}\@ehc}}
\makeatother

\lstdefinestyle{fancylisting}{
  basicstyle=\ttfamily\linespread{1.0}\color{listing-text-color}\small,
  numbers          = left,
  xleftmargin      = 2.7em,
  framexleftmargin = 2.5em,
  backgroundcolor  = \color{listing-background},
  breaklines       = true,
  frame            = single,
  framesep         = 0.19em,
  rulecolor        = \color{listing-rule},
  frameround       = ffff, 
  tabsize          = 4,
  numberstyle      = \color{listing-numbers}\footnotesize\ttfamily{},
  linebackgroundcolor={\ifodd\value{lstnumber}\color{listing-background-alternate}\fi},
  aboveskip        = 1.2em,
  belowskip        = 1em,
  abovecaptionskip = 0em,
  belowcaptionskip = 1.0em,
  keywordstyle     = {\color{listing-keyword}\bfseries},
  keywordstyle     = {[2]\color{listing-keyword-2}},
  keywordstyle     = {[3]\color{listing-keyword-3}\bfseries\itshape},
  keywordstyle     = {[4]\color{listing-keyword-4}},
  sensitive        = true,
  identifierstyle  = \color{listing-identifier},
  commentstyle     = \color{listing-comment},
  stringstyle      = \color{listing-string},
  showstringspaces = false,
  escapeinside     = {/*@}{@*/}  }
\lstset{style=fancylisting}

\lstnewenvironment{es6}[1][]
    {\lstset{
      language=es6,
      morekeywords=[4]{+,<,>,-,=},
      #1
    }}
    {}

\lstnewenvironment{bash}[1][]
    {\lstset{
      language=bash,
      linebackgroundcolor=\color{white},
      backgroundcolor=\color{white},
      numbers=none,
      frame=l,
      framerule=0.5pt,
      rulecolor = \color{listing-rule},
      #1
      }}
    {}

\crefname{lstlisting}{listing}{listings}
\Crefname{lstlisting}{Listing}{Listings}
\crefname{lstinputlisting}{listing}{listings}
\Crefname{lstinputlisting}{Listing}{Listings}

\usepackage{fancyvrb}
\usepackage[cache=false,outputdir=.texpadtmp]{minted}

\begin{document}

Minted (syntax recognized, ugly formatting)

\begin{minted}{jsx}
  const BlogTitle = ({ children }) => (
    <h3>{children}</h3>
  );
  // class component
  class BlogPost extends React.Component {
    renderTitle(title) {
      return <BlogTitle>{title}</BlogTitle>
    };
    render() {
      return (
      <div className="blog-body">
        {this.renderTitle(this.props.title)}
        <p>{this.props.body}</p>
      </div>
      );
    }
  }
\end{minted}

Listing (syntax not recognized, desired formatting):

\begin{es6}
  const BlogTitle = ({ children }) => (
    <h3>{children}</h3>
  );
  // class component
  class BlogPost extends React.Component {
    renderTitle(title) {
      return <BlogTitle>{title}</BlogTitle>
    };
    render() {
      return (
      <div className="blog-body">
        {this.renderTitle(this.props.title)}
        <p>{this.props.body}</p>
      </div>
      );
    }
  }
\end{es6}

\end{document}

谢谢你!

答案1

这是一个经过大量调整的实验性解决方案!为了使其正常工作,您需要手动指定行高并保证所有行的行高相等。另一个问题是我的pygments没有词法分析器。因此,您可能需要在您的终端上将jsx代码更改为。minted language=jsx

在此处输入图片描述

代码

  • 根据您的文档设置更改的值很重要\g_lst_line_height_dim。否则,背景和前景可能不会对齐。如果您要更改的边距tcolorbox,则需要更改所有其他四个边距变量。
  • 循环中可以使用两种以上的颜色。
  • 如果取消注释\bool_gset_true:N \g_lst_debug_bool,则代码列表将在调试模式下呈现。在调试模式下,更容易确定列表框的参数。以下是调试模式的示例输出: 在此处输入图片描述
\documentclass{scrbook}
\usepackage{tcolorbox}
\usepackage{fancyvrb}
\usepackage{expl3}
\usepackage{tikz}
\usepackage{xcolor}

\usetikzlibrary{math, calc}
\tcbuselibrary{listings, minted, hooks, skins}

% change line number style
\renewcommand{\theFancyVerbLine}{%
    \ttfamily\textcolor[rgb]{0.3,0.3,0.3}{\tiny{\arabic{FancyVerbLine}}}%
}

\definecolor{listing-background}{HTML}{FFFFFF}
\definecolor{listing-background-alternate}{HTML}{F8F8F8}

\makeatletter
\tcbset{
    lststyle/.style={
        enhanced,
        left=8mm,
        top=0mm,
        bottom=0mm,
        boxsep=0.5mm,
        listing only,
        listing engine=minted,
        minted language=html, % I don't have jsx lexer on my computer
        arc=0mm,
        colframe=black!5,
        colback=white,
        minted options={
            obeytabs,
            breaklines,
            linenos,
            autogobble,
            fontsize=\scriptsize,
            numbersep=2.5mm,
        },
        underlay=\my@lst@underlay
    }
}

\ExplSyntaxOn

% several variables that need tuning when the configuration changes

% first of all, define the margins of the box
\dim_new:N \g_lst_left_dim
\dim_new:N \g_lst_right_dim
\dim_new:N \g_lst_top_dim
\dim_new:N \g_lst_bottom_dim

\dim_gset:Nn \g_lst_left_dim {7.5mm}
\dim_gset:Nn \g_lst_right_dim {0.5mm}
\dim_gset:Nn \g_lst_top_dim {0.5mm}
\dim_gset:Nn \g_lst_bottom_dim {0.5mm}

% next step, define the line height
\dim_new:N \g_lst_line_height_dim
\dim_gset:Nn \g_lst_line_height_dim {9.38pt}


% this is a switch to turn on debug mode for determining the parameters above
\bool_new:N \g_lst_debug_bool
\bool_gset_false:N \g_lst_debug_bool
%\bool_gset_true:N \g_lst_debug_bool % turn on debug mode

% a list of colors to be used
\clist_new:N \g_lst_colors_clist
\clist_set:Nn \g_lst_colors_clist {listing-background, listing-background-alternate}


\int_new:N \l_lst_tmpa_int
\tl_new:N \l_lst_tmpa_tl
\tl_new:N \l_lst_tmpb_tl
\tl_new:N \l_lst_tmpc_tl
\dim_new:N \l_lst_tmpa_dim
\fp_new:N \l_lst_tmpa_fp
\fp_new:N \l_lst_tmpb_fp
\fp_new:N \l_lst_tmpc_fp

\cs_set:Npn \__lst_anchor_dist:nnnnN #1#2#3#4#5 {
    \pgfpointdiff{\pgfpointanchor{#1}{#2}}%
                 {\pgfpointanchor{#3}{#4}}%
    \edef#5{\fp_eval:n {sqrt(\pgf@x*\pgf@x + \pgf@y*\pgf@y)}}
}

% setup the drawing function
\cs_set:Npn \my@lst@underlay {
    \int_set:Nn \l_lst_tmpa_int {0}
    
    % compute height of tcolorbox
    % warning: does not work if the box is breakable!
    \__lst_anchor_dist:nnnnN {interior}{north~west}{interior}{south~west}\l_lst_tmpa_tl;
    
    % compute line width of tcolorbox
    \__lst_anchor_dist:nnnnN {interior}{north~west}{interior}{north~east}\l_lst_tmpb_tl;
    
    \fp_set:Nn \l_lst_tmpa_fp {\g_lst_top_dim}
    \fp_set:Nn \l_lst_tmpb_fp {\l_lst_tmpa_tl - \g_lst_bottom_dim}
    \dim_set:Nn \l_lst_tmpa_dim {\l_lst_tmpb_tl pt - \g_lst_right_dim - \g_lst_left_dim}
    
    \fp_do_while:nNnn \l_lst_tmpa_fp < \l_lst_tmpb_fp {
        % compute position of end of line
        \fp_set:Nn \l_lst_tmpc_fp {\l_lst_tmpa_fp + \g_lst_line_height_dim}
        \fp_compare:nNnT \l_lst_tmpc_fp < \l_lst_tmpb_fp {
            % if we haven't reached end of box
            % acquire current color
            \edef\l_lst_tmpc_tl{\clist_item:Nn \g_lst_colors_clist {
                    \int_mod:nn {\l_lst_tmpa_int}{\clist_count:N \g_lst_colors_clist} + 1
                }
            }
            
            \bool_if:NTF \g_lst_debug_bool {
                \draw[draw=black] 
                ($(interior.north~west)+(\dim_use:N \g_lst_left_dim, -\fp_use:N \l_lst_tmpa_fp pt)$) 
                rectangle ++(\dim_use:N \l_lst_tmpa_dim, -\dim_use:N \g_lst_line_height_dim);
            } {
                \draw[draw=none,fill=\l_lst_tmpc_tl]
                ($(interior.north~west)+(\dim_use:N \g_lst_left_dim, -\fp_use:N \l_lst_tmpa_fp pt)$) 
                rectangle ++(\dim_use:N \l_lst_tmpa_dim, -\dim_use:N \g_lst_line_height_dim);
            }
            
        }
        \fp_set_eq:NN \l_lst_tmpa_fp \l_lst_tmpc_fp
        \int_incr:N \l_lst_tmpa_int
    }
    
}


\ExplSyntaxOff
\makeatother


\begin{document}

\begin{tcblisting}{lststyle}
  const BlogTitle = ({ children }) => (
    <h3>{children}</h3>
  );
  // class component
  class BlogPost extends React.Component {
    renderTitle(title) {
      return <BlogTitle>{title}</BlogTitle>
    };
    render() {
      return (
      <div className="blog-body">
        {this.renderTitle(this.props.title)}
        <p>{this.props.body}</p>
      </div>
      );
    }
  }
\end{tcblisting}

\end{document}

相关内容