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 writing a scientific paper, and in this paper, I present a series of new terms. The first time a new term is presented, I would like LaTeX to automatically highlight this - e.g. by using italics or small caps.

Does such a package exist? Or if not, do any of you know an alternative way to accomplish the same?

share|improve this question
2  
Welcome to TeX.SE. I believe that the package acronym can be used for this, however, I have no personal experience to provide you a full answer. –  tohecz Apr 3 '12 at 9:50
    
I'm pretty sure this could be done with LuaTeX using a callback and passing a list of words to highlight. –  ℝaphink Apr 3 '12 at 11:26

4 Answers 4

up vote 29 down vote accepted

You can't do this in a fully automated way. It's not possible to give a list of words and get TeX recognize the first occurrence.

What you can do is to mark the terms in the .tex file, after giving the list and something like the following code:

\documentclass{article}

%%% Code to set up special term treatment
\makeatletter
\newcommand{\specialterms}[1]{%
  \@for\next:=#1\do
    {\@namedef{specialterm@\detokenize\expandafter{\next}}{}}%
}
\newcommand\term[1]{%
  \@ifundefined{specialterm@\detokenize{#1}}
    {#1}{\emph{#1}\global\expandafter\let\csname specialterm@\detokenize{#1}\endcsname\relax}%
}
\makeatother

%%% Here we define the special terms we want
\specialterms{foo,bar,baz}

\begin{document}

First occurrence of \term{foo} and second occurrence of \term{foo}.

First occurrence of \term{baz}. Now \term{bar} and
again \term{bar} and \term{baz} and \term{foo}.

\end{document}

enter image description here

What does the code do? The \@for is just an easier way to avoid saying something like

\specialterm{foo}\specialterm{bar}\specialterm{baz}

With \specialterms{foo,bar,baz} we execute the same code for each term: for example, the command \specialterm@foo is defined essentially to do nothing. Indeed we'll examine only its "existence": when LaTeX finds \term{foo} it looks whether \specialterm@foo is defined: if it is it prints \emph{foo} and undefines \specialterm@foo (making it equivalent to \relax, which, for \@ifundefined is exactly being undefined); otherwise it prints foo.

The \detokenize bit is just to avoid problems if the term contains accented characters.

share|improve this answer
1  
Could you please explain the code of your example? Cheers. –  NVaughan Apr 3 '12 at 16:32
    
Thanks. Where can I find more information (a manual, perhaps) on these commands? Cheers. –  NVaughan Apr 3 '12 at 20:16
1  
The TeX book; TeX by Topic (texdoc texbytopic); the LaTeX source (texdoc source2e). –  Caramdir Apr 3 '12 at 20:27

I use the glossaries package for this purpose. It is very flexible, and allows you to define terminology, specify how it should look upon first and subsequent uses, and then produce a glossary of the words. Here is a simple example that displays the first term in italics, and uses hyperref to link the use of the terms to the definition in the glossary (which appears at the end of the document). The glossaries package also has similar support for acronyms.

\documentclass{scrbook}
\usepackage[colorlinks]{hyperref}  % Terms will also be coloured as they are hyperlinks.
\usepackage{glossaries}
\makeglossaries
\newglossaryentry{term}{
  name=term, 
  description={A word or phrase with an unfamiliar but specific meaning that
    should be flagged upon first use and defined}
}

% Customize the format of the first use.  See the manual for details if
% you want to include more information here such as the definition.
\defglsdisplayfirst[\glsdefaulttype]{\textit{#1}}

\begin{document}
% Note that there are forms for plural entries (appending an 's' by default)
% and for capitals such as should occur at the start of a sentence:
This document is about \glspl{term}.  That was the first use of the term
\gls{term}, and this is the second. \Glspl{term} may also occur at the start   
of sentences like this.

% Print the whole glossary
\printglossaries

\end{document}

To make this, run your preferred flavour of LaTeX, then makeglossaries:

pdflatex example
makeglossaries example
pdflatex example
pdflatex example

or you can teach latexmk to use makeglossaries. I recommend latexmk quite highly for building LaTeX documents, especially with the -pdf -pcv options for pdflatex and automatically rebuilding when I change the source.

Note: The documentation for the glossaries package is somewhat inpenetrable – all the information is there, but check out the articles with the {glossaries} tag first to save some time.

Sample output of glossary entries Sample glossary

share|improve this answer

Here is a solution with luatex. The idea is to use the process_input_buffer callback so that luatex will check every input line of text for the word to be emphasized. If it is found and if it is the first time, then it adds a macro around the word to emphasize it.

I use pattern matching to detect if the word is not a 'subword' of an other and to detect punctuation.

Note that I'm not a guru with pattern matching using the string library (I should have done it with lpeg...). So it breaks for the detection of bar (feel free to correct my code).

First the lua file (save it as first-occurence.lua).

local gsub = string.gsub
local find = string.find

first_occurence = first_occurence or {}
first_occurence.table = first_occurence.table or {}

function first_occurence.add (s)
   first_occurence.table[#first_occurence.table + 1] = 
  { [1] = s, [2] = true}
end

function first_occurence.start ()
   luatexbase.add_to_callback(
  'process_input_buffer', 
  function (s)
     for i = 1, #first_occurence.table do
    if first_occurence.table[i][2] then
       local j =  find(s, 
               '[^%a]-' .. 
                  first_occurence.table[i][1] .. 
                  '[\n\t ,.:;!?]+')
       if j then
       -- The final 1 is to limit substitutions made to one.
          s = gsub(s, '[^%a]-' .. first_occurence.table[i][1] .. '[\n\t ,.:;!?]+','\\emph{%1}',1)
       first_occurence.table[i][2] = false
       end
    end
     end
     return s
  end,
  'replace_first_occurence')
end

function first_occurence.stop ()
   luatexbase.remove_from_callback(
  'process_input_buffer', 'replace_first_occurence')
end

return first_occurence

Then the tex file.

\documentclass{standalone}
\usepackage{luatexbase}

\directlua{dofile('first-occurence.lua')}

\def\startreplacefirstoccurence{%
  \directlua{first_occurence.start()}}

\def\stopreplacefirstoccurence{%
  \directlua{first_occurence.stop()}}

\def\addtoreplacefirstoccurence#1{%
  \directlua{first_occurence.add('\luatexluaescapestring{#1}')}}

\addtoreplacefirstoccurence{Test}
\addtoreplacefirstoccurence{foo}
\addtoreplacefirstoccurence{bar}
\begin{document}
Test 
\startreplacefirstoccurence
Test Test Test foobar foo bar 
\end{document}
share|improve this answer
    
I was pretty sure that LuaTeX could do something like that. :) –  egreg Apr 3 '12 at 20:48

I have a feeling I’m missing something crucial in understanding the question, but here’s a naïve approach, creating a new command sequence for every term:

\documentclass{article}
\def\term#1{%
  \ifcsname TERM#1\endcsname%
    #1%
  \else%
    \emph{#1}%
    \expandafter\gdef\csname TERM#1\endcsname{}%
  \fi}
\begin{document}
Lorem ispum \term{dolor} sit amet. Ipsum \term{dolor} sit amet.
Mauris \term{quis} enim facilisis orci porttitor iaculis eu vitae eros.
blah \term{quis} blah. One problem, though: \term{Quis} is a new term, eating
away the number of definitions possible.
\end{document}
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.