From 285f2e662f6dc37d227660aeb7624cac13004686 Mon Sep 17 00:00:00 2001
From: Norbert Preining <norbert@preining.info>
Date: Sun, 22 Aug 2021 03:00:40 +0000
Subject: CTAN sync 202108220300

---
 macros/latex/contrib/mandi/mandistudent.dtx | 1789 +++++++++++++++++++++++++++
 1 file changed, 1789 insertions(+)
 create mode 100644 macros/latex/contrib/mandi/mandistudent.dtx

(limited to 'macros/latex/contrib/mandi/mandistudent.dtx')

diff --git a/macros/latex/contrib/mandi/mandistudent.dtx b/macros/latex/contrib/mandi/mandistudent.dtx
new file mode 100644
index 0000000000..278725234c
--- /dev/null
+++ b/macros/latex/contrib/mandi/mandistudent.dtx
@@ -0,0 +1,1789 @@
+% \iffalse meta-comment
+% !TEX program = lualatexmk
+%
+% Copyright (C) 2021 by Paul J. Heafner <heafnerj@gmail.com>
+% ---------------------------------------------------------------------------
+% This  work may be  distributed and/or modified  under the conditions of the 
+% LaTeX Project Public  License, either  version 1.3  of this  license or (at 
+% your option) any later version. The  latest  version  of this license is in
+%            http://www.latex-project.org/lppl.txt
+% and  version 1.3 or  later is  part of  all distributions of  LaTeX version 
+% 2005/12/01 or later.
+%
+% This work has the LPPL maintenance status `maintained'.
+%
+% The Current Maintainer of this work is Paul J. Heafner.
+%
+% This work consists of the files mandi.dtx
+%                                 mandistudent.dtx
+%                                 mandiexp.dtx
+%                                 mandi.ins
+%                                 mandi.pdf
+%                                 README.md
+%
+% and includes the derived files  mandi.sty
+%                                 mandistudent.sty
+%                                 mandiexp.sty
+%                                 vdemo.py
+% ---------------------------------------------------------------------------
+%
+% \fi
+%
+% \iffalse
+%
+%<*internal>
+\iffalse
+%</internal>
+%
+%<*vdemo>
+from vpython import *
+
+scene.width = 400
+scene.height = 760
+# constants and data
+g = 9.8       # m/s^2
+mball = 0.03  # kg
+Lo = 0.26     # m
+ks = 1.8      # N/m
+deltat = 0.01 # s 
+
+# objects (origin is at ceiling)
+ceiling = box(pos=vector(0,0,0), length=0.2, height=0.01, 
+              width=0.2)
+ball = sphere(pos=vector(0,-0.3,0),radius=0.025,
+              color=color.orange)
+spring = helix(pos=ceiling.pos, axis=ball.pos-ceiling.pos,
+               color=color.cyan,thickness=0.003,coils=40,
+               radius=0.010)
+
+# initial values
+pball = mball * vector(0,0,0)      # kg m/s
+Fgrav = mball * g * vector(0,-1,0) # N
+t = 0
+
+# improve the display
+scene.autoscale = False        # turn off automatic camera zoom
+scene.center = vector(0,-Lo,0) # move camera down
+scene.waitfor('click')         # wait for a mouse click
+
+# initial calculation loop
+# calculation loop
+while t < 10:
+    rate(100)
+    # we need the stretch
+    s = mag(ball.pos) - Lo
+    # we need the spring force
+    Fspring = ks * s * -norm(spring.axis)
+    Fnet = Fgrav + Fspring
+    pball = pball + Fnet * deltat
+    ball.pos = ball.pos + (pball / mball) * deltat
+    spring.axis = ball.pos - ceiling.pos
+    t = t + deltat
+%</vdemo>
+%
+%<*internal>
+\fi
+\def\nameofplainTeX{plain}
+\ifx\fmtname\nameofplainTeX\else
+  \expandafter\begingroup
+\fi
+%</internal>
+%
+%<*internal>
+\usedir{tex/latex/mandi}
+\ifx\fmtname\nameofplainTeX
+  \expandafter\endbatchfile
+\else
+  \expandafter\endgroup
+\fi
+%</internal>
+%
+%<*driver>
+\ProvidesFile{mandistudent.dtx}
+\DisableCrossrefs         % index descriptions only
+\PageIndex                % index refers to page numbers
+\CodelineNumbered         % number source lines
+\RecordChanges            % record changes
+\begin{document}          % main document
+  \DocInput{\jobname.dtx} %
+  \PrintIndex             %
+\end{document}            % end main document
+%</driver>
+% \fi
+%
+% \CheckSum{706}
+%
+% \CharacterTable
+%  {Upper-case    \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
+%   Lower-case    \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
+%   Digits        \0\1\2\3\4\5\6\7\8\9
+%   Exclamation   \!     Double quote  \"     Hash (number) \#
+%   Dollar        \$     Percent       \%     Ampersand     \&
+%   Acute accent  \'     Left paren    \(     Right paren   \)
+%   Asterisk      \*     Plus          \+     Comma         \,
+%   Minus         \-     Point         \.     Solidus       \/
+%   Colon         \:     Semicolon     \;     Less than     \<
+%   Equals        \=     Greater than  \>     Question mark \?
+%   Commercial at \@     Left bracket  \[     Backslash     \\
+%   Right bracket \]     Circumflex    \^     Underscore    \_
+%   Grave accent  \`     Left brace    \{     Vertical bar  \|
+%   Right brace   \}     Tilde         \~}
+%
+% ^^A DO NOT TRY TO COMPILE THIS DTX FILE BY ITSELF. IT WILL FAIL.
+%
+% \section{The \mandistudent\ Package}\setplace{sec:mandistudentpkg}
+%
+% \mandi\ comes with an accessory package \mandistudent,
+% which provides a collection of commands physics students can 
+% use for writing problem solutions. This package focuses on 
+% the most frequently needed tools. These commands should always 
+% be used in math mode. Note that \mandistudent\ requires, and 
+% loads, \mandi\ but \mandi\ doesn't require, and doesn't load, 
+% \mandistudent.
+%
+% Load \mandistudent\ as you would any package in your preamble. 
+% There are no package options.
+%
+%\iffalse
+%<*example>
+%\fi
+\begin{dispListing*}{sidebyside=false,listing only}
+  \usepackage{mandistudent}
+\end{dispListing*}
+%\iffalse
+%</example>
+%\fi
+%
+%\iffalse
+%<*example>
+%\fi
+\begin{docCommand}{mandistudentversion}{}
+  Typesets the current version and build date.
+\end{docCommand}
+\begin{dispExample*}{sidebyside=false}
+  The version is \mandistudentversion\ and is a stable build.
+\end{dispExample*}
+%\iffalse
+%</example>
+%\fi
+%
+% \subsection{Traditional Vector Notation}
+%
+%\iffalse
+%<*example>
+%\fi
+\begin{docCommands}[%
+    doc parameter = \marg{symbol}\oarg{labels},%
+  ]%
+  {%
+    {%
+      doc name = vec,%
+      doc description = use this variant for boldface notation,%
+    },%
+    {%
+      doc name = vec*,%
+      doc description = use this variant for arrow notation,%
+    }%
+  }%
+  Powerful and intelligent command for symbolic vector notation. The 
+  mandatory argument is the symbol for the vector quantity. The optional 
+  label(s) consists of superscripts and/or subscripts and can be 
+  mathematical or textual in nature. If textual, be sure to wrap them in 
+  |\symup{...}| for proper typesetting. The starred variant gives arrow 
+  notation whereas without the star you get boldface notation. Subscript 
+  and superscript labels can be arbitrarily mixed, and order doesn't matter.
+  This command redefines the default \LaTeX\ |\vec| command.
+\end{docCommands}
+\begin{dispExample*}{lefthand ratio=0.6}
+  \( \vec{p} \)                                \\
+  \( \vec{p}_{2} \)                            \\
+  \( \vec{p}^{\symup{ball}} \)                 \\
+  \( \vec{p}_{\symup{final}} \)                \\
+  \( \vec{p}^{\symup{ball}}_{\symup{final}} \) \\
+  \( \vec{p}^{\symup{final}}_{\symup{ball}} \) \\
+  \( \vec*{p} \)
+\end{dispExample*}
+%\iffalse
+%</example>
+%\fi
+%
+%\iffalse
+%<*example>
+%\fi
+\begin{docCommands}[%
+    doc parameter = \marg{symbol}\oarg{labels},%
+  ]%
+  {%
+    {%
+      doc name = dirvec,%
+      doc description = use this variant for boldface notation,%
+    },%
+    {%
+      doc name = dirvec*,%
+      doc description = use this variant for arrow notation,%
+    }%
+  }%
+  Powerful and intelligent command for typesetting the direction of 
+  a vector. The options are the same as those for \refCom{vec}.
+\end{docCommands}
+\begin{dispExample*}{lefthand ratio=0.65}
+  \( \dirvec{p} \)                                \\
+  \( \dirvec{p}_{2} \)                            \\
+  \( \dirvec{p}^{\symup{ball}} \)                 \\
+  \( \dirvec{p}_{\symup{final}} \)                \\
+  \( \dirvec{p}^{\symup{ball}}_{\symup{final}} \) \\
+  \( \dirvec{p}^{\symup{final}}_{\symup{ball}} \) \\
+  \( \dirvec*{p} \)
+\end{dispExample*}
+%\iffalse
+%</example>
+%\fi
+%
+%\iffalse
+%<*example>
+%\fi
+\begin{docCommands}
+  {%
+    {%
+      doc name = zerovec,%
+      doc description = use this variant for boldface notation,%
+    },%
+    {%
+      doc name = zerovec*,%
+      doc description = use this variant for arrow notation,%
+    },%
+  }%
+  Command for typesetting the zero vector. The starred variant gives 
+  arrow notation. Without the star you get boldface notation.
+\end{docCommands}
+\begin{dispExample}
+  \( \zerovec \)  \\
+  \( \zerovec* \)
+\end{dispExample}
+%\iffalse
+%</example>
+%\fi
+%
+%\iffalse
+%<*example>
+%\fi
+\begin{docCommand}{changein}{}%
+  Semantic alias for |\Delta|.
+\end{docCommand}
+\begin{dispExample}
+ \( \changein t \)       \\
+ \( \changein \vec{p} \)
+\end{dispExample}
+%\iffalse
+%</example>
+%\fi
+%
+%\iffalse
+%<*example>
+%\fi
+\begin{docCommands}[%
+    doc new = 2021-02-21,%
+    doc parameter = \oarg{size}\marg{quantity},%
+  ]%
+  {%
+    {%
+      doc name = doublebars,%
+      doc description = double bars,%
+    },%
+    {%
+      doc name = doublebars*,%
+      doc description = double bars for fractions,%
+    },%
+    {%
+      doc name = singlebars,%
+      doc description = single bars,%
+    },%
+    {%
+      doc name = singlebars*,%
+      doc description = single bars for fractions,%
+    },%
+    {%
+      doc name = anglebrackets,%
+      doc description = angle brackets,%
+    },%
+    {%
+      doc name = anglebrackets*,%
+      doc description = angle brackets for fractions,%
+    },%
+    {%
+      doc name = parentheses,%
+      doc description = parentheses,%
+    },%
+    {%
+      doc name = parentheses*,%
+      doc description = parentheses for fractions,%
+    },%
+    {%
+      doc name = squarebrackets,%
+      doc description = square brackets,%
+    },%
+    {%
+      doc name = squarebrackets*,%
+      doc description = square brackets for fractions,%
+    },%
+    {%
+      doc name = curlybraces,%
+      doc description = curly braces,%
+    },%
+    {%
+      doc name = curlybraces*,%
+      doc description = curly braces for fractions,%
+    },%
+  }%
+  If no argument is given, a placeholder is provided. 
+  Sizers like |\big|,|\Big|,|\bigg|, and |\Bigg| can 
+  be optionally specified. Beginners are encouraged 
+  not to use them. See the 
+  \href{https://www.ctan.org/pkg/mathtools}{\pkg{mathtools}} package 
+  documentation for details. 
+\end{docCommands}
+\begin{dispExample}
+  \[ \doublebars{} \]
+  \[ \doublebars{\vec{a}} \]
+  \[ \doublebars*{\frac{\vec{a}}{3}} \]
+  \[ \doublebars[\Bigg]{\frac{\vec{a}}{3}} \]
+\end{dispExample}
+\begin{dispExample}
+  \[ \singlebars{} \]
+  \[ \singlebars{x} \]
+  \[ \singlebars*{\frac{x}{3}} \]
+  \[ \singlebars[\Bigg]{\frac{x}{3}} \]
+\end{dispExample}
+\begin{dispExample}
+  \[ \anglebrackets{} \]
+  \[ \anglebrackets{\vec{a}} \]
+  \[ \anglebrackets*{\frac{\vec{a}}{3}} \]
+  \[ \anglebrackets[\Bigg]{\frac{\vec{a}}{3}} \]
+\end{dispExample}
+\begin{dispExample}
+  \[ \parentheses{} \]
+  \[ \parentheses{x} \]
+  \[ \parentheses*{\frac{x}{3}} \]
+  \[ \parentheses[\Bigg]{\frac{x}{3}} \]
+\end{dispExample}
+\begin{dispExample}
+  \[ \squarebrackets{} \]
+  \[ \squarebrackets{x} \]
+  \[ \squarebrackets*{\frac{x}{3}} \]
+  \[ \squarebrackets[\Bigg]{\frac{x}{3}} \]
+\end{dispExample}
+\begin{dispExample}
+  \[ \curlybraces{} \]
+  \[ \curlybraces{x} \]
+  \[ \curlybraces*{\frac{x}{3}} \]
+  \[ \curlybraces[\Bigg]{\frac{x}{3}} \]
+\end{dispExample}
+%\iffalse
+%</example>
+%\fi
+%
+%\iffalse
+%<*example>
+%\fi
+\begin{docCommands}[%
+    doc new = 2021-02-21,%
+    doc parameter = \oarg{size}\marg{quantity},%
+  ]%
+  {%
+    {%
+      doc name = magnitude,%
+      doc description = alias for double bars,%
+    },%
+    {%
+      doc name = magnitude*,%
+      doc description = alias for double bars for fractions,%
+    },%
+    {%
+      doc name = norm,%
+      doc description = alias for double bars,%
+    },%
+    {%
+      doc name = norm*,%
+      doc description = alias for double bars for fractions,%
+    },%
+    {%
+      doc name = absolutevalue,%
+      doc description = alias for single bars,%
+    },%
+    {%
+      doc name = absolutevalue*,%
+      doc description = alias for single bars for fractions,%
+    },%
+  }%
+  Semantic aliases. Use \refCom{magnitude} or \refCom{magnitude*} to
+  typeset the magnitude of a vector.
+\end{docCommands}
+\begin{dispExample}
+  \[ \magnitude{\vec{p}} \]
+  \[ \magnitude{\vec*{p}} \]
+  \[ \magnitude*{\vec{p}_{\symup{final}}} \]
+  \[ \magnitude*{\vec*{p}_{\symup{final}}} \]
+\end{dispExample}
+%\iffalse
+%</example>
+%\fi
+%
+%\iffalse
+%<*example>
+%\fi
+\begin{docCommands}[%
+    doc new = 2021-04-06,%
+  ]%
+  {%
+    {%
+      doc name = parallelto,%
+    },%
+    {%
+      doc name = perpendicularto,%
+    },%
+  }%
+  Commands for geometric relationships, mainly
+  intended for subscripts.
+\end{docCommands}
+\begin{dispExample*}{lefthand ratio=0.6}
+ \( \vec{F}_{\parallelto} + \vec{F}_{\perpendicularto} \)
+\end{dispExample*}
+%\iffalse
+%</example>
+%\fi
+%
+% \subsection{Problems and Annotated Problem Solutions}
+%
+%\iffalse
+%<*example>
+%\fi
+\begin{docEnvironments}[%
+    doc new = 2021-02-03,%
+    doc parameter = \marg{title},%
+    doclang/environment content = problem,%
+  ]%
+  {%
+    {%
+      doc name = physicsproblem,%
+      doc description = use this variant for vertical lists,%
+    },%
+    {%
+      doc name = physicsproblem*,%
+      doc description = use this variant for in-line lists,%
+    },%
+    {%
+      doc name = parts,%
+      doc description = provides problem parts,%
+    },%
+  }%
+  Provides an environment for stating physics problems. Each problem will 
+  begin on a new page. See the examples for how to handle single and 
+  multiple part problems.
+\end{docEnvironments}
+\begin{docCommand}[doc new = 2012-02-03]{problempart}{}
+  Denotes a part of a problem within a \refEnv{parts}
+  environment.
+\end{docCommand}
+\begin{dispExample*}{sidebyside=false}
+  \begin{physicsproblem}{Problem 1}
+    This is a physics problem with no parts.
+  \end{physicsproblem}
+\end{dispExample*}
+\begin{dispExample*}{sidebyside=false}
+  \begin{physicsproblem}{Problem 2}
+    This is a physics problem with multiple parts.
+    The list is vertical.
+    \begin{parts}
+      \problempart This is the first part.
+      \problempart This is the second part.
+      \problempart This is the third part.
+    \end{parts}
+  \end{physicsproblem}
+\end{dispExample*}
+\begin{dispExample*}{sidebyside=false}
+  \begin{physicsproblem*}{Problem 3}
+    This is a physics problem with multiple parts.
+    The list is in-line.
+    \begin{parts}
+      \problempart This is the first part.
+      \problempart This is the second part.
+      \problempart This is the third part.
+    \end{parts}
+  \end{physicsproblem*}
+\end{dispExample*}
+%\iffalse
+%</example>
+%\fi
+%
+%\iffalse
+%<*example>
+%\fi
+\begin{docEnvironments}[%
+    doc updated = 2021-02-26,%
+    doc parameter = {},%
+    doclang/environment content = solution steps,%
+  ]%
+  {%
+    {%
+      doc name = physicssolution,%
+      doc description = use this variant for numbered steps,%
+    },%
+    {%
+      doc name = physicssolution*,%
+      doc description = use this variant for unnumbered steps,%
+    },%
+  }%
+  This environment is only for mathematical solutions. The starred 
+  variant omits numbering of steps. See the examples.
+\end{docEnvironments}
+\begin{dispExample}
+  \begin{physicssolution}
+    x &= y + z \\
+    z &= x - y \\
+    y &= x - z
+  \end{physicssolution}
+  \begin{physicssolution*}
+    x &= y + z \\
+    z &= x - y \\
+    y &= x - z
+  \end{physicssolution*}
+\end{dispExample}
+%\iffalse
+%</example>
+%\fi
+%
+%\iffalse
+%<*example>
+%\fi
+\begin{docCommand}[doc updated = 2012-02-26]{reason}{\marg{reason}}
+  Provides an annotation in a step-by-step solution.
+  Keep reasons short and to the point. Wrap mathematical
+  content in math mode. 
+\end{docCommand}
+\begin{dispExample}
+  \begin{physicssolution}
+    x &= y + z \reason{This is a reason.}     \\
+    z &= x - y \reason{This is a reason too.} \\
+    y &= x - z \reason{final answer}
+  \end{physicssolution}
+  \begin{physicssolution*}
+    x &= y + z \reason{This is a reason.}     \\
+    z &= x - y \reason{This is a reason too.} \\
+    y &= x - z \reason{final answer}
+  \end{physicssolution*}
+\end{dispExample}
+%\iffalse
+%</example>
+%\fi
+%
+% When writing solutions, remember that the \refEnv{physicssolution} 
+% environment is \emph{only} for mathematical content, not textual 
+% content or explanations. 
+%
+%\iffalse
+%<*example>
+%\fi
+\begin{dispListing*}{sidebyside=false,listing only}
+  \begin{physicsproblem}{Combined Problem and Solution}
+    This is an interesting physics problem.
+    \begin{physicssolution}
+      The solution goes here.
+    \end{physicssolution}
+  \end{physicsproblem}
+\end{dispListing*}
+\begin{dispListing*}{sidebyside=false,listing only}
+  \begin{physicsproblem}{Combined Multipart Problem with Solutions}
+    This is a physics problem with multiple parts.
+    \begin{parts}
+      \problempart This is the first part.
+        \begin{physicssolution}
+          The solution goes here.
+        \end{physicssolution}
+      \problempart This is the second part.
+        \begin{physicssolution}
+          The solution goes here.
+        \end{physicssolution}
+      \problempart This is the third part.
+        \begin{physicssolution}
+          The solution goes here.
+        \end{physicssolution}
+    \end{parts}
+  \end{physicsproblem}
+\end{dispListing*}
+%\iffalse
+%</example>
+%\fi
+%
+%\iffalse
+%<*example>
+%\fi
+\begin{docCommand}[doc new=2021-02-06]{hilite}{%
+    \oarg{color}\marg{target}\oarg{shape}
+  }%
+  Hilites the desired target, which can be an entire mathematical expression 
+  or a part thereof. The default color is magenta and the default shape is a
+  rectangle.
+\end{docCommand} 
+\begin{dispListing*}{sidebyside=false,listing only}
+  \begin{align*}
+    (\Delta s)^2 &= -(\Delta t)^2 + (\Delta x)^2 + (\Delta y)^2 + 
+                     (\Delta z)^2 \\
+    (\Delta s)^2 &= \hilite{-(\Delta t)^2 + (\Delta x)^2}[rounded rectangle] + 
+                     (\Delta y)^2 + (\Delta z)^2 \\
+    (\Delta s)^2 &= \hilite{-(\Delta t)^2 + (\Delta x)^2}[rectangle] + 
+                     (\Delta y)^2 + (\Delta z)^2 \\
+    (\Delta s)^2 &= \hilite{-(\Delta t)^2 + (\Delta x)^2}[ellipse] + 
+                     (\Delta y)^2 + (\Delta z)^2 \\
+    (\Delta s)^{\hilite{2}[circle]} &= \hilite[green]{-}[circle]
+                 (\Delta t)^{\hilite[cyan]{2}[circle]}+
+                 (\Delta x)^{\hilite[orange]{2}[circle]} + 
+                 (\Delta y)^{\hilite[blue!50]{2}[circle]} +
+                 (\Delta z)^{\hilite[violet!45]{2}[circle]}
+  \end{align*}
+\end{dispListing*}
+  \begin{align*}
+    (\Delta s)^2 &= -(\Delta t)^2 + (\Delta x)^2 + (\Delta y)^2 + 
+                     (\Delta z)^2 \\
+    (\Delta s)^2 &= \hilite{-(\Delta t)^2 + (\Delta x)^2}[rounded rectangle] + 
+                    (\Delta y)^2 + (\Delta z)^2 \\
+    (\Delta s)^2 &= \hilite{-(\Delta t)^2 + (\Delta x)^2}[rectangle] + 
+                    (\Delta y)^2 + (\Delta z)^2 \\
+    (\Delta s)^2 &= \hilite{-(\Delta t)^2 + (\Delta x)^2}[ellipse] + 
+                    (\Delta y)^2 + (\Delta z)^2 \\
+    (\Delta s)^{\hilite{2}[circle]} &= \hilite[green]{-}[circle]
+                    (\Delta t)^{\hilite[cyan]{2}[circle]}+
+                    (\Delta x)^{\hilite[orange]{2}[circle]} + 
+                    (\Delta y)^{\hilite[blue!50]{2}[circle]} +
+                    (\Delta z)^{\hilite[violet!45]{2}[circle]}
+  \end{align*}
+\begin{dispListing*}{sidebyside=false,listing only}
+  \begin{align*}
+    \Delta\vec{p} &= \vec{F}_{\sumup{net}}\Delta t \\
+    \hilite[orange]{\Delta\vec{p}}[circle] &= \vec{F}_{\symup{net}}\Delta t \\
+    \Delta\vec{p} &= \hilite[yellow!50]{\vec{F}_{\symup{net}}}
+                     [rounded rectangle]\Delta t \\
+    \Delta\vec{p} &= \vec{F}_{\symup{net}}\hilite[olive!50]
+                     {\Delta t}[rectangle] \\
+    \Delta\vec{p} &= \hilite[cyan!50]{\vec{F}_{\symup{net}}\Delta t}
+                     [ellipse] \\
+    \hilite{\Delta\vec{p}}[rectangle] &= \vec{F}_{\symup{net}}\Delta t
+  \end{align*}
+\end{dispListing*}
+  \begin{align*}
+    \Delta\vec{p} &= \vec{F}_{\symup{net}}\Delta t \\
+    \hilite[orange]{\Delta\vec{p}}[circle] &= \vec{F}_{\symup{net}}
+                     \Delta t \\
+    \Delta\vec{p} &= \hilite[yellow!50]{\vec{F}_{\symup{net}}}
+                     [rounded rectangle]\Delta t \\
+    \Delta\vec{p} &= \vec{F}_{\symup{net}}\hilite[olive!50]{\Delta t}
+                     [rectangle] \\
+    \Delta\vec{p} &= \hilite[cyan!50]{\vec{F}_{\symup{net}}\Delta t}
+                     [ellipse] \\
+    \hilite{\Delta\vec{p}}[rectangle] &= \vec{F}_{\symup{net}}\Delta t
+  \end{align*}
+%\iffalse
+%</example>
+%\fi
+%
+%\iffalse
+%<*example>
+%\fi
+\begin{docCommand}[doc updated = 2021-02-26]{image}{%
+    \oarg{options}\marg{caption}\marg{label}\marg{image}
+  }%
+  Simplified interface for importing an image. The images are treated 
+  as floats, so they may not appear at the most logically intuitive 
+  place.
+\end{docCommand}
+\begin{dispListing*}{sidebyside=false,listing only,verbatim ignore percent}
+  \image[scale=0.20]{example-image-1x1}
+    {Image shown 20 percent actual size.}{reffig1}
+\end{dispListing*}
+\image[scale=0.20]{example-image-1x1}
+    {Image shown 20 percent actual size.}{reffig1}
+\begin{dispExample*}{sidebyside=false}
+  Figure \ref{reffig1} is nice. 
+  It's captioned \nameref{reffig1} and is on page \pageref{reffig1}.
+\end{dispExample*}
+\begin{dispListing*}{sidebyside=false,listing only,verbatim ignore percent}
+  \image[scale=0.20,angle=45]{example-image-1x1}
+  {Image shown 20 percent actual size and rotated.}{reffig1}
+\end{dispListing*}
+\image[scale=0.20,angle=45]{example-image-1x1}
+{Image shown 20 percent actual size and rotated.}{reffig2}
+\begin{dispExample*}{sidebyside=false}
+  Figure \ref{reffig2} is nice. 
+  It's captioned \nameref{reffig2} and is on page \pageref{reffig2}.
+\end{dispExample*}
+%\iffalse
+%</example>
+%\fi
+%
+% \subsection{Coordinate-Free and Index Notation}
+%
+% Beyond the current level of introductory physics, we need intelligent 
+% commands for typesetting vector and tensor symbols and components 
+% suitable for both coordinate-free and index notations.
+%
+%\iffalse
+%<*example>
+%\fi
+\begin{docCommands}[%
+    doc parameter = \oarg{delimiter}\marg{\ensuremath{c_1,\dots,c_n}},%
+  ]%
+  {%
+    {%
+      doc name = colvec,%
+    },%
+    {%
+      doc name = rowvec,%
+    },%
+  }%
+  Typesets column vectors and row vectors as numeric or symbolic components. 
+  There can be more than three components. The delimiter used in the list of 
+  components can be specified; the default is a comma. Units are not 
+  supported, so these are mainly for symbolic work.
+\end{docCommands}
+\begin{dispExample}
+  \[ \colvec{1,2,3} \]
+  \[ \rowvec{1,2,3} \]
+  \[ \colvec{x^0,x^1,x^2,x^3} \]
+  \[ \rowvec{x_0,x_1,x_2,x_3} \]
+\end{dispExample}
+%\iffalse
+%</example>
+%\fi
+%
+%\iffalse
+%<*example>
+%\fi
+\begin{docCommands}[%
+    doc parameter = \marg{symbol},%
+  ]%
+  {%
+    {%
+      doc name = veccomp,%
+      doc description = use this variant for coordinate-free vector notation,%
+    },%
+    {%
+      doc name = veccomp*,%
+      doc description = use this variant for index vector notation,%
+    },%
+    {%
+      doc name = tencomp,%
+      doc description = use this variant for coordinate-free tensor notation,%
+    },%
+    {%
+      doc name = tencomp*,%
+      doc description = use this variant for index tensor notation,%
+    },%
+  }%
+  Conforms to ISO 80000-2 notation.
+\end{docCommands}
+\begin{dispExample}
+  \( \veccomp{r} \)  \\
+  \( \veccomp*{r} \) \\
+  \( \tencomp{r} \)  \\
+  \( \tencomp*{r} \)
+\end{dispExample}
+%\iffalse
+%</example>
+%\fi
+%
+%\iffalse
+%<*example>
+%\fi
+\begin{docCommands}[%
+  doc parameter = \marg{index}\marg{index},%
+  ]%
+  {%
+    {%
+      doc name = valence,%
+    },%
+    {%
+      doc name = valence*,%
+    },%
+  }%
+  Typesets tensor valence. The starred variant typesets it horizontally.
+\end{docCommands}
+\begin{dispExample}
+  A vector is a \( \valence{1}{0} \) tensor.  \\
+  A vector is a \( \valence*{1}{0} \) tensor.
+\end{dispExample}
+%\iffalse
+%</example>
+%\fi
+%
+%\iffalse
+%<*example>
+%\fi
+\begin{docCommands}[%
+  doc parameter = \marg{slot,slot},%
+  ]%
+  {%
+    {%
+      doc name = contraction,%
+    },%
+    {%
+      doc name = contraction*,%
+    },%
+  }%
+  Typesets tensor contraction in coordinate-free notation. There
+  is no standard on this so we assert one here.
+\end{docCommands}
+\begin{dispExample}
+  \( \contraction{1,2} \)  \\
+  \( \contraction*{1,2} \)
+\end{dispExample}
+%\iffalse
+%</example>
+%\fi
+%
+%\iffalse
+%<*example>
+%\fi
+\begin{docCommands}%
+  {%
+    {%
+      doc name = slot,%
+      doc parameter = \oarg{vector},%
+    },%
+    {%
+      doc name = slot*,%
+      doc parameter = \oarg{vector},%
+    },%
+  }%
+  An intelligent slot command for coordinate-free vector
+  and tensor notation. The starred variants suppress the 
+  underscore.
+\end{docCommands}
+\begin{dispExample}
+  \( (\slot) \)          \\
+  \( (\slot[\vec{a}]) \) \\
+  \( (\slot*) \)         \\
+  \( (\slot*[\vec{a}]) \)
+\end{dispExample}
+%\iffalse
+%</example>
+%\fi
+%
+%\iffalse
+%<*example>
+%\fi
+\begin{docCommand}[doc new=2021-04-06]{diff}{}%
+  Intelligent differential (exterior derivative)
+  operator.
+\end{docCommand}
+\begin{dispExample}
+ \[ 
+   \int x\,dx 
+ \]
+ \[
+   \int x\,\diff{x}
+ \]
+ \[
+   \int x\,\diff*{x} 
+ \]
+\end{dispExample}
+%\iffalse
+%</example>
+%\fi
+%
+% \subsection{\GlowScript\ and \VPython\ Program Listings}
+%
+% \href{https://\gsurl}{\GlowScript}\footnote{\href{https://\gsurl}{https://\gsurl}} 
+% and 
+% \href{https://\vpurl}{VPython}\footnote{\href{https://\vpurl}{https://\vpurl}} 
+% are programming environments (both use \href{https://www.python.org}{Python})
+% frequently used in introductory physics to introduce students
+% for modeling physical systems. \mandi\ makes including code listings
+% very simple for students.
+%
+% \subsection{The \texttt{\small glowscriptblock} Environment}
+%
+%\iffalse
+%<*example>
+%\fi
+\begin{docEnvironment}[%
+      doc updated = 2021-02-26,doclang/environment content=GlowScript code%
+    ]%
+  {glowscriptblock}{\oarg{options}(\meta{link})\marg{caption}}
+  Code placed here is nicely formatted and optionally linked to its source on 
+  \href{https://\gsurl}{\GlowScriptorg}. Clicking anywhere in the code window 
+  will open the link in the default browser. A caption is mandatory, and a 
+  label is internally generated. The listing always begins on a new page. A 
+  URL shortening utility is recommended to keep the URL from getting unruly. 
+  For convenience, |https://| is automatically prepended to the URL and can 
+  thus be omitted. The program must exist in a public, not private, folder.
+\end{docEnvironment}
+\begin{dispListing*}{sidebyside=false}
+\begin{glowscriptblock}(tinyurl.com/y3lnqyn3){A \texttt{GlowScript} Program}
+GlowScript 3.0 vpython
+
+scene.width = 400
+scene.height = 760
+# constants and data
+g = 9.8       # m/s^2
+mball = 0.03  # kg
+Lo = 0.26     # m
+ks = 1.8      # N/m
+deltat = 0.01 # s
+
+# objects (origin is at ceiling)
+ceiling = box(pos=vector(0,0,0), length=0.2, height=0.01, 
+              width=0.2)
+ball = sphere(pos=vector(0,-0.3,0),radius=0.025,
+              color=color.orange)
+spring = helix(pos=ceiling.pos, axis=ball.pos-ceiling.pos,
+               color=color.cyan,thickness=0.003,coils=40,
+               radius=0.010)
+
+# initial values
+pball = mball * vector(0,0,0)      # kg m/s
+Fgrav = mball * g * vector(0,-1,0) # N
+t = 0
+
+# improve the display
+scene.autoscale = False        # turn off automatic camera zoom
+scene.center = vector(0,-Lo,0) # move camera down
+scene.waitfor('click')         # wait for a mouse click
+
+# initial calculation loop
+# calculation loop
+while t < 10:
+    rate(100)
+    # we need the stretch
+    s = mag(ball.pos) - Lo
+    # we need the spring force
+    Fspring = ks * s * -norm(spring.axis)
+    Fnet = Fgrav + Fspring
+    pball = pball + Fnet * deltat
+    ball.pos = ball.pos + (pball / mball) * deltat
+    spring.axis = ball.pos - ceiling.pos
+    t = t + deltat
+\end{glowscriptblock}
+\end{dispListing*}
+\begin{glowscriptblock}(tinyurl.com/y3lnqyn3){A \texttt{GlowScript} Program}
+GlowScript 3.0 vpython
+
+scene.width = 400
+scene.height = 760
+# constants and data
+g = 9.8       # m/s^2
+mball = 0.03  # kg
+Lo = 0.26     # m
+ks = 1.8      # N/m
+deltat = 0.01 # s
+
+# objects (origin is at ceiling)
+ceiling = box(pos=vector(0,0,0), length=0.2, height=0.01, 
+              width=0.2)
+ball = sphere(pos=vector(0,-0.3,0),radius=0.025,
+              color=color.orange)
+spring = helix(pos=ceiling.pos, axis=ball.pos-ceiling.pos,
+               color=color.cyan,thickness=0.003,coils=40,
+               radius=0.010)
+
+# initial values
+pball = mball * vector(0,0,0)      # kg m/s
+Fgrav = mball * g * vector(0,-1,0) # N
+t = 0
+
+# improve the display
+scene.autoscale = False        # turn off automatic camera zoom
+scene.center = vector(0,-Lo,0) # move camera down
+scene.waitfor('click')         # wait for a mouse click
+
+# initial calculation loop
+# calculation loop
+while t < 10:
+    rate(100)
+    # we need the stretch
+    s = mag(ball.pos) - Lo
+    # we need the spring force
+    Fspring = ks * s * -norm(spring.axis)
+    Fnet = Fgrav + Fspring
+    pball = pball + Fnet * deltat
+    ball.pos = ball.pos + (pball / mball) * deltat
+    spring.axis = ball.pos - ceiling.pos
+    t = t + deltat
+\end{glowscriptblock}
+%\iffalse
+%</example>
+%\fi
+%
+%\iffalse
+%<*example>
+%\fi
+\begin{dispExample*}{sidebyside=false}
+  \GlowScript\ program \ref{gs:1} is nice. 
+  It's called \nameref{gs:1} and is on page \pageref{gs:1}.
+\end{dispExample*}
+%  
+%\iffalse
+%</example>
+%\fi
+%
+% \subsection{The \texttt{\small vpythonfile} Command}
+%
+%\iffalse
+%<*example>
+%\fi
+\begin{docCommand}[doc updated = 2021-02-26]{vpythonfile}
+  {\oarg{options}\marg{file}\marg{caption}}
+  Command to load and typeset a \VPython\ program. The file is read from 
+  \marg{file}. Clicking anywhere in the code window can optionally open 
+  a link, passed as an option, in the default browser. A caption is mandatory, 
+  and a label is internally generated. The listing always begins on a new page. 
+  A URL shortening utility is recommended to keep the URL from getting unruly. 
+  For convenience, |https://| is automatically prepended to the URL and can 
+  thus be omitted.
+\end{docCommand}
+\begin{dispListing*}{sidebyside=false}
+\vpythonfile[hyperurl interior = https://vpython.org]{vdemo.py}
+  {A \VPython\ Program}
+\end{dispListing*}
+\vpythonfile[hyperurl interior = https://vpython.org]{vdemo.py}
+  {A \VPython\ Program}
+%\iffalse
+%</example>
+%\fi
+%
+%\iffalse
+%<*example>
+%\fi
+\begin{dispExample*}{sidebyside=false}
+  \VPython\ program \ref{vp:1} is nice. 
+  It's called \nameref{vp:1} and is on page \pageref{vp:1}.
+\end{dispExample*}
+%  
+%\iffalse
+%</example>
+%\fi
+%
+% \subsection{The \texttt{\small glowscriptinline} and 
+%   \texttt{\small vpythoninline} Commands}
+%
+%\iffalse
+%<*example>
+%\fi
+\begin{docCommands}[%
+    doc updated = 2021-02-26,%
+  ]%
+  {%
+    {%
+      doc name = glowscriptinline,%
+      doc parameter = \marg{GlowScript code},%
+    },%
+    {%
+      doc name = vpythoninline,%
+      doc parameter = \marg{VPython code},%
+    },%
+  }%
+  Typesets a small, in-line snippet of code. The snippet should be
+  less than one line long.
+\end{docCommands}
+\begin{dispExample*}{sidebyside=false}
+  \GlowScript\ programs begin with \glowscriptinline{GlowScript 3.0 VPython}
+  and \VPython\ programs begin with \vpythoninline{from vpython import *}. 
+\end{dispExample*}
+%\iffalse
+%</example>
+%\fi
+%
+% \StopEventually{}
+%
+% \newgeometry{left=0.50in,right=0.50in,top=1.00in,bottom=1.00in}
+% \subsection{\mandistudent\ Source Code}
+%
+% \iffalse
+%<*package>
+% \fi
+% Definine the package version and date for global use, exploiting the fact
+% that in a \pkg{.sty} file there is now no need for |\makeatletter| and
+% |\makeatother|. This simplifies defining internal commands, with |@| 
+% in the name, that are not for the user to know about.
+%
+%    \begin{macrocode}
+\def\mandistudent@version{\mandi@version}
+\def\mandistudent@date{\mandi@date}
+\NeedsTeXFormat{LaTeX2e}[2020-02-02]
+\DeclareRelease{v3.0.0}{2021-08-21}{mandistudent.sty}
+\DeclareCurrentRelease{v\mandi@version}{\mandi@date}
+\ProvidesPackage{mandistudent}
+  [\mandistudent@date\space v\mandistudent@version\space Macros for introductory physics]
+%    \end{macrocode}
+%
+% Define a convenient package version command.
+%
+%    \begin{macrocode}
+\newcommand*{\mandistudentversion}{v\mandistudent@version\space dated \mandistudent@date}
+%    \end{macrocode}
+%
+% Load third party packages, documenting why each one is needed.
+%
+%    \begin{macrocode}
+\RequirePackage{amsmath}             % AMS goodness (don't load amssymb or amsfonts)
+\RequirePackage[inline]{enumitem}    % needed for physicsproblem environment
+\RequirePackage{eso-pic}             % needed for \hilite
+\RequirePackage[g]{esvect}           % needed for nice vector arrow, style g
+\RequirePackage{pgfopts}             % needed for key-value interface
+\RequirePackage{iftex}               % needed for requiring LuaLaTeX
+\RequirePackage{makebox}             % needed for consistent \dirvect; \makebox
+\RequirePackage{mandi}
+\RequirePackage{mathtools}           % needed for paired delimiters; extends amsmath
+\RequirePackage{nicematrix}          % needed for column and row vectors
+\RequirePackage[most]{tcolorbox}     % needed for program listings
+\RequirePackage{tensor}              % needed for index notation
+\RequirePackage{tikz}                % needed for \hilite
+\usetikzlibrary{shapes,fit,tikzmark} % needed for \hilite
+\RequirePackage{unicode-math}        % needed for Unicode support
+\RequirePackage{hyperref}            % load last
+\RequireLuaTeX                       % require this engine
+%    \end{macrocode}
+%
+% Set up the fonts to be consistent with ISO 80000-2 notation.
+% The \href{https://www.ctan.org/pkg/unicode-math}{\pkg{unicode-math}} package 
+% loads the \href{https://www.ctan.org/pkg/fontspec}{\pkg{fontspec}} and 
+% \href{https://www.ctan.org/pkg/xparse}{\pkg{xparse}}
+% packages. Note that \pkg{xparse} is now part of the \LaTeX\ kernel.
+% Because \pkg{unicode-math} is required, all documents using \mandi\ must
+% be compiled with an engine that supports Unicode. We recommend \lualatex.
+%
+%    \begin{macrocode}
+\unimathsetup{math-style=ISO}
+\unimathsetup{warnings-off={mathtools-colon,mathtools-overbracket}}
+%
+% Use normal math letters from Latin Modern Math for familiarity with 
+% textbooks.
+%
+%    \begin{macrocode}
+\setmathfont[Scale=MatchLowercase]
+  {Latin Modern Math}    % default math font; better J
+%    \end{macrocode}
+%
+% Borrow from GeX Gyre DejaVu Math for vectors and tensors to get single-storey g.
+%
+%    \begin{macrocode}
+\setmathfont[Scale=MatchLowercase,range={sfit/{latin},bfsfit/{latin}}]
+  {TeX Gyre DejaVu Math} % single-storey lowercase g
+%    \end{macrocode}
+%
+% Borrow from GeX Gyre DejaVu Math to get single-storey g.
+%
+%    \begin{macrocode}
+\setmathfont[Scale=MatchLowercase,range={sfup/{latin},bfsfup/{latin}}]
+  {TeX Gyre DejaVu Math} % single-storey lowercase g
+%    \end{macrocode}
+% Borrow |mathscr| and |mathbfscr| from XITS Math.\newline
+% See \url{https://tex.stackexchange.com/a/120073/218142}.
+%
+%    \begin{macrocode}
+\setmathfont[Scale=MatchLowercase,range={\mathscr,\mathbfscr}]{XITS Math}
+%    \end{macrocode}
+%
+% Get original and bold |mathcal| fonts.\newline
+% See \url{https://tex.stackexchange.com/a/21742/218142}.
+%
+%    \begin{macrocode}
+\setmathfont[Scale=MatchLowercase,range={\mathcal,\mathbfcal},StylisticSet=1]{XITS Math}
+%    \end{macrocode}
+%
+% Borrow Greek sfup and sfit letters from STIX Two Math.
+% Since this isn't officially supported in \pkg{unicode-math}
+% we have to manually set this up.
+%
+%    \begin{macrocode}
+\setmathfont[Scale=MatchLowercase,range={"E17C-"E1F6}]{STIX Two Math}
+\newfontfamily{\symsfgreek}{STIX Two Math}
+% I don't understand why \text{...} is necessary.
+\newcommand{\symsfupalpha}      {\text{\symsfgreek{^^^^e196}}}
+\newcommand{\symsfupbeta}       {\text{\symsfgreek{^^^^e197}}}
+\newcommand{\symsfupgamma}      {\text{\symsfgreek{^^^^e198}}}
+\newcommand{\symsfupdelta}      {\text{\symsfgreek{^^^^e199}}}
+\newcommand{\symsfupepsilon}    {\text{\symsfgreek{^^^^e1af}}}
+\newcommand{\symsfupvarepsilon} {\text{\symsfgreek{^^^^e19a}}}
+\newcommand{\symsfupzeta}       {\text{\symsfgreek{^^^^e19b}}}
+\newcommand{\symsfupeta}        {\text{\symsfgreek{^^^^e19c}}}
+\newcommand{\symsfuptheta}      {\text{\symsfgreek{^^^^e19d}}}
+\newcommand{\symsfupvartheta}   {\text{\symsfgreek{^^^^e1b0}}}
+\newcommand{\symsfupiota}       {\text{\symsfgreek{^^^^e19e}}}
+\newcommand{\symsfupkappa}      {\text{\symsfgreek{^^^^e19f}}}
+\newcommand{\symsfuplambda}     {\text{\symsfgreek{^^^^e1a0}}}
+\newcommand{\symsfupmu}         {\text{\symsfgreek{^^^^e1a1}}}
+\newcommand{\symsfupnu}         {\text{\symsfgreek{^^^^e1a2}}}
+\newcommand{\symsfupxi}         {\text{\symsfgreek{^^^^e1a3}}}
+\newcommand{\symsfupomicron}    {\text{\symsfgreek{^^^^e1a4}}}
+\newcommand{\symsfuppi}         {\text{\symsfgreek{^^^^e1a5}}}
+\newcommand{\symsfupvarpi}      {\text{\symsfgreek{^^^^e1b3}}}
+\newcommand{\symsfuprho}        {\text{\symsfgreek{^^^^e1a6}}}
+\newcommand{\symsfupvarrho}     {\text{\symsfgreek{^^^^e1b2}}}
+\newcommand{\symsfupsigma}      {\text{\symsfgreek{^^^^e1a8}}}
+\newcommand{\symsfupvarsigma}   {\text{\symsfgreek{^^^^e1a7}}}
+\newcommand{\symsfuptau}        {\text{\symsfgreek{^^^^e1a9}}}
+\newcommand{\symsfupupsilon}    {\text{\symsfgreek{^^^^e1aa}}}
+\newcommand{\symsfupphi}        {\text{\symsfgreek{^^^^e1b1}}}
+\newcommand{\symsfupvarphi}     {\text{\symsfgreek{^^^^e1ab}}}
+\newcommand{\symsfupchi}        {\text{\symsfgreek{^^^^e1ac}}}
+\newcommand{\symsfuppsi}        {\text{\symsfgreek{^^^^e1ad}}}
+\newcommand{\symsfupomega}      {\text{\symsfgreek{^^^^e1ae}}}
+\newcommand{\symsfupDelta}      {\text{\symsfgreek{^^^^e180}}}
+\newcommand{\symsfupGamma}      {\text{\symsfgreek{^^^^e17f}}}
+\newcommand{\symsfupTheta}      {\text{\symsfgreek{^^^^e18e}}}
+\newcommand{\symsfupLambda}     {\text{\symsfgreek{^^^^e187}}}
+\newcommand{\symsfupXi}         {\text{\symsfgreek{^^^^e18a}}}
+\newcommand{\symsfupPi}         {\text{\symsfgreek{^^^^e18c}}}
+\newcommand{\symsfupSigma}      {\text{\symsfgreek{^^^^e18f}}}
+\newcommand{\symsfupUpsilon}    {\text{\symsfgreek{^^^^e191}}}
+\newcommand{\symsfupPhi}        {\text{\symsfgreek{^^^^e192}}}
+\newcommand{\symsfupPsi}        {\text{\symsfgreek{^^^^e194}}}
+\newcommand{\symsfupOmega}      {\text{\symsfgreek{^^^^e195}}}
+\newcommand{\symsfitalpha}      {\text{\symsfgreek{^^^^e1d8}}}
+\newcommand{\symsfitbeta}       {\text{\symsfgreek{^^^^e1d9}}}
+\newcommand{\symsfitgamma}      {\text{\symsfgreek{^^^^e1da}}}
+\newcommand{\symsfitdelta}      {\text{\symsfgreek{^^^^e1db}}}
+\newcommand{\symsfitepsilon}    {\text{\symsfgreek{^^^^e1f1}}}
+\newcommand{\symsfitvarepsilon} {\text{\symsfgreek{^^^^e1dc}}}
+\newcommand{\symsfitzeta}       {\text{\symsfgreek{^^^^e1dd}}}
+\newcommand{\symsfiteta}        {\text{\symsfgreek{^^^^e1de}}}
+\newcommand{\symsfittheta}      {\text{\symsfgreek{^^^^e1df}}}
+\newcommand{\symsfitvartheta}   {\text{\symsfgreek{^^^^e1f2}}}
+\newcommand{\symsfitiota}       {\text{\symsfgreek{^^^^e1e0}}}
+\newcommand{\symsfitkappa}      {\text{\symsfgreek{^^^^e1e1}}}
+\newcommand{\symsfitlambda}     {\text{\symsfgreek{^^^^e1e2}}}
+\newcommand{\symsfitmu}         {\text{\symsfgreek{^^^^e1e3}}}
+\newcommand{\symsfitnu}         {\text{\symsfgreek{^^^^e1e4}}}
+\newcommand{\symsfitxi}         {\text{\symsfgreek{^^^^e1e5}}}
+\newcommand{\symsfitomicron}    {\text{\symsfgreek{^^^^e1e6}}}
+\newcommand{\symsfitpi}         {\text{\symsfgreek{^^^^e1e7}}}
+\newcommand{\symsfitvarpi}      {\text{\symsfgreek{^^^^e1f5}}}
+\newcommand{\symsfitrho}        {\text{\symsfgreek{^^^^e1e8}}}
+\newcommand{\symsfitvarrho}     {\text{\symsfgreek{^^^^e1f4}}}
+\newcommand{\symsfitsigma}      {\text{\symsfgreek{^^^^e1ea}}}
+\newcommand{\symsfitvarsigma}   {\text{\symsfgreek{^^^^e1e9}}}
+\newcommand{\symsfittau}        {\text{\symsfgreek{^^^^e1eb}}}
+\newcommand{\symsfitupsilon}    {\text{\symsfgreek{^^^^e1ec}}}
+\newcommand{\symsfitphi}        {\text{\symsfgreek{^^^^e1f3}}}
+\newcommand{\symsfitvarphi}     {\text{\symsfgreek{^^^^e1ed}}}
+\newcommand{\symsfitchi}        {\text{\symsfgreek{^^^^e1ee}}}
+\newcommand{\symsfitpsi}        {\text{\symsfgreek{^^^^e1ef}}}
+\newcommand{\symsfitomega}      {\text{\symsfgreek{^^^^e1f0}}}
+\newcommand{\symsfitDelta}      {\text{\symsfgreek{^^^^e1c2}}}
+\newcommand{\symsfitGamma}      {\text{\symsfgreek{^^^^e1c1}}}
+\newcommand{\symsfitTheta}      {\text{\symsfgreek{^^^^e1d0}}}
+\newcommand{\symsfitLambda}     {\text{\symsfgreek{^^^^e1c9}}}
+\newcommand{\symsfitXi}         {\text{\symsfgreek{^^^^e1cc}}}
+\newcommand{\symsfitPi}         {\text{\symsfgreek{^^^^e1ce}}}
+\newcommand{\symsfitSigma}      {\text{\symsfgreek{^^^^e1d1}}}
+\newcommand{\symsfitUpsilon}    {\text{\symsfgreek{^^^^e1d3}}}
+\newcommand{\symsfitPhi}        {\text{\symsfgreek{^^^^e1d4}}}
+\newcommand{\symsfitPsi}        {\text{\symsfgreek{^^^^e1d6}}}
+\newcommand{\symsfitOmega}      {\text{\symsfgreek{^^^^e1d7}}}
+%    \end{macrocode}
+%
+% Tweak the \href{https://www.ctan.org/pkg/esvect}{\pkg{esvect}} package 
+% fonts to get the correct font size. Code provided by |@egreg|.\newline
+% See \url{https://tex.stackexchange.com/a/566676}.
+%
+%    \begin{macrocode}
+\DeclareFontFamily{U}{esvect}{}
+\DeclareFontShape{U}{esvect}{m}{n}{%
+  <-5.5> vect5
+  <5.5-6.5> vect6
+  <6.5-7.5> vect7
+  <7.5-8.5> vect8
+  <8.5-9.5> vect9
+  <9.5-> vect10
+}{}%
+%    \end{macrocode}
+%
+% Write a banner to the console showing the options in use.
+%
+%    \begin{macrocode}
+\typeout{}%
+\typeout{mandistudent: You are using mandistudent \mandistudentversion.}%
+\typeout{mandistudent: This package requires LuaLaTeX.}%
+\typeout{mandistudent: This package changes the default math font(s).}%
+\typeout{mandistudent: This package redefines the \protect\vec\space command.}%
+\typeout{}%
+%    \end{macrocode}
+%
+% A better, intelligent coordinate-free \refCom{vec} command. Note the use of 
+% the |e{_^}| type of optional argument. This accounts for much of the 
+% flexibility and power of this command. Also note the use of the \TeX\ 
+% primitives |\sb{}| and |\sp{}|. Why doesn't it work when I put spaces 
+% around |#3| or |#4|? Because outside of |\ExplSyntaxOn...\ExplSyntaxOff|, 
+% the |_| character has a different catcode and is treated as a mathematical 
+% entity.\newline
+% See \url{https://tex.stackexchange.com/q/554706/218142}.\newline
+% See also \url{https://tex.stackexchange.com/a/531037/218142}.
+%
+%    \begin{macrocode}
+\RenewDocumentCommand{\vec}{ s m e{_^} }{%
+    % Note the \, used to make superscript look better.
+    \IfBooleanTF {#1}
+      {\vv{#2}%      % * gives an arrow
+         % Use \sp{} primitive for superscript.
+         % Adjust superscript for the arrow.
+         \sp{\IfValueT{#4}{\,#4}\vphantom{\smash[t]{\big|}}}
+      }%         
+      {\symbfit{#2}  % no * gives us bold
+         % Use \sp{} primitive for superscript.
+         % No superscript adjustment needed.
+         \sp{\IfValueT{#4}{#4}\vphantom{\smash[t]{\big|}}}
+      }% 
+    % Use \sb{} primitive for subscript.
+    \sb{\IfValueT{#3}{#3}\vphantom{\smash[b]{|}}}
+}%
+%    \end{macrocode}
+%
+% A command for the direction of a vector.
+% We use a slight tweak to get uniform hats that 
+% requires the \href{https://www.ctan.org/pkg/makebox}{\pkg{makebox}} 
+% package.\newline
+% See \url{https://tex.stackexchange.com/a/391204/218142}.
+%
+%    \begin{macrocode}
+\NewDocumentCommand{\dirvec}{ s m e{_^} }{%
+    \widehat{\makebox*{\(w\)}{\ensuremath{%
+      \IfBooleanTF {#1}
+        {%
+          #2
+        }%
+        {%
+          \symbfit{#2}
+        }%
+       }%
+      }%
+     }%
+    \sb{\IfValueT{#3}{#3}\vphantom{\smash[b]{|}}}
+    \sp{\IfValueT{#4}{\,#4}\vphantom{\smash[t]{\big|}}}      
+}%
+%    \end{macrocode}
+%
+% The zero vector.
+%
+%    \begin{macrocode}
+\NewDocumentCommand{\zerovec}{ s }{%
+  \IfBooleanTF {#1}
+    {\vv{0}}%
+    {\symbfup{0}}%
+}%
+%    \end{macrocode}
+%
+% Notation for column and row vectors.
+% Orginal code provided by |@egreg|.\newline
+% See \url{https://tex.stackexchange.com/a/39054/218142}.
+%
+%    \begin{macrocode}
+\ExplSyntaxOn
+\NewDocumentCommand{\colvec}{ O{,} m }{%
+  \vector_main:nnnn { p } { \\ } { #1 } { #2 }
+}%
+\NewDocumentCommand{\rowvec}{ O{,} m }{%
+  \vector_main:nnnn { p } { & } { #1 } { #2 }
+}%
+\seq_new:N \l__vector_arg_seq
+\cs_new_protected:Npn \vector_main:nnnn #1 #2 #3 #4 {%
+  \seq_set_split:Nnn \l__vector_arg_seq { #3 } { #4 }
+  \begin{#1NiceMatrix}[r]
+    \seq_use:Nnnn \l__vector_arg_seq { #2 } { #2 } { #2 }
+  \end{#1NiceMatrix}
+}%
+\ExplSyntaxOff
+%    \end{macrocode}
+%
+% Students always need this symbol.
+%
+%    \begin{macrocode}
+\NewDocumentCommand{\changein}{}{\Delta}
+%    \end{macrocode}
+%
+% Intelligent delimiters provided via the 
+% \href{https://www.ctan.org/pkg/mathtools}{\pkg{mathtools}} package.
+% Use the starred variants for fractions. You can supply optional sizes.
+% Note that default placeholders are used when the argument is empty.
+%
+%    \begin{macrocode}
+\DeclarePairedDelimiterX{\doublebars}[1]{\lVert}{\rVert}{\ifblank{#1}{\:\cdot\:}{#1}}
+\DeclarePairedDelimiterX{\singlebars}[1]{\lvert}{\rvert}{\ifblank{#1}{\:\cdot\:}{#1}}
+\DeclarePairedDelimiterX{\anglebrackets}[1]{\langle}{\rangle}{\ifblank{#1}{\:\cdot\:}{#1}}
+\DeclarePairedDelimiterX{\parentheses}[1]{(}{)}{\ifblank{#1}{\:\cdot\:}{#1}}
+\DeclarePairedDelimiterX{\squarebrackets}[1]{\lbrack}{\rbrack}{\ifblank{#1}{\:\cdot\:}{#1}}
+\DeclarePairedDelimiterX{\curlybraces}[1]{\lbrace}{\rbrace}{\ifblank{#1}{\:\cdot\:}{#1}}
+%    \end{macrocode}
+%
+% Some semantic aliases. Because of the way \refCom{vec} and
+% \refCom{dirvec} are defined, I reluctantly decided not to
+% implement a |\magvec| command. It would require accounting
+% for too mamy options. So \refCom{magnitude} is the new
+% solution.
+%
+%    \begin{macrocode}
+\NewDocumentCommand{\magnitude}{}{\doublebars}
+\NewDocumentCommand{\norm}{}{\doublebars}
+\NewDocumentCommand{\absolutevalue}{}{\singlebars}
+%    \end{macrocode}
+%
+% Commands for two important geometric relationships. These are meant
+% mainly to be subscripts.
+%
+%    \begin{macrocode}
+\NewDocumentCommand{\parallelto}{}
+  {\mkern3mu\vphantom{\perp}\vrule depth 0pt\mkern2mu\vrule depth 0pt\mkern3mu}
+\NewDocumentCommand{\perpendicularto}{}{\perp}
+%    \end{macrocode}
+%
+% An environment for problem statements. The starred variant gives 
+% in-line lists.
+%
+%    \begin{macrocode}
+\NewDocumentEnvironment{physicsproblem}{ m }{%
+  \newpage%
+  \section*{#1}%
+  \newlist{parts}{enumerate}{2}%
+  \setlist[parts]{label=\bfseries(\alph*)}}%
+  {}%
+\NewDocumentEnvironment{physicsproblem*}{ m }{%
+  \newpage%
+  \section*{#1}%
+  \newlist{parts}{enumerate*}{2}%
+  \setlist[parts]{label=\bfseries(\alph*)}}%
+  {}%
+\NewDocumentCommand{\problempart}{}{\item}%
+%    \end{macrocode}
+%
+% An environment for problem solutions.
+%
+%    \begin{macrocode}
+\NewDocumentEnvironment{physicssolution}{ +b }{%
+  % Make equation numbering consecutive through the document.
+  \begin{align}
+    #1
+  \end{align}
+}{}%
+\NewDocumentEnvironment{physicssolution*}{ +b }{%
+  % Make equation numbering consecutive through the document.
+  \begin{align*}
+    #1
+  \end{align*}
+}{}%
+%    \end{macrocode}
+%
+% See \url{https://tex.stackexchange.com/q/570223/218142}.
+%
+%    \begin{macrocode}
+\NewDocumentCommand{\reason}{ O{4cm} m }
+  {&&\begin{minipage}{#1}\raggedright\small #2\end{minipage}}
+%    \end{macrocode}
+%
+% Command for highlighting parts of, or entire, mathematical expressions.\newline
+% Original code by anonymous user |@abcdefg|, modified by me.\newline
+%  See \url{https://texample.net/tikz/examples/beamer-arrows/}.\newline
+%  See also \url{https://tex.stackexchange.com/a/406084/218142}.\newline
+%  See also \url{https://tex.stackexchange.com/a/570858/218142}.\newline
+%  See also \url{https://tex.stackexchange.com/a/570789/218142}.\newline
+%  See also \url{https://tex.stackexchange.com/a/79659/218142}.\newline
+%  See also \url{https://tex.stackexchange.com/q/375032/218142}.\newline
+%  See also \url{https://tex.stackexchange.com/a/571744/218142}%
+%
+%    \begin{macrocode}
+\newcounter{tikzhighlightnode}
+\NewDocumentCommand{\hilite}{ O{magenta!60} m O{rectangle} }{%
+  \stepcounter{tikzhighlightnode}%
+  \tikzmarknode{highlighted-node-\number\value{tikzhighlightnode}}{#2}%
+  \edef\temp{%
+    \noexpand\AddToShipoutPictureBG{%
+      \noexpand\begin{tikzpicture}[overlay,remember picture]%
+      \noexpand\iftikzmarkoncurrentpage{highlighted-node-\number\value{tikzhighlightnode}}%
+       \noexpand\node[inner sep=1.0pt,fill=#1,#3,fit=(highlighted-node-\number\value{tikzhighlightnode})]{};%
+      \noexpand\fi
+      \noexpand\end{tikzpicture}%
+    }%
+  }%
+  \temp%
+}%
+%    \end{macrocode}
+%
+% A simplified command for importing images.
+%
+%    \begin{macrocode}
+\NewDocumentCommand{\image}{ O{scale=1} m m m }{%
+  \begin{figure}[ht!]
+    \begin{center}%
+      \includegraphics[#1]{#2}%
+    \end{center}%
+    \caption{#3}%
+    \label{#4}%
+  \end{figure}%
+}%
+%    \end{macrocode}
+%
+% Intelligent commands for typesetting vector and tensor symbols and 
+% components suitable for use with both coordinate-free and index 
+% notations. Use starred form for index notation, unstarred form for 
+% coordinate-free.
+%
+%    \begin{macrocode}
+\NewDocumentCommand{\veccomp}{ s m }{%
+  % Consider renaming this to \vectorsym.
+  \IfBooleanTF{#1}
+  {%
+    \symnormal{#2}%
+  }%
+  {%
+    \symbfit{#2}%
+  }%
+}%
+\NewDocumentCommand{\tencomp}{ s m }{%
+  % Consider renaming this to \tensororsym.
+  \IfBooleanTF{#1}
+  {%
+    \symsfit{#2}%
+  }%
+  {%
+    \symbfsfit{#2}
+  }%
+}%
+%    \end{macrocode}
+%
+% Command to typeset tensor valence.
+%
+%    \begin{macrocode}
+\NewDocumentCommand{\valence}{ s m m }{%
+  \IfBooleanTF{#1}
+    {(#2,#3)}
+    {\binom{#2}{#3}}
+}%
+%    \end{macrocode}
+%
+% Intelligent notation for contraction on pairs of slots.
+%
+%    \begin{macrocode}
+\NewDocumentCommand{\contraction}{ s m }{%
+  \IfBooleanTF{#1}
+  {\mathsf{C}}%
+  {\symbb{C}}%
+  _{#2}
+}%
+%    \end{macrocode}
+%
+% Intelligent slot command for coordinate-free tensor notation.
+%
+%    \begin{macrocode}
+\NewDocumentCommand{\slot}{ s d[] }{%
+  % d[] must be used because of the way consecutive optional
+  %  arguments are handled. See xparse docs for details.
+  \IfBooleanTF{#1}
+  {%
+    \IfValueTF{#2}
+    {% Insert a vector, but don't show the slot.
+      \smash{\makebox[1.5em]{\ensuremath{#2}}}
+    }%
+    {% No vector, no slot.
+      \smash{\makebox[1.5em]{\ensuremath{}}}
+    }%
+  }%
+  {%
+    \IfValueTF{#2}
+    {% Insert a vector and show the slot.
+      \underline{\smash{\makebox[1.5em]{\ensuremath{#2}}}}
+    }%
+    {% No vector; just show the slot.
+      \underline{\smash{\makebox[1.5em]{\ensuremath{}}}}
+    }%
+  }%
+}%
+%    \end{macrocode}
+%
+% Intelligent differential (exterior derivative) operator.
+%
+%    \begin{macrocode}
+\NewDocumentCommand{\diff}{ s }{%
+  \mathop{}\!
+  \IfBooleanTF{#1}
+  {\symbfsfup{d}}%
+  {\symsfup{d}}%
+}%
+%    \end{macrocode}
+%
+% Here is a clever way to color digits in program listsings thanks to
+% Ulrike Fischer.\newline
+% See \url{https://tex.stackexchange.com/a/570717/218142}.
+%
+%    \begin{macrocode}
+\directlua{%
+ luaotfload.add_colorscheme("colordigits",
+   {["8000FF"] = {"one","two","three","four","five","six","seven","eight","nine","zero"}})
+}%
+\newfontfamily\colordigits{DejaVuSansMono}[RawFeature={color=colordigits}]
+%    \end{macrocode}
+%
+% Set up a color scheme and a new code environment for listings. The new colors 
+% are more restful on the eye. All listing commands now use 
+% \href{https://www.ctan.org/pkg/tcolorbox}{\pkg{tcolorbox}}.\newline
+% See \url{https://tex.stackexchange.com/a/529421/218142}.
+%
+%    \begin{macrocode}
+\newfontfamily{\gsfontfamily}{DejaVuSansMono}    % new font for listings
+\definecolor{gsbggray}     {rgb}{0.90,0.90,0.90} % background gray
+\definecolor{gsgray}       {rgb}{0.30,0.30,0.30} % gray
+\definecolor{gsgreen}      {rgb}{0.00,0.60,0.00} % green
+\definecolor{gsorange}     {rgb}{0.80,0.45,0.12} % orange
+\definecolor{gspeach}      {rgb}{1.00,0.90,0.71} % peach
+\definecolor{gspearl}      {rgb}{0.94,0.92,0.84} % pearl
+\definecolor{gsplum}       {rgb}{0.74,0.46,0.70} % plum
+\lstdefinestyle{vpython}{%                       % style for listings
+  backgroundcolor=\color{gsbggray},%             % background color
+  basicstyle=\colordigits\footnotesize,%         % default style
+  breakatwhitespace=true%                        % break at whitespace
+  breaklines=true,%                              % break long lines
+  captionpos=b,%                                 % position caption
+  classoffset=1,%                                % STILL DON'T UNDERSTAND THIS
+  commentstyle=\color{gsgray},%                  % font for comments
+  deletekeywords={print},%                       % delete keywords from the given language
+  emph={self,cls,@classmethod,@property},%       % words to emphasize
+  emphstyle=\color{gsorange}\itshape,%           % font for emphasis
+  escapeinside={(*@}{@*)},%                      % add LaTeX within your code
+  frame=tb,%                                     % frame style
+  framerule=2.0pt,%                              % frame thickness
+  framexleftmargin=5pt,%                         % extra frame left margin
+  %identifierstyle=\sffamily,%                    % style for identifiers
+  keywordstyle=\gsfontfamily\color{gsplum},%     % color for keywords
+  language=Python,%                              % select language
+  linewidth=\linewidth,%                         % width of listings
+  morekeywords={%                                % VPython/GlowScript specific keywords
+    __future__,abs,acos,align,ambient,angle,append,append_to_caption,%
+    append_to_title,arange,arrow,asin,astuple,atan,atan2,attach_arrow,%
+    attach_trail,autoscale,axis,background,billboard,bind,black,blue,border,%
+    bounding_box,box,bumpaxis,bumpmap,bumpmaps,camera,canvas,caption,capture,%
+    ceil,center,clear,clear_trail,click,clone,CoffeeScript,coils,color,combin,%
+    comp,compound,cone,convex,cos,cross,curve,cyan,cylinder,data,degrees,del,%
+    delete,depth,descender,diff_angle,digits,division,dot,draw_complete,%
+    ellipsoid,emissive,end_face_color,equals,explog,extrusion,faces,factorial,%
+    False,floor,follow,font,format,forward,fov,frame,gcurve,gdisplay,gdots,%
+    get_library,get_selected,ghbars,global,GlowScript,graph,graphs,green,gvbars,%
+    hat,headlength,headwidth,height,helix,hsv_to_rgb,index,interval,keydown,%
+    keyup,label,length,lights,line,linecolor,linewidth,logx,logy,lower_left,%
+    lower_right,mag,mag2,magenta,make_trail,marker_color,markers,material,%
+    max,min,mouse,mousedown,mousemove,mouseup,newball,norm,normal,objects,%
+    offset,one,opacity,orange,origin,path,pause,pi,pixel_to_world,pixels,plot,%
+    points,pos,pow,pps,print,print_function,print_options,proj,purple,pyramid,%
+    quad,radians,radius,random,rate,ray,read_local_file,readonly,red,redraw,%
+    retain,rgb_to_hsv,ring,rotate,round,scene,scroll,shaftwidth,shape,shapes,%
+    shininess,show_end_face,show_start_face,sign,sin,size,size_units,sleep,%
+    smooth,space,sphere,sqrt,start,start_face_color,stop,tan,text,textpos,%
+    texture,textures,thickness,title,trail_color,trail_object,trail_radius,%
+    trail_type,triangle,trigger,True,twist,unbind,up,upper_left,upper_right,%
+    userpan,userspin,userzoom,vec,vector,vertex,vertical_spacing,visible,%
+    visual,vpython,VPython,waitfor,white,width,world,xtitle,yellow,yoffset,%
+    ytitle%
+  },%
+  morekeywords={print,None,TypeError},%      % additional keywords
+  morestring=[b]{"""},%                      % treat triple quotes as strings
+  numbers=left,%                             % where to put line numbers
+  numbersep=10pt,%                           % how far line numbers are from code
+  numberstyle=\bfseries\tiny,%               % set to 'none' for no line numbers
+  showstringspaces=false,%                   % show spaces in strings
+  showtabs=false,%                           % show tabs within strings
+  stringstyle=\gsfontfamily\color{gsgreen},% % color for strings
+  upquote=true,%                             % how to typeset quotes
+}%
+%    \end{macrocode}
+%
+% Introduce a new, more intelligent \refEnv{glowscriptblock} environment.
+%
+%    \begin{macrocode}
+\NewTCBListing[auto counter,list inside=gsprogs]{glowscriptblock}
+  { O{} D(){glowscript.org} m }{%
+  breakable,%
+  center,%
+  code = \newpage,%
+  %derivpeach,%
+  enhanced,%
+  hyperurl interior = https://#2,%
+  label = {gs:\thetcbcounter},%
+  left = 8mm,%
+  list entry = \thetcbcounter~~~~~#3,%
+  listing only,%
+  listing style = vpython,%
+  nameref = {#3},%
+  title = \texttt{GlowScript} Program \thetcbcounter: #3,%
+  width = 0.9\textwidth,%
+  {#1},
+}%
+%    \end{macrocode}
+%
+% A new command for generating a list of \GlowScript\ programs.
+%
+%    \begin{macrocode}
+\NewDocumentCommand{\listofglowscriptprograms}{}{\tcblistof[\section*]{gsprogs}
+  {List of \texttt{GlowScript} Programs}}%
+%    \end{macrocode}
+%
+% Introduce a new, more intelligent \refCom{vpythonfile} command.
+%
+%    \begin{macrocode}
+\NewTCBInputListing[auto counter,list inside=vpprogs]{\vpythonfile}
+  { O{} m m }{%
+  breakable,%
+  center,%
+  code = \newpage,%
+  %derivgray,%
+  enhanced,%
+  hyperurl interior = https://,%
+  label = {vp:\thetcbcounter},%
+  left = 8mm,%
+  list entry = \thetcbcounter~~~~~#3,%
+  listing file = {#2},%
+  listing only,%
+  listing style = vpython,%
+  nameref = {#3},%
+  title = \texttt{VPython} Program \thetcbcounter: #3,%
+  width = 0.9\textwidth,%
+  {#1},%
+}%
+%    \end{macrocode}
+%
+%  A new command for generating a list of \VPython\ programs.
+%
+%    \begin{macrocode}
+\NewDocumentCommand{\listofvpythonprograms}{}{\tcblistof[\section*]{vpprogs}
+  {List of \texttt{VPython} Programs}}%
+%    \end{macrocode}
+%
+% Introduce a new \refCom{glowscriptinline} command.
+%
+%    \begin{macrocode}
+\DeclareTotalTCBox{\glowscriptinline}{ m }{%
+  bottom = 0pt,%
+  bottomrule = 0.0mm,%
+  boxsep = 1.0mm,%
+  colback = gsbggray,%
+  colframe = gsbggray,%
+  left = 0pt,%
+  leftrule = 0.0mm,%
+  nobeforeafter,%
+  right = 0pt,%
+  rightrule = 0.0mm,%
+  sharp corners,%
+  tcbox raise base,%
+  top = 0pt,%
+  toprule = 0.0mm,%
+}{\lstinline[style = vpython]{#1}}%
+%    \end{macrocode}
+%
+% Define \refCom{vpythoninline}, a semantic alias for \VPython\ 
+% in-line listings.
+%
+%    \begin{macrocode}
+\NewDocumentCommand{\vpythoninline}{}{\glowscriptinline}%
+%    \end{macrocode}
+%
+% \restoregeometry
+%
+% \iffalse
+%</package>
+% \fi
+%
+% \Finale
-- 
cgit v1.2.3

