TransWikia.com

Store URLs in a macro without replaceing # and %

TeX - LaTeX Asked by Peter Grill on April 9, 2021

How can I store a URL in a macro if the URL has a # and/or a % in it? The MWE below works fine for the first two, but not the third one.

enter image description here

Notes:

  • One solution is to replace the # with string# and the % with %, but wodering if there is an easier way.

  • I realize that this may mess up the syntax highliting, but the csdef{} section shown here will be in a separte .def file that will be be input{}, so not an issue.

Reference:

Code

documentclass{article}
usepackage{etoolbox}
usepackage{hyperref}
usepackage{tikz}

csdef{url Title 1}{The Google}
csdef{url Link 1}{http://www.google.com}

csdef{url Title 2}{TeX.SE}
csdef{url Link 2}{http://tex.stackexchange.com}

%csdef{url Title 3}{Algebra and Trigonometry:~History of Trigonometry}
%csdef{url Link 3}{https://books.google.com/books?id=4tFFDwAAQBAJ&pg=PT233&dq=history+of+trigonometry&hl=en&newbks=1&newbks_redir=0&sa=X&ved=2ahUKEwjIzcj0-tnqAhXwFjQIHZ6XDLUQ6AEwAnoECAQQAg#v=onepage&q&f=false}

defMaxNUmberOfURLs{5}
newcommand{DisplayURLs}{%
    textbf{List of URLs}
    foreach xCount in {1,...,MaxNUmberOfURLs} {%
        ifcsdef{url Title xCount}{%
            parxCount:
            href{csuse{url Link xCount}}{csuse{url Title xCount}}
        }{}%
    }%
}

begin{document}
DisplayURLs
end{document}

2 Answers

hyperref's hyper@normalise comes in extremely handy here. It can be used to sanitise the argument of a macro and allow it to accept special characters without escaping. (I think I first learned about hyper@normalise from Michael Ummels' answer to Getting those %#!^& signs in the footnote!)

Just use it to define a new macro like newcommand*{csdefurl}[1]{hyper@normalise{csdef{#1}}}. (Note that the argument that is going to be "normalised" is not explicitly part of the definition. newcommand*{csdefurl}[2]{hyper@normalise{csdef{#1}}{#2}} would not work because then the argument is read with the unnormalised catcode setup.)

documentclass{article}
usepackage{etoolbox}
usepackage{hyperref}
usepackage{tikz}

makeatletter
newcommand*{csdefurl}[1]{hyper@normalise{csdef{#1}}}
makeatother

csdef{url Title 1}{The Google}
csdefurl{url Link 1}{http://www.google.com}

csdef{url Title 2}{TeX.SE}
csdefurl{url Link 2}{http://tex.stackexchange.com}

csdef{url Title 3}{Algebra and Trigonometry:~History of Trigonometry}
csdefurl{url Link 3}{https://example.com/~test/a%20and%20b.html#anchor}

defMaxNUmberOfURLs{5}
newcommand{DisplayURLs}{%
    textbf{List of URLs}
    foreach xCount in {1,...,MaxNUmberOfURLs} {%
        ifcsdef{url Title xCount}{%
            parxCount:
            href{csuse{url Link xCount}}{csuse{url Title xCount}}
        }{}%
    }%
}

begin{document}
DisplayURLs
end{document}

Screenshot of the output. The third item reads "Algebra and Trigonometry: History of Trigonometry" and the little pop-up the PDF viewer shows on hover displays "https://example.com/~test/a%20and%20b.html#anchor"


Some more testing reveals that

makeatletter
newcommand*{csdefurl@i}{}
newrobustcmd*{csdefurl}[1]{%
  defcsdefurl@i{csdef{#1}}%
  hyper@normalisecsdefurl@i}
makeatother

might be safer.

Compare this definition to the one above in

documentclass{article}
usepackage{etoolbox}
usepackage{hyperref}
usepackage{tikz}

makeatletter
newcommand*{csdefurl@i}{}
newrobustcmd*{csdefurl}[1]{%
  defcsdefurl@i{csdef{#1}}%
  hyper@normalisecsdefurl@i}
makeatother

csdef{ürl Title 1}{The Google}
csdefurl{ürl Link 1}{http://www.google.com}

csdef{ürl Title 2}{TeX.SE}
csdefurl{ürl Link 2}{http://tex.stackexchange.com}

csdef{ürl Title 3}{Algebra and Trigonometry:~History of Trigonometry}
csdefurl{ürl Link 3}{https://example.com/~test/a%20and%20b.html#anchor}

defMaxNUmberOfURLs{5}
newcommand{DisplayURLs}{%
    textbf{List of URLs}
    foreach xCount in {1,...,MaxNUmberOfURLs} {%
        ifcsdef{ürl Title xCount}{%
            parxCount:
            href{csuse{ürl Link xCount}}{csuse{ürl Title xCount}}
        }{}%
    }%
}

begin{document}
DisplayURLs
end{document}

where we have the non-ASCII ürl instead of url.

Correct answer by moewe on April 9, 2021

You asked,

"How can I store a URL in a macro if the URL has a # and/or a % in it?"

The urldef directive of the url package lets you create precisely such macros. E.g.,

urldef{myURL}url{https://books.google.com/books?id=4tFFDwAAQBAJ&pg=PT233&dq=history+of+trigonometry&hl=en&newbks=1&newbks_redir=0&sa=X&ved=2ahUKEwjIzcj0-tnqAhXwFjQIHZ6XDLUQ6AEwAnoECAQQAg#v=onepage&q&f=false}

Note the syntax: urldef{<macroname>}url{<URLstring>}. Observe taht url{<URLstring>} must not be enclosed in curly braces.

myUrl may be used in the argument of footnote directives.

Answered by Mico on April 9, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP