From 1a12075ba4cc3ca26d4c82b08bcb87b2e2aa62cc Mon Sep 17 00:00:00 2001 From: Karl Berry Date: Mon, 10 Oct 2022 20:22:56 +0000 Subject: exam-n (10oct22) git-svn-id: svn://tug.org/texlive/trunk@64674 c570f23f-e606-0410-a88d-b1316a301751 --- Master/texmf-dist/source/latex/exam-n/exam-n.drv | 78 +- Master/texmf-dist/source/latex/exam-n/exam-n.dtx | 1518 ++++++++++++++------ .../source/latex/exam-n/release-notes.dtx | 43 + 3 files changed, 1179 insertions(+), 460 deletions(-) create mode 100644 Master/texmf-dist/source/latex/exam-n/release-notes.dtx (limited to 'Master/texmf-dist/source/latex/exam-n') diff --git a/Master/texmf-dist/source/latex/exam-n/exam-n.drv b/Master/texmf-dist/source/latex/exam-n/exam-n.drv index ee1e949bbd2..7adfd8aca29 100644 --- a/Master/texmf-dist/source/latex/exam-n/exam-n.drv +++ b/Master/texmf-dist/source/latex/exam-n/exam-n.drv @@ -6,10 +6,13 @@ %% %% exam-n.dtx (with options: `driver') %% exam-n: format exam questions -%% Release version 1.1.4, 2016 December 19. +%% Release version exam-n-1.4.0, 2022 October 10. +%% See https://purl.org/nxg/dist/exam-n +%% and https://heptapod.host/nxg/exam-n +%% and https://www.ctan.org/pkg/exam-n %% %%%% File: exam-n.dtx -%%%% Copyright 2005--2016, Norman Gray +%%%% Copyright 2005--2022, Norman Gray %% %% This work may be distributed and/or modified under the %% conditions of the LaTeX Project Public License, either version 1.3 @@ -21,84 +24,36 @@ %% %% This work has the LPPL maintenance status `maintained'. %% -%% The Current Maintainer of this work is Norman Gray +%% The Current Maintainer of this work is Norman Gray %% %% This work consists of the files exam-n.dtx and exam-n.ins, %% the derived file exam-n.cls, %% and the associated *.clo files. -%%%% Source: Mercurial revision e8a612cb25f4, 2016-12-19 16:49 +0000, tag exam-n-1.1.4 + 0 +%%%% Source: a91e9cff7cac, 2022-10-10T13:33:17+01:00 %% \documentclass{ltxdoc} \title{exam-n: exam papers} -\author{Norman Gray\\(\texttt{norman@astro.gla.ac.uk})} -\date{Release 1.1.4} +\author{Norman Gray\\(\texttt{norman.gray@glasgow.ac.uk})} +\date{Version exam-n-1.4.0, 2022 October 10}% ...rather than exam-n-1.4.0, which isn't reader-focused \usepackage{url} \newcommand\Lopt[1]{\textsf {#1}} % options \newcommand\file[1]{\texttt {#1}} \newcommand\Lcount[1]{\textsl {\small#1}} \newcommand\Lenv[1]{\texttt{\{#1\}}} %environments -\newcommand\Lpackage[1]{\{\textsf{#1}\}} %packages +\newcommand\Lpackage[1]{[\textsf{#1}]} %packages {\catcode`\<=\active \gdef<#1>{{\ensuremath\langle\normalfont\textsl{#1}\ensuremath\rangle}}} \def\cmd{\begingroup - \catcode`\\=12 \catcode`\{=12 \catcode`\}=12 + \catcode`\\=12 \catcode`\{=12 \catcode`\}=12 \catcode`\#=12 \catcode`\<=\active \catcode`\|=12 \docmd} \def\docmd|#1|{\texttt{#1}\endgroup} -%%% \url macro (url.sty does this better) -\def\bs{$\backslash$} -\makeatletter -\newcommand\BSc{B.Sc.{}} -\newcommand\MSci{M.Sci.{}} -\newcommand\MSc{M.Sc.{}} -\newcommand\MA{M.A.{}} -\newcommand\MEng{M.Eng.{}} -\newcommand\BEng{B.Eng.{}} -\newcommand{\dd}{\mathrm{d}} -\newcommand{\ddd}{\,\mathrm{d}} % inside an integral, including thinspace +\def\secref#1{Sect.~\ref{#1}} -\def\Diffl{\@ifstar\@Difflflat\@Diffl} -\def\Partial{\@ifstar\@Partialflat\@Partial} -\def\@Partial{\@ifnextchar[{\@@Diffl\partial}{\@@Diffl\partial[]}} -\def\@Partialflat{\@ifnextchar[{\@@Difflflat\partial}{\@@Difflflat\partial[]}} -\def\@Diffl{\@ifnextchar[{\@@Diffl\dd}{\@@Diffl\dd[]}} -\def\@Difflflat{\@ifnextchar[{\@@Difflflat\dd}{\@@Difflflat\dd[]}} -\def\@@Diffl#1[#2]#3#4{% - \def\@tempa{#2}% - \ifx\@tempa\empty - \frac{#1#3}{#1#4}% - \else - \frac{{#1}^{#2}#3}{#1{#4}^{#2}}% - \fi} -\def\@@Difflflat#1[#2]#3#4{% - \def\@tempa{#2}% - \ifx\@tempa\empty - #1#3\mskip-0.8mu/\mskip-1.2mu #1#4% - \else - {#1}^{#2}#3\mskip-0.8mu /\mskip-1.2mu #1{#4}^{#2}% - \fi} -\def\e{{\mathrm e}} -\def\units{\begingroup - \catcode`\.=\active - \@ifstar{\let\un@tsspace\relax \un@ts}% - {\let\un@tsspace\thinspace\un@ts}} -\begingroup - \catcode`\.=\active - \gdef\un@ts#1{\let~\thinspace\let.\thinspace - \ifmmode - \un@tsspace\mathrm{#1}% - \else - \nobreak$\un@tsspace\mathrm{#1}$% - \fi - \endgroup} -\endgroup -\def\au{au} -\def\lambdabar{\setbox\@tempboxa\hbox{$\lambda$}% - \hbox to 0pt{\hbox to \wd\@tempboxa{\hss$\bar{}$\hss}\hss}\box\@tempboxa} -\makeatother +\usepackage{examndefs} \begin{document} \maketitle @@ -109,6 +64,13 @@ +\@ifl@t@r\fmtversion{2020/10/01} + {\typeout{Format is \fmtversion -- OK!}} + {\ClassError{exam-n} + {You need a more recent version of LaTeX} + {This class now requires a + LaTeX version at least 2020/10/01; version + \fmtversion\ is too old}} \endinput %% %% End of file `exam-n.drv'. diff --git a/Master/texmf-dist/source/latex/exam-n/exam-n.dtx b/Master/texmf-dist/source/latex/exam-n/exam-n.dtx index 043d2c9f7c9..ce752727b85 100644 --- a/Master/texmf-dist/source/latex/exam-n/exam-n.dtx +++ b/Master/texmf-dist/source/latex/exam-n/exam-n.dtx @@ -3,10 +3,13 @@ % % Generated file : DO NOT EDIT % -%% Release version 1.1.4, 2016 December 19. +%% Release version exam-n-1.4.0, 2022 October 10. +%% See https://purl.org/nxg/dist/exam-n +%% and https://heptapod.host/nxg/exam-n +%% and https://www.ctan.org/pkg/exam-n %% %%%% File: exam-n.dtx -%%%% Copyright 2005--2016, Norman Gray +%%%% Copyright 2005--2022, Norman Gray %% %% This work may be distributed and/or modified under the %% conditions of the LaTeX Project Public License, either version 1.3 @@ -18,136 +21,47 @@ %% %% This work has the LPPL maintenance status `maintained'. %% -%% The Current Maintainer of this work is Norman Gray +%% The Current Maintainer of this work is Norman Gray %% %% This work consists of the files exam-n.dtx and exam-n.ins, %% the derived file exam-n.cls, %% and the associated *.clo files. -%<+package|driver|example>%%%% Source: Mercurial revision e8a612cb25f4, 2016-12-19 16:49 +0000, tag exam-n-1.1.4 + 0 + +%<+package|driver|example>%%%% Source: a91e9cff7cac, 2022-10-10T13:33:17+01:00 %% %<*package|driver> % %<+package>\NeedsTeXFormat{LaTeX2e} -%<+package>\ProvidesClass{exam-n}[2016/12/19 1.1.4] -%<+package>\typeout{Class: `exam-n 1.1.4 <2016/12/19>} +%<+package>\ProvidesClass{exam-n}[2022/10/10 exam-n-1.4.0] +%<+package>\typeout{Class: `exam-n-1.4.0 <2022/10/10>} % %<*driver> \documentclass{ltxdoc} \title{exam-n: exam papers} -\author{Norman Gray\\(\texttt{norman@astro.gla.ac.uk})} -\date{Release 1.1.4} +\author{Norman Gray\\(\texttt{norman.gray@glasgow.ac.uk})} +\date{Version exam-n-1.4.0, 2022 October 10}% ...rather than exam-n-1.4.0, which isn't reader-focused \usepackage{url} \newcommand\Lopt[1]{\textsf {#1}} % options \newcommand\file[1]{\texttt {#1}} \newcommand\Lcount[1]{\textsl {\small#1}} \newcommand\Lenv[1]{\texttt{\{#1\}}} %environments -\newcommand\Lpackage[1]{\{\textsf{#1}\}} %packages -%Make command strings easier to write +\newcommand\Lpackage[1]{[\textsf{#1}]} %packages +%Make command strings easier to write, with \cmd|\foo| %{\catcode`\<=\active \gdef<#1>{\meta{#1}}} {\catcode`\<=\active \gdef<#1>{{\ensuremath\langle\normalfont\textsl{#1}\ensuremath\rangle}}} \def\cmd{\begingroup - \catcode`\\=12 \catcode`\{=12 \catcode`\}=12 + \catcode`\\=12 \catcode`\{=12 \catcode`\}=12 \catcode`\#=12 \catcode`\<=\active \catcode`\|=12 \docmd} \def\docmd|#1|{\texttt{#1}\endgroup} -%%% \url macro (url.sty does this better) -%\def\setpathdots{\discretionary{.}{}{.}} -%\def\setpathslash{\discretionary{/}{}{/}} -%{\catcode`\.=\active -% \catcode`\/=\active -% \gdef\pathcats{% -% \catcode`\%=12 \catcode`\~=12 -% \catcode`\.=\active \let.\setpathdots -% \catcode`\/=\active \let/\setpathslash -% \catcode`\#=12 \catcode`\_=12}% -% } -%\def\setpath#1{\ttfamily <\nobreak #1\nobreak>\endgroup} -%\def\url{\begingroup\pathcats\setpath} -\def\bs{$\backslash$} -\makeatletter -% See Makefile for gymnastics here... -% This hoiks the extra symbols at the bottom of the file, into the -% text here, so they can be documented. -% Abbreviations for degrees. -% \begin{macrocode} -\newcommand\BSc{B.Sc.{}} -\newcommand\MSci{M.Sci.{}} -\newcommand\MSc{M.Sc.{}} -\newcommand\MA{M.A.{}} -\newcommand\MEng{M.Eng.{}} -\newcommand\BEng{B.Eng.{}} -% \end{macrocode} -% -% Tweaks to differentials. -% \begin{macrocode} -\newcommand{\dd}{\mathrm{d}} -\newcommand{\ddd}{\,\mathrm{d}} % inside an integral, including thinspace +\def\secref#1{Sect.~\ref{#1}} -\def\Diffl{\@ifstar\@Difflflat\@Diffl} -\def\Partial{\@ifstar\@Partialflat\@Partial} -\def\@Partial{\@ifnextchar[{\@@Diffl\partial}{\@@Diffl\partial[]}} -\def\@Partialflat{\@ifnextchar[{\@@Difflflat\partial}{\@@Difflflat\partial[]}} -\def\@Diffl{\@ifnextchar[{\@@Diffl\dd}{\@@Diffl\dd[]}} -\def\@Difflflat{\@ifnextchar[{\@@Difflflat\dd}{\@@Difflflat\dd[]}} -\def\@@Diffl#1[#2]#3#4{% - \def\@tempa{#2}% - \ifx\@tempa\empty - \frac{#1#3}{#1#4}% - \else - \frac{{#1}^{#2}#3}{#1{#4}^{#2}}% - \fi} -\def\@@Difflflat#1[#2]#3#4{% - \def\@tempa{#2}% - \ifx\@tempa\empty - #1#3\mskip-0.8mu/\mskip-1.2mu #1#4% - \else - {#1}^{#2}#3\mskip-0.8mu /\mskip-1.2mu #1{#4}^{#2}% - \fi} -% \end{macrocode} -% -% The exponential sign -% \begin{macrocode} -\def\e{{\mathrm e}} -% \end{macrocode} -% -% Physical units in |\rm|. Unstarred version includes leading -% |\thinspace|. Starred version doesn't, and is used when referring to -% the unit by itself (eg axis is |$B/\units*T$|), and is not qualifying -% a number. -% FIXME: |\mu| in |\units| can come out wrong in some fonts (mtpro2?) -% -- needs investigation. -% \begin{macrocode} -\def\units{\begingroup - \catcode`\.=\active - \@ifstar{\let\un@tsspace\relax \un@ts}% - {\let\un@tsspace\thinspace\un@ts}} -\begingroup - \catcode`\.=\active - \gdef\un@ts#1{\let~\thinspace\let.\thinspace - \ifmmode - \un@tsspace\mathrm{#1}% - \else - \nobreak$\un@tsspace\mathrm{#1}$% - \fi - \endgroup} -\endgroup -% \end{macrocode} -% -% Other miscellaneous symbols: -% The AU is nothing exciting, but may be adjusted in future -% \begin{macrocode} -\def\au{au} -% \end{macrocode} -% The symbol for Compton wavelength is a crossed lambda -- the following isn't perfect, but is OK for now. -% \begin{macrocode} -\def\lambdabar{\setbox\@tempboxa\hbox{$\lambda$}% - \hbox to 0pt{\hbox to \wd\@tempboxa{\hss$\bar{}$\hss}\hss}\box\@tempboxa} -% \end{macrocode} -\makeatother +% Various definitions of this package, so we can document them. +\usepackage{examndefs} % Uncomment \OnlyDescription to skip the implementation %\OnlyDescription @@ -214,14 +128,74 @@ % |\comment| command. % % \item[\Lopt{cmfonts}, \Lopt{psfonts}, \Lopt{mathptm}, -% \Lopt{mathtime}, \Lopt{mtpro2}] -% The \Lopt{cmfonts} option uses the Computer Modern fonts for the -% document, and the \Lopt{psfonts} uses PostScript fonts. In this -% latter case, you will possibly want to use one of the -% \Lopt{mathtime} or \Lopt{mtpro2} options also, to use the -% mathtime or MTPro2 font set for the maths in the document; -% alternatively you can use the \Lopt{mathptm} option to use that -% free but less good alternative. +% \Lopt{mathtime}, \Lopt{mtpro2}, \Lopt{stix2}] +% The \Lopt{cmfonts} option (the default) uses the Computer Modern fonts for the +% document, and the other options use PostScript or OpenType fonts. +% +% The \Lopt{mathtime} or \Lopt{mtpro2} options select PostScript +% Times Roman, Helvetica and Courier for the body text, plus either Mathtime or +% Mathtime Professional~2 to typeset maths (this is commercially +% distributed by +% PC\TeX\footnote{\url{https://www.pctex.com/mtpro2.html}}, and +% designed to be compatible with Times Roman). A broadly +% compatible alternative to this is to use the \Lopt{mathptm} +% option, but although this is free, the results aren't impressive. +% +% A final option is to use the \Lopt{stix2} option to choose +% specifically and exclusively the +% (free) STIX2 font set\footnote{\url{https://www.stixfonts.org}} +% for both text and maths. +% On this site, you will need to download and install +% the files in the \url{static_otf.zip} bundle. +% Note that the support for this option is somewhat experimental, and +% at present, this package simply uses (serif) STIX2 roman +% for all font shapes. Since the exam style doesn't use any sans serif by +% default, this doesn't matter, at some level. The +% \Lopt{sansserif} option is not compatible with this option (the option +% won't produce any error, but neither will it produce any effect). +% +% \textbf{FIXME: remove this when unicode-math is working.} +% \textbf{Note:} because of an unfortunate interaction between packages, the +% \Lpackage{stix2} and \Lpackage{siunitx} packages can produce unexpected +% results with some combinations of \TeX\ engine and package version +% (specifically, \Lpackage{stix2} plus \Lpackage{siunitx} +% and \cmd|\micro| or \cmd|\circ| can produce garbled characters +% without \LaTeX\ reporting an error). Before \TeX Live 2021, this +% worked correctly with Xe\LaTeX\ and Lua\LaTeX, but not with +% pdf\LaTeX; from \TeX Live 2021 this works as expected with +% pdf\LaTeX, but works with the other two \emph{only} if you load +% the \Lpackage{siunitx} package with +% \cmd|\usepackage{siunitx}[=v2]|. I hope that future versions of +% one or other of these packages will make clear how this package +% should handle them, in a way which avoids this special-casing. +% \iffalse See +% https://github.com/josephwright/siunitx/issues/550 +% https://github.com/josephwright/siunitx/issues/547 +% https://github.com/stipub/stixfonts/issues/235 +% \fi +% +% The handling of non-standard fonts has always been slightly +% fragile in \LaTeX. +% The \Lopt{mtpro2} and \Lopt{stix2} options are those currently +% most used by the author, and are therefore the ones most likely +% to get the various font nuances correct. +% +% \item[\Lopt{uprightpi}]By default $\pi$ is set slanted, as is the +% usual \LaTeX\ default. When this is referring to the circular +% constant, however, this should (in some typesetting styles) be set as an upright letter, in +% fonts which support this. If the option \Lopt{uprightpi} is +% present, then |\pi| is defined to produce an upright letter, and +% the command |\italicpi| is defined to produce the slanted version. +% Whether this option is supplied or not, the macro |\uppi| will +% produce a single upright~$\pi$. +% Note: this is at present implemented +% only for the \Lopt{mtpro2} and \Lopt{stix2} options, +% and the combination of pdflatex+stix2 does not support |\uppi| at present. +% +% \item[\Lopt{(no)siunitx}] Load the \Lpackage{siunitx} package, or +% not. The default is yes. The |\units| macro, described below, +% still exists as an alternative, but will be removed in a +% forthcoming release (probably after 1.4.x). % % \item[\Lopt{(no)showsolutions}] % These control whether the solutions to @@ -235,7 +209,7 @@ % These control whether mark totals and subtotals are tracked within % the question (perquestionmarks), and whether the total available % marks are displayed at the end of the question (showmarktotals). -% See Sect.\,\ref{s:question} for more discussion (this +% See \secref{s:question} for more discussion (this % option was called \Lopt{showmarks} up to release 0.15). % % \item[\Lopt{(no)pageperquestion}] @@ -269,8 +243,9 @@ % \item[\Lopt{sansserif}] % Use a sans serif font for the body text. This is plug-ugly, not % least because it doesn't match the maths font; also, it may be -% easier or harder for dyslexic students to read (depending on your -% superstition -- there seems remarkably little actual evidence +% easier or harder for dyslexic students to read (there seems to be +% a variety of advice here, in both directions, ranging from +% confident to dogmatic, but remarkably little solid evidence % either way). % % \item[\Lopt{largefont}, or \Lopt{hugefont}] @@ -283,9 +258,9 @@ % \file{.clo} file, containing course-, department- or group-specific style % modifications. Most typically, these changes will affect the % rubric, and the sheet of physical constants. -% The only generic style option is \Lopt{A1} +% The only generic style option is \Lopt{myclass} % (which is included as an example of how such a file is written). -% See section~\ref{s:custom} below. +% See \secref{s:custom} below. % % In some circumstances -- for example when processing exam scripts % under the control of a Makefile or script -- it can be convenient to @@ -390,6 +365,9 @@ % preamble. After that, you must provide a question-number argument % (in square brackets) for every question. % +% Using |\label| within a question sets a label for the question number; +% using it within a |\part| (see below) labels the part number. +% % In some odder circumstances, you might not want to have any question % numbers at all; for example, you might want to require examinees to % attempt \emph{all} of the questions, and so simply have a mark for @@ -467,7 +445,8 @@ % different questions, but cannot be |\input| % unedited, as described above. If, however, they have \emph{only} % these structures (that is, only the |\documentclass| command, -% the \Lenv{document} environment, and zero or more |\usepackage| commands), +% the \Lenv{document} environment, and zero or more |\usepackage| +% or |\RequirePackage| commands), % then you can most conveniently import them unedited using the % |\includequestion| command. % \begin{verbatim} @@ -483,6 +462,12 @@ % question, you will have to make sure that whoever is assembling the % master file includes those packages there, too. % +% That is, we don't try too hard to support including just any old \LaTeX, here: +% any complicated preamble requirements in an included file should +% probably be managed by the exams convener transplanting them into +% the preamble of the main document. This may be an overly +% simple-minded approach, and may change in future versions. +% % The |\includequestion| command takes an optional argument which % overrides the question number. This caters for the case where % question authors have (unhelpfully) included question numbers in the @@ -505,7 +490,7 @@ % (c)..., or (i), (ii), (iii), and so on. Precede each of these with % this |\part| command. The formatting of the part numbers is % controlled by the exam style, as customised in -% Sect.~\ref{s:custom}. This macro starts a new paragraph. +% \secref{s:custom}. This macro starts a new paragraph. % % You can use the |\part| macro within solutions: this is useful if % you have the entire \Lenv{solution} environment at the end of the @@ -515,6 +500,13 @@ % so if you use this in the solutions, you must have as many % |\part|s in the solution as there are parts in the question. % +% In some (rare) cases, you may want to force a particular part +% number. You can do that with an optional argument |\part[99]| +% which overrides the auto-incremented numbering. Note that this +% skips the auto-increment of the number but doesn't cancel it, so +% if you do this for one part number you should probably do it for +% all of them. +% % \DescribeMacro{\partmarks} % \DescribeMacro{\partmarks*} % Macros \cmd|\partmarks{}| and \cmd|\partmarks*{}| announce @@ -523,21 +515,55 @@ % number declared at the beginning of the {question} environment. % You will typically have just one |\partmarks| per |\part|, but % you can have more if you want. -% The starred version differs by adjusting the position of the mark -% indicator, and should be used either (i) after (for example) an -% itemized list, or some other structure which leaves an expanse of -% white space on the right-hand side of the page; or (ii) within -% an \emph{unnumbered} equation. If, in case (ii), the style of -% the part-marks indicators is such that the indicator may be -% mistaken for an equation number, then it would be wise to use -% either |\partmarks*| or plain |\partmarks| after the equation, -% instead. +% +% The |\partmarks| command will most typically go at the end of a +% paragraph, but it may also appear inside an equation (that is, in +% |\[...\]|; don't use |$$...$$|), inside one or other +% \Lpackage{amsmath} display or \Lenv{equation} environments, or in +% a list or other environment. If it appears +% inside an environment, the indicator will appear at the +% \emph{end} of the environment, independent of where in the +% environment the command was typed (which implies that you can't +% have more than one inside an environment). The alignment of +% the partmarks indicator is not currently as good as I'd like it +% to be, in the case of \Lpackage{amsmath} alignments, but this +% turns out to be hard to improve. +% +% The starred version is similar, but budges its indicator upwards +% a little, and is a heuristic alternative which is useful in some +% cases \emph{after} a list or display, if the placement of the +% indicator is otherwise inaesthetic +% (if the style of the part-marks indicators happens to be such +% that the indicator may be mistaken for an equation number, then +% it would be wise to use either |\partmarks| or |\partmarks*| +% after the equation, instead). If you use |\partmarks*| within a +% display, you might be confronted by an error message, talking +% about |\eqno| in maths mode, which is even more incomprehensible +% than most \LaTeX\ messages. % % The unstarred version should only be used at the end of a % paragraph, and in fact forces a paragraph end; the starred % version should on stylistic grounds generally be used only at the % end of a paragraph, but it doesn't force one. % +% The |\partmarks| command has an optional argument which +% indicates the category of the question, thus `bookwork', `unseen', +% and so on. If this is present, then the category is included in the +% marks indicator. +% +% The |\partmarks| category/comment will typically be only one or two words +% long, and can sit comfortably in the margin. If an author wants to +% write more here, then it will be turned into a footnote on the +% page. This will obviously change the layout of the page, though +% since this text appears only in \Lopt{showsolutions} mode, that +% shouldn't be a problem. +% +% \DescribeMacro{\defaultpartmarkscategory} +% If the exams convener wishes to \emph{oblige} people to +% include such a category, then they might call +% |\defaultpartmarkscategory{category?}| in a package-options (|.clo|) +% file, to default the category with a highlighted remark to the question setter. +% % \DescribeMacro{\comment} % \cmd|\comment{}| associates a comment with a part of the text. % This is ignored in \Lopt{final} mode, but appears in the margin in the @@ -585,11 +611,10 @@ % Since the contents of this command is automatically uppercased in % some styles, and there are per-department specifics about the punctuation % of abbreviations, you should use the commands |\BSc|, |\MSci|, and -% friends (see section~\ref{s:othercommands}) to set the degree names +% friends (see \secref{s:othercommands}) to set the degree names % appropriately. % % \DescribeMacro{\universitycoursecode} -% \DescribeMacro{\schoolcoursecode} % \DescribeMacro{\degreedescriptions} % \DescribeMacro{\coursetitle} % Declare the identity of the exam with @@ -600,11 +625,6 @@ % This is the code for the course (and thus for the paper) as it % appears in university information systems, and is a % university-unique code such as `PHYS3031'. -% \item[School course code] -% This is a more informal, but more recognisable, code for the -% course/paper, as it is generally recognised within the school; -% for example, the honours Quantum Mechanics course is known -% within the school as P304H. % \item[Course title] % This is just a textual name for the course, for example `Quantum Mechanics'. % \item[Degree descriptions] @@ -623,6 +643,13 @@ % |\rubric|) are suppressed. The layout may end up looking a little % funny. % +% \DescribeMacro{\schoolcoursecode} +% There is also a command |\schoolcoursecode|, which is a more +% informal, but possibly more recognisable, code for the course/paper, +% as it is generally recognised within the school; for example, the +% honours Quantum Mechanics course is known within the school as +% P304H. Its use is optional. +% % \DescribeMacro{\paperident} % It can be convenient to add some identification to each page, if for % no other reason than to double-check that you haven't inserted a @@ -645,7 +672,7 @@ % Sometimes an exam may % have different time limits for different qualifications: this case, % separate the various times with |\\|, as in -% \texttt{\bs examtime\{9.30am -- 12 noon\bs\bs (or) 9.30am -- 1.45am\}} +% \cmd|\examtime{9.30am -- 12 noon\\ (or) 9.30am -- 1.45am}|. % % \DescribeMacro{\rubric} % \DescribeMacro{\norubric} @@ -666,6 +693,12 @@ % You will typically not have to change this, but if you do for some % reason, you can override it with the |\baserubric| command. % +% Note that the |\baserubric| command is typically used within a |.clo| +% file, within the argument to |\OverrideFormatting|. If you wish to +% further override this on a per-exam basis, then you will need to do +% so after |\OverrideFormatting| has done its work, and thus +% immediately after the |\begin{document}|. +% % \DescribeMacro{\numquestions} % Finally, declare the number of questions which are to be in the % paper with |\numquestions|. @@ -711,6 +744,13 @@ % There is analogous support for partial derivatives with |\Partial|. % % \DescribeMacro{\units} +% You should generally type units, and numbers with units, using +% the \Lpackage{siunitx} package, which is loaded by the +% \Lopt{siunitx} option (which is now enabled by default). However +% this class currently also supports a basic |\units| command, +% described below. This macro will be removed in a future version +% of the class. +% % Macros |\units|, |\units*|: you can typeset physical units in % |\rm|, with tilde or dot % acting as a separator between units. Since this is typeset in maths mode, all @@ -719,19 +759,20 @@ % $v=10\units{m.s^{-1}}$. The starred % version can be used when referring to the unit by itself % (eg axis is |$B/\units*T$|, or $B/\units*T$), and is not -% qualifying a number. These macros might be replaced, in the -% future, by a recommendation to use the \Lpackage{siunitx} package. +% qualifying a number. % -% For other useful symbols, see table~\ref{t:symbols}. +% \def\cs#1{$\backslash$\texttt{#1}} +% For other useful symbols, see table~\ref{t:symbols}.\footnote{The +% package used to support an \cs{au} macro, for astronomical +% unit, and \cs{lambdabar} for Compton wavelength, but these have +% since been removed. The former is available via +% \Lpackage{siunitx}.} % % \begin{table} % \hrule \medskip % \begin{tabular}{rlp{8cm}} % |\e|&$\e^{i\pi}=-1$& the exponential is typeset in an upright rather than % italic shape, as in |$\e^{i\pi}=-1$|.\\ -% |\au|&10\au& use this macro for astronomical units.\\ -% |\lambdabar|&$\lambdabar$& the Compton wavelength, as a lambda with a -% bar through it.\\ % \end{tabular} % \caption{\label{t:symbols}Miscellaneous symbols} % \medskip\hrule @@ -741,7 +782,7 @@ % \section{Customising the exam style} % \label{s:custom} % -% As described in section~\ref{s:options} above, any unrecognised +% As described in \secref{s:options} above, any unrecognised % options are interpreted as an instruction to search for and include % a class options file, formed from the name of the unrecognised % option, suffixed with \file{.clo}, which can be anywhere in the @@ -751,7 +792,7 @@ % The most typical changes here will be to adjust the exam rubric for % a particular class, with the command |\baserubric|, and to change the % sheet of physical constants, with the command |\constantssheet|. -% See the sample file |A1.clo| for examples. +% See the sample file |myclass.clo| for examples. % % Examine this sample \file{SpecialExam.clo} file: % \begin{verbatim} @@ -817,13 +858,32 @@ % If you really want to go to town on reformatting, you can redefine % the command |\maketitle|, which formats the front-page title. When % formatting this, you have access to each of the fragments of text -% described in section~\ref{s:preamble}, via a macro named after the +% described in \secref{s:preamble}, via a macro named after the % corresponding command. Thus the argument of the |\exambanner| command % is available in the macro |\@exambanner|. The exception is % |\numquestions|. If you find yourself needing to do this, it might % be worth having a discussion with the style's maintainer -- there % may be a simpler way to get what you want. % +% \DescribeMacro{\CheckExamMetadata} +% One of the things you may change within the |\maketitle| is the +% checking of exam metadata -- which fields are required and which are +% optional. You can change these from the default (in +% \secref{s:preamble}) by defining a command |\CheckExamMetadata|. +% \DescribeMacro{\RequiredMetadata} +% This macro takes no arguments, and should use the command +% \cmd|\RequiredMetadata{}{}{}| to +% perform its tests. +% {\catcode`\<=\active Here is the metadata key, such as +% |{examdate}|, which corresponds to the macro |\examdate|, is +% a brief description of the field, such as |{exam date}|, and +% is a longer bit of explanation. If the corresponding +% data is missing, then \LaTeX\ stops with an error, and the user can +% examine the by pressing the \texttt h key. You can +% adjust the test by examining the value of +% |\iffussydescription ... \fi|, which is set to |\false| if the \Lopt{sloppydescription} +% option was provided.} +% % No more clues. If you want to hack at this, see the definition of % |\maketitle| in the class file \file{exam-n.cls}. % Aspire not to break things. @@ -944,12 +1004,11 @@ $\Delta=6\pi M^2/h^2$, stating clearly any assumptions that you make.\partmarks{6} The solar-mass star HD83443 has a 0.35 Jupiter-mass planet that -follows a circular orbit of period 2.986 days and radius 0.038\units\au. +follows a circular orbit of period 2.986 days and radius \SI{0.038}{\astronomicalunit}. Calculate the rate of precession, in arcseconds per year, of the pericentre line of the planet's orbit.\partmarks{4} -[Schwartzschild radius of the Sun${}= 3.0\times10^3\units{m}$, -$1\units\au=1.5\times10^{11}\units m$]. +[Schwartzschild radius of the Sun: \SI{3e3}m; $\SI1\astronomicalunit = \SI{1.5e11}m$] \begin{solution} In the first type of calculation, we do a calculation in the LIF, in @@ -987,6 +1046,12 @@ have a clue. % % \end{macrocode} % +% \section{Release notes} +% Recent release notes are below. For older notes, see the source +% distribution. +% +% \input{release-notes.dtx} +% % \subsection*{Acknowledgements} % \addcontentsline{toc}{subsection}{Acknowledgements} % @@ -998,6 +1063,26 @@ have a clue. % \section{Implementation} % +% \subsection{\LaTeX3 compatibility}\label{s:compatibility} +% +% As of release 1.4.0, we depend on the \LaTeX3 hooks mechanism, which +% was introduced in 2020. We therefore cannot work with versions +% older than that. +% +% Note that we can't use the (apparently preferable) +% |\IfFormatAtLeastTF| command to do this test: we want to continue to +% work even when we're using a \LaTeX\ which is too old for this +% command to be defined. +% \begin{macrocode} +\@ifl@t@r\fmtversion{2020/10/01} + {\typeout{Format is \fmtversion -- OK!}} + {\ClassError{exam-n} + {You need a more recent version of LaTeX} + {This class now requires a + LaTeX version at least 2020/10/01; version + \fmtversion\ is too old}} +% \end{macrocode} +% % \subsection{Options} % % First, process the compose/draft/final option. @@ -1031,13 +1116,33 @@ have a clue. % from within this class file -- the only reliable way of checking if % they're present is to look for something like rmtmi.pfa, but % |\IfFileExists| isn't able to search for any of those files, only ones -% on the TEXINPUTS path such as mathtime.sty, which can be, and are +% on the \texttt{TEXINPUTS} path such as \texttt{mathtime.sty}, which can be, and are % often, installed without the fonts themselves being present. % \begin{macrocode} \newcount\examn@mtselect \examn@mtselect=0 \DeclareOption{mathptm}{\@psfontstrue\examn@mtselect=0} \DeclareOption{mathtime}{\@psfontstrue\examn@mtselect=1} \DeclareOption{mtpro2}{\@psfontstrue\examn@mtselect=2} +\DeclareOption{stix2}{\@psfontstrue\examn@mtselect=3} +% \end{macrocode} +% +% The letter $\pi$ is usually the circular constant, and as such +% should be set in an upright greek font. Don't this by default, +% since that goes against the usual \LaTeX\ default, but instead +% define the [uprightpi] option to support this, where possible. +% Not all fonts make this easy. +% \begin{macrocode} +\newif\ifexamn@uprightpi \examn@uprightpifalse +\DeclareOption{uprightpi}{\examn@uprightpitrue} +% \end{macrocode} +% +% Load the \Lpackage{siunitx} package, or not, defaulting yes. +% This is now preferred to the |\units| macro, and the latter will be +% removed in a forthcoming release. +% \begin{macrocode} +\newif\ifexamn@siunitx \examn@siunitxtrue +\DeclareOption{siunitx}{\examn@siunitxtrue} +\DeclareOption{nosiunitx}{\examn@siunitxfalse} % \end{macrocode} % % Switch between serif and sans serif fonts. We make little attempt @@ -1109,12 +1214,12 @@ have a clue. % \end{macrocode} % % If \Lopt{sloppydescription} is given, then we don't demand that all -% the exam metadata is provided. Failing this, we object, fatally, to +% the required exam metadata is provided. Failing this, we object, fatally, to % missing information. % \begin{macrocode} -\newif\if@fussydescription -\@fussydescriptiontrue -\DeclareOption{sloppydescription}{\@fussydescriptionfalse} +\newif\iffussydescription +\fussydescriptiontrue +\DeclareOption{sloppydescription}{\fussydescriptionfalse} % \end{macrocode} % % The university logo is typeset in colour by default; the \Lopt{mono} @@ -1127,7 +1232,7 @@ have a clue. % \begin{macrocode} \def\examn@header@shoutformat#1{{\Large\bfseries #1}} \DeclareOption{mono}{ - \PassOptionsToPackage{monochrome}{color} + \PassOptionsToPackage{monochrome}{xcolor} \def\examn@header@shoutformat#1{{\Huge\bfseries #1}} } \DeclareOption{colour}{} @@ -1137,13 +1242,16 @@ have a clue. % exam in `big' or `huge' font sizes, to help students with visual impairments. % The available font variants are represented as numbers. % Note: the |\examn@fontvariant| mechanism is in principle more -% general than simply size variants, but some of the code below +% general than simply size variants, but some of the code below % assumes that |\examn@fontvariant| greater than zero means large % text, and so would need to be adjusted if this becomes untrue. % -% The flag |\ifbigfont| is true if the font is `significantly large'; +% The flag |\ifbigfont| is true if the font is `significantly large', +% in the sense that exam text, or hyphenation or layout, may have to +% be adjusted in this case: % option \Lopt{hugefont} sets it true, option \Lopt{largefont} does -% not; it's intended to be a user-visible and -settable flag. +% not. It's intended to be a user-visible and -settable flag. +% % \emph{Note:} the \Lopt{hugefont} option used to be \Lopt{bigfont}; % the latter is deprecated and may be removed in v1.2. % \begin{macrocode} @@ -1174,10 +1282,20 @@ have a clue. \@styleoverrides={} \def\OverrideFormatting{\@styleoverrides=} % \end{macrocode} +% +% There are a few other settings which may be defaulted within a +% \file{.clo} file: +% \begin{itemize} +% \item |\constantsheet{...}|: is a table of, for example, physical +% constants which should appear in exams associated with a particular +% course. Despite the name, this can be any text which should appear +% on the first non-cover sheet of the exam. +% \item |\baserubric|: a modified `base rubric' -- see the +% documentation of |\rubric| below. +% \end{itemize} +% % If \@constantssheet is defined (using |\constantsheet{...}| in a -% .clo file), then display it on a page by itself. The macro -% |\constantssheet| is declared above, before the point where we include -% .clo files. +% .clo file), then display it on a page by itself. % \begin{macrocode} \newtoks\@constantstoks \def\@@displayconstants{% @@ -1198,6 +1316,38 @@ have a clue. \@constantstoks=} % \end{macrocode} % +% Similarly for the |\baserubric| and |\rubric| commands. +% +% The rubric is typically a per-exam thing. The `base rubric' is +% more-or-less common to all exams, though it's possible to override +% it in a .clo file. +% \begin{macrocode} +\def\@rubric{} +\def\rubric{\long\def\@rubric} +\def\norubric{\let\@rubric\@nnil} +% \end{macrocode} +% \dots and the base rubric: +% \begin{macrocode} +\def\@baserubric{% +\textbf{Answer each question in a separate booklet}\par +Candidates are reminded that devices able to store or display text or +images may not be used in examinations without prior arrangement. +\if@perquestionmarks + \par + Approximate marks are indicated in brackets as a guide for candidates. +\fi +} +\def\baserubric{\long\def\@baserubric} +% \end{macrocode} +% +% The |\defaultpartmarkscategory| macro creates a default partmarks +% `category'. See below. This is declared here, so that it can be +% used in a |.clo| file without error. +% \begin{macrocode} +\let\examn@defaultpartmarkscategory\relax +\def\defaultpartmarkscategory#1{\def\examn@defaultpartmarkscategory{#1}} +% \end{macrocode} +% % Spit out the style overrides at the beginning of the document, % rather than here. % \begin{macrocode} @@ -1279,11 +1429,23 @@ have a clue. \hrule}} % \end{macrocode} % -% Other required packages +% Other required packages. % \begin{macrocode} \RequirePackage[english]{babel} % UK hyphenation \RequirePackage{amsmath} -\RequirePackage{color} +\ifexamn@siunitx + \RequirePackage{siunitx} +\fi +% \end{macrocode} +% We use the \Lpackage{xcolor} package, in preference to +% \Lpackage{color}, so that we are compatible with TikZ (TikZ loads +% the \Lpackage{xcolor} package internally, and that isn't compatible +% with \Lpackage{color}). We could probably work around this some +% other way, but \Lpackage{xcolor} seems to be relatively standard, +% and appears to be backward compatible with \Lpackage{color}, +% so this change is harmless. +% \begin{macrocode} +\RequirePackage{xcolor} % \end{macrocode} % % I think flush-left equations look MUCH better than centred, but @@ -1294,74 +1456,52 @@ have a clue. % % \subsection{Layout} % -% First, handle PDF metadata, and other document identifiers. -% -% Generate an identifier, |\examn@docident| for this paper. This is obtained -% from the university or school course code, followed by the -% day-of-year, and the number of minutes since midnight (the goal here -% is to produce an identifier which automatically increments in time, -% but which isn't obviously a date -% \begin{macrocode} -\def\examn@setdocident{% - \begingroup - % yes, a big \ifcase would be more straightforward; - % no, that wouldn't be any fun at all - % (also it ends up looking messy and even tricksier). - \def\@step##1##2\@nil{\advance\@tempcnta##1 \def\@tempa{##2}} - \def\@tempa{{31}{28}{31}{30}{31}{30}{31}{31}{30}{31}{30}{31}}% - \@tempcnta=\day % day of month - \@tempcntb=\month % month of year (unit-offset) - \loop - \advance\@tempcntb-1 - \ifnum \@tempcntb>0 - \expandafter\@step\@tempa\@nil - \repeat - \@tempcntb=\year % yes, do calculate leap years - \divide\@tempcntb 4 \multiply\@tempcntb 4 - \ifnum\@tempcntb=\year - \ifnum\month>2 % but let's not worry about century years... - \advance\@tempcnta 1 - \fi +% \subsubsection{The \TeX\ engine} +% Identify the \TeX\ engine we're using. If we are using pdf\TeX, +% Xe\TeX, or Lua\TeX, we presume we're generating PDF. The +% \Lpackage{ifpdf} package exists, and evaluates to true for Lua\TeX, +% but doesn't distinguish between Xe- and Lua\TeX. +% It would be nice to use a package such as \Lpackage{iftex}, but (as of late +% 2017) this seems to do something sufficiently exotic with +% respect to |\if| nesting, that it confuses the logic here. +% It seems safer to do this test ourselves, so (a) we know what +% we're getting, and (b) we have the result in a convenient integer form. +% \begin{macrocode} +\newcount\examn@engine +\examn@engine=0 +\expandafter\ifx\csname pdfmatch\endcsname\relax + \expandafter\ifx\csname XeTeXinterchartoks\endcsname\relax + \expandafter\ifx\csname directlua\endcsname\relax + \examn@engine=0 % this is presumably original-TeX (how unutterably retro!) + \else + \examn@engine=3 \fi - % remove any \\ or ~ in the coursecode fields - \let\\\space - \let~\space - \xdef\examn@docident{% first element is based on uni/school course code - \ifx\@coursetitle\@empty - \ifx\@schoolcoursecode\@empty - exam% - \else - \@schoolcoursecode - \fi - \else - \@coursetitle - \fi - /\the\@tempcnta % day-of-year - -\the\time} % minutes since midnight - \endgroup -} -% \end{macrocode} -% Check whether we're generating PDF, and define the |\ifpdf| macro -% accordingly. This does depend on Oberdiek's \Lpackage{ifpdf} package being -% available, but that's been available for quite a long while, and if -% it isn't for some people's installations, we can potentially bring -% back the code which it replaces. -% \begin{macrocode} -\RequirePackage{ifpdf} -\def\@SetDocumentInfo{% - \ifpdf - {\pdfinfo{/Title (\examn@docident)}}% - % Don't put out an /Author(xxx) info entry -- there may be - % multiple authors, and it isn't obviously useful + \else + \examn@engine=2 \fi -} -\AtBeginDocument{\examn@setdocident\@SetDocumentInfo} +\else + \ifnum\pdfoutput>0 + \examn@engine=1 + \else + % this _is_ pdftex, but it's in generate-dvi mode + % (we decide not to detect this case with the other engines) + \examn@engine=0 + \fi +\fi % \end{macrocode} % +% \subsubsection{Fonts} +% % Choose the font set, based on |\if@psfonts| and |\examn@mtselect|. +% The following is \emph{messy}, and it's not clear to me if it's +% irreducibly so, or whether I'm just doing it the wrong way. +% +% Case |\examn@mtselect| is 0: the rather hacky \Lpackage{mathptm} solution. % \begin{macrocode} +\def\ex@fontlabel{???} \if@psfonts \ifcase\examn@mtselect + \def\ex@fontlabel{mathptm} \ifexamn@serif \RequirePackage{times} \else @@ -1369,7 +1509,14 @@ have a clue. \fi \RequirePackage{mathptm} \ClassWarningNoLine{exam-n}{Using mathptm fonts} - \or % use mathtime fonts +% \end{macrocode} +% +% Case |\examn@mtselect| is 1 or 2: use mathtime or Mathtime Pro 2 fonts +% for maths. We use postscript Times and Helvetica for the body fonts +% in both cases. +% \begin{macrocode} + \or + \def\ex@fontlabel{mathtime} \RequirePackage[LY1]{fontenc} % specify text font encoding \RequirePackage[LY1,mtbold]{mathtime} % switch math fonts \ifexamn@serif @@ -1379,6 +1526,7 @@ have a clue. \fi \ClassWarningNoLine{exam-n}{Using Mathtime fonts} \or % use mtpro2 fonts + \def\ex@fontlabel{mtpro2} \RequirePackage[T1]{fontenc} \RequirePackage{textcomp} \ifexamn@serif @@ -1389,13 +1537,103 @@ have a clue. \fi \RequirePackage[mtpbb]{mtpro2} \ClassWarningNoLine{exam-n}{Using MTPro2 fonts} +% \end{macrocode} +% +% Finally, case |\examn@mtselect| is 3: use STIX2 fonts: \url{http://www.stixfonts.org}. +% Since this requires fontspec, it also requires either XeLaTeX or +% LuaLaTeX. If we are in this branch, and not using either +% engine, then fail with what we hope is a reasonably clear error. +% +% First off, refuse to work with original TeX. +% \begin{macrocode} + \or + \def\ex@fontlabel{stix2} + \ifcase\examn@engine + \ClassError{exam-n} + {You can't use STIX fonts with original/DVI LaTeX} + {You must use either XeLaTeX or LuaLaTeX} +% \end{macrocode} +% +% Use of the STIX fonts with pdflatex mostly works, but there is a +% tricky current/legacy issue here. +% The \Lpackage{stix2} package is intended to use the STIX2 +% fonts with `legacy' \TeX\ engines. Does this apply to pdflatex, now +% it defaults to unicode input? See the discussion of +% \Lpackage{unicode-math} below. +% +% As of TeXLive 2022, this mostly works, in the sense that we do use STIX +% fonts, but the upright-pi support below fails (no LaTeX errors, but +% |\uppi| produces slanted pi). +% \begin{macrocode} + \or % pdflatex + \RequirePackage{stix2} +% \end{macrocode} +% +% We support only Xe\TeX\ and Lua\TeX\ here, since only these can use +% `system' fonts. For Xe\LaTeX\ we use `system' Helvetica and Courier +% fonts (slightly scaled) as the sans and mono fonts, respectively, for the sake of +% completeness. +% +% Note: unicode-math is a little complicated. As I (unfortunately) +% discovered via mistaken bug report +% \url{https://github.com/stipub/stixfonts/issues/235}, +% the \Lpackage{stix} package is intended to be used \emph{only} for +% `legacy' \TeX\ engines, and \Lpackage{unicode-math} for current ones +% such as Xe\LaTeX\ and Lua\LaTeX. +% I'm fairly confident (as of 2022 July 11) that the following does +% the right thing, but not yet 100% confident. +% +% Note that (as explained in the \Lpackage{unicode-math} manual, we +% should use the STIX Two \emph{Math} font for symbols, and not the +% text font. +% \begin{macrocode} + \or % XeLaTeX + \RequirePackage[bold-style=ISO,math-style=ISO]{unicode-math} + \setmathfont{STIX Two Math} + \setmainfont{STIX Two Text} + \or % LuaLaTeX: like XeLaTeX + \RequirePackage[bold-style=ISO,math-style=ISO]{unicode-math} + \setmathfont{STIX Two Math} + \setmainfont{STIX Two Text} + \fi +% \end{macrocode} +% The no-match case shouldn't happen. +% \begin{macrocode} \else - \ClassError{exam-n}{Impossible value of mtselect: \examn@mtselect} + \def\ex@fontlabel{ERROR} + \ClassError{exam-n} + {Impossible value of mtselect: \examn@mtselect} + {This shouldn't happen -- this is a class file bug} \fi +% \end{macrocode} +% +% There are no font complications when using CM fonts. That's nice. +% \begin{macrocode} \else + \def\ex@fontlabel{CM} \ClassWarningNoLine{exam-n}{Using CM fonts} \fi % \end{macrocode} +% +% Report what engine and font configuration we're using. +% \begin{macrocode} +\typeout{Environment: + engine: \ifcase\examn@engine original/DVI\or pdfTeX\or XeTeX\or LuaTeX\else ???\fi; + fonts: \ex@fontlabel; + options: % show any non-default options + \ifexamn@uprightpi uprightpi, \fi + \ifexamn@siunitx siunitx, \fi + \ifexamn@serif\else noserif, \fi + \if@pageperquestion pageperquestion, \fi + \if@perquestionmarks\else noperquestionmarks, \fi + \if@showmarktotals\else noshowmarktotals, \fi + \if@twosidepages twoside, \fi + \if@fleqn fleqn, \fi + \iffussydescription\else sloppydescription, \fi + \ifbigfont hugefont, \fi + \if@showsolutions showsolutions\else noshowsolutions\fi} +% \end{macrocode} +% % If we're using a sans serif font, then redefine |\normalfont| appropriately. % The macro |\examn@bodyfontchange| stores up these font changes until % they're applied just after |\maketitle|. @@ -1415,6 +1653,14 @@ have a clue. % \begin{macrocode} \ifcase\examn@fontvariant % default: do nothing + \def\examn@bodyfontchange{ + % ...apart from redefine \small to be more clearly distinct from \normalsize + \renewcommand\small{% + \@setfontsize\normalsize{9}{11}% + \abovedisplayskip 9\p@ \@plus1.5\p@ \@minus5\p@ + \abovedisplayshortskip \z@ \@plus2.5\p@ + \belowdisplayshortskip 5\p@ \@plus2.5\p@ \@minus2.5\p@ + \belowdisplayskip \abovedisplayskip}} \or % font variant 1: 18pt \def\examn@bodyfontchange{ @@ -1425,6 +1671,12 @@ have a clue. \belowdisplayshortskip 10\p@ \@plus5\p@ \@minus5\p@ \belowdisplayskip \abovedisplayskip \let\@listi\@listI} + \renewcommand\small{% + \@setfontsize\normalsize{12}{16}% + \abovedisplayskip 12\p@ \@plus2\p@ \@minus6\p@ + \abovedisplayshortskip \z@ \@plus4\p@ + \belowdisplayshortskip 6.5\p@ \@plus3\p@ \@minus3\p@ + \belowdisplayskip \abovedisplayskip} \parindent=24pt \parskip=18pt % Redefine \FormatPartMarks so that it doesn't push the text off the paper @@ -1440,6 +1692,12 @@ have a clue. \belowdisplayshortskip 21\p@ \@plus10.5\p@ \@minus10.5\p@ \belowdisplayskip \abovedisplayskip \let\@listi\@listI} + \renewcommand\small{% + \@setfontsize\normalsize{24}{28}% + \abovedisplayskip 24\p@ \@plus5\p@ \@minus12\p@ + \abovedisplayshortskip \z@ \@plus8\p@ + \belowdisplayshortskip 14\p@ \@plus8\p@ \@minus8\p@ + \belowdisplayskip \abovedisplayskip} \parindent=48pt \parskip=36pt % Redefine \FormatPartMarks so that it doesn't push the text off the paper @@ -1466,6 +1724,79 @@ have a clue. \fi} % \end{macrocode} % +% Adjust maths font sizes for the various cases: +% \begin{macrocode} +\DeclareMathSizes\@xiipt{12}{9}{7} +\DeclareMathSizes\@xipt{10}{8}{6} +% \end{macrocode} +% +% \subsubsection{PDF metadata, and other document identifiers} +% +% Generate an identifier, |\examn@docident| for this paper. This is obtained +% from the university or school course code, followed by the +% day-of-year, and the number of minutes since midnight (the goal here +% is to produce an identifier which automatically increments in time, +% but which isn't obviously a date. +% +% Yes, a big |\ifcase| would be more straightforward; +% no, that wouldn't be any fun at all +% (also it ends up looking messy and even tricksier). +% \begin{macrocode} +\def\examn@setdocident{% + \begingroup + \def\@step##1##2\@nil{\advance\@tempcnta##1 \def\@tempa{##2}} + \def\@tempa{{31}{28}{31}{30}{31}{30}{31}{31}{30}{31}{30}{31}}% + \@tempcnta=\day % day of month + \@tempcntb=\month % month of year (unit-offset) + \loop + \advance\@tempcntb-1 + \ifnum \@tempcntb>0 + \expandafter\@step\@tempa\@nil + \repeat + \@tempcntb=\year % yes, do calculate leap years + \divide\@tempcntb 4 \multiply\@tempcntb 4 + \ifnum\@tempcntb=\year + \ifnum\month>2 % but let's not worry about century years... + \advance\@tempcnta 1 + \fi + \fi + % remove any \\ or ~ in the coursecode fields + \let\\\space + \let~\space + \xdef\examn@docident{% first element is based on uni/school course code + \ifx\@coursetitle\@empty + \ifx\@schoolcoursecode\@empty + exam% + \else + \@schoolcoursecode + \fi + \else + \@coursetitle + \fi + /\the\@tempcnta % day-of-year + -\the\time} % minutes since midnight + \endgroup +} +% \end{macrocode} +% +% Add information to the PDF document metadata. +% \begin{macrocode} +\ifcase\examn@engine + \let\@SetDocumentInfo\relax % original TeX +\or % pdfTeX + \def\@SetDocumentInfo{\pdfinfo{/Title (\examn@docident)}}% + % Don't put out an /Author(xxx) info entry -- there may be + % multiple authors, and it isn't obviously useful +\or % XeTeX + % dvipdfm special -- see the dvipdfm manual + \def\@SetDocumentInfo{\special{pdf: docinfo << /Title (\examn@docident) >>}}% +\or % LuaTeX + % from the LuaTeX manual + \def\@SetDocumentInfo{\pdfextension info {/Title (\examn@docident)}}% +\fi +\AtBeginDocument{\examn@setdocident\@SetDocumentInfo} +% \end{macrocode} +% % \subsubsection{Exam metadata} % % \begin{macrocode} @@ -1508,25 +1839,6 @@ have a clue. \next} \expandafter\dd\@degreedescriptions\\} % \end{macrocode} -% The rubric is typically a per-exam thing. The `base rubric' is -% more-or-less common to all exams, though it's possible to override -% it in a .clo file. -% \begin{macrocode} -\def\@rubric{} -\def\rubric{\long\def\@rubric} -\def\norubric{\let\@rubric\@nnil} - -\def\@baserubric{% -\textbf{Answer each question in a separate booklet}\par -Candidates are reminded that devices able to store or display text or -images may not be used in examinations without prior arrangement. -\if@perquestionmarks - \par - Approximate marks are indicated in brackets as a guide for candidates. -\fi -} -\def\baserubric{\long\def\@baserubric} -% \end{macrocode} % % We can optionally check the total number of questions. Store this % if it is present, and add a check to the |\end{document}| to check @@ -1623,7 +1935,10 @@ images may not be used in examinations without prior arrangement. %% headheight=\the\headheight, headsep=\the\headsep, topmargin=\the\topmargin} \marginparsep=0.5cm } - +% \end{macrocode} +% In the \Lopt{draft} case, we nudge the text block to the side, to +% give a larger margin. +% \begin{macrocode} \ifnum\@draftstatus > 0 \@settextblock{2cm} \else @@ -1660,7 +1975,7 @@ images may not be used in examinations without prior arrangement. % |begingroup |ttfamily % \catcode`\{=12 \catcode`\}=12 \catcode`\\=12 % |noindent \newcommand\FormatPartNumber{|linebreak -% |noindent|quad\hbox to 2em{(\StylePartNumber{partnumber})\hss}} +% |noindent|null|quad\hbox to 2em{(\StylePartNumber{partnumber})\hss}} % |endgroup % \end{quotation} % works adequately as a part number, @@ -1782,7 +2097,7 @@ images may not be used in examinations without prior arrangement. \fancyhead[C]{\examn@bighead{\highlighted{DRAFT + SOLUTIONS, p\thepage/\pageref{lastpage}}}} \else \fancyhead[C]{\examn@bighead{\highlighted{DRAFT, p\thepage/\pageref{lastpage}}}} - \fi + \fi \else \if@showsolutions % Add a very prominent banner @@ -1805,8 +2120,9 @@ images may not be used in examinations without prior arrangement. % % \subsubsection{The title page} % -% Define a special page style for the title page -% No header: all of the text on the page is handled by |\maketitle| +% Define a special page style for the title page. +% +% There is no header: all of the text on the page is handled by |\maketitle| % The first-page footer doesn't show anything, but it does have to set % |\examn@topmark| in case Q1 starts on this page. % \begin{macrocode} @@ -1817,53 +2133,52 @@ images may not be used in examinations without prior arrangement. % \end{macrocode} % % Create a custom maketitle. -% First, handle the 'final' or 'draft' versions. % Check all required information is present. % \begin{macrocode} -\renewcommand\maketitle{ - \ifnum\@draftstatus < 2 % final or draft version - \ifx\@examdate\@empty - \ClassError{exam-n} - {No exam date given} - {Specify an exam date using \protect\examdate} - \fi - \ifx\@examtime\@empty - \ClassError{exam-n} - {No exam time given} - {Specify an exam time using \protect\examtime} - \fi - \ifx\@exambanner\@empty - \ClassError{exam-n} - {No exam banner given} - {Specify an exam banner (eg Examination for the degree...) using \protect\exambanner} - \fi - \if@fussydescription - \ifx\@schoolcoursecode\@empty - \ClassError{exam-n} - {No school course code given} - {Specify a school course code (eg P304H) using \protect\schoolcoursecode} - \fi - \ifx\@universitycoursecode\@empty - \ClassError{exam-n} +\def\RequiredMetadata#1#2#3{ + \expandafter\ifx\csname @#1\endcsname\@empty + \ClassError{exam-n}{#2}{#3 (command \@backslashchar #1)} + \else + \typeout{#1 check OK} + \fi} +% \end{macrocode} +% Define a |\CheckExamMetadata| test, but only if the macro wasn't defined in a |.clo| file. +% \begin{macrocode} +\@ifundefined{CheckExamMetadata}{ + \def\CheckExamMetadata{ + % First, data which is always required + \RequiredMetadata{examdate} + {No exam date given} + {Specify an exam date} + \RequiredMetadata{examtime} + {No exam time given} + {Specify an exam time} + \RequiredMetadata{exambanner} + {No exam banner given} + {Specify an exam banner (eg Examination for the degree...)} + \iffussydescription + % The following tests can be skipped by using the option [sloppydescription] + \RequiredMetadata{universitycoursecode} {No paper title given} - {Specify a university course code (eg PHYS3031) using \protect\universitycoursecode} - \fi - \ifx\@coursetitle\@empty - \ClassError{exam-n} + {Specify a university course code (eg PHYS3031)} + \RequiredMetadata{coursetitle} {No course title given} - {Specify a course title (eg Quantum Mechanics) using \protect\coursetitle} - \fi - \ifx\@degreedescriptions\@empty - \ClassError{exam-n} + {Specify a course title (eg Quantum Mechanics)} + \RequiredMetadata{degreedescriptions} {No paper subject given} - {Specify a 'degree description' (eg Physics 3) using \protect\degreedescriptions} - \fi - \ifx\@rubric\@empty - \ClassError{exam-n} + {Specify a 'degree description' (eg Physics 3)} + \RequiredMetadata{rubric} {No rubric given} - {Specify a rubric using \protect\rubric, or declare its absence with \protect\norubric} - \fi + {Specify a rubric, or declare its absence with \protect\norubric} \fi + }}{} +% \end{macrocode} +% Start the |\maketitle| command. +% First, handle the 'final' or 'draft' versions. +% \begin{macrocode} +\renewcommand\maketitle{ + \ifnum\@draftstatus < 2 % final or draft version + \CheckExamMetadata % \end{macrocode} % All OK so far\dots. Now produce the actual text. % \begin{macrocode} @@ -2073,6 +2388,8 @@ images may not be used in examinations without prior arrangement. % % \subsection{Structuring commands} % +% \subsubsection{Sections} +% % Define simple sectioning commands. We also check that these aren't % inside questions. % \begin{macrocode} @@ -2143,6 +2460,7 @@ images may not be used in examinations without prior arrangement. \@starttoc{toc}} % \end{macrocode} % +% \subsubsection{Questions and solutions} % Counters: % \begin{macrocode} \newcount\marktotal % number of marks accumulated so far @@ -2155,9 +2473,17 @@ images may not be used in examinations without prior arrangement. % within a question. It's a \LaTeX\ counter, so we can use |\roman|. % % We override the \Lenv{article} |\part| command. +% +% FIXME: +% We would like to use |\StylePartNumber| here, but can't, because +% that's defined as being eg |\alph|, and not |\@alph|. To change +% this, we'll have to retire |\StylePartNumber|, in favour of saying +% that, to change the formatting here, it's merely necessary to +% redefine |\thepartnumber|. % \begin{macrocode} \newcounter{partnumber} -\renewcommand\part{% +\renewcommand\thepartnumber{\thequestionnumber\@alph\c@partnumber} +\renewcommand\part[1][]{% \if@nobreak \else \par \@nobreakfalse @@ -2166,14 +2492,28 @@ images may not be used in examinations without prior arrangement. \vskip 0pt plus 4\bigskipamount \penalty-50 \fi - \stepcounter{partnumber}% - \noindent\FormatPartNumber + \def\@tempa{#1}% + \ifx\@tempa\@empty + \refstepcounter{partnumber}% + \noindent\FormatPartNumber + \else + \noindent\FormatPartNumber[#1]% + \fi } % \end{macrocode} % The default |\FormatPartNumber| creates a box the same size as a % parindent. This therefore assumes that it's following a |\noindent|. % \begin{macrocode} -\newcommand\FormatPartNumber{\hbox to \parindent{(\StylePartNumber{partnumber})\hss}} +\newcommand\FormatPartNumber[1][]{% + \def\@tempa{#1}% + \hbox to \parindent{(% + \ifx\@tempa\@empty + \StylePartNumber{partnumber}% + \else + \@tempa + \fi + )\hss}% +} % \end{macrocode} % And by default we use alphanumeric counters for parts (we abstract % this, rather than simply including |\alph| in the definition of @@ -2235,102 +2575,355 @@ images may not be used in examinations without prior arrangement. } % \end{macrocode} % +% \subsubsection{Partmarks} +% % |\partmarks| is used at the end of a paragraph to indicate the % number of marks associated with this part. The starred variant -% |\partmarks*| is used when the end of a part is the end of a display +% |\partmarks*| is used only when the end of a part is the end of a display % maths block which doesn't have an equation number. This moves the % part note up a bit, which looks nicer. +% +% It's also permissible to use |\partmarks| in the solution, to +% indicate precisely where marks accrue. It's reasonable for this to +% be more fine-grained than in the question. We don't check that the +% partmarks in the solution add up to the mark goal. +% +% Manage the partmarks comments as the contents of a zero-width hbox, +% which is sized to fit reasonably well in the margin. We insert this +% into the output just before formatting the partmarks. +% +% The |\defaultpartmarkscategory| macro creates a default partmarks +% `category'. If this is something like |{category?}|, then this +% should prompt question authors to indicate the category in each call +% to |\partmarks|. This can be declared within a |.clo| option file +% (and is declared above, so that it can be read from there without error). +% +% Below, we must add the footnote text after the end of the paragraph, +% otherwise this inserts vertical mode material, which causes a +% linebreak, at least in the case where the last line is almost full. +% Because we are using the hook mechanism, this package now depends on +% the expl3 modules, and thus on TeXLive versions which aren't too old +% (how old is too old? I'm not sure, but I expect TeXLive 2020 is new enough). +% \begin{macrocode} +\newbox\examn@partmarkscomment +\def\examn@makepartmarkscomment#1{% + \setbox0=\hbox{\small #1}% + \ifdim\wd0 < 3\marginparwidth % let shortish comments wrap here + \setbox\examn@partmarkscomment=\hbox to 0pt{\hbox{% + \vtop to 0pt{% + \hsize=\marginparwidth + \parindent=0pt + \parskip=0pt + \leftskip=1em % 1em matches the hskip in default \FormatPartMarks + \rightskip=0pt plus 0.5\marginsize + \hangindent=2em \hangafter=-1 + \small + #1\vss}}\hss + }% + \else + \stepcounter\@mpfn + \protected@xdef\@thefnmark{\thempfn}% + \@footnotetext{#1}% + % 3em matches the \leftskip+\hangindent above + \setbox\examn@partmarkscomment=\hbox to 0pt{% + \hskip3em\highlighted{\small [comment \thempfn]}\hss}% + \fi + } +\def\examn@getpartmarkscomment{% + \ifhbox\examn@partmarkscomment + \box\examn@partmarkscomment + \fi} +% \end{macrocode} +% Now, finally, define the actual |\partmarks| command. % \begin{macrocode} \def\partmarks{% \@ifstar{\@tempswatrue \@partmarks}{\@tempswafalse \@partmarks}} \newdimen\@partmarksspace \@partmarksspace=2em % default value % \end{macrocode} -% Now implement the part marks indicator. First, check that +% Check whether there's an optional (comment/category) argument, +% enclosed in |[...]|. +% \begin{macrocode} +\def\@partmarks{% + \@ifnextchar[%] + \@@partmarks{\@@partmarks[]}} +% \end{macrocode} +% Implement the part marks indicator. First, check that % `perquestionmarks' is turned on; if it's not, then we shouldn't be % using |\partmarks|. % \begin{macrocode} -\def\@partmarks#1{% +\def\@@partmarks[#1]#2{% \if@perquestionmarks \if@insolution - % visual display only -- doesn't count towards mark total - \setbox0=\vbox to 0pt{\vss - \hbox to \textwidth{\hfil\hbox to 0pt{\quad\small[\dots #1]\hss}} - \vskip0.25ex }% - % the next line is probably unnecessary, but guarantees that box0 - % has zero depth, so no extra vertical space appears because of - % this new box - \dp0=0pt - \ifvmode - \box0 + \@@partmarks@solution{#1}{#2}% + \else + \@@partmarks@question{#1}{#2}% + \fi + \else + \ClassError{exam-n}{\string\partmarks\ is not compatible with + noperquestionmarks}{Either remove \string\partmarks\ or remove + the noperquestionmarks option} + \fi +} +% \end{macrocode} +% +% Finally, implement the two partmarks variants for questions and solutions. +% +% The |\@@partmarks@endenv| command is called when |\partmarks| is +% invoked within an environment, and is used to add a suitable vbox to +% an after-environment hook. +% +% First prepare the vbox that's to be inserted, and then work out how +% to place it. The |\vskip\baselineskip| in the |\@partmarksbox| is +% to better position the box relative to where it ends up in the +% vertical list, and the value has a large heuristic element. +% \begin{macrocode} +\newbox\@partmarksbox +\def\@@partmarks@endenv@display{\@tempswatrue\@@partmarks@endenv@common} +\def\@@partmarks@endenv@nodisplay{\@tempswafalse\@@partmarks@endenv@common} +\def\@@partmarks@endenv@common#1{% + \ifvbox\@partmarksbox % ooops -- been here before: two \partmarks in one env + \ClassError{exam-n} + {Two partmarks commands in one environment! First one IGNORED!} + {You can (currently) have only one partmarks command per environment} + \fi + \global\setbox\@partmarksbox=\vbox to 0pt{\vss + \hbox to \textwidth{% + \strut\hfill + \examn@getpartmarkscomment + \FormatPartMarks{#1}}% + \vskip\baselineskip}% + %\dp\@partmarksbox=0pt +% \end{macrocode} +% Test whether we have the |{question}| environment as our immediate +% container, as opposed to being in an inner environment. +% \begin{macrocode} + \def\@tempa{question}% + \ifx\@tempa\@currenvir + \setbox1=\vbox to 0pt{\vss\box\@partmarksbox}% + \ifvmode + \box1 + \else + \vadjust{\box1}% + \fi + \else +% \end{macrocode} +% Generally the \cmd|env//end| hook seems to +% produce better results, in terms of positioning things at the end of +% environments, but this does not work for environments +% where the command is located inside a display (ie, in \TeX\ terms, +% inside |$$...$$|); in these situations we have to use the +% \texttt{.../after} hook instead. Such displays are most typically amsmath +% alignment environments, but an \cmd|\halign| inside a display will +% also qualify (see the discussion of `alignment displays' in \TeX +% Book ch.19). There isn't a completely straightforward way of +% detecting this situation (though amsmath's \cmd|\start@align| sets +% \cmd|\xatlevel@| to be non-\cmd|\@empty|, which we take to indicate the +% amsmath case), so we have to rely on the caller of this +% command to invoke the \texttt{...@display} or \texttt{...@nodisplay} +% variant appropriately. +% \begin{macrocode} + \if@tempswa % display variant + \AddToHookNext{env/\@currenvir/after}{% + %\typeout{hook:endenv/display #1}% + \ifvmode\box\@partmarksbox + \else\vadjust{\box\@partmarksbox}\fi}% + \else + \AddToHookNext{env/\@currenvir/end}{% + %\typeout{hook:endenv/nodisplay: env/\@currenvir/end #1}% + \ifvmode\box\@partmarksbox + \else\vadjust{\box\@partmarksbox}\fi}% + \fi + \fi +} +% \end{macrocode} +% +% First, define the questions version, for appearing in the version candidates see. +% Here, \cmd|#1| is the possibly empty `classification' text, and \cmd|#2| is the +% number of marks. At this point |\if@tempswa| is true if we got here +% via the \cmd|\partmarks*| variant, and false if it's the unstarred one. +% +% The argument |#2| must be a number: any non-number text will not +% cause an error but will appear in the text. +% +% But first\dots! +% +% The |\partmarks| command increments a global counter, and we +% \emph{don't} want to do this when an \Lpackage{amsmath} alignment is evaluating +% the content in its `measuring' phase. Fortunately, +% \Lpackage{amsmath} has an (internal) flag |\ifmeasuring@| which is +% true in that phase, which it uses for this purpose, so make this macro a no-op in that case. +% \begin{macrocode} +\def\@@partmarks@question{% + \ifmeasuring@ + \let\@@partmarksnext\@gobbletwo + \else + \let\@@partmarksnext\@@partmarks@question@do + \fi + \@@partmarksnext +} +% \end{macrocode} +% On with the main business. +% \begin{macrocode} +\def\@@partmarks@question@do#1#2{% + \global\advance\marktotal #2 + \let\@@partmarksnext\relax % base case +% \end{macrocode} +% Display the `part category', \emph{visible in the question}, +% if \Lopt{showsolutions} is true, either +% explicitly, or implicitly as a consequence of the +% compose/draft/final mode. It's arguable that this should be +% dependent on the mode only, but after some discussion, it ended up +% seeming more reasonable to tie this to \Lopt{showsolutions} directly. +% \begin{macrocode} + \if@showsolutions + \def\@tempa{#1}% + \ifx\@tempa\@empty + \ifx\examn@defaultpartmarkscategory\relax + \let\examn@category\relax \else - \vadjust{\nointerlineskip\box0}% + \examn@makepartmarkscomment{\highlighted{\examn@defaultpartmarkscategory}}% \fi \else - \global\advance\marktotal #1 - \if@tempswa + \examn@makepartmarkscomment{\highlighted{#1}}% + \fi + \fi % \end{macrocode} -% This is the starred form of |\partmarks|. That is, this is being invoked -% (i) just after maths (or some other display which doesn't fill the line), -% \emph{or} (ii) at the end of an unnumbered equation. In case (i), -% we move the part mark up a bit; in case (ii), we format the -% partmarks as a type of equation number -% -% We handle case (ii) first, by detecting whether we're in a maths -% display. If so, we format the partmarks as an equation number, using -% |\eqno|. Note that \Lpackage{amsmath} maths (which is what we're -% using here) formats this differently if the material following -% |\eqno| is of zero size, so we make this slightly larger than that. -% \begin{macrocode} - \ifdim\displaywidth>0pt - \if@eqnsw - \ClassError{exam-n}{\string\partmarks* may not be used - within numbered equations}{Replace \string\partmarks* - with a \string\partmarks\ after the equation} - \global\advance\marktotal -#1 % to cause the mark total to be wrong - \else - \eqno \hbox to 1sp{\FormatPartMarks{#1}\hfil}% - \fi +% +% If |\@tempswa|, then this is the starred form of |\partmarks|. +% This is intended to be used only occasionally, after a display or +% list environment, where for some reason the command can't go inside +% the environment. +% \begin{macrocode} + \if@tempswa + \ifdim\displaywidth>0pt + \ClassError{exam-n} + {Don't use \partmarks* inside a display} + {Use \partmarks inside the display, or \partmarks* + after it, if necessary} % \end{macrocode} -% Case (i), not in maths: We don't automatically end the -% paragraph here, because a display will often not be the end of a paragraph. -% I am not at all convinced that this is the correct approach -% to nudging the partmarks text up the right amount. The -% following appears to do roughly the right thing, but there's a -% strong element of trial and error in it. +% Else we are most likely just after an equation or just after a list +% environment, or something similar. +% (here and below we include some |{#2:n}| debugging code for when I, +% inevitably, revisit this to worry about the spacing). % \begin{macrocode} - \else - \setbox0=\vbox to 0pt{\vss - \hbox to \textwidth{\strut\hfill\FormatPartMarks{#1}}% - \vskip 1\baselineskip}% vskip means box has zero depth - \ifvmode - \box0 - \else - \vadjust{\box0}% - \fi + \else + \@@partmarks@endenv@nodisplay{#2}%{#2:1*}% + \fi +% \end{macrocode} +% We've called the unstarred version of |\partmarks|. +% This is the more usual mode. +% \begin{macrocode} + \else + \ifdim\displaywidth>0pt +% \end{macrocode} +% We're in a display, after |$$|: \TeX\ is probably (but not certainly) in +% maths mode just now; if we're in an amsmath alignment, we're in +% specifically inner maths mode; there are other, rarer, ways of being +% in an `alignment display'. Additionally, and commonly, if we're in +% an \Lenv{equation} environment now -- which we can detect because +% that, amongst other amsmath environments, sets |\eqnsw| to be true +% -- then we're \emph{not} in an alignment, but we \emph{are} in a +% case where the |\eqno| technique will fail (with `You can't use +% `eqno' in math mode.'), so catch that. +% +% CONSIDER: is this |\@eqnsw| test in fact the only one I have to do +% -- is the inner math mode test equivalent? That is, is this, when +% it comes down to it, testing the actual thing I need to test here? +% This will require another dive into the amsmath magic. +% \begin{macrocode} + \@tempswafalse + \ifmmode\ifinner \else \@tempswatrue \fi\fi + \if@tempswa + \if@eqnsw % not so fast... we're in an {equation} + \@tempswafalse \fi + \fi + \if@tempswa % \end{macrocode} -% We've called the unstarred version of |\partmarks|. We also end the paragraph here -% (this technique is filched from the TeXBook, p106). +% We're in outer maths mode, which we can take to mean a |\[...\]| equation. +% In this case, we can very neatly position the partmarks indicator +% using |\eqno|. +% \begin{macrocode} + \def\@@partmarksnext{\eqno \hbox to 1sp{% the \eqno argument must not be zero size + \examn@getpartmarkscomment + \FormatPartMarks{#2}%{#2:1} + \hss}}% +% \end{macrocode} +% Or we're in one or other type of display. % \begin{macrocode} \else + \def\@@partmarksnext{\@@partmarks@endenv@display{#2}}% + %\def\@@partmarksnext{\@@partmarks@endenv@display{#2:2,\@currenvir}}% + \fi +% \end{macrocode} +% +% Otherwise, |\displaywidth=0pt|, and we're not in a display. +% If we are in the |{question}| environment, as opposed to any sub-environment, +% we end the paragraph here and put the partmarks indicator at the end +% of the final line of the paragraph (this technique is filched from the TeXBook, p106). +% Otherwise, we add a suitable box to an end-of-environment hook. +% +% Omitting the |{question}| test below, and handling all cases with +% the end-of-paragraph technique, works in most case, in the sense of +% looking fine. Where it fails is in the case of, eg, |{quote}|, +% where the end-of-line ends up indented from the right. +% +% Using the hook has the additional advantage that |\partmarks| can be anywhere +% within the environment and this locates it at the end. +% +% The dimension |\@partmarksspace| controls how much space the +% partmarks-number takes up, the default is the special case of 0pt, +% which puts it in the margin. +% \begin{macrocode} + \else + \def\@tempa{question}% + \ifx\@tempa\@currenvir \ifdim\@partmarksspace > 0pt {\unskip\nobreak\hfil\penalty50 \hskip\@partmarksspace - \hbox{}\nobreak\hfil\FormatPartMarks{#1}% + \hbox{}\nobreak\hfil\examn@getpartmarkscomment\FormatPartMarks{#2}%{#2:3}% \parfillskip=0pt \finalhyphendemerits=0 \par} \else - \unskip\nobreak\hfill\FormatPartMarks{#1}\par + \unskip\nobreak\hfill\examn@getpartmarkscomment\FormatPartMarks{#2}\par%{#2:4}\par \fi + \let\@@partmarksnext\relax + \else + \def\@@partmarksnext{\@@partmarks@endenv@nodisplay{#2}}% + %\def\@@partmarksnext{\@@partmarks@endenv@nodisplay{#2:5,\@currenvir}}% \fi \fi - \else - \ClassError{exam-n}{\string\partmarks\ is not compatible with - noperquestionmarks}{Either remove \string\partmarks\ or remove - the noperquestionmarks option} \fi +% \end{macrocode} +% +% The `question' variant of this macro includes an |\ignorespaces| at the +% end, since that is generally the right thing to do (the command +% almost always appears at the end of paragraphs, or after equations). +% \begin{macrocode} + \@@partmarksnext \ignorespaces } % \end{macrocode} +% Then the solutions version, for the benefit of markers, which is +% typically more finely itemized, and which isn't summed (ie, we don't +% at present confirm that the marks here match the question's marks goal). +% The solutions variant of this macro omits the |\ignorespaces| +% (since in solutions this macro is scattered within the text). +% Setting |\dp0=0pt| is probably unnecessary, but guarantees that box0 +% has zero depth, so no extra vertical space appears because of +% this new box. +% \begin{macrocode} +\def\@@partmarks@solution#1#2{% + \setbox0=\vbox to 0pt{\vss + \hbox to \textwidth{\hfil\hbox to 0pt{\quad\small[\dots #2]\hss}} + \vskip0.25ex }% + \dp0=0pt + \ifvmode + \box0 + \else + \vadjust{\nointerlineskip\box0}% + \fi +} +% \end{macrocode} % % The code above permits page-breaks between lists and |\partmarks|. % That's because |\@endparenv|, which is called within |\endtrivlist|, @@ -2340,7 +2933,6 @@ images may not be used in examinations without prior arrangement. % \begin{macrocode} \@endparpenalty=\@M % \end{macrocode} - % % The number of marks is formatted by the command |\FormatPartMarks|, which % may be overridden, using |\renewcommand| in a |.clo| file. @@ -2430,7 +3022,7 @@ images may not be used in examinations without prior arrangement. % \begin{macrocode} \def\item{\@tempswafalse\ex@mcqitem} \def\answer{\@tempswatrue\ex@mcqitem} -% \end{macrocode +% \end{macrocode} % Initialise counters, and invoke the common |\do@question| macro. % \begin{macrocode} \ex@mcqi=0 @@ -2863,9 +3455,15 @@ images may not be used in examinations without prior arrangement. % \end{macrocode} % % The |\includequestion| command includes a question from another -% file. For convenience, we disable |\documentclass|, |\usepackage|, and the +% file. For convenience, we disable +%|\documentclass|, |\usepackage|, |\RequirePackage|, and the % \Lenv{document} environment, so that the included file may be a % complete \LaTeX\ document. +% We don't try too hard to support including just any old \LaTeX, here: +% any complicated preamble requirements in an included file should +% probably be managed by the exams convener transplanting them into +% the preamble of the main document. This may be an overly +% simple-minded approach, and may change in future versions. % \begin{macrocode} \def\dummy@documentclass{% \@ifnextchar[\dummy@@documentclass{\dummy@@documentclass[]}} @@ -2877,7 +3475,7 @@ images may not be used in examinations without prior arrangement. \begingroup \let\documentclass\dummy@documentclass \let\document\@empty % not \relax: makes \begin think {document} is undef'd - \let\enddocument\relax + \let\enddocument\endinput % stop reading, discarding any junk below \end{document} \def\@tempa{#1} \ifx\@tempa\@empty \else \def\@includequestionoverridenumber{#1} @@ -2885,6 +3483,7 @@ images may not be used in examinations without prior arrangement. \fi \def\usepackage##1{\ClassWarning{exam-n} {Ignoring \string\usepackage{##1} in included question #2}} + \let\RequirePackage\usepackage \input{#2} \endgroup } @@ -2930,6 +3529,15 @@ images may not be used in examinations without prior arrangement. % Putting a box round the solution would be desirable (it keeps it all % together and would allow a coloured background), but that's rather % hard to arrange in practice. +% +% Solutions are shown in a slightly smaller size (namely |\small|). +% It's debatable whether this is a good thing or not. Note that if +% this is changed by removing the |\small|, then +% |\examn@dummycaptions| will have to be adjusted, too. +% +% If either of the `enlarged font' options has been given, then we set +% the solutions in the same large font, since these might be +% distributed to students as model answers. % \begin{macrocode} \def\@formatsolution{\par \if@insolution @@ -2937,7 +3545,7 @@ images may not be used in examinations without prior arrangement. \else \@insolutiontrue % this happens within a group \fi - \examn@dummycaptions % dummy captions within solutions + \examn@dummycaptions % dummy captions within solutions \typeout{SHOWING SOLUTIONS} \let\part\examn@solutionpart % \end{macrocode} @@ -2948,9 +3556,7 @@ images may not be used in examinations without prior arrangement. \parskip 0.5\baselineskip \raggedright \color{solutiontext}%\slshape - \ifbigfont \else - \small - \fi + \normalsize \hrule \hbox to \textwidth{\vrule height 1ex \hfil \vrule height 1ex} \nobreak @@ -2984,20 +3590,32 @@ images may not be used in examinations without prior arrangement. \if@showsolutions \let\solution\@formatsolution \let\endsolution\end@formatsolution +% \end{macrocode} +% In the case where we're not showing solutions, note that we +% \emph{do} format the contents, so any |\global| effects will still +% happen, unless we take action to avoid them. +% +% In particular, |\part|, which is normally redefined in solutions to +% increment \texttt{answerpartnumber} rather than +% \texttt{partnumber}, would increment \texttt{partnumber} in answers +% unless we take action to stop it. +% \begin{macrocode} \else - \def\solution{% + \def\solution{% make a vbox... + \par \if@insolution \ClassError{exam-n}{Misplaced solution}{You can't have a solution within a solution} \fi \let\endfigure\endfloat@skipsolutions \let\endtable\endfloat@skipsolutions - \examn@dummycaptions % dummy captions avoid counter increments + \examn@dummycaptions % dummy captions avoid counter increments + \let\part\relax % make \part a no-op in discarded {solution} \@ifundefined{includepdf}{}{\let\includepdf\examn@disabledpdfpages} - \par \setbox\@tempboxa\vbox\bgroup - \@insolutiontrue} - \def\endsolution{% - \egroup % ...and do nothing with this box + \@insolutiontrue + } + \def\endsolution{%...and do nothing with this box + \egroup } \fi % \end{macrocode} @@ -3025,9 +3643,14 @@ images may not be used in examinations without prior arrangement. % re-using the standard LaTeX parameter means that \caption works \def\@captype{#1} \setbox\@tempboxa\vbox\bgroup} +% \end{macrocode} +% End both |{figure}| and |{table}| environments. +% End the |\@tempboxa| and add some space and good breaks before displaying it. +% We're typically in hmode here, but don't depend on it. +% \begin{macrocode} \def\examn@endfloat{% \egroup % end \@tempboxa - \unskip + \ifvmode\else \unskip \fi % bare \unskip would can an error in vmode \nobreak % add lots of stretchability, but non-infinite, for the sake of tidiness \vskip 0pt plus 0.5\textheight @@ -3055,6 +3678,18 @@ images may not be used in examinations without prior arrangement. \let\endfigure\examn@endfloat \let\endtable\examn@endfloat % \end{macrocode} +% And disable the \texttt{figure*} and \texttt{table*} environments. +% \begin{macrocode} +\expandafter\def\csname figure*\endcsname{% + \ClassError{exam-n} + {Bad environment figure* -- there is no figure* environment in exam-n} + {Use plain {figure} instead. See the documentation for discussion}} +\expandafter\def\csname table*\endcsname{% + \ClassError{exam-n} + {Bad environment table* -- there is no table* environment in exam-n} + {Use plain {table} instead. See the documentation for discussion}} +% \end{macrocode} +% % Within these 'floats', we must redefine |\caption|, so that we don't % increment the float counters. One motivation for this is so that we don't have % table numbers changing depending on whether solutions are included @@ -3110,25 +3745,83 @@ images may not be used in examinations without prior arrangement. \WriteLastPageLabel} % \end{macrocode} % +% \iffalse extradefs:start +% This is a magic comment -- see Makefile. +% these definitions are referred to, in order to document +% them, both in this class's documentation, and in the +% notes-for-authors. \fi +% % \subsection{Other formatting niceties} % % Format vectors (the default for |\vec| is a symbol with an arrow % over it): +% +% Note: the STIX2+(XeLaTeX/LuaLaTeX) support depends on the LaTeX hook +% mechanism released in 2020. It therefore does not work on versions of +% LaTeX older than that. There is a check for this above (see +% Sect~\ref{s:compatibility}). % \begin{macrocode} -\ifcase\examn@mtselect - % mathptm fonts - % This is a very clumsy version, but it appears to be our only option - \def\vec#1{\mathchoice{\mbox{\boldmath $\displaystyle #1$}} - {\mbox{\boldmath $ #1$}} - {\mbox{\boldmath $\scriptstyle #1$}} - {\mbox{\boldmath $\scriptscriptstyle #1$}}} -\or % mathtime (should this be the same for mathtime as for mtpro2? +\if@psfonts + \ifcase\examn@mtselect + % mathptm fonts + % This is a very clumsy version, but it appears to be our only option + \def\vec#1{\mathchoice{\mbox{\boldmath $\displaystyle #1$}} + {\mbox{\boldmath $ #1$}} + {\mbox{\boldmath $\scriptstyle #1$}} + {\mbox{\boldmath $\scriptscriptstyle #1$}}} + \ifexamn@uprightpi + \ClassWarning{exam-n}{Can't do uprightpi in [mathptm] -- sorry} + \let\italicpi\pi + \examn@uprightpifalse + \fi + \or % mathtime (should this be the same for mathtime as for mtpro2? + \let\vec\mathbf + \ifexamn@uprightpi + \ClassWarning{exam-n}{Can't do uprightpi in [mathtime] -- sorry} + \let\italicpi\pi + \examn@uprightpifalse + \fi + \or % mtpro2 + \let\vec\mathbold + % \uppi is predefined in mtpro2 + \ifexamn@uprightpi + \let\italicpi\pi + \let\pi\uppi + \fi + \else + % STIX2: the unicode-math package provides a \symbf for bold math symbols, + \ifnum\examn@engine<2 % pdflatex + \let\vec\mathbf + % pdftex (or original tex) + % The following should, I think, create an upright pi, but doesn't + \def\uppi{\mathrm{\pi}} + \let\italicpi\pi %for consistency + \let\symup\mathrm %not fully the right thing, but avoid errors below + \else % xelatex or lualatex + % This is where the dependence on a recent LaTeX enters. + \let\vec\symbf + \typeout{stix2: upright=\ifexamn@uprightpi true\else false\fi} + \AddToHook{begindocument/end}{\gdef\uppi{\symup{𝜋}}} + \ifexamn@uprightpi + \AddToHook{begindocument/end}{\gdef\italicpi{\symit{𝜋}}\global\let\pi\uppi} + \fi + \fi + \fi +\else + % CM fonts: \mathbf doesn't work with greek in CM \let\vec\mathbf -\or % mtpro2 - \let\vec\mathbold + \ifexamn@uprightpi + % upright greek is hard to do portably, so give up + % See eg https://tex.stackexchange.com/questions/145926/ for discussion + \ClassWarning{exam-n}{Can't do uprightpi in [cmfonts] -- sorry} + \let\italicpi\pi + \let\uppi\pi %but avoid errors + \examn@uprightpifalse + \fi \fi % \end{macrocode} -% Abbreviations for degrees. +% +% Abbreviations for various degrees. % \begin{macrocode} \newcommand\BSc{B.Sc.{}} \newcommand\MSci{M.Sci.{}} @@ -3138,10 +3831,22 @@ images may not be used in examinations without prior arrangement. \newcommand\BEng{B.Eng.{}} % \end{macrocode} % -% Tweaks to differentials. +% Formatting differentials, and the base of natural logs, +% which should be in an upright font. +% See section~\ref{s:othercommands}, or the `notes for authors', +% for a description of these macros. +% The macro |\ddd| is used inside an integral, and includes a leading thinspace % \begin{macrocode} -\newcommand{\dd}{\mathrm{d}} -\newcommand{\ddd}{\,\mathrm{d}} % inside an integral, including thinspace +\ifnum\examn@mtselect>2 + % ie, STIX2, and thus using the unicode-math package (see above) + \def\e{\symup{e}} + \newcommand{\dd}{\symup{d}} + \newcommand{\ddd}{\,\symup{d}} +\else + \def\e{\mathrm{e}} + \newcommand{\dd}{\mathrm{d}} + \newcommand{\ddd}{\,\mathrm{d}} +\fi \def\Diffl{\@ifstar\@Difflflat\@Diffl} \def\Partial{\@ifstar\@Partialflat\@Partial} @@ -3165,19 +3870,31 @@ images may not be used in examinations without prior arrangement. \fi} % \end{macrocode} % -% The exponential sign -% \begin{macrocode} -\def\e{{\mathrm e}} -% \end{macrocode} +% Physical units in upright roman. This macro is now deprecated in +% favour of use of the \Lopt{siunitx} option (which uses the +% \Lpackage{siunitx} package, qv), and it will be removed in a +% minor release after v1.4. % -% Physical units in |\rm|. Unstarred version includes leading -% |\thinspace|. Starred version doesn't, and is used when referring to +% The unstarred version includes leading +% |\thinspace|. The starred version doesn't, and is used when referring to % the unit by itself (eg axis is |$B/\units*T$|), and is not qualifying % a number. -% FIXME: |\mu| in |\units| can come out wrong in some fonts (mtpro2?) -% -- needs investigation. +% Separate units with either \texttt{.} or |~|, as in |\units{m~s^{-1}}| or +% |\units{m.s^{-1}}|. +% Note that although \texttt{.} and |~| are both possible unit separators in +% general, the former won't work if used within a table (due to the timing of +% token-reading). +% +% This is a rather simple-minded approach to unit formatting. For a much more +% comprehensive treatment, see the \texttt{siunitx} package, +% \url{https://ctan.org/pkg/siunitx}, which is now preferred, in place +% of further use of this macro. +% +% Note: there are detailed prescriptions on the formatting of units and symbols in +% ISO-80000-1:2009, Sect. 7. % \begin{macrocode} -\def\units{\begingroup +\def\units{\examn@unitswarning + \begingroup \catcode`\.=\active \@ifstar{\let\un@tsspace\relax \un@ts}% {\let\un@tsspace\thinspace\un@ts}} @@ -3191,18 +3908,15 @@ images may not be used in examinations without prior arrangement. \fi \endgroup} \endgroup -% \end{macrocode} -% -% Other miscellaneous symbols: -% The AU is nothing exciting, but may be adjusted in future -% \begin{macrocode} -\def\au{au} -% \end{macrocode} -% The symbol for Compton wavelength is a crossed lambda -- the following isn't perfect, but is OK for now. -% \begin{macrocode} -\def\lambdabar{\setbox\@tempboxa\hbox{$\lambda$}% - \hbox to 0pt{\hbox to \wd\@tempboxa{\hss$\bar{}$\hss}\hss}\box\@tempboxa} -% \end{macrocode} +\newif\ifexamn@warnunits \examn@warnunitstrue +\def\examn@unitswarning{\ifexamn@warnunits + \ClassWarning{exam-n}{The units macro will be removed in the next + version; the [siunitx] option is now on by default, so you can use + the macros in the siunits package}% + \global\examn@warnunitsfalse +\fi} +% \end{macrocode} +% \iffalse extradefs:end % magic comment -- see Makefile \fi % % All done. % \begin{macrocode} diff --git a/Master/texmf-dist/source/latex/exam-n/release-notes.dtx b/Master/texmf-dist/source/latex/exam-n/release-notes.dtx new file mode 100644 index 00000000000..84cde9c3a5e --- /dev/null +++ b/Master/texmf-dist/source/latex/exam-n/release-notes.dtx @@ -0,0 +1,43 @@ +% \begin{description}\item[1.4.0, 2022 October 10]\relax \P\thinspace The [siunitx] option is now on by default, and the +% |\units| macro produces a one-time-per-document +% warning that it will be removed in the next version. \P\thinspace Having two |\partmarks| commands in an +% environment is now detected as an error (it was documented as an +% error, but not checked, so the extra |\partmarks| +% commands were simply ignored).\par\item[1.4.0-b1, 2022 August 7]\relax \P\thinspace The class file now depends on a version of LaTeX which is at least +% the 2020/10/01 release. This is so that we can use the current LaTeX +% hooks mechanism. \P\thinspace Rework |\partmarks|: the |\partmarks| +% indicator can now go \emph{inside} most environments, including +% list, quotes, unnumbered equations, and the various amsmath displays. In these +% cases, the indicator will automatically appear at the end of the +% environment. The starred variant of the command still exists, but +% should rarely be necessary.\par\item[1.3.5-b1, 2022 July 11]\relax \P\thinspace Fix erroneous broken line before |\partmarks|, in +% compose mode, when a paragraph fills the last line. \P\thinspace Fix support for STIX2 fonts in XeLaTeX and LuaLaTeX (it was +% working inaccurately before). \P\thinspace Add an optional argument for |\part| to override part numbering. \P\thinspace Use the |xcolor| package for colour management, instead +% of the core |color| package (the |xcolor| +% package is well-known and stable, and this means that we are +% compatible with TikZ). \P\thinspace |\partmarks| in solutions no longer gobble trailing space +% (doing so is probably right in questions, and is still the case, but +% |\partmarks| in solutions tend to be more interspersed with +% text). \P\thinspace |\label| within a |\part| now refers to the +% part number (as opposed to the question number). \P\thinspace Avoid a ‘You can't use `\unskip' in vertical mode’ error, +% in certain circumstances. \P\thinspace Add the |[siunitx]| option, indicating that we should +% load the siunitx\footnote{\url{https://www.ctan.org/pkg/siunitx}} package (default no). +% This is now preferred to the |\units| macro, and the latter will be +% removed in a forthcoming release. \P\thinspace Renamed |A1.clo| to clearer |myclass.clo| \P\thinspace Repository moved from bitbucket to +% https://heptapod.host/nxg/exam-n\footnote{\url{https://heptapod.host/nxg/exam-n}}, +% when bitbucket dropped support for Mercurial. +% This means, incidentally, that links to specific issues at bitbucket +% are now broken. \P\thinspace Bold-italic maths should now work correctly with STIX. \P\thinspace Long |\partmarks| comments now appear as footnotes. \P\thinspace Solutions are now set |\normalsize|. \P\thinspace Bugfix: move definition of |\defaultpartmarkscategory| +% so it can be invoked within a |.clo| file straightforwardly. \P\thinspace Define the |[uprightpi]| option to set |\pi| +% as an upright character, as appropriate for a constant (this is +% implemented fully only for the |[mtpro2]| and +% |[stix2]| options).. \P\thinspace Note that the |\units| macro is likely to be deprecated +% in a forthcoming version, and replaced by a recommendation to use the +% standard |[siunitx]| package.\par\item[1.3, 2018 November 21]\relax \P\thinspace Add a ‘category’ optional argument to |\partmarks|, and +% add |\defaultpartmarkscategory|.\par\item[1.2.1, 2018 July 2]\relax \P\thinspace Bugfix: ignore any content which appears after +% |\end{document}|, in |\includequestion| (author) +% files (fixes issue 6). \P\thinspace The environments |{figure*}| and |{table*}| now produce an error. \P\thinspace The macro |\vec| now produces correct greek bold maths. \P\thinspace Docmentation: notes on unit formatting.\par\item[1.2, 2017 December 1]\relax \P\thinspace Use serif STIX2 fonts for sans and monospace cases, when using +% Lua- or XeLaTeX (the style doesn't use/encourage any sans-serif text, +% so this shouldn't matter). \P\thinspace Fix font sizes in solutions. \P\thinspace Adjustments to font-handling, which appear to have fixed LuaLaTeX differences. \P\thinspace Add the |stix2| option, to use the +% STIX2 font set\footnote{\url{http://www.stixfonts.org/}}. \P\thinspace Make it possible to use |\rubric| and |\baserubric| within a |.clo| file. +% This was advertised as being possible, but it seems it had never been tested!\par\end{description} \ No newline at end of file -- cgit v1.2.3