diff --git a/lib/LaTeXML/Common/Font.pm b/lib/LaTeXML/Common/Font.pm index 5a0de3410..f9f907287 100644 --- a/lib/LaTeXML/Common/Font.pm +++ b/lib/LaTeXML/Common/Font.pm @@ -22,7 +22,7 @@ use LaTeXML::Common::Font::Metric; use LaTeXML::Common::Font::StandardMetrics; use LaTeXML::Common::Color; use List::Util qw(min max sum); -use base qw(LaTeXML::Common::Object); +use base qw(LaTeXML::Common::Object); # Note that this has evolved way beynond just "font", # but covers text properties (or even display properties) in general @@ -62,7 +62,7 @@ my $FLAG_EMPH = 0x10; my %font_family = ( cmr => { family => 'serif' }, cmss => { family => 'sansserif' }, cmtt => { family => 'typewriter' }, cmvtt => { family => 'typewriter' }, - cmti => { family => 'typewriter', shape => 'italic' }, + cmt => { family => 'serif' }, # for cmti "text italic" cmfib => { family => 'serif' }, cmfr => { family => 'serif' }, cmdh => { family => 'serif' }, cm => { family => 'serif' }, ptm => { family => 'serif' }, ppl => { family => 'serif' }, diff --git a/lib/LaTeXML/Core/Document.pm b/lib/LaTeXML/Core/Document.pm index 7c0208785..63b1569be 100644 --- a/lib/LaTeXML/Core/Document.pm +++ b/lib/LaTeXML/Core/Document.pm @@ -21,7 +21,7 @@ use LaTeXML::Common::XML; use LaTeXML::Util::Radix; use Unicode::Normalize; use Scalar::Util qw(blessed); -use base qw(LaTeXML::Common::Object); +use base qw(LaTeXML::Common::Object); #********************************************************************** # These two element names are `leaks' of the document structure into @@ -771,7 +771,7 @@ sub openText { $n = $n->parentNode; } closeToNode($self, $closeto) if $closeto ne $node; # Move to best starting point for this text. openElement($self, $elementname, font => $font, - _fontswitch => 1, _autoopened => 1) + _fontswitch => 1, _autoopened => 1, _autoclose => 1) if $bestdiff > 0; # Open if needed. } # Finally, insert the darned text. diff --git a/lib/LaTeXML/Core/State.pm b/lib/LaTeXML/Core/State.pm index 20d6fcf98..7dbf31c6d 100644 --- a/lib/LaTeXML/Core/State.pm +++ b/lib/LaTeXML/Core/State.pm @@ -123,6 +123,17 @@ sub new { $$self{uccode} = {}; $$self{delcode} = {}; $$self{tracing_definitions} = {}; + # Initializations that INITEX would have set. + $$self{mathcode}{'.'} = [0]; + for (my $c = ord('0') ; $c <= ord('9') ; $c++) { + $$self{mathcode}{ chr($c) } = [0x7000]; } + for (my $c = ord('a') ; $c <= ord('z') ; $c++) { + my $C = $c + ord('A') - ord('a'); + $$self{mathcode}{ chr($c) } = [0x7100]; + $$self{mathcode}{ chr($C) } = [0x7100]; + $$self{uccode}{ chr($c) } = [$C]; + $$self{lccode}{ chr($C) } = [$c]; + $$self{sfcode}{ chr($C) } = [999]; } return $self; } sub assign_internal { diff --git a/lib/LaTeXML/Engine/Base_ParameterTypes.pool.ltxml b/lib/LaTeXML/Engine/Base_ParameterTypes.pool.ltxml index 764bc8c6f..d9ba052a5 100644 --- a/lib/LaTeXML/Engine/Base_ParameterTypes.pool.ltxml +++ b/lib/LaTeXML/Engine/Base_ParameterTypes.pool.ltxml @@ -68,9 +68,13 @@ DefParameterType('Optional', sub { DefParameterType('GeneralText', sub { my ($gullet) = @_; $gullet->unread($gullet->readXToken); # Force expansion to skip before required { - return $gullet->readBalanced(0, 0, 1); }); +DefParameterType('XGeneralText', sub { + my ($gullet) = @_; + $gullet->unread($gullet->readXToken); # Force expansion to skip before required { + return $gullet->readBalanced(1, 0, 1); }); + DefParameterType('Until', sub { my ($gullet, $until) = @_; $gullet->readUntil($until); }, @@ -371,26 +375,36 @@ DefParameterType('BalancedParen', sub { # It is useful when the content would usually need to have been \protect'd # in order to correctly deal with catcodes. # BEWARE: This is NOT a shorthand for a simple digested {}! -DefParameterType('Digested', sub { - no warnings 'recursion'; - my ($gullet) = @_; - $gullet->skipSpaces; - my $ismath = $STATE->lookupValue('IN_MATH'); - my @list = (); - my $token; - do { $token = $gullet->readXToken(0); - } while (defined $token && (($token->getCatcode == CC_SPACE) || $token->equals(T_CS('\relax')))); - if (!defined $token) { } - elsif ($token->getCatcode == CC_BEGIN) { - Digest($token); - push(@list, $STATE->getStomach->digestNextBody()); pop(@list); } # content w/o the braces - else { - push(@list, $STATE->getStomach->invokeToken($token)); } - @list = grep { ref $_ ne 'LaTeXML::Core::Comment' } @list; - List(@list, mode => ($ismath ? 'math' : 'text')); }, +sub readDigested { + no warnings 'recursion'; + my ($gullet) = @_; + $gullet->skipSpaces; + my $ismath = $STATE->lookupValue('IN_MATH'); + my @list = (); + my $token; + do { $token = $gullet->readXToken(0); + } while (defined $token && (($token->getCatcode == CC_SPACE) || $token->equals(T_CS('\relax')))); + if (!defined $token) { } + elsif ($token->getCatcode == CC_BEGIN) { + Digest($token); + push(@list, $STATE->getStomach->digestNextBody()); pop(@list); } # content w/o the braces + else { + push(@list, $STATE->getStomach->invokeToken($token)); } + @list = grep { ref $_ ne 'LaTeXML::Core::Comment' } @list; + return List(@list, mode => ($ismath ? 'math' : 'text')); } + +DefParameterType('Digested', \&readDigested, undigested => 1, # since _already_ digested. reversion => sub { (T_BEGIN, Revert($_[0]), T_END); }); +# Read a Delimiter; +# Formally a delimiter is either a token, or \delimiter or maybe \radical, +# but we don't actually restrict to those. +# Here, we just read a single Digested thing, but reversion gets no braces +DefParameterType('TeXDelimiter', \&readDigested, + undigested => 1, # since _already_ digested. + reversion => sub { Revert($_[0]); }); + # A variation: Digest until we encounter a given token! DefParameterType('DigestUntil', sub { my ($gullet, $until) = @_; diff --git a/lib/LaTeXML/Engine/TeX_FileIO.pool.ltxml b/lib/LaTeXML/Engine/TeX_FileIO.pool.ltxml index d910db78b..16dfe03e0 100644 --- a/lib/LaTeXML/Engine/TeX_FileIO.pool.ltxml +++ b/lib/LaTeXML/Engine/TeX_FileIO.pool.ltxml @@ -106,18 +106,23 @@ DefPrimitive('\openout Number SkipSpaces SkipMatch:= SkipSpaces TeXFileName', su DefPrimitive('\closeout Number', sub { my ($stomach, $port) = @_; $port = ToString($port); + if ($LaTeXML::DEBUG{write}) { + if (my $filename = LookupValue('output_file:' . $port)) { + my $handle = $filename . '_contents'; + my $contents = LookupValue($handle); + Debug("CLOSING $filename with content:\n$contents\n============================="); } } AssignValue('output_file:' . $port => undef, 'global'); return; }); -DefPrimitive('\write Number {}', sub { +DefPrimitive('\write Number XGeneralText', sub { my ($stomach, $port, $tokens) = @_; $port = ToString($port); if (my $filename = LookupValue('output_file:' . $port)) { my $handle = $filename . '_contents'; my $contents = LookupValue($handle); - AssignValue($handle => $contents . UnTeX(Expand($tokens), 1) . "\n", 'global'); } + AssignValue($handle => $contents . UnTeX($tokens, 1) . "\n", 'global'); } else { - Note(UnTeX(Expand($tokens))); } + Note(UnTeX($tokens)); } return; }); # Since we don't paginate, we're effectively always "shipping out", @@ -145,7 +150,7 @@ DefMacro('\input TeXFileName', sub { #---------------------------------------------------------------------- # \special c sends material to the dvi file for special processing. -DefPrimitive('\special {}', sub { +DefPrimitive('\special XGeneralText', sub { my ($stomach, $arg) = @_; my $special_str = ToString($arg); # recognize one special graphics inclusion case @@ -161,7 +166,7 @@ DefPrimitive('\special {}', sub { $stomach->getGullet->unread( T_CS('\ltx@special@graphics'), @kv, T_BEGIN, T_OTHER($graphic), T_END); } else { - Info('ignored', 'special', $stomach, 'Unrecognized TeX Special', $arg); } + Info('ignored', 'special', $stomach, 'Unrecognized TeX Special' . ToString($arg)); } return; }); # adapted from graphicx.sty.ltxml diff --git a/lib/LaTeXML/Engine/TeX_Math.pool.ltxml b/lib/LaTeXML/Engine/TeX_Math.pool.ltxml index eeb255442..a9225a3d4 100644 --- a/lib/LaTeXML/Engine/TeX_Math.pool.ltxml +++ b/lib/LaTeXML/Engine/TeX_Math.pool.ltxml @@ -30,6 +30,9 @@ use LaTeXML::Package; # \muskip iq assigns to a \muskip register. # \nonscript c ignores immediately following glue or kern in script and scriptscript styles. +# This should discard following skip/glue; +# Should this digest whatever is following tountil non-glue/kern???? +DefPrimitive('\nonscript', undef); #====================================================================== # The next two sections are the basic LaTeXML Infrastructure for math. # There are several internal control sequences which need to be renamed! @@ -347,6 +350,12 @@ sub IsScript { return [uc($1), uc($2)]; } return; } +sub doScriptpos { + return (LookupValue('font')->getMathstyle eq 'display' ? 'mid' : 'post'); } + +sub doVariablesizeOp { + return (LookupValue('font')->getMathstyle eq 'display' ? 'display' : 'text'); } + sub scriptHandler { no warnings 'recursion'; my ($stomach, $op) = @_; @@ -568,14 +577,14 @@ sub decodeMathChar { my $font = LookupValue('textfont_' . $fam) || LookupValue('scriptfont_' . $fam) || LookupValue('scriptscriptfont_' . $fam); - my $char = chr($n); - # If no specific class, Lookup properties from a DefMath? - my $charinfo = LookupValue('math_token_attributes_' . $char); - my $fontinfo = lookupFontinfo($font); + my $char = chr($n); + my $fontinfo = lookupFontinfo($font); # Map char(code) to Unicode, via font + my $glyph = ($fontinfo && $$fontinfo{encoding} && FontDecode($n, $$fontinfo{encoding}) // $char); + # If no specific class, Lookup properties from a DefMath? [Or better yet, Unicode data?] + my $charinfo = LookupValue('math_token_attributes_' . $glyph); my $role = $mathclassrole[$class]; $role = $$charinfo{role} if (!defined $role) && $charinfo; - return ($role, - ($fontinfo && $$fontinfo{encoding} ? FontDecode($n, $$fontinfo{encoding}) : $char)); } + return ($role, $glyph); } DefPrimitive('\mathchar Number', sub { my ($stomach, $code) = @_; @@ -627,12 +636,23 @@ DefRegister('\mathcode Number', Number(0), Number(defined $code ? $code : $ch); }, # defaults to the char's code itself(?) setter => sub { $STATE->assignMathcode(chr($_[2]->valueOf) => $_[0]->valueOf, $_[1]); }); # Not used anywhere (yet) -DefRegister('\delcode Number', Number(0), +DefRegister('\delcode Number', Number(-1), getter => sub { my $code = $STATE->lookupDelcode(chr($_[0]->valueOf)); - Number(defined $code ? $code : 0); }, + Number(defined $code ? $code : -1); }, setter => sub { $STATE->assignDelcode(chr($_[2]->valueOf) => $_[0]->valueOf, $_[1]); }); -DefRegister('\fam' => Number(-1)); +# This probably needs work; +# Assigning should choose the font specified by \textfont,\scriptfont... +# but it should be initialized to -1 at beginning of every math! +DefRegister('\fam' => Number(-1), + getter => sub { + $STATE->lookupValue('fontfamily'); }, + setter => sub { + my ($fam, $scope) = @_; + $STATE->assignValue('fontfamily' => $fam->valueOf, $scope); + if (my $font = $STATE->lookupValue('textfont_' . $fam->valueOf)) { + Digest($font); # Digest, since this is a font COMMAND (\font)!!!!! +} }); #====================================================================== # TeX-level grammatical roles @@ -652,15 +672,17 @@ DefRegister('\fam' => Number(-1)); # We need a finer granularity than TeX does: an ORD could be several things, # a BIN could be a MULOP or ADDOP. # AND, rarely, they're empty.... Is it wrong to drop them? -DefConstructor('\mathord{}', "?#1(#1)()", bounded => 1); -DefConstructor('\mathop{}', "?#1(#1)()", +DefConstructor('\mathord Digested', "?#1(#1)()", bounded => 1); +# Parameter Should be Digested, but that throws off doScriptPos's position depth !?!?! +DefConstructor('\mathop {}', "?#1(#1)()", bounded => 1, properties => { scriptpos => \&doScriptpos }); -DefConstructor('\mathbin{}', "?#1(#1)()", bounded => 1); -DefConstructor('\mathrel{}', "?#1(#1)()", bounded => 1); -DefConstructor('\mathopen{}', "?#1(#1)()", bounded => 1); -DefConstructor('\mathclose{}', "?#1(#1)()", bounded => 1); -DefConstructor('\mathpunct{}', "?#1(#1)()", bounded => 1); -DefConstructor('\mathinner{}', "?#1(#1)()", bounded => 1); + +DefConstructor('\mathbin Digested', "?#1(#1)()", bounded => 1); +DefConstructor('\mathrel Digested', "?#1(#1)()", bounded => 1); +DefConstructor('\mathopen Digested', "?#1(#1)()", bounded => 1); +DefConstructor('\mathclose Digested', "?#1(#1)()", bounded => 1); +DefConstructor('\mathpunct Digested', "?#1(#1)()", bounded => 1); +DefConstructor('\mathinner Digested', "?#1(#1)()", bounded => 1); #====================================================================== # Delimiters @@ -670,53 +692,67 @@ DefConstructor('\mathinner{}', "?#1(#1)()", # This duplicates in slightly different way what DefMath has put together. # [duplication seems like a bad idea!] +# This should ultimately be part of some set of Unicode tables. our %DELIMITER_MAP = - ('(' => { char => "(", lrole => 'OPEN', rrole => 'CLOSE' }, - ')' => { char => ")", lrole => 'OPEN', rrole => 'CLOSE' }, - '[' => { char => "[", lrole => 'OPEN', rrole => 'CLOSE' }, - ']' => { char => "]", lrole => 'OPEN', rrole => 'CLOSE' }, - '\{' => { char => "{", lrole => 'OPEN', rrole => 'CLOSE' }, - '\}' => { char => "}", lrole => 'OPEN', rrole => 'CLOSE' }, - '\lfloor' => { char => "\x{230A}", lrole => 'OPEN', rrole => 'CLOSE', name => 'lfloor' }, - '\rfloor' => { char => "\x{230B}", lrole => 'OPEN', rrole => 'CLOSE', name => 'rfloor' }, - '\lceil' => { char => "\x{2308}", lrole => 'OPEN', rrole => 'CLOSE', name => 'lceil' }, - '\rceil' => { char => "\x{2309}", lrole => 'OPEN', rrole => 'CLOSE', name => 'rceil' }, - '\langle' => { char => "\x{27E8}", lrole => 'OPEN', rrole => 'CLOSE', name => 'langle' }, - '\rangle' => { char => "\x{27E9}", lrole => 'OPEN', rrole => 'CLOSE', name => 'rangle' }, - '<' => { char => "\x{27E8}", lrole => 'OPEN', rrole => 'CLOSE', name => 'langle' }, - '>' => { char => "\x{27E9}", lrole => 'OPEN', rrole => 'CLOSE', name => 'rangle' }, - '/' => { char => "/", lrole => 'MULOP', rrole => 'MULOP' }, - '\backslash' => { char => UTF(0x5C), lrole => 'MULOP', rrole => 'MULOP', name => 'backslash' }, - '|' => { char => "|", lrole => 'VERTBAR', rrole => 'VERTBAR' }, - '\|' => { char => "\x{2225}", lrole => 'VERTBAR', rrole => 'VERTBAR' }, - '\uparrow' => { char => "\x{2191}", lrole => 'OPEN', rrole => 'CLOSE', name => 'uparrow' }, # ?? - '\Uparrow' => { char => "\x{21D1}", lrole => 'OPEN', rrole => 'CLOSE', name => 'Uparrow' }, # ?? - '\downarrow' => { char => "\x{2193}", lrole => 'OPEN', rrole => 'CLOSE', name => 'downarrow' }, # ?? - '\Downarrow' => { char => "\x{21D3}", lrole => 'OPEN', rrole => 'CLOSE', name => 'Downarrow' }, # ?? - '\updownarrow' => { char => "\x{2195}", lrole => 'OPEN', rrole => 'CLOSE', name => 'updownarrow' }, # ?? - '\Updownarrow' => { char => "\x{21D5}", lrole => 'OPEN', rrole => 'CLOSE', name => 'Updownarrow' }, # ?? + ('(' => { lrole => 'OPEN', rrole => 'CLOSE' }, + ')' => { lrole => 'OPEN', rrole => 'CLOSE' }, + '[' => { lrole => 'OPEN', rrole => 'CLOSE' }, + ']' => { lrole => 'OPEN', rrole => 'CLOSE' }, + '{' => { lrole => 'OPEN', rrole => 'CLOSE' }, + '}' => { lrole => 'OPEN', rrole => 'CLOSE' }, + "\x{230A}" => { lrole => 'OPEN', rrole => 'CLOSE', name => 'lfloor' }, + "\x{230B}" => { lrole => 'OPEN', rrole => 'CLOSE', name => 'rfloor' }, + "\x{2308}" => { lrole => 'OPEN', rrole => 'CLOSE', name => 'lceil' }, + "\x{2309}" => { lrole => 'OPEN', rrole => 'CLOSE', name => 'rceil' }, + "\x{27E8}" => { lrole => 'OPEN', rrole => 'CLOSE', name => 'langle' }, + "\x{27E9}" => { lrole => 'OPEN', rrole => 'CLOSE', name => 'rangle' }, + '<' => { lrole => 'OPEN', rrole => 'CLOSE', name => 'langle', + char => "\x{27E8}", meaning => undef }, + '>' => { lrole => 'OPEN', rrole => 'CLOSE', name => 'rangle', + char => "\x{27E9}", meaning => undef }, + '/' => { lrole => 'MULOP', rrole => 'MULOP' }, + UTF(0x5C) => { lrole => 'MULOP', rrole => 'MULOP', name => 'backslash' }, + '|' => { lrole => 'VERTBAR', rrole => 'VERTBAR' }, + "\x{2225}" => { lrole => 'VERTBAR', rrole => 'VERTBAR' }, + "\x{2191}" => { lrole => 'OPEN', rrole => 'CLOSE', name => 'uparrow' }, # ?? + "\x{21D1}" => { lrole => 'OPEN', rrole => 'CLOSE', name => 'Uparrow' }, # ?? + "\x{2193}" => { lrole => 'OPEN', rrole => 'CLOSE', name => 'downarrow' }, # ?? + "\x{21D3}" => { lrole => 'OPEN', rrole => 'CLOSE', name => 'Downarrow' }, # ?? + "\x{2195}" => { lrole => 'OPEN', rrole => 'CLOSE', name => 'updownarrow' }, # ?? + "\x{21D5}" => { lrole => 'OPEN', rrole => 'CLOSE', name => 'Updownarrow' }, # ?? ); -# With new treatment of Simple Symbols as just Box's with assigned attributes, -# we're not getting whatsits, and so we're not looking them up the same way!!! -# TEMPORARILY (?) hack the Delimiter map -foreach my $entry (values %DELIMITER_MAP) { - $DELIMITER_MAP{ $$entry{char} } = $entry; } +# The \lx@left, \lx@right versions are like \left,\right but without any extra grouping +DefConstructor('\lx@left TeXDelimiter', + "?#hint()(#1)", + afterDigest => sub { my ($stomach, $whatsit) = @_; + $whatsit->setProperty(hint => 1) if ToString($whatsit->getArg(1)) eq '.'; + return; }, + afterConstruct => sub { augmentDelimiterProperties($_[0], $_[1], 'OPEN'); }, + alias => '\left'); -sub lookup_delimiter { - my ($delim) = @_; - return $DELIMITER_MAP{$delim}; } +DefConstructor('\lx@right TeXDelimiter', + "?#hint()(#1)", + afterDigest => sub { my ($stomach, $whatsit) = @_; + $whatsit->setProperty(hint => 1) if ToString($whatsit->getArg(1)) eq '.'; + return; }, + afterConstruct => sub { augmentDelimiterProperties($_[0], $_[1], 'CLOSE'); }, + alias => '\right'); # This is a little messier than you'd think. -# These effectively create a group between the \left,\right. -# And this also gives us a single list of things to parse separately. -# Since \left,\right are TeX, primitives and must be paired up, -# we use a bit of macro trickery to simulate. -# [The \lx@hidden@bgroup/egroup keep from putting a {} into the UnTeX] -# HOWEVER, an additional complication is that it is a common mistake to omit the balancing \right! -# Using an \egroup (or hidden) makes it hard to recover, so use a special egroup -DefMacro('\left XToken', '\lx@left #1\lx@hidden@bgroup'); -# Like \lx@hidden@egroup, but softer about missing \left +# These effectively create a (boxing) group BETWEEN the \left,\right. (but should be hidden) +# But you have to digest \left's delimiter before you can start the {...} group! +DefConstructor('\left TeXDelimiter', + "?#hint()(#1)", + afterDigest => sub { my ($stomach, $whatsit) = @_; + $whatsit->setProperty(hint => 1) if ToString($whatsit->getArg(1)) eq '.'; + $stomach->getGullet->unread(T_CS('\lx@hidden@bgroup')); + return; }, + afterConstruct => sub { augmentDelimiterProperties($_[0], $_[1], 'OPEN'); }); + +DefMacro('\right', '\lx@hidden@egroup@right\lx@right'); + +# \lx@hidden@egroup@right tries to manage unbalanced {} errors, if an \left was forgotten. DefConstructor('\lx@hidden@egroup@right', '', afterDigest => sub { my ($stomach) = @_; @@ -727,50 +763,30 @@ DefConstructor('\lx@hidden@egroup@right', '', $stomach->egroup; } }, reversion => ''); -DefMacro('\right XToken', '\lx@hidden@egroup@right\lx@right #1'); - -DefConstructor('\lx@left Token', - "?#char(#char)" - . "(?#hint()(#1))", - afterDigest => sub { my ($stomach, $whatsit) = @_; - my $arg = $whatsit->getArg(1); - my $delim = ToString($arg); - if ($delim eq '.') { - $whatsit->setProperty(hint => 1); } - elsif (my $entry = $DELIMITER_MAP{$delim}) { - $whatsit->setProperties(role => $$entry{lrole}, - char => $$entry{char}, - name => $$entry{name}, - stretchy => 'true'); - $whatsit->setFont($arg->getFont()); } - elsif (($arg->getProperty('role') || '') eq 'OPEN') { - $arg->setProperty(stretchy => 'true'); } - else { - Warn('unexpected', $delim, $stomach, - "Missing delimiter; '.' inserted"); } - return; }, - alias => '\left'); -DefConstructor('\lx@right Token', - "?#char(#char)" - . "(?#hint()(#1))", - afterDigest => sub { my ($stomach, $whatsit) = @_; - my $arg = $whatsit->getArg(1); - my $delim = ToString($arg); - if ($delim eq '.') { - $whatsit->setProperty(hint => 1); } - elsif (my $entry = $DELIMITER_MAP{$delim}) { - $whatsit->setProperties(role => $$entry{rrole}, - char => $$entry{char}, - name => $$entry{name}, - stretchy => 'true'); - $whatsit->setFont($arg->getFont()); } - elsif (($arg->getProperty('role') || '') eq 'CLOSE') { - $arg->setProperty(stretchy => 'true'); } - else { - Warn('unexpected', $delim, $stomach, - "Missing delimiter; '.' inserted)"); } - return; }, - alias => '\right'); +# Add delimiter relevant attributes to the current token +sub augmentDelimiterProperties { + my ($document, $whatsit, $pos) = @_; + my $current = $document->getNode; + my $delim = $document->getLastChildElement($current) || $current; + my $char = $delim && $delim->textContent; + $document->setNodeBox($delim, $whatsit); + if ($whatsit->getProperty('hint')) { } + elsif (my $entry = $DELIMITER_MAP{$char}) { + $delim->setAttribute(role => $$entry{ ($pos eq 'OPEN' ? 'lrole' : 'rrole') } || $pos); + $delim->setAttribute(name => $$entry{name}) if $$entry{name}; + $delim->setAttribute(stretchy => 'true'); + if (exists $$entry{meaning}) { + if (my $meaning = $$entry{meaning}) { + $delim->setAttribute(meaning => $meaning); } + else { + $delim->removeAttribute('meaning'); } } # RETRACT the assumed meaning on the delimiter + if (exists $$entry{char}) { + if (my $char = $$entry{char}) { + $delim->firstChild->setData($char); } } + } + elsif (($delim->getAttribute('role') || '') eq $pos) { + $delim->setAttribute(stretchy => 'true'); } + return; } #====================================================================== # Limit placement @@ -1165,7 +1181,7 @@ DefMacroI('\eqno', undef, sub { || (ToString($t) =~ /^\\(?:begin|end)\{/) # any sort of environ begin or end??? # This seems needed within AmSTeX environs ) { - return (Invocation(T_CS('\lx@eqno'), Tokens(@stuff)), $t); } + return (Invocation(T_CS('\lx@eqno'), Tokens(@stuff, T_CS('\relax'))), $t); } else { push(@stuff, $t); } } Error('unexpected', '\eqno', $gullet, "Fell of the end reading tag for \\eqno!", diff --git a/lib/LaTeXML/Engine/plain.pool.ltxml b/lib/LaTeXML/Engine/plain.pool.ltxml index 36d413088..036ed3c92 100644 --- a/lib/LaTeXML/Engine/plain.pool.ltxml +++ b/lib/LaTeXML/Engine/plain.pool.ltxml @@ -20,13 +20,6 @@ use LaTeXML::Package; # Plain; Extracted from Appendix B. #********************************************************************** -# Remember, we're assigning a NUMBER (codepoint) to a CHARACTER! -foreach my $letter (ord('A') .. ord('Z')) { - $STATE->assignLCcode(chr($letter), $letter + 0x20, 'global'); - $STATE->assignUCcode(chr($letter), $letter, 'global'); - $STATE->assignLCcode(chr($letter + 0x20), $letter + 0x20, 'global'); - $STATE->assignUCcode(chr($letter + 0x20), $letter, 'global'); } - DefRegister('\magnification' => Number(1000)); Let('\bye', '\end'); @@ -818,6 +811,7 @@ DefMathI('\surd', undef, "\x{221A}", role => 'OPERATOR', meaning => 'square- DefMathI('\top', undef, "\x{22A4}", role => 'ADDOP', meaning => 'top'); DefMathI('\bot', undef, "\x{22A5}", role => 'ADDOP', meaning => 'bottom'); DefMathI('\|', undef, "\x{2225}", role => 'VERTBAR', name => '||'); + # should get meaning => 'parallel-to' when used as infix, but NOT when for OPEN|CLOSE DefMathI('\angle', undef, "\x{2220}"); @@ -867,12 +861,6 @@ DefMath('\smallint', "\x{222B}", meaning => 'integral', role => 'INTOP', #---------------------------------------------------------------------- # Actually LaTeX; Table 3.8. Variable-sized Symbols, p.44. #---------------------------------------------------------------------- -sub doScriptpos { - return (LookupValue('font')->getMathstyle eq 'display' ? 'mid' : 'post'); } - -sub doVariablesizeOp { - return (LookupValue('font')->getMathstyle eq 'display' ? 'display' : 'text'); } - DefMathI('\sum', undef, "\x{2211}", role => 'SUMOP', scriptpos => \&doScriptpos, diff --git a/lib/LaTeXML/Package.pm b/lib/LaTeXML/Package.pm index 61c16ef50..9146c7948 100644 --- a/lib/LaTeXML/Package.pm +++ b/lib/LaTeXML/Package.pm @@ -1523,8 +1523,8 @@ my $math_options = { # [CONSTANT] revert_as => 1, hide_content_reversion => 1 }; # DEPRECATE! my $simpletoken_options = { # [CONSTANT] - name => 1, meaning => 1, omcd => 1, role => 1, mathstyle => 1, - protected => 1, robust => 1, + name => 1, meaning => 1, omcd => 1, role => 1, mathstyle => 1, stretchy => 1, + protected => 1, robust => 1, alias => 1, lpadding => 1, rpadding => 1, font => 1, scriptpos => 1, scope => 1, locked => 1 }; @@ -1746,13 +1746,16 @@ sub defmath_prim { my %properties = %options; my $font = LookupValue('font')->merge(%$reqfont)->specialize($string); my $mode = (LookupValue('IN_MATH') ? 'math' : 'text'); + my $alias = (ref $options{alias} ? $options{alias} + : (defined $options{alias} ? T_CS($options{alias}) : undef)); + my $reversion = + ((!defined $options{reversion}) && (($options{revert_as} || '') eq 'presentation') + ? $presentation : $alias // $cs); foreach my $key (keys %properties) { my $value = $properties{$key}; if (ref $value eq 'CODE') { $properties{$key} = &$value(); } } - LaTeXML::Core::Box->new($string, $font, $locator, - ((!defined $options{reversion}) && (($options{revert_as} || '') eq 'presentation') - ? $presentation : $cs), + LaTeXML::Core::Box->new($string, $font, $locator, $reversion, mode => $mode, %properties); })); return; } diff --git a/t/ams/mathtools.xml b/t/ams/mathtools.xml index 684f685bf..7173f2336 100644 --- a/t/ams/mathtools.xml +++ b/t/ams/mathtools.xml @@ -1865,7 +1865,7 @@ Then a switch of tag forms.

