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.

While further working on code for my answer to Different approach to literate programming for LaTeX, I am encountering a problem to which I am sure there is a very simple solution, but it completely escapes me.

The issue is: I want to be able to automatically index macro names, some of which will contain the @ character; hence, I need to preprocess them and substitute @ with "@ for makeindex to accept them. I have some code that works while in a listings environment but not when used in a normal environment or command (and I need them too). What's more, if I try to replace any normal letter, it works everywhere – it's only the @ that doesn't work.

So, I suspect the answer has got something to do with listings doing some wizardry on the catcodes, but I would like to find out what it is and how to reproduce it.

Here is the minimal (in which I am reproducing the actual structure of my code, in case the problem lies somewhere there):

\documentclass{article}

\usepackage{listings,etoolbox,xstring}

\makeatletter
\newcommand{\set@macro@type}[1]{\StrSubstitute{#1}{@}{"@}[\entryname]}
\newcommand{\processtexcs}[1]{\set@macro@type{#1}}
\newcommand{\maketexcs}[1]{\forcsvlist{\par\processtexcs{#1}}\entryname}
\makeatother

\lstnewenvironment{code}[1]
    {\maketexcs{#1}}
    {}
\newenvironment{notcode}[1]
    {\maketexcs{#1}}
    {}
\newcommand{\command}[1]{\maketexcs{#1}}

\begin{document}

\begin{code}{my@first@macro}
\end{code}

\begin{notcode}{my@second@macro}
\end{notcode}

\command{my@third@macro}

\end{document}

(Note that it all works if you replace the @ with y in \StrSubstitute.)

share|improve this question
add comment

1 Answer

up vote 3 down vote accepted

It's your wizardry on the category codes. :)

You're defining the main macro in a context where @ has category code 11; but when you use it, \StrSubstitute can't find a category code 11 @. Use

\newcommand{\setmacrotype}[1]{\StrSubstitute{#1}{@}{"@}[\entryname]}
\newcommand{\processtexcs}[1]{\setmacrotype{#1}}
\newcommand{\maketexcs}[1]{\forcsvlist{\par\processtexcs{#1}}\entryname}

without any \makeatletter.

If you're in a .cls or .sty file and want to keep the internal name \set@macro@type, then

\begingroup\lccode`?=`@ \lowercase{\endgroup
  \newcommand{\set@macro@type}[1]{\StrSubstitute{#1}{?}{"?}[\entryname]}
}

will do. The \lowercase operation will transform ? (which has category code 12) into a category code 12 @ before processing \endgroup and \newcommand. Only character tokens are affected by \lowercase, so the list of possibly changed tokens is {[1]#}?" and only ? (under the default setting) will be "lowercased" according to the previous assignment.

share|improve this answer
    
Thanks a million :) Since I am in a class file, the \makeatletter of the MWE wasn't technically wrong, but I altered the catcodes manually in \maketexcs and it all works fine now. Thanks. –  ienissei Jun 28 '12 at 8:27
    
@ienissei I've added a way to do it without too many somersaults. –  egreg Jun 28 '12 at 8:37
    
Thank you, that works as well. –  ienissei Jun 28 '12 at 8:46
add comment

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.