1

I want to create a LaTeX class with optional parameters using LaTeX3. But I'm having problems converting the token list holding the parameter value to a string. I would like to know how to do this correctly even if my entire strategy for processing class options is wrong. I am finding learning expl3 very very difficult.

No matter how I try to convert the token list to a string it just seems to return the LaTeX source code. I feel I have tried every permutation of \tl_to_str:n and :V with every permutation of \str_set:Nn and :NV but I probably haven't otherwise I wouldn't need to ask this question.

For the class I am creating, one optional parameter will allow the end user to choose the underlying document class. The default will be article if no class parameter is supplied:

  • \documentclass{apple} would use the default class article whereas
  • \documentclass[class=book]{apple} would use the specified class book

I thought it good strategy to

  1. define a string constant for the default \str_const:Nn \c__apple_base_class_str { article }
  2. use the string constant to seed the parameter value
  3. use a string to hold the final value once the class options have been processed

Edit: The reason for using a string is that, if I understand correctly, token lists are for stuff that will be typeset and strings (such as LaTeX has them) are for stuff that won't be typeset. Source Token list vs string in LaTeX3

MWE of the broken bit

\str_new:N \l__apple_base_class_str
\str_set:Nn \l__apple_base_class_str { \tl_to_str:n \l__apple_class_tl }

Full MWE

This code is seeded from the accepted answer of how to properly write initialization part with expl3. I assume this is the correct way to specify and process class options.

\NeedsTeXFormat{LaTeX2e}
\RequirePackage{expl3,xparse,l3keys2e}
\ProvidesExplClass{apple}
{2022/06/27} {0.0} {My first class}

\str_const:Nn \c__apple_base_class_str { article }

\keys_define:nn { apple }
  {
  , class .tl_set:N         = \l__apple_class_tl
  , class .initial:n        = { \c__apple_base_class_str }
  , class .value_required:n = true
}

\str_new:N \l__apple_base_class_str
\str_set:Nn \l__apple_base_class_str { \tl_to_str:n \l__apple_class_tl }

\iow_term:x { tl~of~class:~\tl_use:N \l__apple_class_tl }
\iow_term:x { str~of~class:~\str_use:N \l__apple_base_class_str }

\ProcessKeysOptions { apple }
\LoadClass { \str_use:N \l__apple_base_class_str }

Output

Document Class: apple 2022/06/27 v0.0 My first class
tl of class: article
str of class: \tl_to_str:n \l__apple_class_tl
! LaTeX Error: File `\tl_to_str:n \l__apple_class_tl .cls' not found.

Compiling with LuaHBTeX, Version 1.15.0 (MiKTeX 22.3) if that matters.

2 Answers 2

2

You are overdoing. Store the value in a tl-var and use it.

The following requires a current latex (it has now a built-in key processor so it is not longer needed to load l3keys2e).

\begin{filecontents}{apple.cls}
\NeedsTeXFormat{LaTeX2e}
\ProvidesExplClass{apple}
{2022/06/27} {0.0} {My first class}

\keys_define:nn { apple }
  {
  , class .tl_set:N         = \l__apple_class_tl
  , class .initial:n        = { article }
  , class .value_required:n = true
  }


\ProcessKeyOptions
\iow_term:x { tl~of~class:~\tl_use:N \l__apple_class_tl }

\LoadClass { \l__apple_class_tl }
\end{filecontents}
\documentclass[class=book]{apple}


\begin{document}
aaa
\end{document} 
5
  • Thank you. I thought token lists were intended for stuff to be typeset and so I thought I needed a string as I'm not typesetting the value of the class's name. I feel I'm also the victim of out-dated information persisting on the internet.
    – Doc Octal
    Jun 26 at 22:16
  • well as the answer of @egreg shows you can also use strings, but imho for this type of value it doesn't really matter. Jun 26 at 22:21
  • @DocOctal if you don't have any option procssing at all and your class just did \LoadClass{article} then article is a tl (catcode 11 characters) you don't have to use \LoadClass{\detokenize{article}} to make catcode 12 characters, which is what conversion to str is doing Jun 26 at 22:24
  • @DavidCarlisle There will be other options specific to my class. I needed to start simple.
    – Doc Octal
    Jun 26 at 22:28
  • @DocOctal sure, I wasn't commenting on the options, just your comment about using strings for file names, and showing that file names, class names etc almost always get used as token lists without being converted explicitly to str Jun 26 at 22:32
2

If you want to use strings, good, but don't mix them with tl variables. You're doing the conversion before \ProcessKeyOptions, so the value of \l__apple_class_tl is still the initial one.

\NeedsTeXFormat{LaTeX2e}
\RequirePackage{expl3,xparse,l3keys2e}
\ProvidesExplClass{apple} {2022/06/27} {0.0} {My first class}

\str_const:Nn \c__apple_base_class_str { article }

\keys_define:nn { apple }
  {
    class .str_set:N        = \l__apple_class_str ,
    class .initial:V        = \c__apple_base_class_str ,
    class .value_required:n = true ,
  }

\iow_term:x { tl~of~class:~\str_use:N \l__apple_class_str }

\ProcessKeysOptions { apple }
\LoadClass { \str_use:N \l__apple_class_str }
1
  • Thank you this also works and is the type of solution I thought I was seeking. I couldn't see the difference at first. I hadn't seen a .str_set in any examples so I didn't know about it.
    – Doc Octal
    Jun 26 at 22:30

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.