仿生阅读试图找到每一个单词,并将第一部分加粗。
我希望有一个环境可以模仿这种类型
\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).
}
替代祖先AA乙A关于博日沃拉瓦液体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}