// Copyright 2017-2022 The MathJax Consortium // SPDX-License-Identifier: Apache-2.0 // Sources: PhysicsMappings, PhysicsMethods.Quantity and PhysicsItems.AutoOpen.
package tex import type physicsQuantitySpec struct { open, close string argument bool named, variant string } var physicsQuantities = func() map[string]physicsQuantitySpec { := make(map[string]physicsQuantitySpec) for , := range mjSourcePhysicsMaps { if .Name != "Physics-automatic-bracing-macros" { continue } for , := range .Entries { := physicsQuantitySpec{open: "(", close: ")"} if .Value == "Quantity" { [.Name] = continue } , := .Value.(mjSourceList) if ! || len() < 4 || [0] != "Quantity" { continue } .open, .close, .argument = [1].(string), [2].(string), [3].(bool) if len() > 4 { .named, .variant = [4].(string), [5].(string) } [.Name] = } } return }() // The named Quantity pushes its FnItem before GetArgument and the fresh child // parse. Its recipient may reject that item before either operation executes. type physicsQuantityArgument struct { name, open, close, big string star bool } func ( *physicsQuantityArgument) ( *parser) ([]*mml.Node, error) { , , := .readArgumentAtCursor(.name, false) if != nil { return nil, } := .open + " " + + " " + .close if !.star { if .big != "" { = "\\" + .big + "l" + .open + " " + + " \\" + .big + "r" + .close } else { = "\\left" + .open + " " + + " \\right" + .close } } , := .parseChild() if != nil { return nil, } return unwrapInferred(), nil } func ( *parser) ( string, physicsQuantitySpec, **derivativeAutoOpen) ([]*mml.Node, error) { := .argument && .readStar() := func() rune { for .pos < len(.source) && internalTextSpace(.peekRune()) { .consumeRune() } return .peekRune() } := () := .pos := func() ([]*mml.Node, error) { .pos = return []*mml.Node{.leftRightFenced(.open, forcedRow(nil, false), .close, true)}, nil } := "" if == '\\' { .pos++ = .readControlSequence() switch { case "big", "Big", "bigg", "Bigg": = () default: return () } } if .argument && != '{' { return nil, texError("MissingArgFor", "Missing argument for \\%s", ) } , := map[rune]byte{'(': ')', '[': ']', '{': '}', '|': '|'}[] if ! { return () } if == '{' { , := .open, .close if !.argument { , = "\\{", "\\}" } := &physicsQuantityArgument{name: , open: , close: , big: , star: } if .named != "" { := .token("mi", .named) .TeXClass = mml.TeXClassOp .SetProperty("texClass", mml.TeXClassOp) // NodeFactory token overrides run before Quantity sets its variant. .applyVectorFactory() .Attributes.Set("mathvariant", .variant) .commandNamedFunction = true * = &derivativeAutoOpen{quantity: } return []*mml.Node{}, nil } return .parse() } // Quantity consumes the physical opening and then pushes AutoOpen. The // content remains on the caller's input, font scope and macro budget. .pos++ * = &derivativeAutoOpen{open: byte(), closer: , openingConsumed: true, big: } return nil, nil }