tcolorbox 中多列列表的垂直对齐问题

tcolorbox 中多列列表的垂直对齐问题

总结:目前剩余的问题在文章底部


考虑以下测试代码:

% ---------------------------------------------------------------------------- %
% Files
\begin{filecontents*}{empty\jobname.cpp}
\end{filecontents*}
\begin{filecontents*}{\jobname.cpp}
0000
0000
\end{filecontents*}
\begin{filecontents*}{multi\jobname.cpp}
0000
0000
0000
0000
\end{filecontents*}
% ---------------------------------------------------------------------------- %
% Preamble
\documentclass[letterpaper, 12pt, onecolumn]{article}
% ---------------------------------------------------------------------------- %
% Packages
\usepackage[paperwidth = 160mm, paperheight = 550mm, margin = 10mm]{geometry}
\usepackage{xcolor}
\usepackage{listings}
\usepackage{multicol}
\usepackage[most]{tcolorbox}
% ---------------------------------------------------------------------------- %
% Listings options
\newtcbinputlisting{\inputcode}[4][\normalsize]{
    code = {},
    enhanced,
    listing only,
    top = 0pt,
    bottom = 0pt,
    left = 0pt,
    right = 0pt,
    arc = 0pt,
    outer arc = 0pt,
    boxsep = 0pt,
    titlerule = 0pt,
    colback = blue,
    colframe = black,
    boxrule = 2pt,
    title = {\centering{\fontfamily{cmtt}\selectfont#2\strut}},
    listing options = {
        language = C++,
        framesep = 0pt,
        rulesep = 0pt,
        aboveskip = 0pt,
        belowskip = 0pt,
        backgroundcolor = \color{lightgray},
        basicstyle = \fontfamily{cmtt}\selectfont#1,
        #3,
    },
    listing file={#4},
}
% ---------------------------------------------------------------------------- %
% Commands
\newcommand{\makelisting}[2]{%
    \inputcode[#1]{#2}{}{\jobname.cpp}%
    \inputcode[#1]{#2}{multicols = 2}{multi\jobname.cpp}%
    \bigskip\bigskip%
}
% ---------------------------------------------------------------------------- %
% Document
\pagestyle{empty}
\begin{document}
\inputcode[]{empty}{}{empty\jobname.cpp}
\inputcode[]{empty}{multicols = 2}{empty\jobname.cpp}
\bigskip\bigskip
\makelisting{\tiny}{tiny}
\makelisting{\scriptsize}{scriptsize}
\makelisting{\footnotesize}{footnotesize}
\makelisting{\small}{small}
\makelisting{\normalsize}{normalsize}
\makelisting{\large}{large}
\makelisting{\Large}{Large}
\makelisting{\LARGE}{LARGE}
\makelisting{\huge}{huge}
\makelisting{\Huge}{Huge}
\end{document}
% ---------------------------------------------------------------------------- %

它在 tcolorboxes 中生成列表对:一个没有多列,另一个有多列。结果输出:


列表


如这些图片所示,该multicols选项最终会在列表顶部和底部添加额外的空间(图片上为蓝色)。此间距的确切测量值似乎取决于列表的字体样式(\tiny\small\large...)以及文档的字体大小(10pt11pt、 )。使用空列表(文档开头)进行实验还表明,激活12pt该选项后会剩余蓝色间距。multicols

到目前为止,我还不能理解这个垂直间距来自哪里,以及它的确切值来自哪里。


问题:

  • 这个额外的间距来自哪里(在列表的顶部和底部)?
  • 它的值(顶部和底部)是如何计算的?
  • 如何让这个额外的垂直间距消失?

更新 1:

经过几个小时的研究,这里有一个小发现。如果将顶部参数调整为以下内容:

\newlength{\normalsizestrutheight}
\settoheight{\normalsizestrutheight}{\strut}
\newlength{\fontstrutheight}
\newcommand{\getfontstrutheight}[1]{\settoheight{\fontstrutheight}{#1\strut}}
\newlength{\topshift}
\newcommand{\computetopshift}[1]{%
    \getfontstrutheight{#1}%
    \setlength{\topshift}{%
        \minof{-\normalsizestrutheight + \fontstrutheight}{0pt}%
    }%
}

然后对于所有小于 的字体\normalsize,剩余的顶部空间是恒定的。仍然不是零,但至少是常数。但是,这个常数的值仍然取决于文档的默认字体大小(10pt11pt12pt8pt(带有extarticle)、17pt(带有extarticle)...),我仍然无法找到公式。

这是我更新的测试文件:

% ---------------------------------------------------------------------------- %
% Files
\begin{filecontents*}{empty\jobname.cpp}
\end{filecontents*}
\begin{filecontents*}{\jobname.cpp}
0000
\end{filecontents*}
\begin{filecontents*}{multi\jobname.cpp}
0000
0000
0000
0000
\end{filecontents*}
% ---------------------------------------------------------------------------- %
% Preamble
\documentclass[letterpaper, 12pt, onecolumn]{article}
% ---------------------------------------------------------------------------- %
% Packages
\usepackage[paperwidth = 160mm, paperheight = 500mm, margin = 10mm]{geometry}
\usepackage{calc}
\usepackage{xcolor}
\usepackage{listings}
\usepackage{multicol}
\usepackage{printlen}
\usepackage[most]{tcolorbox}
% ---------------------------------------------------------------------------- %
% Measurement computation
\newlength{\normalsizestrutheight}
\settoheight{\normalsizestrutheight}{\strut}
\newlength{\fontstrutheight}
\newcommand{\getfontstrutheight}[1]{\settoheight{\fontstrutheight}{#1\strut}}
\newlength{\topshift}
\newcommand{\computetopshift}[1]{%
    \getfontstrutheight{#1}%
    \setlength{\topshift}{%
        \minof{-\normalsizestrutheight + \fontstrutheight}{0pt}%
    }%
}
% ---------------------------------------------------------------------------- %
% Listings options
\newtcbinputlisting{\inputcode}[5][\normalsize]{
    code = {\computetopshift{\fontfamily{cmtt}\selectfont#1}},
    enhanced,
    listing only,
    top = 0pt,
    bottom = 0pt,
    left = 0pt,
    right = 0pt,
    arc = 0pt,
    outer arc = 0pt,
    boxsep = 0pt,
    titlerule = 0pt,
    colback = red,
    colframe = black,
    boxrule = 2pt,
    title = {\centering{\fontfamily{cmtt}\selectfont#2\strut}},
    listing options = {
        language = C++,
        framesep = 0pt,
        rulesep = 0pt,
        aboveskip = 0pt,
        belowskip = 0pt,
        backgroundcolor = \color{white},
        basicstyle = \fontfamily{cmtt}\selectfont#1,
        #3,
    },
    #4,
    listing file={#5},
}
% ---------------------------------------------------------------------------- %
% Commands
\newcommand{\makeempty}{%
    \inputcode[]{empty}{}{}{empty\jobname.cpp}%
    \inputcode[]{empty}{multicols = 2}{}{empty\jobname.cpp}%
    \bigskip\bigskip%
}
\newcommand{\makelisting}[3]{%
    \inputcode[#1]{#2}{}{}{\jobname.cpp}%
    \inputcode[#1]{#2}{multicols = 2}{top = \topshift, #3,}{multi\jobname.cpp}%
    \bigskip\bigskip%
}
% ---------------------------------------------------------------------------- %
% Document
\pagestyle{empty}
\begin{document}
\makeempty{}
\makelisting{\tiny}{tiny}{}
\makelisting{\scriptsize}{scriptsize}{}
\makelisting{\footnotesize}{footnotesize}{}
\makelisting{\small}{small}{}
\makelisting{\normalsize}{normalsize}{}
\makelisting{\large}{large}{}
\makelisting{\Large}{Large}{}
\makelisting{\LARGE}{LARGE}{}
\makelisting{\huge}{huge}{}
\makelisting{\Huge}{Huge}{}
\end{document}
% ---------------------------------------------------------------------------- %

输出:

上市topshift

但是,如何以通用的方式让剩余的顶部空间消失,以适用于每个默认文档字体大小,以及底部空间,仍然是个谜。


更新2:

\documentclass[Npt]{extarticle}我尝试计算刚刚描述的常数的值,即给定文档字体大小时 tcolorbox 和列表顶部之间的剩余空间N=8, 9, 10, 11, 12, 14, 17, 20。我使用了以下代码:

\newlength{\normalsizestrutheight}
\settoheight{\normalsizestrutheight}{\strut}
\newlength{\fontstrutheight}
\newcommand{\getfontstrutheight}[1]{\settoheight{\fontstrutheight}{#1\strut}}
\newlength{\topconstant}
\setlength{\topconstant}{% something here %}
\newlength{\topshift}
\newcommand{\computetopshift}[1]{%
    \getfontstrutheight{#1}%
    \setlength{\topshift}{%
        \minof{-\normalsizestrutheight + \fontstrutheight - \topconstant}{0pt}%
    }%
}

如果您明白的话,我想知道给定N的 值是多少topconstant才能使顶部的额外间距消失。以下是我收集的近似值:

value of N -> value of topconstant
8pt -> 2.350pt
9pt -> 1.335pt
10pt -> 1.600pt
11pt -> 1.480pt
12pt -> 1.850pt
14pt -> 2.100pt
17pt -> 1.600pt
20pt -> 2.500pt

如果有人知道这些值从何而来以及如何自动计算它们,那就太好了。剩下的另一个问题是如何处理额外的底部间距。


更新 3:

我觉得我发现了一些东西。使用以下代码:

\newlength{\mainfontsize}
\makeatletter
\setlength{\mainfontsize}{\@ptsize}
\makeatother
\newlength{\normalsizestrutheight}
\settoheight{\normalsizestrutheight}{\strut}
\newlength{\fontstrutheight}
\newcommand{\getfontstrutheight}[1]{\settoheight{\fontstrutheight}{#1\strut}}
\newlength{\topshift}
\newcommand{\computetopshift}[1]{%
    \getfontstrutheight{#1}%
    \setlength{\topshift}{%
        \minof{-\mainfontsize + \fontstrutheight}{0pt}%
    }%
}

额外的顶部间距消失... 除了\documentclass[8pt]{extarticle}。对于该特定情况,\mainfontsize需要设置为9pt。更令人惊讶的是,它适用于 ,extarticle但不适用于article

  • 知道为什么8pt在 的字体大小上有这个细微差别吗extarticle
  • 为什么它对 有效extarticle,而对 无效article
  • 但是,如何消除底部间距?

更新 4:剩余问题

Ulrike Fischer 的回答,底部间距的问题仍然悬而未决。通过测试,我还发现额外的底部间距取决于列表中的行数是偶数还是奇数。

答案1

如果将\topskip\mathdepth本地设置为 0pt 和(例如使用before upper*),它似乎可以工作,但空的情况除外。

\begin{filecontents*}{empty\jobname.cpp}
\end{filecontents*}
\begin{filecontents*}{\jobname.cpp}
0000
0000
\end{filecontents*}
\begin{filecontents*}{multi\jobname.cpp}
0000
0000
0000
0000
\end{filecontents*}
% ---------------------------------------------------------------------------- %
% Preamble
\documentclass[letterpaper, 12pt, onecolumn]{article}
% ---------------------------------------------------------------------------- %
% Packages
\usepackage[paperwidth = 160mm, paperheight = 550mm, margin = 10mm]{geometry}
\usepackage{xcolor}
\usepackage{listings}
\usepackage{multicol}
\usepackage[most]{tcolorbox}
% ---------------------------------------------------------------------------- %
% Listings options
\newtcbinputlisting{\inputcode}[4][\normalsize]{
    code = {},
    before upper*={\topskip0pt \maxdepth=0pt}, %<---------------
    enhanced,
    listing only,
    top = 0pt,
    bottom = 0pt,
    left = 0pt,
    right = 0pt,
    arc = 0pt,
    outer arc = 0pt,
    boxsep = 0pt,
    titlerule = 0pt,
    colback = blue,
    colframe = black,
    boxrule = 2pt,
    title = {\centering{\fontfamily{cmtt}\selectfont#2\strut}},
    listing options = {
        language = C++,
        framesep = 0pt,
        rulesep = 0pt,
        aboveskip = 0pt,
        belowskip = 0pt,
        backgroundcolor = \color{lightgray},
        basicstyle = \fontfamily{cmtt}\selectfont#1,
        #3,
    },
    listing file={#4},
}
% ---------------------------------------------------------------------------- %
% Commands
\newcommand{\makelisting}[2]{%
    \inputcode[#1]{#2}{}{\jobname.cpp}%
    \inputcode[#1]{#2}{multicols = 2}{multi\jobname.cpp}%
    \bigskip\bigskip%
}
% ---------------------------------------------------------------------------- %
% Document
\pagestyle{empty}
\begin{document}
\inputcode[]{empty}{}{empty\jobname.cpp}
\inputcode[]{empty}{multicols = 2}{empty\jobname.cpp}
\bigskip\bigskip
\makelisting{\tiny}{tiny}
\makelisting{\scriptsize}{scriptsize}
\makelisting{\footnotesize}{footnotesize}
\makelisting{\small}{small}
\makelisting{\normalsize}{normalsize}
\makelisting{\large}{large}
\makelisting{\Large}{Large}
\makelisting{\LARGE}{LARGE}
\makelisting{\huge}{huge}
\makelisting{\Huge}{Huge}
\end{document}

在此处输入图片描述

答案2

底部间距问题在此处理回答。底线:\hrule height0pt使用钩子在每行后添加\lst@AddToHook{EOL}。这解决了@Ulrike Fischer 的剩余问题回答

\begin{filecontents*}{empty\jobname.cpp}
\end{filecontents*}
\begin{filecontents*}{normal\jobname.cpp}
0000
0000
\end{filecontents*}
\begin{filecontents*}{multiOne\jobname.cpp}
0000
\end{filecontents*}
\begin{filecontents*}{multiEven\jobname.cpp}
0000
0000
\end{filecontents*}
\begin{filecontents*}{multiOdd\jobname.cpp}
0000
0000
0000
\end{filecontents*}

\documentclass[letterpaper, 12pt, onecolumn]{article}

\usepackage[paperwidth = 160mm, paperheight = 550mm, margin = 10mm]{geometry}
\usepackage{xcolor}
\usepackage{listings}
\usepackage{multicol}
\usepackage[most]{tcolorbox}

\makeatletter
\newtcbinputlisting{\inputcodeTemp}[4][\normalsize]{
    before upper* = {\topskip0pt\lst@AddToHook{EOL}{\hrule height0pt}},% set topskip to 0pt and add hrule after each input line
    enhanced,
    listing only,
    top = 0pt,
    bottom = 0pt,
    left = 0pt,
    right = 0pt,
    arc = 0pt,
    outer arc = 0pt,
    boxsep = 0pt,
    titlerule = 0pt,
    colback = blue,
    colframe = black,
    boxrule = 2pt,
    title = {\centering{\fontfamily{cmtt}\selectfont#2\strut}},
    listing options = {
        language = C++,
        framesep = 0pt,
        rulesep = 0pt,
        aboveskip = 0pt,
        belowskip = 0pt,
        backgroundcolor = \color{lightgray},
        basicstyle = \fontfamily{cmtt}\selectfont#1,
        #3,
    },
    listing file = {#4},
}
\makeatother

\makeatletter
\newcommand{\inputcode}[4][\normalsize]{%
\inputcodeTemp[#1]{#2}{#3}{#4}
\gdef\lsthk@EOL{}% clear the hook
}
\makeatother

\makeatletter
\newcommand{\makelisting}[2]{%
    \inputcode[#1]{#2}{}{normal\jobname.cpp}%
    \inputcode[#1]{#2}{multicols = 2}{multiOne\jobname.cpp}%
    \inputcode[#1]{#2}{multicols = 2}{multiEven\jobname.cpp}%
    \inputcode[#1]{#2}{multicols = 2}{multiOdd\jobname.cpp}%
    \vspace{2\baselineskip}
}
\makeatother

\pagestyle{empty}

\begin{document}
\inputcode[]{empty}{}{empty\jobname.cpp}
\inputcode[]{empty}{multicols = 2}{empty\jobname.cpp}
\vspace{2\baselineskip}
\makelisting{\tiny}{tiny}
\makelisting{\scriptsize}{scriptsize}
\makelisting{\footnotesize}{footnotesize}
\makelisting{\small}{small}
\makelisting{\normalsize}{normalsize}
\makelisting{\large}{large}
\makelisting{\Large}{Large}
\makelisting{\LARGE}{LARGE}
\makelisting{\huge}{huge}
\makelisting{\Huge}{Huge}
\end{document}

在此处输入图片描述

相关内容