3

I am currently in the process of writing a comprehensive theoretical manual for my students. To make it easier to compile texts of varying difficulties for different groups of students, I also make heavy use of modes: These enable me to, say, exclude chapters that are intended for second-year-students from PDFs for first-year-students.

To make reading easier, I'm also using a lot of cross references (\in and \at). Unfortunately, that results in a problem, when a section that I'm referencing is excluded during compilation: Obviously, instead of the reference, the final PDF now shows something like "see chapter ??".

I would like to prevent that. Ideally, I would like to set up a new command that shows the full text of the reference only when the reference exists and is being included. Is that possible?

To make clearer what I'm talking about, here's a MWE (the advanced section might be excluded by compiling with context --mode=firstyear ...):

\defineblock[advanced]

\startmodeset
  [firstyear]  {\hideblocks[advanced]}
  [secondyear] {\keepblocks[advanced]}
  [default]    {\keepblocks[advanced]}
\stopmodeset

\def\condin#1#2{%
  % the text specified by #1 should be hidden,
  % when the reference #2 does not exist.
}


\starttext

\chapter{Testing Conditional Cross References}


\beginadvanced

\section[sec:advanced]{Advanced Section}

\input{knuth}

\endadvanced


\section[sec:intermediate]{Intermediate Section}

\input{knuth}


\section[sec:beginner]{Beginner Section}

This section explains the topic in beginner's terms
and refers to another chapter for more advanced details:
Please see \in{section}[sec:advanced] for more details.

This whole sentence should be excluded from the PDF,
when the references sec:advanced does not exist.

\stoptext

Any help would be much appreciated.

9
  • 1
    What is the desired output when mode firstyear is enabled? Simply omit the reference:Please see for more details. or omit the complete line?
    – Aditya
    Nov 28 '17 at 12:42
  • 1
    Does \doifreferencefoundelse do what you want?. The other option is to redefine \dummyreference to something other than ??.
    – Aditya
    Nov 28 '17 at 12:45
  • Yes, the intended output would be to omit the complete line, which is why I would probably define a new command, like \condin{sentence}{reference}. I didn't know that \doifreferencefoundelse exists, I will need to experiment with that. Thank you!
    – Marcus C.
    Nov 28 '17 at 13:11
  • I now tried \doifreferencefoundelse... what a pity that it's not documented too well. But it does exactly what I needed. Thank you very much! Would you like to post your comment as an answer so that I can accept it?
    – Marcus C.
    Nov 28 '17 at 13:20
  • 2
    Possible duplicate of How to test if a label exists
    – awiebe
    Mar 21 '18 at 23:05
3

ConTeXt provides a command \doifreferenceelse (which is a synonym for \doifelsereference), which has the following syntax:

\doifreferenceelse{name}{yes branch}{no branch}

This is similar to the other \doif...else macros.

0

Just in case, anybody is looking for a solution to a similar problem, I'm posting the code that I am using here.

First of all, thanks to @Aditya, who made me aware of the command \doifreferencefoundelse: This was the last building block that I needed. In a nutshell, I defined a new command \condref like this:

\startluacode
  userdata = userdata or {}

  function userdata.findreference(str)
    _, _, inreference = string.find(str, "\\in[^%[]*%[([^%]]+)%]")
    _, _, atreference = string.find(str, "\\at[^%[]*%[([^%]]+)%]")
    if inreference == nil then
      context(atreference)
    else
      context(inreference)
    end
  end
\stopluacode

\def\condref#1{%
  \doifreferencefoundelse{\ctxlua{userdata.findreference([[#1]])}}
    {#1}
    {}
}

This command calls some Lua code to extract the exact cross reference from argument #1 (as specified by \in{...}[...] or \at{...}[...]). Then \doifreferencefoundelse checks, whether the cross reference exists: If it does, the full code from argument #1 is included; if the cross reference is missing, however, the text is deleted (i.e. nothing is included). (This is the first time I'm writing Lua code, so I'd be happy, if somebody could help me make the code more efficient. E.g. I'm not sure, if there's an or construction available (like (in|at))?)

I can now use the command like this:

She took down a jar from one of the shelves as she passed; it was labelled
‘ORANGE MARMALADE’ \condref{\footnote{For more information about Orange
Marmelade, please refer to \in{section}[sec:marmalade].}}, but to her
great disappointment it was empty: she did not like to drop the jar for
fear of killing somebody, so managed to put it into one of the cupboards
as she fell past it.

If the section that's referenced by sec:marmalade exists, the whole footnote is included; if it doesn't (in my case this could happen due to the section being excluded by a compilation mode) the footnote is left out.

Hope that helps.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.