作为学习 LaTeX3 的练习,我想替换以下 7 个函数,它们来自xepersian.sty
它们在包中完成同样的工作
xepersian
,但只有单一功能。
208 \DeclareDocumentCommand \setlatintextfont { O{} m O{} }
209 {
210 \__xepersian_main_setlatintextfont:nn {#1,#3} {#2}
211 \ignorespaces
212 }
213 \cs_new:Nn \__xepersian_main_setlatintextfont:nn
214 {
215 \fontspec_set_family:Nnn \l__xepersian_latinfont_family_tl {Ligatures=TeX,#1} {#2}
216 \use:x { \exp_not:n { \DeclareRobustCommand \latinfont }
217 {
218 \exp_not:N \fontencoding { \g__fontspec_nfss_enc_tl }
219 \exp_not:N \fontfamily { \l__xepersian_latinfont_family_tl }
220 \exp_not:N \selectfont
221 }
222 }
223 \str_if_eq_x:nnT {\familydefault} {\rmdefault}
224 { \tl_set_eq:NN \encodingdefault \g__fontspec_nfss_enc_tl }
225 \__xepersian_setlatintextfont_hook:nn {#1} {#2}
226 \normalfont
227 }
228
229 \cs_set_eq:NN \__xepersian_setlatintextfont_hook:nn \use_none:nn
313 \DeclareDocumentCommand \setpersiansansfont { O{} m O{} }
314 {
315 \__xepersian_main_setpersiansansfont:nn {#1,#3} {#2}
316 \ignorespaces
317 }
318 \cs_new:Nn \__xepersian_main_setpersiansansfont:nn
319 {
320 \fontspec_set_family:Nnn \l__xepersian_persiansffamily_family_tl {Script=Persian,Ligatures=PersianTeX,#1} {#2}
321 \tl_set_eq:NN \persiansfdefault \l__xepersian_persiansffamily_family_tl
322 \use:x { \exp_not:n { \DeclareRobustCommand \persiansffamily }
323 {
324 \exp_not:N \fontencoding { \g__fontspec_nfss_enc_tl }
325 \exp_not:N \fontfamily { \l__xepersian_persiansffamily_family_tl }
326 \exp_not:N \selectfont
327 }
328 }
329 \str_if_eq_x:nnT {\familydefault} {\persiansfdefault}
330 { \tl_set_eq:NN \encodingdefault \g__fontspec_nfss_enc_tl }
331 \__xepersian_setpersiansansfont_hook:nn {#1} {#2}
332 \normalfont
333 }
334
335 \cs_set_eq:NN \__xepersian_setpersiansansfont_hook:nn \use_none:nn
336
337 \DeclareDocumentCommand \setpersianmonofont { O{} m O{} }
338 {
339 \__xepersian_main_setpersianmonofont:nn {#1,#3} {#2}
340 \ignorespaces
341 }
342 \cs_new:Nn \__xepersian_main_setpersianmonofont:nn
343 {
344 \fontspec_set_family:Nnn \l__xepersian_persianttfamily_family_tl {Script=Persian,Ligatures=PersianTeX,#1} {#2}
345 \tl_set_eq:NN \persianttdefault \l__xepersian_persianttfamily_family_tl
346 \use:x { \exp_not:n { \DeclareRobustCommand \persianttfamily }
347 {
348 \exp_not:N \fontencoding { \g__fontspec_nfss_enc_tl }
349 \exp_not:N \fontfamily { \l__xepersian_persianttfamily_family_tl }
350 \exp_not:N \selectfont
351 }
352 }
353 \str_if_eq_x:nnT {\familydefault} {\persianttdefault}
354 { \tl_set_eq:NN \encodingdefault \g__fontspec_nfss_enc_tl }
355 \__xepersian_setpersianmonofont_hook:nn {#1} {#2}
356 \normalfont
357 }
358
359 \cs_set_eq:NN \__xepersian_setpersianmonofont_hook:nn \use_none:nn
360
361 \DeclareDocumentCommand \setnavarfont { O{} m O{} }
362 {
363 \__xepersian_main_setnavarfont:nn {#1,#3} {#2}
364 \ignorespaces
365 }
366 \cs_new:Nn \__xepersian_main_setnavarfont:nn
367 {
368 \fontspec_set_family:Nnn \l__xepersian_navarfamily_family_tl {Script=Persian,Ligatures=PersianTeX,#1} {#2}
369 \tl_set_eq:NN \navardefault \l__xepersian_navarfamily_family_tl
370 \use:x { \exp_not:n { \DeclareRobustCommand \navarfamily }
371 {
372 \exp_not:N \fontencoding { \g__fontspec_nfss_enc_tl }
373 \exp_not:N \fontfamily { \l__xepersian_navarfamily_family_tl }
374 \exp_not:N \selectfont
375 }
376 }
377 \str_if_eq_x:nnT {\familydefault} {\navardefault}
378 { \tl_set_eq:NN \encodingdefault \g__fontspec_nfss_enc_tl }
379 \__xepersian_setnavarfont_hook:nn {#1} {#2}
380 \normalfont
381 }
382
383 \cs_set_eq:NN \__xepersian_setnavarfont_hook:nn \use_none:nn
384
385 \DeclareDocumentCommand \setpookfont { O{} m O{} }
386 {
387 \__xepersian_main_setpookfont:nn {#1,#3} {#2}
388 \ignorespaces
389 }
390 \cs_new:Nn \__xepersian_main_setpookfont:nn
391 {
392 \fontspec_set_family:Nnn \l__xepersian_pookfamily_family_tl {Script=Persian,Ligatures=PersianTeX,#1} {#2}
393 \tl_set_eq:NN \pookdefault \l__xepersian_pookfamily_family_tl
394 \use:x { \exp_not:n { \DeclareRobustCommand \pookfamily }
395 {
396 \exp_not:N \fontencoding { \g__fontspec_nfss_enc_tl }
397 \exp_not:N \fontfamily { \l__xepersian_pookfamily_family_tl }
398 \exp_not:N \selectfont
399 }
400 }
401 \str_if_eq_x:nnT {\familydefault} {\pookdefault}
402 { \tl_set_eq:NN \encodingdefault \g__fontspec_nfss_enc_tl }
403 \__xepersian_setpookfont_hook:nn {#1} {#2}
404 \normalfont
405 }
406
407 \cs_set_eq:NN \__xepersian_setpookfont_hook:nn \use_none:nn
408
409 \DeclareDocumentCommand \setsayehfont { O{} m O{} }
410 {
411 \__xepersian_main_setsayehfont:nn {#1,#3} {#2}
412 \ignorespaces
413 }
414 \cs_new:Nn \__xepersian_main_setsayehfont:nn
415 {
416 \fontspec_set_family:Nnn \l__xepersian_sayehfamily_family_tl {Script=Persian,Ligatures=PersianTeX,#1} {#2}
417 \tl_set_eq:NN \sayehdefault \l__xepersian_sayehfamily_family_tl
418 \use:x { \exp_not:n { \DeclareRobustCommand \sayehfamily }
419 {
420 \exp_not:N \fontencoding { \g__fontspec_nfss_enc_tl }
421 \exp_not:N \fontfamily { \l__xepersian_sayehfamily_family_tl }
422 \exp_not:N \selectfont
423 }
424 }
425 \str_if_eq_x:nnT {\familydefault} {\sayehdefault}
426 { \tl_set_eq:NN \encodingdefault \g__fontspec_nfss_enc_tl }
427 \__xepersian_setsayehfont_hook:nn {#1} {#2}
428 \normalfont
429 }
430
431 \cs_set_eq:NN \__xepersian_setsayehfont_hook:nn \use_none:nn
432
433 \DeclareDocumentCommand \setiranicfont { O{} m O{} }
434 {
435 \__xepersian_main_setiranicfont:nn {#1,#3} {#2}
436 \ignorespaces
437 }
438 \cs_new:Nn \__xepersian_main_setiranicfont:nn
439 {
440 \fontspec_set_family:Nnn \l__xepersian_iranicfamily_family_tl {Script=Persian,Ligatures=PersianTeX,#1} {#2}
441 \tl_set_eq:NN \iranicdefault \l__xepersian_iranicfamily_family_tl
442 \use:x { \exp_not:n { \DeclareRobustCommand \iranicfamily }
443 {
444 \exp_not:N \fontencoding { \g__fontspec_nfss_enc_tl }
445 \exp_not:N \fontfamily { \l__xepersian_iranicfamily_family_tl }
446 \exp_not:N \selectfont
447 }
448 }
449 \str_if_eq_x:nnT {\familydefault} {\iranicdefault}
450 { \tl_set_eq:NN \encodingdefault \g__fontspec_nfss_enc_tl }
451 \__xepersian_setiranicfont_hook:nn {#1} {#2}
452 \normalfont
453 }
454
455 \cs_set_eq:NN \__xepersian_setiranicfont_hook:nn \use_none:nn
以下是我已将以上所有内容替换的代码xepersian.sty
:
\cs_set:Nn \__xepersian_declare_set_fonts:nnnnn
{
\exp_args:Nc \DeclareDocumentCommand { set #1 font } { O{} m O{} }
{
\cs:w __xepersian_main_set #1 font :nn \cs_end: {##1,##3} {##2}
\ignorespaces
}
\exp_args:Nc \cs_new:Nn { __xepersian_main_set #1 font :nn }
{
\exp_args:Ncnx \fontspec_set_family:Nnn { l__xepersian_ #2 #3 _family_tl } {#5,##1} {##2}
\exp_args:Ncc \tl_set_eq:NN { #2 default } { l__xepersian_ #2 #3 _family_tl }
\use:x { \exp_not:n { \exp_args:Nc \DeclareRobustCommand { #2 #3 } }
{
\exp_not:N \fontencoding { \g__fontspec_nfss_enc_tl }
\exp_not:N \fontfamily { \cs:w l__xepersian_ #2 #3 _family_tl \cs_end: }
\exp_not:N \selectfont
}
}
\str_if_eq_x:nnT {\familydefault} { \cs:w #4 default \cs_end: }
{ \tl_set_eq:NN \encodingdefault \g__fontspec_nfss_enc_tl }
\cs:w __xepersian_set #1 font_hook :nn \cs_end: {##1} {##2}
\normalfont
}
\exp_args:Nc \cs_set_eq:NN { __xepersian_set #1 font_hook :nn } \use_none:nn
}
\__xepersian_declare_set_fonts:nnnnn { latintext } { latin } { font } { rm } { Ligatures=TeX }
\seq_new:N \l__my_xepersian_styles_seq
\seq_set_split:Nnn \l__my_xepersian_styles_seq { , }
{
% { { latintext } { latin } { font } { rm } { Ligatures=TeX } } ,
{ { persiansans } { persiansf } { family } { persiansf } { Script=Persian,Ligatures=PersianTeX } } ,
{ { persianmono } { persiantt } { family } { persiantt } { Script=Persian,Ligatures=PersianTeX } } ,
{ { iranic } { iranic } { family } { iranic } { Script=Persian,Ligatures=PersianTeX } } ,
{ { navar } { navar } { family } { navar } { Script=Persian,Ligatures=PersianTeX } } ,
{ { pook } { pook } { family } { pook } { Script=Persian,Ligatures=PersianTeX } } ,
{ { sayeh } { sayeh } { family } { sayeh } { Script=Persian,Ligatures=PersianTeX } }
}
\seq_map_inline:Nn \l__my_xepersian_styles_seq
{
\__xepersian_declare_set_fonts:nnnnn #1
}
由于我是 LaTeX3 的初学者,我想知道是否可以提高代码的质量和效率,或者简化它。我的 MWE 是:
\documentclass{article}
\usepackage{xepersian}
\settextfont{Amiri}
\setlatintextfont[Scale=1.44]{Times New Roman}
\setpersianmonofont[Scale=1.44]{Amiri}
\setpersiansansfont[Scale=1.44]{Amiri}
\setiranicfont[Scale=1.44]{Amiri}
\setnavarfont[Scale=1.44]{Amiri}
\setpookfont[Scale=1.44]{Amiri}
\setsayehfont[Scale=1.44]{Amiri}
\pagestyle{empty}
\begin{document}
\lr{This is a test for numbers: 0 1 2 3 4 5 6 7 8 9.} \\
این یک آزمایش اعداد است: ۰ ۱ ۲ ۳ ۴ ۵ ۶ ۷ ۸ ۹. \\
\persianttfamily \textpersiantt{این یک آزمایش اعداد است: ۰ ۱ ۲ ۳ ۴ ۵ ۶ ۷ ۸ ۹.} \\
\persiansffamily \textpersiansf{این یک آزمایش اعداد است: ۰ ۱ ۲ ۳ ۴ ۵ ۶ ۷ ۸ ۹.} \\
\iranicfamily \textiranic{این یک آزمایش اعداد است: ۰ ۱ ۲ ۳ ۴ ۵ ۶ ۷ ۸ ۹.} \\
\navarfamily \textnavar{این یک آزمایش اعداد است: ۰ ۱ ۲ ۳ ۴ ۵ ۶ ۷ ۸ ۹.} \\
\pookfamily \textpook{این یک آزمایش اعداد است: ۰ ۱ ۲ ۳ ۴ ۵ ۶ ۷ ۸ ۹.} \\
\sayehfamily \textsayeh{این یک آزمایش اعداد است: ۰ ۱ ۲ ۳ ۴ ۵ ۶ ۷ ۸ ۹.}
\end{document}
我修改过的文件xepersian.sty
可以从以下网址下载粘贴箱。
编辑于 2018-12-28:应用建议的更正
\__xepersian_declare_set_fonts:nnnnn
特别感谢 TeXnician 和 Joseph 的帮助,我应用了他们建议的所有更正的函数新版本如下:
\cs_generate_variant:Nn \fontspec_set_family:Nnn { c }
\prg_generate_conditional_variant:Nnn \str_if_eq:nn { Vv } { T, F, TF }
\cs_set:Nn \__xepersian_declare_set_fonts:nnnnn
{
\exp_args:Nc \DeclareDocumentCommand { set #1 font } { O{} m O{} }
{
\use:c { __xepersian_main_set #1 font:nn } {##1,##3} {##2}
\ignorespaces
}
\exp_args:Nc \cs_new:Nn { __xepersian_main_set #1 font :nn }
{
\fontspec_set_family:cnn { l__xepersian_ #2 #3 _family_tl } {#5,##1} {##2}
\tl_set_eq:cc { #2 default } { l__xepersian_ #2 #3 _family_tl }
\use:x { \exp_not:n { \exp_args:Nc \DeclareRobustCommand { #2 #3 } }
{
\exp_not:N \fontencoding { \g__fontspec_nfss_enc_tl }
\exp_not:N \fontfamily { \use:c { l__xepersian_ #2 #3 _family_tl } }
\exp_not:N \selectfont
}
}
\str_if_eq:VvT {\familydefault} { #4 default }
{ \tl_set_eq:NN \encodingdefault \g__fontspec_nfss_enc_tl }
\use:c { __xepersian_set #1 font_hook:nn } {##1} {##2}
\normalfont
}
\cs_set_eq:cN { __xepersian_set #1 font_hook :nn } \use_none:nn
}
修改后xepersian.sty
重命名为hmxepersian.sty
。文件名中的前缀hm
表示现在可以加载HM
名称中带有的字体。
另外,我的新工作示例如下:
% Tested with: xepersian-22.5, Revision 49428 on TeXLive
\documentclass{article}
\usepackage{hmxepersian}
\settextfont[Scale=1.2]{HM XKayhan}
\setlatintextfont[Scale=1.2]{Psychedelia HM}
\setpersianmonofont[Scale=1.2]{DejaVu Sans Mono}
\setpersiansansfont[Scale=1.2]{DejaVu Sans}
\setiranicfont[Scale=1.2]{HM XKayhanOb Oblique}
\setnavarfont[Scale=1.2]{HM XKayhan Navaar}
\setpookfont[Scale=1.2]{HM XKayhan Pook}
\setsayehfont[Scale=1.2]{HM XKayhan Sayeh}
\pagestyle{empty}
\begin{document}
\lr{This is a test for numbers: 0 1 2 3 4 5 6 7 8 9.} \\
این یک آزمایش اعداد است: ۰ ۱ ۲ ۳ ۴ ۵ ۶ ۷ ۸ ۹. \\
\persianttfamily \textpersiantt{این یک آزمایش اعداد است: ۰ ۱ ۲ ۳ ۴ ۵ ۶ ۷ ۸ ۹.} \\
\persiansffamily \textpersiansf{این یک آزمایش اعداد است: ۰ ۱ ۲ ۳ ۴ ۵ ۶ ۷ ۸ ۹.} \\
\iranicfamily \textiranic{این یک آزمایش اعداد است: ۰ ۱ ۲ ۳ ۴ ۵ ۶ ۷ ۸ ۹.} \\
\navarfamily \textnavar{این یک آزمایش اعداد است: ۰ ۱ ۲ ۳ ۴ ۵ ۶ ۷ ۸ ۹.} \\
\pookfamily \textpook{این یک آزمایش اعداد است: ۰ ۱ ۲ ۳ ۴ ۵ ۶ ۷ ۸ ۹.} \\
\sayehfamily \textsayeh{این یک آزمایش اعداد است: ۰ ۱ ۲ ۳ ۴ ۵ ۶ ۷ ۸ ۹.}
\end{document}
答案1
由于您的示例不可编译,因此不易测试,我仅提供一些说明:
您正在使用将一个类型参数
\exp_args
转换为类型,例如N
c
\exp_args:Ncnx \fontspec_set_family:Nnn { l__xepersian_ #2 #3 _family_tl } {#5,##1} {##2}
相反,您应该生成一个
\fontspec_set_family
可以为您完成此扩展技巧的变体。\cs_generate_variant:Nn \fontspec_set_family:Nnn { c }
这可以用作
\fontspec_set_family:cnn { l__xepersian_ #2 #3 _family_tl } {#5,##1} {##2}
。关于变体的另一件事:有预定义的变体。因此,当您使用时,
\exp_args:Ncc \tl_set_eq:NN
您实际上是在请求预定义的变体\tl_set_eq:cc
,您可以使用\tl_set_eq:cc { #2 default } { l__xepersian_ #2 #3 _family_tl }
这也适用于
\cs_set_eq
:\cs_set_eq:cN { __xepersian_set #1 font_hook :nn } \use_none:nn
您正在使用
cs:w … \cs_end:
作为\csname\endcsname
构造,尽管您可以\use:c { __xepersian_main_set #1 font:nn }
在那时使用。\str_if_eq_x
已弃用。似乎您想要比较两个命令序列作为参数所持有的值(每个参数一次展开,然后比较两个参数)。为此,您可以\prg_generate_conditional_variant
使用\str_if_eq:VvT
或,\tl_if_eq:VvT
这将更符合惯用方式,例如\prg_generate_conditional_variant:Nnn \str_if_eq:nn { Vv } { T, F, TF } \str_if_eq:VvT \familydefault { #4 default } { … }
或者你可以
\str_if_eq:ee
改为\str_if_eq_x:nnT {\familydefault} { \cs:w #4 default \cs_end: } { \tl_set_eq:NN \encodingdefault \g__fontspec_nfss_enc_tl } \cs:w __xepersian_set #1 font_hook :nn \cs_end: {##1} {##2}
进入
\str_if_eq:eeT {\familydefault} { \use:c { #4 default } } { \tl_set_eq:NN \encodingdefault \g__fontspec_nfss_enc_tl } \use:c { __xepersian_set #1 font_hook:nn } {##1} {##2}
请注意,我这里没有考虑速度。这些只是从第一眼看到你的代码(整洁性和可读性)得出的一些要点。