4

I am writing a rather long document and I would like to highlight certain names only the first time they appear but add them to the index every time. In other words, I want that:

\important{John Smith} 

behaves like this:

\textbf{John Smith}\index{John Smith}

the first time that appears. And like this:

John Smith \index{John Smith} 

any subsequent time. Of course I can create to commands but the text is very fluid right now I would rather have this automated.

Hernan
  • 237

3 Answers3

6

This could be achieved with a sequence list where each \important{...} checks whether the word (expression) has been added to the list, if not, it's highlighted, otherwise \index{...} is used.

The easiest way to get the list and checking working is using the new expl3 features of the upcoming LaTeX 3 format -- it works however with any modern TeX distribution already.

Some note:

The usage of \index{#1} for both the display and index value isn't healthy and needs some work (e.g. \important{foo!bar} isn't fine)

\documentclass{article}

\usepackage{makeidx}

\usepackage{xparse}

\ExplSyntaxOn
\seq_new:N \l_hernan_seq
\NewDocumentCommand{\important}{m}{
  \seq_if_in:NnTF{\l_hernan_seq}{#1}{
    #1\index{#1}
  }{
    \seq_put_left:Nn{\l_hernan_seq}{#1}
    \textbf{#1}
    \index{#1}
  }
}
\ExplSyntaxOff

\makeindex

\begin{document}


Here is some \important{expression} which isn't highlighted again here \important{expression}

And another \important{word}, not highlighted in here:  \important{word}



\printindex

\end{document}

enter image description here

Edit

\documentclass{article}



\usepackage{imakeidx}

\usepackage{xparse}

\ExplSyntaxOn
\seq_new:N \l_hernan_seq
\NewDocumentCommand{\important}{m}{
  \seq_if_in:NnTF{\l_hernan_seq}{#1}{
    #1\index{#1}
  }{
    \seq_put_left:Nn{\l_hernan_seq}{#1}
    \textbf{#1}
    \index{#1}
  }
}



\NewDocumentCommand{\getimportantwordslist}{+O{\par}}{
  \seq_use:Nn{\l_hernan_seq}{#1}
}
\ExplSyntaxOff


\NewDocumentCommand{\PrintHighlighted}{+m}{%
Here is the list of important words:

\getimportantwordslist
}

\makeindex

\begin{document}

\important{Here} starts the stuff, but \important{Here} it's not highlighted!

Here is some \important{expression} which isn't highlighted again here: \important{expression}

And another \important{word}, not highlighted in here:  \important{word}



\PrintHighlighted


\end{document}

enter image description here

  • It might fail with commands handed over to \important, however, due to lacking expansion –  Sep 18 '15 at 15:32
  • @touhami: ????? –  Sep 18 '15 at 15:40
  • @touhami: I am learning latex3, somehow, yes, just to steal some ticks egreg would get otherwise :-P ... No, seriously, I am just a beginner –  Sep 18 '15 at 15:48
  • @campa: Right: I'll change –  Sep 18 '15 at 15:49
  • @ChristianHupfer Great Answer! One short extra question: is there a way to print that list, in addition to printing the index. The reason is that the index might contain other entries at well. – Hernan Sep 18 '15 at 21:18
  • @Hernan: See the updated version at the end of my answer. The problem is rather that LaTeX3 gobbles whitespace, so one has to switch between ExplSyntax etc. to make commands that work with the L3 - macros and those, that can't. Use \seq_use:Nn{\l_hernan_seq}{\par} for usage with newlines. –  Sep 18 '15 at 21:34
1

You may use a package like glossaries and add your index terms as glossary items. There is an specific style for first time appearance of a glossary item in the text. You may set that style as you want. And you can generate your index list using glossaries package. The only drawback is that, you need to define all glossary items separately, preferably in a glossaries file. It is not that difficult, since if you have an undefined entry you will get an error message and then you can add that item to your glossaries.

Aydin
  • 1,983
0

I took Christian's answer and I tried to make something working with complex indexing situations. The most complex situation that I can imagine is something like

A!b!C@D|E

In this situation what you need to print in bold face is C, so we have to make some manipulation.

A solution could be using delimited arguments, but I decided to use the \seq_set_split: command: at first I create a sequence using the | as separator, then I take only the first element of the sequence, that is everything but the |... part.

Then I create another seq with the @ delimiter, and then another one with the ! delimiter. The last element of this sequence is the entry, stored in the \l_hernan_entry_tl token list. And now you can do what Christian suggested.

\documentclass{article}
\usepackage{imakeidx}
\usepackage{xparse}

\ExplSyntaxOn
\seq_new:N \l_hernan_seq
\tl_new:N \l_hernan_first_split_tl   % for storing the entry without "|see..." part
\tl_new:N \l_hernan_second_split_tl  % for storing the entry without "@..." part
\tl_new:N \l_hernan_entry_tl        % for storing the entry
\seq_new:N \l_hernan_vertical_bar_seq 
\seq_new:N \l_hernan_at_seq
\seq_new:N \l_hernan_entries_seq
\NewDocumentCommand{\important}{m}
    {
    \seq_set_split:Nnn \l_hernan_vertical_bar_seq {|} {#1}
    \seq_get_left:NN  \l_hernan_vertical_bar_seq \l_hernan_first_split_tl
    %
    \seq_set_split:NnV \l_hernan_at_seq {@} \l_hernan_first_split_tl
    \seq_get_left:NN  \l_hernan_at_seq \l_hernan_second_split_tl
    %
    \seq_set_split:NnV \l_hernan_entries_seq {!} \l_hernan_second_split_tl
    \seq_get_right:NN  \l_hernan_entries_seq \l_hernan_entry_tl
    %
    \seq_if_in:NVTF\l_hernan_seq \l_hernan_entry_tl
        {\l_hernan_entry_tl \index{#1}} %true
        {\seq_put_left:NV \l_hernan_seq \l_hernan_entry_tl
        \textbf{\l_hernan_entry_tl}\index{#1}}  %false
    %\seq_show:N \l_hernan_seq
    }

\NewDocumentCommand{\getimportantwordslist}{+O{\par}}{
  \seq_use:Nn{\l_hernan_seq}{#1}
}
\ExplSyntaxOff


\NewDocumentCommand{\PrintHighlighted}{+m}{%
Here is the list of important words:

\getimportantwordslist
}

\makeindex

\begin{document}
The most complex situation that I can imagine is \important{Mainentry!subentry!realentry@myentry|see{other}} for indexing the \important{realentry} word as \important{myentry}.

\important{Here} starts the stuff, but \important{Here} it's not highlighted!

Here is some \important{expression} which isn't highlighted again here: \important{expression}

And another \important{word}, not highlighted in here:  \important{word}

\bigskip
\PrintHighlighted

\printindex
\end{document}

Please let me know if you find some bug.