1

I have some code that convert some macros to a string to write, but unfortunately when a character # is given as input it is turned into ##. I tried to play with catcodes, but seems like it is not effective:

The following code shows:

Hey \notexistingbutnoproblem ##

instead of

Hey \notexistingbutnoproblem #

MWE:

\documentclass[]{article}

\begin{document}

\ExplSyntaxOn

\NewDocumentCommand{\defineString}{m}{ \char_set_catcode_letter:N # \str_set:Nn \l_test_str {#1} % My failed other try: % \tl_set_rescan:Nnn \l_test_str {\char_set_catcode_letter:N #}{#1} % \tl_to_str:n \l_test_str w}

\NewDocumentCommand{\showString}{}{ \show\l_test_str }

\ExplSyntaxOff

\defineString{Hey \notexistingbutnoproblem #} \showString

\end{document}

tobiasBora
  • 8,684
  • 2
    Every solution in https://tex.stackexchange.com/questions/520388/prevent-hash-doubling-with-message also works here. See if you can adapt them. – user202729 Sep 08 '23 at 00:17
  • 3
    this is unrelated to latex3, it is a feature of the primitive \show command you are using – David Carlisle Sep 08 '23 at 04:50
  • Thanks! @DavidCarlisle Well, apparently any command I run on this string see two hashes. \show, but also when I write it to a file, or if I print it verbatim in the file… But egreg’s answer solved my issue. – tobiasBora Sep 08 '23 at 09:39

2 Answers2

2

Your \char_set_catcode_letter:N does nothing useful; actually it does harm, because from the first usage of your \defineString command, # will become category code 11 (respecting grouping).

You want to replace the doubled hashes with single ones.

\documentclass{article}

\begin{document}

\ExplSyntaxOn

\cs_generate_variant:Nn \str_replace_all:Nnn { Nnx }

\NewDocumentCommand{\defineString}{m} { \str_set:Nn \l_test_str {#1} \str_replace_all:Nnx \l_test_str { ## } { \c_hash_str } }

\NewDocumentCommand{\showString}{}{ \str_show:N \l_test_str }

\ExplSyntaxOff

\defineString{Hey \notexistingbutnoproblem #} \showString

\end{document}

You get

> \l_test_str=Hey \notexistingbutnoproblem #.
egreg
  • 1,121,712
  • Thanks a lot! I was thinking of doing that but I thought it would be an ugly fix (so I wrote some other tricks in my other answer, but I trust you more on the fact that your solution is cleaner ^^). – tobiasBora Sep 08 '23 at 09:37
  • Btw, here is a followup question https://tex.stackexchange.com/questions/695497/pgf-key-style-with-no-argument-or-how-to-avoid-escaping-hashes – tobiasBora Sep 08 '23 at 12:53
0

Thanks to the comment of @user202729, I came up with this more "robust" (I hope?) definition:

\cs_set:Nn \str_set_hash_robust:Nn {
  \tl_set:Nn \l_test_str { #2 }
  \regex_replace_all:nnN { \cP\# } { \cO\# } \l_test_str
  \tl_to_str:N {#1}
}
\documentclass[]{article}
\usepackage{tikz}
\begin{document}

\ExplSyntaxOn

%% See also https://tex.stackexchange.com/questions/695432/latex3-latex-doubles-the-number-of-hashes-when-storing-them-in-string/695460#695460 \cs_set:Nn \str_set_hash_robust:Nn { \tl_set:Nn \l_test_str { #2 } \regex_replace_all:nnN { \cP# } { \cO# } \l_test_str \tl_to_str:N {#1} }

\NewDocumentCommand{\defineString}{m}{ \str_set_hash_robust:Nn \l_test_str {#1} % \char_set_catcode_letter:N # % \str_set:Nn \l_test_str {#1} % My failed other try: % \tl_set_rescan:Nnn \l_test_str {\char_set_catcode_letter:N #}{#1} % \tl_to_str:n \l_test_str }

\NewDocumentCommand{\showString}{}{ \show \l_test_str }

\ExplSyntaxOff

\defineString{Hey \notexistingbutnoproblem #} \showString

\pgfkeys{ test/.style={ /utils/exec={% Goal 2: can I avoid escaping the # here? \defineString{Foo \notexistingbutnoproblem ##} \showString } }, test }

\end{document}

tobiasBora
  • 8,684