Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

I've defined the following macro:

\begingroup
\lccode`\~=`\#%
\lowercase{\endgroup%
\def~ #1\par}{%
\begingroup\def\par{\endgroup\par}%
\section*{#1}\par}%
\catcode`\#=13

But if I go on to define a command such as

\begingroup
\lccode`\~=`\#%
\lowercase{\endgroup%
\def~~ #1\par}{%
\begingroup\def\par{\endgroup\par}%
\subsection*{#1}\par}%
\catcode`\#=13

while ## Test now works as expected, any usages of # Test no longer function, and the console returns an error stating that Use of # doesn't match its definition..

How can I configure a macro of this variety so that both macros work as expected?

share|improve this question

1 Answer 1

up vote 7 down vote accepted

When \def is followed by an active character, that is defined and all that follows up to the open brace is the macro's parameter text.

With the first part of the code you're giving a meaning to the active # and \show# prints

> #=macro:
 #1\par ->\begingroup \def \par {\endgroup \par }\section *{#1}\par .

The parameter text is

#1\par

which means that everything up to the first following \par token is to be the argument.

When you execute the second code (that of course requires to delay \catcode#=13), you're overriding the meaning of the active#; indeed,\show#` now prints

> #=macro:
# #1\par ->\begingroup \def \par {\endgroup \par }\subsection *{#1}\par .

Now # is a macro (active character) that expects to be followed by another active #. Therefore # Text will raise the error

Use of # doesn't match its definition.

You need to define the active # to look whether the following token is another # and, in this case take the appropriate action.


Here's a possible definition

\documentclass{article}

\makeatletter
\begingroup\lccode`~=`#
\lowercase{\endgroup
  \def~{\@ifnextchar~\markdown@subsec\markdown@sec}
}

\def\markdown@sec#1\par{\section*{#1}}
\def\markdown@subsec#1{\@ifnextchar\valign\relax\markdown@subsec@aux}
\def\markdown@subsec@aux#1\par{\subsection*{#1}}
\makeatother

\AtBeginDocument{\catcode`\#=\active}

\begin{document}
# Section Title

Some text

## Subsection Title

Some other text

\end{document}

The mysterious definition of \markdown@subsec is explained by the need of eating up spaces: \@ifnextchar does just this, because it's quite difficult that you write ##\valign; and if you do, the macro would fail.

The extension for subsubsections is straightforward:

\documentclass{article}

\makeatletter
\begingroup\lccode`~=`#
\lowercase{\endgroup
  \def~{\@ifnextchar~\markdown@subsec\markdown@sec}
  \def\markdown@subsec#1{\@ifnextchar~\markdown@subsubsec\markdown@subsec@aux}
}
\def\markdown@sec#1\par{\section*{#1}}
\def\markdown@subsubsec#1{\@ifnextchar\valign\relax\markdown@subsubsec@aux}
\def\markdown@subsec@aux#1\par{\subsection*{#1}}
\def\markdown@subsubsec@aux#1\par{\subsubsection*{#1}}
\makeatother

\AtBeginDocument{\catcode`\#=\active}

\begin{document}
# Section Title

Some text

## Subsection Title

Some other text

### Subsubsection Title

Oh, well!

\end{document}

enter image description here

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.