summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/spbmark/spbmark.dtx
blob: b2666aab8060a400fbfd1708cfd2866b07803bb9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
% \iffalse meta-comment
%
% Copyright (C) 2021 by Qu Yi <quee123@foxmail.com>
%
% This work may be distributed and/or modified under the
% conditions of the CC-BY 4.0 License.
% The latest version of this license is in
%   https://creativecommons.org/licenses/by/4.0/legalcode
% \fi
%
% \iffalse
%<*driver>
\documentclass{l3doc}
\usepackage{spbmark,siunitx}
\usepackage[noto]{newtxmath}
\OnlyDescription
\begin{document}
  \DocInput{\jobname.dtx}
  \PrintIndex
\end{document}
%</driver>
% \fi
%
% \title{\pkg{spbmark} -- Customize superscripts and subscripts}
% \author{Qu Yi}
% \date{2021/07/23\hskip 1em\relax v1.04\thanks{\url{https://github.com/texl3/spbmark}}}
%
% \maketitle
% \begin{abstract}
%   \pkg{spbmark} provides three commands \tn{super}, \tn{sub} and \tn{supersub} to improve the layout of superscripts and subscripts which can be adjusted the relative position and format, and can be used in text and math mode.
% \end{abstract}
% \tableofcontents
%
% \section{Macro package options}
% \label{sec:macro package options}
% \begin{function}[added = 2021-06-26]{ctex}
% This option works with the C\TeX{} document class used by simplified Chinese users, there's actually no functional change. Adding path \texttt{style} to \tn{ctexset} command, which is equivalent to using \tn{spbset}.
% \end{function}
%
% \begin{function}[added = 2021-06-30]{newsupb}
% \texttt{newsupb} is a boolean option with a default value of true that redefines the \LaTeX{} kernel commands to cause \tn{sp} and \tn{textsuperscript} are equivalent to \tn{super} command, and \tn{sb} and \tn{textsubscript} are equivalent to \tn{sub} command.
% \end{function}
%
% \section{User commands}
% \begin{function}[added = 2021-06-26,updated = 2021-06-28]{\super,\sub,\supersub}
% \begin{syntax}
%   \tn{super*}\oarg{vshift}[<height>,<depth>]\parg{code}\marg{content}\oarg{hshift}
%   \tn{sub*}\oarg{vshift}[<height>,<depth>]\parg{code}\marg{content}\oarg{hshift}
%   \tn{supersub*}\oarg{script sep}\oarg{script align}\parg{super format code}
%   \          \marg{super content}\marg{sub content}
%   \          \oarg{horizontal shift}\parg{sub format code}
% \end{syntax}
% \tn{super} command is used to output superscripts, \tn{sub} command is used to output subscripts, \tn{supersub} command is used to output both superscripts and subscripts.
% \end{function}
%
% They match the corresponding pattern depending on whether they are currently in text mode or mathematical mode, or they can use an asterisk variant to force the mathematical pattern. The \meta{vshift} and \meta{hshift} represent respectively vertical and horizontal offsets of superscript or subscript, their default value is \texttt{0pt}, and the parameters of \meta{script align} are the same as the \texttt{supersubalign}.
%
% The second optional parameter generally does not need to be used. The \meta{height} and \meta{depth} are separated by commas. Only the front part indicates the height of the superscript or subscript, and only the back part indicates the depth.
%
% The \meta{code} is used to format superscripts and subscripts, and can insert commands such as fonts or colors. The last command in the code can take an argument, which is either a superscript or a subscript.
%
% \begin{function}[added = 2021-06-30]{\sp,\sb,\spb,\textsuperscript,\textsubscript}
% Except for the \tn{spb} command which is equivalent to \tn{supersub}, the others are \LaTeX{} kernel commands. If you use the \texttt{newsupb} package option then they will be redefined to make the command shorter, see section \ref{sec:macro package options}.
%
% If you need to use the original definitions of \tn{textsuperscript} and \tn{textsubscript}, then \tn{spb@textsuperscript@save} and \tn{spb@textsubscript@save} will be available. If you need to use the original definitions of \tn{sp} and \tn{sb}, then \tn{spb@sp@save} and \tn{spb@sb@save} will be available.
% \end{function}
%
% \section{Global control interface}
% \begin{function}[added = 2021-06-26,updated = 2021-07-23]{\spbset}
% \begin{syntax}
%   \tn{spbset}\marg{key-value list}
% \end{syntax}
% \pkg{spbmark} uses the \tn{spbset} command to control the global default format of superscripts and subscripts. The values ​​set by it will be overwritten by the optional parameters of the superscript and other commands.
% \end{function}
%
% \begin{function}{super-vshift,super-hshift,sub-vshift,sub-hshift,super-format,sub-format}
% \begin{syntax}
%   super-vshift = <fixed length>
%   super-hshift = <fixed length>
%   sub-vshift = <fixed length>
%   sub-hshift = <fixed length>
%   super-format = <format code>
%   sub-format = <format code>
% \end{syntax}
% These list of keys control the format of superscript or subscript. They are equivalent to the optional parameters of the \tn{super} or \tn{sub} commands.
% \end{function}
%
% \noindent
% \DescribeOption{super-vshift} Extra vertical shift of the superscripts. \\
% \DescribeOption{super-hshift} Extra horizontal shift of the superscripts. \\
% \DescribeOption{sub-vshift} Extra vertical shift of the subscripts. \\
% \DescribeOption{sub-hshift} Extra horizontal shift of the subscripts. \\
% \DescribeOption{super-format} Control the format of superscripts, the last command in the code can take an argument, which is a superscript. \\
% \DescribeOption{sub-format} Control the format of subscripts, the last command in the code can take an argument, which is a subscript.
%
% \begin{function}{supersub-hshift,supersub-format,supersubsep,supersubalign}
% \begin{syntax}
%   supersub-hshift = <fixed length>
%   supersub-format = \{<super code>,<sub code>\}
%   supersubsep = <fixed length>
%   supersubalign = <horizontal alignment>
% \end{syntax}
% These list of keys control the format of superscripts and subscripts. They are equivalent to the optional parameters of the \tn{supersub} command.
% \end{function}
%
% \noindent
% \DescribeOption{supersub-hshift} Extra vertical shift of the superscripts and the subscripts. \\
% \DescribeOption{supersub-format} Control the format of superscripts or subscripts. The first part is in superscript format, and the latter part is in subscript format. The two are separated by commas, or only the first part exists. \\
% \DescribeOption{supersubsep} The distance between superscripts and subscripts, its default value is \texttt{0.3ex}. \\
% \DescribeOption{supersubalign} The alignment of superscripts and subscripts, which contains \texttt{l}, \texttt{c}, and \texttt{r} parameters respectively for left, center, and right alignment.
%
% \section{Examples of use}
% Here is a list of the three commands, please pay attention to the delimiter and usage of optional parameters:
% \begin{quotation}
%   \noindent
%   |\spbset{supersub-format = {\ttfamily,\color{blue}}}| \\
%   |A\super[0.2ex](\textcolor{red}){exam}[0.2em]B| \\
%   |$A\sub(\mathsf){exam}B$| \\
%   |A\supersub[0.3ex][c]{examsuper}{sub}B| \\
%   \spbset{supersub-format = {\ttfamily,\color{blue}}}
%   A\super[0.2ex](\textcolor{red}){exam}[0.2em]B \\
%   $A\sub(\mathsf){exam}B$ \\
%   A\supersub[0.3ex][c]{examsuper}{sub}B
% \end{quotation}
%
% It can also be used with the \pkg{siunitx} package to output superscripts and subscripts in the unit:
% \begin{quotation}
%   \noindent
%   |\unit[mode = math]{kg.m/s\super*[-1pt]{2}}| \\
%   |\qty[mode = text]{30}{A\supersub(\color{red}){b}{c}[1pt]}| \\
%   |\spbset{sub-hshift = 2pt}\unit[mode = text]{A_b}| \\
%   \unit[mode = math]{kg.m/s\super*[-1pt]{2}} \\
%   \qty[mode = text]{30}{A\supersub(\color{red}){b}{c}[1pt]} \\
%   \spbset{sub-hshift = 2pt}\unit[mode = text]{A_b}
% \end{quotation}
%
% \pkg{spbmark} also patches the footer markers for standard document class and \cls{KOMA-Script}. You can format the footer markers by redefining the \tn{fnmarkfont} command. Note that extra horizontal shift does not work with footnote markers.
%
% \section{Known issues}
% At present, the vertical and horizontal offsets are effective for the unit commands in the \pkg{siunitx} macro package. However, due to the special mechanism that the decimal point is not recognized correctly because it is converted to a space in the \tn{unit} command, it is recommended to use \texttt{pt} as the unit of offset.
%
% \newcommand\urlprefix{\newline\hspace*{\fill}}
% \let\OldUrl\url
% \renewcommand\url[2][]{{\small\textit{#1}~\OldUrl{#2}}}
% \begin{thebibliography}{99}
% \bibitem{realscripts}
% \textsc{Will Robertson}.
% \newblock \textit{The realscripts package} [CP/OL].
% \newblock version 0.3d,
% \newblock (2016-02-13)
% \urlprefix\url{https://ctan.org/pkg/realscripts}
% \end{thebibliography}
%
% \StopEventually{}
%<*package>
\NeedsTeXFormat{LaTeX2e}[2018/12/31]
\RequirePackage{xparse,l3keys2e}
\ProvidesExplPackage{spbmark}{2021/07/23}{1.04}
  {Customize superscripts and subscripts}

\cs_new_protected:Npn \spb_define:n { \keys_define:nn { spbmark } }
\cs_new_protected:Npn \spbset { \keys_set:nn { spbmark } }
\keys_define:nn { spbmark/option }
  {
    ctex .code:n        =
      {
        \cs_set:Npn \spb_define:n { \keys_define:nn { ctex/style } }
        \cs_set:Npn \spbset { \keys_set:nn { ctex/style } }
      },
    newsupb .bool_set:N = \l__spb_new_supersub_bool,
    newsupb .default:n  = true,
    newsupb .initial:n  = true
  }

\ProcessKeysOptions{spbmark/option}

\tl_new:N \l__spb_super_script_formatii_tl
\tl_new:N \l__spb_sub_script_formatii_tl
\spb_define:n
  {
    super-vshift .dim_set:N     = \l__spb_super_script_vshift_dim,
    super-vshift .initial:n     = 0pt,
    super-hshift .dim_set:N     = \l__spb_super_script_hshift_dim,
    super-hshift .initial:n     = 0pt,
    sub-vshift .dim_set:N       = \l__spb_sub_script_vshift_dim,
    sub-vshift .initial:n       = 0pt,
    sub-hshift .dim_set:N       = \l__spb_sub_script_hshift_dim,
    sub-hshift .initial:n       = 0pt,
    supersub-hshift .dim_set:N  = \l__spb_supersub_script_hshift_dim,
    supersub-hshift .initial:n  = 0pt,
    super-format .tl_set:N      = \l__spb_super_script_formati_tl,
    sub-format .tl_set:N        = \l__spb_sub_script_formati_tl,
    supersub-format .code:n     = \spb_both_format_assign:n {#1},
    supersubsep .dim_set:N      = \l__spb_supersub_script_sep_dim,
    supersubsep .initial:n      = 0.3ex,
    supersubalign .tl_set:N     = \l__spb_supersub_script_align_tl,
    supersubalign .initial:n    = l
  }

\tl_set:Nn \l__spb_boxa_wd_tl { \box_wd:N \l_tmpa_box }
\tl_set:Nn \l__spb_boxb_wd_tl { \box_wd:N \l_tmpb_box }
\cs_new:Npn \spb_tmp_boxa_use: { \box_use:N \l_tmpa_box }
\cs_new:Npn \spb_tmp_boxb_use: { \box_use:N \l_tmpb_box }
\cs_new:Npn \spb_box_max_dim_horizontal:
  {
    \skip_horizontal:n
      { \dim_max:nn { \l__spb_boxa_wd_tl } { \l__spb_boxb_wd_tl } }
  }
\cs_new:Npn \spb_boxwd_subtract:nnnn #1#2#3#4
  {
    \skip_horizontal:n
      { #1\tl_use:c { l__spb_#3_wd_tl } - #2\tl_use:c { l__spb_#4_wd_tl } }
  }
\cs_new:Npn \spb_boxwd_script_align:nn #1#2
  {
    \spb_boxwd_subtract:nnnn { 0.5 } { 0.5 } {#1} {#2}
    \use:c { spb_tmp_#2_use: }
    \spb_boxwd_subtract:nnnn { -0.5 } { 0.5 } {#1} {#2}
    \use:c { spb_tmp_#1_use: }
  }
\cs_new:Npn \spb_math_print_store:nnn #1#2#3
  {
    \hbox_set:Nn \l_tmpa_box
      { \ensuremath{#1{\spb_math:nn {#2} {#3}}} }
  }
\cs_new:Npn \spb_text_print_store:nnn #1#2#3
  {
    \hbox_set:Nn \l_tmpa_box
      { #1{\use:c { spb@text#2script@save }{#3}} }
  }
\cs_new:Npn \spb_math_print_store:nnnn #1#2#3#4
  {
    \hbox_set:Nn \l_tmpa_box { \ensuremath{#1{\spb@sp@save{#2}}} }
    \hbox_set:Nn \l_tmpb_box { \ensuremath{#3{\spb@sb@save{#4}}} }
  }
\cs_new:Npn \spb_text_print_store:nnnn #1#2#3#4
  {
    \hbox_set:Nn \l_tmpa_box { #1{\spb@textsuperscript@save{#2}} }
    \hbox_set:Nn \l_tmpb_box { #3{\spb@textsubscript@save{#4}} }
  }
\cs_set_eq:NN \spb@textsuperscript@save \textsuperscript
\cs_set_eq:NN \spb@textsubscript@save \textsubscript
\cs_set_eq:NN \spb@sp@save \sp
\cs_set_eq:NN \spb@sb@save \sb
\cs_new:Npn \spb_math:nn #1
  {
    \str_case:nn {#1}
      {
        { super } { \spb@sp@save }
        { sub } { \spb@sb@save }
      }
  }
\cs_new_protected:Npn \spb_box_ht_dp_assign:nn #1#2
  {
    \tl_if_empty:nF {#1} { \box_set_ht:Nn \l_tmpb_box {#1} }
    \tl_if_novalue:nF {#2} { \box_set_dp:Nn \l_tmpb_box {#2} }
  }
\NewDocumentCommand{\spb_both_format_assign:n}
  {>{\SplitArgument{1}{,}}m}
  {\spb_supersub_script_both_format:nn #1}
\cs_new_protected:Npn \spb_supersub_script_both_format:nn #1#2
  {
    \tl_set:Nn \l__spb_super_script_formatii_tl {#1}
    \tl_if_novalue:nTF {#2}
      { \tl_clear:N \l__spb_sub_script_formatii_tl }
      { \tl_set:Nn \l__spb_sub_script_formatii_tl {#2} }
  }

\clist_map_inline:nn
  { super,sub }
  {
    \exp_args:Nc \NewDocumentCommand {#1}
      {
        sO{\dim_use:c { l__spb_#1_script_vshift_dim }}
        >{\SplitArgument{1}{,}}O{}
        D(){\tl_use:c { l__spb_#1_script_formati_tl }}
        mO{\dim_use:c { l__spb_#1_script_hshift_dim }}
      }
      {
        \IfBooleanTF{##1}
          {\spb_math_print_store:nnn {##4} {#1} {##5}}
          {
            \mode_if_math:TF
              { \spb_math_print_store:nnn {##4} {#1} {##5} }
              { \spb_text_print_store:nnn {##4} {#1} {##5} }
          }
        \hbox_set_to_wd:Nnn \l_tmpb_box { \l__spb_boxa_wd_tl + ##6 }
          { \hss\box_move_up:nn {##2} { \spb_tmp_boxa_use: } }
        \spb_box_ht_dp_assign:nn ##3
        \spb_tmp_boxb_use:
      }
  }
\NewDocumentCommand{\supersub}
  {
    sO{\l__spb_supersub_script_sep_dim}
    O{\l__spb_supersub_script_align_tl}
    D(){\l__spb_super_script_formatii_tl}mm
    O{\l__spb_supersub_script_hshift_dim}
    D(){\l__spb_sub_script_formatii_tl}
  }
  {
    \IfBooleanTF{#1}
      {\spb_math_print_store:nnnn {#4} {#5} {#8} {#6}}
      {
        \mode_if_math:TF
          { \spb_math_print_store:nnnn {#4} {#5} {#8} {#6} }
          { \spb_text_print_store:nnnn {#4} {#5} {#8} {#6} }
      }
    \hbox_set_to_wd:Nnn \l_tmpa_box { \l__spb_boxa_wd_tl + #7 }
      { \hss\box_move_up:nn {#2} { \spb_tmp_boxa_use: } }
    \hbox_set_to_wd:Nnn \l_tmpb_box { \l__spb_boxb_wd_tl + #7 }
      { \hss\box_move_down:nn {#2} { \spb_tmp_boxb_use: } }
    \str_case:onF {#3}
      {
        { l } { \use_i:nnn }
        { c } { \use_ii:nnn }
        { r } { \use_iii:nnn }
      }
      {
        \msg_warning:nn { spbmark } { unsupported-align }
        \use_i:nnn
      }
      {
        \hbox_overlap_right:n { \spb_tmp_boxa_use: }
        \hbox_overlap_right:n { \spb_tmp_boxb_use: }
        \spb_box_max_dim_horizontal:
      }
      {
        \dim_compare:nNnTF { \l__spb_boxa_wd_tl } > { \l__spb_boxb_wd_tl }
          { \spb_boxwd_script_align:nn { boxa } { boxb } }
          { \spb_boxwd_script_align:nn { boxb } { boxa } }
      }
      {
        \spb_box_max_dim_horizontal:
        \hbox_overlap_left:n { \spb_tmp_boxa_use: }
        \hbox_overlap_left:n { \spb_tmp_boxb_use: }
      }
  }
\msg_new:nnn { spbmark } { unsupported-align }
  {
    Alignment~only~supports~l,~c,~and~r. \\
    The~l~parameter~will~be~used~by~default.
  }

\bool_if:NT \l__spb_new_supersub_bool
  {
    \clist_map_inline:nn
      {
        { sp,sb },
        { textsuperscript,textsubscript }
      }
      {
        \cs_set_eq:cN { \clist_item:nn {#1} { 1 } } \super
        \cs_set_eq:cN { \clist_item:nn {#1} { 2 } } \sub
      }
  }
\cs_set_eq:NN \spb \supersub
\cs_set:Npn \@makefnmark
  { \hbox:n { \fnmarkfont\super{\@thefnmark}[0pt] } }
\cs_if_exist:NTF \ftntm@font
  { \cs_new:Npn \fnmarkfont { \ftntm@font } }
  { \cs_new:Npn \fnmarkfont { \normalfont } }
%</package>
\endinput