并排 minipage 和 tcblisting 环境

并排 minipage 和 tcblisting 环境

我想使用类似下面这样的配置,让 minipage 的宽度自动适应 tcblisting 的宽度,但我不知道如何获取 varwidth 的宽度(这里记为 \varwidthwidth)。

\documentclass{article}
\usepackage{varwidth}
\usepackage{lipsum}
\usepackage[listings]{tcolorbox}

\begin{document}

\begin{minipage}{\linewidth-\varwidthwidth-1em}
\lipsum[1][1-5]
\end{minipage}\hfill%
\begin{varwidth}{.5\linewidth}
\begin{tcblisting}{hbox,listing only}
x
\end{tcblisting}
\end{varwidth}

\end{document}

答案1

您不需要 varwidth 来测量 的宽度\hbox。请注意,tcblisting 的基线位于底部。有趣的是,我不得不使用lrbox而不是\savebox

\documentclass{article}
\usepackage{lipsum}
\usepackage[listings]{tcolorbox}

\newsavebox{\tempbox}

\begin{document}

\begin{lrbox}{\tempbox}
\begin{tcblisting}{hbox,listing only}
%Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Ut purus
x
\end{tcblisting}
\end{lrbox}%
\ifdim\wd\tempbox>0.5\textwidth
  \begin{lrbox}{\tempbox}
  \begin{tcblisting}{listing only, width=0.5\textwidth}
  %Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Ut purus
  x
  \end{tcblisting}
  \end{lrbox}%
\fi
\noindent\begin{minipage}[b]{\dimexpr \linewidth-\wd\tempbox-1em}
\lipsum[1][1-5]
\end{minipage}\hfill\box\tempbox

\end{document}

答案2

您的定义环绕varwidth实际上tcblisting并不能将最大宽度保持在 .5 线宽(它适用于文本,但不适用于绘制的框 - 我通过使用 -keywidth和删除解决了这个问题hbox,但只有当自然宽度超出指定的最大水平空间时,所以tcblisting可能会使用两次,一次使用 ,hbox一次使用width)。

除此之外,下面的代码还可以做你想做的事情,使用enverb(我写的一些未发布的代码,主要用于我的文档expkv-bundle)。它假定左侧永远不需要逐字内容,因此将其作为正常的强制参数。

该代码具有基于使用 -statement 的行缩进的自动缩进检测功能\end,并允许删除额外的符号(此处计算空格,但代码很“愚蠢”,会删除任何字符,并且如果行比应删除的行短,则当前会抛出低级错误)。默认设置会删除两个额外的空格(因为这是我用来缩进环境内容的数量)。它还可以使用和键在每行的开头和结尾添加bol内容eol

\enverb具有一种机制,用于读取可选参数并在本地设置其设置。我删除了一些对您的应用程序不必要的其他功能(或与我的特定输出需求相关的功能)。相反,我添加了两个键来控制您的输出,varwidth设置嵌套环境的最大宽度varwidth,并tcbopts设置转发到的选项tcblisting(如果您使用+=它,它将添加到现有选项中)。

\documentclass{article}
\usepackage{lipsum}
\usepackage[listings]{tcolorbox}

\makeatletter
\usepackage{expkv-def}

