在 listing 和 showexpl 包中,我的问题是代码遍历整个页面,另一个问题是,当页面结束时,如何将图像和代码分开,即上一页中的图像和新页面中的代码?
这是我的代码
\documentclass[12pt,a4paper]{article}
\usepackage[utf8]{vietnam}
\usepackage{amsmath}
\usepackage{amsfonts}
\usepackage{amssymb}
\usepackage{graphicx}
\usepackage[width=0.00cm, height=0.00cm, left=2.00cm, right=2.00cm, top=2.00cm, bottom=2.00cm]{geometry}
\usepackage{tkz-euclide}
\usepackage{tikz-3dplot}
\usepackage{tikz,tkz-tab,tkz-linknodes}
\usetkzobj{all}
\usetikzlibrary{decorations.text,calc,intersections,patterns}
%sao chép y nguyên code
\usepackage{caption}
\usepackage{listings}
\usepackage{showexpl}
\usepackage{color,xcolor}
\lstset{ % General setup for the package
language=TeX,
breaklines=true,
basicstyle=\small\sffamily,
numbers=left,
numberstyle=\tiny,
frame=tb,
tabsize=4,
columns=fixed,
showstringspaces=false,
showtabs=false,
commentstyle=\color{red},
keywordstyle=\color{blue}
}
\begin{document}
\begin{LTXexample}[pos=t]
%Tree source: http://www.texample.net/tikz/examples/tree-pic/
%Man source: https://tex.stackexchange.com/questions/249588/node-below-icon-in-tikz
\usetikzlibrary{decorations.pathmorphing,shapes}
\tikzset{
treetop/.style = {
decoration={random steps, segment length=0.4mm},
decorate
},
trunk/.style = {
decoration={random steps, segment length=2mm, amplitude=0.2mm},
decorate
}
}
\tikzset{
man/.pic={%
\fill [rounded corners=1.5] (0,0.4) -- (0,0.8) -- (0.4,0.8) -- (0.4,0.4) --
(0.325,0.4) -- (0.325,0.7) -- (0.3,0.7) -- (0.3,0) -- (0.225,0) --
(0.225,0.4) -- (0.175,0.4) -- (0.175,0) -- (0.1,0) -- (0.1,0.7) --
(0.075,0.7) -- (0.075,0.4) -- cycle;
\fill (0.2,0.9) circle (0.1);
\coordinate (-head) at (0.2,1);
\coordinate (-foot) at (0.2,0);
}
}
\begin{center}
\begin{tikzpicture}
\tkzInit[xmin=-11,ymin=-5,xmax=3,ymax=3]
\tkzClip\tkzGrid
\tkzDefPoints{-11/-3/A,-9.8/-2.09/A',0/1.47/B', 2/-3/B,0/-2.09/C,-10.1/-3/M,0/-3/T}
\pic[red] at (-10.1,-3) (myman) {man};
\foreach \w/\f in {0.3/30,0.2/50,0.1/70} {
\fill [brown!\f!black, trunk] (0,0) ++(-\w/2,0) rectangle +(\w,-3);
}
\foreach \n/\f in {1.4/40,1.2/50,1/60,0.8/70,0.6/80,0.4/90} {
\fill [green!\f!black, treetop] ellipse (\n/1.5 and \n);
}
\tkzDrawSegments[dashed](A',B' A',C)
\tkzDrawSegments(A,B T,B')
\tkzMarkAngles[size=0.7cm,arc=ll,mark=|](C,A',B')
\tkzLabelAngles[pos=1.5](C,A',B'){$30^{\circ}$}
\tkzLabelSegment[below](M,T){$20$ cm}
\tkzLabelPoints(A,B,C,A',B',C,M,T)
\end{tikzpicture}
\end{center}
\end{LTXexample}
\end{document}
答案1
编辑2:\g@addto@macro\SX@put@code@result
我的补丁中 有以下几行
\expandafter\lstset\expandafter{\SX@@explpreset@saved}%
应该
\edef\SX@@explpreset{\SX@@explpreset@saved}%
防止自定义预设被包预设覆盖。
\global
之前\@SX@pos@tbfalse
和之后都少了一个\@SX@pos@tb@pagebreakfalse
编辑:
在进一步研究showexpl
包之后,我弄清楚了它的工作流程:LTXexample
环境使用\lst@BeginWriteFile
将输入写入\SX@codefile
,然后调用\SX@put@code@result
,主要通过\SX@resultInput
和\SX@codeInput
分别渲染结果和代码。这两个输入的顺序在 中定义\SX@put@<pos>
。
因此,基本上,我\SX@put@tb
放弃了用于稍后渲染的参数#3
。\SX@codeInput
使用此方法,您需要保存预设,\SX@@explpreset
因为它是在 中的组内本地定义的\SX@put@code@result
。
为了使解决方案更简洁,我添加了一个pagebreak
选项(虽然没有这个选项的 vsep 可能不正确)并用来\g@addto@macro
将代码部分附加到\SX@put@code@result
。
MWE 如下所示:
\documentclass[12pt,a4paper]{article}
\usepackage{listings}
\usepackage{showexpl}
\usepackage{xcolor}
\lstdefinestyle{customlatex}{
basicstyle=\small\ttfamily,
language=[LaTeX]TeX,
commentstyle=\color{Brown},
keywordstyle=\color{Green}\bfseries,
texcsstyle=*\color{blue}\bfseries,
numbers=none,
keepspaces=true,
columns=fixed,
basewidth=0.5em
}
\begin{document}
\makeatletter
% option for force page break
\lst@Key{pagebreak}f[t]{\lstKV@SetIf{#1}\if@SX@pagebreak}
% if pos is 'tb', if force page break
\newif\if@SX@pos@tb \@SX@pos@tbfalse
\newif\if@SX@pos@tb@pagebreak \@SX@pos@tb@pagebreakfalse
% Defines new position 'tb'
\newcommand*\SX@put@tb[3]{%
\SX@ResultArea{\linewidth}{#2}\endgraf%
\@tempdima=\dimexpr\SX@vsep\vskip\@tempdima
% Code area dropped
\global\@SX@pos@tbtrue%
% Save preset for later rendering
\xdef\SX@@explpreset@saved{\SX@@explpreset}%
\if@SX@pagebreak\global\@SX@pos@tb@pagebreaktrue\fi%
}
% patch \SX@put@code@result for code area
\g@addto@macro\SX@put@code@result{%
\if@SX@pos@tb%
\if@SX@pos@tb@pagebreak\clearpage\fi%
\begingroup%
% Bugfix: prevent custom preset from being overwritten
%\expandafter\lstset\expandafter{\SX@@explpreset@saved}%
\edef\SX@@explpreset{\SX@@explpreset@saved}%
\SX@codeInput%
\endgroup%
\fi%
% Bugfix: Misssing \global
%\@SX@pos@tbfalse
%\@SX@pos@tb@pagebreakfalse
\global\@SX@pos@tbfalse
\global\@SX@pos@tb@pagebreakfalse
}
\makeatother
% Width override
\begin{LTXexample}[pos=tb, width=\linewidth, pagebreak, style=customlatex]
\LaTeX
\LaTeX
\LaTeX
\LaTeX
\LaTeX
\LaTeX
\LaTeX
\LaTeX
\LaTeX
\LaTeX\\
\LaTeX
\LaTeX
\LaTeX
\LaTeX
\LaTeX
\LaTeX
\LaTeX
\LaTeX
\LaTeX
\LaTeX\\
\LaTeX
\LaTeX
\LaTeX
\LaTeX
\LaTeX
\LaTeX
\LaTeX
\LaTeX
\LaTeX
\LaTeX\\
\LaTeX
\LaTeX
\LaTeX
\LaTeX
\LaTeX
\LaTeX
\LaTeX
\LaTeX
\LaTeX
\LaTeX\\
\LaTeX
\LaTeX
\LaTeX
\LaTeX
\LaTeX
\LaTeX
\LaTeX
\LaTeX
\LaTeX
\LaTeX
\end{LTXexample}
\end{document}
结果如下所示:
原始答案:
showexpl
包将代码区域和结果区域放在同一个\makebox
(参见\SX@put@code@result
),因此当你指定时\pagebreak[2]
inside\SX@put@t
将不起作用[pos=t]
。
我的解决方案是使用 保存代码区域\makebox
,将其偷运到全局范围,然后通过 使用它\usebox
。为了防止干扰现有的位置设置宏,我将新位置命名tb
为[t]op [b]reakable
。请注意,您需要将其与 一起使用,width=\linewidth
因为除 和 之外的位置设置t
将b
导致半宽。另请注意,如果结果区域或代码区域超出页面,您仍会得到一个满框。希望包作者稍后能添加长代码和分页符支持。
MWE 如下所示:
\documentclass[12pt,a4paper]{article}
\usepackage{listings}
\usepackage{showexpl}
\begin{document}
\makeatletter
% Idea comes from https://tex.stackexchange.com/questions/283373
% Code area box to be saved
\newsavebox{\SX@CodeLater}
% Defines new position 'tb'
\newcommand\SX@put@tb[3]{%
\SX@ResultArea{\linewidth}{#2}\endgraf%
\@tempdima=\dimexpr\SX@vsep\vskip\@tempdima
% Save code area box and smuggle to global scope
\newsavebox{\SX@CodeLaterLocal}%
\savebox\SX@CodeLaterLocal{\SX@CodeArea{\linewidth}{#3}}%
\global\expandafter\setbox\SX@CodeLater\box\SX@CodeLaterLocal%
}
\makeatother
% Result only, with width override
\begin{LTXexample}[pos=tb, width=\linewidth]
Hello, \LaTeX!
\end{LTXexample}
% Page break
\clearpage
% Use code area box
\makeatletter
\noindent\usebox{\SX@CodeLater}%
\makeatother
\end{document}
结果如下所示: