解决方法 1

解决方法 1

所有内容都在标题中。我想在列出包的字符前为文本添加颜色。

例如,我想在 makefile 中为行首和:或之间的文本添加颜色。=

我尝试使用moredelimiters但没有成功。

在此处输入图片描述

\documentclass{article}

\usepackage{listings}
\usepackage{xcolor}
\definecolor{keycolor}{RGB}{172, 42, 42}
\definecolor{mbleu}{RGB}{64,96,127}
\definecolor{vimvert}{RGB}{46, 139, 87}

\lstdefinestyle{global}{
  basicstyle=\ttfamily\scriptsize\color{black!90},%
  stringstyle=\itshape\color{magenta},%
  showstringspaces=false,%
  keywordstyle={\bfseries\color{keycolor}},%
  commentstyle=\color{blue}\slshape,%
  framexleftmargin=1mm,%
  backgroundcolor=\color{black!2},%
}

\lstdefinestyle{makefile}{
  style=global,%
  morecomment=[l][commentstyle]{\#},%
  emphstyle={\color{vimvert}},%
  moredelim=[s][emphstyle]{\$(}{)}%
}

\begin{document}

\begin{lstlisting}[style=makefile]
.SUFFIXES: .inc .f .f90 .F

# all CPP processed fortran files have the extension .f90
SUFFIX=.f90

#-----------------------------------------------------------------------
# this release should be fpp clean
# we now recommend fpp as preprocessor
# if this fails go back to cpp
CPP_=fpp -f_com=no -free -w0 $*.F $*$(SUFFIX)

vasp: $(SOURCE) $(FFT3D) $(INC) main.o 
    rm -f vasp
    $(FCL) -o vasp main.o  $(SOURCE)   $(FFT3D) $(LIB) $(LINK)
makeparam: $(SOURCE) $(FFT3D) makeparam.o main.F $(INC)
    $(FCL) -o makeparam  $(LINK) makeparam.o $(SOURCE) $(FFT3D) $(LIB)
zgemmtest: zgemmtest.o base.o random.o $(INC)
    $(FCL) -o zgemmtest $(LINK) zgemmtest.o random.o base.o $(LIB)
dgemmtest: dgemmtest.o base.o random.o $(INC)
    $(FCL) -o dgemmtest $(LINK) dgemmtest.o random.o base.o $(LIB) 
ffttest: base.o smart_allocate.o mpi.o mgrid.o random.o ffttest.o $(FFT3D) $(INC)
    $(FCL) -o ffttest $(LINK) ffttest.o mpi.o mgrid.o random.o smart_allocate.o base.o $(FFT3D) $(LIB)
kpoints: $(SOURCE) $(FFT3D) makekpoints.o main.F $(INC)
    $(FCL) -o kpoints $(LINK) makekpoints.o $(SOURCE) $(FFT3D) $(LIB)

clean:  
    -rm -f *.g *.f *.o *.L *.mod ; touch *.F
\end{lstlisting}

\end{document}

答案1

.SUFFIXES是预定义语言中的关键字[gnu]makeSUFFIX是预定义的,但通过和和键ACSL的组合加载语言似乎没有产生预期的效果。我建议您按照以下解决方法定义您的。languagealsolanguageclassoffsetmakefile

解决方法 1

在此解决方案中,冒号也是彩色的。只需按如下方式:设置:\lstdefinestyle

\lstdefinestyle{global}{
basicstyle=\ttfamily\scriptsize\color{black!90},%
stringstyle=\itshape\color{magenta},%
showstringspaces=false,%
keywordstyle={[1]\bfseries\color{keycolor}},%
keywordstyle={[2]\bfseries\color{mbleu}},%
commentstyle=\color{blue}\slshape,%
framexleftmargin=1mm,%
backgroundcolor=\color{black!2},%
}

\lstdefinestyle{makefile}{
otherkeywords={.SUFFIXES},
alsoletter={:},
morekeywords=[1]{SUFFIX, CPP_},
morekeywords=[2]{vasp:,makeparam:,zgemmtest:,dgemmtest:,ffttest:,kpoints:,clean:},
style=global,%
morecomment=[l][commentstyle]{\#},%
emphstyle={\color{vimvert}},%
moredelim=[s][\color{vimvert}]{\$(}{)}%
}

输出

在此处输入图片描述

解释

  • otherkeywords定义包含其他字符的关键字,或以数字开头
  • alsoletter构成:一个字母,否则包含这些符号的单词将不会被识别为单词。
  • 您可以使用语法或制作单独的morekeywords或列表。这里我选择了或 ,但您可以根据自己的喜好进行修改。然后您必须将此列表与相应的或进行匹配。moreemphmorekeywords=[<number>]{<list of keywords>}moreemph=[<number>]{<list of emphs>}keywordskeywordstyleemphstyle

解决方法 2

您可能不希望冒号有颜色。在这种情况下,您可以使用(猜猜是什么?)moredelimmoredelim=[is][\color{mbleu}]{/*}{*/},手册中所述:

更通用的分隔符可以用键 moredelim 来定义。合法的类型是ls。这些类型前面可以加i,但这次只有分隔符会从输出中丢弃。

以下是完整代码

%\documentclass{article}
\documentclass[preview,border=5]{standalone}

\usepackage{geometry}
\geometry{margin=1in}
\usepackage[procnames]{listings}
\usepackage{xcolor}
\definecolor{keycolor}{RGB}{172, 42, 42}
\definecolor{mbleu}{RGB}{64,96,127}
\definecolor{vimvert}{RGB}{46, 139, 87}

\lstdefinestyle{global}{
basicstyle=\ttfamily\scriptsize\color{black!90},%
stringstyle=\itshape\color{magenta},%
showstringspaces=false,%
keywordstyle=\bfseries\color{keycolor},%
commentstyle=\color{blue}\slshape,%
framexleftmargin=1mm,%
backgroundcolor=\color{black!2},%
    }

\lstdefinestyle{makefile}{
otherkeywords={.SUFFIXES},
morekeywords={SUFFIX, CPP_,},
moredelim=[is][\color{mbleu}]{/*}{*/},
style=global,%
morecomment=[l][commentstyle]{\#},%
emphstyle={\color{vimvert}},%
moredelim=[s][\color{vimvert}]{\$(}{)}%
}

\begin{document}

\begin{lstlisting}[style=makefile]
.SUFFIXES: .inc .f .f90 .F

# all CPP processed fortran files have the extension .f90
SUFFIX=.f90

#-----------------------------------------------------------------------
# this release should be fpp clean
# we now recommend fpp as preprocessor
# if this fails go back to cpp
CPP_=fpp -f_com=no -free -w0 $*.F $*$(SUFFIX)

/*vasp*/: $(SOURCE) $(FFT3D) $(INC) main.o 
        rm -f vasp
        $(FCL) -o vasp main.o  $(SOURCE)   $(FFT3D) $(LIB) $(LINK)
/*makeparam*/: $(SOURCE) $(FFT3D) makeparam.o main.F $(INC)
        $(FCL) -o makeparam  $(LINK) makeparam.o $(SOURCE) $(FFT3D) $(LIB)
/*zgemmtest*/: zgemmtest.o base.o random.o $(INC)
        $(FCL) -o zgemmtest $(LINK) zgemmtest.o random.o base.o $(LIB)
/*dgemmtest*/: dgemmtest.o base.o random.o $(INC)
        $(FCL) -o dgemmtest $(LINK) dgemmtest.o random.o base.o $(LIB) 
/*ffttest*/: base.o smart_allocate.o mpi.o mgrid.o random.o ffttest.o $(FFT3D) $(INC)
        $(FCL) -o ffttest $(LINK) ffttest.o mpi.o mgrid.o random.o smart_allocate.o base.o $(FFT3D) $(LIB)
/*kpoints*/: $(SOURCE) $(FFT3D) makekpoints.o main.F $(INC)
        $(FCL) -o kpoints $(LINK) makekpoints.o $(SOURCE) $(FFT3D) $(LIB)
/*clean*/:  
        -rm -f *.g *.f *.o *.L *.mod ; touch *.F
\end{lstlisting}

\end{document}

输出

在此处输入图片描述

答案2

在此处输入图片描述

hpesoj626 发布的答案显示了两种产生所需输出的方法;对于少量行,它们是完全可以接受的。不幸的是,随着目标数量的增加,这两种方法很快就会变得乏味且难以维护,因为它们缺乏自动化:

  • 解决方法 1 需要将所有make目标名称(例如vaspmakeparam等)定义为关键字;
  • 解决方法 2 需要通过用自定义分隔符括住所有目标名称来改变列表。

我假设您需要一个自动化解决方案,既不需要定义一长串关键词,也不需要修改原始列表。以下假设您的问题确实是

我可以让“列表”自动突出显示给定字符之前的文本吗?如果可以,怎么做?

简短回答

是又不是;但大多情况下不是。

更详细的答案

listings包以非常线性的方式读取列表。据我所知,它无法真正向前看很远,然后回溯以根据找到的内容有条件地应用样式。

不过,在某些情况下,您可以listings随意修改 的内部结构以获得所需的结果。您可以定义开关、计数器等,当遇到给定字符或标识符时,或者在某些listings“钩子”处,它们的值会更新。然后,您可以使用这些“状态变量”有条件地应用样式。

具体来说,在这里,为了仅使make目标以洋红色突出显示,我将每行开头的当前样式设置为洋红色(通过提供的钩子调用EveryLinelistings,并且一旦遇到冒号,我就会恢复为“默认”样式(黑色)。

请注意,如果您希望变量以不同于目标的样式突出显示,我的方法仍然要求您将make变量定义为关键字;我想不出一种可靠的方法让变量自动以不同于目标的样式突出显示。但是,我相信典型 makefile 中的变量数量通常少于目标数量,因此将每个变量定义为listings关键字应该不会太麻烦……

为什么操作中缺少制表符?

如果你简单地复制下面的代码,粘贴到你最喜欢的编辑器中,然后编译,你将不是获得与我的屏幕截图中所示的相同输出。这是因为 makefile 中的命令行前面有制表位,但 TeX.SX 用四个空格替换所有制表位。您必须在编译之前手动重新插入我的代码中的制表位;然后一切都应该按预期工作。

\documentclass{article}

\usepackage[margin=2cm]{geometry}
\usepackage{textcomp}
\usepackage{xcolor}
\usepackage{listings}

% --- color definitions ---
\definecolor{mktext}    {RGB}{000, 043, 054}
\definecolor{mktarget}  {RGB}{211, 054, 130}
\definecolor{mkstring}  {RGB}{000, 127, 127}
\definecolor{mkvariable}{RGB}{038, 139, 210}
\definecolor{mkkeyword} {RGB}{133, 153, 000}
\definecolor{mklinecont}{RGB}{220, 050, 047}
\definecolor{mkcomment} {RGB}{088, 110, 117}
\definecolor{mkcommand} {RGB}{042, 161, 152}

% --- auxiliary macros for styles ---
\newcommand\mktextstyle{\color{mktext}}
\newcommand\mktargetstyle{\color{mktarget}}
\newcommand\mkstringstyle{\color{mkstring}}
\newcommand\mkvariablestyle{\color{mkvariable}}
\newcommand\mkkeywordstyle{\color{mkkeyword}}
\newcommand\mklinecontstyle{\color{mklinecont}}
\newcommand\mkcommentstyle{\slshape\color{mkcomment}}
\newcommand\mkcommandstyle{\color{mkcommand}}

\makeatletter
% --- context switches ---
\newif\iftarget@make@
\newif\iflinecont@make@

% --- hook into listings to keep track of context ---
\lst@AddToHook{InitVarsBOL}
{%
  \iflinecont@make@%
    \global\target@make@false%
  \else
    \global\target@make@true%
  \fi
  \global\linecont@make@false%
}

\lst@AddToHook{Output}
{%
  \ifnum\lst@mode=\lst@Pmode%
      \iftarget@make@%
        \gdef\globalstyle@make{\the@lststyle}%
        \def\lst@thestyle{\mktargetstyle}%
      \fi
    \fi
  \ifnum\lst@mode=\lst@Pmode% only test for keyword if we're in "processing" mode
    \lsthk@DetectKeywords%
  \fi
}

\lstdefinestyle{make-pretty}
{
  upquote=true,
  showstringspaces=false,
  basicstyle=\ttfamily\scriptsize\mktextstyle,
  sensitive=true,
  alsoletter=.-,
  keywords = {.CC,.CFLAGS,.PHONY,.SUFFIXES,SUFFIX,CPP_},
  keywordstyle = \mkkeywordstyle,
  moredelim=[is][\mkvariablestyle(\aftergroup\closingparen@make]{(}{)},
  moredelim=*[l][\mkcommandstyle]{\^^I},
  morestring=[b]',
  morestring=[b]",
  stringstyle=\mkstringstyle,
  literate =
    {\%}{{{\mkvariablestyle\%}}}1
    {\$}{{{\mkvariablestyle\$}}}1
    {\$*}{{{\mkvariablestyle\$*}}}2
    {\\}{{{\mklinecontstyle\lstum@backslash}}}1,
  MoreSelectCharTable =
    \processColon@make
    \processEqual@make
    \processBackslash@make
    \processTab@make,
  morecomment = [l]{\#},
  commentstyle = \mkcommentstyle,
}

% --- helper macros ---
\newcommand\closingparen@make{{\mkvariablestyle)}}

\newcommand\processEqual@make
{%
  \lst@DefSaveDef{`=}\equal@make%
  {%
    \equal@make%
    \global\target@make@false%
    \def\lst@thestyle{\globalstyle@make}%
  }%
}

\newcommand\processColon@make
{%
  \lst@DefSaveDef{`:}\colon@make%
  {%
    \colon@make%
    \global\target@make@false%
    \def\lst@thestyle{\globalstyle@make}%
  }%
}

\newcommand\processBackslash@make
{%
  \lst@DefSaveDef{`\\}\backslash@make%
  {%
    \backslash@make%
    \ifnum\lst@mode=\lst@Pmode%
      \global\linecont@make@true%
      \def\lst@thestyle{\globalstyle@make}%
    \fi
  }%
}

\newcommand\processTab@make
{%
  \lst@DefSaveDef{`^^I}\tabchar@make%
  {%
    \tabchar@make%
    \global\target@make@false%
  }%
}
\makeatother

\begin{document}
\begin{lstlisting}[style=make-pretty]
.SUFFIXES: .inc .f .f90 .F

# all CPP processed fortran files have the extension .f90
SUFFIX=.f90

#-----------------------------------------------------------------------
# this release should be fpp clean
# we now recommend fpp as preprocessor
# if this fails go back to cpp
CPP_=fpp -f_com=no -free -w0 $*.F $*$(SUFFIX)

vasp: $(SOURCE) $(FFT3D) $(INC) main.o 
    rm -f vasp
    $(FCL) -o vasp main.o  $(SOURCE)   $(FFT3D) $(LIB) $(LINK)
makeparam: $(SOURCE) $(FFT3D) makeparam.o main.F $(INC)
    $(FCL) -o makeparam  $(LINK) makeparam.o $(SOURCE) $(FFT3D) $(LIB)
zgemmtest: zgemmtest.o base.o random.o $(INC)
    $(FCL) -o zgemmtest $(LINK) zgemmtest.o random.o base.o $(LIB)
dgemmtest: dgemmtest.o base.o random.o $(INC)
    $(FCL) -o dgemmtest $(LINK) dgemmtest.o random.o base.o $(LIB) 
ffttest: base.o smart_allocate.o mpi.o mgrid.o random.o ffttest.o $(FFT3D) $(INC)
    $(FCL) -o ffttest $(LINK) ffttest.o mpi.o mgrid.o random.o smart_allocate.o base.o $(FFT3D) $(LIB)
kpoints: $(SOURCE) $(FFT3D) makekpoints.o main.F $(INC)
    $(FCL) -o kpoints $(LINK) makekpoints.o $(SOURCE) $(FFT3D) $(LIB)

clean:  
    rm -f *.g *.f *.o *.L *.mod ; touch *.F
\end{lstlisting}
\end{document}

答案3

我最近发现了一种使用minted包的替代方法pygmentize。不便之处在于它不是完整的 LaTeX 解决方案。

铸造包

\documentclass{article}

\usepackage[margin=2cm]{geometry}
\usepackage{textcomp}
\usepackage{minted}

\begin{document}
\begin{minted}{make}
.SUFFIXES: .inc .f .f90 .F

# all CPP processed fortran files have the extension .f90
SUFFIX=.f90

#-----------------------------------------------------------------------
# this release should be fpp clean
# we now recommend fpp as preprocessor
# if this fails go back to cpp
CPP_=fpp -f_com=no -free -w0 $*.F $*$(SUFFIX)

vasp: $(SOURCE) $(FFT3D) $(INC) main.o 
    rm -f vasp
    $(FCL) -o vasp main.o  $(SOURCE)   $(FFT3D) $(LIB) $(LINK)
makeparam: $(SOURCE) $(FFT3D) makeparam.o main.F $(INC)
    $(FCL) -o makeparam  $(LINK) makeparam.o $(SOURCE) $(FFT3D) $(LIB)
zgemmtest: zgemmtest.o base.o random.o $(INC)
    $(FCL) -o zgemmtest $(LINK) zgemmtest.o random.o base.o $(LIB)
dgemmtest: dgemmtest.o base.o random.o $(INC)
    $(FCL) -o dgemmtest $(LINK) dgemmtest.o random.o base.o $(LIB) 
ffttest: base.o smart_allocate.o mpi.o mgrid.o random.o ffttest.o $(FFT3D) $(INC)
    $(FCL) -o ffttest $(LINK) ffttest.o mpi.o mgrid.o random.o smart_allocate.o base.o $(FFT3D) $(LIB)
kpoints: $(SOURCE) $(FFT3D) makekpoints.o main.F $(INC)
    $(FCL) -o kpoints $(LINK) makekpoints.o $(SOURCE) $(FFT3D) $(LIB)

clean:  
    rm -f *.g *.f *.o *.L *.mod ; touch *.F
\end{minted}
\end{document}

相关内容