6

I can't believe I'm the first person to ask this, but is there a better way to set a literal colon (:) within Expl syntax than \str_use:N\c_colon_str? That's pretty clunky for things like writing a URL. For example, I'm writing a command to print out a link to a certain page on my examples server, and right now that is defined like this:

\NewDocumentCommand \server { m }
{ \href { \str_use:N \c_app_proto_str \str_use:N \c_colon_str // \str_use:N \c_app_host_str / #1 / }
        { \str_use:N \c_app_proto_str \str_use:N \c_colon_str // \linebreak[2]
          \str_use:N \c_app_host_str / \linebreak[2] #1 / } }

All of these \str_use:Ns are really obscuring what should really be a pretty simple command.

2
  • For str you can drop the \str_use:N if you want to. But if you only need the character : to appear, and don't care which category code it has (11 or 12), then you can just use : in your macro (for instance \href { \c_app_proto_str :// \c_app_host_str /#1/ } should work).
    – Skillmon
    Apr 12 at 14:19
  • @Skillmon Brilliant! If you make that an answer, I'll happily accept it. I was getting errors earlier with colons, but I guess I just need to make sure they're not getting globbed with other tokens. Apr 12 at 14:25

2 Answers 2

5

Inside of \ExplSyntaxOn the : can be used directly to output something, just as any other letter, as long as you don't really need it to have category 12 and category 11 would also be fine.You only have to make sure that it doesn't "touch" a macro name, so you can use \c_app_proto_str : but not \c_app_proto_str:.

Also for str and tl variables the \..._use:N accessor isn't strictly necessary and you can omit it.

Your code snippet can therefore be shortened to

\NewDocumentCommand \server { m }
{ \href { \c_app_proto_str \c_colon_str // \c_app_host_str / #1 / }
        { \c_app_proto_str :// \linebreak[2]
          \c_app_host_str / \linebreak[2] #1 / } }

Thanks to Ulrike Fischer for pointing out that the first argument of \href needs to have a category 12 colon, hence we need to use \c_colon_str there.

3
  • 4
    that doesn't work. It prints the right thing, but hyperref no longer can detect that there is a protocol at the begin and then produces a file link instead of an uri: /F(https://ctan.org/.pdf)/S/GoToR Apr 12 at 14:51
  • Huh. I guess \c_colon_str it is, then. Still nice to know I don't need the \str_use:N. Apr 12 at 19:19
  • 1
    @UlrikeFischer thanks for pointing this out! I never checked it, tbh., and wasn't aware hyperref needs a category 12 for its test.
    – Skillmon
    Apr 13 at 19:53
2

The main problem is that \href wants to see an explicit character token : of category code 12, in order to write the correct link in the PDF file, isolating the protocol from the rest.

You can do it in three steps.

\documentclass{article}
\usepackage{hyperref}

\ExplSyntaxOn

\NewDocumentCommand \server { m }
 {
  \ar_href:VVn \c_app_proto_str \c_app_host_str { #1 }
 }

\cs_new_protected:Nn \ar_href:nnn
 {% we need one more technical step for the colon
  \__ar_href:Vnnn \c_colon_str { #1 } { #2 } { #3 }
 }
\cs_new_protected:Nn \__ar_href:nnnn
 {
  \href { #2 #1 // #3 / #4 / }
        { #2 #1 // \linebreak[2] #3 / \linebreak[2] #4 / }
 }
\cs_generate_variant:Nn \__ar_href:nnnn { V }
\cs_generate_variant:Nn \ar_href:nnn { VV }

\str_const:Nn \c_app_proto_str { https }
\str_const:Nn \c_app_host_str { example.com }

\ExplSyntaxOff

\begin{document}

\server{whatever}

\end{document}

enter image description here

I'm not sure you want the trailing /.

What am I doing? I define a generic \ar_href:nnn function that you can use also in different contexts (for other protocols, for instance) and a variant thereof that takes the string constants as arguments.

Due to the peculiar state of the colon, a further step is better, so this function actually calls another, where the first argument, through a variant, will provide the colon with the right category code.

It would be much easier if you add the colon to the prot constant:

\documentclass{article}
\usepackage{hyperref}

\ExplSyntaxOn

\NewDocumentCommand \server { m }
 {
  \ar_href:VVn \c_app_proto_str \c_app_host_str { #1 }
 }

\cs_new_protected:Nn \ar_href:nnn
 {
  \href { #1 // #2 / #3 / }
        { #1 // \linebreak[2] #2 / \linebreak[2] #3 / }
 }
\cs_generate_variant:Nn \ar_href:nnn { VV }

\str_const:Nn \c_app_proto_str { https: }
\str_const:Nn \c_app_host_str { example.com }

\ExplSyntaxOff

\begin{document}

\server{whatever}

\end{document}
13
  • 1
    @A.R. I changed a little the implementation, to make it cleaner. Variants are a “plus” of expl3.
    – egreg
    Apr 12 at 19:43
  • 3
    Honestly, this is so absurdly complicated that I'd sooner give up on expl3, turn \ExplSyntaxOff and just write the stupid function the old-fashioned way than even attempt to understand what you've done here. You shouldn't need a PhD to write a colon into the document. Apr 12 at 20:18
  • 1
    @A.R. You're complicating things with string constants…
    – egreg
    Apr 12 at 20:19
  • 2
    @User23456234 I've already read expl3.pdf, or as much as I can grasp, and I think expl3 is taking LaTeX in a positive direction. Nevertheless, learning is a process, and nobody just picks things up effortlessly. Telling people "it's easier, just read the PDF" or calling them "silly" (especially when they didn't downvote) could be turned into more constructive approaches. Elaborating on the why can increase the value of an answer to readers beyond just the OP, plus it helps users to "learn how to fish" and use expl3 on their own.
    – gz839918
    Apr 13 at 5:33
  • 2
    As I understand it, the original version of the other answer didn't work. However, the current one apparently does. So I completely understand why somebody should prefer your answer to the first version of the other one, but I'm not following why somebody should prefer it to the revised version of the other one. Could you maybe explain why an extra step is better? Doesn't \href get to see an actual colon with category 12 with both answers now?
    – cfr
    Apr 14 at 6:02

You must log in to answer this question.

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