我正在尝试定义一个命令,用重复次数\todopar[dummy]{msg}
填充一个段落并在段落中居中排版。dummy
msg
最终结果应该是这样的(没有间距问题)
我的第一次尝试
\documentclass[draft]{article}
\usepackage{lipsum}
\usepackage{xcolor}
\colorlet{todocol}{green!30!black}
\newcommand{\repetita}[1]{\leavevmode\xleaders\hbox{#1\ }\hfill\kern0pt}
\newcommand{\todopar}[2][To Do]{%
\par\medskip\noindent{%
\color{todocol!50!white}
\null\repetita{#1}\\%
\null\repetita{#1}\\%
\null\repetita{#1}%
\textcolor{todocol}{#2}%
\repetita{#1}\\%
\null\repetita{#1}\\%
\null\repetita{#1}\par\medskip%
}}
\begin{document}
\lipsum*[1]
\todopar{This is somehing we have to do soooo bad that takes even more than one line oh my gosh.}
\lipsum*[1]
\todopar{Lot of work}
\lipsum*[1]
\end{document}
不幸的是,使用时\xleaders
我没有得到与段落其余部分对齐的中心行中的虚拟文本,而且hbox
领导者的内容以空格结尾,这意味着最后一次重复也将以空格结束该行。
我该如何解决这两个问题?有没有更优雅的方法来实现这种效果?
答案1
我会用一段话来代替领导者:
\documentclass[draft]{article}
\usepackage{lipsum}
\usepackage{xcolor}
\colorlet{todocol}{green!30!black}
\newcommand{\todopar}[2][To Do]{%
% end the previous par and start a local group
\par\medskip{%
% special para uses full length lines, no white space
% at start or end
\parindent0pt
\parfillskip0pt
% set colour for the filler text
\color{todocol!50!white}%
% save filler text in box, for measuring
\sbox0{#1 }%
%
% Set the message text in a normal paragraph with normal
% \parfillskip to allow the last line to be short as usual.
% the whole construct is inside a scratch box 2.
\setbox2\vbox{\parfillskip\fill\strut#2\unskip\strut
% Finish the paragraph with the message text
\par
% Probably not needed but remove any glue or penalty
% after the last line
\unskip\unpenalty
% remove the last (or only) line of the message paragraph
\setbox0\lastbox
%
% At this point box0 is always full width but contains the last
% line of the message followed by \rightskip and \parfillskip glue
% so \unskip twice and globally save box1 with the natural length
% of the last line of the message.
\global\setbox1\hbox{\unhbox0\unskip\unskip}%
%
% Now remove the baselineskip glue before that last line.
\unskip\unpenalty\unskip\unpenalty
% and finish the box
}%
% Now box2 contains all the lines of the message except the last
% so for a short message it will be empty
%
% see how many filler text it takes for 2 lines of text
\count0=\dimexpr2\columnwidth\relax
\divide\count0 \wd0 %
%
% see how many filler text it takes to pad one side
% of a line that has the (last line of) the message in
% the middle
\count2=\dimexpr(\columnwidth-\wd1-2em)/2\relax
\divide\count2 \wd0 %
%
% save the filler text, use a macro rather than the box
% to allow any white space in the filler to stretch
\def\tmp{\strut#1 }%
%
% make a paragraph of \count0 copies of the filler making
% a two full length line paragraph
\xrep{\count0}\par
%
% unbox box 2 this is the initial full length lines of the message
% in the main color. As this is unboxed it is a normal sequence of
% line boxes and glue so can break at a page.
{\color{todocol}\unvbox2}%
%
% Now make a 1-line paragraph with count2 copies of filler
% either side of the last line of the message, with a word space
% padding either side/
\xrep{\count2} \textcolor{todocol}{\unhbox1} \xrep{\count2}\par
%
% As before a 2 line filler paragraph
\xrep{\count0}\par%
%
% end the local group
}%
% A skip to match the one at the start.
\medskip}
% A simple recursive loop macro, makes #1
% copies of \tmp
\def\xrep#1{%
\ifnum#1>0
\tmp
\xrep{\numexpr#1-1\relax}%
\fi}
% A test document....
\begin{document}
\lipsum*[1]
\todopar{This is somehing we have to do soooo bad that takes even more than one line oh my gosh.}
\lipsum*[1]
\todopar{Lot of work}
\lipsum*[1]
\end{document}