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.

In index the ! char is used for item separation. I have index strings which contain folders and files.

These index entrys should look like

\index{files!fonts/!fonts.tex}

However I pass these to the index using this command:

\newcommand*{\labelfile}[1]{\index{files!#1}}

which results in

\index{files!fonts/fonts.tex}

thus the replacement of every / in #1 by /! is missing.

How can I replace chars in a string in LaTeX ?

EDIT:

Using the code example from Heiko Oberdiek (which works!) I created the following approach to wrap all items in a \texttt command. Unfortunately my approach fails...

\newcommand*{\labelfile}[1]{%
  \StrSubstitute{#1}{/}{,}[\TempIndexFileEntry]%
  \def\doc@IndexFileEntry\empty
  \def\do##1{%
    \edef\@tempa{\zap@space##1 \@empty}%
    \ifdefempty{\doc@IndexFileEntry}{
      \renewcommand{\doc@IndexFileEntry}{\texttt{\@tempa}}
    }{%
      \renewcommand{\doc@IndexFileEntry}{\doc@IndexFileEntry/\texttt{\@tempa}}
    }%
  }%
  %% Process csv list with command \do (etoolbox)
  \docsvlist{\TempIndexFileEntry}%
  %% rename
  \let\TempIndexFileEntry\doc@IndexFileEntry
  \@bsphack
  \StrSubstitute{\TempIndexFileEntry}{/}{/!}[\IndexFileEntry]%
  \index{files!\IndexFileEntry}%
  \@esphack
}

with

! Use of \TempIndexFileEntry doesn't match its definition.
\@xs@StrSubstitute@@ ...}\@xs@def \@xs@arg@ii {#2}
\@xs@def \@xs@arg@iii {#3}...
share|improve this question
    
Shoudn't you escape the ! (usually with "!) –  Peter Breitfeld Aug 5 '12 at 21:56

2 Answers 2

up vote 4 down vote accepted

Package xstring provides \StrSubstitute that can replace a substring by another substring:

\documentclass{article}
\usepackage{makeidx}
\makeindex

\usepackage{xstring}
\newcommand*{\labelfile}[1]{%
  \StrSubstitute{#1}{/}{/!}[\IndexFileEntry]%
  \index{files!\IndexFileEntry}%
}


\begin{document}
Hello World

\index{files!fonts/!abc.tex}

\labelfile{fonts/xyz.tex}

\printindex
\end{document}

The file test.idx contains:

\indexentry{files!fonts/!abc.tex}{1}
\indexentry{files!fonts/!xyz.tex}{1}

enter image description here

In an more elaborated version of \labelfile, the definition could be surrounded by \@bsphack and \@esphack to preserve the behaviour of \index regarding preceding and following spaces.

\makeatletter
\newcommand*{\labelfile}[1]{%
  \@bsphack
  ...
  \@esphack
}
\makeatother

Also some special characters for makeindex can be quoted:

\StrSubstitute{...}{@}{"@}

Or the file names could be put in \texttt, …

Note: Makeindex only supports three levels. Thus the file specification should only contain one slash. Level 0 is used for files, level 1 for the directory and level 2 for the file name.

Edit: A further request is indeed to put the file names in \texttt. I start similar as in the edited questions to make a comma separated list, but I use package kvsetkeys for parsing the comma separated list, because I am more familiar with this package (as author I should be). We need the following structure of the index entry, e.g. for <directory>/<file>:

\index{files!<directory>/@\texttt{<directory>/}!<file>@\texttt{<file>}}

Each directory or file is doubled, first it is used as sort key, then it is formatted using \texttt.

\documentclass{article}
\usepackage{makeidx}
\makeindex

\usepackage{xstring}
\usepackage{kvsetkeys}

\makeatletter
\newcommand*{\labelfile}[1]{%
  \StrSubstitute{#1}{/}{/,}[\IndexFileA]%
  \let\IndexFileB\@empty
  \expandafter
  \comma@parse@normalized\expandafter{\IndexFileA}\@AddFileEntry
  \index{files!\IndexFileB}%
}
\newcommand*{\@AddFileEntry}[1]{%
  \ifx\IndexFileB\@empty
    \def\IndexFileB{#1@\texttt{#1}}%
  \else
    \expandafter\def\expandafter\IndexFileB\expandafter{%
      \IndexFileB!%
      #1@\texttt{#1}%
    }%
  \fi
}
\makeatother

\begin{document}
Hello World

\labelfile{README}
\labelfile{fonts/abc.tex}
\labelfile{fonts/xyz.tex}

\printindex
\end{document}

The .idx file:

\indexentry{files!README@\texttt  {README}}{1}
\indexentry{files!fonts/@\texttt  {fonts/}!abc.tex@\texttt  {abc.tex}}{1}
\indexentry{files!fonts/@\texttt  {fonts/}!xyz.tex@\texttt  {xyz.tex}}{1}

The multiple spaces are an artefact of LaTeX's protection mechanisms and do not disturb here.

The index looks like:

Index with file names in \texttt

share|improve this answer
    
Works as expected. However putting all file names in \texttt is a bigger problem than I thought. See my edited question for the approach that I took. –  Matthias Pospiech Aug 6 '12 at 18:16

The level character is not fixed if you have a file say myind.ist that has the line

level ;

then ; would be the level separator rather than !. Any suitable character may be used.

You would then process with

makeindex -s myind.ist myfile

to use the myind.ist style.

See for example the index style designed to go with the doc style for documenting latex packages, which is usually installed somewhere like

 texmf-dist/makeindex/latex/gind.ist
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.