关于利用changepage宏包实现悬挂缩进的两个问题

发布于 2022-04-11 09:24:43

我现有如下代码:

\documentclass{ctexart}
\usepackage{changepage}
\begin{document}
默认效果:

第一层
\begin{adjustwidth}{5em}{0mm}
试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试
\end{adjustwidth}
加上\verb|\leavevmode\vspace*{-16.5pt}|实现悬挂效果:

第一层
\leavevmode\vspace*{-16.5pt}
\begin{adjustwidth}{5em}{0mm}
试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试\\
第二层\leavevmode\vspace*{-16.5pt}
\begin{adjustwidth}{3em}{0mm}
测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试试测试\\
第三层\leavevmode\vspace*{-16.5pt}
\begin{adjustwidth}{3em}{0mm}
测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试
\end{adjustwidth}
\end{adjustwidth}
\end{adjustwidth}
\end{document}

第一个问题,adjustwidth环境默认新行开始,我用了leavevmodevspace*{-16.5pt}把它向上移动了,-16.5pt是估计值,那么精确值如何确定呢?
第二个问题,如何测量标签的长度,比如“第一层”这几个字
34f6a121801fef5f786159b80063bfc.jpg

查看更多

关注者
0
被浏览
1.8k
雾月
雾月 2022-04-11
这家伙很懒,什么也没写!

与缩进相关的环境和命令基本上都是使用 trivlistlist 环境(list 也使用 trivlist 环境)制作的。包括但不限于 theorem、changepage 宏包、itemize、description 等。你用 changepage,自定义环境等还不如直接使用 list 环境来定义,而且 list 环境已经给你做好了嵌套使用所需的准备工作。

trivlistlist 环境使用 \hangindent\hangafter 等 primitive 来制作,这意味着由它们定义的环境和命令无法与其它使用 \hangindent\hangafter\parshape primitive 定义的环境和命令共同使用,包括但不限于图文绕排、lettrine(首字下沉)等。这是 LaTeX 固有的缺陷。要么不同时使用,要么用 ConTeXt。

回到这个问题上来,adjustwidth 环境不是默认从新的一行开始,而是只能从新的一行开始,所有的 trivlist 环境都是如此,根本原因是上述 primitive 只能从新的一行或一段开始生效。

在只包含正常文字的情况下,两基线间的距离为 \baselineskip

你可以把文字放在一个盒子中,以测量其长度,或者使用 \settowidth{dim register}{content}

如下代码支持 text\hang{...\hang{...}...},基本实现了原始需要,但是,编译次数至少为:嵌套次数+1。比如上述 \hang 中嵌套了一个 \hang,需要至少编译 3 次。不支持多栏。

若要在任意位置开始,需显示地给出 \indentstart 以标明起始位置,见最后一例。

\documentclass{ctexart}
\usepackage[a4paper,includeheadfoot,margin=1.98cm]{geometry}

\usepackage{changepage}
\usepackage{zref,zref-savepos,zref-abspos}
\makeatletter
\newdimen\@autoindentsuppshift
\newdimen\@autoindenttrueyshift
\newdimen\@autoindentxshift
\newdimen\@autoindentyshift
\newcount\@autoindentdepth
\newcount\@autoindentcount
\zref@newlist{autoindent@info}
\zref@newprop{lastyshift}[0pt]{0pt}
\zref@newprop{yshift}[0pt]{0pt}
\zref@addprops{autoindent@info}{lastyshift,yshift}
% \def\@autoindent@strut{\hb@xt@\z@{\hss
%   \vrule\@width\z@\@depth\dimexpr -\zref@getcurrent{yshift}+\f@size\p@\relax}}
\def\@autoindent@strut{}
\def\indentstart{\leavevmode
  \@namedef{autoindent@record@\the\numexpr\@autoindentcount+1}{}%
  \zsavepos{autoindent@labelpos@\the\numexpr\@autoindentcount+1@0}}
\def\@autoindent@startposx{\zref@ifrefundefined
  {autoindent@labelpos@\the\@autoindentcount @0}
  {\zref@absposx{\@autoindent@label}{body}{left}}
  {\zposx{autoindent@labelpos@\the\@autoindentcount @0}}}
\def\@autoindent@info{autoindent@info@\the\@autoindentcount @\the\@autoindentdepth}
\def\@autoindent@hang{autoindent@hangpos@\the\@autoindentcount @\the\@autoindentdepth}
\def\@autoindent@label{autoindent@labelpos@\the\@autoindentcount @\the\@autoindentdepth}
\def\@autoindent@savelabelpos{\advance\@autoindentdepth\@ne
  \zsavepos{\@autoindent@label}}
\def\@autoindent@savehangpos{\zsavepos{\@autoindent@hang}}
\def\@autoindent@labelposx{\zposx{\@autoindent@label}}
\def\@autoindent@labelposy{\zposy{\@autoindent@label}}
\def\@autoindent@hangposx{\zposx{\@autoindent@hang}}
\def\@autoindent@hangposy{\zposy{\@autoindent@hang}}

