![“写 300 句关于 \Lipsum 的句子”?这样的 `\Lipsum` 宏会很棒](https://linux22.com/image/333317/%E2%80%9C%E5%86%99%20300%20%E5%8F%A5%E5%85%B3%E4%BA%8E%20%5CLipsum%20%E7%9A%84%E5%8F%A5%E5%AD%90%E2%80%9D%EF%BC%9F%E8%BF%99%E6%A0%B7%E7%9A%84%20%60%5CLipsum%60%20%E5%AE%8F%E4%BC%9A%E5%BE%88%E6%A3%92.png)
免责声明:这个问题不是为了满足一般需要。它甚至不是我自己的问题需要,或者任何其他人的“需要”。只是建议一个简洁的使用和抛出宏。
在为我和我的学生制作模板LaTeX
文件时,我认为写下以下内容会很有趣:
Write \Lipsum 300 sentences.
该宏\Lipsum
需要一个数字和一个终止序列。在上面的例子中,数字是整数 300。终止序列始终相同:sentences.
,即标记的序列:“ s
”,“ e
”,...,“ e
”,“ s
”,“ .
”。
宏将扩展为指定句子数的 Lipsum 文本。如果这些文本不总是相同就好了。
答案1
以下是利用 PGF 功能的可能解决方案:
\documentclass{article}
\usepackage{pgffor}
\def\getRandomSentence{%
\pgfmathparse{random(5)}%
\ifcase\pgfmathresult\relax
Sentence 1.
\or
Sentence 2.
\or
Sentence 3.
\or
Sentence 4.
\or
Sentence 5.
\else
Default Sentence.
\fi
}
\def\Lipsum#1 sentences.{%
\ifnum#1<1
ERROR!
\else
\foreach \n in {1,...,#1} {%
% (\n)
\getRandomSentence
}%
\fi
\ignorespaces
}
\begin{document}
Test A:
Write \Lipsum 1 sentences. Test
Test B:
Write \Lipsum 10 sentences. Test
Test C:
Write \Lipsum 0 sentences. Test
\end{document}
只需添加适当数量的句子并相应地更改数字random(5)
。\Lipsum
测试句子数是否大于或等于 1,如果不大于或等于,则写入“ERROR”。
在\Lipsum 1 sentences.
数字前的空格处选修的而数字后面的空格是强制的喜欢sentences.
。
不过我建议使用类似的正常语法\LipsumSentences{300}
。
答案2
我在我的博客中更详细地解释了这个实现:http://tobiw.de/tbdm/blindtext(仅限德语)
更新:
该实现现在尝试立即防止重复句子(和标点符号)。尝试获取不同含义的最大次数设置为 10,但可以在代码中更改。此外,调试信息稍好一些,现在也写入日志文件(终端)。
这是使用 LaTeX3 函数的另一种实现。在此解决方案中,可以设置带有 的句子池\SetLipsumPool
和带有 的标点符号池\SetPunctPool
。
生成文本使用
\LipsumI <N> sentences.
或者
\LipsumII{<N>}
我会使用后者……
代码:
\documentclass{article}
\usepackage{pgffor,xparse}
\ExplSyntaxOn
% pool for sentences
\seq_new:N \g_yossi_lipsum_pool_seq
% count of sentences in pool
\int_new:N \g_yossi_lipsum_pool_int
% numbers for generating a random number
\int_new:N \g_yossi_current_int
\int_new:N \g_yossi_tries_int
\int_new:N \g_yossi_last_lipsum_int
\int_new:N \g_yossi_last_punct_int
% number of max tries to get a differnet random number than last on
\int_new:N \c_yossi_max_tries_int
\int_set:Nn \c_yossi_max_tries_int { 10 }
% pool for punctuation
\seq_new:N \g_yossi_punct_pool_seq
% count of punctuation marks in pool
\int_new:N \g_yossi_punct_pool_int
% boolean for debug mode
\bool_new:N \c_yossi_debug_bool
%\bool_set_true:N \c_yossi_debug_bool% debug mode on
\cs_new:Npn \yossi_add_to_lipsum_pool:n #1 {
% set from argument by spliting at dots
\seq_gset_split:Nnn \tmpa_seq { . } { #1 }
\seq_gconcat:NNN \yossi_lipsum_pool_seq \yossi_lipsum_pool_seq \tmpa_seq
% remove the duplicates
\seq_gremove_duplicates:N \yossi_lipsum_pool_seq
% remove emtpy sentences
\seq_remove_all:Nn \yossi_lipsum_pool_seq { }
% save number of sentences in pool
\int_gset:Nn \g_yossi_lipsum_pool_int { \seq_count:N \yossi_lipsum_pool_seq }
}
% user macro to set up the pool
\NewDocumentCommand { \SetLipsumPool } { m } {
\seq_gclear:N \yossi_lipsum_pool_seq
\yossi_add_to_lipsum_pool:n { #1 }
}
% user macro to add sentences to the pool
\NewDocumentCommand{ \AddToLipsumPool }{ m }{
\yossi_add_to_lipsum_pool:n { #1 }
}
% user macro to set up the pool
\NewDocumentCommand { \SetPunctPool } { m } {
% set from argument
\seq_gset_split:Nnn \g_yossi_punct_pool_seq { } { #1 }
% save number of puctuation marks in pool
\int_gset:Nn \g_yossi_punct_pool_int { \seq_count:N \g_yossi_punct_pool_seq }
}
\cs_new:Npn \yossi_get_random_number:NN #1#2 {
\int_gzero:N \g_yossi_tries_int
\bool_do_while:nn {
\int_compare_p:n { #2 = \g_yossi_current_int }
&&
\int_compare_p:n { \g_yossi_tries_int < \c_yossi_max_tries_int }
} {
\pgfmathparse { random(1,#1) }
\int_gset:Nn \g_yossi_current_int { \pgfmathresult }
\int_gincr:N \g_yossi_tries_int
\iow_term:x {
[
find ~ random ~ number: ~
curr = \int_use:N \g_yossi_current_int \c_space_tl
last = \int_use:N #2 \c_space_tl
try = \int_use:N \g_yossi_tries_int
]
}
}
% debug info
\bool_if:NT \c_yossi_debug_bool {
\newline (
get ~ random ~ number: ~
current\,=\,\int_use:N \g_yossi_current_int ; ~
last\,=\,\int_use:N #2 ; ~
tries\,=\,\int_use:N \g_yossi_tries_int )
\newline
}
\int_gset_eq:NN #2 \g_yossi_current_int
}
% internal macro to get random sentecs
\cs_new_protected:Nn \yossi_get_random_sentence: {
% get random sentence from pool
\yossi_get_random_number:NN \g_yossi_lipsum_pool_int \g_yossi_last_lipsum_int
\seq_item:Nn \yossi_lipsum_pool_seq { \g_yossi_current_int }
% add random punctiation
\yossi_get_random_number:NN \g_yossi_punct_pool_int \g_yossi_last_punct_int
\seq_item:Nn \g_yossi_punct_pool_seq { \g_yossi_current_int }
% add space
\c_space_tl
}
% user macro to get #1 sentences
\def\LipsumI#1~sentences. {%
\iow_term:x {
===================================== ^^J
START LIPSUMS ^^J
-------------------------------------
}
% test if ' is bigger than 1
\int_compare:nTF { #1 < 1 } {% TRUE - #1 is smaller: Error
ERROR!
} {% FALSE - #1 is bigger: loop #1 times
\foreach \n in {1,...,#1} {%
% debug info
\bool_if:NT \c_yossi_debug_bool {
\par\bigskip
\fbox{\textbf{n\,=\,\n}}
}
\iow_term:x {
\n . ~ SENTENCE
}
% get random sentence (incl. punct and space)
\yossi_get_random_sentence:
}%
}
\iow_term:x {
------------------------------------- ^^J
END LIPSUMS ^^J
=====================================
}
% ignore spaces (on was added by \yossi_get_random_sentence: already)
\ignorespaces
}
% alternative user macro with normal syntax
% (copy the implementation if you want to use this version)
\NewDocumentCommand{ \LipsumII } { m } {
\LipsumI #1~sentences.
}
\ExplSyntaxOff
% preset pools
\SetLipsumPool{Lorem ipsum dolor sit amet, consectetur adipiscing elit.}
\SetPunctPool{.}
\begin{document}
% set pools
\SetLipsumPool{
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis lectus elit,
tempus quis efficitur ut, consequat sed lorem. Cras convallis et nibh id
accumsan.
}
\SetPunctPool{........:?!}% make dot more likely
Write \LipsumI 1 sentences. Test
Write \LipsumI 10 sentences. Test
Write \LipsumI 0 sentences. Test
\AddToLipsumPool{Another senseless sentence.}
Write \LipsumI 10 sentences. Test
\AddToLipsumPool{
Pellentesque mollis, magna sed placerat mattis, quam nisl euismod dui, et
sollicitudin orci lacus ac dolor. Phasellus pretium, purus ac lobortis
mattis, leo libero lobortis ligula, ut rhoncus mauris purus at odio. Morbi
vitae mollis ipsum. Morbi risus augue, feugiat quis posuere a, dapibus sed
arcu. Fusce pharetra massa vitae tristique auctor. Sed sagittis placerat
vestibulum. Curabitur a tempus arcu, eget ullamcorper urna. Maecenas
malesuada placerat enim, sit amet commodo risus scelerisque vel. Sed vel
feugiat est. Pellentesque habitant morbi tristique senectus et netus et
malesuada fames ac turpis egestas. Praesent rhoncus facilisis quam in
faucibus.
}
Write \LipsumI 10 sentences. Test
\SetLipsumPool{Only one sentence}
Write \LipsumI 10 sentences. Test
\bigskip
Write \LipsumII{5} Test
\end{document}
笔记:
该实现还包括一个基本的调试模式。