diff --git a/resources/ormc_handout.cls b/resources/ormc_handout.cls old mode 100644 new mode 100755 index 1d977b6..63e5b62 --- a/resources/ormc_handout.cls +++ b/resources/ormc_handout.cls @@ -1,46 +1,60 @@ % Mark's math circle handout style. % Source is at https://git.betalupi.com/Mark/ormc-handouts - - \NeedsTeXFormat{LaTeX2e} -\ProvidesClass{ormc_handout}[2023/05/14 1.2.2 ORMC Handout] +\ProvidesClass{ormc_handout}[2023/05/25 2.0.0 ORMC Handout] -% Boolean that determines solution behavior. -% If false, solutions and instructor notes are hidden. -\newif{\ifsolutions} -\solutionstrue +% ------------------ % +% Option Definitions % +% ------------------ % -% Boolean that determines object numbering -% If true, the same counter is used for all objects. -\newif{\ifsinglenumbering} -\singlenumberingfalse +\newif{\if@solutions} % If false, solutions and instructor notes are hidden. +\newif{\if@singlenumbering} % If true, the same counter is used for all objects. +\newif{\if@nopagenumber} % If true, don't number pages. +\newif{\if@shortwarning} % If true, show a smaller solutions warning +\newif{\if@nowarning} % If true, do not show solution warning -% Boolean. If true, don't number pages. -\newif{\ifnopagenumber} -\nopagenumberfalse - -% Boolean. If true, show a smaller solutions warning -\newif{\ifshortwarning} -\shortwarningfalse - -% Boolean. If true, do not show solution warning -\newif{\ifnowarning} -\nowarningfalse - -% Declare and parse arguments -\DeclareOption{solutions}{\solutionstrue} -\DeclareOption{nosolutions}{\solutionsfalse} -\DeclareOption{singlenumbering}{\singlenumberingtrue} -\DeclareOption{nopagenumber}{\nopagenumbertrue} -\DeclareOption{shortwarning}{\shortwarningtrue} -\DeclareOption{nowarning}{\nowarningtrue} +\DeclareOption{solutions}{\@solutionstrue} +\DeclareOption{nosolutions}{\@solutionsfalse} +\DeclareOption{multinumbering}{\@singlenumberingfalse} +\DeclareOption{singlenumbering}{\@singlenumberingtrue} +\DeclareOption{pagenumber}{\@nopagenumberfalse} +\DeclareOption{nopagenumber}{\@nopagenumbertrue} +\DeclareOption{longwarning}{\@shortwarningfalse} +\DeclareOption{shortwarning}{\@shortwarningtrue} +\DeclareOption{showwarning}{\@nowarningfalse} +\DeclareOption{hidewarning}{\@nowarningtrue} \DeclareOption*{\ClassWarning{ormc_handout}{\CurrentOption ignored}} -\ProcessOptions\relax + +\ExecuteOptions{ + solutions, + multinumbering, + pagenumber, + longwarning, + yeswarning +} + +\ProcessOptions + +% Hack to allow script option override. +% To force a build with solutions, compile a file containing the following: +% `\def\argYesSolutions{1}\input{}` +\ifdefined\argYesSolutions\solutionstrue\fi +\ifdefined\argNoSolutions\solutionsfalse\fi + + + + + + + + +\RequirePackage{etoolbox} % Based on article class \LoadClass{article} -\makeatletter % Allow commands with @ (\makeatother is at end of this file) +\undef\maketitle +\undef\section \newcommand\sbullet[1][.5]{\mathbin{\vcenter{\hbox{\scalebox{#1}{$\bullet$}}}}} @@ -48,33 +62,18 @@ \renewcommand{\labelitemii}{$\cdot$} \renewcommand{\labelenumi}{\textbf{\Alph{enumi}:}} -% Hack for command-line arguments. -% To force a build with solutions, run -% latexmk -% -synctex=1 -% -interaction=nonstopmode -% -file-line-error -% -outdir=%OUTDIR% -% -xelatex -% -jobname=%DOCFILE%.sol -% -pdfxelatex="xelatex %O \"\\def\\argYesSolutions{1}\\input{%S}\"" -% %DOC% -% -% Or, make a new file with the contents -% \def\argYesSolutions{1}\input{} -% and build that with latex. -\ifdefined\argYesSolutions - \solutionstrue -\else - \ifdefined\argNoSolutions - \solutionsfalse - \fi -\fi -%%% PACKAGES %%% + + + + + +% ------------- % +% Package Setup % +% ------------- % % Set up page geometry. @@ -91,18 +90,14 @@ headsep = 75mm, } -\RequirePackage{enumitem} % list customization -\RequirePackage{xparse} % Provides powerful macros via \NewDocumentCommand +\RequirePackage{enumitem} % List customization \RequirePackage{xcolor} % For colored text -\RequirePackage{tcolorbox} % For solution boxes \RequirePackage{tikz} % Used by \boxlinehack \RequirePackage{comment} % Used to hide solutions -\RequirePackage{fancyhdr} % Header/Footer customization -\RequirePackage{adjustbox} % Used for title - +\RequirePackage{tcolorbox} % For solution boxes \tcbuselibrary{breakable} % Allows tcolorboxes to break across pages -\RequirePackage[ +\RequirePackage[ % Provides \say{} for quoted text. left = ``, right = '', leftsub = `, @@ -112,375 +107,271 @@ % Not used by this class, but likely to be used in documents \RequirePackage{amsmath} \RequirePackage{amssymb} -\RequirePackage{multicol} \RequirePackage{tabto} \TabPositions{1cm, 2cm, 3cm, 4cm, 5cm, 6cm, 7cm, 8cm} -%%% CONFIG %%% -% No paragraph indentation, no list item spacing, -% raggedright layout (hyphenation is excessive). + + +% ----------- % +% Style Setup % +% ----------- % + +\if@nopagenumber + \pagestyle{empty} +\else + \pagestyle{plain} +\fi + +\renewcommand*{\thefootnote}{\arabic{footnote}} \setlength{\parindent}{0mm} \setlist{noitemsep, topsep=0mm} \raggedright - -\renewcommand*{\thefootnote}{\arabic{footnote}} - -% One space after a period. \frenchspacing -% Fancyhdr setup -\pagestyle{fancy} -\fancyhf{} -\renewcommand{\headrulewidth}{0mm} - -\ifnopagenumber -\else - \fancyfoot[C]{\thepage} -\fi -%%% COMMANDS %%% -% Make a heading. -% Arguments: -% -% First: Top-left text -% Second: Top-right text -% Both are optional, but should only be provided TOGETHER. -% -% Third: Title -% Forth: author -\RenewDocumentCommand{\maketitle}{ d<> d<> m m } { - \begin{adjustbox}{minipage=0.7\textwidth, margin=0pt \smallskipamount,center} - \begin{center} - \IfNoValueF{#1}{\textsc{#1}} \hfill \IfNoValueF{#2}{\textsc{#2}} \par - \rule{\linewidth}{0.2mm} \par - \huge - #3 \par - \normalsize - \vspace{1ex} - #4 - \rule{\linewidth}{0.2mm} \par - % Instructor's handout warning - \ifnowarning\else - \ifsolutions - % Short warning - \ifshortwarning - \begin{tcolorbox}[ - colback=white, - colframe=red - ] - \begin{center} - \large - \textcolor{red}{ - \textbf{Instructor's Handout} - } \par - \normalsize - \end{center} - \end{tcolorbox} - \else - % Regular warning - \begin{tcolorbox}[ - colback=white, - colframe=red - ] - \begin{center} - \large - \textcolor{red}{ - \textbf{Instructor's Handout} - } \par - \normalsize - \end{center} - \vspace{1ex} +% ------------- % +% Handout Title % +% ------------- % - \textcolor{red}{This file contains solutions and notes.} +% These are in LaTeX by default, but we don't use them here. +% Undef them to avoid confusion. +\undef\thanks +\undef\author +\undef\date - \textcolor{red}{Compile with the ``nosolutions'' flag before distributing.} - \end{tcolorbox} - \fi - \fi\fi +% Additional title parameters +\def\@subtitle{\relax} +\def\@uptitlel{\relax} +\def\@uptitler{\relax} +\newcommand{\subtitle}[1]{\gdef\@subtitle{#1}} +\newcommand{\uptitlel}[1]{\gdef\@uptitlel{#1}} +\newcommand{\uptitler}[1]{\gdef\@uptitler{#1}} - \end{center} - \end{adjustbox} +\newcommand{\@shortwarning}{ + \begin{tcolorbox}[colback=white, colframe=red] + \large\centering\color{red} + \textbf{Instructor's Handout} \par + \end{tcolorbox} +} + +\newcommand{\@longwarning}{ + \begin{tcolorbox}[colback=white, colframe=red] + \color{red} + \begingroup + \large\centering + \textbf{Instructor's Handout} \par + \endgroup + \vspace{1ex} + This file contains solutions and notes. \par + Compile with the ``nosolutions'' flag before distributing. \par + \end{tcolorbox} +} + +\newcommand{\maketitle}{ + \begingroup + \centering + \begin{minipage}{0.7\textwidth} + \centering + + % Left and right headers (uptitle) + \def\uptitle{% + \if\@uptitlel\relax\else\textsc{\@uptitlel}\fi \hfill~% + \if\@uptitler\relax\else\textsc{\@uptitler}\fi \par + } + \if\@uptitlel\relax % If neither header is defined, + \if\@uptitlel\relax % don't insert an upper title. + \def\@uptitle{\relax} + \fi\fi\uptitle{} + + % Main title + \rule{\linewidth}{0.2mm} \par + \huge \@title \par \normalsize + \vspace{1ex} \@subtitle \par + \rule{\linewidth}{0.2mm} \par + + % Solution warning + \if@nowarning\else\if@solutions% + \if@shortwarning \@shortwarning% + \else \@longwarning% + \fi\fi\fi + \end{minipage} \par + \vspace{2ex} + \endgroup } + + + + + + +% ---------------- % +% Handout Sections % +% ---------------- % + % Helper command that creates a label with custom text. -% First arg: label name -% Second arg: custom text -\newcommand{\customlabel}[2]{% - \protected@write \@auxout {}{ - \string \newlabel {#1}{{#2}{}} +% Аrgs: label name, custom text +\newcommand{\@customlabel}[2]{% + \protected@write\@auxout{}{\string\newlabel{#1}{{#2}{}}}% +} + +\newcounter{section_counter} +\NewDocumentCommand{\section}{ m d<> }{ + \stepcounter{section_counter} + \vspace{8mm} + {\bf\Large \hfill Part \arabic{section_counter}\IfNoValueF{#1}{: #1} \hfill} + \IfNoValueF{#2}{\@customlabel{#2}Part \arabic{section_counter}} \\* + \vspace{2mm} +} + +% Generic object. +% Same format as \problem, \theorem, etc, but has no counter. +\NewDocumentCommand{\generic}{ m d<> }{ + \vspace{3mm} + {\bf\normalsize #1} \\* + \IfNoValueF{#2}{\@customlabel{#2}{#1}} +} + +% Make a new secion type. +% Args: command, counter, title. +\newcommand\@newobj[3]{ + \NewDocumentCommand{#1}{ m d<> }{ + \stepcounter{#2} + \generic{#3 \arabic{#2}:\IfNoValueF{##1}{ ##1}} + \IfNoValueF{##2}{\@customlabel{##2}{#3 \arabic{#2}}} } } - -% Commands for problems, theorems, and definitions -% -% Each of these take two arguments. For example: -% -% \problem{} makes an unnamed problem -% \problem{Division} makes a named problem -% \problem{} -% makes a problem and a label "problem:gcd" -% that gives text "Problem X" when referenced. - -\newcounter{section_counter} -\newcounter{problempartcounter} - -\ifsinglenumbering +\if@singlenumbering \newcounter{object_counter} + \def\@problemcounter{object_counter} - \def\problemcounter{object_counter} - \def\theoremcounter{object_counter} - \def\definitioncounter{object_counter} - \def\examplecounter{object_counter} - \def\propositioncounter{object_counter} + \@newobj{\definition}{object_counter}{Definition} + \@newobj{\theorem}{object_counter}{Theorem} + \@newobj{\proposition}{object_counter}{Proposition} + \@newobj{\example}{object_counter}{Example} \else \newcounter{problem_counter} \newcounter{theorem_counter} \newcounter{definition_counter} \newcounter{example_counter} \newcounter{proposition_counter} + \def\@problemcounter{problem_counter} - \def\problemcounter{problem_counter} - \def\theoremcounter{theorem_counter} - \def\definitioncounter{definition_counter} - \def\examplecounter{example_counter} - \def\propositioncounter{proposition_counter} + \@newobj{\definition}{definition_counter}{Definition} + \@newobj{\theorem}{theorem_counter}{Theorem} + \@newobj{\proposition}{proposition_counter}{Proposition} + \@newobj{\example}{example_counter}{Example} \fi - -% Generic object command. -% First arg: counter name (mandatory) -% Second arg: object type (optional) -% Third arg: object title (mandatory, can be empty) -% -% If the second argument is ommited, the counter is hidden -% and only the object title is shown. For example: -% \@object{counter}[Problem]{Example Problem} -> Problem 1: Example Problem -% \@object{counter}{Example Problem} -> Example Problem -% -% Only used internally (See following definitions) -\NewDocumentCommand{\@object}{ m d[] m}{ - \stepcounter{#1} - \vspace{3mm} - \IfNoValueTF{#2} { - {\bf\normalsize #3} - } { - {\bf\normalsize #2 \arabic{#1}:\IfNoValueF{#3}{ #3}} - } -} - -% Generic object. -% Does the same thing as \problem, \theorem, etc, but with no counter. -\NewDocumentCommand{\generic}{ m d<> }{ - \vspace{3mm} - {\bf\normalsize #1} \\lat* - - \IfNoValueF{#2}{ - \customlabel{#2}{#1} - } -} - -% If not starred, text is "Part X: " -% If starred, text is "<title>" -\RenewDocumentCommand{\section}{ s m d<> }{ - \stepcounter{section_counter} - \vspace{8mm} - \IfBooleanTF{#1}{ - {\bf\Large \hfill #2 \hfill} - \IfNoValueF{#3}{\customlabel{#3}#2} \\* - } { - {\bf\Large \hfill Part \arabic{section_counter}\IfNoValueF{#2}{: #2} \hfill} - \IfNoValueF{#3}{\customlabel{#3}Part \arabic{section_counter}} \\* - } - \vspace{2mm} -} - - -\RenewDocumentCommand{\paragraph}{}{ - \hspace{1cm} -} - +% These must be defined manually, since +% problems and problemparts use two counters. +\newcounter{problempartcounter} \NewDocumentCommand{\problem}{ m d<> }{ \setcounter{problempartcounter}{0} - - \@object{\problemcounter}[Problem]{#1} - \IfNoValueF{#2}{ - \customlabel{#2}{Problem \arabic{\problemcounter}} - \customlabel{NUM:#2}{\arabic{\problemcounter}} - } \\* + \stepcounter{\@problemcounter} + \generic{Problem \arabic{\@problemcounter}:\IfNoValueF{#1}{ #1}} + \IfNoValueF{#2}{\@customlabel{#2}{Problem \arabic{\@problemcounter}}} } - \NewDocumentCommand{\problempart}{ m d<> }{ - \@object{problempartcounter}[Part]{#1} - \IfNoValueF{#2}{ - \customlabel - {#2} - {Problem \arabic{\problemcounter}\alph{problempartcounter}} - \customlabel{NUM:#2}{\arabic{\problemcounter}\alph{problempartcounter}} - } \\* -} - -\NewDocumentCommand{\definition}{ m d<> }{ - \@object{\definitioncounter}[Definition]{#1} - \IfNoValueF{#2}{ - \customlabel{#2}{Definition \arabic{\definitioncounter}} - \customlabel{NUM:#2}{\arabic{\definitioncounter}} - } \\* -} - -\NewDocumentCommand{\theorem}{ m d<> }{ - \@object{\theoremcounter}[Theorem]{#1} - \IfNoValueF{#2}{ - \customlabel{#2}{Theorem \arabic{\theoremcounter}} - \customlabel{NUM:#2}{\arabic{\theoremcounter}} - } \\* -} - -\NewDocumentCommand{\proposition}{ m d<> }{ - \@object{\propositioncounter}[Proposition]{#1} - \IfNoValueF{#2}{ - \customlabel{#2}{Proposition \arabic{\propositioncounter}} - \customlabel{NUM:#2}{\arabic{\propositioncounter}} - } \\* -} - -\NewDocumentCommand{\example}{ m d<> }{ - \@object{\examplecounter}[Example]{#1} - \IfNoValueF{#2}{ - \customlabel{#2}{Example \arabic{\examplecounter}} - \customlabel{NUM:#2}{\arabic{\examplecounter}} - } \\* + \stepcounter{problempartcounter} + \generic{Part \arabic{problempartcounter}:\IfNoValueF{#1}{ #1}} + \IfNoValueF{#2}{\@customlabel{#2}{Problem \arabic{\@problemcounter}.\arabic{problempartcounter}}} } -% Solution environment. -% examplesolution environment is always shown (useful for example problems) -% solution environments do the same thing, but are hidden when the [nosolutions] flag is passed. -\newenvironment{examplesolution} { - \begin{tcolorbox}[ - colback=white, - colframe=gray!75!black, - title={\textbf{Example Solution}} - ] -}{ - \end{tcolorbox} -} + + + + + +% ---------------- % +% Box environments % +% ---------------- % + +% Keep track of the current background color. +% Useful for transparent tikz drawings. \def\ORMCbgcolor{white} -% \if isn't parsed inside of LaTeX environents, -% so we have to use the comment package. -\newenvironment{@shown_solution} { - \def\ORMCbgcolor{red!5!white} - \begin{tcolorbox}[ - breakable, - colback=red!5!white, - colframe=red!75!black, - title={\textbf{Solution}} - ] - \raggedright -}{ - \end{tcolorbox} -} +% Make a box environment. +% These can safely be nested. +% Args: name, title, back color, frame color. +\newcommand{\@makeORMCbox}[4]{ + \newenvironment{#1}{ + % \linehack draws a line across a tcolorbox. + % tcolorbox only supports two sections, but + % this hack allows us to have more. + \def\linehack{ + \begin{tikzpicture} + \path[use as bounding box] + (0, 0) -- + (\linewidth, 0); -\newenvironment{@shown_note} { - \def\ORMCbgcolor{cyan!5!white} - \begin{tcolorbox}[ - colback=cyan!5!white, - colframe=cyan!75!black, - title={\textbf{Note for Instructors}} - ] - \raggedright -}{ - \end{tcolorbox} -} + \draw[color=#4, dashed, dash phase=1mm] + (0 - \kvtcb@leftlower-\kvtcb@boxsep, 0) -- + (\linewidth + \kvtcb@rightlower + \kvtcb@boxsep, 0); + \end{tikzpicture} \par + \vspace{2mm} + } -% tcolorbox only give us two sections. -% This macro makes a macro \linehack that draws -% lines across a tcolorbox. -% -% Inside every environment that needs a -% \linehack macro, put \@makelinehack{color}. -\newcommand{\@makelinehack}[1]{ - \newcommand{\linehack}{ - \begin{tikzpicture} - \path[use as bounding box] - (0, 0) - -- - (\linewidth, 0); + % Keep track of the current background color. + % Useful for transparent tikz drawings. + \def\ORMCbgcolor{#3} - \draw[ - color=#1, - dashed, - dash phase=1mm - ] - ( - 0 - \kvtcb@leftlower-\kvtcb@boxsep, - 0 - ) -- ( - \linewidth + \kvtcb@rightlower + \kvtcb@boxsep, - 0 - ); - \end{tikzpicture} \par - \vspace{2mm} - } -} - -\ifsolutions - \newenvironment{solution}{ - % ifdefined hack allows for nested environments. - % could be done better, this doesn't preserve inner line color. - \ifdefined\linehack - \else - \@makelinehack{red!75!black} - \fi - \begin{@shown_solution} + \begin{tcolorbox}[ + breakable, + colback=#3, + colframe=#4, + title={\textbf{#2}} + ] + \raggedright } { - \end{@shown_solution} - } - \newenvironment{instructornote}{ - % ifdefined hack allows for nested environments. - % could be done better, this doesn't preserve inner line color. - \ifdefined\linehack - \else - \@makelinehack{cyan!75!black} - \fi - \begin{@shown_note} - } { - \end{@shown_note} + \end{tcolorbox} } +} + +\@makeORMCbox{examplesolution}{Example Solution}{white}{grey!75!black} + +\if@solutions + \@makeORMCbox{solution}{Solution}{red!5!white}{red!75!black} + \@makeORMCbox{instructornote}{Note for Instructors}{cyan!5!white}{cyan!75!black} \else \excludecomment{solution} \excludecomment{instructornote} \fi -\NewDocumentCommand{\note}{ d<> m }{ - \IfNoValueTF{#1} { - \textcolor{gray}{#2} \par - } { - \textcolor{gray}{\textit{#1:} #2} \par - } -} -\NewDocumentCommand{\hint}{ m }{ - \note<Hint>{#1} -} -\makeatother + + + + +% -------------------- % +% Misc helper commands % +% -------------------- % + +\NewDocumentCommand{\note}{ d[] m }{ + \IfNoValueTF{#1} + {\textcolor{gray}{#2}} + {\textcolor{gray}{\textit{#1:} #2}} + \par +} +\newcommand{\hint}[1]{\note[Hint]{#1}}