\ExplSyntaxOn
\cs_new_eq:NN \enverb@count \tl_count:n
\ExplSyntaxOff
%% key setup
\ekvdefinekeys{enverb}
  {
    % if true ignore the number of spaces preceding the \end-statement
     boolTF auto-ignore    = \enverb@ifautoignore
    ,initial auto-ignore
    % number of additional characters to ignore for nested indentation
    ,eint more-ignore      = \enverb@moreignore
    ,initial more-ignore   = 2
    % if used ignore exactly this many characters (overwrites auto-ignore)
    ,protected code ignore = \let\enverb@ifautoignore\@secondoftwo
    ,also eint ignore      = \enverb@ignore
    % contents to place at the start of every line
    ,long store bol = \enverb@bol@content
    % contents to place at the end of every line
    ,long store eol = \enverb@eol@content
    ,e: initial eol = \csname char_generate:nn\endcsname{13}{12}
    %% Additional keys for your environment
    % maximum varwidth width
    ,long store varwidth = \mbAeVarwidthwidth
    ,initial    varwidth = .5\linewidth
    % tcb-options
    ,long store tcbopts  = \mbAeTcbopts
    ,initial    tcbopts  = {listing only, box align=center}
    % define tcbopts+={<keys>} to add to the tcbopts instead of resetting them
    ,meta  tcbopts      += {o: tcbopts = {\mbAeTcbopts, #1}}
    ,meta  tcbopts+      = {o: tcbopts = {\mbAeTcbopts, #1}}
  }
\protected\long\ekvsetdef\enverbsetup{enverb}

%% auxiliary error function
\newcommand\enverb@error[1]
  {%
    \GenericError
      {(enverb)\@spaces\@spaces\@spaces\@spaces}%
      {Environment enverb error: #1}%
      {Just use it correctly!}%
      {Read the sources.}%
  }

%% setup for weird category code regime
\begingroup
\lccode`\~=`\^^M
\catcode`\:=13
\lccode`\:=`\ % <- space
\catcode`\;=13
\lccode`\;=`\^^I % <- tab
\lowercase{\endgroup
%% code for spaces and CR
\def\enverb@body@space{}%
\def\enverb@body@tab{}%
\def\enverb@body@newline#1~%
  {\enverb@ifnotend{#1}{\enverb@bol\unexpanded{#1}\enverb@eol~}}%
%% activate the category code regime of the body
\protected\def\enverb@body@setup
  {%
    \let\enverbCollectedBody\@empty
    \let\do\@makeother\dospecials
    \catcode`\^^M=13 \let~\enverb@body@newline
    \catcode`\   =13 \let:\enverb@body@space
    \catcode`\^^I=13 \let;\enverb@body@tab
    \let\enverb@bol\relax
    \let\enverb@eol\relax
  }
%% check for optional argument
\newcommand\enverb@search@oarg@a
  {%
    \ifx:\next
      \ifenverb@firsteol
      \else
        \enverb@body@add{:}%
      \fi
      \let\next\enverb@search@oarg@b
    \else
      \ifx~\next
        \ifenverb@firsteol
          \enverb@firsteolfalse
        \else
          \enverb@body@add{~}%
        \fi
        \let\next\enverb@search@oarg@b
      \else
        \ifx[\next\@gobble]%
          \let\next\enverb@oarg
        \else
          \ifenverb@firsteol
            \let\next\enverb@body@after@begin
          \else
            \let\next\enverb@body
          \fi
        \fi
      \fi
    \fi
    \next
  }
%% start body collection
\newcommand\enverb@body
  {\edef\enverbCollectedBody{\iffalse}\fi\expandafter~\enverbCollectedBody}
%% check the line after an oarg
\def\enverb@body@after@oarg#1~%
  {\enverb@ensure@blank{#1}{closing bracket}\enverb@body}
%% check the line after the \begin statement
\def\enverb@body@after@begin#1~%
  {\enverb@ensure@blank{#1}{\string\begin}\enverb@body}
}
%% quick check for empty line
\newcommand\enverb@ensure@blank[2]
  {%
    \expandafter\enverb@ifempty\expanded{{#1}}{}%
      {%
        \expanded{%
        \noexpand\enverb@error
          {%
            Line after #2 not empty.\noexpand\MessageBreak
            Contains: \detokenize\expandafter{\romannumeral`\^^@#1}%
          }%
        }%
      }%
  }
%% quick check for empty argument
\newcommand\enverb@ifempty[1]
  {%
    \enverb@ifempty@\enverb@ifempty@A#1\enverb@ifempty@B.\enverb@ifempty@true
      \enverb@ifempty@A\enverb@ifempty@B
  }
\def\enverb@ifempty@#1\enverb@ifempty@A\enverb@ifempty@B#2#3{#3}
\def\enverb@ifempty@true\enverb@ifempty@A\enverb@ifempty@B#1#2{#1}
\newcommand\enverb@gadd[2]{\xdef#1{\unexpanded\expandafter{#1#2}}}
\newcommand\enverb@body@add[1]
  {%
    \edef\enverbCollectedBody
      {\unexpanded\expandafter{\enverbCollectedBody#1}}%
  }
% start of environment `enverb'
\newcommand\enverb
  {%
    \begingroup
      \def\tmp{enverb}%
      \expandafter
    \endgroup
    \expandafter\enverb@ifnotend@setup@perhaps\expanded
      {{\string{\@currenvir\string}}}%
    \begingroup
    \enverb@body@setup
    \enverb@firsteoltrue
    \let\enverb@collected@oarg\@empty
    \enverb@search@oarg
  }
\newif\ifenverb@firsteol
\newcommand\enverb@search@oarg{\futurelet\next\enverb@search@oarg@a}
\newcommand\enverb@search@oarg@b{\expandafter\enverb@search@oarg\@gobble}
\newcommand\enverb@oarg{\endgroup\enverb@oarg@}
\NewDocumentCommand\enverb@oarg@{O{}}
  {%
    \edef\enverb@collected@oarg{\unexpanded{#1}}%
    \begingroup
    \enverb@body@setup
    \enverb@body@after@oarg
  }
\def\enverb@ifnotend#1%
  {%
    \def\enverb@ifnotend##1%
      {%
        \enverb@ifnotend@
          ##1\enverb@mark\enverb@ifnotend@maybe
          #1\enverb@mark\@thirdofthree
          \enverb@stop
      }%
    \def\enverb@ifnotend@##1#1##2\enverb@mark##3##4\enverb@stop{##3{##1}{##2}}%
  }
\expandafter\enverb@ifnotend\expanded{{\expandafter\@gobble\string\\end}}
\newcommand\enverb@ifnotend@maybe[2]
  {\expandafter\enverb@ifnotend@perhaps\expandafter{\romannumeral`\^^@#2}{#1}}
\newcommand\enverb@ifnotend@setup@perhaps[1]
  {%
    \def\enverb@ifnotend@perhaps##1%
      {%
        \enverb@ifnotend@perhaps@\enverb@mark##1\enverb@mark\enverb@ifnotend@end
          \enverb@mark#1\enverb@mark\@thirdofthree
          \enverb@stop
      }%
    \def\enverb@ifnotend@perhaps@
        ##1\enverb@mark#1##2\enverb@mark##3##4\enverb@stop
      {##3{##2}}%
  }
\providecommand\@thirdofthree[3]{#3}
\newcommand\enverb@ifnotend@end[3]
  {%
    \iffalse{\fi}%
    \enverb@ensure@blank{#1}{\string\end}%
    \expanded
      {%
        \endgroup
        \enverbsetup
          {\unexpanded\expandafter{\enverb@collected@oarg}}%
        \noexpand\enverb@final
          {\unexpanded\expandafter{\enverbCollectedBody}}%
      }%
      {#2}%
    \expandafter\end\expandafter{\@currenvir}%
  }
\long\def\enverb@final#1#2%
  {%
    \enverb@ifautoignore
      {\enverb@setup@ignore{\enverb@count{#2}+\enverb@moreignore}}%
      {\enverb@setup@ignore\enverb@ignore}%
    \edef\enverb@line##1\enverb@eol
      {%
        \noexpand\detokenize{##1}%
        \noexpand\unexpanded{\unexpanded\expandafter{\enverb@eol@content}}%
      }%
    \edef\enverbCollectedBody{#1}%
  }
\providecommand\@firstofnine[9]{#1}
\newcommand\enverb@setup@ignore[1]
  {\expandafter\enverb@setup@ignore@\the\numexpr#1\relax;\enverb@line}
\def\enverb@setup@ignore@#1;#2%
  {%
    \ifnum#1>9
      \expandafter\@firstoftwo
    \else
      \expandafter\@secondoftwo
    \fi
    {\expandafter\enverb@setup@ignore@\the\numexpr#1-8;{\@firstofnine{#2}}}%
    {%
      \let\enverb@bol@gobble\@empty % just so that renewcommand doesn't go nuts
      \expanded
        {%
          \unexpanded{\renewcommand\enverb@bol@gobble}\ifnum#1>\z@[#1]\fi
            {%
              \noexpand\unexpanded
                {\unexpanded\expandafter{\enverb@bol@content}}%
              \unexpanded{#2}%
            }%
          \unexpanded{\def\enverb@bol##1\enverb@eol}%
            {%
              \unexpanded{\expandafter\enverb@ifempty\expanded}{{##1}}%
                {\noexpand\enverb@line}%
                {\noexpand\enverb@bol@gobble}%
              ##1\unexpanded{\enverb@eol}%
            }%
        }%
    }%
  }
\let\endenverb\@empty
\makeatother

\newcommand*\mbAeLeftHandSide{}
\newsavebox\mbAeRightHandSide
\newcommand*\mbAeRightHandSideListing[1]
  {%
    \sbox\mbAeRightHandSide
      {%
        % \csname tl_analysis_show:N\endcsname\mbAeRightHandSideContents
        \scantokens\expanded
          {{%
              \noexpand\begin{tcblisting}%
                  {#1,\unexpanded\expandafter{\mbAeTcbopts}}%
                \mbAeRightHandSideContents
              \noexpand\end{tcblisting}\csname char_generate:nn\endcsname{13}{12}%
              \noexpand\noexpand\noexpand\noexpand
          }}%
      }%
  }
\expanded{\unexpanded{\def\mbAeSplitSides#1}\string\BREAK}#2\stop
  {%
    \def\mbAeLeftHandSideContents {#1}%
    \def\mbAeRightHandSideContents{#2}%
  }
\newenvironment{mbAe}
  {\enverb}
  {%
    \expandafter\mbAeSplitSides\enverbCollectedBody\stop
    \mbAeRightHandSideListing{hbox}% first pass, try hbox
    \ifdim\wd\mbAeRightHandSide>\mbAeVarwidthwidth\relax % if too wide use width
      \mbAeRightHandSideListing{width=\mbAeVarwidthwidth}%
    \fi
    \par\noindent
    \begin{minipage}[c]{\dimexpr\linewidth-\wd\mbAeRightHandSide-1em\relax}
      \scantokens\expanded{{\mbAeLeftHandSideContents\noexpand\noexpand\noexpand\noexpand}}%
    \end{minipage}%
    \hfill
    \usebox\mbAeRightHandSide
    \par
  }

\usepackage{varwidth} % only needed to show your approach

\begin{document}
\begin{mbAe}[tcbopts+={colback=red!15}]
  \lipsum[1][1-5]
  \BREAK
  x
\end{mbAe}

\begin{mbAe}
  \lipsum[1][1-5]
  \BREAK
  This is a very long line that takes most likely more than half a line width
\end{mbAe}

\begin{minipage}{\dimexpr\linewidth-5cm-1em\relax}
\lipsum[1][1-5]
\end{minipage}\hfill%
\begin{varwidth}{.5\linewidth}
\begin{tcblisting}{hbox,listing only}
This is a very long line that takes most likely more than half a line width
\end{tcblisting}
\end{varwidth}
\end{document}

在此处输入图片描述

相关内容