diff options
author | Karl Berry <karl@freefriends.org> | 2009-06-09 23:31:15 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2009-06-09 23:31:15 +0000 |
commit | 215b9a864d5829070bdc66ba736986eb72e5143e (patch) | |
tree | fe0882c81fc4ec945cee4b512f72eaa21ea5f791 /Master/texmf-dist/source/latex/expl3/l3msg.dtx | |
parent | df90ec06321940c2f066b05e12f1b5ab099105da (diff) |
expl3 1407 (9jun09)
git-svn-id: svn://tug.org/texlive/trunk@13686 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/source/latex/expl3/l3msg.dtx')
-rw-r--r-- | Master/texmf-dist/source/latex/expl3/l3msg.dtx | 1336 |
1 files changed, 1336 insertions, 0 deletions
diff --git a/Master/texmf-dist/source/latex/expl3/l3msg.dtx b/Master/texmf-dist/source/latex/expl3/l3msg.dtx new file mode 100644 index 00000000000..4eb211be1a6 --- /dev/null +++ b/Master/texmf-dist/source/latex/expl3/l3msg.dtx @@ -0,0 +1,1336 @@ +% \iffalse +%% File: l3msg.dtx Copyright (C) 2009 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 ``expl3 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 LaTeX Project Team. +%% +%% ----------------------------------------------------------------------- +%% +% +%<*driver|package> +\RequirePackage{l3names} +%</driver|package> +%\fi +\GetIdInfo$Id: l3msg.dtx 1362 2009-05-28 20:19:21Z joseph $ + {L3 Experimental LaTeX Messages module} +%\iffalse +%<*driver> +%\fi +\ProvidesFile{\filename.\filenameext} + [\filedate\space v\fileversion\space\filedescription] +%\iffalse +\documentclass[full]{l3doc} +\begin{document} +\DocInput{l3msg.dtx} +\end{document} +%</driver> +% \fi +% +% \title{The \textsf{l3msg} package\thanks{This file +% has version number \fileversion, last +% revised \filedate.}\\ +% Communicating with the user} +% \author{\Team} +% \date{\filedate} +% \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 +% 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. Inside the +% message text, spaces are \emph{not} ignored. A space where \TeX\ +% would normally gobble one can be created using |\ |, and a new line +% with |\\|. New lines may have ``continuation'' text added by the +% output system. +% +%\begin{function}{ +% \msg_new:nnnnn| +% \msg_new:nnnn| +% \msg_new:nnn| +% \msg_set:nnnnn| +% \msg_set:nnnn| +% \msg_set:nnn +%} +% \begin{syntax} +% "\msg_new:nnnn" <module> <name> <text> <more text> <code> +% \end{syntax} +% Creates new message <name> for <module> to produce <text> initially, +% <more text> if requested by the user and to insert <code> after the +% message when used as an error. <text> and <more text> can use up to +% two macro parameters (|#1| and |#2|), which are supplied by the +% message system. Inside <text> and <more text> spaces are not ignored. +%\end{function} +% +% \section{Message classes} +% +% Creating message output requires the message to be given a class. +% +%\begin{function}{ +% \msg_class_new:nn| +% \msg_class_set:nn +%} +% \begin{syntax} +% "\msg_class_new:nn" <class> <code> +% \end{syntax} +% Creates new <class> to output a message, using <code> to process +% the message text. +%\end{function} +% +% The module defines several common message classes. The following +% describes the standard behaviour of each class if no redirection of +% the class or message is active. +% +%\begin{function}{ +% \msg_fatal:nnxx| +% \msg_fatal:nnx| +% \msg_fatal:nn +%} +% \begin{syntax} +% "\msg_fatal:nnxx" <module> <name> <arg one> <arg two> +% \end{syntax} +% Issues <module> error message <name>, passing <arg one> and +% <arg two> to the text-creating functions. The \TeX\ run then halts. +%\end{function} +% +%\begin{function}{ +% \msg_error:nnxx| +% \msg_error:nnx| +% \msg_error:nn +%} +% \begin{syntax} +% "\msg_error:nnxx" <module> <name> <arg one> <arg two> +% \end{syntax} +% Issues <module> error message <name>, passing <arg one> and +% <arg two> to the text-creating functions. +% \begin{texnote} +% The standard output here is similar to \cs{PackageError}. +% \end{texnote} +%\end{function} +% +%\begin{function}{ +% \msg_warning:nnxx| +% \msg_warning:nnx| +% \msg_warning:nn +%} +% \begin{syntax} +% "\msg_warning:nnxx" <module> <name> <arg one> <arg two> +% \end{syntax} +% Prints <module> message <name> to the terminal, passing <arg one> and +% <arg two> to the text-creating functions. +% \begin{texnote} +% The standard output here is similar to \cs{PackageWarningNoLine}. +% \end{texnote} +%\end{function} +% +%\begin{function}{ +% \msg_info:nnxx| +% \msg_info:nnx| +% \msg_info:nn +%} +% \begin{syntax} +% "\msg_info:nnxx" <module> <name> <arg one> <arg two> +% \end{syntax} +% Prints <module> message <name> to the log, passing <arg one> and +% <arg two> to the text-creating functions. +% \begin{texnote} +% The standard output here is similar to \cs{PackageInfoNoLine}. +% \end{texnote} +%\end{function} +% +%\begin{function}{ +% \msg_log:nnxx| +% \msg_log:nnx| +% \msg_log:nn +%} +% \begin{syntax} +% "\msg_info:nnxx" <module> <name> <arg one> <arg two> +% \end{syntax} +% Prints <module> message <name> to the log, passing <arg one> and +% <arg two> to the text-creating functions. No continuation text is +% added. +%\end{function} +% +%\begin{function}{ +% \msg_trace:nnxx| +% \msg_trace:nnx| +% \msg_trace:nn +%} +% \begin{syntax} +% "\msg_info:nnxx" <module> <name> <arg one> <arg two> +% \end{syntax} +% Prints <module> message <name> to the log, passing <arg one> and +% <arg two> to the text-creating functions. No continuation text is +% added. +%\end{function} +% +%\begin{function}{ +% \msg_none:nnxx| +% \msg_none:nnx| +% \msg_none:nn +%} +% \begin{syntax} +% "\msg_none:nnxx" <module> <name> <arg one> <arg two> +% \end{syntax} +% Does nothing: used for redirecting other message classes. +%\end{function} +% +% \section{Redirecting messages} +% +%\begin{function}{\msg_redirect_class:nn} +% \begin{syntax} +% "\msg_redirect_class:nn" <class one> <class two> +% \end{syntax} +% Redirect all messages of <class one> to appear as those of +% <class two>. +%\end{function} +% +%\begin{function}{\msg_redirect_module:nnn} +% \begin{syntax} +% "\msg_redirect_module:nnn" <class one> <module> <class two> +% \end{syntax} +% Redirect <module> messages of <class one> to appear in <class two>. +% \begin{texnote} +% This function can be used to make some messages ``silent'' by +% default. For example, all of the \texttt{trace} messages of +% <module> could be turned off with: +% \begin{verbatim} +% \msg_redirect_module:nnn { trace } { module } { none } +% \end{verbatim} +% \end{texnote} +%\end{function} +% +%\begin{function}{\msg_redirect_name:nnn} +% \begin{syntax} +% "\msg_redirect_name:nnn" <module> <message> <class> +% \end{syntax} +% Redirect <module> <message> to appear using <class>. +%\end{function} +% +% \section{Support functions for output} +% +%\begin{function}{\msg_line_context:} +% \begin{syntax} +% "\msg_line_context:" +% \end{syntax} +% Prints the current line number preceded by \cs{c_msg_on_line_tl}. +%\end{function} +% +%\begin{function}{\msg_line_number:} +% \begin{syntax} +% "\msg_line_number:" +% \end{syntax} +% Prints the current line number. +%\end{function} +% +%\begin{function}{ +% \msg_newline:| +% \msg_two_newlines: +%} +% \begin{syntax} +% "\msg_newline:" +% \end{syntax} +% Print one or two newlines with no continuation information. +%\end{function} +% +%\begin{function}{ +% \msg_space:| +% \msg_two_spaces:| +% \msg_four_spaces: +%} +% \begin{syntax} +% "\msg_space:" +% \end{syntax} +% Print one, two or four spaces: needed where a literal space would +% otherwise be gobbled by \TeX. +%\end{function} +% +% \section{Low-level functions} +% +% The low-level functions do not make assumptions about module names. +% The output functions here produce messages directly, and do not +% respond to redirection. +% +%\begin{function}{ +% \msg_generic_new:nnnn| +% \msg_generic_new:nnn| +% \msg_generic_new:nn| +% \msg_generic_set:nnnn| +% \msg_generic_set:nnn| +% \msg_generic_set:nn +%} +% \begin{syntax} +% "\msg_generic_new:nnnn" <name> <text> <more text> <code> +% \end{syntax} +% Creates new message <name> to produce <text> initially, <more text> +% if requested by the user and to insert <code> after the message when +% used as an error. <text> and <more text> can use up to two macro +% parameters (|#1| and |#2|), which are supplied by the message system. +% Inside <text> and <more text> spaces are not ignored. +%\end{function} +% +%\begin{function}{\msg_direct_interrupt:xxxxn} +% \begin{syntax} +% "\msg_direct_interrupt:xxxxn" <first line> <text> +% ~~~~<continuation> <more text> <code> +% \end{syntax} +% Executes a \TeX\ error, interrupting compilation. The <first line> +% is displayed followed by <text> and the input prompt. <more text> is +% displays if requested by the user, and <code> is inserted after the +% message. If <more text> is blank a default is supplied. Each line of +% <text> (broken with |\\|) begins with <continuation>. +%\end{function} +% +%\begin{function}{ +% \msg_direct_log:xx| +% \msg_direct_term:xx +%} +% \begin{syntax} +% "\msg_direct_log:xx" <text> <continuation> +% \end{syntax} +% Prints <text> to either the log or terminal. New lines (broken +% with |\\|) start with <continuation>. +%\end{function} +% +% \section{Kernel-specific functions} +% +%\begin{function}{ +% \msg_kernel_new:nnnn| +% \msg_kernel_new:nnn| +% \msg_kernel_new:nn| +% \msg_kernel_set:nnnn| +% \msg_kernel_set:nnn| +% \msg_kernel_set:nn +%} +% \begin{syntax} +% "\msg_kernel_new:nnn" <name> <text> <more text> <code> +% \end{syntax} +% Creates new kernel message <name> to produce <text> initially, +% <more text> if requested by the user and to insert <code> after the +% message when used as an error. <text> and <more text> can use up to +% two macro parameters (|#1| and |#2|), which are supplied by the +% message system. +%\end{function} +% +%\begin{function}{ +% \msg_kernel_fatal:nxx| +% \msg_kernel_fatal:nx| +% \msg_kernel_fatal:n +%} +% \begin{syntax} +% "\msg_kernel_fatal:nxx" <name> <arg one> <arg two> +% \end{syntax} +% Issues kernel error message <name>, passing <arg one> and +% <arg two> to the text-creating functions. The \TeX\ run then halts. +% Cannot be redirected. +%\end{function} +% +%\begin{function}{ +% \msg_kernel_error:nxx| +% \msg_kernel_error:nx| +% \msg_kernel_error:n +%} +% \begin{syntax} +% "\msg_kernel_error:nxx" <name> <arg one> <arg two> +% \end{syntax} +% Issues kernel error message <name>, passing <arg one> and +% <arg two> to the text-creating functions. Cannot be redirected. +%\end{function} +% +%\begin{function}{ +% \msg_kernel_warning:nxx| +% \msg_kernel_warning:nx| +% \msg_kernel_warning:n +%} +% \begin{syntax} +% "\msg_kernel_warning:nxx" <name> <arg one> <arg two> +% \end{syntax} +% Prints kernel message <name> to the terminal, passing <arg one> and +% <arg two> to the text-creating functions. +%\end{function} +% +%\begin{function}{ +% \msg_kernel_info:nxx| +% \msg_kernel_info:nx| +% \msg_kernel_info:n +%} +% \begin{syntax} +% "\msg_kernel_info:nxx" <name> <arg one> <arg two> +% \end{syntax} +% Prints kernel message <name> to the log, passing <arg one> and +% <arg two> to the text-creating functions. +%\end{function} +% +%\begin{function}{\msg_kernel_bug:x} +% \begin{syntax} +% "\msg_kernel_bug:x" <text> +% \end{syntax} +% Short-cut for ``This is a LaTeX bug: check coding'' errors. +%\end{function} +% +% \section{Variables and constants} +% +%\begin{variable}{ +% \c_msg_fatal_tl| +% \c_msg_error_tl| +% \c_msg_warning_tl| +% \c_msg_info_tl +%} +% Simple headers for errors. +%\end{variable} +% +%\begin{variable}{ +% \c_msg_fatal_text_tl| +% \c_msg_help_text_tl| +% \c_msg_kernel_bug_text_tl| +% \c_msg_kernel_bug_more_text_tl| +% \c_msg_no_info_text_tl| +% \c_msg_return_text_tl +%} +% Various pieces of text for use in messages, which are not changed by +% the code here although they could be to alter the language. +%\end{variable} +% +%\begin{variable}{\c_msg_on_line_tl} +% The ``on line'' phrase for line numbers. +%\end{variable} +% +%\begin{variable}{ +% \c_msg_text_prefix_tl| +% \c_msg_more_text_prefix_tl| +% \c_msg_code_prefix_tl +%} +% Header information for storing the ``paths'' to parts of a message. +%\end{variable} +% +%\begin{variable}{ +% \l_msg_class_tl| +% \l_msg_current_class_tl +%} +% Information about message method, used for filtering. +%\end{variable} +% +%\begin{variable}{\l_msg_names_clist} +% List of all of the message names defined. +%\end{variable} +% +%\begin{variable}{ +% \l_msg_redirect_classes_prop| +% \l_msg_redirect_names_prop +%} +% Re-direction lists containing the class of message to convert an +% different one. +%\end{variable} +% +%\begin{variable}{\l_msg_redirect_classes_clist} +% List so that filtering does not loop. +%\end{variable} +% +% \end{documentation} +% +% \begin{implementation} +% +% \section{\pkg{l3msg} implementation} +% +% The usual lead-off. +% \begin{macrocode} +%<*package> +\ProvidesExplPackage + {\filename}{\filedate}{\fileversion}{\filedescription} +\package_check_loaded_expl: +%</package> +%<*initex|package> +% \end{macrocode} +% +% \LaTeX\ is handling context, so the \TeX\ ``noise'' is turned down. +% \begin{macrocode} +\int_set:Nn \tex_errorcontextlines:D { \c_minus_one } +% \end{macrocode} +% +% \subsection{Variables and constants} +% +%\begin{macro}{\c_msg_fatal_tl} +%\begin{macro}{\c_msg_error_tl} +%\begin{macro}{\c_msg_warning_tl} +%\begin{macro}{\c_msg_info_tl} +% Header information. +% \begin{macrocode} +\tl_new:Nn \c_msg_fatal_tl { Fatal~Error } +\tl_new:Nn \c_msg_error_tl { Error } +\tl_new:Nn \c_msg_warning_tl { Warning } +\tl_new:Nn \c_msg_info_tl { Info } +% \end{macrocode} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +% +%\begin{macro}{\c_msg_fatal_text_tl} +%\begin{macro}{\c_msg_help_text_tl} +%\begin{macro}{\c_msg_kernel_bug_text_tl} +%\begin{macro}{\c_msg_kernel_bug_more_text_tl} +%\begin{macro}{\c_msg_no_info_text_tl} +%\begin{macro}{\c_msg_return_text_tl} +% Simple pieces of text for messages. +% \begin{macrocode} +\tl_new:Nn \c_msg_fatal_text_tl { + This~is~a~fatal~error:~LaTeX~will~abort +} +\tl_new:Nn \c_msg_help_text_tl { + For~immediate~help~type~H~<return> +} +\tl_new:Nn \c_msg_kernel_bug_text_tl { + This~is~a~LaTeX~bug:~check~coding! +} +\tl_new:Nn \c_msg_kernel_bug_more_text_tl { + There~is~a~coding~bug~somewhere~around~here. + \msg_newline: + This~probably~needs~examining~by~an~expert. + \c_msg_return_text_tl +} +\tl_new:Nn \c_msg_no_info_text_tl { + LaTeX~does~not~know~anything~more~about~this~error,~sorry. + \c_msg_return_text_tl +} +\tl_new:Nn \c_msg_return_text_tl { + \msg_two_newlines: + Try~typing~<return>~to~proceed. + \msg_newline: + If~that~doesn't~work,~type~X~<return>~to~quit +} +% \end{macrocode} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +% +%\begin{macro}[aux]{\c_msg_hide_tl<spaces>} +% An empty variable with a number of (category code 11) spaces at the +% end of its name. This is used to push the \TeX\ part of an error +% message ``off the screen''. +% +% No indentation here as \verb*| | is a letter! +% \begin{macrocode} +\group_begin: +\char_make_letter:N\ % +\tl_to_lowercase:n{% +\group_end:% +\tl_new:Nn% +\c_msg_hide_tl % +{}% +}% +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\c_msg_on_line_tl} +% ``On line''. +% \begin{macrocode} +\tl_new:Nn \c_msg_on_line_tl { on~line } +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\c_msg_text_prefix_tl} +%\begin{macro}{\c_msg_more_text_prefix_tl} +%\begin{macro}{\c_msg_code_prefix_tl} +% Prefixes for storage areas. +% \begin{macrocode} +\tl_new:Nn \c_msg_text_prefix_tl { msg_text // } +\tl_new:Nn \c_msg_more_text_prefix_tl { msg_text_more // } +\tl_new:Nn \c_msg_code_prefix_tl { msg_code // } +% \end{macrocode} +%\end{macro} +%\end{macro} +%\end{macro} +% +%\begin{macro}{\l_msg_class_tl} +%\begin{macro}{\l_msg_current_class_tl} +% For holding the current message method and that for redirection. +% \begin{macrocode} +\tl_new:N \l_msg_class_tl +\tl_new:N \l_msg_current_class_tl +% \end{macrocode} +%\end{macro} +%\end{macro} +% +%\begin{macro}{\l_msg_names_clist} +% Lists used for filtering. +% \begin{macrocode} +\clist_new:N \l_msg_names_clist +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\l_msg_redirect_classes_prop} +%\begin{macro}{\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{macro} +%\end{macro} +%\begin{macro}{\l_msg_redirect_classes_clist} +% To prevent an infinite loop. +% \begin{macrocode} +\clist_new:N \l_msg_redirect_classes_clist +% \end{macrocode} +%\end{macro} +% +% \subsection{Output helper functions} +% +%\begin{macro}{\msg_line_number:} +%\begin{macro}{\msg_line_context:} +% For writing the line number nicely. +% \begin{macrocode} +\cs_new_nopar:Nn { \msg_line_number: } { + \toks_use:N \tex_inputlineno:D +} +\cs_new_nopar:Nn { \msg_line_context: } { + \msg_space: + \c_msg_on_line_tl + \msg_space: + \msg_line_number: +} +% \end{macrocode} +%\end{macro} +%\end{macro} +% +%\begin{macro}{\msg_newline:} +%\begin{macro}{\msg_two_newlines:} +% Always forces a new line. +% \begin{macrocode} +\cs_new_nopar:Nn \msg_newline: { ^^J } +\cs_new_nopar:Nn \msg_two_newlines: { ^^J ^^J } +% \end{macrocode} +%\end{macro} +%\end{macro} +% +%\begin{macro}{\msg_space:} +%\begin{macro}{\msg_two_spaces:} +%\begin{macro}{\msg_four_spaces:} +% For printing spaces, some very simple functions. +% \begin{macrocode} +\cs_new_nopar:Nn \msg_space: { ~ } +\cs_new_nopar:Nn \msg_two_spaces: { \msg_space: \msg_space: } +\cs_new_nopar:Nn \msg_four_spaces: { \msg_two_spaces: \msg_two_spaces: } +% \end{macrocode} +%\end{macro} +%\end{macro} +%\end{macro} +% +%\subsection{Generic functions} +% +% The lowest level functions make no assumptions about modules, +% \emph{etc.} +% +%\begin{macro}{\msg_generic_new:nnnn} +%\begin{macro}{\msg_generic_new:nnn} +%\begin{macro}{\msg_generic_new:nn} +% Creating a new message is basically the same as the non-checking +% version, and so after a check everything hands over. +% \begin{macrocode} +\cs_new_nopar:Npn \msg_generic_new:nnnn #1 { + \exp_args:Nc \chk_if_free_cs:N { \c_msg_text_prefix_tl #1 :nn } + \msg_generic_set:nnnn {#1} +} +\cs_new_nopar:Npn \msg_generic_new:nnn #1 { + \exp_args:Nc \chk_if_free_cs:N { \c_msg_text_prefix_tl #1 :nn } + \msg_generic_set:nnn {#1} +} +\cs_new_nopar:Npn \msg_generic_new:nn #1 { + \exp_args:Nc \chk_if_free_cs:N { \c_msg_text_prefix_tl #1 :nn } + \msg_generic_set:nn {#1} +} +% \end{macrocode} +%\end{macro} +%\end{macro} +%\end{macro} +% +%\begin{macro}{\msg_generic_set:nnnn} +%\begin{macro}{\msg_generic_set:nnn} +%\begin{macro}{\msg_generic_set:nn} +%\begin{macro}[aux]{\msg_generic_set_clist:n} +%\begin{macro}[aux]{\msg_generic_set_text:n} +%\begin{macro}[aux]{\msg_generic_set_more_text:n} +%\begin{macro}[aux]{\msg_generic_set_code:n} +% Creating a message is quite simple. There must be a short text part, +% while the other parts may not exist. To avoid filling up the hash +% table with empty functions,only non-empty arguments are stored. +% The various auxiliary functions are used to allow spaces in the +% text arguments. +% \begin{macrocode} +\cs_new_nopar:Npn \msg_generic_set:nnnn #1 { + \msg_generic_set_clist:n {#1} + \char_make_space:N \ % + \msg_generic_set_code:nnnn{#1}% +} +\cs_new_nopar:Npn \msg_generic_set:nnn #1 { + \msg_generic_set_clist:n {#1} + \char_make_space:N \ % + \msg_generic_set_more_text:nnn{#1}% +} +\cs_new_nopar:Npn \msg_generic_set:nn #1 { + \msg_generic_set_clist:n {#1} + \char_make_space:N \ % + \msg_generic_set_text:nn{#1}% +} +\cs_new_nopar:Npn \msg_generic_set_clist:n #1 { + \clist_if_in:NnF \l_msg_names_clist { // #1 / } { + \clist_put_right:Nn \l_msg_names_clist { // #1 / } + } +} +\cs_new:Nn \msg_generic_set_text:nn { + \cs_set:cn { \c_msg_text_prefix_tl #1 :nn } {#2} + \char_make_ignore:N \ +} +\cs_new:Nn \msg_generic_set_more_text:nnn { + \cs_set:cn { \c_msg_text_prefix_tl #1 :nn } {#2} + \tl_if_empty:nTF {#3} { + \cs_set_eq:cN { \c_msg_more_text_prefix_tl #1 } \c_undefined + }{ + \cs_set:cn { \c_msg_more_text_prefix_tl #1 :nn } {#3} + } + \char_make_ignore:N \ +} +\cs_new:Npn \msg_generic_set_code:nnnn #1#2#3 { + \cs_set:cn { \c_msg_text_prefix_tl #1 :nn } {#2} + \tl_if_empty:nTF {#3} { + \cs_set_eq:cN { \c_msg_more_text_prefix_tl #1 } \c_undefined + }{ + \cs_set:cn { \c_msg_more_text_prefix_tl #1 :nn } {#3} + } + \char_make_ignore:N \ + \msg_generic_set_code:nn {#1} +} +\cs_new:Nn \msg_generic_set_code:nn { + \tl_if_empty:nTF {#2} { + \cs_set_eq:cN { \c_msg_code_prefix_tl #1 : } \c_undefined + }{ + \cs_set:cn { \c_msg_code_prefix_tl #1 : } {#2} + } +} +% \end{macrocode} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +% +%\begin{macro}{\msg_direct_interrupt:xxxxn} +%\begin{macro}[aux]{\msg_direct_interrupt:n} +% 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 spaces. To achieve this, +% spaces have to be letters: hence no indentation. The odd +% \cs{c_msg_hide_tl} actually does the hiding: it is the large run of +% spaces 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} +\group_begin: + \char_set_lccode:nn {`\&} {`\ } % { + \char_set_lccode:w `\} = `\ \scan_stop: + \char_make_active:N \& + \char_make_letter:N\ % +\tl_to_lowercase:n{% +\group_end:% +\cs_new_protected:Nn\msg_direct_interrupt:xxxxn{% +\group_begin:% +\cs_set_eq:NN\\\msg_newline:% +\cs_set_eq:NN\ \msg_space:% +\msg_direct_interrupt_aux:n{#4}% +\cs_set_nopar:Npn\\{\msg_newline:#3}% +\tex_errhelp:D\l_msg_tmp_tl% +\cs_set:Npn&{% +\tex_errmessage:D{% +#1\msg_newline:% +#2\msg_two_newlines:% +\c_msg_help_text_tl% +\c_msg_hide_tl % +}% +}% +&% +\group_end:% +#5% +}% +}% +\cs_new:Nn \msg_direct_interrupt_aux:n { + \tl_if_empty:nTF {#1} { + \tl_set:Nx \l_msg_tmp_tl { { \c_msg_no_info_text_tl } } + }{ + \tl_set:Nx \l_msg_tmp_tl { {#1 } } + } +} +% \end{macrocode} +%\end{macro} +%\end{macro} +% +%\begin{macro}{\msg_direct_log:xx} +%\begin{macro}{\msg_direct_term:xx} +% Printing to the log or terminal without a stop is rather easier. +% \begin{macrocode} +\cs_new_protected:Nn \msg_direct_log:xx { + \group_begin: + \cs_set:Npn \\ { \msg_newline: #2 } + \cs_set_eq:NN \ \msg_space: + \iow_log:x { #1 \msg_newline: } + \group_end: +} +\cs_new_protected:Nn \msg_direct_term:xx { + \group_begin: + \cs_set:Npn \\ { \msg_newline: #2 } + \cs_set_eq:NN \ \msg_space: + \iow_term:x { #1 \msg_newline: } + \group_end: +} +% \end{macrocode} +%\end{macro} +%\end{macro} +% +%\subsection{General functions} +% +% The main functions for messaging are built around the separation of +% module from the message name. These have short names as they will be +% widely used. +% +%\begin{macro}{\msg_new:nnnnn} +%\begin{macro}{\msg_new:nnnn} +%\begin{macro}{\msg_new:nnn} +%\begin{macro}{\msg_set:nnnnn} +%\begin{macro}{\msg_set:nnnn} +%\begin{macro}{\msg_set:nnn} +% For making messages. +% \begin{macrocode} +\cs_new_nopar:Npn \msg_new:nnnnn #1#2 { + \msg_generic_new:nnnn { #1 / #2 } +} +\cs_new_nopar:Npn \msg_new:nnnn #1#2 { + \msg_generic_new:nnn { #1 / #2 } +} +\cs_new_nopar:Npn \msg_new:nnn #1#2 { + \msg_generic_new:nn { #1 / #2 } +} +\cs_new_nopar:Npn \msg_set:nnnnn #1#2 { + \msg_generic_set:nnnn { #1 / #2 } +} +\cs_new_nopar:Npn \msg_set:nnnn #1#2 { + \msg_generic_set:nnn { #1 / #2 } +} +\cs_new_nopar:Npn \msg_set:nnn #1#2 { + \msg_generic_set:nn { #1 / #2 } +} +% \end{macrocode} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +% +%\begin{macro}{\msg_class_new:nn} +%\begin{macro}{\msg_class_set:nn} +% Creating a new class produces three new functions, with varying +% numbers of arguments. The \cs{msg_class_loop:n} function is set up +% so that redirection will work as desired. +% \begin{macrocode} +\cs_new_nopar:Npn \msg_class_new:nn #1 { + \exp_args:Nc \chk_if_free_cs:N { msg_ #1 :nnxx } + \prop_new:c { l_msg_redirect_ #1 _prop } + \msg_class_set:nn {#1} +} +\cs_new_nopar:Nn \msg_class_set:nn { + \prop_clear:c { l_msg_redirect_ #1 _prop } + \cs_set_protected:cn { msg_ #1 :nnxx } { + \msg_use:nnnnxx {#1} {#2} {##1} {##2} {##3} {##4} + } + \cs_set_protected:cn { msg_ #1 :nnx } { + \use:c { msg_ #1 :nnxx } {##1} {##2} {##3} { } + } + \cs_set_protected:cn { msg_ #1 :nn } { + \use:c { msg_ #1 :nnxx } {##1} {##2} { } { } + } +} +% \end{macrocode} +%\end{macro} +%\end{macro} +% +%\begin{macro}[aux]{\msg_use:nnnnxx} +% 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:Nn \msg_use:nnnnxx { + \cs_set:Nn \msg_use_code: { + \clist_clear:N \l_msg_redirect_classes_clist + #2 + } + \cs_set:Nn \msg_use_loop:n { + \clist_if_in:NnTF \l_msg_redirect_classes_clist {#1} { + \msg_kernel_error:n { message~loop } + }{ + \clist_put_right:Nn \l_msg_redirect_classes_clist {#1} + \cs_if_exist:cTF { msg_ ##1 :nnxx } { + \use:c { msg_ ##1 :nnxx } {#3} {#4} {#5} {#6} + }{ + \msg_kernel_error:nx { message~class~unknown } { ##1 } + } + } + } + \cs_if_exist:cTF { \c_msg_text_prefix_tl #3 / #4 :nn } { + \msg_use_aux:nnn {#1} {#3} {#4} + }{ + \msg_kernel_error:nxx { message~unknown } { #3 } { #4 } + } +} +% \end{macrocode} +%\end{macro} +%\begin{macro}[aux]{\msg_use_code:} +%\begin{macro}[aux]{\msg_use_loop:} +% Blank definitions are initially created for these functions. +% \begin{macrocode} +\cs_new_nopar:Nn \msg_use_code: { } +\cs_new_nopar:Nn \msg_use_loop:n { } +% \end{macrocode} +%\end{macro} +%\end{macro} +% +%\begin{macro}[aux]{\msg_use_aux:nnn} +% The first auxiliary macro looks for a match by name: the most +% restrictive check. +% \begin{macrocode} +\cs_new_nopar:Nn \msg_use_aux:nnn { + \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} +%\end{macro} +%\begin{macro}[aux]{\msg_use_aux:nn} +% The second function checks for general matches by module or for +% all modules. +% \begin{macrocode} +\cs_new_nopar:Nn \msg_use_aux:nn { + \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} +%\end{macro} +%\begin{macro}[aux]{\msg_use_loop_check:nn} +% When checking whether to loop, the same code is needed in a few +% places. +% \begin{macrocode} +\cs_new:Nn \msg_use_loop_check:nn { + \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:n { \l_msg_class_tl } + } +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\msg_fatal:nnxx} +%\begin{macro}{\msg_fatal:nnx} +%\begin{macro}{\msg_fatal:nn} +% For fatal errors, after the error message \TeX\ bails out. +% \begin{macrocode} +\msg_class_new:nn { fatal } { + \msg_direct_interrupt:xxxxn + { \c_msg_fatal_tl \msg_two_newlines: } + { + ( \c_msg_fatal_tl ) \msg_space: + \use:c { \c_msg_text_prefix_tl #1 / #2 :nn } {#3} {#4} + } + { ( \c_msg_fatal_tl ) \msg_space: } + { \c_msg_fatal_text_tl } + { \tex_end:D } +} +% \end{macrocode} +%\end{macro} +%\end{macro} +%\end{macro} +% +%\begin{macro}{\msg_error:nnxx} +%\begin{macro}{\msg_error:nnx} +%\begin{macro}{\msg_error:nn} +% For an error, the interrupt routine is called, then any recovery code +% is tried. +% \begin{macrocode} +\msg_class_new:nn { error } { + \msg_direct_interrupt:xxxxn + { #1~\c_msg_error_tl \msg_newline: } + { + ( #1 ) \msg_space: + \use:c { \c_msg_text_prefix_tl #1 / #2 :nn } {#3} {#4} + } + { ( #1 ) \msg_space: } + { + \cs_if_exist:cTF { \c_msg_more_text_prefix_tl #1 / #2 :nn } { + \use:c { \c_msg_more_text_prefix_tl #1 / #2 :nn } {#3} {#4} + }{ + \c_msg_no_info_text_tl + } + } + { + \cs_if_exist:cT { \c_msg_code_prefix_tl #1 /#2 :nn } { + \use:c { \c_msg_code_prefix_tl #1 / #2 :nn} {#3} {#4} + } + } +} +% \end{macrocode} +%\end{macro} +%\end{macro} +%\end{macro} +% +%\begin{macro}{\msg_warning:nnxx} +%\begin{macro}{\msg_warning:nnx} +%\begin{macro}{\msg_warning:nn} +% Warnings are printed to the terminal. +% \begin{macrocode} +\msg_class_new:nn { warning } { + \msg_direct_term:xx { + \msg_space: #1~\c_msg_warning_tl :~ + \use:c { \c_msg_text_prefix_tl #1 / #2 :nn } {#3} {#4} + } + { ( #1 ) \msg_two_spaces: } +} +% \end{macrocode} +%\end{macro} +%\end{macro} +%\end{macro} +% +%\begin{macro}{\msg_info:nnxx} +%\begin{macro}{\msg_info:nnx} +%\begin{macro}{\msg_info:nn} +% Information only goes into the log. +% \begin{macrocode} +\msg_class_new:nn { info } { + \msg_direct_log:xx { + \msg_space: #1~\c_msg_info_tl :~ + \use:c { \c_msg_text_prefix_tl #1 / #2 :nn } {#3} {#4} + } + { ( #1 ) \msg_two_spaces: } +} +% \end{macrocode} +%\end{macro} +%\end{macro} +%\end{macro} +% +%\begin{macro}{\msg_log:nnxx} +%\begin{macro}{\msg_log:nnx} +%\begin{macro}{\msg_log:nn} +% ``Log'' data is very similar to information, but with no extras +% added. +% \begin{macrocode} +\msg_class_new:nn { log } { + \msg_direct_log:xx { + \use:c { \c_msg_text_prefix_tl #1 / #2 :nn } {#3} {#4} + } + { } +} +% \end{macrocode} +%\end{macro} +%\end{macro} +%\end{macro} +% +%\begin{macro}{\msg_trace:nnxx} +%\begin{macro}{\msg_trace:nnx} +%\begin{macro}{\msg_trace:nn} +% Trace data is the same as log data, more or less +% \begin{macrocode} +\msg_class_new:nn { trace } { + \msg_direct_log:xx { + \use:c { \c_msg_text_prefix_tl #1 / #2 :nn } {#3} {#4} + } + { } +} +% \end{macrocode} +%\end{macro} +%\end{macro} +%\end{macro} +% +%\begin{macro}{\msg_none:nnxx} +%\begin{macro}{\msg_none:nnx} +%\begin{macro}{\msg_none:nn} +% The \texttt{none} message type is needed so that input can be gobbled. +% \begin{macrocode} +\msg_class_new:nn { none } { } +% \end{macrocode} +%\end{macro} +%\end{macro} +%\end{macro} +% +%\subsection{Redirection functions} +% +%\begin{macro}{\msg_redirect_class:nn} +% Converts class one into class two. +% \begin{macrocode} +\cs_new_nopar:Nn \msg_redirect_class:nn { + \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_nopar:Nn \msg_redirect_module:nnn { + \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_nopar:Nn \msg_redirect_name:nnn { + \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_new:nn} +%\begin{macro}{\msg_kernel_set:nnnn} +%\begin{macro}{\msg_kernel_set:nnn} +%\begin{macro}{\msg_kernel_set:nn} +% 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_nopar:Npn \msg_kernel_new:nnnn #1 { + \msg_new:nnnnn { LaTeX } {#1} +} +\cs_new_nopar:Npn \msg_kernel_new:nnn #1 { + \msg_new:nnnn { LaTeX } {#1} +} +\cs_new_nopar:Npn \msg_kernel_new:nn #1 { + \msg_new:nnn { LaTeX } {#1} +} +\cs_new_nopar:Npn \msg_kernel_set:nnnn #1 { + \msg_set:nnnnn { LaTeX } {#1} +} +\cs_new_nopar:Npn \msg_kernel_set:nnn #1 { + \msg_set:nnnn { LaTeX } {#1} +} +\cs_new_nopar:Npn \msg_kernel_set:nn #1 { + \msg_set:nnn { LaTeX } {#1} +} +% \end{macrocode} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +% +%\begin{macro}[aux]{\msg_kernel_classes_new:n} +% Quickly make the fewer-arguments versions. +% \begin{macrocode} +\cs_new_nopar:Nn \msg_kernel_classes_new:n { + \cs_new_protected:cn { msg_kernel_ #1 :nx } { + \use:c { msg_kernel_ #1 :nxx } {##1} {##2} { } + } + \cs_new_protected:cn { msg_kernel_ #1 :n } { + \use:c { msg_kernel_ #1 :nxx } {##1} { } { } + } +} +% \end{macrocode} +%\end{macro} +% +%\begin{macro}{\msg_kernel_fatal:nxx} +%\begin{macro}{\msg_kernel_fatal:nx} +%\begin{macro}{\msg_kernel_fatal:n} +% Fatal kernel errors cannot be re-defined. +% \begin{macrocode} +\cs_new_protected:Nn \msg_kernel_fatal:nxx { + \msg_direct_interrupt:xxxxn + { \c_msg_fatal_tl \msg_two_newlines: } + { + ( LaTeX ) \msg_space: + \use:c { \c_msg_text_prefix_tl LaTeX / #1 :nn } {#2} {#3} + } + { ( LaTeX ) \msg_space: } + { \c_msg_fatal_text_tl } + { \tex_end:D } +} +\msg_kernel_classes_new:n { fatal } +% \end{macrocode} +%\end{macro} +%\end{macro} +%\end{macro} +% +%\begin{macro}{\msg_kernel_error:nxx} +%\begin{macro}{\msg_kernel_error:nx} +%\begin{macro}{\msg_kernel_error:n} +% Neither can kernel errors. +% \begin{macrocode} +\cs_new_protected:Nn \msg_kernel_error:nxx { + \msg_direct_interrupt:xxxxn + { LaTeX~\c_msg_error_tl \msg_newline: } + { + ( LaTeX ) \msg_space: + \use:c { \c_msg_text_prefix_tl LaTeX / #1 :nn } {#2} {#3} + } + { ( LaTeX ) \msg_space: } + { + \cs_if_exist:cTF { \c_msg_more_text_prefix_tl LaTeX / #1 :nn } { + \use:c { \c_msg_more_text_prefix_tl LaTeX / #1 :nn } {#2} {#3} + }{ + \c_msg_no_info_text_tl + } + } + { + \cs_if_exist:cT { \c_msg_code_prefix_tl LaTeX /#1 :nn } { + \use:c { \c_msg_code_prefix_tl LaTeX / #1 :nn} {#2} {#3} + } + } +} +\msg_kernel_classes_new:n { error } +% \end{macrocode} +%\end{macro} +%\end{macro} +%\end{macro} +% +%\begin{macro}{\msg_kernel_warning:nxx} +%\begin{macro}{\msg_kernel_warning:nx} +%\begin{macro}{\msg_kernel_warning:n} +%\begin{macro}{\msg_kernel_info:nxx} +%\begin{macro}{\msg_kernel_info:nx} +%\begin{macro}{\msg_kernel_info:n} +% Life is much more simple for warnings and information messages, as +% these are just short-cuts to the standard classes. +% \begin{macrocode} +\cs_new_protected_nopar:Npn \msg_kernel_warning:nxx { + \msg_warning:nnxx { LaTeX } +} +\msg_kernel_classes_new:n { warning } +\cs_new_protected_nopar:Npn \msg_kernel_info:nxx { + \msg_info:nnxx { LaTeX } +} +\msg_kernel_classes_new:n { info } +% \end{macrocode} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +%\end{macro} +% +% Some very basic error messages. +% \begin{macrocode} +\msg_kernel_new:nnn + { coding~bug } + {This is a LaTeX bug: check coding!\\#1} + {#2} +\msg_kernel_new:nnn + { message~unknown } + {Unknown message `#2' for module `#1'.} + {LaTeX was asked to display a message by the `#1' module.\\ + The message was supposed to be called `#2', but I can't\\ + find a message with that name. + \c_msg_return_text_tl} +\msg_kernel_new:nnn + { message~class~unknown } + {Unknown message class `#1'.} + {You have asked for a message to be redirected to class `#1'\\ + but this class is unknown. + \c_msg_return_text_tl} +\msg_kernel_new:nnn + { message~loop } + {Message redirection loop.} + {You have asked for a message to be redirected,\\ + but the redirection instructions form a loop:\\ + you've lost the message. + \c_msg_return_text_tl} +% \end{macrocode} +% +%\begin{macro}{\msg_kernel_bug:x} +% The \LaTeX\ coding bug error gets re-visited here. +% \begin{macrocode} +\cs_set_protected:Nn \msg_kernel_bug:x { + \msg_direct_interrupt:xxxxn + { \c_msg_kernel_bug_text_tl } + { !~#1 } + { ! } + { \c_msg_kernel_bug_more_text_tl } + { } +} +% \end{macrocode} +%\end{macro} +% +% \begin{macrocode} +%</initex|package> +% \end{macrocode} +% +% \end{implementation} +% +% \PrintIndex |