3

I am trying to have my document read its own filename (which is known to be words and numbers separated by hyphens) and parse it. For everything after a certain hyphen, I want to replace the hyphens by spaces, and then capitalize each "important" word (where "important" is defined as a word not appearing in the mfirstuc-english list). My code is doing everything but the last step correctly—all of the words are capitalized regardless of their being important or not. Several hours of searching suggests that the difference must be in how the ecapitalisewords command expands macros, but the fix is beyond my grasp at this point. Any help is greatly appreciated.

Here is my best attempt at a MWE where the filename I used was 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}
5

The problem is not expansion but catcodes: all chars in \jobname have catcode 12. But mfirstuc-english set up the "capitalization exceptions" only for words with normal letters (catcode 11). You can reproduce the problem (and solve it) by using \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}

enter image description here

  • Many thanks, Ulrike. Forgive me if I'm being dense, but does your intended solution mean that I would, essentially, produce a copy of the mfirstuc-english style file where all of the unimportant words are detokenized? – adamglesser Sep 7 '15 at 15:20
  • Yes, but as there are only 14 words in the style it is imho managable. ;-). The solution from egreg (who does it the other way round and rescans \jobname with catcode 11) is naturally better, my answer was more meant to explain the source of the problem. – Ulrike Fischer Sep 7 '15 at 15:26
  • The advantage of your solution is that I fully understand it and that a little regex action would probably handle the copy pretty quickly. @egreg's solution is very fast to implement, but is going to take me some time to understand. – adamglesser Sep 7 '15 at 15:40
  • Yes all the underscores in expl3 code and the naming of the macros need a bit time to get used too. But I highly recommend to try it out. expl3 is very good. Your code will be much cleaner and better to understand -- and you will need much lesser \expandafter. – Ulrike Fischer Sep 7 '15 at 15:44
  • A quick follow up. I implemented your solution, @Ulrike Fischer, and it works exactly as expected. My long-term goal (read, ``better give me a few weeks'') is to learn enough expl3 so as to understand and implement @egreg's solution as it will be more versatile going forward and won't rely on me keeping track of two different lists. – adamglesser Sep 7 '15 at 18:33
3

The main fact is that \jobname expands to letters of category code 12, as remarked by Ulrike Fischer.

A solution in 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}

enter image description here

For extracting the parts of a complex file name such as

fall-15-math-150a-quiz-02-approximating-the-derivative.tex

you can use some more advanced expl3 facilities.

\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}

enter image description here

  • Thanks, egreg. I'm an absolute novice with the expl3 stuff, so this will take me a bit to process. One quick question, though. As I mentioned in the MWE, I want to be able to access different parts of the filename for different reasons. So, in the MWE, I would want to have access to "Test" and the first "the", or whatever else would be in the first two (or seven as is the case in my F(ull)WE) positions. In essence, how do I replicate the work of \filename@parse in my MWE? – adamglesser Sep 7 '15 at 15:55
  • 1
    @adamglesser I added the macro: \thisfilenamepart{<number>} accesses to the corresponding file name part. – egreg Sep 7 '15 at 16:12
  • Cool deal. One difference between your solution and mine is that mine will store every word after some set number (two in the MWE) into one part. The reason I need this is not clear in the MWE, so let me quickly elaborate here. My file names will all look something like fall-15-math-150a-quiz-02-approximating-the-derivative. The first six parts are all used by the template to create the header, and then everything after ``02'' is the title (which can have varying length). In the MWE, this would mean that there should be three filenameparts, the last containing everything after "the". – adamglesser Sep 7 '15 at 16:35
  • @adamglesser It's difficult to answer without knowing the real specifications. Now you should find the macros to suit you. – egreg Sep 7 '15 at 17:22
  • 1
    As of September 2015, \c_job_name_tl should become \c_sys_jobname_str – egreg Sep 30 '15 at 9:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.