# ConTeXt: Prevent Reference Name Clashes in Floating Objects of Different Types

I find it very annoying that ConTeXt uses the same namespace for references of floating objects. In other words, if you give the same reference to a figure and a table, then you'd always refer to the one which was defined first, i.e. obvious clash of names. This is stupid from my point of view. On ConTeXt Wiki I've seen workarounds like \figure[figure:Your Reference], i.e. they propose to spam figure:, table: prefixes on all of your references, what I find quite annoying once again.

Here is what I want to do:

\let\corefigure\figure

\def
\figure{
\dosingleargument
\dofigure
}

\def
\dofigure[#1]{
\corefigure[figure:#1]
}


and

\let\corestartplacefigure\startplacefigure

\def
\startplacefigure{
\dotripleargument
\dostartplacefigure
}

\def
\dostartplacefigure[#1][#2][#3]{
# TODO: Somehow insert "figure:" into #1 after "reference="...
\corestartplacefigure[#1][#2][#3]
}


The same would go for table. So how to cleverly fulfill the TODO thingy?

Looking for suggestions and clarifications. Thanks.

-
Please: less drama, more useful information (i.e., full document showing your problem). –  Thomas May 11 '14 at 12:25
Post a complete minimal example. AFAIK, there is no core \figure macro. Is that supposed to be a replacement for \in? –  Aditya May 11 '14 at 15:47
@Aditya: \figure wraps \in when one uses \definereferenceformat[figure]. Anyway, I've managed to tailor a good solution, see my answer if you are interested. –  Alexander Shukaev May 13 '14 at 14:00

You can set a prefix for each float type with the referenceprefix key for the \setupcation command.

\setupexternalfigures[location=default]

\setupcaption[figure][referenceprefix=figure]
\setupcaption[table] [referenceprefix=table]

\starttext

\dorecurse{3}{\input knuth\par}

\startplacefigure[title=Test figure,reference=test]
\externalfigure[cow][width=4cm]
\stopplacefigure

\dorecurse{3}{\input zapf\par}

\startplacetable[title=Test table,reference=test]
\starttabulate[|l|l|]
\HL
\NC One \NC Two \NC\NR
\NC Three \NC Four \NC\NR
\HL
\stoptabulate
\stopplacetable

\dorecurse{3}{\input tufte\par}

\page

This documents contains a figure on \at{page}[figure:test] and a table on \at{page}[table:test].

\stoptext

-
Please post complete answers, not just fractions. –  Christian Hupfer May 11 '14 at 16:14
@ChristianHupfer as far as I can see this is a complete answer?! The code compiles fine and the first sentence explains the significant piece of code... –  clemens May 11 '14 at 18:47
@Christian Hupfer: Agreed, this answer was a good hint, but not complete. See my own answer for the complete solution if you are interested. –  Alexander Shukaev May 13 '14 at 13:53
This answer provides a complete answer of the question, as far as one could understand the question. I have started a bounty that I will award to this clear and succinct answer. –  Aditya May 13 '14 at 16:13
@Haroogan: The only question in your post was So how to cleverly fulfill the TODO thingy?. The post answers that. –  Aditya May 13 '14 at 19:58
\let\figure\corefigure

\def
\figure{


defines \figure twice, discarding the first definition to \corefigure, I suspect you intended the \let in the other direction to save the existing definition of \figure

 \let\corefigure\figure

-
@Haroogan as for latex questions on the site it would be far easier for anyone to answer if you posted a small complete document and said exactly what doesn't work with the posted document typos in posted code indicates the posted code isn't generating the problem described. I don't know context that well, but posting a working example helps whether it's context or latex or Fortran for that matter. –  David Carlisle May 11 '14 at 9:52

Although Metafox's answer provided a very good hint with referenceprefix, it was still only a half of the solution. Here I would like to provide full robust solution with explanations because there were some nasty pitfalls before I could piece it all together. I will present the solutions for figures, tables, and formulas, other floating objects will obey the same scheme. I'm sure some people will find it useful.

P.S. God bless you, bittermen, who down voted my question.

## Solution

So, the first things to define are captions:

\setupcaption
[figure][
style={small},
width={\textwidth},
align={middle},
location={bottom},
way={bysection},
prefix={yes},
prefixsegments={chapter:section},
referenceprefix={figure},
]

\setupcaption
[table][
style={small},
width={\textwidth},
align={right},
location={top},
way={bysection},
prefix={yes},
prefixsegments={chapter:section},
referenceprefix={table},
]

\setupformulas[
numberstyle={bold},
way={bysection},
prefix={yes},
prefixsegments={chapter:section},
referenceprefix={formula},
]


There are plenty of settings, but they are listed just for the sake of completeness. The important ones for our discussion are referenceprefix. Next, we define reference formats:

\definereferenceformat
[infigure]

\definereferenceformat
[intable]

\definereferenceformat
[informula][
left={(},
right={)},
]


Pay attention that I gave all of them a prefix in. This is important because in fact commands above have defined new macros: \infigure[...], \intable[...], \informula[...]. These will be our auxiliary macros, and we are not going to use them directly in our text!

Finally, we define our custom macros with friendly names: \figure[...], \table[...], \formula[...]:

\def
\figure{
\dosingleargument
\dofigure
}

\def
\dofigure[#1]{%
\leavevmode
\unskip
\infigure
[figure:#1]
\ignorespaces
\unskip
}

\def
\table{
\dosingleargument
\dotable
}

\def
\dotable[#1]{%
\leavevmode
\unskip
\intable
[table:#1]
\ignorespaces
\unskip
}

\def
\formula{
\dosingleargument
\doformula
}

\def
\doformula[#1]{%
\leavevmode
\unskip
\informula
[formula:#1]
\ignorespaces
\unskip
}


We are done. Now you can safely use \figure[...], \table[...], and \formula[...] in your text without fear of naming clash between different types of floating objects. Continue reading if you want to learn about pitfalls and how they were solved.

## Pitfalls

First, notice the percent sign (%) after \dofigure[#1]{ and brothers. This one prevents additional parasite space in front of references. Try to remove it and you'll see what I'm talking about.

Secondly, notice how \infigure[figure:#1] and brothers are wrapped into

\leavevmode
\unskip
...
\ignorespaces
\unskip


You can try to omit them to see yourself what's going to happen. You should notice weird spacing around all of your references: to be more specific, it seems like 2 additional parasite spaces are added around references. This is the problem that I've noticed on pure \in[...] macro wherever it is used, and on the ones defined with \definereferenceformat (like our auxiliary macros \infigure[...], \intable[...], \informula[...]) only if they are expanded inside other macros like our \figure[...], \table[...], and \formula[...].

You could say, "OK, why not try conventional way:"

\def
\dofigure[#1]{%
\infigure[figure:#1]%
}


The answer is that it will prevent only right parasite space, but one additional parasite space from the left will still remain. Therefore it is important to keep auxiliary macros wrapped into above construct to keep spacing around references being typeset correctly.

-
The space on the left is because you do not use % after the { in the first \def\figure{. You do not need all the \unskip and \ignorespaces. If you do not want to add % all over the code, look at \starttexdefinition, etc. –  Aditya May 13 '14 at 19:56