按字母(或单词)拆分的有趣标题

按字母(或单词)拆分的有趣标题

我想使用我在这个有趣的讨论

这个想法是可以轻松选择不同的简单效果。不幸的是,下面的代码有一些我无法克服的限制:它不接受空格、重音符或宏。

\documentclass[12pt]{article}
\usepackage{graphicx}
\usepackage{lcg}

% decoration
\def\efect{}
\def\decorate#1#2{\reinitrand[first=-#1,last=#1]\aux#2\end}
\def\aux#1{%
    \ifx\end#1
    \else
        \efect#1%
        \expandafter\aux
    \fi}

% efects
\newcommand{\jumpingbox}[1]{\rand\raisebox{\therand pt}{\fbox{#1}}}
\newcommand{\rotationbox}[1]{\rand\rotatebox{\therand}{\fbox{#1}}}

\begin{document}
\noindent
\let\efect\jumpingbox
\decorate{2}{The quick brown fox jumps}\\
\let\efect\rotationbox
\decorate{10}{The quick brown fox jumps}\\
\decorate{10}{{{The}}{{quick}}{{brown}}{{fox}}{{jumps}}{{\dots}}}
\end{document}

在此处输入图片描述

笔记:

  1. 上述链接中的其他解决方案均不支持重音符号(我想也不支持 utf-8 输入编码)。它们中的大多数也不支持空格。
  2. 不知何故,我还会有“逐字逐句”的功能。
  3. 对我来说,研究 TeX 代码很有教育意义。它看起来像一个简单的递归程序。然而,我怀疑它里面可能隐藏着一个非常黑暗的世界。
  4. 我的尝试:

为空格添加条件句

\if#1 %
    { }
\else
    \efect#1%
\fi

以及一个可怕的语法来调用它

\decorate{2}{The{ }quick{ }brown{ }fox{ }jumps{ 
over{ }Mar{{í}}a}\\ % <- note the accentuated 'i'

这些措施虽然可以部分解决问题,但显然不能作为万全之策。

答案1

您可以用空格分隔参数\aux,这样它就逐字进行操作,而不是逐个标记进行操作(这就是它不适用于重音字符的原因:它们由多个标记组成)。

\documentclass[12pt]{article}
\usepackage{graphicx}
\usepackage{lcg}

% decoration
\def\effect{}
\def\decorateEND{\decorateEND}
\edef\decorate#1#2{%
  \noexpand\reinitrand[first=-#1,last=#1]%
  \noexpand\decorateAUX#2 %
  \noexpand\decorateEND\space}
\def\decorateAUX#1 {%
  \ifx\decorateEND#1%
  \else
    \effect{#1}%
    \expandafter\decorateAUX
  \fi}

% effects
\newcommand{\jumpingbox}[1]{\rand\raisebox{\therand pt}{\fbox{#1}}}
\newcommand{\rotationbox}[1]{\rand\rotatebox{\therand}{\fbox{#1}}}

\begin{document}
\noindent
\let\effect\jumpingbox
\decorate{2}{The quick brown fox jumps}\\
\let\effect\rotationbox
\decorate{10}{The quick brown fox jumps}\\
\decorate{10}{The quick brown fox jumps \dots}\\
\decorate{10}{The quick brown fox jumps over María}
\end{document}

在此处输入图片描述


expl3提供了方便的工具来映射列表并获取随机数。您可以使用 分割空格中的输入\seq_set_split:Nnn,然后使用 循环遍历该列表\seq_map_inline:Nn,应用\effect。然后使用\int_rand:nn {min} {max}在该间隔内生成一个随机数。代码非常简单:

\documentclass[12pt]{article}
\usepackage{graphicx}
\usepackage{xparse}
\newcommand\effect{}
\ExplSyntaxOn
\NewDocumentCommand \decorate { m m }
  { \emoro_decorate:nn {#1} {#2} }
\seq_new:N \l__emoro_words_seq
\cs_new_protected:Npn \emoro_decorate:nn #1 #2
  {
    \seq_set_split:Nnn \l__emoro_words_seq { ~ } {#2}
    \seq_map_inline:Nn \l__emoro_words_seq
      { \effect { \int_rand:nn {-#1} {#1} } {##1} }
  }
\ExplSyntaxOff

% efects
\newcommand{\jumpingbox}[2]{\raisebox{#1pt}{\fbox{#2}}}
\newcommand{\rotationbox}[2]{\rotatebox{#1}{\fbox{#2}}}

\begin{document}
\noindent
\let\effect\jumpingbox
\decorate{2}{The quick brown fox jumps}\\
\let\effect\rotationbox
\decorate{10}{The quick brown fox jumps}\\
\decorate{10}{The quick brown fox jumps \dots}\\
\decorate{10}{The quick brown fox jumps over María}
\end{document}

要逐个字母而不是逐个标记地工作,您需要进行一些解析。在 XeTeX 或 LuaTeX 中,这很简单,因为引擎本身支持 Unicode,i并且íι都是单个标记,因此您只需检测空格即可。在 pdfTeX 中,重音字母í由两个标记组成,它们映射到 的 UTF8 代码点í

例如í,“特殊”字符 会扩展为\UTFviii@two@octets <byte>\UTFviii@three@octets <byte>或 之类的内容\UTFviii@four@octets <byte>,这告诉我们正在查看的字母由多少个字节组成。一旦我们知道了,我们就可以抓取该数量的标记并将它们一起传递给\effect

在下面的代码中,这是在 中完成的\__emoro_decorate_token:N\tl_case:NnTF测试查看当前标记的扩展,如果它以任一开头,\UTFviii@<some>@octets则它会调用适当的宏来获取字符的剩余部分并将其传递给\effect。其余代码只是循环遍历参数标记列表并分离单个字符、空格和分组标记(您可以找到此循环机制的简要说明这里这里)您可以使用其他您喜欢的循环机制。

\documentclass[12pt]{article}
\usepackage{graphicx}
\usepackage{xparse}
\newcommand\effect{}
\makeatletter
\ExplSyntaxOn
\NewDocumentCommand \decoratewords { m m }
  { \emoro_decorate_words:nn {#1} {#2} }
\seq_new:N \l__emoro_words_seq
\cs_new_protected:Npn \emoro_decorate_words:nn #1 #2
  {
    \seq_set_split:Nnn \l__emoro_words_seq { ~ } {#2}
    \seq_map_inline:Nn \l__emoro_words_seq
      { \effect {#1} {##1} }
  }
%
\NewDocumentCommand \decorateletters { m m }
  { \emoro_decorate_letters:nn {#1} {#2} }
\tl_new:N \l__emoro_parm_tl
\tl_new:N \l__emoro_output_tl
\cs_new_protected:Npn \emoro_decorate_letters:nn #1 #2
  {
    \tl_set:Nn \l__emoro_parm_tl {#1}
    \tl_clear:N \l__emoro_output_tl
    \__emoro_decorate_loop:w #2
      \q_recursion_tail \q_recursion_stop
  }
\cs_new_protected:Npn \__emoro_decorate_loop:w #1 \q_recursion_stop
  {
    \tl_if_head_is_N_type:nTF {#1}
      { \__emoro_decorate_token:N }
      {
        \tl_if_head_is_group:nTF {#1}
          { \__emoro_decorate_group:n }
          { \__emoro_decorate_space:w }
      }
    #1 \q_recursion_stop
  }
\cs_new_protected:Npn \__emoro_decorate_token:N #1
  {
    \quark_if_recursion_tail_stop_do:Nn #1
      { \tl_use:N \l__emoro_output_tl }
    \exp_args:NNo \exp_args:No \tl_case:NnTF
        { \exp_after:wN \tl_head:w #1 \q_stop }
      {
        { \UTFviii@two@octets   } { \__emoro_UTFviii_two:NNw    }
        { \UTFviii@three@octets } { \__emoro_UTFviii_three:NNNw }
        { \UTFviii@four@octets  } { \__emoro_UTFviii_four:NNNNw }
      }
        {#1}
        { \__emoro_add_output:nw { \__emoro_effect:n {#1} } }
  }
\cs_new_protected:Npn \__emoro_UTFviii_two:NNw #1 #2
  { \__emoro_add_output:nw { \__emoro_effect:n {#1#2} } }
\cs_new_protected:Npn \__emoro_UTFviii_three:NNNw #1 #2 #3
  { \__emoro_add_output:nw { \__emoro_effect:n {#1#2#3} } }
\cs_new_protected:Npn \__emoro_UTFviii_four:NNNNw #1 #2 #3 #4
  { \__emoro_add_output:nw { \__emoro_effect:n {#1#2#3#4} } }
\cs_new_protected:Npn \__emoro_decorate_group:n #1
  { \__emoro_add_output:nw { \__emoro_effect:n {#1} } }
\exp_last_unbraced:NNo
\cs_new_protected:Npn \__emoro_decorate_space:w { \c_space_tl }
  { \__emoro_add_output:nw { \__emoro_effect:n { ~ } } }
\cs_new_protected:Npn \__emoro_add_output:nw #1 #2 \q_recursion_stop
  {
    \tl_put_right:Nn \l__emoro_output_tl {#1}
    \__emoro_decorate_loop:w #2 \q_recursion_stop
  }
\cs_new_protected:Npn \__emoro_effect:n #1
  { \exp_args:NV \effect \l__emoro_parm_tl {#1} }
\cs_new_eq:NN \intrand \int_rand:nn
%
\ExplSyntaxOff

% efects
\newcommand{\jumpingbox}[2]{%
  \if\space#2%
    \space
  \else
    \raisebox{\intrand{-#1}{#1}pt}{\fbox{#2}}%
  \fi}
\newcommand{\rotationbox}[2]{%
  \if\space#2%
    \space
  \else
    \rotatebox{\intrand{-#1}{#1}}{\fbox{#2}}%
  \fi}

\begin{document}

\noindent
\let\effect\jumpingbox
\decoratewords{2}{The quick brown fox jumps}\\
\let\effect\rotationbox
\decoratewords{10}{The quick brown fox jumps}\\
\decoratewords{10}{The quick brown fox jumps \dots}\\
\decoratewords{10}{The quick brown fox jumps over María}

\noindent
\let\effect\jumpingbox
\decorateletters{2}{The quick brown fox jumps}\\
\let\effect\rotationbox
\decorateletters{10}{The quick brown fox jumps}\\
\decorateletters{10}{The quick brown fox jumps \dots}\\
\decorateletters{10}{The quick brown fox jumps over María}
\end{document}

在此处输入图片描述

答案2

这是一个基于的解决方案这个答案

\documentclass[12pt]{article}
\usepackage{graphicx}
\usepackage{lcg}
\usepackage{soul}

\makeatletter
\def\SOUL@soeverytoken{%
 \efect{\the\SOUL@token}}
\makeatother

\newcommand{\jumpingbox}[1]{\rand\raisebox{\therand pt}{\fbox{#1}}}
\newcommand{\rotationbox}[1]{\rand\rotatebox{\therand}{\fbox{#1}}}

\def\decorate#1#2{\reinitrand[first=-#1,last=#1]\so{#2}}

\begin{document}
\noindent
\let\efect\jumpingbox
\decorate{2}{The quick brown fox jumps}\\
\let\efect\rotationbox
\decorate{10}{The quick brown fox jumps}\\
\decorate{10}{{{The}}{{quick}}{{brown}}{{fox}}{{jumps}}{{\dots}}}
\end{document}

在此处输入图片描述

顺便说一句,对于我们猫来说,狐狸不是快速地。

相关内容