9

In a macro containing some conditions searching for existing macros that match a pattern, I have a combination of conditions that should be impossible. If the user mistakenly provides parameters that get them into this situation, I'd like the run to fail immediately with an error message. What's the easiest way to make this happen? I'm assuming there's a straightforward answer, but I'm coming up empty with a search – everything is about troubleshooting failed compiles.

I'm imagining something like:

\usepackage{etoolbox}

\newcommand*{\mycommand}[1]{% \ifcsdef{somecommandcontaining#1}{ \ifcsdef{someothercommandcontaining#1}{ valid condition 1, do something }{ %%%%% This combination of conditions is invalid %%%%% \failthisrun{Invalid parameter '#1'} }% }{% valid condition 2, do something else } }

3 Answers3

10

You can generate a latex formatted error with

\PackageError{mypackage}{Invalid parameter '#1'}{dont do that}

For a quick debugging error you can simply use \AnyUndefinedCommand (I use \ERROR typically) and it stops

David Carlisle
  • 757,742
9

In LaTeX you can use the macro \stop as a "panic button" for aborting compilation without having raised an error-message.

I suggest using the package l3msg of expl3 for raising (error-)messages and probably notifying about aborting before aborting compilation via \stop.

"probably" because I don't know what criteria you use to classify a compile/run as "failed" - whether it's enough that there was an error message, or whether there must have been a situation that lead to abortion of compilation.

If your LaTeX distribution is up to date (L3 programming layer <2021-05-18> or more recent), you can do something like this:

\ExplSyntaxOn
\prop_gput:Nnn \g_msg_module_type_prop { MYPREAMBLECODE } {}
\prop_gput:Nnn \g_msg_module_name_prop { MYPREAMBLECODE } {Preamble Code}
\msg_new:nnnn {MYPREAMBLECODE} 
              {Invalid Parameter}
              {Invalid~parameter~'#3'~as~#2~argument~of~macro~#1~\msg_line_context: .} 
              {Don't~pass~'#3'~as~#2~argument~of~macro~#1! }
\msg_new:nnnn {MYPREAMBLECODE} 
              {Abort compilation}
              {Compilation~is~aborted~now.} 
              {The~situation~really~is~weird!~Please~fix~the~reported~errors!}
\cs_new:Npn \InvalidParameterErrorStop #1 #2 #3 {
  % \msg_error:... etc turn their arguments into strings, but let's make sure
  % the control sequence token whose name is to be displayed is stringified with a
  % leading backslash regardless the current value of the \escapechar parameter:
  \exp_args:Nne \use:n  {
    \msg_error:nnnnn {MYPREAMBLECODE} {Invalid Parameter}
    %\msg_expandable_error:nnnnn {MYPREAMBLECODE} {Invalid Parameter}
  }{\iow_char:N \\\cs_to_str:N #1}{#2}{#3}
  % --- the following lines lead to aborting the LaTeX-run 
  %     after notifying about imminent abortion:
  \msg_note:nn {MYPREAMBLECODE} {Abort compilation}
  %\msg_expandable_note:nn {MYPREAMBLECODE} {Abort compilation}
  \stop
  % --------------------------------------------------------
}
\ExplSyntaxOff

\RequirePackage{etoolbox}

\newcommand*{\mycommand}[1]{% \ifcsdef{somecommandcontaining#1}{% \ifcsdef{someothercommandcontaining#1}{% valid condition 1, do something }{ %%%%% This combination of conditions is invalid %%%%% \InvalidParameterErrorStop{\mycommand}{first}{#1}% }% }{% valid condition 2, do something else }% }%

\newcommand\somecommandcontainingFooBar{This is defined.}

\documentclass{article}

\begin{document}

\mycommand{FooBar}

\end{document}

Output on terminal and in .log-file:

! Preamble Code Error: Invalid parameter 'FooBar' as first argument of macro
(Preamble Code)        \mycommand on line 49.

For immediate help type H <return>. ...

l.49 \mycommand{FooBar}

? H

Don't pass 'FooBar' as first argument of macro \mycommand!

?

Preamble Code Info: Compilation is aborted now.

Ulrich Diez
  • 28,770
  • \stop though does not signal a error it's more like a special form of \end{document} (your code implies this already by giving a error first, but "aborting" in your opening line might suggest an error exit – David Carlisle Jul 24 '22 at 21:43
  • @DavidCarlisle According to source2e.pdf \stop is a "panic button to stop LaTeX in the middle". It does not signal an error - that's why I suggested using l3msg for raising an error-message and a note about aborting compilation. – Ulrich Diez Jul 24 '22 at 21:47
  • yes sure as I say your code is fine, just the opening line. Quoting documentation is of course a cruel and unfair blow:-) – David Carlisle Jul 24 '22 at 21:49
  • @DavidCarlisle as I say your code is fine, just the opening line Really? Thanks! Code of mine seldom is fine. ... What a rhyme! I must be on a high... - I hope rhyming comes out better than quoting manuals. ;-) – Ulrich Diez Jul 24 '22 at 21:59
6

There is TeX primitive command \errmessage. For example:

\def\mycommand#1{%
   \ifcsname somecommandcontaining#1\endcsname
      \ifcsname someothercommandcontaining#1\endcsname
         valid condition 1, do something
      \else
         \errmessage{Invalid parameter "#1"}%
      \fi
   \else
      valid condition 2, do something else
   \fi
}
wipet
  • 74,238