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}

1 Answers1

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
    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! – LaTeXereXeTaL Sep 21 '21 at 20:03