- + @@ -1904,7 +1904,7 @@ Then a switch of tag forms.

- +
@@ -2070,7 +2070,7 @@ Then a switch of tag forms.

- + @@ -2095,7 +2095,7 @@ Then a switch of tag forms.

- +
@@ -2107,7 +2107,7 @@ Then a switch of tag forms.

- + @@ -2132,7 +2132,7 @@ Then a switch of tag forms.

- +
@@ -2248,7 +2248,7 @@ Then a switch of tag forms.

- + @@ -2280,7 +2280,7 @@ Then a switch of tag forms.

- +
@@ -2292,7 +2292,7 @@ Then a switch of tag forms.

- + @@ -2324,7 +2324,7 @@ Then a switch of tag forms.

- +
@@ -2440,7 +2440,7 @@ Then a switch of tag forms.

- + @@ -2472,7 +2472,7 @@ Then a switch of tag forms.

- +
@@ -2484,7 +2484,7 @@ Then a switch of tag forms.

- + @@ -2516,7 +2516,7 @@ Then a switch of tag forms.

- +
diff --git a/t/ams/matrix.xml b/t/ams/matrix.xml index 4dca4cc3e..4a1389be8 100644 --- a/t/ams/matrix.xml +++ b/t/ams/matrix.xml @@ -172,7 +172,7 @@ - + @@ -188,7 +188,7 @@ - + diff --git a/t/complex/physics.xml b/t/complex/physics.xml index d515018b0..d9b74f3d7 100644 --- a/t/complex/physics.xml +++ b/t/complex/physics.xml @@ -296,9 +296,9 @@ - + a - + diff --git a/t/digestion/io.pdf b/t/digestion/io.pdf index 6c7a1daf7..96f545a36 100644 Binary files a/t/digestion/io.pdf and b/t/digestion/io.pdf differ diff --git a/t/digestion/io.tex b/t/digestion/io.tex index bb41972aa..5f39974de 100644 --- a/t/digestion/io.tex +++ b/t/digestion/io.tex @@ -94,7 +94,8 @@ \immediate\openout\file = generated.data \immediate\write\file {First line} \immediate\write\file {Second line} -\immediate\write\file {Timing \timing.} +\immediate\write\file {Timing before: \timing.} +\immediate\write\file {Timing after: \noexpand\timing.} \immediate\write\file {Last line} \immediate\closeout\file \def\timing{After} diff --git a/t/digestion/io.xml b/t/digestion/io.xml index 16fe9262b..f7dccd946 100644 --- a/t/digestion/io.xml +++ b/t/digestion/io.xml @@ -385,7 +385,10 @@ Line: “First line Line: “Second line ” -Line: “Timing Before. +Line: “Timing before: Before. +” + +Line: “Timing after: After. ” Line: “Last line diff --git a/t/math/sampler.xml b/t/math/sampler.xml index 46e1e2e07..a85e112f8 100644 --- a/t/math/sampler.xml +++ b/t/math/sampler.xml @@ -1411,7 +1411,7 @@ are not currently tested.

