我喜欢在某些文档的版权页中包含字体信息,并且我希望它是自动的。我首先使用\showfont
这个论坛上各种问题中使用的命令,即:
\newcommand{\showfont}{
encoding: \f@encoding,
family: \f@family,
series: \f@series,
shape: \f@shape,
size: \f@size
}
但是 提供的系列与\f@family
我设置时指定的系列不对应,例如,它给出的不是“Source Sans Pro”,而是“SoureSansPro(1)”。我尝试通过学习一点 来解决这个问题expl3
,但我陷入了困境。下面的 MWE 定义了一个宏\decamelize
,它抓取参数的首字母并在每个 lowerUPPER 字母对之间插入一个空格。它在普通文本上运行良好,但在 上使用时失败\f@family
。
我对 还很陌生expl3
。我不明白的很多事情之一是,我需要使用\expandafter
MWE 才能运行完成,但即便如此,它也不能像在普通文本输入上那样工作。
\documentclass{article}
\usepackage{fontspec}
\usepackage{xparse}
\setmainfont{Source Sans Pro}
\ExplSyntaxOn
%% a function to change FooBarBaz10 into 'Foo Bar Baz'
\NewDocumentCommand{\decamelize}{m}
{
\gtk_camel:n { #1 }
}
\cs_new:Nn \gtk_camel:n {
% clear result queue
\seq_clear:N \l_tmpa_seq
% get the opening letters of the text
\regex_extract_all:nnN { ^ [a-zA-Z]+ } { #1 } \l_tmpa_seq
\seq_get_left:NN \l_tmpa_seq \l_my_tl
% Insert a space into every lowercaseUPPERCASE character pair
\regex_replace_all:nnN { ([a-z])([A-Z]) } { \1 \~ \2 } \l_my_tl
\l_my_tl
}
\ExplSyntaxOff
%Now adjust \showfont to include the multi-word families
\makeatletter
\newcommand{\showfont}{
encoding: \f@encoding,
family: \expandafter\decamelize\f@family,
series: \f@series,
shape: \f@shape,
size: \f@size
}
\makeatother
\begin{document}
% This works, gives 'Source Sans Pro'
%\decamelize{SourceSansPro(10)}
%this does not work when \f@family is provided
\showfont Aa
\end{document}
答案1
宏\f@encoding
等\f@family
可以被视为标记列表变量。
然后你需要将“去驼峰化”过程应用于标记列表变量的内容。因此,想法是
\cs_new_protected:Nn \gtk_decamelize:n { ... }
\cs_generate_variant:Nn \gtk_decamelize:n { V }
这样就可以调用
\gtk_decamelize:V \f@family
但这需要\makeatletter
,因此还有另一种方便的变体可用:
\cs_generate_variant:Nn \gtk_decamelize:n { v }
你可以打电话
\gtk_decamelize:v { f@family }
请注意,您的“去驼峰化”函数应该受到保护,因为\regex_...
命令不可扩展。无需拆分标记列表:您可以轻松删除任何(<digits>)
尾随部分。
\documentclass{article}
\usepackage{fontspec}
%\usepackage{xparse}% no longer needed
\setmainfont{Source Sans Pro}
\ExplSyntaxOn
\NewDocumentCommand{\showfont}{}
{
encoding:~\tl_use:c { f@encoding },~
family:~\gtk_decamelize:v { f@family },~
series:~\tl_use:c { f@series },~
shape:~\tl_use:c { f@shape },~
size:~\tl_use:c { f@size }
}
\cs_new_protected:Nn \gtk_decamelize:n
{
\tl_set:Nn \l_tmpa_tl { #1 }
% Remove (<digits>) at the end
\regex_replace_once:nnN { \([0-9]*\) \Z } { } \l_tmpa_tl
% Insert a space into every lowercaseUPPERCASE character pair
\regex_replace_all:nnN { ([a-z])([A-Z]) } { \1 \~ \2 } \l_tmpa_tl
\tl_use:N \l_tmpa_tl
}
\cs_generate_variant:Nn \gtk_decamelize:n { v }
\ExplSyntaxOff
\begin{document}
\showfont
\end{document}
但这并非万无一失:例如,DejaVu 字体在“Vu”之前没有空格。
答案2
用这个:
family: \expandafter\decamelize\expandafter{\f@family},
首先,\expandafter
使用结果处理两个 s \decamelize{SourceSansPro(0)}
,然后\decamelize
处理您的宏。
答案3
如果你将整个家族令牌传递给你的驼峰函数
family: \decamelize\f@family,
您可以在正则表达式之前扩展参数,以便
\regex_extract_all:neN { ^ [a-zA-Z]+ } { #1 } \l_tmpa_seq
代替\regex_extract_all:nnN
该变体未预先声明,因此您还需要
\cs_generate_variant:Nn \regex_extract_all:nnN {ne}