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














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