我正在使用 Beamer 创建演示文稿,并尝试突出显示算法中的某些行。我实际上正在使用algcompatible
。
我找到了解决方案这里并根据该解决方案创建了几个新命令来突出显示算法中的某些代码行:
\newcommand{\algcolor}[2]{\hspace*{-\fboxsep}\colorbox{#1}{\parbox{\linewidth}{#2}}}
\newcommand{\algemph}[1]{\algcolor{GreenYellow}{#1}}
效果很好,但在某些情况下会失败,具体取决于我想要突出显示的行。例如,以下算法可以正常工作:
\begin{algorithmic}[1]
\FORALL{$elem$ in $collection$}
\STATE $foo(elem)$
\algemph{\STATE $bar(elem)$}
\ENDFOR
\end{algorithmic}
但是,如果我在循环中交换这两个语句:
\begin{algorithmic}[1]
\FORALL{$elem$ in $collection$}
\algemph{\STATE $bar(elem)$}
\STATE $foo(elem)$
\ENDFOR
\end{algorithmic}
调用时出现此错误pdflatex
:
! Missing \endcsname inserted.
<to be read again>
\ALG@currentblock@2
l.19 \end{frame}
这里有一个最小的可重现测试用例:
\PassOptionsToPackage{dvipsnames}{xcolor} % prevent an option clash
\documentclass{beamer}
\usepackage[dvipsnames]{xcolor}
\usepackage{algcompatible}
\newcommand{\algcolor}[2]{\hspace*{-\fboxsep}\colorbox{#1}{\parbox{\linewidth}{#2}}}
\newcommand{\algemph}[1]{\algcolor{GreenYellow}{#1}}
\begin{document}
\begin{frame}{Test Frame}
\begin{algorithmic}[1]
\FORALL{$elem$ in $collection$}
\algemph{\STATE $bar(elem)$}
\STATE $foo(elem)$
\ENDFOR
\end{algorithmic}
\end{frame}
\end{document}
是否可以修复我当前使用的方法?算法中还有其他着色线条的解决方案吗?
答案1
这是一个可能的解决方案,使用\tikzmark
Andrew Stacey 在his answer
到tikzmark 在首次运行时会有不同的行为(并且标记位置尚不可用)。
这个想法是定义一个新的循环和声明系列,完全类似于所提供的algcompatible
,但自动添加彩色背景;对于形式为的每个命令,\X
现在您都有相应的命令\CX
(在原始名称前加上大写字母C
),它会自动处理颜色;例如,现在您有标准\STATE
命令和彩色版本\CSTATE
;每个命令的功能和语法\CX
与其对应命令完全相同\X
。
\PassOptionsToPackage{dvipsnames}{xcolor}
\documentclass{beamer}
\usepackage[dvipsnames]{xcolor}
\usepackage{algcompatible}
\usepackage{tikz}
\usetikzlibrary{calc}
\makeatletter
% code borrowed from Andrew Stacey; See
% https://tex.stackexchange.com/a/50054/3954
\tikzset{%
remember picture with id/.style={%
remember picture,
overlay,
save picture id=#1,
},
save picture id/.code={%
\edef\pgf@temp{#1}%
\immediate\write\pgfutil@auxout{%
\noexpand\savepointas{\pgf@temp}{\pgfpictureid}}%
},
if picture id/.code args={#1#2#3}{%
\@ifundefined{save@pt@#1}{%
\pgfkeysalso{#3}%
}{
\pgfkeysalso{#2}%
}
}
}
\def\savepointas#1#2{%
\expandafter\gdef\csname save@pt@#1\endcsname{#2}%
}
\def\tmk@labeldef#1,#2\@nil{%
\def\tmk@label{#1}%
\def\tmk@def{#2}%
}
\tikzdeclarecoordinatesystem{pic}{%
\pgfutil@in@,{#1}%
\ifpgfutil@in@%
\tmk@labeldef#1\@nil
\else
\tmk@labeldef#1,(0pt,0pt)\@nil
\fi
\@ifundefined{save@pt@\tmk@label}{%
\tikz@scan@one@point\pgfutil@firstofone\tmk@def
}{%
\pgfsys@getposition{\csname save@pt@\tmk@label\endcsname}\save@orig@pic%
\pgfsys@getposition{\pgfpictureid}\save@this@pic%
\pgf@process{\pgfpointorigin\save@this@pic}%
\pgf@xa=\pgf@x
\pgf@ya=\pgf@y
\pgf@process{\pgfpointorigin\save@orig@pic}%
\advance\pgf@x by -\pgf@xa
\advance\pgf@y by -\pgf@ya
}%
}
\makeatother
% end of Andrew's code
% main command to draw the colored background
\newcounter{mymark}
\newcommand\ColorLine{%
\stepcounter{mymark}%
\tikz[remember picture with id=mark-\themymark,overlay] {;}%
\begin{tikzpicture}[remember picture,overlay]%
\filldraw[GreenYellow]%
let \p1=(pic cs:mark-\themymark),
\p2=(current page.east) in
([xshift=-0.3em,yshift=-0.7ex]0,\y1) rectangle ++([xshift=-1.2cm]\x2,\baselineskip);
\end{tikzpicture}%
}%
% colored loops and declarations
\makeatletter
\algnewcommand\CREQUIRE{\item[\ColorLine\algorithmicrequire]}%
\algnewcommand\CENSURE{\item[\ColorLine\algorithmicensure]}%
\algnewcommand\CSTATE{\State\ColorLine}%
\algnewcommand\CSTATEx{\Statex\ColorLine}%
\algnewcommand\CCOMMENT{\Comment\ColorLine}%
\algdef{SE}[WHILE]{CWHILE}{ENDWHILE}%
[2][default]{\ColorLine\algorithmicwhile\ #2\ \algorithmicdo\ALG@compatcomm{#1}}%
{\algorithmicend\ \algorithmicwhile}%
\algdef{SE}[FOR]{CFOR}{ENDFOR}%
[2][default]{\ColorLine\algorithmicfor\ #2\ \algorithmicdo\ALG@compatcomm{#1}}%
{\algorithmicend\ \algorithmicfor}%
\algdef{S}[FOR]{CFORALL}%
[2][default]{\ColorLine\algorithmicforall\ #2\ \algorithmicdo\ALG@compatcomm{#1}}%
\algdef{SE}[LOOP]{CLOOP}{ENDLOOP}%
[1][default]{\ColorLine\algorithmicloop\ALG@compatcomm{#1}}%
{\algorithmicend\ \algorithmicloop}%
\algdef{SE}[REPEAT]{CREPEAT}{UNTIL}%
[1][default]{\ColorLine\algorithmicrepeat\ALG@compatcomm{#1}}%
[1]{\algorithmicuntil\ #1}%
\algdef{SE}[IF]{CIF}{ENDIF}%
[2][default]{\ColorLine\algorithmicif\ #2\ \algorithmicthen\ALG@compatcomm{#1}}%
{\algorithmicend\ \algorithmicif}%
\algdef{C}[IF]{IF}{CELSIF}%
[2][default]{\ColorLine\algorithmicelse\ \algorithmicif\ #2\ \algorithmicthen\ALG@compatcomm{#1}}%
\algdef{Ce}[ELSE]{IF}{CELSE}{ENDIF}%
[1][default]{\ColorLine\algorithmicelse\ALG@compatcomm{#1}}%
\makeatother
\begin{document}
\begin{frame}{Test Frame 1}
\begin{algorithmic}[1]
\CREQUIRE Some initial values
\ENSURE Some conditions
\CLOOP
\STATE$bar(elem)$
\STATE$baz(elem)$
\CFOR{$quality\ge 9$}
\STATE$a\gets perfect$
\CSTATE$a\gets unusable$
\ENDFOR
\ENDLOOP
\end{algorithmic}
\end{frame}
\begin{frame}{Test Frame 2}
\begin{algorithmic}[1]
\REQUIRE Some initial values
\CENSURE Some conditions
\FORALL{$elem$ in $collection$}
\STATE$bar(elem)$
\CSTATE$foo(elem)$
\STATE$baz(elem)$
\CIF{$quality\ge 9$}
\STATE$a\gets perfect$
\ELSE
\CSTATE$a\gets unusable$
\ENDIF
\ENDFOR
\end{algorithmic}
\end{frame}
\end{document}
所获文件的图像:
该文件必须处理两次。
这里有一个小小的变化,其中背景颜色的条纹具有统一的长度:
\PassOptionsToPackage{dvipsnames}{xcolor}
\documentclass{beamer}
\usepackage[dvipsnames]{xcolor}
\usepackage{algcompatible}
\usepackage{tikz}
\usetikzlibrary{calc}
\makeatletter
% code borrowed from Andrew Stacey; See
% https://tex.stackexchange.com/a/50054/3954
\tikzset{%
remember picture with id/.style={%
remember picture,
overlay,
save picture id=#1,
},
save picture id/.code={%
\edef\pgf@temp{#1}%
\immediate\write\pgfutil@auxout{%
\noexpand\savepointas{\pgf@temp}{\pgfpictureid}}%
},
if picture id/.code args={#1#2#3}{%
\@ifundefined{save@pt@#1}{%
\pgfkeysalso{#3}%
}{
\pgfkeysalso{#2}%
}
}
}
\def\savepointas#1#2{%
\expandafter\gdef\csname save@pt@#1\endcsname{#2}%
}
\def\tmk@labeldef#1,#2\@nil{%
\def\tmk@label{#1}%
\def\tmk@def{#2}%
}
\tikzdeclarecoordinatesystem{pic}{%
\pgfutil@in@,{#1}%
\ifpgfutil@in@%
\tmk@labeldef#1\@nil
\else
\tmk@labeldef#1,(0pt,0pt)\@nil
\fi
\@ifundefined{save@pt@\tmk@label}{%
\tikz@scan@one@point\pgfutil@firstofone\tmk@def
}{%
\pgfsys@getposition{\csname save@pt@\tmk@label\endcsname}\save@orig@pic%
\pgfsys@getposition{\pgfpictureid}\save@this@pic%
\pgf@process{\pgfpointorigin\save@this@pic}%
\pgf@xa=\pgf@x
\pgf@ya=\pgf@y
\pgf@process{\pgfpointorigin\save@orig@pic}%
\advance\pgf@x by -\pgf@xa
\advance\pgf@y by -\pgf@ya
}%
}
% end of Andrew's code
\newlength\AlgIndent
\setlength\AlgIndent{0pt}
% main command to draw the colored background
\newcounter{mymark}
\newcommand\ColorLine{%
\stepcounter{mymark}%
\tikz[remember picture with id=mark-\themymark,overlay] {;}%
\begin{tikzpicture}[remember picture,overlay]%
\filldraw[GreenYellow]%
let \p1=(pic cs:mark-\themymark),
\p2=(current page.east) in
([xshift=-\[email protected],yshift=-0.7ex]0,\y1) rectangle ++(\linewidth+\AlgIndent,\baselineskip);
\end{tikzpicture}%
}%
% colored loops and declarations
\algnewcommand\CREQUIRE{\item[\setlength\AlgIndent{1.6em}\ColorLine\algorithmicrequire]}%
\algnewcommand\CENSURE{\item[\setlength\AlgIndent{1.6em}\ColorLine\algorithmicensure]}%
\algnewcommand\CSTATE{\State\ColorLine}%
\algnewcommand\CSTATEx{\Statex\ColorLine}%
\algnewcommand\CCOMMENT{\Comment\ColorLine}%
\algdef{SE}[WHILE]{CWHILE}{ENDWHILE}%
[2][default]{\ColorLine\algorithmicwhile\ #2\ \algorithmicdo\ALG@compatcomm{#1}}%
{\algorithmicend\ \algorithmicwhile}%
\algdef{SE}[FOR]{CFOR}{ENDFOR}%
[2][default]{\ColorLine\algorithmicfor\ #2\ \algorithmicdo\ALG@compatcomm{#1}}%
{\algorithmicend\ \algorithmicfor}%
\algdef{S}[FOR]{CFORALL}%
[2][default]{\ColorLine\algorithmicforall\ #2\ \algorithmicdo\ALG@compatcomm{#1}}%
\algdef{SE}[LOOP]{CLOOP}{ENDLOOP}%
[1][default]{\ColorLine\algorithmicloop\ALG@compatcomm{#1}}%
{\algorithmicend\ \algorithmicloop}%
\algdef{SE}[REPEAT]{CREPEAT}{UNTIL}%
[1][default]{\ColorLine\algorithmicrepeat\ALG@compatcomm{#1}}%
[1]{\algorithmicuntil\ #1}%
\algdef{SE}[IF]{CIF}{ENDIF}%
[2][default]{\ColorLine\algorithmicif\ #2\ \algorithmicthen\ALG@compatcomm{#1}}%
{\algorithmicend\ \algorithmicif}%
\algdef{C}[IF]{IF}{CELSIF}%
[2][default]{\ColorLine\algorithmicelse\ \algorithmicif\ #2\ \algorithmicthen\ALG@compatcomm{#1}}%
\algdef{Ce}[ELSE]{IF}{CELSE}{ENDIF}%
[1][default]{\ColorLine\algorithmicelse\ALG@compatcomm{#1}}%
\makeatother
\begin{document}
\begin{frame}{Test Frame 1}
\begin{algorithmic}[1]
\CREQUIRE Some initial values
\ENSURE Some conditions
\CLOOP
\STATE$bar(elem)$
\STATE$baz(elem)$
\CFOR{$quality\ge 9$}
\STATE$a\gets perfect$
\CSTATE$a\gets unusable$
\ENDFOR
\ENDLOOP
\end{algorithmic}
\end{frame}
\begin{frame}{Test Frame 2}
\begin{algorithmic}[1]
\REQUIRE Some initial values
\CENSURE Some conditions
\FORALL{$elem$ in $collection$}
\STATE$bar(elem)$
\CSTATE$foo(elem)$
\STATE$baz(elem)$
\CIF{$quality\ge 9$}
\STATE$a\gets perfect$
\ELSE
\CSTATE$a\gets unusable$
\ENDIF
\ENDFOR
\end{algorithmic}
\end{frame}
\end{document}
答案2
下面的定义\algemph
有效,但应按以下方式使用:
\STATE \algemph{<stuff>}
\PassOptionsToPackage{dvipsnames}{xcolor} % prevent an option clash
\documentclass{beamer}% http://ctan.org/pkg/beamer
\usepackage[dvipsnames]{xcolor}% http://ctan.org/pkg/xcolor
\usepackage{algcompatible}% http://ctan.org/pkg/algorithmicx
\makeatletter
\newcommand{\algcolor}[2]{%
\hskip-\ALG@thistlm\colorbox{#1}{\parbox{\dimexpr\linewidth-2\fboxsep}{\hskip\ALG@thistlm\relax #2}}%
}
\newcommand{\algemph}[1]{\algcolor{GreenYellow}{#1}}
\makeatother
\begin{document}
\begin{frame}{Test Frame}
\begin{algorithmic}[1]
\FORALL{$elem$ in $collection$}
\STATE $foo(elem)$
\STATE \algemph{$bar(elem)$}
\ENDFOR
\FORALL{$elem$ in $collection$}
\STATE \algemph{$bar(elem)$}
\STATE $foo(elem)$
\ENDFOR
\end{algorithmic}
\end{frame}
\end{document}
合理的方法是设置行号第一的(在algorithmicx
) 包括缩进。\algemph
随后跳回(水平),然后设置彩色框(重新插入所需的缩进)。