This works (doesn't need anything further, loading the package and that code works perfectly fine, ofc it's just copy-paste from glossaries-extra documentation after all):


My question now is: When I have let's say idx stored in a string-variable \str_new:... (if that's nonesense, and I should normally use a different type of variable than asume that one) how do I do the same like above? I don't want to write idx., \idx, and so on, what I want is something that does this automatically with the stored value in the string-variable.

Similar to something along those lines (xparse):


With this \Test{idx} would obviously do the same as my first code. But what I want is that all that stuff {\idx}{\idxpl}{\Idx}{\Idxpl} too is somehow replaced with '#1+however I do this' so that I can use \Test{...} multiple times for different glossaries etc. And ofc I don't want it with #1 and the \NewDocumentCommand (was just an example), rather with a string-variable where idx is stored (or whatever one would use here) from the expl3 package.

1 Answer 1


This should do:



\cs_new_protected:Npn \yumina_gls_from_str:n #1
  { \exp_args:Ne \__yumina_gls_from_str_aux:n { \tl_to_str:n {#1} } }
\cs_generate_variant:Nn \yumina_gls_from_str:n { V }
\cs_new_protected:Npn \__yumina_gls_from_str_aux:n #1
    % the group is necessary to not let the build macros to `\relax`
    \exp_args:Nncccc \use:n { \group_end: \glsxtrnewglslike[hyper=false]{#1.} }
      { #1 }
      { #1pl }
      { \char_uppercase:N #1 }
      { \char_uppercase:N #1pl }
\exp_args_generate:n { ncccc }

\str_new:N \l_yumina_tmp_str
\str_set:Nn \l_yumina_tmp_str {idx}
\yumina_gls_from_str:V \l_yumina_tmp_str

% or shorter:
\yumina_gls_from_str:n { etc }

Some document doing stuff.


  • \exp_args:N... expands the arguments of a function before that function sees them, the different expansion types used here are:

    • n do nothing, just a normal argument in braces

    • e fully expand things (used on \tl_to_str:n that will turn its argument into a string, which can't expand further)

    • c build a control sequence name from the contents of the argument (kind-of-fully expanding on the way, but our argument is a string, so just turn that into a control sequence name)

  • \char_uppercase:N will turn the first character in the string to its upper-case form

  • \cs_generate_variant:Nn will create a version of a macro that can expand its arguments, we use:

    • V get the contents of a variable (as an n-type argument, so in braces)
  • \exp_args_generate:n builds a new \exp_args:N... variant from the argument.

  • the stringification in \yumina_gls_from_str:n is used because it gets an n-type argument, probably some user provided code that's not necessarily a string. The fact that we use it on the contents of a string variable isn't known at this point, that's just added later on by \cs_generate_variant:Nn (and could in theory also get the contents of a token list variable, or an int, or a dimen, ...).

  • can you explain what this \cs_new_protected:Npn \yumina_gls_from_str:n #1 { \exp_args:Ne \__yumina_gls_from_str_aux:n { \tl_to_str:n {#1} } } part does? And first of all ofc thank you <3, it works exactly as I wanted it to. :D Feb 4, 2022 at 0:20
  • ... sure, it's bad practice for people to just post code and no explanation (I'd rather answers with explanation and no code)... but you can also just read up \cs_new_protected, \tl_to_str, exp_args documentation in interface3. @Yumina弓那Nirvalen (the gist is to construct the cs token from the cs name using c-type argument)
    – user202729
    Feb 4, 2022 at 0:29
  • 1
    @Yumina弓那Nirvalen ... after reading the documentation? Sure maybe that one can be hard to understand. (basically \exp_args:Ne \__yumina_gls_from_str_aux:n { \tl_to_str:n {#1} } is equivalent to \__yumina_gls_from_str_aux:e { \tl_to_str:n {#1} } after the appropriate \cs_generate_variant:Nn.
    – user202729
    Feb 4, 2022 at 0:47
  • 1
    @user202729 it was in the middle of the night and I was tired -> no explanations.
    – Skillmon
    Feb 4, 2022 at 13:56
  • 1
    @Yumina弓那Nirvalen you could use \NewDocumentCommand \yuminagls { m } { \yumina_gls_from_str:n {#1} } don't skip the stringification of user-provided arguments if you intend to work on strings. Otherwise the argument might further expand (if that's intended behaviour then, yes, you could leave out the \tl_to_str:n).
    – Skillmon
    Feb 4, 2022 at 14:12

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .