% \iffalse meta-comment % %% File: l3msg.dtx Copyright (C) 2009-2011 The LaTeX3 Project %% %% It may be distributed and/or modified under the conditions of the %% LaTeX Project Public License (LPPL), either version 1.3c of this %% license or (at your option) any later version. The latest version %% of this license is in the file %% %% http://www.latex-project.org/lppl.txt %% %% This file is part of the "l3kernel bundle" (The Work in LPPL) %% and all files in that bundle must be distributed together. %% %% The released version of this bundle is available from CTAN. %% %% ----------------------------------------------------------------------- %% %% The development version of the bundle can be found at %% %% http://www.latex-project.org/svnroot/experimental/trunk/ %% %% for those people who are interested. %% %%%%%%%%%%% %% NOTE: %% %%%%%%%%%%% %% %% Snapshots taken from the repository represent work in progress and may %% not work or may contain conflicting material! We therefore ask %% people _not_ to put them into distributions, archives, etc. without %% prior consultation with the LaTeX3 Project. %% %% ----------------------------------------------------------------------- % %<*driver|package> \RequirePackage{l3names} \GetIdInfo$Id: l3msg.dtx 3086 2011-12-22 17:55:46Z bruno $ {L3 Experimental messages} % %<*driver> \documentclass[full]{l3doc} \begin{document} \DocInput{\jobname.dtx} \end{document} % % \fi % % \title{^^A % The \pkg{l3msg} package\\ Messages^^A % \thanks{This file describes v\ExplFileVersion, % last revised \ExplFileDate.}^^A % } % % \author{^^A % The \LaTeX3 Project\thanks % {^^A % E-mail: % \href{mailto:latex-team@latex-project.org} % {latex-team@latex-project.org}^^A % }^^A % } % % \date{Released \ExplFileDate} % % \maketitle % % \begin{documentation} % % Messages need to be passed to the user by modules, either when errors % occur or to indicate how the code is proceeding. The \pkg{l3msg} % module provides a consistent method for doing this (as opposed to % writing directly to the terminal or log). % % The system used by \pkg{l3msg} to create messages divides the process % into two distinct parts. Named messages are created in the first part % of the process; at this stage, no decision is made about the type of % output that the message will produce. The second part of the process % is actually producing a message. At this stage a choice of message % \emph{class} has to be made, for example \texttt{error}, % \texttt{warning} or \texttt{info}. % % By separating out the creation and use of messages, several benefits % are available. First, the messages can be altered later without % needing details of where they are used in the code. This makes it % possible to alter the language used, the detail level and so on. % Secondly, the output which results from a given message can be % altered. This can be done on a message class, module or message name % basis. In this way, message behaviour can be altered and messages can % be entirely suppressed. % % \section{Creating new messages} % % All messages have to be created before they can be used. All message % setting is local, with the general assumption that messages will % be managed as part of module set up outside of any \TeX{} grouping. % % The text of messages will automatically by wrapped to the length % available in the console. As a result, formatting is only needed % where it will help to show meaning. In particular, |\\| may be % used to force a new line and \verb*|\ | forces an explicit space. % % \begin{function}[updated = 2011-08-16]{\msg_new:nnnn, \msg_new:nnn} % \begin{syntax} % \cs{msg_new:nnnn} \Arg{module} \Arg{message} \Arg{text} \Arg{more text} % \end{syntax} % Creates a \meta{message} for a given \meta{module}. % The message will be defined to first give \meta{text} and then % \meta{more text} if the user requests it. If no \meta{more text} is % available then a standard text is given instead. Within \meta{text} % and \meta{more text} four parameters (|#1| to |#4|) can be used: % these will be supplied at the time the message is used. The % parameters will be expanded when the message is used. Within the % \meta{text} and \meta{more text} |\\| can be used to start a new % line. An error will be raised if the \meta{message} already exists. % \end{function} % % \begin{function}{\msg_set:nnnn, \msg_set:nnn, \msg_gset:nnnn, \msg_gset:nnn} % \begin{syntax} % \cs{msg_set:nnnn} \Arg{module} \Arg{message} \Arg{text} \Arg{more text} % \end{syntax} % Sets up the text for a \meta{message} for a given \meta{module}. % The message will be defined to first give \meta{text} and then % \meta{more text} if the user requests it. If no \meta{more text} is % available then a standard text is given instead. Within \meta{text} % and \meta{more text} four parameters (|#1| to |#4|) can be used: % these will be supplied at the time the message is used. The % parameters will be expanded when the message is used. Within the % \meta{text} and \meta{more text} |\\| can be used to start a new % line. % \end{function} % % \section{Contextual information for messages} % % \begin{function}[rEXP]{\msg_line_context:} % \begin{syntax} % \cs{msg_line_context:} % \end{syntax} % Prints the current line number when a message is given, and % thus suitable for giving context to messages. The number itself % is proceeded by the text |on line|. % \end{function} % % \begin{function}[EXP]{\msg_line_number:} % \begin{syntax} % \cs{msg_line_number:} % \end{syntax} % Prints the current line number when a message is given. % \end{function} % % \begin{variable}{\c_msg_return_text_tl} % Standard text to indicate that the user should try pressing % \meta{return} to continue. The standard definition reads: % \begin{verbatim} % Try typing to proceed. % % If that doesn't work, type X to quit. % \end{verbatim} % \end{variable} % % \begin{variable}{\c_msg_trouble_text_tl} % Standard text to indicate that the more errors are likely and % that aborting the run is advised. The standard definition reads: % \begin{verbatim} % More errors will almost certainly follow: % the LaTeX run should be aborted. % \end{verbatim} % \end{variable} % % \begin{function}[EXP]{\msg_fatal_text:n} % \begin{syntax} % \cs{msg_fatal_text:n} \Arg{module} % \end{syntax} % Produces the standard text: % \begin{verbatim} % Fatal error % \end{verbatim} % This function can be redefined to alter the language in which the % message is give, using |#1| as the name of the \meta{module} to % be included. % \end{function} % % \begin{function}[EXP]{\msg_critical_text:n} % \begin{syntax} % \cs{msg_critical_text:n} \Arg{module} % \end{syntax} % Produces the standard text: % \begin{verbatim} % Critical error % \end{verbatim} % This function can be redefined to alter the language in which the % message is give, using |#1| as the name of the \meta{module} to % be included. % \end{function} % % \begin{function}[EXP]{\msg_error_text:n} % \begin{syntax} % \cs{msg_error_text:n} \Arg{module} % \end{syntax} % Produces the standard text: % \begin{verbatim} % error % \end{verbatim} % This function can be redefined to alter the language in which the % message is give, using |#1| as the name of the \meta{module} to % be included. % \end{function} % % \begin{function}[EXP]{\msg_warning_text:n} % \begin{syntax} % \cs{msg_warning_text:n} \Arg{module} % \end{syntax} % Produces the standard text: % \begin{verbatim} % warning % \end{verbatim} % This function can be redefined to alter the language in which the % message is give, using |#1| as the name of the \meta{module} to % be included. % \end{function} % % \begin{function}[EXP]{\msg_info_text:n} % \begin{syntax} % \cs{msg_info_text:n} \Arg{module} % \end{syntax} % Produces the standard text: % \begin{verbatim} % info % \end{verbatim} % This function can be redefined to alter the language in which the % message is give, using |#1| as the name of the \meta{module} to % be included. % \end{function} % % \section{Issuing messages} % % Messages behave differently depending on the message class. A number % of standard message classes are supplied, but more can be % created. % % When issuing messages, any arguments passed should use % \cs{tl_to_str:n} or \cs{token_to_str:N} to prevent unwanted expansion % of the material. % % \begin{function}{\msg_class_set:nn} % \begin{syntax} % \cs{msg_class_set:nn} \Arg{class} \Arg{code} % \end{syntax} % Sets a \meta{class} to output a message, using \meta{code} % to process the message text. The \meta{class} should be a text % value, while the \meta{code} may be any arbitrary material. % The \meta{code} will receive $6$ arguments: the module % name (|#1|), the message name (|#2|) and the four arguments % taken by the message text (|#3| to |#6|). % \end{function} % % The kernel defines several common message classes. The following % describes the standard behaviour of each class if no redirection of % the class or message is active. In all cases, the message may be % issued supplying $0$ to $4$ arguments. The code will % ensure that there an no errors if the number of arguments supplied % here does not match the number in the definition of the message % (although of course the sense of the message may be impaired). % % \begin{function} % { % \msg_fatal:nnxxxx , % \msg_fatal:nnxxx , % \msg_fatal:nnxx , % \msg_fatal:nnx , % \msg_fatal:nn % } % \begin{syntax} % \cs{msg_fatal:nnxxxx} \Arg{module} \Arg{message} \Arg{arg one} % ~~\Arg{arg two} \Arg{arg three} \Arg{arg four} % \end{syntax} % Issues \meta{module} error \meta{message}, passing \meta{arg one} to % \meta{arg four} to the text-creating functions. After issuing a % fatal error the \TeX{} run will halt. % \end{function} % % \begin{function} % { % \msg_critical:nnxxxx , % \msg_critical:nnxxx , % \msg_critical:nnxx , % \msg_critical:nnx , % \msg_critical:nn % } % \begin{syntax} % \cs{msg_critical:nnxxxx} \Arg{module} \Arg{message} \Arg{arg one} % ~~\Arg{arg two} \Arg{arg three} \Arg{arg four} % \end{syntax} % Issues \meta{module} error \meta{message}, passing \meta{arg one} to % \meta{arg four} to the text-creating functions. After issuing the % message reading the current input file will stop. This may halt % the \TeX{} run (if the current file is the main file) or % may abort reading a sub-file. % \end{function} % % \begin{function} % { % \msg_error:nnxxxx , % \msg_error:nnxxx , % \msg_error:nnxx , % \msg_error:nnx , % \msg_error:nn % } % \begin{syntax} % \cs{msg_error:nnxxxx} \Arg{module} \Arg{message} \Arg{arg one} % ~~\Arg{arg two} \Arg{arg three} \Arg{arg four} % \end{syntax} % Issues \meta{module} error \meta{message}, passing \meta{arg one} to % \meta{arg four} to the text-creating functions. The error will % stop processing and issue the text at the terminal. After user input, % the run will continue. % \end{function} % % \begin{function} % { % \msg_warning:nnxxxx , % \msg_warning:nnxxx , % \msg_warning:nnxx , % \msg_warning:nnx , % \msg_warning:nn % } % \begin{syntax} % \cs{msg_warning:nnxxxx} \Arg{module} \Arg{message} \Arg{arg one} % ~~\Arg{arg two} \Arg{arg three} \Arg{arg four} % \end{syntax} % Issues \meta{module} warning \meta{message}, passing \meta{arg one} to % \meta{arg four} to the text-creating functions. The warning text % will be added to the log file, but the \TeX{} run will not be % interrupted. % \end{function} % % \begin{function} % { % \msg_info:nnxxxx , % \msg_info:nnxxx , % \msg_info:nnxx , % \msg_info:nnx , % \msg_info:nn % } % \begin{syntax} % \cs{msg_info:nnxxxx} \Arg{module} \Arg{message} \Arg{arg one} % ~~\Arg{arg two} \Arg{arg three} \Arg{arg four} % \end{syntax} % Issues \meta{module} information \meta{message}, passing % \meta{arg one} to \meta{arg four} to the text-creating functions. % The information text will be added to the log file. % \end{function} % % \begin{function} % { % \msg_log:nnxxxx , % \msg_log:nnxxx , % \msg_log:nnxx , % \msg_log:nnx , % \msg_log:nn % } % \begin{syntax} % \cs{msg_log:nnxxxx} \Arg{module} \Arg{message} \Arg{arg one} % ~~\Arg{arg two} \Arg{arg three} \Arg{arg four} % \end{syntax} % Issues \meta{module} information \meta{message}, passing % \meta{arg one} to \meta{arg four} to the text-creating functions. % The information text will be added to the log file: the output % is briefer than \cs{msg_info:nnxxxx}. % \end{function} % % \begin{function} % { % \msg_none:nnxxxx , % \msg_none:nnxxx , % \msg_none:nnxx , % \msg_none:nnx , % \msg_none:nn % } % \begin{syntax} % \cs{msg_none:nnxxxx} \Arg{module} \Arg{message} \Arg{arg one} % ~~\Arg{arg two} \Arg{arg three} \Arg{arg four} % \end{syntax} % Does nothing: used as a message class to prevent any output at % all (see the discussion of message redirection). % \end{function} % % \section{Redirecting messages} % % Each message has a \enquote{name}, which can be used to alter the behaviour % of the message when it is given. Thus we might have % \begin{verbatim} % \msg_new:nnnn { module } { my-message } { Some~text } { Some~more~text } % \end{verbatim} % to define a message, with % \begin{verbatim} % \msg_error:nn { module } { my-message } % \end{verbatim} % when it is used. With no filtering, this will raise an error. However, we % could alter the behaviour with % \begin{verbatim} % \msg_redirect_class:nn { error } { warning } % \end{verbatim} % to turn all errors into warnings, or with % \begin{verbatim} % \msg_redirect_module:nnn { module } { error } { warning } % \end{verbatim} % to alter just those messages for module, or even % \begin{verbatim} % \msg_redirect_name:nnn { module } { my-message } { warning } % \end{verbatim} % to target just one message. % % \begin{function}{\msg_redirect_class:nn} % \begin{syntax} % \cs{msg_redirect_class:nn} \Arg{class one} \Arg{class two} % \end{syntax} % Changes the behaviour of messages of \meta{class one} so that they % are processed using the code for those of \meta{class two}. Multiple % redirections are possible. Redirection to a missing class or % infinite loops will raise errors when the messages are used, % rather than at the point of redirection. % \end{function} % % \begin{function}{\msg_redirect_module:nnn} % \begin{syntax} % \cs{msg_redirect_module:nnn} \Arg{module} \Arg{class one} \Arg{class two} % \end{syntax} % Redirects message of \meta{class one} for \meta{module} to act as % though they were from \meta{class two}. Messages of \meta{class one} % from sources other than \meta{module} are not affected by this % redirection. This function can be used to make some messages % \enquote{silent} by default. For example, all of the % \texttt{trace} messages of \meta{module} could be turned off with: % \begin{verbatim} % \msg_redirect_module:nnn { module } { trace } { none } % \end{verbatim} % \end{function} % % \begin{function}{\msg_redirect_name:nnn} % \begin{syntax} % \cs{msg_redirect_name:nn} \Arg{module} \Arg{message} \Arg{class} % \end{syntax} % Redirects a specific \meta{message} from a specific \meta{module} % to act as a member of \meta{class} of messages. This function can % be used to make a selected message \enquote{silent} without % changing global parameters: % \begin{verbatim} % \msg_redirect_name:nnn { module } { annoying-message } { none } % \end{verbatim} % \end{function} % % \section{Low-level message functions} % % The lower-level message functions should usually be accessed from the % higher-level system. However, there are occasions where direct % access to these functions is desirable. % % \begin{function}[EXP]{\msg_newline:, \msg_two_newlines:} % \begin{syntax} % \cs{msg_newline:} % \end{syntax} % Forces a new line in a message. This is a low-level function, which % will not include any additional printing information in the message: % contrast with |\\| in messages. The |two| version adds two lines. % \end{function} % % \begin{function}{\msg_interrupt:xxx} % \begin{syntax} % \cs{msg_interrupt:xxx} \Arg{first line} \Arg{text} \Arg{extra text} % \end{syntax} % Interrupts the \TeX{} run, issuing a formatted message comprising % \meta{first line} and \meta{text} laid out in the format % \begin{verbatim} % !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! % ! % ! % ! % ! % !............................................... % \end{verbatim} % where the \meta{text} will be wrapped to fit within the current % line length. The user may then request more information, at which % stage the \meta{extra text} will be shown in the terminal in the % format % \begin{verbatim} % |''''''''''''''''''''''''''''''''''''''''''''''' % | % |............................................... % \end{verbatim} % where the \meta{extra text} will be wrapped to fit within the current % line length. % \end{function} % % \begin{function}{\msg_log:x} % \begin{syntax} % \cs{msg_log:x} \Arg{text} % \end{syntax} % Writes to the log file with the \meta{text} laid out in the format % \begin{verbatim} % ................................................. % . % ................................................. % \end{verbatim} % where the \meta{text} will be wrapped to fit within the current % line length. % \end{function} % % \begin{function}{\msg_term:x} % \begin{syntax} % \cs{msg_term:x} \Arg{text} % \end{syntax} % Writes to the terminal and log file with the \meta{text} laid out in the % format % \begin{verbatim} % ************************************************* % * % ************************************************* % \end{verbatim} % where the \meta{text} will be wrapped to fit within the current % line length. % \end{function} % % \section{Kernel-specific functions} % % Messages from \LaTeX3 itself are handled by the general message system, % but have their own functions. This allows some text to be pre-defined, % and also ensures that serious errors can be handled properly. % % \begin{function}[updated = 2011-08-16] % {\msg_kernel_new:nnnn, \msg_kernel_new:nnn} % \begin{syntax} % \cs{msg_kernel_new:nnnn} \Arg{module} \Arg{message} \Arg{text} \Arg{more text} % \end{syntax} % Creates a kernel \meta{message} for a given \meta{module}. % The message will be defined to first give \meta{text} and then % \meta{more text} if the user requests it. If no \meta{more text} is % available then a standard text is given instead. Within \meta{text} % and \meta{more text} four parameters (|#1| to |#4|) can be used: % these will be supplied at the time the message is used. The % parameters will be expanded when the message is used. Within the % \meta{text} and \meta{more text} |\\| can be used to start a new % line. An error will be raised if the \meta{message} already exists. % \end{function} % % \begin{function}{\msg_kernel_set:nnnn, \msg_kernel_set:nnn} % \begin{syntax} % \cs{msg_kernel_set:nnnn} \Arg{module} \Arg{message} \Arg{text} \Arg{more text} % \end{syntax} % Sets up the text for a kernel \meta{message} for a given \meta{module}. % The message will be defined to first give \meta{text} and then % \meta{more text} if the user requests it. If no \meta{more text} is % available then a standard text is given instead. Within \meta{text} % and \meta{more text} four parameters (|#1| to |#4|) can be used: % these will be supplied at the time the message is used. The % parameters will be expanded when the message is used. Within the % \meta{text} and \meta{more text} |\\| can be used to start a new % line. % \end{function} % % \begin{function} % { % \msg_kernel_fatal:nnxxxx , % \msg_kernel_fatal:nnxxx , % \msg_kernel_fatal:nnxx , % \msg_kernel_fatal:nnx , % \msg_kernel_fatal:nn % } % \begin{syntax} % \cs{msg_kernel_fatal:nnxxxx} \Arg{module} \Arg{message} \Arg{arg one} % ~~\Arg{arg two} \Arg{arg three} \Arg{arg four} % \end{syntax} % Issues kernel \meta{module} error \meta{message}, passing \meta{arg one} % to \meta{arg four} to the text-creating functions. After issuing a % fatal error the \TeX{} run will halt. Cannot be redirected. % \end{function} % % \begin{function} % { % \msg_kernel_error:nnxxxx , % \msg_kernel_error:nnxxx , % \msg_kernel_error:nnxx , % \msg_kernel_error:nnx , % \msg_kernel_error:nn % } % \begin{syntax} % \cs{msg_kernel_error:nnxxxx} \Arg{module} \Arg{message} \Arg{arg one} % ~~\Arg{arg two} \Arg{arg three} \Arg{arg four} % \end{syntax} % Issues kernel \meta{module} error \meta{message}, passing \meta{arg one} % to % \meta{arg four} to the text-creating functions. The error will % stop processing and issue the text at the terminal. After user input, % the run will continue. Cannot be redirected. % \end{function} % % \begin{function} % { % \msg_kernel_warning:nnxxxx , % \msg_kernel_warning:nnxxx , % \msg_kernel_warning:nnxx , % \msg_kernel_warning:nnx , % \msg_kernel_warning:nn % } % \begin{syntax} % \cs{msg_kernel_warning:nnxxxx} \Arg{module} \Arg{message} \Arg{arg one} % ~~\Arg{arg two} \Arg{arg three} \Arg{arg four} % \end{syntax} % Issues kernel \meta{module} warning \meta{message}, passing % \meta{arg one} to % \meta{arg four} to the text-creating functions. The warning text % will be added to the log file, but the \TeX{} run will not be % interrupted. % \end{function} % % \begin{function} % { % \msg_kernel_info:nnxxxx , % \msg_kernel_info:nnxxx , % \msg_kernel_info:nnxx , % \msg_kernel_info:nnx , % \msg_kernel_info:nn % } % \begin{syntax} % \cs{msg_kernel_info:nnxxxx} \Arg{module} \Arg{message} \Arg{arg one} % ~~\Arg{arg two} \Arg{arg three} \Arg{arg four} % \end{syntax} % Issues kernel \meta{module} information \meta{message}, passing % \meta{arg one} to \meta{arg four} to the text-creating functions. % The information text will be added to the log file. % \end{function} % % \section{Expandable errors} % % In a few places, the \LaTeX3 kernel needs to produce errors in an % expansion only context. This must be handled internally very % differently from normal error messages, as none of the tools % to print to the terminal or the log file are expandable. % However, the interface is similar. % % \begin{function}[EXP, added = 2011-11-23] % { % \msg_expandable_kernel_error:nnnnnn, % \msg_expandable_kernel_error:nnnnn, % \msg_expandable_kernel_error:nnnn, % \msg_expandable_kernel_error:nnn, % \msg_expandable_kernel_error:nn % } % \begin{syntax} % \cs{msg_expandable_kernel_error:nnnnnn} \Arg{module} \Arg{message} % ~~\Arg{arg one} \Arg{arg two} \Arg{arg three} \Arg{arg four} % \end{syntax} % Issues an error, passing \meta{arg one} to \meta{arg four} % to the text-creating functions. The resulting string must % be shorter than a line, otherwise it will be cropped. % \end{function} % % \begin{function}[EXP, added = 2011-08-11, updated = 2011-08-13] % {\msg_expandable_error:n} % \begin{syntax} % \cs{msg_expandable_error:n} \Arg{error message} % \end{syntax} % Issues an \enquote{Undefined error} message from \TeX{} itself, % and prints the \meta{error message}. The \meta{error message} % must be short: it is cropped at the end of one line. % \begin{texnote} % This function expands to an empty token list after two steps. % Tokens inserted in response to \TeX{}'s prompt are read with % the current category code setting, and inserted just after % the place where the error message was issued. % \end{texnote} % \end{function} % % \section{Internal \pkg{l3msg} functions} % % The following functions are used in several kernel modules. % % \begin{function}{\msg_aux_use:nn, \msg_aux_use:nnxxxx} % \begin{syntax} % \cs{msg_aux_use:nnxx} \Arg{module} \Arg{message} % ~~\Arg{arg one} \Arg{arg two} \Arg{arg three} \Arg{arg four} % \end{syntax} % Prints the \meta{message} from \meta{module} in the terminal, % without formatting. % \end{function} % % \begin{function}{\msg_aux_show:x} % \begin{syntax} % \cs{msg_aux_show:x} \Arg{formatted string} % \end{syntax} % Shows the \meta{formatted string} on the terminal. % The \meta{formatted string} must start with |^^J>|, % failure to do so causes low-level \TeX{} errors. % \end{function} % % \begin{function}{\msg_aux_show:Nnx} % \begin{syntax} % \cs{msg_aux_show:Nnx} \meta{variable} \Arg{module} \Arg{token list} % \end{syntax} % Auxiliary common to \pkg{l3clist}, \pkg{l3prop} and \pkg{seq}, % which displays an appropriate message and the contents of the variable. % \end{function} % % \end{documentation} % % \begin{implementation} % % \section{\pkg{l3msg} implementation} % % \begin{macrocode} %<*initex|package> % \end{macrocode} % % \begin{macrocode} %<*package> \ProvidesExplPackage {\ExplFileName}{\ExplFileDate}{\ExplFileVersion}{\ExplFileDescription} \package_check_loaded_expl: % % \end{macrocode} % % \begin{variable}{\l_msg_tmp_tl} % A general scratch for the module. % \begin{macrocode} \tl_new:N \l_msg_tmp_tl % \end{macrocode} % \end{variable} % % \subsection{Creating messages} % % Messages are created and used separately, so there two parts to % the code here. First, a mechanism for creating message text. % This is pretty simple, as there is not actually a lot to do. % %\begin{variable}{\c_msg_text_prefix_tl, \c_msg_more_text_prefix_tl} % Locations for the text of messages. % \begin{macrocode} \tl_const:Nn \c_msg_text_prefix_tl { msg~text~>~ } \tl_const:Nn \c_msg_more_text_prefix_tl { msg~extra~text~>~ } % \end{macrocode} % \end{variable} % % \begin{macro}{\msg_new:nnnn, \msg_new:nnn} % \begin{macro}{\msg_gset:nnnn,\msg_gset:nnn} % \begin{macro}{\msg_set:nnnn, \msg_set:nnn} % Setting a message simply means saving the appropriate text % into two functions. A sanity check first. % \begin{macrocode} \cs_new_protected:Npn \msg_new:nnnn #1#2 { \cs_if_exist:cT { \c_msg_text_prefix_tl #1 / #2 } { \msg_kernel_error:nnxx { msg } { message-already-defined } {#1} {#2} } \msg_gset:nnnn {#1} {#2} } \cs_new_protected:Npn \msg_new:nnn #1#2#3 { \msg_new:nnnn {#1} {#2} {#3} { } } \cs_new_protected:Npn \msg_set:nnnn #1#2#3#4 { \cs_set:cpn { \c_msg_text_prefix_tl #1 / #2 } ##1##2##3##4 {#3} \cs_set:cpn { \c_msg_more_text_prefix_tl #1 / #2 } ##1##2##3##4 {#4} } \cs_new_protected:Npn \msg_set:nnn #1#2#3 { \msg_set:nnnn {#1} {#2} {#3} { } } \cs_new_protected:Npn \msg_gset:nnnn #1#2#3#4 { \cs_gset:cpn { \c_msg_text_prefix_tl #1 / #2 } ##1##2##3##4 {#3} \cs_gset:cpn { \c_msg_more_text_prefix_tl #1 / #2 } ##1##2##3##4 {#4} } \cs_new_protected:Npn \msg_gset:nnn #1#2#3 { \msg_gset:nnnn {#1} {#2} {#3} { } } % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % % \subsection{Messages: support functions and text} % % \begin{variable} % { % \c_msg_coding_error_text_tl , % \c_msg_continue_text_tl , % \c_msg_critical_text_tl , % \c_msg_fatal_text_tl , % \c_msg_help_text_tl , % \c_msg_no_info_text_tl , % \c_msg_on_line_tl , % \c_msg_return_text_tl , % \c_msg_trouble_text_tl % } % Simple pieces of text for messages. % \begin{macrocode} \tl_const:Nn \c_msg_coding_error_text_tl { This~is~a~coding~error. \\ \\ } \tl_const:Nn \c_msg_continue_text_tl { Type~~to~continue } \tl_const:Nn \c_msg_critical_text_tl { Reading~the~current~file~will~stop } \tl_const:Nn \c_msg_fatal_text_tl { This~is~a~fatal~error:~LaTeX~will~abort } \tl_const:Nn \c_msg_help_text_tl { For~immediate~help~type~H~ } \tl_const:Nn \c_msg_no_info_text_tl { LaTeX~does~not~know~anything~more~about~this~error,~sorry. \c_msg_return_text_tl } \tl_const:Nn \c_msg_on_line_text_tl { on~line } \tl_const:Nn \c_msg_return_text_tl { \\ \\ Try~typing~~to~proceed. \\ If~that~doesn't~work,~type~X~~to~quit. } \tl_const:Nn \c_msg_trouble_text_tl { \\ \\ More~errors~will~almost~certainly~follow: \\ the~LaTeX~run~should~be~aborted. } % \end{macrocode} % \end{variable} % % \begin{macro}{\msg_newline:, \msg_two_newlines:} % New lines are printed in the same way as for low-level file writing. % \begin{macrocode} \cs_new_nopar:Npn \msg_newline: { ^^J } \cs_new_nopar:Npn \msg_two_newlines: { ^^J ^^J } % \end{macrocode} % \end{macro} % % \begin{macro}{\msg_line_number:} % \begin{macro}{\msg_line_context:} % For writing the line number nicely. % \begin{macrocode} \cs_new_nopar:Npn \msg_line_number: { \int_use:N \tex_inputlineno:D } \cs_set_nopar:Npn \msg_line_context: { \c_msg_on_line_text_tl \c_space_tl \msg_line_number: } % \end{macrocode} % \end{macro} % \end{macro} % % \subsection{Showing messages: low level mechanism} % % \begin{variable}{\c_msg_hide_tl} % \begin{variable}{\c_msg_hide_tl} % An empty variable with a number of (category code 11) periods at the % end of its name. This is used to push the \TeX{} part of an error % message \enquote{off the screen}. Using two variables here means that % later life is a little easier. % \begin{macrocode} \char_set_catcode_letter:N \. \tl_new:N \c_msg_hide_tl.......................................................... \tl_const:Nn \c_msg_hide_tl { \c_msg_hide_tl.......................................................... } \char_set_catcode_other:N \. % \end{macrocode} % \end{variable} % \end{variable} % % \begin{variable}{\l_msg_text_tl} % For wrapping message text. % \begin{macrocode} \tl_new:N \l_msg_text_tl % \end{macrocode} %\end{variable} % % \begin{macro}{\msg_interrupt:xxx} % \begin{macro}[aux]{\msg_interrupt_no_details:xx} % \begin{macro}[aux]{\msg_interrupt_details:xxx} % \begin{macro}[aux]{\msg_interrupt_text:n} % \begin{macro}[aux]{\msg_interrupt_more_text:n} % \begin{macro}[aux]{\msg_interrupt_aux:} % The low-level interruption macro is rather opaque, unfortunately. The % idea here is to create a a message which hides all of \TeX{}'s own % information by filling the output up with dots. To achieve this, % dots have to be letters. The odd % \cs{c_msg_hide_tl} actually does the hiding: it is the % large run of dots in the name that is important here. The meaning % of |\\| is altered so that the explanation text is a simple run % whilst the initial error has line-continuation shown. % \begin{macrocode} \cs_new_protected:Npn \msg_interrupt:xxx #1#2#3 { \group_begin: \tl_if_empty:nTF {#3} { \msg_interrupt_no_details:xx {#1} {#2} } { \msg_interrupt_details:xxx {#1} {#2} {#3} } \msg_interrupt_aux: \group_end: } % \end{macrocode} % Depending on the availability of more information there is a choice of % how to set up the further help. The extra help text has to be set % before the message itself can be issued. Everything is done using % \texttt{x}-type expansion as the new line markers are different for % the two type of text and need to be correctly set up. % \begin{macrocode} \cs_new_protected:Npn \msg_interrupt_no_details:xx #1#2 { \iow_wrap:xnnnN { \\ \c_msg_no_info_text_tl } { |~ } { 2 } { } \msg_interrupt_more_text:n \iow_wrap:xnnnN { #1 \\ \\ #2 \\ \\ \c_msg_continue_text_tl } { ! ~ } { 2 } {} \msg_interrupt_text:n } \cs_new_protected:Npn \msg_interrupt_details:xxx #1#2#3 { \iow_wrap:xnnnN { \\ #3 } { |~ } { 2 } { } \msg_interrupt_more_text:n \iow_wrap:xnnnN { #1 \\ \\ #2 \\ \\ \c_msg_help_text_tl } { ! ~ } { 2 } { } \msg_interrupt_text:n } \cs_new_protected:Npn \msg_interrupt_text:n #1 { \tl_set:Nn \l_msg_text_tl {#1} } \cs_new_protected:Npn \msg_interrupt_more_text:n #1 { %<*initex> \tl_set:Nx \l_msg_tmp_tl % %<*package> \protected@edef \l_msg_tmp_tl % { |''''''''''''''''''''''''''''''''''''''''''''''' #1 \msg_newline: |............................................... } \tex_errhelp:D \exp_after:wN { \l_msg_tmp_tl } } % \end{macrocode} % The business end of the process starts by producing some visual % separation of the message from the main part of the log. It then % adds the hiding text to the message to print. The error message needs % to be printed with everything made \enquote{invisible}: this is where % the strange business with |&| comes in: this is made into another % |!|. There is also a closing brace that will show up in the output, % which is turned into a blank space. % \begin{macrocode} \group_begin: % { \char_set_lccode:nn {`\}} {`\ } \char_set_lccode:nn {`\&} {`\!} \char_set_catcode_active:N \& \tl_to_lowercase:n { \group_end: \cs_new_protected:Npn \msg_interrupt_aux: { \iow_term:x { \iow_newline: !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! \iow_newline: ! } \tl_put_right:No \l_msg_text_tl { \c_msg_hide_tl } \cs_set_protected_nopar:Npx & { \tex_errmessage:D { \exp_not:o { \l_msg_text_tl } } } & } } % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\msg_log:x} % \begin{macro}{\msg_term:x} % Printing to the log or terminal without a stop is rather easier. % A bit of simple visual work sets things off nicely. % \begin{macrocode} \cs_new_protected:Npn \msg_log:x #1 { \iow_log:x { ................................................. } \iow_wrap:xnnnN { . ~ #1} { . ~ } { 2 } { } \iow_log:x \iow_log:x { ................................................. } } \cs_new_protected:Npn \msg_term:x #1 { \iow_term:x { ************************************************* } \iow_wrap:xnnnN { * ~ #1} { * ~ } { 2 } { } \iow_term:x \iow_term:x { ************************************************* } } % \end{macrocode} % \end{macro} % \end{macro} % \subsection{Displaying messages} % % \LaTeX{} is handling error messages and so the \TeX{} ones are disabled. % \begin{macrocode} \int_set:Nn \tex_errorcontextlines:D { -1 } % \end{macrocode} % % \begin{macro} % { % \msg_fatal_text:n , % \msg_critical_text:n , % \msg_error_text:n , % \msg_warning_text:n , % \msg_info_text:n % } % A function for issuing messages: both the text and order could % in principal vary. % \begin{macrocode} \cs_new:Npn \msg_fatal_text:n #1 { Fatal~#1~error } \cs_new:Npn \msg_critical_text:n #1 { Critical~#1~error } \cs_new:Npn \msg_error_text:n #1 { #1~error } \cs_new:Npn \msg_warning_text:n #1 { #1~warning } \cs_new:Npn \msg_info_text:n #1 { #1~info } % \end{macrocode} % \end{macro} % % \begin{macro}{\msg_see_documentation_text:n} % Contextual footer information. % \begin{macrocode} \cs_new:Npn \msg_see_documentation_text:n #1 { \\ \\ See~the~#1~documentation~for~further~information. } % \end{macrocode} % \end{macro} % % \begin{variable}{\l_msg_redirect_classes_prop, \l_msg_redirect_names_prop} % For filtering messages, a list of all messages and of those which have % to be modified is required. % \begin{macrocode} \prop_new:N \l_msg_redirect_classes_prop \prop_new:N \l_msg_redirect_names_prop % \end{macrocode} % \end{variable} % % \begin{macro}{\msg_class_set:nn} % Setting up a message class does two tasks. Any existing redirection % is cleared, and the various message functions are created % to simply use the code stored for the message. % \begin{macrocode} \cs_new_protected:Npn \msg_class_set:nn #1#2 { \prop_clear_new:c { l_msg_redirect_ #1 _prop } \cs_set_protected:cpn { msg_ #1 :nnxxxx } ##1##2##3##4##5##6 { \msg_use:nnnnxxxx {#1} {#2} {##1} {##2} {##3} {##4} {##5} {##6} } \cs_set_protected:cpx { msg_ #1 :nnxxx } ##1##2##3##4##5 { \exp_not:c { msg_ #1 :nnxxxx } {##1} {##2} {##3} {##4} {##5} { } } \cs_set_protected:cpx { msg_ #1 :nnxx } ##1##2##3##4 { \exp_not:c { msg_ #1 :nnxxxx } {##1} {##2} {##3} {##4} { } { } } \cs_set_protected:cpx { msg_ #1 :nnx } ##1##2##3 { \exp_not:c { msg_ #1 :nnxxxx } {##1} {##2} {##3} { } { } { } } \cs_set_protected:cpx { msg_ #1 :nn } ##1##2 { \exp_not:c { msg_ #1 :nnxxxx } {##1} {##2} { } { } { } { } } } % \end{macrocode} % \end{macro} % % \begin{macro}[pTF]{\msg_if_more_text:N, \msg_if_more_text:c} % \begin{macro}[aux]{\msg_no_more_text:xxxx} % A test to see if any more text is available, using a % permanently-empty text function. % \begin{macrocode} \prg_set_conditional:Npnn \msg_if_more_text:N #1 { p , T , F , TF } { \cs_if_eq:NNTF #1 \msg_no_more_text:xxxx { \prg_return_false: } { \prg_return_true: } } \cs_new:Npn \msg_no_more_text:xxxx #1#2#3#4 { } \cs_generate_variant:Nn \msg_if_more_text_p:N { c } \cs_generate_variant:Nn \msg_if_more_text:NT { c } \cs_generate_variant:Nn \msg_if_more_text:NF { c } \cs_generate_variant:Nn \msg_if_more_text:NTF { c } % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro} % { % \msg_fatal:nnxxxx , % \msg_fatal:nnxxx , % \msg_fatal:nnxx , % \msg_fatal:nnx , % \msg_fatal:nn % } % For fatal errors, after the error message \TeX{} bails out. % \begin{macrocode} \msg_class_set:nn { fatal } { \msg_interrupt:xxx { \msg_fatal_text:n {#1} : ~ "#2" } { \use:c { \c_msg_text_prefix_tl #1 / #2 } {#3} {#4} {#5} {#6} \msg_see_documentation_text:n {#1} } { \c_msg_fatal_text_tl } \tex_end:D } % \end{macrocode} % \end{macro} % % \begin{macro} % { % \msg_critical:nnxxxx , % \msg_critical:nnxxx , % \msg_critical:nnxx , % \msg_critical:nnx , % \msg_critical:nn % } % Not quite so bad: just end the current file. % \begin{macrocode} \msg_class_set:nn { critical } { \msg_interrupt:xxx { \msg_critical_text:n {#1} : ~ "#2" } { \use:c { \c_msg_text_prefix_tl #1 / #2 } {#3} {#4} {#5} {#6} \msg_see_documentation_text:n {#1} } { \c_msg_critical_text_tl } \tex_endinput:D } % \end{macrocode} % \end{macro} % % \begin{macro} % { % \msg_error:nnxxxx , % \msg_error:nnxxx , % \msg_error:nnxx , % \msg_error:nnx , % \msg_error:nn % } % For an error, the interrupt routine is called, then any recovery code % is tried. % \begin{macrocode} \msg_class_set:nn { error } { \msg_if_more_text:cTF { \c_msg_more_text_prefix_tl #1 / #2 } { \msg_interrupt:xxx { \msg_error_text:n {#1} : ~ "#2" } { \use:c { \c_msg_text_prefix_tl #1 / #2 } {#3} {#4} {#5} {#6} \msg_see_documentation_text:n {#1} } { \use:c { \c_msg_more_text_prefix_tl #1 / #2 } {#3} {#4} {#5} {#6} } } { \msg_interrupt:xxx { \msg_error_text:n {#1} : ~ "#2" } { \use:c { \c_msg_text_prefix_tl #1 / #2 } {#3} {#4} {#5} {#6} \msg_see_documentation_text:n {#1} } { } } } % \end{macrocode} % \end{macro} % % \begin{macro} % { % \msg_warning:nnxxxx , % \msg_warning:nnxxx , % \msg_warning:nnxx , % \msg_warning:nnx , % \msg_warning:nn % } % Warnings are printed to the terminal. % \begin{macrocode} \msg_class_set:nn { warning } { \msg_term:x { \msg_warning_text:n {#1} : ~ "#2" \\ \\ \use:c { \c_msg_text_prefix_tl #1 / #2 } {#3} {#4} {#5} {#6} } } % \end{macrocode} % \end{macro} % % \begin{macro} % { % \msg_info:nnxxxx , % \msg_info:nnxxx , % \msg_info:nnxx , % \msg_info:nnx , % \msg_info:nn % } % Information only goes into the log. % \begin{macrocode} \msg_class_set:nn { info } { \msg_log:x { \msg_info_text:n {#1} : ~ "#2" \\ \\ \use:c { \c_msg_text_prefix_tl #1 / #2 } {#3} {#4} {#5} {#6} } } % \end{macrocode} % \end{macro} % % \begin{macro} % { % \msg_log:nnxxxx , % \msg_log:nnxxx , % \msg_log:nnxx , % \msg_log:nnx , % \msg_log:nn % } % \enquote{Log} data is very similar to information, but with no extras % added. % \begin{macrocode} \msg_class_set:nn { log } { \msg_log:x { \use:c { \c_msg_text_prefix_tl #1 / #2 } {#3} {#4} {#5} {#6} } } % \end{macrocode} % \end{macro} % % \begin{macro} % { % \msg_none:nnxxxx , % \msg_none:nnxxx , % \msg_none:nnxx , % \msg_none:nnx , % \msg_none:nn % } % The \texttt{none} message type is needed so that input can be gobbled. % \begin{macrocode} \msg_class_set:nn { none } { } % \end{macrocode} % \end{macro} % % \begin{variable} % { % \l_msg_redirect_classes_seq , % \l_msg_class_tl , % \l_msg_current_class_tl , % \l_msg_current_module_tl % } % Support variables needed for the redirection system. % \begin{macrocode} \seq_new:N \l_msg_redirect_classes_seq \tl_new:N \l_msg_class_tl \tl_new:N \l_msg_current_class_tl \tl_new:N \l_msg_current_module_tl % \end{macrocode} %\end{variable} % % \begin{macro}[int]{\msg_use:nnnnxxxx} % \begin{macro}[aux]{\msg_use_aux:nnn} % \begin{macro}[aux]{\msg_use_aux:nn} % \begin{macro}[aux]{\msg_use_loop_check:nn} % \begin{macro}[aux]{\msg_use_code:} % \begin{macro}[aux]{\msg_use_loop:n, \msg_use_loop:o} % The main message-using macro creates two auxiliary functions: one % containing the code for the message, and the second a loop function. % There is then a hand-off to the system for checking if redirection is % needed. % \begin{macrocode} \cs_new_protected:Npn \msg_use:nnnnxxxx #1#2#3#4#5#6#7#8 { \cs_set_protected_nopar:Npx \msg_use_code: { \seq_clear:N \exp_not:N \l_msg_redirect_classes_seq \exp_not:n {#2} } \cs_set_protected:Npx \msg_use_loop:n ##1 { \seq_if_in:NnTF \exp_not:n \l_msg_redirect_classes_seq {#1} { \msg_kernel_error:nn { msg } { message-loop } {#1} } { \seq_put_right:Nn \exp_not:N \l_msg_redirect_classes_seq {#1} \exp_not:N \cs_if_exist:cTF { msg_ ##1 :nnxxxx } { \exp_not:N \use:c { msg_ ##1 :nnxxxx } \exp_not:n { {#3} {#4} {#5} {#6} {#7} {#8} } } { \msg_kernel_error:nnx { msg } { message-class-unknown } {##1} } } } \cs_if_exist:cTF { \c_msg_text_prefix_tl #3 / #4 } { \msg_use_aux:nnn {#1} {#3} {#4} } { \msg_kernel_error:nnxx { msg } { message-unknown } {#3} {#4} } } % \end{macrocode} % The first auxiliary macro looks for a match by name: the most % restrictive check. % \begin{macrocode} \cs_new_protected:Npn \msg_use_aux:nnn #1#2#3 { \tl_set:Nn \l_msg_current_class_tl {#1} \tl_set:Nn \l_msg_current_module_tl {#2} \prop_if_in:NnTF \l_msg_redirect_names_prop { // #2 / #3 / } { \msg_use_loop_check:nn { names } { // #2 / #3 / } } { \msg_use_aux:nn {#1} {#2} } } % \end{macrocode} % The second function checks for general matches by module or for % all modules. % \begin{macrocode} \cs_new_protected:Npn \msg_use_aux:nn #1#2 { \prop_if_in:cnTF { l_msg_redirect_ #1 _prop } {#2} { \msg_use_loop_check:nn {#1} {#2} } { \prop_if_in:cnTF { l_msg_redirect_ #1 _prop } { * } { \msg_use_loop_check:nn {#1} { * } } { \msg_use_code: } } } % \end{macrocode} % When checking whether to loop, the same code is needed in a few % places. % \begin{macrocode} \cs_new_protected:Npn \msg_use_loop_check:nn #1#2 { \prop_get:cnN { l_msg_redirect_ #1 _prop } {#2} \l_msg_class_tl \tl_if_eq:NNTF \l_msg_current_class_tl \l_msg_class_tl { { \msg_use_code: } { \msg_use_loop:o \l_msg_class_tl } } } \cs_new_protected_nopar:Npn \msg_use_code: { } \cs_new_protected:Npn \msg_use_loop:n #1 { } \cs_generate_variant:Nn \msg_use_loop:n { o } % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\msg_redirect_class:nn} % Converts class one into class two. % \begin{macrocode} \cs_new_protected:Npn \msg_redirect_class:nn #1#2 { \prop_put:cnn { l_msg_redirect_ #1 _prop } { * } {#2} } % \end{macrocode} % \end{macro} % % \begin{macro}{\msg_redirect_module:nnn} % For when all messages of a class should be altered for a given module. % \begin{macrocode} \cs_new_protected:Npn \msg_redirect_module:nnn #1#2#3 { \prop_put:cnn { l_msg_redirect_ #2 _prop } {#1} {#3} } % \end{macrocode} % \end{macro} % % \begin{macro}{\msg_redirect_name:nnn} % Named message will always use the given class. % \begin{macrocode} \cs_new_protected:Npn \msg_redirect_name:nnn #1#2#3 { \prop_put:Nnn \l_msg_redirect_names_prop { // #1 / #2 / } {#3} } % \end{macrocode} % \end{macro} % % \subsection{Kernel-specific functions} % % \begin{macro}{\msg_kernel_new:nnnn} % \begin{macro}{\msg_kernel_new:nnn} % \begin{macro}{\msg_kernel_set:nnnn} % \begin{macro}{\msg_kernel_set:nnn} % The kernel needs some messages of its own. These are created using % pre-built functions. Two functions are provided: one more general % and one which only has the short text part. % \begin{macrocode} \cs_new_protected:Npn \msg_kernel_new:nnnn #1#2 { \msg_new:nnnn { LaTeX } { #1 / #2 } } \cs_new_protected:Npn \msg_kernel_new:nnn #1#2 { \msg_new:nnn { LaTeX } { #1 / #2 } } \cs_new_protected:Npn \msg_kernel_set:nnnn #1#2 { \msg_set:nnnn { LaTeX } { #1 / #2 } } \cs_new_protected:Npn \msg_kernel_set:nnn #1#2 { \msg_set:nnn { LaTeX } { #1 / #2 } } % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\msg_kernel_fatal:nnxxxx} % \begin{macro}{\msg_kernel_fatal:nnxxx} % \begin{macro}{\msg_kernel_fatal:nnxx} % \begin{macro}{\msg_kernel_fatal:nnx} % \begin{macro}{\msg_kernel_fatal:nn} % Fatal kernel errors cannot be re-defined. % \begin{macrocode} \cs_new_protected:Npn \msg_kernel_fatal:nnxxxx #1#2#3#4#5#6 { \msg_interrupt:xxx { \msg_fatal_text:n { LaTeX } : ~ "#1 / #2" } { \use:c { \c_msg_text_prefix_tl LaTeX / #1 / #2 } {#3} {#4} {#5} {#6} \msg_see_documentation_text:n { LaTeX3 } } { \c_msg_fatal_text_tl } \tex_end:D } \cs_new_protected:Npn \msg_kernel_fatal:nnxxx #1#2#3#4#5 {\msg_kernel_fatal:nnxxxx {#1} {#2} {#3} {#4} {#5} { } } \cs_new_protected:Npn \msg_kernel_fatal:nnxx #1#2#3#4 { \msg_kernel_fatal:nnxxxx {#1} {#2} {#3} {#4} { } { } } \cs_new_protected:Npn \msg_kernel_fatal:nnx #1#2#3 { \msg_kernel_fatal:nnxxxx {#1} {#2} {#3} { } { } { } } \cs_new_protected:Npn \msg_kernel_fatal:nn #1#2 { \msg_kernel_fatal:nnxxxx {#1} {#2} { } { } { } { } } % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\msg_kernel_error:nnxxxx} % \begin{macro}{\msg_kernel_error:nnxxx} % \begin{macro}{\msg_kernel_error:nnxx} % \begin{macro}{\msg_kernel_error:nnx} % \begin{macro}{\msg_kernel_error:nn} % Neither can kernel errors. % \begin{macrocode} \cs_new_protected:Npn \msg_kernel_error:nnxxxx #1#2#3#4#5#6 { \msg_if_more_text:cTF { \c_msg_more_text_prefix_tl LaTeX / #1 / #2 } { \msg_interrupt:xxx { \msg_error_text:n { LaTeX } : ~ " #1 / #2 " } { \use:c { \c_msg_text_prefix_tl LaTeX / #1 / #2 } {#3} {#4} {#5} {#6} \msg_see_documentation_text:n { LaTeX3 } } { \use:c { \c_msg_more_text_prefix_tl LaTeX / #1 / #2 } {#3} {#4} {#5} {#6} } } { \msg_interrupt:xxx { \msg_error_text:n { LaTeX } : ~ " #1 / #2 " } { \use:c { \c_msg_text_prefix_tl LaTeX / #1 / #2 } {#3} {#4} {#5} {#6} \msg_see_documentation_text:n { LaTeX3 } } { } } } \cs_new_protected:Npn \msg_kernel_error:nnxxx #1#2#3#4#5 {\msg_kernel_error:nnxxxx {#1} {#2} {#3} {#4} {#5} { } } \cs_set_protected:Npn \msg_kernel_error:nnxx #1#2#3#4 { \msg_kernel_error:nnxxxx {#1} {#2} {#3} {#4} { } { } } \cs_set_protected:Npn \msg_kernel_error:nnx #1#2#3 { \msg_kernel_error:nnxxxx {#1} {#2} {#3} { } { } { } } \cs_set_protected:Npn \msg_kernel_error:nn #1#2 { \msg_kernel_error:nnxxxx {#1} {#2} { } { } { } { } } % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\msg_kernel_warning:nnxxxx} % \begin{macro}{\msg_kernel_warning:nnxxx} % \begin{macro}{\msg_kernel_warning:nnxx} % \begin{macro}{\msg_kernel_warning:nnx} % \begin{macro}{\msg_kernel_warning:nn} % \begin{macro}{\msg_kernel_info:nnxxxx} % \begin{macro}{\msg_kernel_info:nnxxx} % \begin{macro}{\msg_kernel_info:nnxx} % \begin{macro}{\msg_kernel_info:nnx} % \begin{macro}{\msg_kernel_info:nn} % Kernel messages which can be redirected. % \begin{macrocode} \prop_new:N \l_msg_redirect_kernel_warning_prop \cs_new_protected:Npn \msg_kernel_warning:nnxxxx #1#2#3#4#5#6 { \msg_use:nnnnxxxx { warning } { \msg_term:x { \msg_warning_text:n { LaTeX } : ~ " #1 / #2 " \\ \\ \use:c { \c_msg_text_prefix_tl LaTeX / #1 / #2 } {#3} {#4} {#5} {#6} } } { LaTeX } { #1 / #2 } {#3} {#4} {#5} {#6} } \cs_new_protected:Npn \msg_kernel_warning:nnxxx #1#2#3#4#5 { \msg_kernel_warning:nnxxxx {#1} {#2} {#3} {#4} {#5} { } } \cs_new_protected:Npn \msg_kernel_warning:nnxx #1#2#3#4 { \msg_kernel_warning:nnxxxx {#1} {#2} {#3} {#4} { } { } } \cs_new_protected:Npn \msg_kernel_warning:nnx #1#2#3 { \msg_kernel_warning:nnxxxx {#1} {#2} {#3} { } { } { } } \cs_new_protected:Npn \msg_kernel_warning:nn #1#2 { \msg_kernel_warning:nnxxxx {#1} {#2} { } { } { } { } } \prop_new:N \l_msg_redirect_kernel_info_prop \cs_new_protected:Npn \msg_kernel_info:nnxxxx #1#2#3#4#5#6 { \msg_use:nnnnxxxx { info } { \msg_log:x { \msg_info_text:n { LaTeX } : ~ " #1 / #2 " \\ \\ \use:c { \c_msg_text_prefix_tl LaTeX / #1 / #2 } {#3} {#4} {#5} {#6} } } { LaTeX } { #1 / #2 } {#3} {#4} {#5} {#6} } \cs_new_protected:Npn \msg_kernel_info:nnxxx #1#2#3#4#5 { \msg_kernel_info:nnxxxx {#1} {#2} {#3} {#4} {#5} { } } \cs_new_protected:Npn \msg_kernel_info:nnxx #1#2#3#4 { \msg_kernel_info:nnxxxx {#1} {#2} {#3} {#4} { } { } } \cs_new_protected:Npn \msg_kernel_info:nnx #1#2#3 { \msg_kernel_info:nnxxxx {#1} {#2} {#3} { } { } { } } \cs_new_protected:Npn \msg_kernel_info:nn #1#2 { \msg_kernel_info:nnxxxx {#1} {#2} { } { } { } { } } % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % Error messages needed to actually implement the message system % itself. % \begin{macrocode} \msg_kernel_new:nnnn { msg } { message-already-defined } { Message~'#2'~for~module~'#1'~already~defined. } { \c_msg_coding_error_text_tl LaTeX~was~asked~to~define~a~new~message~called~'#2'\ by~the~module~'#1':~this~message~already~exists. \c_msg_return_text_tl } \msg_kernel_new:nnnn { msg } { message-unknown } { Unknown~message~'#2'~for~module~'#1'. } { \c_msg_coding_error_text_tl LaTeX~was~asked~to~display~a~message~called~'#2'\\ by~the~module~'#1'~module:~this~message~does~not~exist. \c_msg_return_text_tl } \msg_kernel_new:nnnn { msg } { message-class-unknown } { Unknown~message~class~'#1'. } { LaTeX~has~been~asked~to~redirect~messages~to~a~class~'#1':\\ this~was~never~defined. \c_msg_return_text_tl } \msg_kernel_new:nnnn { msg } { redirect-loop } { Message~redirection~loop~for~message~class~'#1'. } { LaTeX~has~been~asked~to~redirect~messages~in~an~infinite~loop.\\ The~original~message~here~has~been~lost. \c_msg_return_text_tl } % \end{macrocode} % % Messages for earlier kernel modules. % \begin{macrocode} \msg_kernel_new:nnnn { kernel } { bad-number-of-arguments } { Function~'#1'~cannot~be~defined~with~#2~arguments. } { \c_msg_coding_error_text_tl LaTeX~has~been~asked~to~define~a~function~'#1'~with~ #2~arguments. \\ TeX~allows~between~0~and~9~arguments~for~a~single~function. } \msg_kernel_new:nnnn { kernel } { command-already-defined } { Control~sequence~#1~already~defined. } { \c_msg_coding_error_text_tl LaTeX~has~been~asked~to~create~a~new~control~sequence~'#1'~ but~this~name~has~already~been~used~elsewhere. \\ \\ The~current~meaning~is:\\ \ \ #2 } \msg_kernel_new:nnnn { kernel } { command-not-defined } { Control~sequence~#1~undefined. } { \c_msg_coding_error_text_tl LaTeX~has~been~asked~to~use~a~command~#1,~but~this~has~not~ been~defined~yet. } \msg_kernel_new:nnnn { kernel } { variable-not-defined } { Variable~#1~undefined. } { \c_msg_coding_error_text_tl LaTeX~has~been~asked~to~show~a~variable~#1,~but~this~has~not~ been~defined~yet. } \msg_kernel_new:nnnn { seq } { empty-sequence } { Empty~sequence~#1. } { \c_msg_coding_error_text_tl LaTeX~has~been~asked~to~recover~an~entry~from~a~sequence~that~ has~no~content:~that~cannot~happen! } \msg_kernel_new:nnnn { tl } { empty-search-pattern } { Empty~search~pattern. } { \c_msg_coding_error_text_tl LaTeX~has~been~asked~to~replace~an~empty~pattern~by~'#1':~that~% would~lead~to~an~infinite~loop! } \msg_kernel_new:nnnn { scan } { already-defined } { Scan~mark~#1~already~defined. } { \c_msg_coding_error_text_tl LaTeX~has~been~asked~to~create~a~new~scan~mark~'#1'~ but~this~name~has~already~been~used~for~a~scan~mark. } % \end{macrocode} % % Some errors only appear in expandable settings, % hence don't need a \enquote{more-text} argument. % \begin{macrocode} \msg_kernel_new:nnn { seq } { misused } { A~sequence~was~misused. } \msg_kernel_new:nnn { kernel } { bad-var } { Erroneous~variable~#1 used! } \msg_kernel_new:nnn { prg } { zero-step } { Zero~step~size~for~stepwise~function~#1. } \msg_kernel_new:nnn { prg } { replicate-neg } { Negative~argument~for~\prg_replicate:nn. } % \end{macrocode} % % Messages used by the \enquote{\texttt{show}} functions. % \begin{macrocode} \msg_kernel_new:nnn { seq } { show } { Sequence~\token_to_str:N #1~ \seq_if_empty:NTF #1 { is~empty } { contains~the~items~(without~outer~braces): } } \msg_kernel_new:nnn { prop } { show } { Property~list~\token_to_str:N #1~ \prop_if_empty:NTF #1 { is~empty } { contains~the~pairs~(without~outer~braces): } } \msg_kernel_new:nnn { clist } { show } { Comma~list~ \str_if_eq:nnF {#1} { \l_clist_tmpa_clist } { \token_to_str:N #1~} \clist_if_empty:NTF #1 { is~empty } { contains~the~items~(without~outer~braces): } } \msg_kernel_new:nnn { ior } { show-no-stream } { No~input~streams~are~open } \msg_kernel_new:nnn { ior } { show-open-streams } { The~following~input~streams~are~in~use: } \msg_kernel_new:nnn { iow } { show-no-stream } { No~output~streams~are~open } \msg_kernel_new:nnn { iow } { show-open-streams } { The~following~output~streams~are~in~use: } % \end{macrocode} % % \subsection{Expandable errors} % % \begin{macro}[int]{\msg_expandable_error:n} % In expansion only context, we cannot use the normal means of % reporting errors. Instead, we feed \TeX{} an undefined control % sequence, \cs{LaTeX3 error:}. It is thus interrupted, and shows % the context, which thanks to the odd-looking \cs{use:n} is % \begin{verbatim} % \LaTeX3 error: % The error message. % \end{verbatim} % In other words, \TeX{} is processing the argument of \cs{use:n}, % which is \cs{LaTeX3 error:} \meta{error message}. % Then \cs{msg_expandable_error_aux:w} cleans up. In fact, there % is an extra subtlety: if the user inserts tokens for error recovery, % they should be kept. Thus we also use an odd space character % (with category code $7$) and keep tokens until that space character, % dropping everything else until \cs{q_stop}. The \cs{c_zero} prevents % losing braces around the user-inserted text if any, and stops the % expansion of \tn{romannumeral}. % \begin{macrocode} \group_begin: \char_set_catcode_math_superscript:N \^ \char_set_lccode:nn {`^} {`\ } \char_set_lccode:nn {`L} {`L} \char_set_lccode:nn {`T} {`T} \char_set_lccode:nn {`X} {`X} \tl_to_lowercase:n { \cs_new:Npx \msg_expandable_error:n #1 { \exp_not:n { \tex_romannumeral:D \exp_after:wN \exp_after:wN \exp_after:wN \msg_expandable_error_aux:w \exp_after:wN \exp_after:wN \exp_after:wN \c_zero } \exp_not:N \use:n { \exp_not:c { LaTeX3~error: } ^ #1 } ^ } \cs_new:Npn \msg_expandable_error_aux:w #1 ^ #2 ^ { #1 } } \group_end: % \end{macrocode} % \end{macro} % % \begin{macro} % { % \msg_expandable_kernel_error:nnnnnn, % \msg_expandable_kernel_error:nnnnn, % \msg_expandable_kernel_error:nnnn, % \msg_expandable_kernel_error:nnn, % \msg_expandable_kernel_error:nn % } % The command built from the csname % |\c_msg_text_prefix_tl LaTeX / #1 / #2| % takes four arguments and builds the error text, which is fed to % \cs{msg_expandable_error:n}. % \begin{macrocode} \cs_new:Npn \msg_expandable_kernel_error:nnnnnn #1#2#3#4#5#6 { \exp_args:Nf \msg_expandable_error:n { \exp_args:NNc \exp_after:wN \exp_stop_f: { \c_msg_text_prefix_tl LaTeX / #1 / #2 } {#3} {#4} {#5} {#6} } } \cs_new:Npn \msg_expandable_kernel_error:nnnnn #1#2#3#4#5 { \msg_expandable_kernel_error:nnnnnn {#1} {#2} {#3} {#4} {#5} { } } \cs_new:Npn \msg_expandable_kernel_error:nnnn #1#2#3#4 { \msg_expandable_kernel_error:nnnnnn {#1} {#2} {#3} {#4} { } { } } \cs_new:Npn \msg_expandable_kernel_error:nnn #1#2#3 { \msg_expandable_kernel_error:nnnnnn {#1} {#2} {#3} { } { } { } } \cs_new:Npn \msg_expandable_kernel_error:nn #1#2 { \msg_expandable_kernel_error:nnnnnn {#1} {#2} { } { } { } { } } % \end{macrocode} % \end{macro} % % \subsection{Showing variables} % % Functions defined in this section are used for diagnostic functions % in \pkg{l3clist}, \pkg{l3io}, \pkg{l3prop}, \pkg{l3seq}, \pkg{xtemplate} % % \begin{variable}{\l_msg_show_tl} % Used to store the material for the diagnostic functions % of various modules. % \begin{macrocode} \tl_new:N \l_msg_show_tl % \end{macrocode} % \end{variable} % % \begin{macro}[aux]{\msg_aux_use:nn} % \begin{macro}[aux]{\msg_aux_use:nnxxxx} % Print the text of a message to the terminal, without formatting. % \begin{macrocode} \cs_new_protected:Npn \msg_aux_use:nn #1#2 { \msg_aux_use:nnxxxx {#1} {#2} { } { } { } { } } \cs_new_protected:Npn \msg_aux_use:nnxxxx #1#2#3#4#5#6 { \iow_term:x { \use:c { \c_msg_text_prefix_tl #1 / #2 } {#3} {#4} {#5} {#6} } } % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}[int]{\msg_aux_show:Nnx} % \begin{macro}[aux]{\msg_aux_show:x} % \begin{macro}[aux,EXP]{\msg_aux_show:w} % The arguments of \cs{msg_aux_show:Nnx} are % \begin{itemize} % \item The \meta{variable} to be shown. % \item The \texttt{TF} emptyness conditional for that type of variables. % \item The type of the variable. % \item A mapping of the form \cs{seq_map_function:NN} \meta{variable} % \cs{msg_aux_show:n}, which produces the formatted string. % \end{itemize} % We remove a new line and \verb*|> | from the first item using % a \texttt{w}-type auxiliary, and the fact that \texttt{f}-expansion % removes a space. To avoid a low-level \TeX{} error if there is % an empty argument, a simple test is used to keep the output % \enquote{clean}. The odd \cs{exp_after:wN} and trailing % \cs{prg_do_nothing:} improve the output slightly. % \begin{macrocode} \cs_new_protected:Npn \msg_aux_show:Nnx #1#2#3 { \cs_if_exist:NTF #1 { \msg_aux_use:nnxxxx { LaTeX / #2 } { show } {#1} { } { } { } \msg_aux_show:x {#3} } { \msg_kernel_error:nnx { kernel } { variable-not-defined } { \token_to_str:N #1 } } } \cs_new_protected:Npn \msg_aux_show:x #1 { \tl_set:Nx \l_msg_show_tl {#1} \tl_if_empty:NT \l_msg_show_tl { \tl_set:Nx \l_msg_show_tl { > } } \exp_args:Nf \etex_showtokens:D { \exp_after:wN \exp_after:wN \exp_after:wN \msg_aux_show:w \exp_after:wN \l_msg_show_tl \exp_after:wN } \prg_do_nothing: } \cs_new:Npn \msg_aux_show:w #1 > { } % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}[aux,EXP]{\msg_aux_show:n} % \begin{macro}[aux,EXP]{\msg_aux_show:nn} % \begin{macro}[aux,EXP]{\msg_aux_show_unbraced:nn} % Each item in the variable is formatted using one of % the following functions. % \begin{macrocode} \cs_new:Npn \msg_aux_show:n #1 { \iow_newline: > \c_space_tl \c_space_tl { \exp_not:n {#1} } } \cs_new:Npn \msg_aux_show:nn #1#2 { \iow_newline: > \c_space_tl \c_space_tl { \exp_not:n {#1} } \c_space_tl \c_space_tl => \c_space_tl \c_space_tl { \exp_not:n {#2} } } \cs_new:Npn \msg_aux_show_unbraced:nn #1#2 { \iow_newline: > \c_space_tl \c_space_tl \exp_not:n {#1} \c_space_tl \c_space_tl => \c_space_tl \c_space_tl \exp_not:n {#2} } % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % % \subsection{Deprecated functions} % % Deprecated on 2011-05-27, for removal by 2011-08-31. % % \begin{macro}{\msg_class_new:nn} % This is only ever used in a |set| fashion. % \begin{macrocode} %<*deprecated> \cs_new_eq:NN \msg_class_new:nn \msg_class_set:nn % % \end{macrocode} % \end{macro} % % \begin{macro} % { % \msg_trace:nnxxxx, \msg_trace:nnxxx, \msg_trace:nnxx, % \msg_trace:nnx, \msg_trace:nn % } % The performance here is never going to be good enough for tracing % code, so let's be realistic. % \begin{macrocode} %<*deprecated> \cs_new_eq:NN \msg_trace:nnxxxx \msg_log:nnxxxx \cs_new_eq:NN \msg_trace:nnxxx \msg_log:nnxxx \cs_new_eq:NN \msg_trace:nnxx \msg_log:nnxx \cs_new_eq:NN \msg_trace:nnx \msg_log:nnx \cs_new_eq:NN \msg_trace:nn \msg_log:nn % % \end{macrocode} %\end{macro} % % \begin{macro}{\msg_generic_new:nnn} % \begin{macro}{\msg_generic_new:nn} % \begin{macro}{\msg_generic_set:nnn} % \begin{macro}{\msg_generic_set:nn} % \begin{macro}{\msg_direct_interrupt:xxxxx} % \begin{macro}{\msg_direct_log:xx} % \begin{macro}{\msg_direct_term:xx} % These were all too low-level. % \begin{macrocode} %<*deprecated> \cs_new_protected:Npn \msg_generic_new:nnn #1#2#3 { \deprecated } \cs_new_protected:Npn \msg_generic_new:nn #1#2 { \deprecated } \cs_new_protected:Npn \msg_generic_set:nnn #1#2#3 { \deprecated } \cs_new_protected:Npn \msg_generic_set:nn #1#2 { \deprecated } \cs_new_protected:Npn \msg_direct_interrupt:xxxxx #1#2#3#4#5 { \deprecated } \cs_new_protected:Npn \msg_direct_log:xx #1#2 { \deprecated } \cs_new_protected:Npn \msg_direct_term:xx #1#2 { \deprecated } % % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\msg_kernel_bug:x} % \begin{variable}{\c_msg_kernel_bug_text_tl, \c_msg_kernel_bug_more_text_tl} % \begin{macrocode} %<*deprecated> \cs_set_protected:Npn \msg_kernel_bug:x #1 { \msg_interrupt:xxx { \c_msg_kernel_bug_text_tl } { #1 \msg_see_documentation_text:n { LaTeX3 } } { \c_msg_kernel_bug_more_text_tl } } \tl_const:Nn \c_msg_kernel_bug_text_tl { This~is~a~LaTeX~bug:~check~coding! } \tl_const:Nn \c_msg_kernel_bug_more_text_tl { There~is~a~coding~bug~somewhere~around~here. \\ This~probably~needs~examining~by~an~expert. \c_msg_return_text_tl } % % \end{macrocode} % \end{variable} % \end{macro} % % \begin{macrocode} % % \end{macrocode} % % \end{implementation} % % \PrintIndex