packages feed

texmath 0.13.2.2 → 0.13.3

raw patch · 44 files changed

+537/−177 lines, 44 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

+ Text.TeXMath.Shared: everywhereExp :: (Exp -> Exp) -> Exp -> Exp
+ Text.TeXMath.Shared: everywhereExpList :: ([Exp] -> [Exp]) -> [Exp] -> [Exp]
+ Text.TeXMath.Shared: mapExpChildren :: (Exp -> Exp) -> ([Exp] -> [Exp]) -> Exp -> Exp

Files

changelog.md view
@@ -1,3 +1,67 @@+texmath (0.13.3)++  * Replace SYB traversals with hand-written ones. Text.TeXMath.Shared+    now provides `mapExpChildren`, `everywhereExp` and+    `everywhereExpList` [API change]. These replicate the SYB+    semantics but are much faster. These are now used instead of SYB+    functions throughout the code base. This speeds up many functions+    (in particular, `writeOMML` is 6x faster on our benchmark).++  * TeX reader: Fix handling of ` and " in math mode (#296).++  * TeX reader: gate hot-path command checks behind a one-char `lookAhead`.++  * TeX reader: use a prefix trie in `oneOfStrings`.++  * TeX reader: don't fail on `p{...}` and `>{...}` array column specs.+    Column specs like `p{2cm}`, `m{0.4\textwidth}`, `b{1in}`, `>{\bf}`,+    and `<{x}` caused the whole array environment to fail to parse.  The AST+    cannot represent column widths or inserted material, so parse and+    ignore them.++  * TeX writer: use `\vec`, `\tilde`, `\hat` for single-character bases.+    The diacriticals table in Shared contained dead duplicate entries+    (`\vec` shadowed by `\overrightarrow`, `\tilde` by `\widetilde`),+    so the TeX writer always emitted the wide accent commands, even for+    single characters where `\vec{v}`, `\tilde{x}`, `\hat{H}` are canonical.++ * `renderTeX`: use a lazy Text accumulator to avoid quadratic rendering.+    This yields large performance gains on large outputs.++  * eqn writer: escape `"` and `\` in quoted text. (#297, Dylan Pulver).+    The writer wraps text in the double quotes eqn uses for literal text but+    emitted the content unescaped, so a `"` ended the string early and a `\`+    began a troff escape sequence.++  * Shared: fix unit conversion in `readLength`/`unitToMultiplier`.++  * Shared: hoist per-call table constructions to top-level CAFs.++  * MathML/OMML readers: don't crash on malformed input.++  * Macros: fix parsing of escaped braces in macro bodies.++  * Macros: don't silently drop input in `applyMacros`.++  * Macros: fix nested same-name environments in `newenvironment`.++  * Macros: speed up `applyMacros`.++  * OMML reader: fix `w:sym` private-use codepoints and empty-run junk.+    `lowerFromPrivate` only matched uppercase 'F' prefixes, so lowercase+    codepoints like `w:char="f062"` were not mapped down from the private+    use area and silently produced no symbol. Match 'f' as well.+    Also make `getSymChar` return Maybe instead of an empty string, so an+    unresolvable `w:sym` (unknown font, missing attributes, out-of-range+    codepoint) is dropped instead of becoming an empty text run, and fix+    `interpretText` to return `[]` for empty input.++  * OMML writer: don't require equal scales on delimiter pairs.+    `handleScaledDelims` only converted a scaled open/close pair to an+    m:d element when both delimiters had exactly the same scale factor,+    so pairs like \bigl( x \Bigr) degraded to flat character runs with+    no delimiter structure.+ texmath (0.13.2.2)    * Typst writer: fix spacing commands (#295).
src/Text/TeXMath/Readers/MathML.hs view
@@ -53,6 +53,7 @@ import Control.Applicative ((<|>)) import qualified Data.Text as T import Control.Monad (filterM, mzero)+import Text.Read (readMaybe) import Control.Monad.Reader (ReaderT, runReaderT, asks, local) import Data.Either (rights) @@ -399,7 +400,8 @@  action :: Element -> MML Exp action e = do-  selection <-  maybe 1 (read . T.unpack) <$> (findAttrQ "selection" e)  -- 1-indexing+  selection <-  maybe 1 (fromMaybe 1 . readMaybe . T.unpack)+                  <$> (findAttrQ "selection" e)  -- 1-indexing, defaults to 1   safeExpr =<< maybeToEither ("Selection out of range")             (listToMaybe $ drop (selection - 1) (elChildren e)) 
src/Text/TeXMath/Readers/OMML.hs view
@@ -165,7 +165,7 @@     || isElem "w" "delText" element = Just $ TextRun $ T.pack $ strContent element   | isElem "w" "br" element = Just LnBrk   | isElem "w" "tab" element = Just Tab-  | isElem "w" "sym" element = Just $ TextRun $ getSymChar element+  | isElem "w" "sym" element = TextRun <$> getSymChar element   | isElem "w" "ins" element = Just $ Inserted $ mapMaybe elemToOMathRunElem (elChildren element)   | otherwise = Nothing @@ -319,7 +319,7 @@ elemToExps' element | isElem "m" "eqArr" element =   let expLst = mapMaybe elemToBases (elChildren element)       expLst' = map breakOnAmpersand expLst-      cols = maximum (map length expLst')+      cols = foldr max 0 (map length expLst')       colspecs = take cols $ cycle [AlignRight , AlignLeft]   in    return [EArray colspecs expLst']@@ -500,6 +500,7 @@  interpretText :: T.Text -> [Exp] interpretText s+  | T.null s = []   | Just (c, xs) <- T.uncons s   , T.null xs = [interpretChar c]   | T.all isDigit s         = [ENumber s]@@ -508,16 +509,17 @@   | otherwise             = map interpretChar (T.unpack s)  -- The char attribute is a hex string-getSymChar :: Element -> T.Text-getSymChar element-  | Just s <- lowerFromPrivate <$> getCodepoint-  , Just font <- getFont =+getSymChar :: Element -> Maybe T.Text+getSymChar element = do+  s <- lowerFromPrivate <$> getCodepoint+  font <- getFont   case readLitChar ("\\x" ++ s) of-     [(char, _)] -> maybe "" T.singleton $ getUnicode font char-     _ -> ""+     [(char, _)] -> T.singleton <$> getUnicode font char+     _ -> Nothing   where     getCodepoint = findAttrBy (hasElemName "w" "char") element     getFont = (textToFont . T.pack) =<< findAttrBy (hasElemName "w" "font") element-    lowerFromPrivate ('F':xs) = '0':xs+    -- Symbol fonts store codepoints in the private use area+    -- (F000-F0FF); subtract 0xF000 to get the character code.+    lowerFromPrivate (c:xs) | c == 'F' || c == 'f' = '0':xs     lowerFromPrivate xs = xs-getSymChar _ = ""
src/Text/TeXMath/Readers/TeX.hs view
@@ -25,14 +25,14 @@ module Text.TeXMath.Readers.TeX (readTeX) where -import Data.List (intercalate, intersperse, find, foldl')+import Data.List (intercalate, intersperse, foldl') import Control.Monad import Data.Char (isDigit, isAscii, isLetter) import qualified Data.Map as M import qualified Data.Text as T import Data.Text (Text) import Data.Ratio ((%))-import Data.Maybe (catMaybes, fromJust, mapMaybe)+import Data.Maybe (catMaybes, fromJust, fromMaybe, mapMaybe) import Text.Parsec hiding (label) import Text.Parsec.Error import Text.Parsec.Text@@ -43,7 +43,6 @@ import Text.TeXMath.Unicode.ToTeX (getSymbolType) import Text.TeXMath.Unicode.ToUnicode (toUnicode) import Text.TeXMath.Shared (getSpaceChars)-import Data.Generics (everywhere, mkT) import Text.TeXMath.Readers.TeX.Commands ( styleOps, textOps, enclosures,                                            operators, symbols, siUnitMap ) import Data.Text.Read (decimal)@@ -71,12 +70,13 @@           [ inbraces           , variable           , number-          , unicode           , operator           , bareSubSup           , enclosure           , hyperref           , command+          , unicode+          , special           ] <* ignorable  -- | Parse a formula, returning a list of 'Exp'.@@ -89,7 +89,7 @@   -- | Convert Bin symbol type in certain contexts (#176, #234).   fixBinList :: [Exp] -> [Exp]   fixBinList =-    reverse . foldl' goExp [] . everywhere (mkT fixBins)+    reverse . foldl' goExp [] . map (S.everywhereExp fixBins)    -- TeXBook:   -- 5. If the current item is a Bin atom, and if this was the first@@ -195,8 +195,11 @@  expr :: TP Exp expr = do-  optional (ctrlseq "displaystyle" <|> ctrlseq "textstyle" <|>-            ctrlseq "scriptstyle" <|> ctrlseq "scriptscriptstyle")+  -- the lookAhead is just an optimization: it lets us skip the four+  -- ctrlseq attempts with a one-character test on most input+  optional (lookAhead (char '\\') *>+             (ctrlseq "displaystyle" <|> ctrlseq "textstyle" <|>+              ctrlseq "scriptstyle" <|> ctrlseq "scriptscriptstyle"))   (a, convertible) <- try (braces operatorname) -- needed because macros add {}                  <|> operatorname                  <|> ((,False) <$> expr1)@@ -289,7 +292,10 @@   <|> return Nothing  binomCmd :: TP Text-binomCmd = oneOfCommands (M.keys binomCmds)+binomCmd = lookAhead (char '\\') *> oneOfCommands (M.keys binomCmds)+  -- the lookAhead is just an optimization: this parser is run (via+  -- notFollowedBy) before every token in manyExp', and the quick+  -- one-character test lets it fail cheaply on most input.  binomCmds :: M.Map Text (Exp -> Exp -> Exp) binomCmds = M.fromList@@ -466,10 +472,12 @@ arrayAlignments :: TP [Alignment] arrayAlignments = mconcat <$>   braces (many (-                ((:[]) . letterToAlignment <$> letter)+                ((:[]) <$> try (AlignLeft <$ oneOf "pmb" <* skipBraces))+            <|> ((:[]) . letterToAlignment <$> letter)             <|> ([] <$ char '|')             <|> ([] <$ oneOf " \t")             <|> ([] <$ ((char '@' <|> char '!') <* inbraces))+            <|> ([] <$ ((char '>' <|> char '<') <* skipBraces))             <|> (do char '*'                     num <- T.pack <$> braces (many1 digit)                     cols <- arrayAlignments@@ -483,10 +491,15 @@    letterToAlignment 'c' = AlignCenter    letterToAlignment 'r' = AlignRight    letterToAlignment _   = AlignCenter+   -- Column widths (p{...}, m{...}, b{...}) and inserted material+   -- (>{...}, <{...}) can't be represented in the AST, so we parse+   -- and ignore the contents of the brace group.+   skipBraces = () <$ (char '{' *> manyTill (skipBraces <|> () <$ noneOf "}")+                                            (char '}'))  environment :: Text -> TP Exp environment "\\begin" = do-  name <- braces (oneOfStrings (M.keys environments) <* optional (char '*'))+  name <- environmentName   spaces   case M.lookup name environments of         Just env -> do@@ -499,6 +512,11 @@         Nothing  -> mzero  -- should not happen environment _ = mzero +-- A top-level binding, so that the underlying trie is built only once.+environmentName :: TP Text+environmentName =+  braces (oneOfStrings (M.keys environments) <* optional (char '*'))+ environments :: M.Map Text (TP Exp) environments = M.fromList   [ ("array", stdarray)@@ -642,6 +660,11 @@     c <- satisfy (not . isAscii)     return (ESymbol (getSymbolType c) $ T.singleton c) +-- special is to catch some things that otherwise cause parse errors,+-- e.g. $\"y$ or $`x$ -- see #296+special :: TP Exp+special = EText TextNormal <$> (quote <|> textCommand)+ ensuremath :: Text -> TP Exp ensuremath "\\ensuremath" = inbraces ensuremath _ = mzero@@ -875,25 +898,41 @@   spaces   return cmd -oneOfStrings' :: (Char -> Char -> Bool) -> [(String, Text)] -> TP Text-oneOfStrings' _ [] = mzero-oneOfStrings' matches strs = try $ do-    c <- anyChar-    let strs' = [(xs, t) | ((x:xs), t) <- strs, x `matches` c]-    case strs' of-      []  -> mzero-      _   -> oneOfStrings' matches strs'-             <|> case find (null . fst) strs' of-                   Just (_, t) -> return t-                   Nothing     -> mzero+-- A prefix trie over the characters of a fixed set of strings; the+-- value at a node is the string spelled out by the path to it, if+-- that string is in the set.+data Trie = Trie (Maybe Text) (M.Map Char Trie) +buildTrie :: [Text] -> Trie+buildTrie = foldr insertStr (Trie Nothing M.empty) . filter (not . T.null)+  where+    insertStr t = go (T.unpack t)+      where+        go [] (Trie _ cs) = Trie (Just t) cs+        go (c:rest) (Trie v cs) = Trie v $+          M.alter (Just . go rest . fromMaybe (Trie Nothing M.empty)) c cs++-- Longest match: try to descend on the next character, and fall+-- back to the match ending at the current node.+trieParser :: Trie -> TP Text+trieParser (Trie val children) =+  (if M.null children+      then mzero+      else try $ do+             c <- anyChar+             case M.lookup c children of+               Just subtrie -> trieParser subtrie+               Nothing      -> mzero)+  <|> maybe mzero return val+ -- | Parses one of a list of strings.  If the list contains -- two strings one of which is a prefix of the other, the longer--- string will be matched if possible.+-- string will be matched if possible.  The trie is built only once+-- when the resulting parser is shared, so prefer binding the result+-- to a name over calling this repeatedly with the same list. oneOfStrings :: [Text] -> TP Text-oneOfStrings strs = oneOfStrings' (==) strs' <??> (intercalate ", " $ map show strs)-  where-    strs' = map (\x -> (T.unpack x, x)) strs+oneOfStrings strs =+  trieParser (buildTrie strs) <??> (intercalate ", " $ map show strs)  -- | Like '(<?>)', but moves position back to the beginning of the parse -- before reporting the error.@@ -974,7 +1013,10 @@ ligature = try ("\x2014" <$ string "---")        <|> try ("\x2013" <$ string "--")        <|> try (textStr "-")-       <|> try ("\x201C" <$ string "``")+       <|> quote++quote :: TP Text+quote =    try ("\x201C" <$ string "``")        <|> try ("\x201D" <$ string "''")        <|> try ("\x2019" <$ string "'")        <|> try ("\x2018" <$ string "`")@@ -1127,6 +1169,7 @@ umlaut 'i' = "ï" umlaut 'o' = "ö" umlaut 'u' = "ü"+umlaut 'y' = "ÿ" umlaut c   = T.singleton c  dot :: Char -> Text
src/Text/TeXMath/Readers/TeX/Macros.hs view
@@ -78,32 +78,40 @@ -- same name, earlier ones will shadow later ones. applyMacros :: [Macro] -> T.Text -> T.Text applyMacros [] s = s-applyMacros ms s =-  maybe s id $ iterateToFixedPoint ((2 * length ms) + 1)-    (applyMacrosOnce ms) s+applyMacros ms s = maybe s id $ go ((2 * length ms) + 1) s+  where+    -- The limit caps the number of rewriting passes, in case of a+    -- loop in the macros.+    go :: Int -> T.Text -> Maybe T.Text+    go 0 _ = Nothing+    go limit x =+      case applyMacrosOnce ms x of+           Nothing -> Nothing+           Just (y, expanded)+             | expanded  -> go (limit - 1) y+             | otherwise -> Just y  -- no macro fired: y is a fixed point  ------------------------------------------------------------------------------ -iterateToFixedPoint :: Eq a => Int -> (a -> Maybe a) -> a -> Maybe a-iterateToFixedPoint 0     _ _ = Nothing-  -- Macro application did not terminate in a reasonable time, possibly-  -- because of a loop in the macro.-iterateToFixedPoint limit f x =-  case f x of-       Nothing       -> Nothing-       Just y-         | y == x    -> Just y-         | otherwise -> iterateToFixedPoint (limit - 1) f y--applyMacrosOnce :: [Macro] -> T.Text -> Maybe T.Text+-- Returns the rewritten text and whether any macro was expanded.+applyMacrosOnce :: [Macro] -> T.Text -> Maybe (T.Text, Bool) applyMacrosOnce ms s =-  case parse (many tok) "input" s of-       Right r -> Just $ T.concat r+  -- The unconsumed rest of the input (in case a token fails to parse,+  -- e.g. on a trailing comment or backslash) is passed through+  -- unchanged rather than dropped.+  case runParser ((,,) <$> many tok <*> getInput <*> getState)+         False "input" s of+       Right (r, rest, expanded) -> Just (T.concat r <> rest, expanded)        Left _  -> Nothing     where tok = try $ do                   skipComment                   choice [ choice (map (\m -> macroParser m) ms)+                             <* putState True                          , T.pack <$> ctrlseq+                           -- Macros only match at '\\' and comments+                           -- only at '%', so anything else can be+                           -- consumed as a single chunk.+                         , T.pack <$> many1 (noneOf "\\%")                          , T.pack <$> count 1 anyChar ]  ctrlseq :: (Monad m, Stream s m Char)@@ -181,30 +189,35 @@              (if numargs > 0 then ("[" ++ show numargs ++ "]") else "") ++              case optarg of { Nothing -> ""; Just x -> "[" ++ x ++ "]"} ++              "%\n{" ++ opener ++ "}%\n" ++ "{" ++ closer ++ "}"-  return $ Macro (T.pack defn) $ fmap T.pack $ try $ do-    string "\\begin"-    pSkipSpaceComments-    char '{'-    string name-    pSkipSpaceComments-    char '}'-    opt <- case optarg of-                Nothing  -> return Nothing-                Just _   -> liftM (`mplus` optarg) optArg-    args <- count numargs' (pSkipSpaceComments >>-                  (inbraces <|> ctrlseq <|> count 1 anyChar))-    let args' = case opt of-                     Just x  -> x : args-                     Nothing -> args-    let ender = try $ do-                      string "\\end"-                      pSkipSpaceComments-                      char '{'-                      string name-                      char '}'-    body <- manyTill anyChar ender-    return $ apply args'-           $ opener ++ body ++ closer+  return $ Macro (T.pack defn) $ fmap T.pack $+    let pEnv = try $ do+          string "\\begin"+          pSkipSpaceComments+          char '{'+          string name+          pSkipSpaceComments+          char '}'+          opt <- case optarg of+                      Nothing  -> return Nothing+                      Just _   -> liftM (`mplus` optarg) optArg+          args <- count numargs' (pSkipSpaceComments >>+                        (inbraces <|> ctrlseq <|> count 1 anyChar))+          let args' = case opt of+                           Just x  -> x : args+                           Nothing -> args+          body <- pBody+          return $ apply args'+                 $ opener ++ body ++ closer+        ender = try $ do+          string "\\end"+          pSkipSpaceComments+          char '{'+          string name+          char '}'+        -- Expand nested environments with the same name recursively,+        -- so that the body isn't ended at a nested \end.+        pBody = concat <$> manyTill (pEnv <|> count 1 anyChar) ender+    in  pEnv  -- | Parser for \DeclareMathOperator(*) command. declareMathOperator :: (Monad m, Stream s m Char)@@ -285,7 +298,7 @@ inbraces = try $ do   char '{'   res <- manyTill (skipComment >>-            (inbraces' <|> count 1 anyChar <|> escaped "{}"))+            (inbraces' <|> escaped "{}" <|> count 1 anyChar))     (try $ skipComment >> char '}')   return $ concat res 
src/Text/TeXMath/Shared.hs view
@@ -30,6 +30,9 @@   , getOperator   , readLength   , fixTree+  , everywhereExp+  , everywhereExpList+  , mapExpChildren   , isEmpty   , empty   , handleDownup@@ -47,9 +50,7 @@ import Data.Maybe (fromMaybe) import Data.Ratio ((%)) import Data.List (sort)-import Control.Monad (guard) import Text.Parsec (Parsec, parse, getInput, digit, char, many1, option)-import Data.Generics (everywhere, mkT)  -- As we constuct from the bottom up, this situation can occur. removeNesting :: Exp -> Exp@@ -74,8 +75,61 @@ -- fixing delimited expressions with no delimiters and unnecessarily -- grouped expressions. fixTree :: Exp -> Exp-fixTree = everywhere (mkT removeNesting) . everywhere (mkT removeEmpty)+fixTree = everywhereExp removeNesting . goE+  where+    -- Remove empty expressions from every expression list, bottom up.+    -- (Filtering each list once is equivalent to the per-tail+    -- application 'everywhereExpList' would do, since removeEmpty is+    -- an element-wise filter.)+    goE = mapExpChildren goE (removeEmpty . map goE) +-- | Apply a transformation to every subexpression, bottom up+-- (equivalent to SYB's @everywhere (mkT f)@, but faster, since it+-- involves no run-time type checks).+everywhereExp :: (Exp -> Exp) -> Exp -> Exp+everywhereExp f = go+  where go = f . mapExpChildren go (map go)++-- | Apply a transformation to every expression list in an expression+-- list, bottom up.  Like SYB's @everywhere (mkT f)@, this applies the+-- function to every /tail/ of every list (right to left), since each+-- tail is itself a @[Exp]@ node; a rewrite can thus consume+-- already-rewritten material to its right.+everywhereExpList :: ([Exp] -> [Exp]) -> [Exp] -> [Exp]+everywhereExpList f = goL+  where goL = foldr (\x acc -> f (goE x : acc)) (f [])+        goE = mapExpChildren goE goL++-- | Apply @goE@ to each immediate subexpression of a node and @goL@+-- to each immediate subexpression list.  A building block for+-- expression traversals.+mapExpChildren :: (Exp -> Exp) -> ([Exp] -> [Exp]) -> Exp -> Exp+mapExpChildren goE goL e =+  case e of+    ENumber{}          -> e+    EGrouped es        -> EGrouped (goL es)+    EDelimited o c ds  -> EDelimited o c (map (fmap goE) ds)+    EIdentifier{}      -> e+    EMathOperator{}    -> e+    ESymbol{}          -> e+    ESpace{}           -> e+    ESub a b           -> ESub (goE a) (goE b)+    ESuper a b         -> ESuper (goE a) (goE b)+    ESubsup a b c      -> ESubsup (goE a) (goE b) (goE c)+    EOver conv a b     -> EOver conv (goE a) (goE b)+    EUnder conv a b    -> EUnder conv (goE a) (goE b)+    EUnderover conv a b c -> EUnderover conv (goE a) (goE b) (goE c)+    EPhantom a         -> EPhantom (goE a)+    EBoxed a           -> EBoxed (goE a)+    ECancel st a       -> ECancel st (goE a)+    EFraction ft a b   -> EFraction ft (goE a) (goE b)+    ERoot a b          -> ERoot (goE a) (goE b)+    ESqrt a            -> ESqrt (goE a)+    EScaled r a        -> EScaled r (goE a)+    EArray as rows     -> EArray as (map (map goL) rows)+    EText{}            -> e+    EStyled tt es      -> EStyled tt (goL es)+ -- | Maps TextType to the corresponding MathML mathvariant getMMLType :: TextType -> T.Text getMMLType t = fromMaybe "normal" (fst <$> M.lookup t textTypesMap)@@ -96,12 +150,16 @@ -- | Maps a LaTeX scaling command to the percentage scaling getScalerCommand :: Rational -> Maybe T.Text getScalerCommand width =-  case sort [ (w, cmd) | (cmd, w) <- scalers, w >= width ] of-       ((_,cmd):_) -> Just cmd-       _           -> Nothing-  -- note, we don't use a Map here because we need the first-  -- match:  \Big, not \Bigr+  case [ cmd | (w, cmd) <- sortedScalers, w >= width ] of+       (cmd:_) -> Just cmd+       _       -> Nothing +-- Scalers sorted by increasing width (then command name), so the+-- first command with sufficient width is the preferred one:+-- \Big, not \Bigr.  (We don't use a Map because of this tie-break.)+sortedScalers :: [(Rational, T.Text)]+sortedScalers = sort [ (w, cmd) | (cmd, w) <- scalers ]+ -- | Gets percentage scaling from LaTeX scaling command getScalerValue :: T.Text -> Maybe Rational getScalerValue command = lookup command scalers@@ -114,9 +172,10 @@   case pos of     Under -> if below then Just command else Nothing     Over -> if not below then Just command else Nothing-  where-    diaMap = M.fromList diacriticals +diaMap :: M.Map T.Text T.Text+diaMap = M.fromList diacriticals+ -- Operator Table  getOperator :: Exp -> Maybe TeX@@ -305,14 +364,12 @@                , ("\x20DC", "\\ddddot")                , ("\x00B0", "\\mathring")                , ("\x030A", "\\mathring")-               , ("\x20D7", "\\vec")                , ("\x20D7", "\\overrightarrow")                , ("\x20D6", "\\overleftarrow")                , ("\x005E", "\\hat")                , ("\x02C6", "\\widehat")                , ("\x0302", "\\widehat")                , ("\x02DC", "\\widetilde")-               , ("\x0303", "\\tilde")                , ("\x0303", "\\widetilde")                , ("\x0304", "\\bar")                , ("\x203E", "\\bar")@@ -331,19 +388,21 @@   -- Converts unit to multiplier to reach em+-- (em length per unit, assuming 1em = 10pt) unitToMultiplier :: T.Text -> Maybe Rational unitToMultiplier s = M.lookup s units-  where-    units = M.fromList  [ ( "pt" , 10)-                        , ( "mm" , (351/10))-                        , ( "cm" , (35/100))-                        , ( "in" , (14/100))-                        , ( "ex" , (232/100))-                        , ( "em" , 1)-                        , ( "mu" , 18)-                        , ( "dd" , (93/100))-                        , ( "bp" , (996/1000))-                        , ( "pc" , (83/100)) ]++units :: M.Map T.Text Rational+units = M.fromList  [ ( "pt" , (1/10))+                    , ( "mm" , (2845/10000))   -- 1mm = 72.27/25.4 pt+                    , ( "cm" , (2845/1000))+                    , ( "in" , (7227/1000))    -- 1in = 72.27pt+                    , ( "ex" , (43/100))       -- 1ex ~ 4.3pt (cmr10)+                    , ( "em" , 1)+                    , ( "mu" , (1/18))         -- 18mu = 1em+                    , ( "dd" , (107/1000))     -- 1dd = 1238/1157 pt+                    , ( "bp" , (1004/10000))   -- 1bp = 72.27/72 pt+                    , ( "pc" , (12/10)) ]      -- 1pc = 12pt  handleDownup :: DisplayType -> Exp -> Exp handleDownup DisplayInline (EUnder True x y)       = ESub x y
src/Text/TeXMath/TeX.hs view
@@ -7,6 +7,7 @@ where import Data.Char (isLetter, isAlphaNum, isAscii) import qualified Data.Text as T+import qualified Data.Text.Lazy as TL  -- | An intermediate representation of TeX math, to be used in rendering. data TeX = ControlSeq T.Text@@ -18,23 +19,32 @@  -- | Render a 'TeX' to a string, appending to the front of the given string. renderTeX :: TeX -> T.Text -> T.Text-renderTeX (Token c) cs     = T.cons c cs-renderTeX (Literal s) cs-  | endsWith (not . isLetter) s = s <> cs-  | startsWith isLetter cs      = s <> T.cons ' ' cs-  | otherwise                   = s <> cs-renderTeX (ControlSeq s) cs-  | s == "\\ "               = s <> cs+renderTeX t cs = TL.toStrict $ renderTeX' t (TL.fromStrict cs)++-- Rendering builds the output back to front, and looks ahead at the+-- rendered rest to decide on spacing.  The accumulator is a lazy+-- Text, so that prepending is O(1) rather than a copy of the whole+-- rest (which would make rendering quadratic).+renderTeX' :: TeX -> TL.Text -> TL.Text+renderTeX' (Token c) cs     = TL.cons c cs+renderTeX' (Literal s) cs+  | endsWith (not . isLetter) s = s' <> cs+  | startsWith isLetter cs      = s' <> TL.cons ' ' cs+  | otherwise                   = s' <> cs+  where s' = TL.fromStrict s+renderTeX' (ControlSeq s) cs+  | s == "\\ "               = s' <> cs   | startsWith (\c -> isAlphaNum c || not (isAscii c)) cs-                             = s <> T.cons ' ' cs-  | otherwise                = s <> cs-renderTeX (Grouped [Grouped xs]) cs  = renderTeX (Grouped xs) cs-renderTeX (Grouped xs) cs     =-  "{" <> foldr renderTeX "" (trimSpaces xs) <> "}" <> cs-renderTeX Space cs-  | cs == ""                   = ""-  | any (`T.isPrefixOf` cs) ps = cs-  | otherwise                  = T.cons ' ' cs+                             = s' <> TL.cons ' ' cs+  | otherwise                = s' <> cs+  where s' = TL.fromStrict s+renderTeX' (Grouped [Grouped xs]) cs  = renderTeX' (Grouped xs) cs+renderTeX' (Grouped xs) cs     =+  "{" <> foldr renderTeX' "" (trimSpaces xs) <> "}" <> cs+renderTeX' Space cs+  | TL.null cs                  = ""+  | any (`TL.isPrefixOf` cs) ps = cs+  | otherwise                   = TL.cons ' ' cs   where     -- No space before ^, _, or \limits, and no doubled up spaces     ps = [ "^", "_", " ", "\\limits" ]@@ -43,8 +53,8 @@ trimSpaces = reverse . go . reverse . go   where go = dropWhile (== Space) -startsWith :: (Char -> Bool) -> T.Text -> Bool-startsWith p t = case T.uncons t of+startsWith :: (Char -> Bool) -> TL.Text -> Bool+startsWith p t = case TL.uncons t of   Just (c, _) -> p c   Nothing     -> False 
src/Text/TeXMath/Writers/Eqn.hs view
@@ -27,7 +27,6 @@ import Text.Printf (printf) import Text.TeXMath.Types import qualified Text.TeXMath.Shared as S-import Data.Generics (everywhere, mkT) import Data.Ratio ((%)) import Data.Text (Text) @@ -37,7 +36,7 @@ -- | Transforms an expression tree to equivalent Eqn writeEqn :: DisplayType -> [Exp] -> T.Text writeEqn dt exprs =-  T.unwords $ map writeExp $ everywhere (mkT $ S.handleDownup dt) exprs+  T.unwords $ map (writeExp . S.everywhereExp (S.handleDownup dt)) exprs  -- like writeExp but inserts {} if contents contain a space writeExp' :: Exp -> T.Text@@ -54,13 +53,23 @@ asgroup "" = "{\"\"}"  -- see #198 asgroup t = "{" <> t <> "}" +-- Put text in the double quotes eqn uses to delimit literal text,+-- escaping the two characters that are special inside them: an+-- unescaped @"@ ends the string, and a backslash begins a troff+-- escape sequence.+quoteText :: Text -> Text+quoteText t = "\"" <> T.concatMap escapeChar t <> "\""+  where escapeChar '"'  = "\\\""+        escapeChar '\\' = "\\[rs]"+        escapeChar c    = T.singleton c+ writeExp :: Exp -> T.Text writeExp (ENumber s) = s writeExp (EGrouped es) = asgroup $ writeExps es writeExp (EDelimited open close es) =   "left " <> mbQuote open <> " " <> T.intercalate " " (map fromDelimited es) <>   " right " <> mbQuote close-  where fromDelimited (Left e)  = "\"" <> e <> "\""+  where fromDelimited (Left e)  = quoteText e         fromDelimited (Right e) = writeExp e         mbQuote "" = "\"\""         mbQuote s  = s@@ -69,7 +78,7 @@                "tanh", "arc", "max", "min", "lim",                "log", "ln", "exp"]      then s-     else "\"" <> s <> "\""+     else quoteText s writeExp (ESymbol Ord (T.unpack -> [c]))  -- do not render "invisible operators"   | c `elem` ['\x2061'..'\x2064'] = "" -- see 3.2.5.5 of mathml spec writeExp (EIdentifier s) = writeExp (ESymbol Ord s)@@ -190,7 +199,7 @@ writeExp (ECancel _ e) = writeExp e -- TODO  writeExp (EScaled _size e) = writeExp e -- TODO: any way? writeExp (EText ttype s) =-  let quoted = "\"" <> s <> "\""+  let quoted = quoteText s   in case ttype of        TextNormal -> "roman " <> quoted        TextItalic -> quoted
src/Text/TeXMath/Writers/MathML.hs view
@@ -26,9 +26,8 @@  import Text.XML.Light import Text.TeXMath.Types-import Data.Generics (everywhere, mkT) import Text.TeXMath.Unicode.ToUnicode (toUnicode)-import Text.TeXMath.Shared (getMMLType, handleDownup,+import Text.TeXMath.Shared (getMMLType, handleDownup, everywhereExp,                             isUppercaseGreek, isRLSequence) import Text.TeXMath.Readers.MathML.MMLDict (getMathMLOperator) import qualified Data.Text as T@@ -38,7 +37,7 @@ writeMathML :: DisplayType -> [Exp] -> Element writeMathML dt exprs =   add_attr dtattr $ math $ showExp Nothing $ EGrouped-  $ everywhere (mkT $ handleDownup dt) exprs+  $ map (everywhereExp (handleDownup dt)) exprs     where dtattr = Attr (unqual "display") dt'           dt' =  case dt of                       DisplayBlock  -> "block"
src/Text/TeXMath/Writers/OMML.hs view
@@ -26,8 +26,8 @@  import Text.XML.Light import Text.TeXMath.Types-import Text.TeXMath.Shared (isUppercaseGreek, isRLSequence)-import Data.Generics (everywhere, mkT)+import Text.TeXMath.Shared (isUppercaseGreek, isRLSequence,+                            everywhereExpList, mapExpChildren) import Data.Char (isSymbol, isPunctuation) import Data.Either (lefts, isLeft, rights) import qualified Data.Text as T@@ -37,9 +37,9 @@ -- | Transforms an expression tree to an OMML XML Tree writeOMML :: DisplayType -> [Exp] -> Element writeOMML dt = container . concatMap (showExp [])-            . everywhere (mkT $ handleDownup dt)-            . everywhere (mkT $ handleDownup' dt)-            . everywhere (mkT $ handleScaledDelims)+            . everywhereExpList (handleDownup dt)+            . handleDownupDelims dt+            . everywhereExpList handleScaledDelims     where container = case dt of                   DisplayBlock  -> \x -> mnode "oMathPara"                                     [ mnode "oMathParaPr"@@ -132,10 +132,13 @@    where sty x = mnodeA "sty" x ()          scr x = mnodeA "scr" x () +-- OMML cannot represent a numeric scale factor for delimiters, so+-- render a pair of scaled delimiters as an m:d, which grows the+-- delimiters to fit their content. handleScaledDelims :: [Exp] -> [Exp]-handleScaledDelims (x@(EScaled scale (ESymbol Open op)) : xs) =+handleScaledDelims (x@(EScaled _ (ESymbol Open op)) : xs) =   case break isCloser xs of-    (ys, EScaled scale' (ESymbol Close cl) : zs) | scale' == scale ->+    (ys, EScaled _ (ESymbol Close cl) : zs) ->       EDelimited op cl (map Right ys) : zs     _ -> x:xs  where@@ -171,6 +174,17 @@                               []     -> (emptyGroup, [])           emptyGroup = EGrouped [] handleDownup _ []            = []++-- | Apply @handleDownup' dt@ to every delimited-expression list,+-- bottom up, including every tail of every list (the same traversal+-- the SYB @everywhere@ it replaces performed).+handleDownupDelims :: DisplayType -> [Exp] -> [Exp]+handleDownupDelims dt = map goE+  where+    goE (EDelimited o c ds) = EDelimited o c (goDs ds)+    goE e = mapExpChildren goE (map goE) e+    goDs = foldr (\d acc -> f (fmap goE d : acc)) (f [])+    f = handleDownup' dt  -- TODO This duplication is ugly and inefficient.  See #92. handleDownup' :: DisplayType -> [InEDelimited] -> [InEDelimited]
src/Text/TeXMath/Writers/StarMath.hs view
@@ -4,7 +4,6 @@   ) where  import Data.Char (isLetter)-import Data.Generics (everywhere, mkT) import qualified Data.List as List import qualified Data.Text as T import qualified Text.TeXMath.Shared as S@@ -23,7 +22,7 @@ -- Falls back to TeX output for expressions that are not yet supported. writeStarMath :: DisplayType -> [Exp] -> T.Text writeStarMath dt exps =-  case renderExps dt (normalizeExps (everywhere (mkT $ S.handleDownup dt) exps)) of+  case renderExps dt (normalizeExps (map (S.everywhereExp (S.handleDownup dt)) exps)) of     Just rendered -> T.strip rendered     Nothing       -> writeTeX exps 
src/Text/TeXMath/Writers/TeX.hs view
@@ -25,7 +25,6 @@ import Text.TeXMath.Unicode.ToUnicode (fromUnicode) import qualified Text.TeXMath.Shared as S import qualified Data.Text as T-import Data.Generics (everywhere, mkT) import Control.Monad (when, unless, foldM_) import Control.Monad.Reader (MonadReader, runReader, Reader, asks, local) import Control.Monad.Writer( MonadWriter, WriterT,@@ -101,6 +100,22 @@        tell [ControlSeq cmd]        writeExp y +-- | Replace styled unicode characters with their unstyled+-- equivalents in every text field of an expression.+fromUnicodeExp :: TextType -> Exp -> Exp+fromUnicodeExp ttype = S.everywhereExp go+  where+    f = fromUnicode ttype+    go e = case e of+      ENumber t         -> ENumber (f t)+      EIdentifier t     -> EIdentifier (f t)+      EMathOperator t   -> EMathOperator (f t)+      ESymbol ty t      -> ESymbol ty (f t)+      EText tt t        -> EText tt (f t)+      EDelimited o c ds -> EDelimited (f o) (f c)+                             (map (either (Left . f) Right) ds)+      _                 -> e+ writeExp :: Exp -> Math () writeExp (ENumber s) = tell =<< getTeXMathM s writeExp (EGrouped es) = tellGroup (mapM_ writeExp es)@@ -287,11 +302,11 @@        xs   -> tell $ txtcmd (Grouped xs) writeExp (EStyled TextNormal [EStyled TextBold es]) = do   tell [ControlSeq "\\mathbf"]-  tellGroup $ mapM_ writeExp $ everywhere (mkT (fromUnicode TextBold)) es+  tellGroup $ mapM_ (writeExp . fromUnicodeExp TextBold) es writeExp (EStyled ttype es) = do   txtcmd <- (flip S.getLaTeXTextCommand ttype) <$> asks mathEnv   tell [ControlSeq txtcmd]-  tellGroup (mapM_ writeExp $ everywhere (mkT (fromUnicode ttype)) es)+  tellGroup (mapM_ (writeExp . fromUnicodeExp ttype) es) writeExp (EArray as rows)   | S.isRLSequence as = do   env <- asks mathEnv@@ -350,7 +365,8 @@   let diacmd = case e1 of                     ESymbol stype a                       | stype `elem` [Accent, TOver, TUnder]-                      -> S.getDiacriticalCommand pos a+                      -> (if isNarrow b then narrowDiacritical else id)+                           <$> S.getDiacriticalCommand pos a                     _ -> Nothing   case diacmd of        Just cmd -> do@@ -458,6 +474,25 @@ isOperator (EMathOperator _) = True isOperator (ESymbol Op _)    = True isOperator _                 = False++-- | True if the expression is a single character wide, so that+-- narrow accent commands like \vec are preferable to wide ones+-- like \overrightarrow.+isNarrow :: Exp -> Bool+isNarrow (EIdentifier t) = T.length t == 1+isNarrow (ENumber t)     = T.length t == 1+isNarrow (ESymbol _ t)   = T.length t == 1+isNarrow (EGrouped [x])  = isNarrow x+isNarrow (EStyled _ [x]) = isNarrow x+isNarrow _               = False++-- | Preferred variants of wide accent commands for single-character+-- bases.+narrowDiacritical :: T.Text -> T.Text+narrowDiacritical "\\overrightarrow" = "\\vec"+narrowDiacritical "\\widetilde"      = "\\tilde"+narrowDiacritical "\\widehat"        = "\\hat"+narrowDiacritical cmd                = cmd  removeOuterGroup :: [Exp] -> [Exp] removeOuterGroup [EGrouped es] = es
src/Text/TeXMath/Writers/Typst.hs view
@@ -26,7 +26,6 @@ import Text.TeXMath.Types import qualified Text.TeXMath.Shared as S import qualified Typst.Symbols as TS-import Data.Generics (everywhere, mkT) import Data.Text (Text) import Data.Char (isDigit, isAlpha, isAscii) import Data.Maybe (fromMaybe)@@ -38,7 +37,7 @@ -- | Transforms an expression tree to equivalent Typst writeTypst :: DisplayType -> [Exp] -> Text writeTypst dt exprs =-  writeExps $ everywhere (mkT $ S.handleDownup dt) exprs+  writeExps $ map (S.everywhereExp (S.handleDownup dt)) exprs  writeExps :: [Exp] -> Text writeExps = go . map writeExp
test/reader/mml/complex3.test view
@@ -19392,9 +19392,9 @@       ]     , [ [ EGrouped             [ ENumber "5"-            , ESpace (7 % 100)+            , ESpace (7227 % 2000)             , EGrouped [ ENumber "24" , ESymbol Pun "!" ]-            , ESpace (7 % 100)+            , ESpace (7227 % 2000)             , ESuper (EIdentifier "x") (ENumber "6")             ]         ]
test/reader/mml/mspace1.test view
@@ -18,9 +18,9 @@   </mrow> </math> >>> native [ EIdentifier "x"-, ESpace (58 % 25)+, ESpace (43 % 100) , EIdentifier "M"-, ESpace (58 % 25)+, ESpace (43 % 100) , EIdentifier "x" , ESpace (0 % 1) ]
test/reader/mml/mspacestruts2.test view
@@ -31,7 +31,8 @@ >>> native [ EFraction     NormalFrac-    (EGrouped [ EIdentifier "x" , ESpace (7 % 20) , EIdentifier "y" ])+    (EGrouped+       [ EIdentifier "x" , ESpace (569 % 200) , EIdentifier "y" ])     (ENumber "2") , ESymbol Bin "+" , EFraction
+ test/reader/omml/sym.test view
@@ -0,0 +1,9 @@+<<< omml+<m:oMath xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math" xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">+  <m:r><w:sym w:font="Symbol" w:char="F062"/></m:r>+  <m:r><w:sym w:font="Symbol" w:char="f062"/></m:r>+  <m:r><w:sym w:font="Symbol" w:char="FFFFFFFF"/></m:r>+  <m:r><w:sym w:char="F062"/></m:r>+</m:oMath>+>>> native+[ EIdentifier "\946" , EIdentifier "\946" ]
+ test/reader/tex/array_column_specs.test view
@@ -0,0 +1,20 @@+<<< tex+\begin{array}{p{2cm}|>{\bf}c<{x}m{0.4\textwidth}r}+a & b & c & d \\+e & f & g & h+\end{array}+>>> native+[ EArray+    [ AlignLeft , AlignCenter , AlignLeft , AlignRight ]+    [ [ [ EIdentifier "a" ]+      , [ EIdentifier "b" ]+      , [ EIdentifier "c" ]+      , [ EIdentifier "d" ]+      ]+    , [ [ EIdentifier "e" ]+      , [ EIdentifier "f" ]+      , [ EIdentifier "g" ]+      , [ EIdentifier "h" ]+      ]+    ]+]
+ test/reader/tex/macros_escaped_braces.test view
@@ -0,0 +1,13 @@+<<< tex+\newcommand{\set}[1]{\{#1\}}+\newcommand{\lbr}{\{}+\newcommand{\abc}{5}++\set{a} + \lbr \abc+>>> native+[ EGrouped+    [ ESymbol Open "{" , EIdentifier "a" , ESymbol Close "}" ]+, ESymbol Bin "+"+, ESymbol Open "{"+, ENumber "5"+]
+ test/reader/tex/macros_nested_env.test view
@@ -0,0 +1,20 @@+<<< tex+\newenvironment{brak}[1]{\langle #1:}{:#1\rangle}+\begin{brak}{a} x \begin{brak}{b} y \end{brak} z \end{brak}+>>> native+[ ESymbol Open "\10216"+, EIdentifier "a"+, ESymbol Rel ":"+, EIdentifier "x"+, ESymbol Open "\10216"+, EIdentifier "b"+, ESymbol Rel ":"+, EIdentifier "y"+, ESymbol Rel ":"+, EIdentifier "b"+, ESymbol Close "\10217"+, EIdentifier "z"+, ESymbol Rel ":"+, EIdentifier "a"+, ESymbol Close "\10217"+]
+ test/regression/296.test view
@@ -0,0 +1,16 @@+<<< tex+a`b x\"y p``q+>>> mml+<?xml version='1.0' ?>+<math display="block" xmlns="http://www.w3.org/1998/Math/MathML">+  <mrow>+    <mi>a</mi>+    <mtext mathvariant="normal">‘</mtext>+    <mi>b</mi>+    <mi>x</mi>+    <mtext mathvariant="normal">ÿ</mtext>+    <mi>p</mi>+    <mtext mathvariant="normal">“</mtext>+    <mi>q</mi>+  </mrow>+</math>
+ test/regression/297.test view
@@ -0,0 +1,4 @@+<<< tex+\text{say "hi"} + \text{a\textbackslash b}+>>> eqn+roman "say \"hi\"" + roman "a\[rs]b"
test/writer/eqn/complex3.test view
@@ -7896,6 +7896,6 @@ ccol{ {x = {y + z}} above {= {k + m}} } }} above {matrix{ lcol{ {roman "College Algebra " roman "Second Edition"} above {roman "James Stewart " roman "McMaster Universitiy"} above {roman "Lothar Redlin" roman " Pennsylvania State University"} above {roman "Saleem Watson" roman " California State University, Long Beach"} above {roman "Copyright 1996, ISBN 0 534-33983-2"} above {roman "Brooks/Cole Publishing Company"} above {roman "An International Thomson Publishing Company"} }-} ~} above {left { {1 over 2} over {1 over 2} "↑" sum from 1 to 2 right }} above {left 〈 {1 over 2} over {1 over 2} "|" sum from 1 to 2 right 〉} above {left ⌈ {1 over 2} over {1 over 2} "|" sum from 1 to 2 right ⌉} above {left "" "⇓" left "" {1 over 2} over {1 over 2} "↕" sum from 1 to 2 right "" "⇓" right ""} above {left [ {1 over 2} over {1 over 2} right ]} above {left ( {1 over 2} over {1 over 2} right )} above {left { {1 over 2} over {1 over 2} right }} above {left 〈 {1 over 2} over {1 over 2} right 〉} above {left ⌊ {1 over 2} over {1 over 2} right ⌋} above {left ⌈ {1 over 2} over {1 over 2} right ⌉} above {left "" "↑" {1 over 2} over {1 over 2} "↑" right ""} above {left "" "↓" {1 over 2} over {1 over 2} "↓" right ""} above {left "" "↕" {1 over 2} over {1 over 2} "↕" right ""} above {left "" "⇑" {1 over 2} over {1 over 2} "⇑" right ""} above {left "" "⇓" {1 over 2} over {1 over 2} "⇓" right ""} above {left "" "⇕" {1 over 2} over {1 over 2} "⇕" right ""} above {{1 over 2} over {1 over 2}} above {left \arrowvert {1 over 2} over {1 over 2} right \arrowvert} above {left \Arrowvert {1 over 2} over {1 over 2} right \Arrowvert} above {left \bracevert {1 over 2} over {1 over 2} right \bracevert} above {left | {1 over 2} over {1 over 2} right |} above {left | {1 over 2} over {1 over 2} right |} above {left | {1 over 2} over {1 over 2} right |} above {left "" "∥" {1 over 2} over {1 over 2} "∥" right ""} above {left "" "∥" {1 over 2} over {1 over 2} "∥" right ""} above {left "" "/" {1 over 2} over {1 over 2} "/" right ""} above {left "" "\" {1 over 2} over {1 over 2} "\" right ""} above {left ⎱ {1 over 2} over {1 over 2} right ⎰} above {left \lgroup {1 over 2} over {1 over 2} right \rgroup} above {left ⌞ {1 over 2} over {1 over 2} right ⌟} above {left ⌜ {1 over 2} over {1 over 2} right ⌝} above {A <- from ^ to {n + mu - 1} B -> from T to {n +- i - 1} C} above {1 over {sqrt 2 + 1 over {sqrt 3 + 1 over {sqrt 4 + 1 over {sqrt 5 + 1 over {sqrt 6 + ...}}}}}} above {1 over {sqrt 2 + 1 over {sqrt 3 + 1 over {sqrt 4 + 1 over {sqrt 5 + 1 over {sqrt 6 + ...}}}}}} above {left ( {sin  theta} over M right ⌋} above {left ( {sin  theta} over M right ⌋} above {left ( {sin  theta} over M right ⌋} above {left ( {sin  theta} over M right ⌋} above {left ( {sin  theta} over M right ⌋} above {left ( {sin  theta} over M right ⌋} above {left ( {sin  theta} over M right ⌋} above {left ( {sin  theta} over M right ⌋} above {left ( {sin  theta} over M right ⌋} above {{sin  theta} over M} above {{sin  theta} over M} above {{sin  theta} over M} above {{sin  theta} over M} above {{sin  theta} over M} above {{sin  theta} over M} above {{sin  theta} over M} above {{sin  theta} over M} above {{sin  theta} over M} }+} ~} above {left { {1 over 2} over {1 over 2} "↑" sum from 1 to 2 right }} above {left 〈 {1 over 2} over {1 over 2} "|" sum from 1 to 2 right 〉} above {left ⌈ {1 over 2} over {1 over 2} "|" sum from 1 to 2 right ⌉} above {left "" "⇓" left "" {1 over 2} over {1 over 2} "↕" sum from 1 to 2 right "" "⇓" right ""} above {left [ {1 over 2} over {1 over 2} right ]} above {left ( {1 over 2} over {1 over 2} right )} above {left { {1 over 2} over {1 over 2} right }} above {left 〈 {1 over 2} over {1 over 2} right 〉} above {left ⌊ {1 over 2} over {1 over 2} right ⌋} above {left ⌈ {1 over 2} over {1 over 2} right ⌉} above {left "" "↑" {1 over 2} over {1 over 2} "↑" right ""} above {left "" "↓" {1 over 2} over {1 over 2} "↓" right ""} above {left "" "↕" {1 over 2} over {1 over 2} "↕" right ""} above {left "" "⇑" {1 over 2} over {1 over 2} "⇑" right ""} above {left "" "⇓" {1 over 2} over {1 over 2} "⇓" right ""} above {left "" "⇕" {1 over 2} over {1 over 2} "⇕" right ""} above {{1 over 2} over {1 over 2}} above {left \arrowvert {1 over 2} over {1 over 2} right \arrowvert} above {left \Arrowvert {1 over 2} over {1 over 2} right \Arrowvert} above {left \bracevert {1 over 2} over {1 over 2} right \bracevert} above {left | {1 over 2} over {1 over 2} right |} above {left | {1 over 2} over {1 over 2} right |} above {left | {1 over 2} over {1 over 2} right |} above {left "" "∥" {1 over 2} over {1 over 2} "∥" right ""} above {left "" "∥" {1 over 2} over {1 over 2} "∥" right ""} above {left "" "/" {1 over 2} over {1 over 2} "/" right ""} above {left "" "\[rs]" {1 over 2} over {1 over 2} "\[rs]" right ""} above {left ⎱ {1 over 2} over {1 over 2} right ⎰} above {left \lgroup {1 over 2} over {1 over 2} right \rgroup} above {left ⌞ {1 over 2} over {1 over 2} right ⌟} above {left ⌜ {1 over 2} over {1 over 2} right ⌝} above {A <- from ^ to {n + mu - 1} B -> from T to {n +- i - 1} C} above {1 over {sqrt 2 + 1 over {sqrt 3 + 1 over {sqrt 4 + 1 over {sqrt 5 + 1 over {sqrt 6 + ...}}}}}} above {1 over {sqrt 2 + 1 over {sqrt 3 + 1 over {sqrt 4 + 1 over {sqrt 5 + 1 over {sqrt 6 + ...}}}}}} above {left ( {sin  theta} over M right ⌋} above {left ( {sin  theta} over M right ⌋} above {left ( {sin  theta} over M right ⌋} above {left ( {sin  theta} over M right ⌋} above {left ( {sin  theta} over M right ⌋} above {left ( {sin  theta} over M right ⌋} above {left ( {sin  theta} over M right ⌋} above {left ( {sin  theta} over M right ⌋} above {left ( {sin  theta} over M right ⌋} above {{sin  theta} over M} above {{sin  theta} over M} above {{sin  theta} over M} above {{sin  theta} over M} above {{sin  theta} over M} above {{sin  theta} over M} above {{sin  theta} over M} above {{sin  theta} over M} above {{sin  theta} over M} } ccol{ {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {x = {1 + y}} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} } }
test/writer/eqn/ms-15.test view
@@ -4,4 +4,4 @@ , EText TextNormal "\8220string\"" ] >>> eqn-roman ""string”" = roman "“string""+roman "\"string”" = roman "“string\""
test/writer/eqn/ms-16.test view
@@ -4,4 +4,4 @@ , EText TextNormal "\8220string\8221" ] >>> eqn-roman ""string"" = roman "“string”"+roman "\"string\"" = roman "“string”"
test/writer/eqn/sans-serif-bold-italic.test view
@@ -28,5 +28,5 @@ ] >>> eqn {matrix{-lcol{ {roman "!"#$%&'()*+,-./0123456789:;<=>?"} above {roman "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_"} above {roman "`abcdefghijklmnopqrstuvwxyz{|}~"} above {roman "ıȷ"} above {roman "ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡϴΣΤΥΦΧΨΩ∇"} above {roman "αβγδεζηθικλμνξοπρςστυφχψω∂"} above {roman "ϵϑϰϕϱϖϜϝ"} above {roman "±·×÷‘’“”•−∓∕∗∙≠≤≥⋅"} }+lcol{ {roman "!\"#$%&'()*+,-./0123456789:;<=>?"} above {roman "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\[rs]]^_"} above {roman "`abcdefghijklmnopqrstuvwxyz{|}~"} above {roman "ıȷ"} above {roman "ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡϴΣΤΥΦΧΨΩ∇"} above {roman "αβγδεζηθικλμνξοπρςστυφχψω∂"} above {roman "ϵϑϰϕϱϖϜϝ"} above {roman "±·×÷‘’“”•−∓∕∗∙≠≤≥⋅"} } }}
test/writer/eqn/sans-serif-bold.test view
@@ -28,5 +28,5 @@ ] >>> eqn {matrix{-lcol{ {roman "!"#$%&'()*+,-./0123456789:;<=>?"} above {roman "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_"} above {roman "`abcdefghijklmnopqrstuvwxyz{|}~"} above {roman "ıȷ"} above {roman "ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡϴΣΤΥΦΧΨΩ∇"} above {roman "αβγδεζηθικλμνξοπρςστυφχψω∂"} above {roman "ϵϑϰϕϱϖϜϝ"} above {roman "±·×÷‘’“”•−∓∕∗∙≠≤≥⋅"} }+lcol{ {roman "!\"#$%&'()*+,-./0123456789:;<=>?"} above {roman "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\[rs]]^_"} above {roman "`abcdefghijklmnopqrstuvwxyz{|}~"} above {roman "ıȷ"} above {roman "ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡϴΣΤΥΦΧΨΩ∇"} above {roman "αβγδεζηθικλμνξοπρςστυφχψω∂"} above {roman "ϵϑϰϕϱϖϜϝ"} above {roman "±·×÷‘’“”•−∓∕∗∙≠≤≥⋅"} } }}
test/writer/eqn/sans-serif-italic.test view
@@ -28,5 +28,5 @@ ] >>> eqn {matrix{-lcol{ {roman "!"#$%&'()*+,-./0123456789:;<=>?"} above {roman "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_"} above {roman "`abcdefghijklmnopqrstuvwxyz{|}~"} above {roman "ıȷ"} above {roman "ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡϴΣΤΥΦΧΨΩ∇"} above {roman "αβγδεζηθικλμνξοπρςστυφχψω∂"} above {roman "ϵϑϰϕϱϖϜϝ"} above {roman "±·×÷‘’“”•−∓∕∗∙≠≤≥⋅"} }+lcol{ {roman "!\"#$%&'()*+,-./0123456789:;<=>?"} above {roman "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\[rs]]^_"} above {roman "`abcdefghijklmnopqrstuvwxyz{|}~"} above {roman "ıȷ"} above {roman "ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡϴΣΤΥΦΧΨΩ∇"} above {roman "αβγδεζηθικλμνξοπρςστυφχψω∂"} above {roman "ϵϑϰϕϱϖϜϝ"} above {roman "±·×÷‘’“”•−∓∕∗∙≠≤≥⋅"} } }}
test/writer/eqn/sans-serif.test view
@@ -28,5 +28,5 @@ ] >>> eqn {matrix{-lcol{ {roman "!"#$%&'()*+,-./0123456789:;<=>?"} above {roman "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_"} above {roman "`abcdefghijklmnopqrstuvwxyz{|}~"} above {roman "ıȷ"} above {roman "ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡϴΣΤΥΦΧΨΩ∇"} above {roman "αβγδεζηθικλμνξοπρςστυφχψω∂"} above {roman "ϵϑϰϕϱϖϜϝ"} above {roman "±·×÷‘’“”•−∓∕∗∙≠≤≥⋅"} }+lcol{ {roman "!\"#$%&'()*+,-./0123456789:;<=>?"} above {roman "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\[rs]]^_"} above {roman "`abcdefghijklmnopqrstuvwxyz{|}~"} above {roman "ıȷ"} above {roman "ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡϴΣΤΥΦΧΨΩ∇"} above {roman "αβγδεζηθικλμνξοπρςστυφχψω∂"} above {roman "ϵϑϰϕϱϖϜϝ"} above {roman "±·×÷‘’“”•−∓∕∗∙≠≤≥⋅"} } }}
test/writer/eqn/serif-bold-italic.test view
@@ -28,5 +28,5 @@ ] >>> eqn bold italic {matrix{-lcol{ {roman "!"#$%&'()*+,-./0123456789:;<=>?"} above {roman "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_"} above {roman "`abcdefghijklmnopqrstuvwxyz{|}~"} above {roman "ıȷ"} above {roman "ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡϴΣΤΥΦΧΨΩ∇"} above {roman "αβγδεζηθικλμνξοπρςστυφχψω∂"} above {roman "ϵϑϰϕϱϖϜϝ"} above {roman "±·×÷‘’“”•−∓∕∗∙≠≤≥⋅"} }+lcol{ {roman "!\"#$%&'()*+,-./0123456789:;<=>?"} above {roman "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\[rs]]^_"} above {roman "`abcdefghijklmnopqrstuvwxyz{|}~"} above {roman "ıȷ"} above {roman "ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡϴΣΤΥΦΧΨΩ∇"} above {roman "αβγδεζηθικλμνξοπρςστυφχψω∂"} above {roman "ϵϑϰϕϱϖϜϝ"} above {roman "±·×÷‘’“”•−∓∕∗∙≠≤≥⋅"} } }}
test/writer/eqn/serif-bold.test view
@@ -28,5 +28,5 @@ ] >>> eqn bold {matrix{-lcol{ {roman "!"#$%&'()*+,-./0123456789:;<=>?"} above {roman "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_"} above {roman "`abcdefghijklmnopqrstuvwxyz{|}~"} above {roman "ıȷ"} above {roman "ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡϴΣΤΥΦΧΨΩ∇"} above {roman "αβγδεζηθικλμνξοπρςστυφχψω∂"} above {roman "ϵϑϰϕϱϖϜϝ"} above {roman "±·×÷‘’“”•−∓∕∗∙≠≤≥⋅"} }+lcol{ {roman "!\"#$%&'()*+,-./0123456789:;<=>?"} above {roman "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\[rs]]^_"} above {roman "`abcdefghijklmnopqrstuvwxyz{|}~"} above {roman "ıȷ"} above {roman "ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡϴΣΤΥΦΧΨΩ∇"} above {roman "αβγδεζηθικλμνξοπρςστυφχψω∂"} above {roman "ϵϑϰϕϱϖϜϝ"} above {roman "±·×÷‘’“”•−∓∕∗∙≠≤≥⋅"} } }}
test/writer/eqn/serif-italic.test view
@@ -28,5 +28,5 @@ ] >>> eqn italic {matrix{-lcol{ {roman "!"#$%&'()*+,-./0123456789:;<=>?"} above {roman "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_"} above {roman "`abcdefghijklmnopqrstuvwxyz{|}~"} above {roman "ıȷ"} above {roman "ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡϴΣΤΥΦΧΨΩ∇"} above {roman "αβγδεζηθικλμνξοπρςστυφχψω∂"} above {roman "ϵϑϰϕϱϖϜϝ"} above {roman "±·×÷‘’“”•−∓∕∗∙≠≤≥⋅"} }+lcol{ {roman "!\"#$%&'()*+,-./0123456789:;<=>?"} above {roman "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\[rs]]^_"} above {roman "`abcdefghijklmnopqrstuvwxyz{|}~"} above {roman "ıȷ"} above {roman "ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡϴΣΤΥΦΧΨΩ∇"} above {roman "αβγδεζηθικλμνξοπρςστυφχψω∂"} above {roman "ϵϑϰϕϱϖϜϝ"} above {roman "±·×÷‘’“”•−∓∕∗∙≠≤≥⋅"} } }}
test/writer/eqn/serif.test view
@@ -25,5 +25,5 @@ ] >>> eqn matrix{-lcol{ {roman "!"#$%&'()*+,-./0123456789:;<=>?"} above {roman "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_"} above {roman "`abcdefghijklmnopqrstuvwxyz{|}~"} above {roman "ıȷ"} above {roman "ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡϴΣΤΥΦΧΨΩ∇"} above {roman "αβγδεζηθικλμνξοπρςστυφχψω∂"} above {roman "ϵϑϰϕϱϖϜϝ"} above {roman "±·×÷‘’“”•−∓∕∗∙≠≤≥⋅"} }+lcol{ {roman "!\"#$%&'()*+,-./0123456789:;<=>?"} above {roman "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\[rs]]^_"} above {roman "`abcdefghijklmnopqrstuvwxyz{|}~"} above {roman "ıȷ"} above {roman "ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡϴΣΤΥΦΧΨΩ∇"} above {roman "αβγδεζηθικλμνξοπρςστυφχψω∂"} above {roman "ϵϑϰϕϱϖϜϝ"} above {roman "±·×÷‘’“”•−∓∕∗∙≠≤≥⋅"} } }
+ test/writer/omml/scaled_delims.test view
@@ -0,0 +1,27 @@+<<< native+[ EScaled (6 % 5) (ESymbol Open "(")+, EIdentifier "x"+, EScaled (9 % 5) (ESymbol Close ")")+]+>>> omml+<?xml version='1.0' ?>+<m:oMathPara>+  <m:oMathParaPr>+    <m:jc m:val="center" />+  </m:oMathParaPr>+  <m:oMath>+    <m:d>+      <m:dPr>+        <m:begChr m:val="(" />+        <m:sepChr m:val="" />+        <m:endChr m:val=")" />+        <m:grow />+      </m:dPr>+      <m:e>+        <m:r>+          <m:t>x</m:t>+        </m:r>+      </m:e>+    </m:d>+  </m:oMath>+</m:oMathPara>
test/writer/tex/accents1.test view
@@ -88,7 +88,7 @@ >>> tex \begin{array}{l} \text{default: (accent=true)} \\-{\overset{'}{H}\hat{H}\overset{\_}{H}\grave{H}\overset{\sim}{H}\overset{¨}{H}\overline{H}\acute{H}\overset{¸}{H}\widehat{H}\check{H}\breve{H}\overset{˙}{H}\overset{˚}{H}\widetilde{H}\overset{˝}{H}\widehat{H}\overset{̑}{H}\bar{H}\dddot{H}\ddddot{H}\overset{\leftarrow}{H}\overset{\rightarrow}{H}\overset{\leftrightarrow}{H}\overset{\leftharpoonup}{H}\overset{\leftharpoondown}{H}\overset{\rightharpoonup}{H}\overset{\rightharpoondown}{H}\overbracket{H}\overset{⎵}{H}\overset{⏜}{H}\overset{⏝}{H}\overbrace{H}\overset{\underbrace{}}{H}\overset{⥎}{H}\overset{⥐}{H}} \\+{\overset{'}{H}\hat{H}\overset{\_}{H}\grave{H}\overset{\sim}{H}\overset{¨}{H}\overline{H}\acute{H}\overset{¸}{H}\hat{H}\check{H}\breve{H}\overset{˙}{H}\overset{˚}{H}\tilde{H}\overset{˝}{H}\hat{H}\overset{̑}{H}\bar{H}\dddot{H}\ddddot{H}\overset{\leftarrow}{H}\overset{\rightarrow}{H}\overset{\leftrightarrow}{H}\overset{\leftharpoonup}{H}\overset{\leftharpoondown}{H}\overset{\rightharpoonup}{H}\overset{\rightharpoondown}{H}\overbracket{H}\overset{⎵}{H}\overset{⏜}{H}\overset{⏝}{H}\overbrace{H}\overset{\underbrace{}}{H}\overset{⥎}{H}\overset{⥐}{H}} \\ \text{accent=false:} \\-{\overset{'}{H}\overset{\hat{}}{H}\overset{\_}{H}\overset{`}{H}\overset{\sim}{H}\overset{¨}{H}\overset{¯}{H}\overset{´}{H}\overset{¸}{H}\overset{\hat{}}{H}\overset{ˇ}{H}\overset{˘}{H}\overset{˙}{H}\overset{˚}{H}\overset{˜}{H}\overset{˝}{H}\widehat{H}\overset{̑}{H}\overset{‾}{H}\dddot{H}\ddddot{H}\overset{\leftarrow}{H}\overset{\rightarrow}{H}\overset{\leftrightarrow}{H}\overset{\leftharpoonup}{H}\overset{\leftharpoondown}{H}\overset{\rightharpoonup}{H}\overset{\rightharpoondown}{H}\overbracket{H}\overset{⎵}{H}\overset{⏜}{H}\overset{⏝}{H}\overbrace{H}\overset{\underbrace{}}{H}\overset{⥎}{H}\overset{⥐}{H}}+{\overset{'}{H}\overset{\hat{}}{H}\overset{\_}{H}\overset{`}{H}\overset{\sim}{H}\overset{¨}{H}\overset{¯}{H}\overset{´}{H}\overset{¸}{H}\overset{\hat{}}{H}\overset{ˇ}{H}\overset{˘}{H}\overset{˙}{H}\overset{˚}{H}\overset{˜}{H}\overset{˝}{H}\hat{H}\overset{̑}{H}\overset{‾}{H}\dddot{H}\ddddot{H}\overset{\leftarrow}{H}\overset{\rightarrow}{H}\overset{\leftrightarrow}{H}\overset{\leftharpoonup}{H}\overset{\leftharpoondown}{H}\overset{\rightharpoonup}{H}\overset{\rightharpoondown}{H}\overbracket{H}\overset{⎵}{H}\overset{⏜}{H}\overset{⏝}{H}\overbrace{H}\overset{\underbrace{}}{H}\overset{⥎}{H}\overset{⥐}{H}} \end{array}
test/writer/tex/accents2.test view
@@ -88,7 +88,7 @@ >>> tex \begin{array}{l} \text{default: (accent=true)} \\-{\overset{'}{x}\hat{x}\overset{\_}{x}\grave{x}\overset{\sim}{x}\overset{¨}{x}\overline{x}\acute{x}\overset{¸}{x}\widehat{x}\check{x}\breve{x}\overset{˙}{x}\overset{˚}{x}\widetilde{x}\overset{˝}{x}\widehat{x}\overset{̑}{x}\bar{x}\dddot{x}\ddddot{x}\overset{\leftarrow}{x}\overset{\rightarrow}{x}\overset{\leftrightarrow}{x}\overset{\leftharpoonup}{x}\overset{\leftharpoondown}{x}\overset{\rightharpoonup}{x}\overset{\rightharpoondown}{x}\overbracket{x}\overset{⎵}{x}\overset{⏜}{x}\overset{⏝}{x}\overbrace{x}\overset{\underbrace{}}{x}\overset{⥎}{x}\overset{⥐}{x}} \\+{\overset{'}{x}\hat{x}\overset{\_}{x}\grave{x}\overset{\sim}{x}\overset{¨}{x}\overline{x}\acute{x}\overset{¸}{x}\hat{x}\check{x}\breve{x}\overset{˙}{x}\overset{˚}{x}\tilde{x}\overset{˝}{x}\hat{x}\overset{̑}{x}\bar{x}\dddot{x}\ddddot{x}\overset{\leftarrow}{x}\overset{\rightarrow}{x}\overset{\leftrightarrow}{x}\overset{\leftharpoonup}{x}\overset{\leftharpoondown}{x}\overset{\rightharpoonup}{x}\overset{\rightharpoondown}{x}\overbracket{x}\overset{⎵}{x}\overset{⏜}{x}\overset{⏝}{x}\overbrace{x}\overset{\underbrace{}}{x}\overset{⥎}{x}\overset{⥐}{x}} \\ \text{accent=false:} \\-{\overset{'}{x}\overset{\hat{}}{x}\overset{\_}{x}\overset{`}{x}\overset{\sim}{x}\overset{¨}{x}\overset{¯}{x}\overset{´}{x}\overset{¸}{x}\overset{\hat{}}{x}\overset{ˇ}{x}\overset{˘}{x}\overset{˙}{x}\overset{˚}{x}\overset{˜}{x}\overset{˝}{x}\widehat{x}\overset{̑}{x}\overset{‾}{x}\dddot{x}\ddddot{x}\overset{\leftarrow}{x}\overset{\rightarrow}{x}\overset{\leftrightarrow}{x}\overset{\leftharpoonup}{x}\overset{\leftharpoondown}{x}\overset{\rightharpoonup}{x}\overset{\rightharpoondown}{x}\overbracket{x}\overset{⎵}{x}\overset{⏜}{x}\overset{⏝}{x}\overbrace{x}\overset{\underbrace{}}{x}\overset{⥎}{x}\overset{⥐}{x}}+{\overset{'}{x}\overset{\hat{}}{x}\overset{\_}{x}\overset{`}{x}\overset{\sim}{x}\overset{¨}{x}\overset{¯}{x}\overset{´}{x}\overset{¸}{x}\overset{\hat{}}{x}\overset{ˇ}{x}\overset{˘}{x}\overset{˙}{x}\overset{˚}{x}\overset{˜}{x}\overset{˝}{x}\hat{x}\overset{̑}{x}\overset{‾}{x}\dddot{x}\ddddot{x}\overset{\leftarrow}{x}\overset{\rightarrow}{x}\overset{\leftrightarrow}{x}\overset{\leftharpoonup}{x}\overset{\leftharpoondown}{x}\overset{\rightharpoonup}{x}\overset{\rightharpoondown}{x}\overbracket{x}\overset{⎵}{x}\overset{⏜}{x}\overset{⏝}{x}\overbrace{x}\overset{\underbrace{}}{x}\overset{⥎}{x}\overset{⥐}{x}} \end{array}
test/writer/tex/accents5.test view
@@ -295,7 +295,7 @@ >>> tex \begin{array}{l} \text{default: (accent=true)} \\-{\underset{'}{\overset{'}{H}}\underset{\hat{}}{\hat{H}}\underline{\overset{\_}{H}}\underset{`}{\grave{H}}\underset{\sim}{\overset{\sim}{H}}\underset{¨}{\overset{¨}{H}}\underset{¯}{\overline{H}}\underset{´}{\acute{H}}\underset{¸}{\overset{¸}{H}}\underset{\hat{}}{\widehat{H}}\underset{ˇ}{\check{H}}\underset{˘}{\breve{H}}\underset{˙}{\overset{˙}{H}}\underset{˚}{\overset{˚}{H}}\underset{˜}{\widetilde{H}}\underset{˝}{\overset{˝}{H}}\underset{\hat{}}{\widehat{H}}\underset{̑}{\overset{̑}{H}}\underset{‾}{\bar{H}}\underset{\dddot{}}{\dddot{H}}\underset{\ddddot{}}{\ddddot{H}}\underset{\leftarrow}{\overset{\leftarrow}{H}}\underset{\rightarrow}{\overset{\rightarrow}{H}}\underset{\leftrightarrow}{\overset{\leftrightarrow}{H}}\underset{\leftharpoonup}{\overset{\leftharpoonup}{H}}\underset{\leftharpoondown}{\overset{\leftharpoondown}{H}}\underset{\rightharpoonup}{\overset{\rightharpoonup}{H}}\underset{\rightharpoondown}{\overset{\rightharpoondown}{H}}\underset{⎴}{\overbracket{H}}\underbracket{\overset{⎵}{H}}\underset{⏜}{\overset{⏜}{H}}\underset{⏝}{\overset{⏝}{H}}\underset{\overbrace{}}{\overbrace{H}}\underbrace{\overset{\underbrace{}}{H}}\underset{⥎}{\overset{⥎}{H}}\underset{⥐}{\overset{⥐}{H}}} \\+{\underset{'}{\overset{'}{H}}\underset{\hat{}}{\hat{H}}\underline{\overset{\_}{H}}\underset{`}{\grave{H}}\underset{\sim}{\overset{\sim}{H}}\underset{¨}{\overset{¨}{H}}\underset{¯}{\overline{H}}\underset{´}{\acute{H}}\underset{¸}{\overset{¸}{H}}\underset{\hat{}}{\hat{H}}\underset{ˇ}{\check{H}}\underset{˘}{\breve{H}}\underset{˙}{\overset{˙}{H}}\underset{˚}{\overset{˚}{H}}\underset{˜}{\tilde{H}}\underset{˝}{\overset{˝}{H}}\underset{\hat{}}{\hat{H}}\underset{̑}{\overset{̑}{H}}\underset{‾}{\bar{H}}\underset{\dddot{}}{\dddot{H}}\underset{\ddddot{}}{\ddddot{H}}\underset{\leftarrow}{\overset{\leftarrow}{H}}\underset{\rightarrow}{\overset{\rightarrow}{H}}\underset{\leftrightarrow}{\overset{\leftrightarrow}{H}}\underset{\leftharpoonup}{\overset{\leftharpoonup}{H}}\underset{\leftharpoondown}{\overset{\leftharpoondown}{H}}\underset{\rightharpoonup}{\overset{\rightharpoonup}{H}}\underset{\rightharpoondown}{\overset{\rightharpoondown}{H}}\underset{⎴}{\overbracket{H}}\underbracket{\overset{⎵}{H}}\underset{⏜}{\overset{⏜}{H}}\underset{⏝}{\overset{⏝}{H}}\underset{\overbrace{}}{\overbrace{H}}\underbrace{\overset{\underbrace{}}{H}}\underset{⥎}{\overset{⥎}{H}}\underset{⥐}{\overset{⥐}{H}}} \\ \text{accent=false:} \\-{\underset{'}{\overset{'}{H}}\underset{\hat{}}{\overset{\hat{}}{H}}\underset{\_}{\overset{\_}{H}}\underset{`}{\overset{`}{H}}\underset{\sim}{\overset{\sim}{H}}\underset{¨}{\overset{¨}{H}}\underset{¯}{\overset{¯}{H}}\underset{´}{\overset{´}{H}}\underset{¸}{\overset{¸}{H}}\underset{\hat{}}{\overset{\hat{}}{H}}\underset{ˇ}{\overset{ˇ}{H}}\underset{˘}{\overset{˘}{H}}\underset{˙}{\overset{˙}{H}}\underset{˚}{\overset{˚}{H}}\underset{˜}{\overset{˜}{H}}\underset{˝}{\overset{˝}{H}}\underset{\hat{}}{\widehat{H}}\underset{̑}{\overset{̑}{H}}\underset{‾}{\overset{‾}{H}}\underset{\dddot{}}{\dddot{H}}\underset{\ddddot{}}{\ddddot{H}}\underset{\leftarrow}{\overset{\leftarrow}{H}}\underset{\rightarrow}{\overset{\rightarrow}{H}}\underset{\leftrightarrow}{\overset{\leftrightarrow}{H}}\underset{\leftharpoonup}{\overset{\leftharpoonup}{H}}\underset{\leftharpoondown}{\overset{\leftharpoondown}{H}}\underset{\rightharpoonup}{\overset{\rightharpoonup}{H}}\underset{\rightharpoondown}{\overset{\rightharpoondown}{H}}\underset{⎴}{\overbracket{H}}\underbracket{\overset{⎵}{H}}\underset{⏜}{\overset{⏜}{H}}\underset{⏝}{\overset{⏝}{H}}\underset{\overbrace{}}{\overbrace{H}}\underbrace{\overset{\underbrace{}}{H}}\underset{⥎}{\overset{⥎}{H}}\underset{⥐}{\overset{⥐}{H}}}+{\underset{'}{\overset{'}{H}}\underset{\hat{}}{\overset{\hat{}}{H}}\underset{\_}{\overset{\_}{H}}\underset{`}{\overset{`}{H}}\underset{\sim}{\overset{\sim}{H}}\underset{¨}{\overset{¨}{H}}\underset{¯}{\overset{¯}{H}}\underset{´}{\overset{´}{H}}\underset{¸}{\overset{¸}{H}}\underset{\hat{}}{\overset{\hat{}}{H}}\underset{ˇ}{\overset{ˇ}{H}}\underset{˘}{\overset{˘}{H}}\underset{˙}{\overset{˙}{H}}\underset{˚}{\overset{˚}{H}}\underset{˜}{\overset{˜}{H}}\underset{˝}{\overset{˝}{H}}\underset{\hat{}}{\hat{H}}\underset{̑}{\overset{̑}{H}}\underset{‾}{\overset{‾}{H}}\underset{\dddot{}}{\dddot{H}}\underset{\ddddot{}}{\ddddot{H}}\underset{\leftarrow}{\overset{\leftarrow}{H}}\underset{\rightarrow}{\overset{\rightarrow}{H}}\underset{\leftrightarrow}{\overset{\leftrightarrow}{H}}\underset{\leftharpoonup}{\overset{\leftharpoonup}{H}}\underset{\leftharpoondown}{\overset{\leftharpoondown}{H}}\underset{\rightharpoonup}{\overset{\rightharpoonup}{H}}\underset{\rightharpoondown}{\overset{\rightharpoondown}{H}}\underset{⎴}{\overbracket{H}}\underbracket{\overset{⎵}{H}}\underset{⏜}{\overset{⏜}{H}}\underset{⏝}{\overset{⏝}{H}}\underset{\overbrace{}}{\overbrace{H}}\underbrace{\overset{\underbrace{}}{H}}\underset{⥎}{\overset{⥎}{H}}\underset{⥐}{\overset{⥐}{H}}} \end{array}
test/writer/tex/accents6.test view
@@ -295,7 +295,7 @@ >>> tex \begin{array}{l} \text{default: (accent=true)} \\-{\underset{'}{\overset{'}{x}}\underset{\hat{}}{\hat{x}}\underline{\overset{\_}{x}}\underset{`}{\grave{x}}\underset{\sim}{\overset{\sim}{x}}\underset{¨}{\overset{¨}{x}}\underset{¯}{\overline{x}}\underset{´}{\acute{x}}\underset{¸}{\overset{¸}{x}}\underset{\hat{}}{\widehat{x}}\underset{ˇ}{\check{x}}\underset{˘}{\breve{x}}\underset{˙}{\overset{˙}{x}}\underset{˚}{\overset{˚}{x}}\underset{˜}{\widetilde{x}}\underset{˝}{\overset{˝}{x}}\underset{\hat{}}{\widehat{x}}\underset{̑}{\overset{̑}{x}}\underset{‾}{\bar{x}}\underset{\dddot{}}{\dddot{x}}\underset{\ddddot{}}{\ddddot{x}}\underset{\leftarrow}{\overset{\leftarrow}{x}}\underset{\rightarrow}{\overset{\rightarrow}{x}}\underset{\leftrightarrow}{\overset{\leftrightarrow}{x}}\underset{\leftharpoonup}{\overset{\leftharpoonup}{x}}\underset{\leftharpoondown}{\overset{\leftharpoondown}{x}}\underset{\rightharpoonup}{\overset{\rightharpoonup}{x}}\underset{\rightharpoondown}{\overset{\rightharpoondown}{x}}\underset{⎴}{\overbracket{x}}\underbracket{\overset{⎵}{x}}\underset{⏜}{\overset{⏜}{x}}\underset{⏝}{\overset{⏝}{x}}\underset{\overbrace{}}{\overbrace{x}}\underbrace{\overset{\underbrace{}}{x}}\underset{⥎}{\overset{⥎}{x}}\underset{⥐}{\overset{⥐}{x}}} \\+{\underset{'}{\overset{'}{x}}\underset{\hat{}}{\hat{x}}\underline{\overset{\_}{x}}\underset{`}{\grave{x}}\underset{\sim}{\overset{\sim}{x}}\underset{¨}{\overset{¨}{x}}\underset{¯}{\overline{x}}\underset{´}{\acute{x}}\underset{¸}{\overset{¸}{x}}\underset{\hat{}}{\hat{x}}\underset{ˇ}{\check{x}}\underset{˘}{\breve{x}}\underset{˙}{\overset{˙}{x}}\underset{˚}{\overset{˚}{x}}\underset{˜}{\tilde{x}}\underset{˝}{\overset{˝}{x}}\underset{\hat{}}{\hat{x}}\underset{̑}{\overset{̑}{x}}\underset{‾}{\bar{x}}\underset{\dddot{}}{\dddot{x}}\underset{\ddddot{}}{\ddddot{x}}\underset{\leftarrow}{\overset{\leftarrow}{x}}\underset{\rightarrow}{\overset{\rightarrow}{x}}\underset{\leftrightarrow}{\overset{\leftrightarrow}{x}}\underset{\leftharpoonup}{\overset{\leftharpoonup}{x}}\underset{\leftharpoondown}{\overset{\leftharpoondown}{x}}\underset{\rightharpoonup}{\overset{\rightharpoonup}{x}}\underset{\rightharpoondown}{\overset{\rightharpoondown}{x}}\underset{⎴}{\overbracket{x}}\underbracket{\overset{⎵}{x}}\underset{⏜}{\overset{⏜}{x}}\underset{⏝}{\overset{⏝}{x}}\underset{\overbrace{}}{\overbrace{x}}\underbrace{\overset{\underbrace{}}{x}}\underset{⥎}{\overset{⥎}{x}}\underset{⥐}{\overset{⥐}{x}}} \\ \text{accent=false:} \\-{\underset{'}{\overset{'}{x}}\underset{\hat{}}{\overset{\hat{}}{x}}\underset{\_}{\overset{\_}{x}}\underset{`}{\overset{`}{x}}\underset{\sim}{\overset{\sim}{x}}\underset{¨}{\overset{¨}{x}}\underset{¯}{\overset{¯}{x}}\underset{´}{\overset{´}{x}}\underset{¸}{\overset{¸}{x}}\underset{\hat{}}{\overset{\hat{}}{x}}\underset{ˇ}{\overset{ˇ}{x}}\underset{˘}{\overset{˘}{x}}\underset{˙}{\overset{˙}{x}}\underset{˚}{\overset{˚}{x}}\underset{˜}{\overset{˜}{x}}\underset{˝}{\overset{˝}{x}}\underset{\hat{}}{\widehat{x}}\underset{̑}{\overset{̑}{x}}\underset{‾}{\overset{‾}{x}}\underset{\dddot{}}{\dddot{x}}\underset{\ddddot{}}{\ddddot{x}}\underset{\leftarrow}{\overset{\leftarrow}{x}}\underset{\rightarrow}{\overset{\rightarrow}{x}}\underset{\leftrightarrow}{\overset{\leftrightarrow}{x}}\underset{\leftharpoonup}{\overset{\leftharpoonup}{x}}\underset{\leftharpoondown}{\overset{\leftharpoondown}{x}}\underset{\rightharpoonup}{\overset{\rightharpoonup}{x}}\underset{\rightharpoondown}{\overset{\rightharpoondown}{x}}\underset{⎴}{\overbracket{x}}\underbracket{\overset{⎵}{x}}\underset{⏜}{\overset{⏜}{x}}\underset{⏝}{\overset{⏝}{x}}\underset{\overbrace{}}{\overbrace{x}}\underbrace{\overset{\underbrace{}}{x}}\underset{⥎}{\overset{⥎}{x}}\underset{⥐}{\overset{⥐}{x}}}+{\underset{'}{\overset{'}{x}}\underset{\hat{}}{\overset{\hat{}}{x}}\underset{\_}{\overset{\_}{x}}\underset{`}{\overset{`}{x}}\underset{\sim}{\overset{\sim}{x}}\underset{¨}{\overset{¨}{x}}\underset{¯}{\overset{¯}{x}}\underset{´}{\overset{´}{x}}\underset{¸}{\overset{¸}{x}}\underset{\hat{}}{\overset{\hat{}}{x}}\underset{ˇ}{\overset{ˇ}{x}}\underset{˘}{\overset{˘}{x}}\underset{˙}{\overset{˙}{x}}\underset{˚}{\overset{˚}{x}}\underset{˜}{\overset{˜}{x}}\underset{˝}{\overset{˝}{x}}\underset{\hat{}}{\hat{x}}\underset{̑}{\overset{̑}{x}}\underset{‾}{\overset{‾}{x}}\underset{\dddot{}}{\dddot{x}}\underset{\ddddot{}}{\ddddot{x}}\underset{\leftarrow}{\overset{\leftarrow}{x}}\underset{\rightarrow}{\overset{\rightarrow}{x}}\underset{\leftrightarrow}{\overset{\leftrightarrow}{x}}\underset{\leftharpoonup}{\overset{\leftharpoonup}{x}}\underset{\leftharpoondown}{\overset{\leftharpoondown}{x}}\underset{\rightharpoonup}{\overset{\rightharpoonup}{x}}\underset{\rightharpoondown}{\overset{\rightharpoondown}{x}}\underset{⎴}{\overbracket{x}}\underbracket{\overset{⎵}{x}}\underset{⏜}{\overset{⏜}{x}}\underset{⏝}{\overset{⏝}{x}}\underset{\overbrace{}}{\overbrace{x}}\underbrace{\overset{\underbrace{}}{x}}\underset{⥎}{\overset{⥎}{x}}\underset{⥐}{\overset{⥐}{x}}} \end{array}
test/writer/tex/complex3.test view
@@ -8079,7 +8079,7 @@ {\text{testing }\begin{matrix} {\sin\theta} \end{matrix}} & \\-{\widehat{a} + \check{b} + \widetilde{c} + \acute{d} + \grave{e} + \breve{f} + \overline{g} + h + \overset{˚}{i} + \overset{˙}{j} + \overset{¨}{k} + \dddot{l} + \ddddot{m} + \overset{\rightarrow}{n}} & \\+{\hat{a} + \check{b} + \tilde{c} + \acute{d} + \grave{e} + \breve{f} + \overline{g} + h + \overset{˚}{i} + \overset{˙}{j} + \overset{¨}{k} + \dddot{l} + \ddddot{m} + \overset{\rightarrow}{n}} & \\ {{f{({g{(x)}})}} = {{\sin^{3}x^{2}} + {{\sin x^{2}}{\sin\left( {\sin x^{2}} \right)}}}} & \\ {\left( {x^{2} + 12} \right) + 1234} & \\ \begin{matrix}
test/writer/tex/divergence.test view
@@ -22,4 +22,4 @@     (EGrouped [ ESymbol Ord "\8706" , EIdentifier "z" ]) ] >>> tex-\nabla \cdot \overrightarrow{v} = \frac{\partial v_{x}}{\partial x} + \frac{\partial v_{y}}{\partial y} + \frac{\partial v_{z}}{\partial z}+\nabla \cdot \vec{v} = \frac{\partial v_{x}}{\partial x} + \frac{\partial v_{y}}{\partial y} + \frac{\partial v_{z}}{\partial z}
test/writer/tex/mover3.test view
@@ -8,4 +8,4 @@ , EOver False (EIdentifier "x") (ESymbol Alpha "\710") ] >>> tex-\widehat{x} \neq \overset{\hat{}}{x} = \overset{\hat{}}{x} = \overset{\hat{}}{x}+\hat{x} \neq \overset{\hat{}}{x} = \overset{\hat{}}{x} = \overset{\hat{}}{x}
test/writer/tex/mover5.test view
@@ -8,4 +8,4 @@ , EOver False (EIdentifier "x") (ESymbol Ord "\732") ] >>> tex-\widetilde{x} \neq \overset{˜}{x} = \overset{˜}{x} = \overset{˜}{x}+\tilde{x} \neq \overset{˜}{x} = \overset{˜}{x} = \overset{˜}{x}
test/writer/tex/tokens.test view
@@ -9,4 +9,4 @@ , EIdentifier "\958" ] >>> tex-\widetilde{\phi}\sqrt{\phi}\frac{\phi}{\xi}\frac{\phi}{\xi}\frac{\phi}{\xi}(\phi)(\phi)\xi+\tilde{\phi}\sqrt{\phi}\frac{\phi}{\xi}\frac{\phi}{\xi}\frac{\phi}{\xi}(\phi)(\phi)\xi
texmath.cabal view
@@ -1,6 +1,6 @@ Name:                texmath-Version:             0.13.2.2-Cabal-Version:       >= 1.10+Version:             0.13.3+Cabal-Version:       2.0 Build-type:          Simple Synopsis:            Conversion between math formats. Description:         The texmath library provides functions to read@@ -35,11 +35,11 @@ Author:              John MacFarlane, Matthew Pickering Maintainer:          jgm@berkeley.edu Homepage:            http://github.com/jgm/texmath-Extra-source-files:  README.md+Extra-doc-files:     README.md                      changelog.md-                     man/texmath.1.md-                     man/Makefile                      man/man1/texmath.1+Extra-source-files:  man/texmath.1.md+                     man/Makefile                      server/texmath.html                      test/writer/mml/*.test                      test/writer/omml/*.test@@ -109,6 +109,7 @@                          Text.TeXMath.Shared     Other-modules:       Text.TeXMath.Readers.TeX.Commands                          Paths_texmath+    Autogen-modules:     Paths_texmath     if impl(ghc >= 6.12)       Ghc-Options:     -Wall -fno-warn-unused-do-bind     else@@ -121,6 +122,7 @@     Default-Language:    Haskell2010     Main-is:             texmath.hs     Other-Modules:       Paths_texmath+    Autogen-modules:     Paths_texmath     Hs-Source-Dirs:      extra     if impl(ghc >= 6.12)       Ghc-Options:     -Wall -fno-warn-unused-do-bind