LaTeX如何形成Bionic-Reading风格的环境?

LaTeX如何形成Bionic-Reading风格的环境?

仿生阅读试图找到每一个单词,并将第一部分加粗。

我希望有一个环境可以模仿这种类型

\bionic{Confucius said: Madam, I'm Adam.}

其解释与代码相同

{\bf Conf}ucius {\bf sa}id: {\bf Ma}dam, I'm {\bf Ad}am.

并在编译后的 PDF 文件中显示如下

会议尤西乌斯ID:妈的,我广告是。

或者有一个可选参数,为 0 至 1 之间的数字,用于显示单词的多少部分应加粗。

例如,代码

\bionic{internationalization}
\bionic[0.5]{internationalization}
\bionic[0.25]{internationalization}
\bionic[0.8]{internationalization}

分别编译成

国际最终化

国际最终化

跨国公司国有化

国际化


在 5.24 中编辑:如何使仿生环境适应数学环境和 SI 单位?例如:我希望以下代码能够工作,其中执行公式代码和 SI 单位代码,而不是按原样列出,也不加粗。

\bionic{
    Substances A and B are both volatile liquids with
    $p_A^* = \SI{300}{Torr}$, 
    $p_B^* = \SI{250}{Torr}$, and 
    $K_B   = \SI{200}{Torr}$ 
    (concentration expressed in mole fraction). 
}

替代祖先AAA关于沃拉液体uids无线p A * = 300 Torr、p B * = 250 Torr 和 KB = 200 Torr(关注牵引表达式埃塞德n分形化)。

答案1

我的解决方案只使用了 TeX 基元和通用宏\newcount。我们不需要其他任何东西。

\newcount\tmpnum
\def\bionic{\futurelet\next\bionicA}
\def\bionicA{\ifx\next[\afterfi\bionicB \else \afterfi{\bionicB[50]}\fi}
\def\bionicB[#1]#2{{\def\wratio{#1}\bionicC#2 {} }}
\def\bionicC #1 {\ifx^#1^\else
    \spacebetweenwords
    \tmpnum=0 \lcount #1{}% saves the number of letters to \tmpnum
    \multiply\tmpnum by\wratio \divide\tmpnum by100
    \testIm #1''\end % says \tmpnum=0 if #1 includes ' inside the word
    \bgroup \bf \wordpart #1%
    \expandafter\bionicC \fi
}
\def\spacebetweenwords{\def\spacebetweenwords{ }}
\def\lcount #1{\ifx^#1^\else \advance\tmpnum by1 \expandafter\lcount\fi}
\def\wordpart #1{%
   \ifnum\tmpnum=0 \egroup#1% 
   \else #1\advance\tmpnum by-1 \expandafter \wordpart \fi}
\def\testIm #1'#2'#3\end{\ifx^#2^\else \tmpnum=0 \fi}
\def\afterfi#1#2\fi{\fi#1}

%tests:
\bionic{Confucius said: Madam, I'm Adam.}

\bionic[50]{internationalization}
\bionic[25]{internationalization}
\bionic[80]{internationalization}

如果使用 OpTeX,则代码可以更紧凑,并且可选参数可以是 OP 中给出的十进制数字。

\optdef\bionic[.5]#1{{\bionicC #1 {} }}
\def\bionicC #1 {\ifx^#1^\else
    \spacebetweenwords
    \tmpnum=0 \foreach #1\do{\incr\tmpnum}%
    \def\_decdigits{0}\tmpnum=\expr{\the\opt*(\the\tmpnum-1)}%
    \testIm #1''\end % says \tmpnum=0 if #1 includes ' inside the word
    \bgroup \bf \wordpart #1%
    \ea\bionicC \fi
}
\def\spacebetweenwords{\def\spacebetweenwords{ }}
\def\wordpart #1{\ifnum\tmpnum=0 \egroup#1\else #1\decr\tmpnum \ea\wordpart\fi}
\def\testIm #1'#2'#3\end{\ifx^#2^\else \tmpnum=0 \fi}

%tests:
\bionic{Confucius said: Madam, I'm Adam.}

\bionic[.5]{internationalization}
\bionic[.25]{internationalization}
\bionic[.8]{internationalization}

\bye

答案2

这是一个使用expl3(LaTeX3,如果你喜欢)的解决方案

答案3

使用xstring包进行字符串操作和xfp计算子字符串长度的方法:

\documentclass{article}
\usepackage{xstring}
\usepackage{xfp}

\newcommand{\bionic}[2][0.5]{%
% split on first space
\StrCut{#2}{ }{\nextword}{\otherwords}%
% count length of first word
\exploregroups%
\StrLen{\nextword}[\currlen]%
% calculate nr. of characters for left part
\edef\halflen{\fpeval{ceil(\currlen*#1)}}%
% print left part in bold
\bfseries\StrLeft{\nextword}{\halflen}%
% print right part and add space back
\normalfont\StrGobbleLeft{\nextword}{\halflen}\space%
\noexploregroups%
% call function recursively if there are other words
\IfStrEq{\otherwords}{}{}{%
\bionic[#1]{\otherwords}%
}}

\begin{document}
\bionic{Confucius said: Madam, I'm Adam.}

\bionic[0.3]{Confucius said: Madam, I'm Adam.}

\bionic[0.3]{Confucius said: {Madam, I'm} Adam.}

\bionic{internationalization}

\bionic[0.5]{internationalization}

\bionic[0.25]{internationalization}

\bionic[0.8]{internationalization}
\end{document}

输出与Rmano 的回答。请注意,\exploregroups第三个示例需要这些命令{Madam, I'm},如果字符串中没有组,则可以通过删除这些命令进一步简化代码。

答案4

由于问题非常有趣,我尝试了一下(在 LaTeX2e 中),尽管它已经有了答案。我不是专家,我认为如果有重音符号或其他奇怪的东西,它会失败。

\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}

\makeatletter
% This command counts the number of letters in a word
\newcounter{ACtotal}
\def\AC@count#1#2\AC@delim{%
    \ifx\AC@undef#2\AC@undef%
        \ifcat.#1\else\stepcounter{ACtotal}\fi%
    \else%
        \ifcat.#1\else\stepcounter{ACtotal}\fi\AC@count#2\AC@delim%
    \fi%
}
\newcommand{\LtCount}[1]{%
    \AC@count#1\AC@delim%
}

% This command formats the bold in the word
\newcounter{ACcount}
\def\AC@format#1#2#3\AC@delim{%
    \ifx\AC@undef#3\AC@undef%
        \stepcounter{ACcount}%
        \ifnum\value{ACcount}<#1%
            \textbf{#2}%
        \else%
            #2%
        \fi%
    \else%
        \stepcounter{ACcount}%
        \ifnum\value{ACcount}<#1%
            \textbf{#2}%
        \else%
            #2%
        \fi%
        \AC@format{#1}#3\AC@delim%
    \fi%
}
\newcommand{\LtForm}[2][4]{%
    \AC@format{#1}#2\AC@delim%
    \setcounter{ACcount}{0}%
    \setcounter{ACtotal}{0}%
}

% This command sepparates a text by the spaces and applies the count of characters to each word and the formatting
\long\def\AC@sep#1#2 #3\AC@delim{%
    \LtCount{#2}
    \multiply\value{ACtotal} by #1
    \divide\value{ACtotal} by 100
    \advance\value{ACtotal} by 1
    \ifx\AC@undef#3\AC@undef%
        \LtForm[\value{ACtotal}]{#2}
    \else%
        \LtForm[\value{ACtotal}]{#2}
        \AC@sep{#1}#3\AC@delim%
    \fi%
}
\newcommand{\bionic}[2][50]{\AC@sep{#1}#2 \AC@delim}
\makeatother

\begin{document}

\bionic{Confucius said: Madam, I'm Adam.}

\bionic[30]{Confucius said: Madam, I'm Adam.}

\bionic[30]{Confucius said: {Madam,\ I'm} Adam.}

\bionic{internationalization}

\bionic[50]{internationalization}

\bionic[25]{internationalization}

\bionic[80]{internationalization}

\end{document}

结果如下 结果

相关内容