我正在尝试让我的文档读取自己的文件名(已知是连字符分隔的单词和数字)并对其进行解析。对于某个连字符后的所有内容,我想用空格替换连字符,然后将每个“重要”单词大写(“重要”定义为未出现在列表中的单词mfirstuc-english
)。我的代码除了最后一步外都正确执行 - 所有单词都大写,无论它们是否重要。几个小时的搜索表明差异一定在于命令如何ecapitalisewords
扩展宏,但目前我无法解决此问题。任何帮助都将不胜感激。
这是我在 MWE 中的最佳尝试,其中我使用的文件名是test-the-document-that-reads-the-filename.tex
。
\documentclass{article}
\usepackage{mfirstuc-english}
\makeatletter
\newcommand{\hyphentospace}[1]{\@hyphentospace[#1-]}
\def\@hyphentospace[#1-#2]{#1%
\if\relax\detokenize{#2}\relax
\else%
\space \@hyphentospace[#2]%
\fi%
}
\makeatother
\makeatletter
\newcommand{\filenameparse}[1]{\expandafter\filename@parse@#1\@nil}
\def\filename@parse@#1-#2-#3\@nil{%
\gdef\firstpart{#1}% first part
\gdef\secondpart{#2}% second part
\gdef\thirdpart{#3}% third part
}
\makeatother
\newcommand{\spaced}[1]{\expandafter\hyphentospace\expandafter{#1}} %Replace hyphens with spaces in the third part
\newcommand{\cappedspaced}[1]{\expandafter\ecapitalisewords{\spaced{#1}}} %Capitalise the first letter in the important words in the spaced third part
\newcommand{\inputtext}{document-that-reads-the-filename} %Manually supply the third part of the file name
\begin{document}
\filenameparse{\jobname}
\cappedspaced{\thirdpart} %Returns ``Document That Reads The Filename''
\cappedspaced{\inputtext} %Returns ``Document That Reads the Filename''
\end{document}
答案1
问题不是扩展而是 catcodes: 中的所有字符\jobname
都有 catcode 12。但mfirstuc-english
仅为具有正常字母的单词(catcode 11)设置“大写例外”。您可以使用以下方法重现问题(并解决它)\detokenize
:
\documentclass{article}
\usepackage{mfirstuc-english}
\begin{document}
\capitalisewords{There is a bird in a tree}
\ecapitalisewords{\detokenize{There is a bird in a tree}}
\expandafter\MFUnocap\expandafter{\detokenize{a}}
\expandafter\MFUnocap\expandafter{\detokenize{in}}
\expandafter\MFUnocap\expandafter{\detokenize{is}}
\MFUnocap{is}
\capitalisewords{There is a bird in a tree}
\ecapitalisewords{\detokenize{There is a bird in a tree}}
\end{document}
答案2
主要事实是,它\jobname
扩展为类别代码 12 的字母,正如 Ulrike Fischer 所说。
解决方案expl3
:
\documentclass{article}
\usepackage{mfirstuc-english}
\usepackage{xparse}
\ExplSyntaxOn
\tl_new:N \g_adam_spaced_job_name_tl
\seq_new:N \g_adam_job_name_seq
% rescan \jobname
\tl_gset_rescan:Nnx \g_adam_spaced_job_name_tl { } { \c_job_name_tl }
\seq_gset_split:NnV \g_adam_job_name_seq { - } \g_adam_spaced_job_name_tl
% replace hyphens by spaces
\tl_greplace_all:Nnn \g_adam_spaced_job_name_tl { - } { ~ }
\NewDocumentCommand{\thisfilename}{}
{
% just print the (spaced) file name
\tl_use:N \g_adam_spaced_job_name_tl
}
\NewDocumentCommand{\casedthisfilename}{}
{
% apply \ecapitalisewords to the variable
\adam_ecapitalise_words:V \g_adam_spaced_job_name_tl
}
\NewDocumentCommand{\thisfilenamepart}{m}
{
\seq_item:Nn \g_adam_job_name_seq { #1 }
}
% syntactic sugar
\cs_set_eq:NN \adam_ecapitalise_words:n \ecapitalisewords
\cs_generate_variant:Nn \adam_ecapitalise_words:n { V }
\ExplSyntaxOff
\begin{document}
\thisfilename
\casedthisfilename
\thisfilenamepart{1} \thisfilenamepart{2} \thisfilenamepart{3}
\thisfilenamepart{4} \thisfilenamepart{5} \thisfilenamepart{6}
\thisfilenamepart{7}
\end{document}
用于提取复杂文件名的部分,例如
fall-15-math-150a-quiz-02-approximating-the-derivative.tex
您可以使用一些更先进的expl3
设施。
\documentclass{article}
\usepackage{mfirstuc-english}
\usepackage{xparse}
\ExplSyntaxOn
% allocate some variables
\tl_new:N \g_adam_spaced_job_name_tl
\tl_new:N \g_adam_file_classifier_tl
\tl_new:N \g_adam_file_title_tl
\seq_new:N \g_adam_job_name_seq
% rescan \jobname
\tl_gset_rescan:Nnx \g_adam_spaced_job_name_tl { } { \c_job_name_tl }
% split the file name into parts at hyphens
\seq_gset_split:NnV \g_adam_job_name_seq { - } \g_adam_spaced_job_name_tl
% make the classifier with the first six parts
\tl_gset:Nx \g_adam_file_classifier_tl { \seq_item:Nn \g_adam_job_name_seq { 1 } }
\int_step_inline:nnnn { 2 } { 1 } { 6 }
{
\tl_gput_right:Nx \g_adam_file_classifier_tl { - \seq_item:Nn \g_adam_job_name_seq { #1 } }
}
% make the title with the remaining parts
\tl_gset:Nx \g_adam_file_title_tl { \seq_item:Nn \g_adam_job_name_seq { 7 } }
\int_step_inline:nnnn { 8 } { 1 } { \seq_count:N \g_adam_job_name_seq }
{
\tl_gput_right:Nx \g_adam_file_title_tl { ~ \seq_item:Nn \g_adam_job_name_seq { #1 } }
}
% user level commands
\NewDocumentCommand{\thisfileclassifier}{}
{
% just print the file classifier
\tl_use:N \g_adam_file_classifier_tl
}
\NewDocumentCommand{\thisfiletitle}{}
{
% just print the (spaced) file name
\tl_use:N \g_adam_file_title_tl
}
\NewDocumentCommand{\casedthisfiletitle}{}
{
% apply \ecapitalisewords to the variable
\adam_ecapitalise_words:V \g_adam_file_title_tl
}
\NewDocumentCommand{\thisfilenamepart}{m}
{
% access to generic file name parts
\seq_item:Nn \g_adam_job_name_seq { #1 }
}
% syntactic sugar
\cs_set_eq:NN \adam_ecapitalise_words:n \ecapitalisewords
\cs_generate_variant:Nn \adam_ecapitalise_words:n { V }
\ExplSyntaxOff
\begin{document}
\thisfileclassifier
\thisfiletitle
\casedthisfiletitle
\thisfilenamepart{1}
\end{document}