@@ -2035,6 +2035,7 @@ def __init__(self):
2035
2035
p .non_math = Forward ()
2036
2036
p .operatorname = Forward ()
2037
2037
p .overline = Forward ()
2038
+ p .overset = Forward ()
2038
2039
p .placeable = Forward ()
2039
2040
p .rbrace = Forward ()
2040
2041
p .rbracket = Forward ()
@@ -2053,6 +2054,7 @@ def __init__(self):
2053
2054
p .symbol = Forward ()
2054
2055
p .symbol_name = Forward ()
2055
2056
p .token = Forward ()
2057
+ p .underset = Forward ()
2056
2058
p .unknown_symbol = Forward ()
2057
2059
2058
2060
# Set names on everything -- very useful for debugging
@@ -2169,6 +2171,18 @@ def __init__(self):
2169
2171
- (p .required_group | Error ("Expected \\ overline{value}" ))
2170
2172
)
2171
2173
2174
+ p .overset <<= Group (
2175
+ Suppress (Literal (r"\overset" ))
2176
+ - ((p .simple_group + p .simple_group )
2177
+ | Error ("Expected \\ overset{body}{annotation}" ))
2178
+ )
2179
+
2180
+ p .underset <<= Group (
2181
+ Suppress (Literal (r"\underset" ))
2182
+ - ((p .simple_group + p .simple_group )
2183
+ | Error ("Expected \\ underset{body}{annotation}" ))
2184
+ )
2185
+
2172
2186
p .unknown_symbol <<= Combine (p .bslash + Regex ("[A-Za-z]*" ))
2173
2187
2174
2188
p .operatorname <<= Group (
@@ -2190,6 +2204,8 @@ def __init__(self):
2190
2204
| p .dfrac
2191
2205
| p .binom
2192
2206
| p .genfrac
2207
+ | p .overset
2208
+ | p .underset
2193
2209
| p .sqrt
2194
2210
| p .overline
2195
2211
| p .operatorname
@@ -2842,6 +2858,38 @@ def binom(self, s, loc, toks):
2842
2858
return self ._genfrac ('(' , ')' , 0.0 , self ._MathStyle .TEXTSTYLE ,
2843
2859
num , den )
2844
2860
2861
+ def _genset (self , state , body , annotation , overunder ):
2862
+ thickness = state .font_output .get_underline_thickness (
2863
+ state .font , state .fontsize , state .dpi )
2864
+
2865
+ body .shrink ()
2866
+
2867
+ cbody = HCentered ([body ])
2868
+ cannotation = HCentered ([annotation ])
2869
+ width = max (cbody .width , cannotation .width )
2870
+ cbody .hpack (width , 'exactly' )
2871
+ cannotation .hpack (width , 'exactly' )
2872
+
2873
+ vgap = thickness * 3
2874
+ if overunder == "under" :
2875
+ vlist = Vlist ([cannotation , # annotation
2876
+ Vbox (0 , vgap ), # space
2877
+ cbody # body
2878
+ ])
2879
+ # Shift so the annotation sits in the same vertical position
2880
+ shift_amount = cannotation .depth + cbody .height + vgap
2881
+
2882
+ vlist .shift_amount = shift_amount
2883
+ else :
2884
+ vlist = Vlist ([cbody , # body
2885
+ Vbox (0 , vgap ), # space
2886
+ cannotation # annotation
2887
+ ])
2888
+
2889
+ # To add horizontal gap between symbols: wrap the Vlist into
2890
+ # an Hlist and extend it with an Hbox(0, horizontal_gap)
2891
+ return vlist
2892
+
2845
2893
def sqrt (self , s , loc , toks ):
2846
2894
(root , body ), = toks
2847
2895
state = self .get_state ()
@@ -2902,6 +2950,24 @@ def overline(self, s, loc, toks):
2902
2950
hlist = Hlist ([rightside ])
2903
2951
return [hlist ]
2904
2952
2953
+ def overset (self , s , loc , toks ):
2954
+ assert len (toks ) == 1
2955
+ assert len (toks [0 ]) == 2
2956
+
2957
+ state = self .get_state ()
2958
+ body , annotation = toks [0 ]
2959
+
2960
+ return self ._genset (state , body , annotation , overunder = "over" )
2961
+
2962
+ def underset (self , s , loc , toks ):
2963
+ assert len (toks ) == 1
2964
+ assert len (toks [0 ]) == 2
2965
+
2966
+ state = self .get_state ()
2967
+ body , annotation = toks [0 ]
2968
+
2969
+ return self ._genset (state , body , annotation , overunder = "under" )
2970
+
2905
2971
def _auto_sized_delimiter (self , front , middle , back ):
2906
2972
state = self .get_state ()
2907
2973
if len (middle ):
0 commit comments