1

I have frequent need to use URLs with # characters in them, and the hashtag causes compilation errors of course. To date, I have used two ways to get around this. One is to manually escape them (change them to \# and the other is to use a URL shortener. The students in my class don't always remember to do either of these and I'd like a way to simply pass the URL to a macro. I discovered I can use the \AtBeginEnvironment hook to fix the problem when I define an environment that uses the URL, but the hook mechanism doesn't work for the macro form of the environment (which may be an artifact of tcolorbox). Why is this?

I have spent hours searching this site for a solution and nothing seems to work. The solutions explained in https://tex.stackexchange.com/a/554190/218142 and https://tex.stackexchange.com/a/554200/218142 looked promising but didn't work for me.

Is there a clean way to pass the URL without having to manually fix it every time or without having to shorten it every time?

% !TEX program = lualatexmk
% !TEX encoding = UTF-8 Unicode

\documentclass{article}

\begin{filecontents}[overwrite,noheader]{demo.py}
Hello, world!
\end{filecontents}

\usepackage[most]{tcolorbox}
\usepackage{hyperref}

\AtBeginEnvironment{codeenv}{\catcode`\#=12}
\NewTCBListing[auto counter]{codeenv}
  { O{} D(){glowscript.org} m }{%
  breakable,%
  center,%
  %code = \newpage,%
  enhanced,%
  hyperurl interior = https://#2,%
  label = {gs:\thetcbcounter},%
  left = 8mm,%
  listing only,%
  listing style = tcblatex,%
  title = Listing: #3,%
  width = 0.9\textwidth,%
  {#1},
}%

\NewTCBInputListing[auto counter]{\codefile}
  { O{} D(){glowscript.org} m m }{%
  breakable,%
  center,%
  %code = \newpage,%
  enhanced,%
  hyperurl interior = https://#2,%
  label = {vp:\thetcbcounter},%
  left = 8mm,%
  listing file = {#3},%
  listing only,%
  listing style = tcblatex,%
  title = Listing: #4,%
  width = 0.9\textwidth,%
  {#1},%
}%

\begin{document}
This works using the hook.
\begin{codeenv}(www.glowscript.org/#/user/heafnerj/folder/Public/program/nhattest){My Program}
Hello, world!
\end{codeenv}

This works with a shortened URL.
\begin{codeenv}(t.ly/9i20){My Program}
Hello, world!
\end{codeenv}

%This does not work.
%\codefile(www.glowscript.org/#/user/heafnerj/folder/Public/program/nhattest){demo.py}{My Program File}

This works by escaping the \#.
\codefile(www.glowscript.org/\#/user/heafnerj/folder/Public/program/nhattest){demo.py}{My Program File}

This works with a shortened URL.
\codefile(t.ly/9i20){demo.py}{My Program File}
\end{document}
0

1 Answer 1

2

Here, I added the lines

\newcommand\codefile{\catcode`\#=12 \codefileauxA}
\NewDocumentCommand\codefileauxA{ O{} D(){glowscript.org} m m }{%
  \codefileauxB[#1](#2){#3}{#4}%
  \catcode`\#=6 
}

and renamed what had been \codefile to

\NewTCBInputListing[auto counter]{\codefileauxB}

The effect of this is to change the catcode of # only for the invocation of \codefileauxA (where the actual arguments are absorbed) and change it back after \codefileauxB is complete.

The MWE:

% !TEX program = lualatexmk
% !TEX encoding = UTF-8 Unicode

\documentclass{article}

\begin{filecontents}[overwrite,noheader]{demo.py}
Hello, world!
\end{filecontents}

\usepackage[most]{tcolorbox}
\usepackage{hyperref}

\AtBeginEnvironment{codeenv}{\catcode`\#=12}
\NewTCBListing[auto counter]{codeenv}
  { O{} D(){glowscript.org} m }{%
  breakable,%
  center,%
  %code = \newpage,%
  enhanced,%
  hyperurl interior = https://#2,%
  label = {gs:\thetcbcounter},%
  left = 8mm,%
  listing only,%
  listing style = tcblatex,%
  title = Listing: #3,%
  width = 0.9\textwidth,%
  {#1},
}%

\newcommand\codefile{\catcode`\#=12 \codefileauxA}
\NewDocumentCommand\codefileauxA{ O{} D(){glowscript.org} m m }{%
  \codefileauxB[#1](#2){#3}{#4}%
  \catcode`\#=6 
}
\NewTCBInputListing[auto counter]{\codefileauxB}
  { O{} D(){glowscript.org} m m }{%
  breakable,%
  center,%
  %code = \newpage,%
  enhanced,%
  hyperurl interior = https://#2,%
  label = {vp:\thetcbcounter},%
  left = 8mm,%
  listing file = {#3},%
  listing only,%
  listing style = tcblatex,%
  title = Listing: #4,%
  width = 0.9\textwidth,%
  {#1},%
}%

\begin{document}
This works using the hook.
\begin{codeenv}(www.glowscript.org/#/user/heafnerj/folder/Public/program/nhattest){My Program}
Hello, world!
\end{codeenv}

This works with a shortened URL.
\begin{codeenv}(t.ly/9i20){My Program}
Hello, world!
\end{codeenv}

This does not work.
\codefile(www.glowscript.org/#/user/heafnerj/folder/Public/program/nhattest){demo.py}{My Program File}

This works by escaping the \#.
\codefile(www.glowscript.org/\#/user/heafnerj/folder/Public/program/nhattest){demo.py}{My Program File}

This works with a shortened URL.
\codefile(t.ly/9i20){demo.py}{My Program File}
\end{document}

enter image description here

1
  • 1
    AHA! I see what I was doing wrong! I neglected to rename the original macro while doing so inside the wrapper. I was hoping it was something simple like this. Thank you! Sep 21, 2021 at 20:03

You must log in to answer this question.

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