为了寻求更好的解决方案如何使用时更改特定线条的外观\lstincludelisting
,我偶然发现了linebackground=
,我在 Martin Scharrer 的回答中使用列表创建斑马效果。
基本思想是有一个宏
% \btLstHL<overlay spec>{range list}
\newcommand<>{\btLstHL}[1]{%
\only#2{\btIfInRange{\value{lstnumber}}{#1}{\color{blue!30}}{}}%
}%
\color{blue!30}
如果当前行适合范围,则扩展为 a ,\empty
否则扩展为 (?)。然后将其与linebackground
\begin{lstlisting}[language=C, gobble=6,linebackgroundcolor={%
\btLstHL{4}%
\btLstHL<1>{1-2,5-6}%
\btLstHL<2>{7}%
}]
/**
* Prints Hello World.
**/
#include <stdio.h>
int main(void) {
printf("Hello World!");
return 0;
}
\end{lstlisting}
然而,这并没有按预期工作,因为所有未选定的行现在都得到了白色背景:
罪魁祸首,我猜,正在实施中lstlinebackground
,以及在其处理过程中如何btLstHL
扩展:
\lst@Key{linebackgroundcolor}{}{%
\def\lst@linebgrdcolor{#1}%
}
\newcommand{\lst@linebgrd}{%
\ifx\lst@linebgrdcolor\empty\else % PROBLEM: for \btLstHL does not expand to \empty ???
\rlap{%
\lst@basicstyle
\color{-.}% By default use the opposite (`-`) of the current color (`.`) as background
\lst@linebgrdcolor{%
\kern-\dimexpr\lst@linebgrdsep\relax%
\lst@linebgrdcmd{\lst@linebgrdwidth}{\lst@linebgrdheight}{\lst@linebgrddepth}%
}%
}%
\fi
}
显然,\btLstHL
扩展为“无”,但\empty
对于未选定的行则不然,这会导致\lst@linebgrd
背景突出显示,但使用其默认颜色,与当前文本颜色(黑色)相反。
这时我迷失了 :-(
那么,如果该线不在给定范围内,\btLstHL
它就扩展为如何定义?\empty
完成 MWE:
\documentclass{beamer}
% beamer class setup
\usecolortheme{rose}
\setbeamertemplate{navigation symbols}{}
% we use UTF8
\usepackage[utf8]{inputenc}
% font setup
\usepackage[T1]{fontenc}
\usepackage[scaled=0.85]{beramono}
\usepackage{xcolor,listings, pgffor}
\makeatletter
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% \btIfInRange{number}{range list}{TRUE}{FALSE}
%
% Test if int number <number> is element of a (comma separated) list of ranges
% (such as: {1,3-5,7,10-12,14}) and processes <TRUE> or <FALSE> respectively
\newcount\bt@rangea
\newcount\bt@rangeb
\newcommand\btIfInRange[2]{%
\global\let\bt@inrange\@secondoftwo%
\edef\bt@rangelist{#2}%
\foreach \range in \bt@rangelist {%
\afterassignment\bt@getrangeb%
\bt@rangea=0\range\relax%
\pgfmathtruncatemacro\result{ ( #1 >= \bt@rangea) && (#1 <= \bt@rangeb) }%
\ifnum\result=1\relax%
\breakforeach%
\global\let\bt@inrange\@firstoftwo%
\fi%
}%
\bt@inrange%
}
\newcommand\bt@getrangeb{%
\@ifnextchar\relax%
{\bt@rangeb=\bt@rangea}%
{\@getrangeb}%
}
\def\@getrangeb-#1\relax{%
\ifx\relax#1\relax%
\bt@rangeb=100000% \maxdimen is too large for pgfmath
\else%
\bt@rangeb=#1\relax%
\fi%
}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% \btLstHL<overlay spec>{range list}
%
\newcommand<>{\btLstHL}[1]{%
\only#2{\btIfInRange{\value{lstnumber}}{#1}{\color{blue!30}}{}}%
}%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% \btInputEmph<overlay spec>[listing options]{range list}{file name}
%
\newcommand<>{\btLstInputEmph}[3][\empty]{%
\only#4{%
\lstset{linebackgroundcolor=\btLstHL{#2}}%
\lstinputlisting{#3}%
}% \only
}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% lstlinebgrd.sty
%% see: https://tex.stackexchange.com/questions/18969/creating-a-zebra-effect-using-listings/18989#18989
%%
%% This small package is not yet published/not commonly available.
%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Patch line number key to call line background macro
\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}}
% New keys
\lst@Key{linebackgroundcolor}{}{%
\def\lst@linebgrdcolor{#1}%
}
\lst@Key{linebackgroundsep}{0pt}{%
\def\lst@linebgrdsep{#1}%
}
\lst@Key{linebackgroundwidth}{\linewidth}{%
\def\lst@linebgrdwidth{#1}%
}
\lst@Key{linebackgroundheight}{\ht\strutbox}{%
\def\lst@linebgrdheight{#1}%
}
\lst@Key{linebackgrounddepth}{\dp\strutbox}{%
\def\lst@linebgrddepth{#1}%
}
\lst@Key{linebackgroundcmd}{\color@block}{%
\def\lst@linebgrdcmd{#1}%
}
% Line Background macro
\newcommand{\lst@linebgrd}{%
\ifx\lst@linebgrdcolor\empty\else
\rlap{%
\lst@basicstyle
\color{-.}% By default use the opposite (`-`) of the current color (`.`) as background
\lst@linebgrdcolor{%
\kern-\dimexpr\lst@linebgrdsep\relax%
\lst@linebgrdcmd{\lst@linebgrdwidth}{\lst@linebgrdheight}{\lst@linebgrddepth}%
}%
}%
\fi
}
\makeatother
\begin{document}
\begin{frame}[fragile]{Problem}
\begin{alertblock}{A cool app; unfortunately it has a white background}
\begin{lstlisting}[language=C, gobble=6,linebackgroundcolor={%
\btLstHL{4}%
\btLstHL<1>{1-2,5-6}%
\btLstHL<2>{7}%
}]
/**
* Prints Hello World.
**/
#include <stdio.h>
int main(void) {
printf("Hello World!");
return 0;
}
\end{lstlisting}
\end{alertblock}
\end{frame}
\end{document}
答案1
在更好地理解了它的\ifx
实际作用之后(感谢 whlt3!)我得出结论,我无法\btLstHL
以第一级扩展的方式定义它\empty
。
我的当前解决方法是走另一条路线并重新定义\lst@linebgrdcmd
,\btLstHL
以便它成为未选定行的无操作:
% \btLstHL<overlay spec>{range list}
\newcommand<>{\btLstHL}[1]{%
\only#2{\btIfInRange{\value{lstnumber}}{#1}%
{\color{blue!30}}%
{\def\lst@linebgrdcmd####1####2####3{}}% define as no-op
}%
}%
笔记:要不使用 beamer 来使用它,只需<>
从\newcommand
和\only#2
命令(包括其花括号)中删除 即可。
这样我确实得到了预期的结果。但是,这个解决方案有点“老套”。我仍然愿意接受更好的方法。