我现有如下代码:
\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是估计值,那么精确值如何确定呢?
第二个问题,如何测量标签的长度,比如“第一层”这几个字
与缩进相关的环境和命令基本上都是使用 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}
大佬你好,我需要这种东西实现这样的效果:
标签\hang{悬挂文本}
,也就是说标签要在悬挂环境(或命令)的外面,然后要支持嵌套,之前我也提过相似的问题,但总没有一个比较好的解决方案。如果不是在正常文字,两基线间的距离就不一定是 baselineskip,比较棘手的
能否根据不同的情况自动测量基线?能否把标签放在环境的外面?
@u7483 为什么要做这个。
@u7483 1. 保存绝对坐标。 2. 保存绝对坐标。
使用
\lastxpos
、\lastypos
primitive,或者zref-abspos
、zref-savepos
(zref
bundles)宏包。@u10307 做这个是为了更方便地实现悬挂缩进
不支持多栏是什么意思?我用paracol环境分两栏好像没问题的
感觉还是迁就一下LaTeX,工作比较愉快。