\newenvironment{autoindent}
  {\ifdim\@autoindentsuppshift=\z@ \global\advance\@autoindentcount\@ne\fi 
    \@autoindent@savelabelpos \leavevmode 
    \setlength\@autoindentxshift{\dimexpr
      \@autoindent@labelposx sp -
      \@autoindent@startposx sp - 
      \@autoindentsuppshift}%
    \advance\@autoindentsuppshift\@autoindentxshift
    \ifnum\zref@extract{\@autoindent@label}{abspage}
      =\zref@extract{\@autoindent@hang}{abspage}
      \setlength\@autoindentyshift{\dimexpr
        \@autoindent@hangposy sp - \@autoindent@labelposy sp}%
      \ifdim\@autoindentyshift=\z@ 
        \ifdim\@autoindent@hangposy sp>\z@ 
          \zref@ifrefundefined{\@autoindent@info}
            {\zref@setcurrent{yshift}{0pt}}
            {\ifdim\zref@extract{\@autoindent@info}{yshift}=\z@ 
                \zref@setcurrent{yshift}{\the\dimexpr
                  \zref@extract{\@autoindent@info}{lastyshift}}%
              \else
                \zref@setcurrent{yshift}{\the\dimexpr
                  \zref@extract{\@autoindent@info}{yshift}}%
              \fi}
        \else 
          \zref@setcurrent{yshift}{0pt}%
        \fi 
      \else
        \ifdim\zref@extract{\@autoindent@info}{lastyshift}=\@autoindentyshift
          \ifdim\zref@extract{\@autoindent@info}{lastyshift}=
            \zref@extract{\@autoindent@info}{yshift}
            \zref@setcurrent{yshift}{\the\dimexpr\@autoindentyshift}
          \else
            \zref@setcurrent{yshift}{\the\dimexpr
              \zref@extract{\@autoindent@info}{lastyshift}+
              \zref@extract{\@autoindent@info}{yshift}}%
          \fi
        \else 
          \zref@setcurrent{yshift}{\the\dimexpr\@autoindentyshift}%
        \fi
      \fi 
    \else 
      \zref@setcurrent{yshift}{0pt}%
    \fi
    \zref@setcurrent{lastyshift}{\zref@extract{\@autoindent@info}{yshift}}%
    \zref@labelbylist{\@autoindent@info}{autoindent@info}%
    \setlength\@autoindenttrueyshift{\zref@getcurrent{yshift}}%
    \vspace*{\@autoindenttrueyshift}%
    \begin{adjustwidth}{\@autoindentxshift}{\z@}\leavevmode
      \@autoindent@savehangpos \@autoindent@strut \ignorespaces}
  {\end{adjustwidth}}
\newcommand\hang[1]{\begin{autoindent}#1\end{autoindent}}


\newenvironment{autoindent*}[1]{\leavevmode\setbox0\hbox{#1}%
  \ifnum\@autoindentdepth=\z@ \setlength\@autoindentxshift{\dimexpr\parindent+\wd0}%
  \else \setlength\@autoindentxshift{\wd0}%
  \fi
  \setlength\@autoindentyshift{-\baselineskip}%
  \advance\@autoindentdepth\@ne
  \unhbox0
  \nobreak\vspace*{\@autoindentyshift}%
  \begin{adjustwidth}{\@autoindentxshift}{0pt}\ignorespaces}
 {\end{adjustwidth}}

\makeatletter

\begin{document}

\begin{autoindent*}{第一层}
试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试\\
\begin{autoindent*}{第二层}
试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试\\
\begin{autoindent*}{第三层}
试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试
\end{autoindent*}
\end{autoindent*}
\end{autoindent*}

第一层\begin{autoindent}
试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测测试测试测试测试测%
\begin{autoindent}
试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试%
\begin{autoindent}
试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试%
\end{autoindent}
\end{autoindent}
\end{autoindent}

第一层\hang{试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测测试测试测试测试测\hang{试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试\hang{试测试测试测试测试测试测试测试测试测试测试测试测试\hang{测试试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测}}}}

测试 $\displaystyle\int_{\sum}^{\prod}$ 测试\hang{试测试 $\displaystyle\int_{\sum}^{\prod}$ 测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测 $\displaystyle\int_{\sum}^{\prod}$ 试测\hang{试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试}}

\begin{center}
\begin{minipage}{.8\textwidth}
\indentstart 第一层\hang{试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测测试测试测试测试测\hang{试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试\hang{试测试测试测试测试测试测试测试测试测试测试测试测试}}}
\end{minipage}
\end{center}

\end{document}

image.png

1 个回答

撰写答案

请登录后再发布答案,点击登录

发布
问题

分享
好友

手机
浏览

扫码手机浏览