handouts/resources/ormc_handout.cls

476 lines
10 KiB
OpenEdge ABL
Raw Normal View History

2023-03-01 09:04:12 -08:00
% Mark's handout style.
%
% Source is at https://git.betalupi.com/Mark/ormc-handouts
2023-01-12 10:30:53 -08:00
\NeedsTeXFormat{LaTeX2e}
2023-05-13 17:11:33 -07:00
\ProvidesClass{ormc_handout}[2023/05/13 1.2.0 ORMC Handout]
2023-01-12 10:30:53 -08:00
% Boolean that determines solution behavior.
% If false, solutions and instructor notes are hidden.
\newif{\ifsolutions}
\solutionstrue
% Boolean that determines object numbering
% If true, the same counter is used for all objects.
\newif{\ifsinglenumbering}
\singlenumberingfalse
% Boolean. If true, don't number pages.
\newif{\ifnopagenumber}
\nopagenumberfalse
2023-03-01 09:04:12 -08:00
% Boolean. If true, show a smaller solutions warning
\newif{\ifshortwarning}
\shortwarningfalse
2023-03-23 09:51:10 -07:00
% Boolean. If true, do not show solution warning
\newif{\ifnowarning}
\nowarningfalse
2023-01-12 10:30:53 -08:00
% Declare and parse arguments
\DeclareOption{solutions}{\solutionstrue}
\DeclareOption{nosolutions}{\solutionsfalse}
\DeclareOption{singlenumbering}{\singlenumberingtrue}
\DeclareOption{nopagenumber}{\nopagenumbertrue}
2023-03-01 09:04:12 -08:00
\DeclareOption{shortwarning}{\shortwarningtrue}
2023-03-23 09:51:10 -07:00
\DeclareOption{nowarning}{\nowarningtrue}
2023-01-12 10:30:53 -08:00
\DeclareOption*{\ClassWarning{ormc_handout}{\CurrentOption ignored}}
\ProcessOptions\relax
% Based on article class
\LoadClass{article}
\makeatletter % Allow commands with @ (\makeatother is at end of this file)
\newcommand\sbullet[1][.5]{\mathbin{\vcenter{\hbox{\scalebox{#1}{$\bullet$}}}}}
\renewcommand{\labelitemi}{$\sbullet$}
\renewcommand{\labelitemii}{$\cdot$}
% 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{<target file>}
% and build that with latex.
\ifdefined\argYesSolutions
\solutionstrue
\else
\ifdefined\argNoSolutions
\solutionsfalse
\fi
\fi
%%% PACKAGES %%%
% Set up page geometry.
% MUST BE DONE FIRST!
\RequirePackage{geometry}
\geometry{
paper = letterpaper,
top = 25mm,
bottom = 30mm,
left = 30mm,
right = 30mm,
headheight = 75mm,
footskip = 15mm,
headsep = 75mm,
}
\RequirePackage{enumitem} % list customization
\RequirePackage{xparse} % Provides powerful macros via \NewDocumentCommand
\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
2023-05-13 17:11:33 -07:00
\tcbuselibrary{breakable}
2023-01-12 10:30:53 -08:00
\RequirePackage[
left = ``,
right = '',
leftsub = `,
rightsub = '
]{dirtytalk}
% Not used by this class, but likely to be used in documents
\RequirePackage{amsmath}
\RequirePackage{amssymb}
\RequirePackage{multicol}
%%% CONFIG %%%
% No paragraph indentation, no list item spacing,
% raggedright layout (hyphenation is excessive).
\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}
2023-05-03 22:39:18 -07:00
\IfNoValueF{#1}{\textsc{#1}} \hfill \IfNoValueF{#2}{\textsc{#2}} \par
\rule{\linewidth}{0.2mm} \par
2023-01-12 10:30:53 -08:00
\huge
2023-05-03 22:39:18 -07:00
#3 \par
2023-01-12 10:30:53 -08:00
\normalsize
\vspace{1ex}
#4
2023-05-03 22:39:18 -07:00
\rule{\linewidth}{0.2mm} \par
2023-01-12 10:30:53 -08:00
% Instructor's handout warning
2023-03-23 09:51:10 -07:00
\ifnowarning\else
2023-01-12 10:30:53 -08:00
\ifsolutions
2023-03-01 09:04:12 -08:00
% Short warning
\ifshortwarning
\begin{tcolorbox}[
colback=white,
colframe=red
]
\begin{center}
\large
\textcolor{red}{
\textbf{Instructor's Handout}
2023-05-03 22:39:18 -07:00
} \par
2023-03-01 09:04:12 -08:00
\normalsize
\end{center}
\end{tcolorbox}
\else
% Regular warning
\begin{tcolorbox}[
colback=white,
colframe=red
]
\begin{center}
\large
\textcolor{red}{
\textbf{Instructor's Handout}
2023-05-03 22:39:18 -07:00
} \par
2023-03-01 09:04:12 -08:00
\normalsize
\end{center}
\vspace{1ex}
\textcolor{red}{This file contains solutions and notes.}
\textcolor{red}{Compile with the ``nosolutions'' flag before distributing.}
\end{tcolorbox}
\fi
2023-03-23 09:51:10 -07:00
\fi\fi
2023-01-12 10:30:53 -08:00
\end{center}
\end{adjustbox}
}
% 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}{}}
}
}
% 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{}<gcd>
% makes a problem and a label "problem:gcd"
% that gives text "Problem X" when referenced.
\newcounter{section_counter}
\newcounter{problempartcounter}
\ifsinglenumbering
\newcounter{object_counter}
\def\problemcounter{object_counter}
\def\theoremcounter{object_counter}
\def\definitioncounter{object_counter}
\def\examplecounter{object_counter}
\def\propositioncounter{object_counter}
\else
\newcounter{problem_counter}
\newcounter{theorem_counter}
\newcounter{definition_counter}
\newcounter{example_counter}
\newcounter{proposition_counter}
\def\problemcounter{problem_counter}
\def\theoremcounter{theorem_counter}
\def\definitioncounter{definition_counter}
\def\examplecounter{example_counter}
\def\propositioncounter{proposition_counter}
\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}
2023-05-03 22:39:18 -07:00
{\bf\normalsize #1} \\lat*
2023-01-12 10:30:53 -08:00
\IfNoValueF{#2}{
\customlabel{#2}{#1}
}
}
% If not starred, text is "Part X: <title>"
% 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}
}
\NewDocumentCommand{\problem}{ m d<> }{
\setcounter{problempartcounter}{0}
\@object{\problemcounter}[Problem]{#1}
\IfNoValueF{#2}{
\customlabel{#2}{Problem \arabic{\problemcounter}}
\customlabel{NUM:#2}{\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}}
} \\*
}
% 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}
}
\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}[
2023-05-13 17:11:33 -07:00
breakable,
2023-01-12 10:30:53 -08:00
colback=red!5!white,
colframe=red!75!black,
title={\textbf{Solution}}
]
\raggedright
}{
\end{tcolorbox}
}
\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}
}
% 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);
\draw[
color=#1,
dashed,
dash phase=1mm
]
(
0 - \kvtcb@leftlower-\kvtcb@boxsep,
0
) -- (
\linewidth + \kvtcb@rightlower + \kvtcb@boxsep,
0
);
2023-05-03 22:39:18 -07:00
\end{tikzpicture} \par
2023-05-06 10:18:55 -07:00
\vspace{2mm}
2023-01-12 10:30:53 -08:00
}
}
\ifsolutions
\newenvironment{solution}{
\@makelinehack{red!75!black}
\begin{@shown_solution}
} {
\end{@shown_solution}
}
\newenvironment{instructornote}{
\@makelinehack{cyan!75!black}
\begin{@shown_note}
} {
\end{@shown_note}
}
\else
\excludecomment{solution}
\excludecomment{instructornote}
\fi
\NewDocumentCommand{\note}{ d<> m }{
\IfNoValueTF{#1} {
2023-05-03 22:39:18 -07:00
\textcolor{gray}{#2} \par
2023-01-12 10:30:53 -08:00
} {
2023-05-03 22:39:18 -07:00
\textcolor{gray}{\textit{#1:} #2} \par
2023-01-12 10:30:53 -08:00
}
}
\NewDocumentCommand{\hint}{ m }{
\note<Hint>{#1}
}
\makeatother