# Indirectly defining two active characters within an \AtBeginDocument command

I'm trying to define a macro that uses two active characters inside an \AtBeginDocument command.

I can write a macro such as the following using only one active character:

\catcode\_=13
\begingroup
\lccode\~=\_
\lowercase{\endgroup
\def~#1~}{\emph{#1}}
\def\_{\char"5F\relax}


However, I'd like to define two characters as active and use them at the same time to enclose a shorthand syntax.

If I use code similar to the following:

\catcode\<=13
\catcode\>=13
\begingroup
\lccode\~=\<
\lowercase{\endgroup
\def~#1>}{\url{#1}}
\def\<{\char"3C\relax}
\def\>{\char"3E\relax}


the console returns Paragraph ended before < was complete.

It seems that both characters need to be used in an indirect method similar to defining them as a lowercase version of the tilde.

Is there another character I can use in such a situation to make such a macro work? Or would there be a better way of doing this?

• Are you after a <...> shorthand for URLs? – Werner Nov 4 '12 at 4:20
• Yes, but I would also like to be able to define other similar commands if possible. – Кигава Енсеи Nov 4 '12 at 4:24

If you're after defining a shorthand for URLs of the form <my URL>, then the following works:

\documentclass{article}
\usepackage{url}% http://ctan.org/pkg/url

% Create <URL> shorthand
\catcode\<=13%
\begingroup
\lccode\~=\<
\lowercase{\endgroup
\def~#1>}{\url{#1}}

\begin{document}
\end{document}


The reason why this works is because you're only using > as a delimiter in terms of the argument specification for < - a now active character. It doesn't need to be active itself.

Note that this will cause problems when you're using < in math mode.

• Use \lowercase{\endgroup\def~}{\relax\ifmmode<\else\expandafter\abbrvurl\fi} and \def\abbrvurl#1>{\url{#1}} but delay activating < with \AtBeginDocument. – egreg Nov 4 '12 at 10:57

I can't see why <http://a.b.c> is to be preferred to \url{http://a.b.c}, nor how _xyz_ is clearer than \emph{xyz}. I believe that in both cases the latter syntax is better.

However, here's a solution for your problem.

\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage{hyperref}

\begingroup\lccode\~=\_ \lowercase{\endgroup
\protected\def~{\ifmmode\sb\else\expandafter\abbrvemph\fi}
\def\abbrvemph#1~{\emph{#1}}

\begingroup\lccode~=< \lowercase{\endgroup
\protected\def~}{\ifmmode<\else\expandafter\abbrvurl\fi}}
\def\abbrvurl#1>{\url{#1}}

\AtBeginDocument{
\catcode<=\active
\catcode_=\active
}

\begin{document}

This is a URL: <http://a.b.c> and this _is_ emphasized,
but in formulas like $a<b_{1}$ there is _no_ prob\_lem.

\end{document}


Note that there is no need to define \_; nor you need to clobber \< or \>, since < in math mode will work correctly, and the same for _

Note that there is nothing special about ~ any active character would do. Also, it isn't clear from your question why you need the indirection via \lowercase at all.

\catcode\<=13
\catcode\>=13
\begingroup
\lccode\~=\<
\lowercase{\endgroup
\def~#1>}{\url{#1}}
\def\<{\char"3C\relax}
\def\>{\char"3E\relax}


is the same as

\catcode\<=13
\catcode\>=13
\def<#1>{\url{#1}}
\def\<{\char"3C\relax}
\def\>{\char"3E\relax}


You only need to use the \lowercase trick if you need to use both the non active and active token at the same time. For example you used \char here but you in your first version you could have delayed the activation of < until after the definition and written

\def\<{<}


or even something like

 \def~{<}


to define an active < to expand to a non-active one.

So for example the following produces a log of

A: the character <
B: macro:#1>->\url {#1}


from the file

\documentclass{article}
\usepackage{url}
\begingroup
\catcode\<=13
\catcode\>=13
\AtBeginDocument{%
\catcode\<=13 %
\catcode\>=13 %
\def<#1>{\url{#1}}%
\def\<{\char"3C\relax}%
\def\>{\char"3E\relax}%
}
\endgroup

\typeout{A: \meaning<}

\begin{document}

\typeout{B: \meaning<}

<http://example.org>

\end{document}

• The indirection seems to be necessary because if it's omitted, as in your example, the console returns an error: Missing control sequence inserted. <inserted text> \inaccessible l.7 \begin{document} The error doesn't occur using the indirect method. Similarly, omitting the indirect method on the other example, using underscores, results in the command simply not taking effect. I'm not sure, but I think that it is the result of putting the code inside the \AtBeginDocument argument rather than manually after the begin{document} command. – Кигава Енсеи Nov 5 '12 at 5:31
• That is why we always ask that people put complete small documents in their question, that shows the problem. In this case the problem is in the way you are calling \AtBeginDocument ie it is in code that you have not shown which makes it hard to help. I have put a complete example into my answer. – David Carlisle Nov 5 '12 at 9:57