假设我有一个原始文本定义为:
\newcommand{\rawtext}{this is some raw text with many words in it}
如何在给定单词或位置后中断此行?当然,我只能\rawtext
在呼叫站点中访问。
一个可能的解决方案是在第 n 个空格前面加上\\
,我只是不知道如何做。
答案1
您也可以使用xstring
包。无需分配计数器并构建循环:
\documentclass{article}
\usepackage{xstring}
\newcommand\breakstring[2]{%
\expandarg\StrCut[#2]{\noexpand#1}{ }\firstline\secondline
\firstline\par\secondline}
\begin{document}
\breakstring{This is the story of Foo Bear}{3}
\end{document}
编辑:为了概括该方法,第二个参数可以包含以逗号分隔的数字列表。每个数字都是一行中的单词数:
\documentclass{article}
\usepackage{xstring}
\newcommand\breakstring[2]{%
\saveexpandmode\expandarg
\def\remaintext{#1}\def\listofcuts{#2,}%
\loop
\StrCut\listofcuts,\currentnumber\listofcuts
\StrCut[\currentnumber]\remaintext\space\currentline\remaintext
\currentline\par
\unless\ifx\empty\listofcuts
\repeat
\remaintext
\restoreexpandmode}
\begin{document}
\breakstring{Une petite cantate du bout des doigts obs\'edante et maladroite monte vers toi}{3,2,4,1}
\end{document}
这使:
答案2
使用 LaTeX3 宏的解决方案。
\documentclass{article}
\usepackage[margin=1cm,a4paper]{geometry} % wide text width
\usepackage{xparse}
\usepackage{kantlipsum}
\kantdef{\rawtext}{1} % some random text
\ExplSyntaxOn
\NewDocumentCommand{\breakafter}{mm}
{
\julio_breakafter:Nn #1 { #2 }
}
\cs_new_protected:Npn \julio_breakafter:Nn #1 #2
{
% split the text into words, breaking at spaces
\seq_set_split:NnV \l_julio_text_seq { ~ } #1
% detach the last word
\seq_pop_right:NN \l_julio_text_seq \l_tmpa_tl
\int_zero:N \l_tmpa_int
% start a mapping on the sequence
\seq_map_inline:Nn \l_julio_text_seq
{
% print the word
##1
% one step done
\int_incr:N \l_tmpa_int
% if the number of steps is a multiple of #2, add \\, else a space
\int_compare:nTF { \int_mod:nn { \l_tmpa_int } { #2 } == 0 }
{ \\ }
{ ~ }
}
% print the last word (unskipping; the space will disappear if at line start
\unskip \c_space_token \l_tmpa_tl
}
\ExplSyntaxOff
\begin{document}
\breakafter\rawtext{8}
\breakafter\rawtext{16}
\end{document}
答案3
这stringstrings
\breakstring
包可以与下面定义的命令一起提供帮助
\documentclass{article}
\usepackage{stringstrings}
\newcounter{wordcount}
\newcommand\breakstring[2]{%
\getargs{#1}%
\setcounter{wordcount}{0}%
\whiledo{\value{wordcount} < \narg}{%
\addtocounter{wordcount}{1}%
\csname arg\roman{wordcount}\endcsname%
\ifthenelse{\value{wordcount} = #2}{\par}{ }%
}
}
\begin{document}
\breakstring{This is the story of Foo Bear}{3}
\end{document}
但如果你点击这个链接,将 \$ 解析为改进的 \getargs 命令的一部分,你会发现你可以用更快的版本替换 \getargs,如下所示。它确实使解析速度更快。我在下面用相同示例包含它的用法:
\documentclass{article}
%DITCH THE FOLLOWING LINE
%\usepackage{stringstrings}
%ADD THIS SECTION INSTEAD
\usepackage{ifnextok}
\usepackage{ifthen}
\makeatletter
\def\stringend{$}
\newcounter{arg@index}
\def\getargsFAST#1{\edef\argi{}\setcounter{arg@index}{1}%
\expandafter\parse@Block#1\stringend}
\def\parse@Block{\IfNextToken\stringend%
{\edef\narg{\arabic{arg@index}}\@gobble}%
{\IfNextToken\@sptoken{\addtocounter{arg@index}{1}%
\expandafter\def\csname arg\roman{arg@index}\endcsname{}%
\add@to{\parse@Block}}%
{\add@to{\parse@Block}}}}
\def\add@to#1#2{\expandafter\protected@edef\csname arg\roman{arg@index}\endcsname%
{\csname arg\roman{arg@index}\endcsname#2}#1}
\makeatother
%END OF ADD SECTION
\newcounter{wordcount}
\newcommand\breakstring[2]{%
\getargsFAST{#1}%
\setcounter{wordcount}{0}%
\whiledo{\value{wordcount} < \narg}{%
\addtocounter{wordcount}{1}%
\csname arg\roman{wordcount}\endcsname%
\ifthenelse{\value{wordcount} = #2}{\par}{ }%
}
}
\begin{document}
\breakstring{This is the story of Foo Bear}{3}
\end{document}
答案4
该宏\breaktextat
接受两个参数。第一个参数表示在哪个空格处进行分行,因为它可能是一个数字,也可能是一个逗号分隔的数字列表。第二个参数是要分行的文本。该宏被声明为“短”,这意味着要分行的文本不应包含空行或\par
空行内的内容。
\documentclass{article}
% we try to make sure we don't overwrite anything
\newcommand*{\breakspacecount}{}
\newcount\breakspacecount
\newcommand*{\breaktextaux}{}
\newcommand*{\breakplace}{}
\newcommand*{\breaknexttoken}{}
\newcommand*{\myendmarker}{}
\def\myendmarker{\myendmarker}
\makeatletter
\newcommand*{\breaktexttest}{%
\ifx\breaknexttoken\myendmarker
\expandafter\@gobble\else
\expandafter\breaktextaux\fi}
% first parameter=comma separated list of break places
% second parameter= the text (no empty line within)
\newcommand*{\breaktextat}[2]{%
\def\breaktextaux ##1 %
{##1\advance\breakspacecount 1
\@for\breakplace:=#1\do{\ifnum\breakspacecount=\breakplace
\\\relax\fi}%
\space
\futurelet\breaknexttoken\breaktexttest}%
\breakspacecount 0
\breaktextaux #2 \myendmarker
}
\makeatother
\begin{document}\thispagestyle{empty}
\breaktextat{3}{this is some raw text with many words in it}
\breaktextat{1,3,5,8,11,14,18,22,26,31,36,41,47,53,59}
{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. Phasellus eu tellus sit
amet tortor gravida placerat. Integer sapien est, iaculis in,
pretium quis, viverra ac, nunc. Praesent eget sem vel leo
ultrices bibendum.}
% inserting more than one line:
\breaktextat{3,3,3,3}{this is some raw text with many words in it}
\end{document}