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'm trying to make a class following my school's standard for thesis and I got a problem when I tried to implement a list of acronyms, because this list should be alphabetically sorted and the packages that I found were incompatible with my implemented class. So I decide to make my own implementation using arrays.

I can create arrays as \foo#1 (in which each element of array receive as new index in #1, using \csname foo#1 \endcsname), but to sort this array I need to insert an element in a specific position of the array.

An example of my code at now is:

\documentclass[]{report}

\newcounter{countArrayTest}
\setcounter{countArrayTest}{0}

\newcommand{\appendElement}[1]{%
    \expandafter\newcommand\csname arraytest\the\value{countArrayTest} \endcsname{#1}
    \stepcounter{countArrayTest}
}

\newcommand{\getIndexElement}[1]{
    \csname arraytest#1 \endcsname
}

\newcommand{\testInsert}{%
    \expandafter\renewcommand\csname arraytest1 \endcsname{\getIndexElement{0}}
    \expandafter\renewcommand\csname arraytest0 \endcsname{Test1}
}

\newcounter{CountTempAux}

\newcommand{\showAll}{%
    \setcounter{CountTempAux}{0}
    \loop\ifnum\value{CountTempAux}<\value{countArrayTest}
        \csname arraytest\the\value{CountTempAux} \endcsname
        \stepcounter{CountTempAux}
    \repeat
}

\begin{document}


\appendElement{Element1}
\appendElement{Element2}


\testInsert

\showAll

\end{document}

The problem is, I expected the answer "Test1 Element1", but I got "Test1 Test1".

Any suggestion to solve this problem?

share|improve this question

migrated from stackoverflow.com May 8 '12 at 12:55

This question came from our site for professional and enthusiast programmers.

1  
Since doing this sort of thing is quite complicated, maybe you could describe problem you had implementing any of the existing acronym packages and we could help solve that problem. –  Alan Munn May 8 '12 at 13:05
    
Changing \testInsert to \newcommand{\testInsert}{\expandafter\edef\csname arraytest1 \endcsname{\getIndexElement{0}} \expandafter\edef\csname arraytest0 \endcsname{Test1} } yields the desired result, but not sure if that shows what you are trying to do is working correctly. –  Peter Grill May 8 '12 at 15:47
    
Alternatively, you could use the \g@addto@macro as described in How keep a running list of strings and then process them one at a time and then sort via Sorting Comma Separated Lists defined with, or without macro. –  Peter Grill May 8 '12 at 15:50
    
Peter. Your first suggestion solved my problem of inserting an element in the middle of an array. Thanks. –  Caio May 8 '12 at 17:58
add comment

2 Answers

up vote 2 down vote accepted

I agree with Alan Munn's comment that it is probably easier if you show'd us the problems you're having with the acronym packages you tried (acronym? glossaries?).

To your question at hand: the problem you're having lies in

\newcommand{\testInsert}{%
    \expandafter\renewcommand\csname arraytest1 \endcsname{\getIndexElement{0}}
    \expandafter\renewcommand\csname arraytest0 \endcsname{Test1}
}

\arraytest1 is not defined to be \arraytest0 but to \getIndexElement{0}. Later when you call it inside \showall \arraytest0 has already been redefined to Test1.

In order to store the contents of \arraytest0 you'd need to expand \getIndexEntry{0}

\newcommand{\testInsert}{%
    \expandafter\edef\csname arraytest1 \endcsname{\getIndexElement{0}}%
    \expandafter\renewcommand\csname arraytest0 \endcsname{Test1}%
}

Now

\appendElement{Element1}\appendElement{Element2}
\testInsert
\showAll

will give

Test1 Element1

This won't work if \arraytest0 contains unexpandable stuff, though:

\appendElement{\textbf{Element1}}\appendElement{Element2}
\testInsert
\showAll

In this case you can use \protected@edef

\makeatletter
\newcommand{\testInsert}{%
    \expandafter\protected@edef\csname arraytest1 \endcsname{\getIndexElement{0}}%
    \expandafter\renewcommand\csname arraytest0 \endcsname{Test1}%
}
\makeatother
\appendElement{\textbf{Element1}}\appendElement{Element2}
\testInsert
\showAll

Test1 Element1

You could also use etoolbox's \csletcs (*):

\usepackage{etoolbox}
\newcommand{\testInsert}{%
    \csletcs{arraytest1}{arraytest0}%
    \expandafter\renewcommand\csname arraytest0\endcsname{Test1}%
}

(*) your current definition of showall produces lots of spaces between the elements. In order to avoid that you should comment out all lines not ending with a command:

\newcommand{\showAll}{%
    \setcounter{CountTempAux}{0}%
    \loop\ifnum\value{CountTempAux}<\value{countArrayTest}%
        \csname arraytest\the\value{CountTempAux} \endcsname
        \stepcounter{CountTempAux}%
    \repeat
}

The same holds for every other command you're defining. For example

\newcommand{\appendElement}[1]{%
    \expandafter\newcommand\csname arraytest\the\value{countArrayTest} \endcsname{#1}
    \stepcounter{countArrayTest}
}

defines \arraytest0 (including a space after the 0! unless you change that the \csletcs code from me won't work yet) and produces two additional spaces when called. Better:

\newcommand{\appendElement}[1]{%
    \expandafter\newcommand\csname arraytest\the\value{countArrayTest}\endcsname{#1}%
    \stepcounter{countArrayTest}%
}

You might want to use \@namedef or etoolbox's \csdef, anyway:

\newcommand{\appendElement}[1]{%
    \@namedef{arraytest\the\value{countArrayTest}}{#1}%
    \stepcounter{countArrayTest}%
}
share|improve this answer
add comment

If you are willing to put in this much work, it may be worth trying the tocloft package. Here's a quick-start article on the tocloft package. It drops a file in the compilation directory that you can run through sort(1) or another utility as part of the build process.

share|improve this answer
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.