summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/spbmark/spbmark.sty
blob: bc2aeab66f94bb7eda4144034ac4058e28ea11d6 (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
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
%
% ***************** THE SPBMARK PACKAGE *****************
%
% Copyright (C) 2021-2022 by Qu Yi <q1jx@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
\NeedsTeXFormat{LaTeX2e}[2018/12/31]
\RequirePackage{xparse,l3keys2e}
\ProvidesExplPackage{spbmark}{2022/01/23}{1.3}
  {Customize superscripts and subscripts}

\cs_generate_variant:Nn \box_set_ht:Nn { cv }
\cs_generate_variant:Nn \box_set_dp:Nn { cv }
\cs_generate_variant:Nn \dim_max:nn { VV }
\cs_generate_variant:Nn \dim_compare:nNnTF { V }
\cs_generate_variant:Nn \msg_warning:nnn { nnV }
\cs_generate_variant:Nn \str_case:nn { x }
\cs_generate_variant:Nn \tl_if_novalue:nF { V }

\cs_new_protected:Npn \spb_define:n { \keys_define:nn { ctex/style } }
\cs_new_protected:Npn \spbset { \keys_set:nn { ctex/style } }
\keys_define:nn { spbmark/option }
  {
    text .bool_set:N        = \l_spb_newsupb_text_bool,
    text .default:n         = true,
    math .bool_set:N        = \l_spb_newsupb_math_bool,
    math .default:n         = true,
    foot .bool_set:N        = \l_spb_newsupb_foot_bool,
    foot .default:n         = true,
    both .meta:n            = { text,math },
    both .value_forbidden:n = true,
    all .meta:n             = { text,math,foot },
    all .value_forbidden:n  = true,
    ctex .code:n            = { },
    newsupb .code:n         = { }
  }

\ProcessKeysOptions{spbmark/option}

\tl_new:N \l__spb_super_cmd_ii_tl
\tl_new:N \l__spb_sub_cmd_ii_tl
\tl_new:N \g__spb_mark_case_init_tl

\cs_new_protected:Npn \spb_local_case_init:nnn #1#2#3
  {
    \str_case:Vn \g__spb_mark_case_init_tl
      {
        { super } {#1}
        { sub } {#2}
        { supersub } {#3}
      }
  }
\cs_new_protected:Npn \defspbstyle #1#2
  {
    \spb_define:n
      {
        style/#1 .undefine:,
        style/#1 .code:n = \keys_set:nn { ctex/style } {#2}
      }
  }
\spb_define:n
  {
    spvmove .tl_set:N   = \l__spb_super_vmove_tl,
    spvmove .initial:n  = 0pt,
    sphmove .tl_set:N   = \l__spb_super_hmove_tl,
    sphmove .initial:n  = 0pt,
    sbvmove .tl_set:N   = \l__spb_sub_vmove_tl,
    sbvmove .initial:n  = 0pt,
    sbhmove .tl_set:N   = \l__spb_sub_hmove_tl,
    sbhmove .initial:n  = 0pt,
    spbhmove .tl_set:N  = \l__spb_supersub_hmove_tl,
    spbhmove .initial:n = 0pt,
    vmove .code:n       =
      {
        \spb_local_case_init:nnn
          { \tl_set:Nn \l__spb_super_vmove_tl {#1} }
          { \tl_set:Nn \l__spb_sub_vmove_tl {#1} }
          { \tl_set:Nn \l__spb_supersub_vsep_tl {#1} }
      },
    hmove .code:n       =
      {
        \spb_local_case_init:nnn
          { \tl_set:Nn \l__spb_super_hmove_tl {#1} }
          { \tl_set:Nn \l__spb_sub_hmove_tl {#1} }
          { \tl_set:Nn \l__spb_supersub_hmove_tl {#1} }
      },
    nohmove .meta:n     = { sphmove = 0pt,sbhmove = 0pt },
    novmove .meta:n     = { spvmove = 0pt,sbvmove = 0pt },
    spcmd .tl_set:N     = \l__spb_super_cmd_i_tl,
    sbcmd .tl_set:N     = \l__spb_sub_cmd_i_tl,
    spbcmd .code:n      = \spb@both@cmd@assign{#1},
    cmd .code:n         =
      {
        \spb_local_case_init:nnn
          { \tl_set:Nn \l__spb_super_cmd_i_tl {#1} }
          { \tl_set:Nn \l__spb_sub_cmd_i_tl {#1} }
          { \spb@both@cmd@assign{#1} }
      },
    spcmd+ .code:n      = \tl_put_right:Nn \l__spb_super_cmd_i_tl {#1},
    sbcmd+ .code:n      = \tl_put_right:Nn \l__spb_sub_cmd_i_tl {#1},
    spbcmd+ .code:n     = \spb@both@cmd@assign+{#1},
    cmd+ .code:n        =
      {
        \spb_local_case_init:nnn
          { \tl_put_right:Nn \l__spb_super_cmd_i_tl {#1} }
          { \tl_put_right:Nn \l__spb_sub_cmd_i_tl {#1} }
          { \spb@both@cmd@assign+{#1} }
      },
    spheight .tl_set:N  = \l__super_height_i_tl,
    sbheight .tl_set:N  = \l__sub_height_i_tl,
    spbheight .tl_set:N = \l__super_height_ii_tl,
    height .code:n      =
      {
        \spb_local_case_init:nnn
          { \tl_set:Nn \l__super_height_i_tl {#1} }
          { \tl_set:Nn \l__sub_height_i_tl {#1} }
          { \tl_set:Nn \l__super_height_ii_tl {#1} }
      },
    spdepth .tl_set:N   = \l__super_depth_i_tl,
    sbdepth .tl_set:N   = \l__sub_depth_i_tl,
    spbdepth .tl_set:N  = \l__sub_depth_ii_tl,
    depth .code:n       =
      {
        \spb_local_case_init:nnn
          { \tl_set:Nn \l__super_depth_i_tl {#1} }
          { \tl_set:Nn \l__sub_depth_i_tl {#1} }
          { \tl_set:Nn \l__sub_depth_ii_tl {#1} }
      },
    vsep .tl_set:N      = \l__spb_supersub_vsep_tl,
    vsep .initial:n     = 0.6ex,
    halign .tl_set:N    = \l__spb_supersub_halign_tl,
    halign .initial:n   = l,
    style .choice:,
    style .value_required:n = true,
    mode .tl_set:N      = \l__spb_mode_value_tl,
    mode .initial:n     = match
  }

\cs_set_eq:NN \spb@textsuperscript@save \textsuperscript
\cs_set_eq:NN \spb@textsubscript@save \textsubscript
\cs_set_eq:NN \spb@math@super@save \sp
\cs_set_eq:NN \spb@math@sub@save \sb
\box_new:N \l__super_i_box
\box_new:N \l__sub_i_box
\box_new:N \l__super_ii_box
\box_new:N \l__sub_ii_box
\cs_new:Npn \spb_math_print_store_i:nn #1#2
  {
    \hbox_set:cn { l__#1_i_box }
      {
        \ensuremath
          {
            \use:c { spb@math@#1@save }
              { \tl_use:c { l__spb_#1_cmd_i_tl }{#2} }
          }
      }
  }
\cs_new:Npn \spb_text_print_store_i:nn #1#2
  {
    \hbox_set:cn { l__#1_i_box }
      {
        \use:c { spb@text#1script@save }
          { \tl_use:c { l__spb_#1_cmd_i_tl }{#2} }
      }
  }
\cs_new:Npn \spb_math_print_store_ii:nn #1#2
  {
    \hbox_set:Nn \l__super_ii_box
      { \ensuremath{\spb@math@super@save{\l__spb_super_cmd_ii_tl{#1}}} }
    \hbox_set:Nn \l__sub_ii_box
      { \ensuremath{\spb@math@sub@save{\l__spb_sub_cmd_ii_tl{#2}}} }
  }
\cs_new:Npn \spb_text_print_store_ii:nn #1#2
  {
    \hbox_set:Nn \l__super_ii_box
      { \spb@textsuperscript@save{\l__spb_super_cmd_ii_tl{#1}} }
    \hbox_set:Nn \l__sub_ii_box
      { \spb@textsubscript@save{\l__spb_sub_cmd_ii_tl{#2}} }
  }
\cs_set_eq:NN \spbifmath \use_ii:nn
\cs_new:Npn \spb@ifmathtrue { \cs_set_eq:NN \spbifmath \use_i:nn }
\cs_new:Npn \spb@ifmathfalse { \cs_set_eq:NN \spbifmath \use_ii:nn }
\cs_new_protected:Npn \spb_mode_switch:nnn #1#2#3
  {
    \str_case:Vn \l__spb_mode_value_tl
      {
        { math }
        {
          \spb@ifmathtrue
          \use:c { spb_math_print_store_#3:nn } {#1} {#2}
        }
        { text }
        {
          \spb@ifmathfalse
          \use:c { spb_text_print_store_#3:nn } {#1} {#2}
        }
        { match }
        {
          \mode_if_math:TF
            {
              \spb@ifmathtrue
              \use:c { spb_math_print_store_#3:nn } {#1} {#2}
            }
            {
              \spb@ifmathfalse
              \use:c { spb_text_print_store_#3:nn } {#1} {#2}
            }
        }
      }
   }
\tl_set:Nn \l__spb_box_super_wd_i_tl { \box_wd:N \l__super_i_box }
\tl_set:Nn \l__spb_box_sub_wd_i_tl { \box_wd:N \l__sub_i_box }
\tl_set:Nn \l__spb_box_super_wd_ii_tl { \box_wd:N \l__super_ii_box }
\tl_set:Nn \l__spb_box_sub_wd_ii_tl { \box_wd:N \l__sub_ii_box }
\tl_set:Nn \l__spb_box_max_wd_tl
  { \dim_max:VV \l__spb_box_super_wd_ii_tl \l__spb_box_sub_wd_ii_tl }
\providecommand{\hbox_overlap_center:n}[1]
  { \hbox_to_zero:n { \hss #1\hss } }
\cs_new:Npn \spb_box_super_move_i_up:n #1
  { \box_move_up:nn {#1} { \box_use:N \l__super_i_box } }
\cs_new:Npn \spb_box_sub_move_i_down:n #1
  { \box_move_down:nn {#1} { \box_use:N \l__sub_i_box } }
\cs_new:Npn \spb_box_super_move_ii_up:n #1
  { \box_move_up:nn {#1} { \box_use:N \l__super_ii_box } }
\cs_new:Npn \spb_box_sub_move_ii_down:n #1
  { \box_move_down:nn {#1} { \box_use:N \l__sub_ii_box } }
\cs_new:Npn \spb_box_vmove:nn #1
  {
    \str_case:nn {#1}
      {
        { super } { \spb_box_super_move_i_up:n }
        { sub } { \spb_box_sub_move_i_down:n }
      }
  }
\cs_generate_variant:Nn \spb_box_super_move_ii_up:n { V }
\cs_generate_variant:Nn \spb_box_sub_move_ii_down:n { V }
\dim_new:N \l__spb_supersub_half_vsep_tl
\cs_new:Npn \spb_hbox_overlap_vmove:n #1
  {
    \tl_set:Nn \l__spb_supersub_half_vsep_tl
      { \l__spb_supersub_vsep_tl/2 }
    \use:c { hbox_overlap_#1:n }
      { \spb_box_super_move_ii_up:V \l__spb_supersub_half_vsep_tl }
    \use:c { hbox_overlap_#1:n }
      { \spb_box_sub_move_ii_down:V \l__spb_supersub_half_vsep_tl }
  }
\NewDocumentCommand{\spb@both@cmd@assign}
  {t+>{\SplitArgument{1}{,}}m}
  {
    \IfBooleanTF{#1}
      {\spb_supersub_both_addto_cmd:nn #2}
      {\spb_supersub_both_cmd:nn #2}
  }
\cs_new_protected:Npn \spb_supersub_both_cmd:nn #1#2
  {
    \tl_set:Nn \l__spb_super_cmd_ii_tl {#1}
    \tl_if_novalue:nTF {#2}
      { \tl_clear:N \l__spb_sub_cmd_ii_tl }
      { \tl_set:Nn \l__spb_sub_cmd_ii_tl {#2} }
  }
\cs_new_protected:Npn \spb_supersub_both_addto_cmd:nn #1#2
  {
    \tl_put_right:Nn \l__spb_super_cmd_ii_tl {#1}
    \tl_if_novalue:nF {#2} { \tl_put_right:Nn \l__spb_sub_cmd_ii_tl {#2} }
  }
\cs_new_protected:Npn \spb_ht_dp_assign:nnn #1#2#3
  {
    \tl_if_empty:cF { l__#1_height_#3_tl }
      { \box_set_ht:cv { l__#1_#3_box } { l__#1_height_#3_tl } }
    \tl_if_empty:cF { l__#1_depth_i_tl }
      { \box_set_dp:cv { l__#2_#3_box } { l__#2_depth_#3_tl } }
  }

\cs_new_protected:Npn \spb_both_newcmd_map:n #1
  {
    \exp_args:Nc \NewDocumentCommand {#1}{O{}mO{}}
      {
        \group_begin:
        \tl_gset:Nn \g__spb_mark_case_init_tl {#1}
        \keys_set:nn { ctex/style } {##1,##3}
        \spb_mode_switch:nnn {#1} {##2} { i }
        \spb_content_hbox_set:n {#1}
        \spb_ht_dp_assign:nnn {#1} {#1} { i }
        \box_use:c { l__#1_i_box }
        \group_end:
      }
  }
\cs_new_protected:Npn \spb_content_hbox_set:n #1
  {
    \hbox_set:cn { l__#1_i_box }
      {
        \dim_compare:nNnTF { \tl_use:c { l__spb_#1_hmove_tl } } < { 0pt }
          {
            \hbox_overlap_left:n
              {
                \hbox_overlap_right:n
                  { \spb_box_vmove:nn {#1} { \tl_use:c { l__spb_#1_vmove_tl } } }
                \skip_horizontal:n { -\tl_use:c { l__spb_#1_hmove_tl } }
              }
          }
          {
            \hbox_to_wd:nn
              { \tl_use:c { l__spb_box_#1_wd_i_tl } + \tl_use:c { l__spb_#1_hmove_tl } }
              { \hss\spb_box_vmove:nn {#1} { \tl_use:c { l__spb_#1_vmove_tl } } }
          }
      }
  }
\clist_map_inline:nn { super,sub } { \spb_both_newcmd_map:n {#1} }

\cs_new:Npn \spb_supersub_hmove_if_negative:TF #1#2
  { \dim_compare:VNnTF \l__spb_supersub_hmove_tl < { 0pt } {#1} {#2} }
\NewDocumentCommand{\supersub}{O{}mmO{}}
  {
    \group_begin:
    \tl_gset:Nn \g__spb_mark_case_init_tl { supersub }
    \keys_set:nn { ctex/style } {#1,#4}
    \spb_mode_switch:nnn {#2} {#3} { ii }
    \spb_ht_dp_assign:nnn { super } { sub } { ii }
    \str_case:VnF \l__spb_supersub_halign_tl
      {
        { l } { \use_i:nnn }
        { c } { \use_ii:nnn }
        { r } { \use_iii:nnn }
      }
      {
        \msg_warning:nn { spbmark } { unsupported-align }
        \use_i:nnn
      }
      {
        \spb_supersub_hmove_if_negative:TF
          {
            \hbox_overlap_left:n
              {
                \spb_hbox_overlap_vmove:n { right }
                \skip_horizontal:n { -\l__spb_supersub_hmove_tl }
              }
          }
          {
            \hbox:n
              {
                \skip_horizontal:n { \l__spb_supersub_hmove_tl }
                \spb_hbox_overlap_vmove:n { right } 
                \skip_horizontal:n { \l__spb_box_max_wd_tl }
              }
          }
      }
      {
        \spb_supersub_hmove_if_negative:TF
          {
            \hbox_overlap_left:n
              {
                \spb_hbox_overlap_vmove:n { center }
                \skip_horizontal:n { -\l__spb_supersub_hmove_tl - \l__spb_box_max_wd_tl/2 }
              }
          }
          {
            \hbox:n
              {
                \skip_horizontal:n { \l__spb_box_max_wd_tl/2 + \l__spb_supersub_hmove_tl }
                \spb_hbox_overlap_vmove:n { center } 
                \skip_horizontal:n { \l__spb_box_max_wd_tl/2 }
              }
          }
      }
      {
        \spb_supersub_hmove_if_negative:TF
          {
            \hbox_overlap_left:n
              {
                \spb_hbox_overlap_vmove:n { left }
                \skip_horizontal:n { -\l__spb_supersub_hmove_tl - \l__spb_box_max_wd_tl }
              }
          }
          {
            \hbox:n
              {
                \skip_horizontal:n { \l__spb_box_max_wd_tl + \l__spb_supersub_hmove_tl }
                \spb_hbox_overlap_vmove:n { left } 
              }
          }
      }
    \group_end:
  }
\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_newsupb_text_bool
  {
    \cs_set_eq:NN \textsuperscript \super
    \cs_set_eq:NN \textsubscript \sub
  }
\bool_if:NT \l_spb_newsupb_math_bool
  {
    \cs_set_eq:NN \sp \super
    \cs_set_eq:NN \sb \sub
  }
\bool_if:NT \l_spb_newsupb_foot_bool
  {
    \cs_set:Npn \@makefnmark
      { \hbox:n { \fnmarkfont{\super{\@thefnmark}} } }
  }
\cs_set_eq:NN \spb \supersub
\tl_if_exist:NTF \ftntm@font
  { \tl_set_eq:NN \fnmarkfont \ftntm@font }
  { \tl_set_eq:NN \fnmarkfont \normalfont }
\endinput
%
% End of file `spbmark.sty'.