summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/tex/latex/jnuexam
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2023-12-11 21:08:45 +0000
committerKarl Berry <karl@freefriends.org>2023-12-11 21:08:45 +0000
commit607ed556f1f9c4e573ade023f3ec7d4d66799db8 (patch)
tree8bfaa9823b0c4865b867d626f947533a2df92a3c /Master/texmf-dist/tex/latex/jnuexam
parentc4c08d41114a16394510c0cf62dfd55eaf3581d7 (diff)
jnuexam (11dec23)
git-svn-id: svn://tug.org/texlive/trunk@69089 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/tex/latex/jnuexam')
-rw-r--r--Master/texmf-dist/tex/latex/jnuexam/jnuexam.cls853
1 files changed, 660 insertions, 193 deletions
diff --git a/Master/texmf-dist/tex/latex/jnuexam/jnuexam.cls b/Master/texmf-dist/tex/latex/jnuexam/jnuexam.cls
index bace8c2a698..5b25fa01d69 100644
--- a/Master/texmf-dist/tex/latex/jnuexam/jnuexam.cls
+++ b/Master/texmf-dist/tex/latex/jnuexam/jnuexam.cls
@@ -6,25 +6,39 @@
% ----------------------------------------------------------------------------
\NeedsTeXFormat{LaTeX2e}
-\ProvidesClass{jnuexam}[2020/11/06 v1.0 An exam class for Jinan University]
-
-\newif\ifmifengxian \mifengxiantrue % 是否加密封线
-\newif\ifsidebyside \sidebysidefalse % 是否 A3 纸张
-\newif\ifreverse \reversefalse % 是否逆序出题
-\newif\ifanswer \answertrue % 是否显示答案
-\newif\ifamsfonts \amsfontsfalse % 切换数学字体
-\newif\ifsourcehan \sourcehanfalse % 切换思源字体
-\newif\ifdisplay \displayfalse % 切换展示公式
-\newif\ifcollection \collectionfalse % 用于试卷题库
-
-\DeclareOption{a3paper}{\sidebysidetrue}
-\DeclareOption{a3input}{\sidebysidetrue\mifengxianfalse}
-\DeclareOption{reverse}{\reversetrue}
+\ProvidesClass{jnuexam}[2023/12/11 v2.0 An exam class for Jinan University]
+
+%% 旧版本的 LaTeX 不能识别 2022-11-01 这种日期格式
+%\@ifl@t@r\fmtversion{2022-11-01}{}{
+\@ifl@t@r\fmtversion{2022/11/01}{}{
+ \ClassError{jnuexam}{%
+ Your current TeX distribution is quite old.\MessageBreak
+ We need CTeX 3.0+ or MiKTeX 2023+ or TeXLive 2023+%
+ }{Please update your TeX distribution first.}
+}
+
+\newif\ifplain \plainfalse % 是否添加装订线和草稿纸
+\newif\iftwoinone \twoinonefalse % 是否使用 A3 纸张
+\newif\ifoneside \onesidefalse % 是否单面印刷试卷
+\newif\ifresetnumber \resetnumbertrue % 是否对各题型小题分别编号
+\newif\ifrandom \randomfalse % 是否乱序出题
+\newif\ifanswer \answertrue % 是否显示答案
+\newif\ifamsfonts \amsfontsfalse % 切换数学字体
+\newif\ifsourcehan \sourcehanfalse % 切换思源字体
+\newif\ifsolidot \solidotfalse % 是否替换空心句号为实心句号
+\newif\ifcellspace \cellspacefalse % 增加表格列间距
+\newif\ifmedmath \medmathfalse % 切换公式尺寸
+
+\DeclareOption{plain}{\plaintrue}
+\DeclareOption{a3paper}{\twoinonetrue}
+\DeclareOption{a3input}{\twoinonetrue\plaintrue}
+\DeclareOption{oneside}{\onesidetrue}
+\DeclareOption{random}{\randomtrue}
\DeclareOption{noanswer}{\answerfalse}
\DeclareOption{amsfonts}{\amsfontstrue}
\DeclareOption{sourcehan}{\sourcehantrue}
-\DeclareOption{display}{\displaytrue}
-\DeclareOption{collection}{\collectiontrue\mifengxianfalse}
+\DeclareOption{solidot}{\solidottrue}
+\DeclareOption{medmath}{\cellspacetrue\medmathtrue}
\DeclareOption*{\PassOptionsToClass{\CurrentOption}{ctexart}} %其它选项
@@ -32,32 +46,61 @@
% 四号 小四号 五号 小五号
% 14bp 12bp 10.5bp 9bp
+% 实际上,在旧版本 ctex 中只能用 cs4size 和 c5size 选项
+% 而新版本 ctex 中,可以利用 zihao 选项指定各种中文字号
+\PassOptionsToPackage{CJKnumber}{xeCJK}
\LoadClass[cs4size,UTF8,noindent]{ctexart}
-\ifamsfonts
- \RequirePackage{amssymb}
-\else
- \RequirePackage[utopia]{mathdesign} % charter, utopia
- \renewcommand\bfdefault{bx}
- \let\oldoiint\oiint\renewcommand{\oiint}{\oldoiint\nolimits}
- \DeclareTextCommandDefault{\nobreakspace}{\leavevmode\nobreak\ }
+% 在旧版本 xeCJK 中,必须用 CJKnumber 选项载入 CJKnumb 包,后面才载入会报错
+% 但在新版本 xeCJK 中 CJKnumber 选项已经被废弃,需要在后面自行载入它
+% 在 xeCJK 中已经禁止载入 CJK,但是在新版本 ctex 宏包中却失效了
+% 我们假装 CJK 已经载入,再载入 CJKnumb,避免出现 \CJKglue 重复定义的问题
+% 注意用 PDFLaTeX 编译时需要用到 CJK,所以只在未定义时才作修改
+\ifdefined\else
+ \@namedef{ver@CJK.sty}{}
+ %\@namedef{opt@CJK.sty}{}
\fi
+\RequirePackage{CJKnumb}
+
+% 新版本 xeCJK 已经废弃并禁用 CJKfntef,改用 xeCJKfntef 取代,我们需要载入后者
+% 注意要保证能在较旧的 TeX 系统中编译,我们只能用 \ifXeTeX 而不能用 \ifxetex
+% 因为旧版本 iftex 宏包只有 \ifXeTeX 命令,而 ifxetex 宏包才有 \ifxetex 命令
+% 在 2019 年 10 月,LaTeX 开发团队接管了 iftex 宏包,新版本同时提供这两个命令
+\RequirePackage{CJKfntef}
+\RequirePackage{iftex}
+\ifXeTeX\@ifpackagelater{xeCJK}{2020/02/10}{\RequirePackage{xeCJKfntef}}{}\fi
-\ifsidebyside
+\iftwoinone
\RequirePackage[a3paper,landscape,twocolumn,columnsep=60mm,left=30mm,right=30mm,top=25mm,bottom=25mm]{geometry}
\else
\RequirePackage[a4paper,left=30mm,right=30mm,top=25mm,bottom=25mm]{geometry}
\fi
-\RequirePackage{tabularx}
-\RequirePackage{lastpage}
-\RequirePackage{fancyhdr}
-\RequirePackage{xcolor}
+\RequirePackage{amsmath}
+\RequirePackage{array}
+\RequirePackage{calc}
\RequirePackage{comment}
+\RequirePackage[inline]{enumitem}
\RequirePackage{environ}
\RequirePackage{etoolbox}
-\RequirePackage{calc}
-\RequirePackage{iftex}
+\RequirePackage{fancyhdr}
+\RequirePackage{zref-user,zref-lastpage}
+\RequirePackage{tabularx}
+\RequirePackage{xcolor}
+\RequirePackage{xkeyval}
+
+\ifplain
+ \allowdisplaybreaks[4]
+\fi
+
+\ifamsfonts
+ \RequirePackage{amssymb}
+\else
+ \RequirePackage[utopia]{mathdesign} % charter, utopia
+ \renewcommand\bfdefault{bx}
+ \let\oldoiint\oiint\renewcommand{\oiint}{\oldoiint\nolimits}
+ \DeclareTextCommandDefault{\nobreakspace}{\leavevmode\nobreak\ }
+\fi
\newcolumntype{Y}{>{\centering\arraybackslash}X}
\newcolumntype{n}[1]{>{\centering\arraybackslash}m{#1}}
@@ -67,55 +110,151 @@
\setlength{\lineskip}{4pt}
%% ---------------------------------------------------------------------------
-%% 密封线命令 \mifengxian
-%% 草稿纸命令 \caogaozhi
-%% 这两个命令仅在 A3 纸张中用到,且需要编译两次才能得到正确结果
+%% 装订线命令 \addbindingline
+%% 草稿纸命令 \addscratchpaper
+%% 这两个命令需要编译两次才能得到正确结果
%% ---------------------------------------------------------------------------
-\newcommand{\mifengxianleft}{
+\newcommand{\setexam}[1]{\setkeys{jnuexam@setup}{#1}}
+
+\ifplain\else
+ \RequirePackage{tikz}
+ \RequirePackage{everypage}
+\fi
+
+\newcommand{\bindinglineleft}{
\path (current page.north west) +(25mm,-25mm) coordinate (a1);
\path (current page.south west) +(25mm,25mm) coordinate (a2);
\draw[dashed] (a1) -- node[left=1mm,text width=1em,inner sep=0pt]{\1{线}\0\1{订}\0\1{装}} (a2);
}
-\newcommand{\mifengxianright}{
+\newcommand{\bindinglineright}{
\path (current page.north east) +(-25mm,-25mm) coordinate (b1);
\path (current page.south east) +(-25mm,25mm) coordinate (b2);
\draw[dashed] (b1) -- node[right=1mm,text width=1em,inner sep=0pt]{\2{装}\0\2{订}\0\2{线}} (b2);
}
-\newcommand{\mifengxianone}{%
+\newcommand{\bindinglineone}{%
\def\0{\\[70mm]}\def\1{\rotatebox{90}}\def\2{\rotatebox{-90}}%
\begin{tikzpicture}[remember picture,overlay,very thick]
- \ifnumodd{\value{page}}{\mifengxianleft}{\mifengxianright}
+ \ifnumodd{\value{page}}{\bindinglineleft}{\bindinglineright}
\end{tikzpicture}}
-\newcommand{\mifengxiantwo}{%
+\newcommand{\bindinglinetwo}{%
\def\0{\\[70mm]}\def\1{\rotatebox{90}}\def\2{\rotatebox{-90}}%
\begin{tikzpicture}[remember picture,overlay,very thick]
- \mifengxianleft\mifengxianright
+ \bindinglineleft\bindinglineright
+\end{tikzpicture}}
+
+\iftwoinone
+ \let\bindingline=\bindinglinetwo
+\else
+ \let\bindingline=\bindinglineone
+\fi
+
+\def\zhuangdingxian{1}
+\define@key{jnuexam@setup}{binding}[2]{\def\zhuangdingxian{#1}}
+
+\newcommand{\addbindingline}{%
+ \ifcase\zhuangdingxian % 0
+ \or % 1
+ \ifbool{answer}{}{\bindingline}%
+ \or % 2
+ \bindingline
+ \fi
+}
+
+\ifplain\else
+ \AddEverypageHook{\addbindingline}
+\fi
+
+\newcommand{\scratchpaperone}{%
+\begin{tikzpicture}[remember picture,overlay,font=\sffamily\fontsize{120pt}{120pt}\selectfont]
+ \node[text=lightgray!40,text width=120pt] at (current page.center) {草\\ 稿\\ 纸};
\end{tikzpicture}}
-\newcommand{\caogaozhi}{%
+\newcommand{\scratchpapertwo}{%
\begin{tikzpicture}[remember picture,overlay,font=\sffamily\fontsize{180pt}{180pt}\selectfont]
\node[text=lightgray!40] at (current page.center) {草\quad 稿\quad 纸};
\end{tikzpicture}}
-\ifmifengxian
- \RequirePackage{tikz}
- \RequirePackage{everypage}
- \ifsidebyside
- \AddEverypageHook{\mifengxiantwo}
- % 在 twocolumn 文档中,\newpage 可能是到下一栏,\clearpage 才能保证到下一页
- \preto{\@enddocumenthook}{\clearpage\pagestyle{empty}\caogaozhi\clearpage\caogaozhi\addtocounter{page}{-2}}
- % 在旧版本 ctex 宏包中不能用 \AtEndDocument 添加含中文的内容,即不能用 \appto 而要用 \preto
- %\AtEndDocument{\clearpage\pagestyle{empty}\caogaozhi\clearpage\caogaozhi\addtocounter{page}{-2}}
- \else
- \AddEverypageHook{\mifengxianone}
- \fi
+\def\caogaozhi{0}
+\define@key{jnuexam@setup}{scratch}[1]{\def\caogaozhi{#1}}
+
+\newcounter{my@empty@page} % 空白页数
+\newcounter{my@scratch@page} % 草稿页数
+\newcounter{my@extra@page} % 空白页数+草稿页数
+
+% 添加空白页,使得草稿纸前页数在单面印刷时为偶数,双面印刷时为4的倍数
+% 添加草稿纸,页数在单面印刷时等于设置值的两倍,双面印刷时等于设置值的4倍
+\newcommand{\doscratchpaperone}{%
+ \clearpage\pagestyle{empty}\let\addbindingline=\relax
+ \ifnumgreater{\caogaozhi}{0}{%
+ \ifbool{oneside}{%
+ \ifnumodd{\value{page}}%
+ {\setcounter{my@empty@page}{0}}%
+ {\setcounter{my@empty@page}{1}}%
+ \setcounter{my@scratch@page}{\caogaozhi*2}%
+ }{%
+ \setcounter{my@empty@page}{(\value{page}+2)/4*4+1-\value{page}}%
+ \setcounter{my@scratch@page}{\caogaozhi*4}%
+ }%
+ \my@add@extra@page
+ }{}%
+}
+
+% 注意在 twocolumn 文档中,\newpage 到下一栏,\clearpage 到下一页
+% 另外注意第一行的 \clearpage 等不能移动到 \my@add@extra@page 命令里
+% 因为 \clearpage 后本页已经结束,page 表示的是下一页的页码
+\newcommand{\doscratchpapertwo}{%
+ \clearpage\pagestyle{empty}\let\addbindingline=\relax
+ \ifnumgreater{\caogaozhi}{0}{%
+ \ifbool{oneside}{%
+ \setcounter{my@empty@page}{0}%
+ \setcounter{my@scratch@page}{\caogaozhi}%
+ }{%
+ \setcounter{my@empty@page}{(\value{page}/2)-(\value{page}/2)/2*2}%
+ \setcounter{my@scratch@page}{\caogaozhi*2}%
+ }%
+ \my@add@extra@page
+ }{}%
+}
+
+\newcommand{\my@add@extra@page}{%
+ \setcounter{my@extra@page}{\value{my@empty@page}+\value{my@scratch@page}}%
+ \whileboolexpr{
+ test{\ifnumgreater{\value{my@empty@page}}{0}}
+ }{%
+ \addtocounter{my@empty@page}{-1}%
+ \leavevmode\clearpage
+ }%
+ \whileboolexpr{
+ test{\ifnumgreater{\value{my@scratch@page}}{0}}
+ }{%
+ \addtocounter{my@scratch@page}{-1}%
+ \leavevmode\scratchpaper\clearpage
+ }%
+ \addtocounter{page}{-\value{my@extra@page}}%
+}
+
+\iftwoinone
+ \let\scratchpaper=\scratchpapertwo
+ \let\doscratchpaper=\doscratchpapertwo
+\else
+ \let\scratchpaper=\scratchpaperone
+ \let\doscratchpaper=\doscratchpaperone
\fi
-\ifsidebyside
+% 在旧版本 ctex 宏包中不能用 \AtEndDocument 添加含中文的内容,即不能用 \appto 而要用 \preto
+\newcommand{\addscratchpaper}{%
+ \preto{\@enddocumenthook}{\doscratchpaper}%
+}
+
+\ifplain\else\ifanswer\else
+ \addscratchpaper
+\fi\fi
+
+\iftwoinone
\RequirePackage{pdfpages}
% 新版本 pdfpages 将 \includepdf 放在文档开头时会有命令未定义的错误
% 见 https://tex.stackexchange.com/questions/352007/ieeetran-and-pdfpages
@@ -167,7 +306,7 @@
\hline
\textbf{考试方式} \\ 开卷~[\isquad{\bijuan}]\quad 闭卷~[\ischeck{\bijuan}] \\
\hline
- \textbf{试卷类别}~(\,A, B, C\,)\\\relax [\,\shijuan\,]\hfill 共~\pageref{LastPage}~页
+ \textbf{试卷类别}~(\,A, B, C\,)\\\relax [\,\shijuan\,]\hfill 共~\zpageref{LastPage}~页
\end{tabular}
}
@@ -181,9 +320,12 @@
\newcommand{\makehead}{
\thispagestyle{plain}
- \centerline{\LARGE\bfseries 暨\quad 南\quad 大\quad 学\quad 考\quad 试\quad 试\quad 卷}
+ \centerline{%
+ \LARGE\bfseries\ifanswer\color{red!80!black}\fi
+ 暨\quad 南\quad 大\quad 学\quad 考\quad 试\quad 试\quad 卷\ifanswer\quad 答\quad 案\fi
+ }%
\vspace{2em}%
- \ifreverse
+ \ifrandom
\ifx\shijuan\my@temp@a\renewcommand{\shijuan}{B}\fi
\ifx\shijuan\my@temp@c\renewcommand{\shijuan}{D}\fi
\fi
@@ -204,9 +346,9 @@
\hline
\textbf{题\quad 号} & 一 & 二 & 三 & 四 & 五 & 六 & 总分\\
\hline
- \textbf{得\quad 分} & & & & & & & \\
+ \textbf{得\quad 分}\rule[-0.75em]{0pt}{2.5em} & & & & & & & \\
\hline
- \textbf{评阅人} & & & & & & & \\
+ \textbf{评阅人}\rule[-0.75em]{0pt}{2.5em} & & & & & & & \\
\hline
\end{tabularx}
}
@@ -219,12 +361,27 @@
\newcommand{\my@headleft}{\hspace{-0.3em}《\kecheng》\kern-0.3em 试卷\,\shijuan}
\newcommand{\my@headright}{姓名\hspace{6em}学号\hspace{6em}}
\newcommand{\my@headtext}{\my@headleft\hfill \my@headright}
-\newcommand{\my@foottext}{第~\thepage~页\quad 共~\pageref{LastPage}~页}
+\newcommand{\my@foottext}{第~\thepage~页\quad 共~\zpageref{LastPage}~页}
+% fancy page style
+\fancyhf{} % 清空页眉页脚
+\iftwoinone
+ \renewcommand{\headrulewidth}{0pt}%
+ \lhead{\small\underline{\my@columnbox{\my@headtext}\strut}}
+ \rhead{\small\underline{\my@columnbox{\my@headtext}\strut}}
+ \lfoot{\small\my@columnbox{\my@foottext}}
+ \rfoot{\small\my@columnbox{\stepcounter{page}\my@foottext}}
+\else
+ \lhead{\small\my@headleft}
+ \rhead{\small\my@headright}
+ \cfoot{\small\my@foottext}
+\fi
+
+% plain page style
\fancypagestyle{plain}{
\renewcommand{\headrulewidth}{0pt}%
\fancyhf{}
- \ifsidebyside
+ \iftwoinone
\rhead{\small\underline{\my@columnbox{\my@headtext\strut}}}
\lfoot{\small\my@columnbox{\my@foottext}}
\rfoot{\small\my@columnbox{\stepcounter{page}\my@foottext}}
@@ -232,18 +389,11 @@
\cfoot{\small\my@foottext}
\fi
}
-\fancyhf{}
-\pagestyle{fancy}
-\ifsidebyside
- \renewcommand{\headrulewidth}{0pt}%
- \lhead{\small\underline{\my@columnbox{\my@headtext}\strut}}
- \rhead{\small\underline{\my@columnbox{\my@headtext}\strut}}
- \lfoot{\small\my@columnbox{\my@foottext}}
- \rfoot{\small\my@columnbox{\stepcounter{page}\my@foottext}}
+
+\ifplain
+ \pagestyle{plain}
\else
- \lhead{\small\my@headleft}
- \rhead{\small\my@headright}
- \cfoot{\small\my@foottext}
+ \pagestyle{fancy}
\fi
%% ---------------------------------------------------------------------------
@@ -251,44 +401,174 @@
%% 附录命令 \makedata
%% 题目环境 problem
%% 解答环境 solution
-%% 逆序选项 reverse
+%% 乱序选项 random
%% ---------------------------------------------------------------------------
+\newif\ifonlyoneproblem \onlyoneproblemfalse % 此部分仅有一道题时不显示题目编号
\xdef\allproblems{}
\xdef\lastproblem{}
-\newcounter{problem}
+\newcounter{problem} % 当前题型的小题编号
+\newcounter{problemreal} % 实际显示的小题编号,在各题型小题统一编号时使用
+\newcounter{totalproblems} % 之前各题型小题总数,在各题型小题统一编号时使用
\newcommand{\solutionname}{解}
\newcounter{choice} % 后面选择题的 abcd 环境要用到
-\newcounter{step} % 后面解答题的 \step 命令要用到
+\newcommand{\hangtext}{}
+\newlength{\hanglength}
+\colorlet{part number}{black}
+\colorlet{problem number}{blue!80!black}
+\colorlet{solution name}{blue!80!black}
+
+\ifrandom
+ \RequirePackage{pgf}
+ \RequirePackage{pgffor}
+\fi
+
+\newcounter{my@shuffle@temp@cnt}
+\newcounter{my@list@temp@cnt}
+
+\newcommand\my@list@print[1]{%
+ \par\renewcommand*{\do}[1]{(##1)}%
+ \dolistloop#1%
+}
+
+\newcommand\my@list@remove[2]{%
+ %\my@list@print\my@shuffle@list
+ \setcounter{my@list@temp@cnt}{0}%
+ \global\let\my@tmpa@list=#1%
+ \gdef#1{}%
+ \par\renewcommand*{\do}[1]{%
+ \stepcounter{my@list@temp@cnt}%
+ \ifnumequal{\value{my@list@temp@cnt}}{#2}{%
+ \def\my@list@item{##1}%
+ %[##1]%
+ }{
+ \listxadd#1{##1}%
+ }%
+ }%
+ \dolistloop\my@tmpa@list
+}
-\newcommand{\printproblems}{\ifreverse\lastproblem\allproblems\fi\xdef\allproblems{}\xdef\lastproblem{}}
+%% 随机数种子不能超过 2147483647 = "7FFFFFFF
+\def\my@random@seed{19061116}
+\define@key{jnuexam@setup}{seed}[19061116]{\def\my@random@seed{#1}}
+
+\newcommand\my@shuffle@problems{%
+ %% 当\pgfmathrandom的参数为3的倍数时,对相邻种子生成的多个随机数分布不均匀
+ %\pgfmathsetseed{\numexpr\my@random@seed+\value{section}-1\relax}%
+ %% 因此我们改用下面的方法,用随机数种子生成下一个随机数种子
+ \pgfmathsetseed{\my@random@seed}%
+ \pgfmathrandominteger\my@random@seed{1}{2147483647}%
+ \ifnumgreater{\value{problem}}{2}{%
+ \gdef\my@shuffle@list{}%
+ \foreach \i in {1,...,\value{problem}} {\listxadd\my@shuffle@list{\i}}%
+ %% 首尾两个小题的位置总要改变
+ \pgfmathrandom{2,\value{problem}}%
+ \my@list@remove\my@shuffle@list{\pgfmathresult}%
+ \global\csletcs{my@problem@b@1}{my@problem@a@\my@list@item}%
+ \ifnumequal{\my@list@item}{\value{problem}}{
+ \pgfmathrandom{\numexpr\value{problem}-1\relax}%
+ \my@list@remove\my@shuffle@list{\pgfmathresult}%
+ \global\csletcs{my@problem@b@\the\value{problem}}{my@problem@a@\my@list@item}%
+ }{%
+ \pgfmathrandom{\numexpr\value{problem}-2\relax}%
+ \my@list@remove\my@shuffle@list{\pgfmathresult}%
+ \global\csletcs{my@problem@b@\the\value{problem}}{my@problem@a@\my@list@item}%
+ }%
+ %% 其他小题的位置没有任何限制
+ \setcounter{my@shuffle@temp@cnt}{1}%
+ \whileboolexpr{%
+ test{\ifnumless{\value{my@shuffle@temp@cnt}}{\numexpr\value{problem}-1\relax}}%
+ }{%
+ \stepcounter{my@shuffle@temp@cnt}%
+ \pgfmathrandom{\numexpr\value{problem}-\value{my@shuffle@temp@cnt}\relax}%
+ \my@list@remove\my@shuffle@list{\pgfmathresult}%
+ \global\csletcs{my@problem@b@\the\value{my@shuffle@temp@cnt}}{%
+ my@problem@a@\my@list@item
+ }%
+ }%
+ }{%
+ \ifnumequal{\value{problem}}{2}{%
+ \global\csletcs{my@problem@b@1}{my@problem@a@2}%
+ \global\csletcs{my@problem@b@2}{my@problem@a@1}%
+ }{}%
+ }%
+}
+
+\newcommand{\printproblems}{%
+ \ifrandom
+ \my@appto@problems
+ \my@shuffle@problems
+ \setcounter{problem}{0}%
+ \allproblems
+ \fi
+ \xdef\allproblems{}%
+ \xdef\lastproblem{}%
+}
\newcommand{\makepart}[2]{%
\printproblems
+ \setcounter{totalproblems}{\value{totalproblems}+\value{problem}}%
\setcounter{problem}{0}%
\stepcounter{section}%
\vspace{1em}%
- \noindent\textbf{\Chinese{section}、#1}(#2)%
- \par\vspace{1em}%
+ \noindent\textbf{\textcolor{part number}{\Chinese{section}}、#1}(#2)%
+ \par\nopagebreak
+ \if\relax\detokenize{#1}\relax % #1 is empty
+ \onlyoneproblemtrue
+ \else
+ \onlyoneproblemfalse
+ \vspace{1em}%
+ \fi
+ %其中设定了\@nobreaktrue,保证在列表前也不分页,详情见 source2e
+ \@afterheading
}
\newcommand{\makedata}[1]{%
- \printproblems\my@stop@reverse
+ \printproblems\my@stop@random
\centerline{\textbf{附录}\quad #1}\smallskip
}
-\preto{\@enddocumenthook}{\printproblems\my@stop@reverse}
+\preto{\@enddocumenthook}{\printproblems\my@stop@random}
\newcommand\ignorepars{\@ifnextchar\par{\expandafter\ignorepars\@gobble}{}}
-\newenvironment{problemreal}{%
- \stepcounter{problem}\setcounter{choice}{0}\setcounter{step}{0}%
- \textbf{\textsf{{\color{blue}\arabic{problem}}.}}\;\,\ignorespaces
-}{\par}
+% 局部定义,仅在当前题目内有效
+\define@key{jnuexam@problem}{points}[-1]{\def\my@problem@points{#1}}
+\define@key{jnuexam@problem}{level}[]{\def\my@problem@level{#1}}
+\define@key{jnuexam@problem}{year}[]{\def\my@problem@year{#1}}
+
+\newcommand{\problempointstext}[1]{(#1 分)}
+
+\newcommand\my@hook@exec@other@keys{}
+
+\newcommand{\execute@problem@keys}[1]{%
+ \setkeys{jnuexam@problem}{#1}%
+ \my@hook@exec@other@keys
+ \ifdefvoid{\my@problem@points}{}{\problempointstext{\my@problem@points}}%
+}
+
+\newenvironment{problemreal}[1][]{%
+ \stepcounter{problem}\setcounter{choice}{0}%
+ \ifresetnumber
+ \ifonlyoneproblem
+ \renewcommand{\hangtext}{\qquad}%
+ \else
+ \renewcommand{\hangtext}{\textbf{\textsf{\textcolor{problem number}{\arabic{problem}}.}}\;\,}%
+ \fi
+ \else
+ \setcounter{problemreal}{\value{totalproblems}+\value{problem}}%
+ \renewcommand{\hangtext}{\textbf{\textsf{\textcolor{problem number}{\arabic{problemreal}}.}}\;\,}%
+ \fi
+ \settowidth{\hanglength}{\hangtext}%
+ \description[leftmargin=\hanglength,labelwidth=0pt,labelsep=0pt,topsep=0pt,parsep=0pt]
+ \item[\hangtext]\execute@problem@keys{#1}%
+}{\enddescription}
\newenvironment{solutionreal}{%
- \setcounter{step}{0}%
- \textbf{\textsf{{\color{blue}\solutionname}.}}\;\,\ignorepars
-}{\par}
+ \renewcommand{\hangtext}{\textbf{\textsf{\textcolor{solution name}{\solutionname}.}}\;\,}%
+ \settowidth{\hanglength}{\hangtext}%
+ \description[leftmargin=\hanglength,labelwidth=0pt,labelsep=0pt,topsep=0pt,parsep=0pt]
+ \item[\hangtext]
+}{\enddescription}
\let \oldnewpage = \newpage
\let \oldvfill = \vfill
@@ -296,42 +576,45 @@
\let \oldmedskip = \medskip
\let \oldbigskip = \bigskip
-\ifreverse
+\ifrandom
+ \newcommand\my@appto@problems{%
+ \xappto\allproblems{\expandonce\lastproblem}%
+ }%
\NewEnviron{problem}{%
- \xdef\allproblems{%
- \unexpanded\expandafter{\lastproblem}%
- \unexpanded\expandafter{\allproblems}%
- }%
- \xdef\lastproblem{%
+ \stepcounter{problem}%
+ \my@appto@problems
+ \csxdef{my@problem@a@\the\value{problem}}{%
\unexpanded{\begin{problemreal}}%
\unexpanded\expandafter{\BODY}%
\unexpanded{\end{problemreal}}%
}%
+ \csxdef{my@problem@b@\the\value{problem}}{%
+ \expandonce{\csname my@problem@a@\the\value{problem}\endcsname}%
+ }%
+ \xdef\lastproblem{%
+ \expandonce{\csname my@problem@b@\the\value{problem}\endcsname}%
+ }%
}
\NewEnviron{solution}{%
- \xdef\lastproblem{%
- \unexpanded\expandafter{\lastproblem}%
+ \csxappto{my@problem@a@\the\value{problem}}{%
\unexpanded{\begin{solutionreal}}%
- \unexpanded\expandafter{\BODY}%
+ \expandonce{\BODY}%
\unexpanded{\end{solutionreal}}%
}%
}
- \renewcommand{\newpage}{\xdef\lastproblem{\noexpand\oldnewpage\unexpanded\expandafter{\lastproblem}}}
- \renewcommand{\vfill}{\xdef\lastproblem{\unexpanded\expandafter{\lastproblem\oldvfill}}}
- \renewcommand{\smallskip}{\xdef\lastproblem{\unexpanded\expandafter{\lastproblem\oldsmallskip}}}
- \renewcommand{\medskip}{\xdef\lastproblem{\unexpanded\expandafter{\lastproblem\oldmedskip}}}
- \renewcommand{\bigskip}{\xdef\lastproblem{\unexpanded\expandafter{\lastproblem\oldbigskip}}}
- \let \newpagea = \relax
- \let \newpageb = \newpage
+ \renewcommand{\newpage}{\gappto\lastproblem{\oldnewpage}}
+ \renewcommand{\vfill}{\csgappto{my@problem@a@\the\value{problem}}{\oldvfill}}
+ \renewcommand{\smallskip}{\csgappto{my@problem@a@\the\value{problem}}{\oldsmallskip}}
+ \renewcommand{\medskip}{\csgappto{my@problem@a@\the\value{problem}}{\oldmedskip}}
+ \renewcommand{\bigskip}{\csgappto{my@problem@a@\the\value{problem}}{\oldbigskip}}
\else
- \newenvironment{problem}{\problemreal}{\endproblemreal}
- \newenvironment{solution}{\solutionreal}{\endsolutionreal}
- \let \newpagea = \newpage
- \let \newpageb = \relax
+ \newenvironment{problem}[1][]{\problemreal[#1]}{\endproblemreal}
+ %\newenvironment{solution}{\solutionreal}{\endsolutionreal}
+ \NewEnviron{solution}{\begin{solutionreal}\BODY\end{solutionreal}}
\fi
-\newcommand{\my@stop@reverse}{%
- \ifreverse
+\newcommand{\my@stop@random}{%
+ \ifrandom
\renewenvironment{problem}{\problemreal}{\endproblemreal}%
\renewenvironment{solution}{\solutionreal}{\endsolutionreal}%
\let \newpage = \oldnewpage
@@ -416,23 +699,34 @@
%% ---------------------------------------------------------------------------
%% 答案切换命令 \answer
-%% 判断命令 \true 和 \false
+%% 判断命令 \tickin 和 \tickout
%% 填空命令 \fillin 和 \fillout
%% 选择命令 \pickin 和 \pickout
%% ---------------------------------------------------------------------------
\newcommand{\answer}[1]{\ifanswer#1\else\phantom{#1}\fi}
-\newcommand{\cdotfill}{\leavevmode\xleaders\hbox to 0.5em{\hss$\cdot$\hss}\hfill\kern0pt\relax}
-\newcommand{\true}{\unskip\nobreak\cdotfill(\makebox[1.5em]{\color{blue}\answer{$\checkmark$}})}
-\newcommand{\false}{\unskip\nobreak\cdotfill(\makebox[1.5em]{\color{blue}\answer{\sffamily x}})}
+\newcommand*{\cdotfill}{\leavevmode\xleaders\hbox to 0.5em{\hss$\cdot$\hss}\hfill\kern0pt\relax}
+
+\newcommand*{\tick@box}[1]{[\makebox[1.5em]{\color{blue}\answer{#1}}]}
+\newcommand*{\tick@text@t}{$\checkmark$}
+\newcommand*{\tick@text@f}{{\large$\times$}}
+\newcommand*{\tick@text@T}{\sffamily T}
+\newcommand*{\tick@text@F}{\sffamily F}
+\newcommand*{\tickin}[1]{\tick@box{\csname tick@text@#1\endcsname}}
+\newcommand*{\tickout}[1]{\unskip\nobreak\cdotfill\tick@box{\csname tick@text@#1\endcsname}}
+% 过时命令,不要再使用
+%\newcommand*{\true}{\tickout{t}}
+%\newcommand*{\false}{\tickout{f}}
+
+\newcommand*{\ulinefill}[1]{\xleaders\hbox{\underline{\vphantom{#1}\kern1pt}}\hfill\kern0pt}
+\newcommand*{\minwidthbox}[2]{\makebox[{\ifdim#1<\width\width\else#1\fi}]{#2}}
-\newcommand{\ulinefill}[1]{\xleaders\hbox{\underline{\vphantom{#1}\kern1pt}}\hfill\kern0pt}
-\newcommand{\fillout}[1]{\allowbreak\hbox{}\nobreak\ulinefill{#1}\underline{\color{blue}\answer{#1}}\ulinefill{#1}}
-\newcommand{\fillin}[1]{\underline{\hspace{1em}\color{blue}\answer{#1}\hspace{1em}}}
+\newcommand*{\fillout}[1]{\allowbreak\hbox{}\nobreak\ulinefill{#1}\underline{\color{blue}\answer{#1}}\ulinefill{#1}}
+\newcommand*{\fillin}[1]{\underline{\hspace{1em}\color{blue}\minwidthbox{2em}{\answer{#1}}\hspace{1em}}}
-\newcommand{\pickout}[1]{\unskip\nobreak\cdotfill(\makebox[1.5em]{\color{blue}\answer{#1}})}
-\newcommand{\pickin}[1]{\unskip\nobreak\hspace{0.3em}(\makebox[1.5em]{\color{blue}\answer{#1}})\hspace{0.3em}\ignorespaces}
+\newcommand*{\pickout}[1]{\unskip\nobreak\cdotfill(\makebox[1.5em]{\color{blue}\answer{#1}})}
+\newcommand*{\pickin}[1]{\unskip\nobreak\hspace{0.3em}(\makebox[1.5em]{\color{blue}\answer{#1}})\hspace{0.3em}\ignorespaces}
%% ---------------------------------------------------------------------------
%% 选择题四个选项排版环境,根据四个选项的长度自动排成一行、两行或四行
@@ -440,6 +734,7 @@
%% ---------------------------------------------------------------------------
\newlength{\my@item@len}
+\newlength{\my@label@len}
\newcommand\my@item@temp{%
\unskip\cr\stepcounter{choice}(\Alph{choice})\ %
@@ -449,7 +744,13 @@
\stepcounter{choice}(\Alph{choice})\ \ignorespaces
}
\newcommand\my@item@par{%
- \par\stepcounter{choice}(\Alph{choice})\ \ignorespaces
+ \stepcounter{choice}%
+ \def\my@label@text{(\Alph{choice})\ }%
+ \settowidth{\my@label@len}{\my@label@text}%
+ \par \parshape 2 \hanglength \linewidth
+ \dimexpr\hanglength + \my@label@len\relax
+ \dimexpr\linewidth - \my@label@len\relax
+ \my@label@text\ignorespaces
}
\NewEnviron{abcd}{
@@ -514,13 +815,14 @@
}
%% ---------------------------------------------------------------------------
-%% 解答题步骤命令 \step
+%% 设定有序列表使用悬挂缩进,并指定前两级有序列表的标签格式
+%% 标签宽度按最宽者自动设定,左边距自动计算,竖直空白全部去掉
+%% 最后的 itemjoin 设定行内有序列表 enumerate* 两项之间的空白
%% ---------------------------------------------------------------------------
-\newcommand{\step}{%
- \stepcounter{step}%
- \textsf{(\arabic{step})}\;\,%
-}
+\setlist[enumerate]{labelindent=0pt,labelsep=0.2em,itemindent=0pt,leftmargin=*,nosep,itemjoin=\quad}
+\setlist[enumerate,1]{label=(\arabic*)}
+\setlist[enumerate,2]{label=(\alph*),widest*=1}
%% ---------------------------------------------------------------------------
%% 自由对齐命令 \tabpoint, \tabto, \tableft
@@ -593,48 +895,31 @@
\let \< = \tableft
%% ---------------------------------------------------------------------------
-%% 评分命令 \score
+%% 评分命令 \points
%% ---------------------------------------------------------------------------
\PassOptionsToPackage{tbtags}{amsmath}
\RequirePackage{amsmath}
-\newcommand{\myscore}[1]{\textcolor{red}{#1\kern0.15em 分}}
+\newcommand{\mypoints}[1]{\textcolor{red}{#1\kern0.15em 分}}
-\newcommand{\scoretext}[1]{\mbox{}\nobreak\hfill$\cdots\cdots$\myscore{#1}\par\noindent\ignorespaces}
-\newcommand{\scoreeqno}[1]{\eqno{\cdots\cdots\text{\myscore{#1}}}}
-\newcommand{\scoretag}[1]{\tag*{$\cdots\cdots$\myscore{#1}}}
+\newcommand{\pointstext}[1]{\mbox{}\nobreak\hfill$\cdots\cdots$\mypoints{#1}\par\noindent\ignorespaces}
+\newcommand{\pointseqno}[1]{\eqno{\cdots\cdots\text{\mypoints{#1}}}}
+\newcommand{\pointstag}[1]{\tag*{$\cdots\cdots$\mypoints{#1}}}
-\newrobustcmd{\score}[1]{%
+\newrobustcmd{\points}[1]{%
\ifbool{mmode}{%
- \ifdefstrequal{\tag}{\dft@tag}{\scoreeqno{#1}}{\scoretag{#1}}%
+ \ifdefstrequal{\tag}{\dft@tag}{\pointseqno{#1}}{\pointstag{#1}}%
}{%
- \scoretext{#1}%
+ \pointstext{#1}%
}%
}
-
-%% ---------------------------------------------------------------------------
-%% 文档选项 display 将全部公式都设为展示公式
-%% 命令 \display 将当前环境的公式都设为展示公式
-%% ---------------------------------------------------------------------------
-
-\newcommand{\display}{\everymath\expandafter{\the\everymath\displaystyle}}
-\ifbool{display}{
- \RequirePackage[math]{cellspace}
- \setlength\cellspacetoplimit{2pt}
- \setlength\cellspacebottomlimit{2pt}
- \addparagraphcolumntypes{X}
- % Fix cellspace bug before version 1.7
- % See https://tex.stackexchange.com/a/385581
- \@ifpackagelater{cellspace}{2017/08/12}{}{
- \patchcmd{\@endpbox}{\color@endgroup}{\expandafter\color@endgroup}{}{}
- }
- \display
-}{}
+%\let\score=\points % \score 命令已经废弃,不要再使用
%% ---------------------------------------------------------------------------
%% 载入个人定制文件 jnuexam.cfg
%% 中文字体切换选项 sourcehan
+%% 实心句号替换选项 solidot
%% ---------------------------------------------------------------------------
\InputIfFileExists{jnuexam.cfg}{}{}
@@ -647,50 +932,149 @@
%\setCJKsansfont{思源黑体}
}
-\ifbool{sourcehan}{
- % https://sourceforge.net/p/xetex/code/ci/master/tree/source/texk/web2c/xetexdir/NEWS
- \ifbool{XeTeX}{ % TeXLive 2015
- \ifdimless{\the\XeTeXversion\XeTeXrevision pt}{0.99992pt}{}{\my@set@sourcehan}
- }{}
- \ifbool{LuaTeX}{\my@set@sourcehan}{}
-}{}
+\AtBeginDocument{%
+ \ifbool{sourcehan}{%
+ % https://sourceforge.net/p/xetex/code/ci/master/tree/source/texk/web2c/xetexdir/NEWS
+ \ifbool{XeTeX}{% TeXLive 2015
+ \ifdimless{\the\XeTeXversion\XeTeXrevision pt}{0.99992pt}{}{\my@set@sourcehan}%
+ }{}%
+ \ifbool{LuaTeX}{\my@set@sourcehan}{}%
+ }{}%
+}
+
+%% 这里不能用 \ifbool,因为涉及到 catcode 的改变
+\ifsolidot
+ \ifXeTeX
+ \catcode`。=\active\def。{.}%
+ \else\ifLuaTeX
+ \catcode`。=\active\def。{.}%
+ \fi
+ \fi
+\fi
%% ---------------------------------------------------------------------------
-%% 试卷题库选项 collection
+%% 在 tabular 和 array 等表格环境中添加列间距
+%% 避免单元格里出现的分式太过接近上面和下面行
%% ---------------------------------------------------------------------------
-\ifcollection
- \RequirePackage{hyperref}
- \hypersetup{
- pdfstartview={FitH},
- bookmarksnumbered=true,
- unicode=true,
- hidelinks=true
- %colorlinks=true,
- %linkcolor=black
- }
- \appto{\endproblem}{\medskip}
- \appto{\endsolution}{\medskip}
- \preto{\problem}{\ifnum\value{problem}=9 \setcounter{problem}{-1}\fi}
- \pagestyle{plain}
- \let\chapter=\part
- \@addtoreset{section}{part}
- \RequirePackage{xkeyval}
- \define@key{jnuexam}{level}[]{\def\my@collection@level{#1}}
- \define@key{jnuexam}{year}[]{\def\my@collection@year{#1}}
- \define@key{jnuexam}{name}[]{\def\my@collection@name{#1}}
- \newcommand{\info}[1]{%
- \setkeys{jnuexam}{level,year,name,#1}% 重置之前的数据
- \my@collection@info@do
+\newcommand{\my@do@cellspace}{%
+ \RequirePackage[math]{cellspace}%
+ \setlength\cellspacetoplimit{2pt}%
+ \setlength\cellspacebottomlimit{2pt}%
+ \addparagraphcolumntypes{X}%
+ \newcolumntype{0}[1]{>{\bcolumn ##1\@nil}##1<{\ecolumn}}%
+ \newcolumntype{5}[1]{>{$}0{##1}<{$}}%
+ % Fix cellspace bug before version 1.7
+ % See https://tex.stackexchange.com/a/385581
+ \@ifpackagelater{cellspace}{2017/08/12}{}{%
+ \patchcmd{\@endpbox}{\color@endgroup}{\expandafter\color@endgroup}{}{}%
+ }%
+}
+
+\AtBeginDocument{%
+ \ifcellspace \my@do@cellspace \fi
+}
+
+%% ---------------------------------------------------------------------------
+%% 统一行间公式和行内公式的巨算符和分式的尺寸
+%% 利用开头的 medmath 选项可以启用此部分设定
+%% ---------------------------------------------------------------------------
+
+\newcommand{\my@do@medmath}{%
+ \RequirePackage[mediummath]{nccmath}%
+ %% 补充 \oiint 命令的调整
+ \ifdef{\oiint}{%
+ \let\NCC@op@oiint=\oiint
+ \DeclareRobustCommand{\oiintop}{\mathop{\medmath{\NCC@op@oiint}}}%
+ \def\oiint{\DOTSI\NCC@op@prepare{\oiintop}}%
+ }{}%
+ %% 设定 nccmath 的积分号校正尺寸
+ %% 后面已经改用相对尺寸,不再需要
+ %\ifamsfonts
+ % \medintcorr{0.5em}
+ %\else
+ % \medintcorr{0.3em}
+ %\fi
+ %% 使用 nccmath 宏包后,cases 环境包含定积分时将无法编译,这里重新定义此环境
+ %% 注意相比 amsmath 的原始定义,我们这里将 \quad 从两列之间移动到第二列最前面
+ %% 这是因为,我们常将 cases 用于只有一列的方程组,这样处理末尾不会有多余空白
+ \ifbool{cellspace}{%
+ \renewenvironment{cases}{%
+ \left\{\linespread{1.0}\selectfont\def\arraystretch{1.2}%
+ \begin{array}{@{}5l@{}>{\quad}5l@{}}%
+ }{%
+ \end{array}\right.%
+ }%
+ }{%
+ \renewenvironment{cases}{%
+ \left\{\linespread{1.0}\selectfont\def\arraystretch{1.2}%
+ \begin{array}{@{}l@{}>{\quad}l@{}}%
+ }{%
+ \end{array}\right.%
+ }%
}
- \newcommand{\my@collection@info@do}{%
- \bigskip\hrule\nopagebreak\vspace{0.4em}\nopagebreak
- \ifdefempty{\my@collection@level}{}{Level = \my@collection@level\quad}%
- \ifdefempty{\my@collection@year}{}{Year = \my@collection@year\quad}%
- \ifdefempty{\my@collection@name}{}{Name = \my@collection@name\quad}%
- \nopagebreak\vspace{0.4em}\nopagebreak\hrule\medskip
+ %% 当 minipage 或 \parbox 仅包含行间公式时,盒子的右边距丢失,这里修正它
+ %% 其他类似问题的描述见 http://tex.stackexchange.com/q/22170
+ \let\start@gather=\NCC@startgather
+ \let\start@align=\NCC@startalign
+ \let\start@multline=\NCC@startmultline
+ \let\mathdisplay=\NCC@startdisplay
+}
+
+\newcommand{\my@do@medmath@fix}{%
+ %% 修正在角标处的非积分巨算符尺寸
+ %% 参考了 scalerel 宏包对数学样式的保存方法
+ % 非角标巨算符保持为 \displaystyle 巨算符的 80% 大小
+ % 一级角标巨算符修改为 \textstyle 巨算符的 80% 大小
+ % 二级角标巨算符修改为 \scriptstyle 巨算符的 80% 大小
+ \def\@my@style@D{\displaystyle}%
+ \def\@my@style@T{\displaystyle}%
+ \def\@my@style@S{\textstyle}%
+ \def\@my@style@s{\scriptstyle}%
+ \def\my@style@saved{\csname @my@style@\@my@style@switch\endcsname}%
+ \newcommand{\my@style@this}[1]{%
+ \mathchoice{\def\@my@style@switch{D}##1}{\def\@my@style@switch{T}##1}
+ {\def\@my@style@switch{S}##1}{\def\@my@style@switch{s}##1}%
+ }%
+ \DeclareRobustCommand*\medmath[1]{\NCC@select@msize
+ \mathord{\my@style@this{\raise\@tempdima\hbox{\NCC@prepare@msize$\my@style@saved ##1$}}}%
}
-\fi
+ %% 修正在角标处的积分算符尺寸和上下限位置
+ \newlength{\@my@em}%
+ \setlength{\@my@em}{1em}%
+ \ifamsfonts
+ \medintcorr{0.5\@my@em}%
+ \else
+ \medintcorr{0.3\@my@em}%
+ \fi
+ \newcommand{\my@style@unit}[1]{%
+ \mathchoice{\setlength{\@my@em}{1em}##1}{\setlength{\@my@em}{1em}##1}
+ {\setlength{\@my@em}{0.5em}##1}{\setlength{\@my@em}{0.3em}##1}%
+ }%
+ \let\my@saved@op@printm=\NCC@op@printm
+ \def\NCC@op@printm{\my@style@unit{\my@saved@op@printm}}%
+ %% 修正在角标位置的分式和嵌套分式
+ %% 总是使用当前样式尺寸来排版分式的分子和分母
+ \newcommand{\my@larger@frac}[2]{%
+ \mathchoice{\genfrac{}{}{}{0}{##1}{##2}}{\genfrac{}{}{}{0}{##1}{##2}}%
+ {\genfrac{}{}{}{1}{##1}{##2}}{\genfrac{}{}{}{2}{##1}{##2}}%
+ }%
+ \DeclareRobustCommand{\frac}[2]{%
+ \mathchoice{\mfrac{##1}{##2}}{\mfrac{##1}{##2}}%
+ {\my@larger@frac{##1}{##2}}{\my@larger@frac{##1}{##2}}%
+ }%
+ \patchcmd{\NCC@prepare@msize}{%
+ \def\frac{\protect\NCC@innerfrac{}}%
+ }{%
+ \let\frac=\my@larger@frac
+ }{}{}%
+}
+
+\AtBeginDocument{%
+ \ifmedmath
+ \my@do@medmath \my@do@medmath@fix
+ \fi
+}
%% ---------------------------------------------------------------------------
%% 载入常用宏包,定义常用命令
@@ -713,26 +1097,55 @@
\xeCJKsetcharclass{"2460}{"24FF}{1} % 带圈数字字母,括号数字字母,带点数字等
}{}
-\RequirePackage{CJKfntef}
\RequirePackage{multirow}
-\RequirePackage{diagbox}
\RequirePackage{tabu}
+\RequirePackage{diagbox}
+%% 修正 \diagbox 在 array 环境中使用的问题
+\newrobustcmd{\diagboxtwo}[3][]{%
+ \ifbool{mmode}{%
+ \hbox{\let\tabcolsep=\arraycolsep\diagbox[#1]{$#2$}{$#3$}}%
+ }{%
+ \diagbox[#1]{#2}{#3}%
+ }
+}
+\newrobustcmd{\diagboxthree}[4][]{%
+ \ifbool{mmode}{%
+ \hbox{\let\tabcolsep=\arraycolsep\diagbox[#1]{$#2$}{$#3$}{$#4$}}%
+ }{%
+ \diagbox[#1]{#2}{#3}{#4}%
+ }
+}
+
+\RequirePackage{mathtools} % \mathllap 命令,pmatrix* 环境等
\RequirePackage{extarrows}
\RequirePackage{relsize}
\newcommand{\Int}{\mathop{\mathlarger{\int}}}
+\AtBeginDocument{%
+ \let\my@saved@lim=\lim \def\lim{\my@saved@lim\limits}%
+ \let\my@saved@sum=\sum \def\sum{\my@saved@sum\limits}%
+ \let\my@saved@prod=\prod \def\prod{\my@saved@prod\limits}%
+}
+%\newcommand{\limit}{\lim\limits} % 废弃命令,不要再使用
+
\newcommand{\e}{\mathrm{e}}
-\newcommand{\limit}{\lim\limits}
\newcommand{\R}{\mathbb{R}}
+\DeclareMathOperator{\arccot}{arccot}
\DeclareMathOperator{\Corr}{\rho}
\DeclareMathOperator{\Cov}{Cov}
+\DeclareMathOperator{\diag}{diag}
\DeclareMathOperator{\grad}{grad}
\DeclareMathOperator{\Prj}{Prj}
+\DeclareMathOperator{\tr}{tr}
\DeclareMathOperator{\Var}{Var}
+\DeclareMathOperator{\diver}{div}
+\let\division=\div
+\let\div=\diver
+
\newcommand{\diff}{\mathop{}\!\mathrm{d}}
\newcommand{\dx}{\diff x}
\newcommand{\dy}{\diff y}
@@ -750,6 +1163,23 @@
\renewrobustcmd{\d}{\ifbool{mmode}{\diff}{\oldd}}%
}
+\let\pd=\partial
+\newcommand{\pdf}{\pd f}
+\newcommand{\pdg}{\pd g}
+\newcommand{\pdh}{\pd h}
+\newcommand{\pdl}{\pd l}
+\newcommand{\pdn}{\pd n}
+\newcommand{\pdu}{\pd u}
+\newcommand{\pdv}{\pd v}
+\newcommand{\pdx}{\pd x}
+\newcommand{\pdy}{\pd y}
+\newcommand{\pdz}{\pd z}
+\newcommand{\pdF}{\pd F}
+\newcommand{\pdL}{\pd L}
+\newcommand{\pdP}{\pd P}
+\newcommand{\pdQ}{\pd Q}
+\newcommand{\pdR}{\pd R}
+
% from mathabx package
\DeclareFontFamily{U}{mathx}{\hyphenchar\font45}
\DeclareFontShape{U}{mathx}{m}{n}{<-> mathx10}{}
@@ -778,7 +1208,44 @@
\def\T{\mathrm{T}\kern-.5pt}
-\newrobustcmd{\wfrac}[3][2pt]{%
- {\begingroup\hspace{#1}#2\hspace{#1}\endgroup\over\hspace{#1}#3\hspace{#1}}%
+% 分数线长一点的分数,\wfrac[2pt]{x}{y} 表示左右加 2pt
+% 和前面的 medmath 一样,将代码放在 \AtBeginDocument 里
+\AtBeginDocument{%
+ \newrobustcmd{\wfrac}[3][2pt]{%
+ \frac{\hspace{#1}#2\hspace{#1}}{\hspace{#1}#3\hspace{#1}}%
+ }%
+ \newrobustcmd{\wdfrac}[3][2pt]{%
+ \dfrac{\hspace{#1}#2\hspace{#1}}{\hspace{#1}#3\hspace{#1}}%
+ }%
+ \newrobustcmd{\wtfrac}[3][2pt]{%
+ \tfrac{\hspace{#1}#2\hspace{#1}}{\hspace{#1}#3\hspace{#1}}%
+ }%
}
+% 使用 stix font 中的 white arrows
+\ifxetex
+ %\IfFileExists{STIX-Regular.otf}{% 在 TeXLive 中无效
+ \IfFileExists{stix.sty}{%
+ \newfontfamily{\mystix}{STIX} % stix v1.1
+ }{%
+ \newfontfamily{\mystix}{STIXGeneral} % stix v1.0
+ }
+ \newrobustcmd\leftwhitearrow{%
+ \mathrel{\text{\normalfont\mystix\symbol{"21E6}}}%
+ }
+ \newrobustcmd\upwhitearrow{%
+ \mathrel{\text{\normalfont\mystix\symbol{"21E7}}}%
+ }
+ \newrobustcmd\rightwhitearrow{%
+ \mathrel{\text{\normalfont\mystix\symbol{"21E8}}}%
+ }
+ \newrobustcmd\downwhitearrow{%
+ \mathrel{\text{\normalfont\mystix\symbol{"21E9}}}%
+ }
+\else
+ \let \leftwhitearrow = \Leftarrow
+ \let \rightwhitearrow = \Rightarrow
+ \let \upwhitearrow = \Uparrow
+ \let \downwhitearrow = \Downarrow
+\fi
+