我使用以下布局,其中\sec{}
标题放在边距中,\subsec{}
标题和文本段落放在旁边的主列中。
但是,当 a\subsec{}
紧跟在 之后时\sec{}
,我希望两者都从同一行开始,没有垂直空格。问题是我不能只在其中一个命令中包含负空格,因为\subsec{}
当它跟在 以外的任何命令之后时仍应创建空格\sec{}
。我该如何实现这一点?
这是一个显示了不需要的空间的小例子,我希望 SECTION 和 Subsection 从同一行开始,并保持所有其他间距不变:
\documentclass{article}
\usepackage{calc}
\usepackage{changepage}
\usepackage{lipsum}
\setlength{\parskip}{.5em}
\setlength{\parindent}{0em}
\newcommand{\titlecol}{1.45in}
\newcommand{\titlesep}{0.5em}
\newcommand{\secskip}{1.6em}
\newcommand{\subsecskip}{0.6em}
\renewcommand{\sec}[1]{%
\vspace{\secskip}\hspace{-\titlecol}%
\parbox[t][0pt][t]{\titlecol-\titlesep}{#1\raggedright}}
\newcommand{\subsec}[1]{\vspace{\subsecskip}\textbf{#1}\par}
\begin{document}
\begin{adjustwidth}{\titlecol}{0em}
\sec{SECTION}
\subsec{Subsection}
\lipsum[1][1-2] \par
\lipsum[1][3]
\subsec{Subsection}
\lipsum[1][1-3]
\sec{ANOTHER SECTION}
\lipsum[1][1-3]
\end{adjustwidth}
\end{document}
答案1
以下纯 TeX 宏\sec
以这样的方式定义:将节标题排版为节中第一段的一部分(因此不会插入分页符):
\def\sec#1{\vskip\secskip
\noindent\llap{
\setbox0=\vtop{\hsize\titlecol\advance\hsize by-\titlesep\raggedright#1}
\dp0=0pt\box0\hskip\titlesep}\ignorespaces}
如果您已经在段落中,则可以省略小节之前的垂直跳过,即仅在垂直模式下贡献垂直跳过:
\def\subsec#1{\ifvmode\vskip\subsecskip\fi\textbf{#1}\par}
\sec
但是您必须避免在和之间留空行\subsec
,因为这将结束该节开始的段落,从而使该小节贡献垂直跳过:
\sec{SECTION}
\subsec{Subsection}
答案2
您可以设置标题文本,然后返回到垂直模式,然后通过一组\vskip
s 来纠正垂直位置,然后放置一个\penalty
带有特殊(不可破坏)数字(示例中为 10013)的 s。
如果情况\subsec
如下,那么您可以通过 读取该数字,并在 上面\lastskip
放置(或不放置) a :\vskip
\subsec
\parskip=.5em
\parindent=0em
\def\titlecol{1.3in}
\def\titlesep{0.5em}
\def\secskip{1.6em}
\def\subsecskip{0.6em}
\hoffset=6cm
\hsize=12cm
\def\sec#1{%
\vskip\secskip
\hskip-\titlecol
\vtop {\hsize=\dimexpr\titlecol-\titlesep\relax \rightskip=0pt plus1fil\relax #1\vss}
\par
\nobreak \vskip-\prevdepth \prevdepth=0pt \vskip-\baselineskip \vskip-\parskip
\penalty10013
}
\def\subsec#1{\ifnum\lastpenalty=10013 \else \vskip\subsecskip\fi {\bf#1}\par\nobreak}
\sec{SECTION}
\subsec{Subsection}
\lipsum[1]\par
\lipsum[2]
\subsec{Subsection}
\lipsum[1]
\sec{ANOTHER SECTION}
\lipsum[1]
编辑:我尝试更详细地解释代码。\sec
宏将 放在\vtop
左侧(一行或多行),作为 由 完成的单行段落的一部分\par
。 中的第二行和更多行\vtop
累积在 的深度中。如果我们在 之后放置下一个材料\par
,则该材料将位于其之后,即 的最后一行之后\vtop
。\prevdepth
是 TeX 寄存器(只能在垂直模式下使用),我们可以在其中读取或设置最后一个设置为垂直模式的框的深度,即\vtop
我们示例中的这个。\vtop-\prevdepth
返回 的第一行基线处的当前排版点\vtop
。我们在使用它之后将其设置为零,因为在垂直模式下下一个框的放置是根据\baselineskip
或计算\lineskip
的\prevdepth
。我们想要使用\baselineskip
,我们通过 返回排版点,-\baselineskip
以便下一个框的基线与 的基线相同\vtop
。但下一段\parskip
也会增加,所以我们也必须放置负数\parskip
。
\rightskip=0pt plus1fil\relax
与 类似,但\raggedright
右侧的粘连可无限拉伸,因此排除开始使用连字符的单词(因为我们不希望标题中出现这样的连字符)。
答案3
这假定您从不以 开始章节文本{
。
\documentclass{article}
\usepackage{calc}
\usepackage{changepage}
\usepackage{lipsum}
\setlength{\parskip}{.5em}
\setlength{\parindent}{0em}
\newcommand{\titlecol}{1.45in}
\newcommand{\titlesep}{0.5em}
\newcommand{\secskip}{1.6em}
\newcommand{\subsecskip}{0.6em}
\renewcommand{\sec}[1]{%
\par
\addvspace{\secskip}\hspace{-\titlecol}%
\makebox[\titlecol][l]{\parbox[t][0pt][t]{\titlecol-\titlesep}{#1\raggedright}}%
\subsecfalse
\checksubsec
}
\makeatletter
\newcommand{\checksubsec}[1]{%
\ifx#1\par
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
\fi
{\checksubsec}% found \par, repeat
{\checksubsec@#1}% check for \subsec
}
\newcommand{\checksubsec@}[1]{%
\ifx#1\subsec
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
\fi
{\subsectrue\subsec}% found \subsec set the conditional to true
{#1}% reinsert the token
}
\makeatother
\newif\ifsubsec
\newcommand{\subsec}[1]{%
\ifsubsec\else\par\addvspace{\subsecskip}\fi
\textbf{#1}\par\nobreak
}
\begin{document}
\begin{adjustwidth}{\titlecol}{0em}
\sec{SECTION}
\subsec{Subsection}
\lipsum[1][1-2] \par
\lipsum[1][3]
\subsec{Subsection}
\lipsum[1][1-3]
\sec{ANOTHER SECTION}
\lipsum[1][1-3]
\end{adjustwidth}
\end{document}
查看第一个标记(忽略空格)。如果是,\par
则将其丢弃并重复;如果是,\subsec
则将条件设置为 true 并\subsec
再次发出。否则,将重新插入标记并继续排版。
我做了一些更改:将章节标题设置在适当尺寸的框中,并在其中设置\parbox
减小的宽度(减小的);我添加了章节或小节,以便它们不会与以下文本分离。\titlesep
\nobreak
您最好使用geometry
并实际设置边距中的章节标题,而不是使用全局的来伪造它adjustwidth
。
答案4
非常感谢 Heiko Theißen 建议将\sec
内联排版为段落的一部分,然后检查\subsec
我们是否已经在段落中,否则(\ifvmode
)插入垂直空格。
我还曾经为了避免在开始新段落\@ifnextchar\par\@gobble\relax}
后出现空行,而这需要将定义包装在和 中。由于我们已经忽略了段落分隔符,因此似乎不再需要了。\sec
\sec
\makeatletter
\makeatother
\ignorespaces
此外,我从纯 TeX 解决方案切换到\parbox
我更熟悉的 LaTex,这样我就可以更轻松地理解和修改解决方案。还要感谢 egreg 建议使用\nobreak
/\nopagebreak
来防止部分与后续段落分离。
\makeatletter
\def\sec#1{%
\vskip\secskip%
\noindent\llap{\parbox[t][0pt][t]{\titlecol-\titlesep}{\raggedright#1}}%
\nopagebreak\@ifnextchar\par\@gobble\relax}
\makeatother
\def\subsec#1{%
\ifvmode\vskip\subsecskip\fi%
\textbf{#1}\par\nopagebreak}
完整示例:
\documentclass{article}
\usepackage{calc}
\usepackage{changepage}
\usepackage{lipsum}
\setlength{\parskip}{.5em}
\setlength{\parindent}{0em}
\newcommand{\titlecol}{1.45in}
\newcommand{\titlesep}{0.5em}
\newcommand{\secskip}{1.6em}
\newcommand{\subsecskip}{0.6em}
\makeatletter
\def\sec#1{%
\vskip\secskip%
\noindent\llap{\parbox[t][0pt][t]{\titlecol-\titlesep}{\raggedright#1}}%
\nobreak\@ifnextchar\par\@gobble\relax}
\makeatother
\def\subsec#1{%
\ifvmode\vskip\subsecskip\fi%
\textbf{#1}\par}
\begin{document}
\begin{adjustwidth}{\titlecol}{0em}
\sec{SECTION}
\subsec{Subsection}
\lipsum[1][1-2]\par
\lipsum[2][1-3]
\subsec{Subsection}
\lipsum[1][1-2]
\sec{ANOTHER SECTION}
\lipsum[1][1-3]
\end{adjustwidth}
\end{document}
结果: