""" LaTeX Builder for fluent construction of LaTeX expressions. This builder provides a fluent interface for constructing complex LaTeX expressions with proper brace balancing and formatting. """ from typing import List, Optional class LaTeXBuilder: """ Fluent builder for constructing LaTeX expressions. This builder provides method chaining for building complex LaTeX expressions with automatic brace balancing and spacing optimization. Examples: Simple fraction: >>> builder = LaTeXBuilder() >>> result = builder.add_fraction("a", "b").build() >>> result '\\frac{a}{b}' Superscript: >>> builder = LaTeXBuilder() >>> result = builder.add_superscript("x", "2").build() >>> result 'x^{2}' Complex expression: >>> builder = LaTeXBuilder() >>> result = (builder ... .add_command("sin", "x") ... .add_text(" + ") ... .add_fraction("1", "2") ... .build()) >>> result '\\sin{x} + \\frac{1}{2}' Nested fractions: >>> builder = LaTeXBuilder() >>> inner = LaTeXBuilder().add_fraction("a", "b").build() >>> result = builder.add_fraction(inner, "c").build() >>> result '\\frac{\\frac{a}{b}}{c}' """ def __init__(self): """Initialize the LaTeX builder.""" self._parts: List[str] = [] def add_text(self, text: str) -> 'LaTeXBuilder': """ Add raw text to the LaTeX expression. Args: text: The text to add (no processing) Returns: Self for method chaining Examples: >>> builder = LaTeXBuilder() >>> builder.add_text("x + y").build() 'x + y' """ if text: self._parts.append(text) return self def add_command(self, cmd: str, arg: str) -> 'LaTeXBuilder': """ Add a LaTeX command with one argument: \\cmd{arg} Args: cmd: The command name (without backslash) arg: The argument content Returns: Self for method chaining Examples: >>> builder = LaTeXBuilder() >>> builder.add_command("sin", "x").build() '\\sin{x}' >>> builder = LaTeXBuilder() >>> builder.add_command("text", "hello").build() '\\text{hello}' """ self._parts.append(f"\\{cmd}{{{arg}}}") return self def add_fraction(self, numerator: str, denominator: str) -> 'LaTeXBuilder': """ Add a fraction: \\frac{numerator}{denominator} Args: numerator: The numerator expression denominator: The denominator expression Returns: Self for method chaining Examples: >>> builder = LaTeXBuilder() >>> builder.add_fraction("a", "b").build() '\\frac{a}{b}' >>> builder = LaTeXBuilder() >>> builder.add_fraction("x + 1", "y - 2").build() '\\frac{x + 1}{y - 2}' """ self._parts.append(f"\\frac{{{numerator}}}{{{denominator}}}") return self def add_superscript(self, base: str, superscript: str) -> 'LaTeXBuilder': """ Add a superscript: base^{superscript} Args: base: The base expression superscript: The superscript expression Returns: Self for method chaining Examples: >>> builder = LaTeXBuilder() >>> builder.add_superscript("x", "2").build() 'x^{2}' >>> builder = LaTeXBuilder() >>> builder.add_superscript("e", "i\\pi").build() 'e^{i\\pi}' """ self._parts.append(f"{base}^{{{superscript}}}") return self def add_subscript(self, base: str, subscript: str) -> 'LaTeXBuilder': """ Add a subscript: base_{subscript} Args: base: The base expression subscript: The subscript expression Returns: Self for method chaining Examples: >>> builder = LaTeXBuilder() >>> builder.add_subscript("x", "1").build() 'x_{1}' >>> builder = LaTeXBuilder() >>> builder.add_subscript("a", "i+j").build() 'a_{i+j}' """ self._parts.append(f"{base}_{{{subscript}}}") return self def add_subscript_superscript(self, base: str, subscript: str, superscript: str) -> 'LaTeXBuilder': """ Add both subscript and superscript: base_{subscript}^{superscript} Args: base: The base expression subscript: The subscript expression superscript: The superscript expression Returns: Self for method chaining Examples: >>> builder = LaTeXBuilder() >>> builder.add_subscript_superscript("x", "1", "2").build() 'x_{1}^{2}' >>> builder = LaTeXBuilder() >>> builder.add_subscript_superscript("R", "i", "j").build() 'R_{i}^{j}' """ self._parts.append(f"{base}_{{{subscript}}}^{{{superscript}}}") return self def add_sqrt(self, content: str, root: Optional[str] = None) -> 'LaTeXBuilder': """ Add a square root or nth root. Args: content: The content under the root root: Optional root index (None for square root) Returns: Self for method chaining Examples: >>> builder = LaTeXBuilder() >>> builder.add_sqrt("x").build() '\\sqrt{x}' >>> builder = LaTeXBuilder() >>> builder.add_sqrt("x", "3").build() '\\sqrt[3]{x}' """ if root: self._parts.append(f"\\sqrt[{root}]{{{content}}}") else: self._parts.append(f"\\sqrt{{{content}}}") return self def add_environment(self, env: str, content: str) -> 'LaTeXBuilder': """ Add a LaTeX environment: \\begin{env}content\\end{env} Args: env: The environment name content: The environment content Returns: Self for method chaining Examples: >>> builder = LaTeXBuilder() >>> builder.add_environment("cases", "x & x > 0 \\\\\\\\ 0 & x \\\\leq 0").build() '\\begin{cases}x & x > 0 \\\\\\\\ 0 & x \\\\leq 0\\end{cases}' """ self._parts.append(f"\\begin{{{env}}}{content}\\end{{{env}}}") return self def add_delimiter_pair(self, left: str, content: str, right: str) -> 'LaTeXBuilder': """ Add delimiter pair: \\left{left}content\\right{right} Args: left: The left delimiter content: The content between delimiters right: The right delimiter Returns: Self for method chaining Examples: >>> builder = LaTeXBuilder() >>> builder.add_delimiter_pair("(", "x + y", ")").build() '\\left(x + y\\right)' >>> builder = LaTeXBuilder() >>> builder.add_delimiter_pair("\\\\{", "a, b, c", "\\\\}").build() '\\left\\\\{a, b, c\\right\\\\}' """ self._parts.append(f"\\left{left}{content}\\right{right}") return self def add_matrix(self, rows: List[List[str]], environment: str = "matrix") -> 'LaTeXBuilder': """ Add a matrix environment. Args: rows: List of rows, each row is a list of cell contents environment: The matrix environment (matrix, pmatrix, bmatrix, etc.) Returns: Self for method chaining Examples: >>> builder = LaTeXBuilder() >>> rows = [["a", "b"], ["c", "d"]] >>> builder.add_matrix(rows, "pmatrix").build() '\\begin{pmatrix}a & b \\\\\\\\ c & d\\end{pmatrix}' """ matrix_content = " \\\\ ".join( " & ".join(cell for cell in row) for row in rows ) self._parts.append(f"\\begin{{{environment}}}{matrix_content}\\end{{{environment}}}") return self def clear(self) -> 'LaTeXBuilder': """ Clear all parts (reset the builder). Returns: Self for method chaining Examples: >>> builder = LaTeXBuilder() >>> builder.add_text("x").clear().add_text("y").build() 'y' """ self._parts.clear() return self def build(self) -> str: """ Build the final LaTeX string. Returns: The constructed LaTeX expression Examples: >>> builder = LaTeXBuilder() >>> builder.add_fraction("a", "b").build() '\\frac{a}{b}' >>> builder = LaTeXBuilder() >>> builder.add_text("x").add_text(" + ").add_text("y").build() 'x + y' """ return "".join(self._parts) def __str__(self) -> str: """String representation (same as build()).""" return self.build() def __repr__(self) -> str: """Debug representation.""" return f"LaTeXBuilder(parts={len(self._parts)})"