如何分离 showexpl 包中的图像和代码,并在页面结束时将代码分解到新页面?

如何分离 showexpl 包中的图像和代码,并在页面结束时将代码分解到新页面?

在 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因为除 和 之外的位置设置tb导致半宽。另请注意,如果结果区域或代码区域超出页面,您仍会得到一个满框。希望包作者稍后能添加长代码和分页符支持。

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}

结果如下所示:

原始结果图像

相关内容