1

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?

4
  • 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, 2012 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. May 8, 2012 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. May 8, 2012 at 15:50
  • Peter. Your first suggestion solved my problem of inserting an element in the middle of an array. Thanks.
    – Caio
    May 8, 2012 at 17:58

2 Answers 2

2

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}%
}
0

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.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .