当使用时\parshape
,我可以使用
\newline\hspace*{0.5\parindent}
产生一个新的“段落”并且仍然继续当前的\parshape
。
是否可以留下一个空行,并仍然获得上述效果?也就是说,空行应该不是成为一个\par
重置的\parshape
。
下面的 MWE(带有注释掉\par
和\newline\hspace*{0.5\parindent}
取消注释的)产生所需的输出:
但我希望能够留下一个空白行,并且在使用时\parshape
自动使用一些产生所需行为的宏。
笔记:
- 这适用于一页内可容纳的几个段落。
- 除了在视觉上更易于阅读/编辑之外,留出空白行还可以进行常规排版。我需要能够在此环境中正常排版内容。
代码:
\documentclass{article}
\usepackage{showframe}
\newcommand*{\Text}{%
\sloppy\noindent
Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
Ut purus elit, vestibulum ut, placerat ac, adipiscing vitae, felis.
\par% <-- would prefer this though, or even better a blank line
%\newline\hspace*{0.5\parindent}% <-- Replacing the \par with this works
Curabitur dictum
gravida mauris. Nam arcu libero, nonummy eget, consectetuer id, vulputate a, magna.
Donec vehicula augue eu neque. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Mauris ut leo. Cras viverra metus rhoncus sem.
Nulla et lectus vestibulum urna fringilla ultrices.%
}%
\newcommand*{\TitleParShape}{%
0.40\hsize 0.20\hsize
}%
\newcommand*{\BodyParShape}{%
0.35\hsize 0.30\hsize
0.30\hsize 0.40\hsize
0.25\hsize 0.50\hsize
0.20\hsize 0.60\hsize
0.15\hsize 0.70\hsize
0.10\hsize 0.80\hsize
0.05\hsize 0.90\hsize
0.00\hsize 1.00\hsize
}%
\newcommand*{\MyParShape}{%
\parshape 9
\TitleParShape
\BodyParShape
}%
\begin{document}
\parshape 1
\TitleParShape
{\bfseries\centering My Title\par\smallskip}%
\parshape 8
\BodyParShape
\Text
\end{document}
答案1
在更多情况下重写工作
我删除了原始答案并添加了此重写。重写应适用于更多 par 形状(原始答案仅适用于最多具有 8 个定义的 par 形状)。
怎么运行的:
我正在重新定义\par
宏以插入一些代码(因此请谨慎使用,如果有疑问则将其分组,重新定义是本地的)。
\documentclass{article}
\usepackage{showframe}
\newcommand*{\Text}{%
\sloppy\noindent
Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
Ut purus elit, vestibulum ut, placerat ac, adipiscing vitae, felis.
Curabitur dictum
gravida mauris. Nam arcu libero, nonummy eget, consectetuer id, vulputate a, magna.
Donec vehicula augue eu neque. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Mauris ut leo. Cras viverra metus rhoncus sem.
Nulla et lectus vestibulum urna fringilla ultrices.%
}%
\makeatletter
\@ifdefinable\peterCountA{\newcount\peterCountA}% stores lines already done
\@ifdefinable\peterCountB{\newcount\peterCountB}% stores prevgraf
\@ifdefinable\peterCountC{\newcount\peterCountC}% stores BodyParShape number
\newcommand*{\TitleParShape}{%
0.40\hsize 0.20\hsize
}%
\peterCountC=8 % number of items in the BodyParShape
\newcommand*{\BodyParShape}{%
0.35\hsize 0.30\hsize
0.30\hsize 0.40\hsize
0.25\hsize 0.50\hsize
0.20\hsize 0.60\hsize
0.15\hsize 0.70\hsize
0.10\hsize 0.80\hsize
0.05\hsize 0.90\hsize
0.00\hsize 1.00\hsize
}
\@ifdefinable\eatParShapeLine
{\long\def\eatParShapeLine#1\hsize #2\hsize {}}
\@ifdefinable\myif@fiAa % equivalent to \expandafter\@firstoftwo
{\long\def\myif@fiAa#1\fi#2#3{\fi#2}}
\@ifdefinable\myif@fiBb % equivalent to \expandafter\@secondoftwo
{\long\def\myif@fiBb\fi#1#2{\fi#2}}
% helper macro to expand the first token in the last argument once
\newcommand\myexp@NnV[3]
{%
\expandafter\myexp@NnV@\expandafter{#3}{#1}{#2}%
}
\newcommand\myexp@NnV@[3]
{%
#2{#3}{#1}%
}
% a wrapper around \eatParShapeLine to eat the first #1 lines in the parshape #2
\newcommand\eatParShapeLines[2]
{%
\myexp@NnV\eatParShapeLinesAux{#1}{#2}%
}
% expandable loop
\newcommand\eatParShapeLinesAux[2]
{%
% if still loops to do
\ifnum#1>0
% reinsert the first token/group after \fi
\myif@fiAa
\else
% reinsert the second token/group after \fi
\myif@fiBb
\fi
{%
% reinsert the \eatParShapeLinesAux with #1 decreased by 1 and the first
% two \hsize fractions from #2 eaten
\expandafter\myexp@NnV\expandafter\eatParShapeLinesAux\expandafter
{\the\numexpr#1-1}{\eatParShapeLine#2}%
}
% loop is done, reinsert the shortened parshape
{#2}%
}
\newcommand\BodyParShapeNum[2]
{%
% \parshape expands its arguments to find numbers and dimensions
\parshape #1 \eatParShapeLines{#2}\BodyParShape
}
\newcommand*{\MyParShape}{%
\parshape 9
\TitleParShape
\BodyParShape
}%
\newcommand\ParshapeMultiPar
{%
% setup initial BodyParShape
\parshape \peterCountC \BodyParShape
% no lines processed yet
\peterCountA=0
% redefine \par to reinsert the left over parshape entries
\def\par
{%
% end the previous paragraph
\endgraf
% save the \prevgraf counter (lines of last paragraph)
\peterCountB\prevgraf
% check whether there are still lines left from BodyParShape
\ifnum\numexpr\peterCountC-\peterCountA>\peterCountB
% update lines already done
\advance\peterCountA\peterCountB
% set the parshape for the next par, leave out first \peterCountA
% lines
\expandafter\BodyParShapeNum\expandafter
{\the\numexpr\peterCountC-\peterCountA}{\peterCountA}%
% fake a parindent
\noindent\hspace*{.5\parindent}
\else
% else is executed if the BodyParShape was ended in the previous
% paragraph. In this case revert the redefinition of \par
\let\par\endgraf
\fi
}%
}
\makeatother
\begin{document}
\parshape 1
\TitleParShape
{\bfseries\centering My Title\par\smallskip}%
\parshape 8
\BodyParShape
\Text
\ParshapeMultiPar
\Text
\end{document}
答案2
不确定这是否是您想要的。我通过\parskip
设置在输出中添加了一个空白行。我删除了\Text
所有格式,因为您说您想在其他地方使用宏。\resumebody
默认情况下不执行任何操作,但可用于恢复某些 parshape。(不需要了解 parshape 的太多信息,也许是它处理的行数;如果前一段已经用尽 parshape,我没有添加错误检查。)
\documentclass{article}
\usepackage{showframe}
\newcommand*{\Text}{%
Lorem ipsum dolor sit amet, consectetuer adipiscing
elit. Ut purus elit, vestibulum ut, placerat ac, adipiscing vitae,
felis.
\resumebody
Curabitur dictum gravida mauris. Nam arcu libero, nonummy eget,
consectetuer id, vulputate a, magna. Donec vehicula augue eu neque.
Pellentesque habitant morbi tristique senectus et netus et malesuada
fames ac turpis egestas. Mauris ut leo. Cras viverra metus rhoncus
sem. Nulla et lectus vestibulum urna fringilla ultrices.%
}%
\newcommand*{\TitleParShape}{%
0.40\hsize 0.20\hsize
}%
\newcommand*{\BodyParShape}{%
0.35\hsize 0.30\hsize % 10 tokens per line spec
0.30\hsize 0.40\hsize
0.25\hsize 0.50\hsize
0.20\hsize 0.60\hsize
0.15\hsize 0.70\hsize
0.10\hsize 0.80\hsize
0.05\hsize 0.90\hsize
0.00\hsize 1.00\hsize
}%
\newcommand*{\MyParShape}{%
\parshape 9
\TitleParShape
\BodyParShape
}%
\usepackage{xinttools}
\newcommand*{\resumebodyparshape}{%
\parshape \numexpr8-\prevgraf-1\relax
\xintTrim{10*\prevgraf+10}{\BodyParShape}%
}
\newcommand*{\resumebody}{}
\begin{document}
\parshape 1
\TitleParShape
{\bfseries\centering My Title\par\smallskip}%
\parshape 8
\BodyParShape
\let\resumebody\resumebodyparshape
\edef\currentparfillskip{\the\parfillskip}\parfillskip0pt
\edef\currentparskip{\the\parskip}\parskip\baselineskip
\sloppy
\noindent
\Text
\parfillskip\currentparfillskip
\par
\parskip\currentparskip
\let\resumebody\empty
\end{document}
我为了方便使用,甚至通过它的宏xinttools
,更轻量级的包就足够了。(但是我需要在吞噬之前添加一些扩展,即这有效:xintkernel
\xintgobble
\expandafter
\BodyParShape
\usepackage{xintkernel}
\newcommand*{\resumebodyparshape}{%
\edef\temp{%
\parshape \numexpr8-\prevgraf-1\relax
\noexpand\romannumeral\noexpand\xintgobble{10*\prevgraf+10}\BodyParShape}%
\temp
}
或这个
\usepackage{xintkernel}
\newcommand*{\resumebodyparshape}{%
\parshape \numexpr8-\prevgraf-1\relax
\expandafter\resumebodyaux\expandafter{\BodyParShape}%
}%
\def\resumebodyaux#1{\romannumeral\xintgobble{10*\prevgraf+10}#1}
并且只需要xintkernel
包。)
答案3
如果你够勇敢的话l3galley
...我认为现在还存在太多问题无法l3galley
真正使用它,但它展示了未来可能实现的可能性。
一些说明:
- 我使用内部变量在环境结束时停止剪切(以防段落较短)。这似乎是个坏主意,但我无法通过其他方式停止剪切。
l3galley
破坏东西。
平均能量损失
\documentclass{article}
\usepackage{xparse}
\usepackage{l3galley}
\ExplSyntaxOn
\clist_new:N \l__grill_indents_clist
\clist_set:Nn \l__grill_indents_clist
{
0.35\hsize, 0.30\hsize, 0.25\hsize, 0.20\hsize,
0.15\hsize, 0.10\hsize, 0.05\hsize, 0.00\hsize
}
\NewDocumentEnvironment { pyramid } { }
{
\dim_set:Nn \l_galley_par_indent_dim { 0pt }
\use:x
{
\exp_not:N \galley_cutout_left:nn { 0 }
{
\clist_use:Nn \l__grill_indents_clist { , }
}
}
\use:x
{
\exp_not:N \galley_cutout_right:nn { 0 }
{
\clist_use:Nn \l__grill_indents_clist { , }
}
}
\sloppy
}
{
\galley_par:
\seq_gclear:N \g__galley_cutout_left_seq
\seq_gclear:N \g__galley_cutout_right_seq
\bool_gset_false:N \g__galley_cutout_active_bool
}
\ExplSyntaxOff
\begin{document}
\begin{pyramid}
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Ut purus elit,
vestibulum ut, placerat ac, adipiscing vitae, felis.
Curabitur dictum gravida mauris. Nam arcu libero, nonummy eget, consectetuer
id, vulputate a, magna. Donec vehicula augue eu neque. Pellentesque habitant
morbi tristique senectus et netus et malesuada fames ac turpis egestas.
Mauris ut leo. Cras viverra metus rhoncus sem. Nulla et lectus vestibulum
urna fringilla ultrices.
\end{pyramid}
\end{document}