- + @@ -1436,7 +1436,7 @@ are not currently tested.

- +
, @@ -1449,7 +1449,7 @@ are not currently tested.

- + @@ -1474,7 +1474,7 @@ are not currently tested.

- +
diff --git a/t/parse/parens.pdf b/t/parse/parens.pdf index 8e3fbe7ab..109cabcb0 100644 Binary files a/t/parse/parens.pdf and b/t/parse/parens.pdf differ diff --git a/t/parse/parens.tex b/t/parse/parens.tex index b5c5c7b49..aa7511b88 100644 --- a/t/parse/parens.tex +++ b/t/parse/parens.tex @@ -40,6 +40,7 @@ \section{Delimiters} \[ \left\lceil {a \over b} \right\rceil \] \[ \left< {a \over b} \right> \] \[ \left\langle {a \over b} \right\rangle \] +\[ \left\delimiter"426830A {a \over b} \right\delimiter"526930B \] \[ \left| {a \over b} \right| \] \[ \left\vert {a \over b} \right\vert \] \[ \left\| {a \over b} \right\| \] @@ -48,6 +49,8 @@ \section{Delimiters} \[ \left\Uparrow {a \over b} \right\Downarrow \] \[ \left\updownarrow {a \over b} \right\Updownarrow \] + + \def\foo{\langle} \def\bar{\rangle} \[ a + \left\foo {b \over c} \right\bar + d \] diff --git a/t/parse/parens.xml b/t/parse/parens.xml index 10d3d9330..f873b0abc 100644 --- a/t/parse/parens.xml +++ b/t/parse/parens.xml @@ -537,21 +537,21 @@ - + - + - | + a b - | + @@ -579,21 +579,21 @@ - + - + - + | a b - + | @@ -608,75 +608,96 @@ - + a b - + - + - + - + a b - + - + - + - + a b - + - + - + - + a b + + + + + + + + + + + + + + + + + + + a + b + @@ -685,8 +706,8 @@ - - + + + @@ -694,11 +715,11 @@ - + - + b c @@ -713,11 +734,11 @@ - - + + - / + / a