Loading...
No commits yet
Not committed History
Blame
_tables.py • 4.5 KB
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# File: src/scitex_writer/_mcp/handlers/_tables.py

"""Table conversion handlers: CSV to LaTeX, LaTeX to CSV."""


import re
from pathlib import Path
from typing import Optional


def csv_to_latex(
    csv_path: str,
    output_path: Optional[str] = None,
    caption: Optional[str] = None,
    label: Optional[str] = None,
    longtable: bool = False,
) -> dict:
    """Convert CSV file to LaTeX table."""
    try:
        import pandas as pd

        csv_file = Path(csv_path)
        if not csv_file.exists():
            return {"success": False, "error": f"CSV file not found: {csv_path}"}

        df = pd.read_csv(csv_file)
        base_name = csv_file.stem

        alignments = []
        for col in df.columns:
            try:
                pd.to_numeric(df[col], errors="raise")
                alignments.append("r")
            except Exception:
                alignments.append("l")

        lines = []
        if longtable:
            lines.append("\\begin{longtable}{" + "".join(alignments) + "}")
        else:
            lines.extend(
                [
                    "\\begin{table}[htbp]",
                    "\\centering",
                    "\\begin{tabular}{" + "".join(alignments) + "}",
                ]
            )

        lines.append("\\toprule")
        lines.append(" & ".join([f"\\textbf{{{col}}}" for col in df.columns]) + " \\\\")
        lines.append("\\midrule")

        for _, row in df.iterrows():
            values = [str(v) if pd.notna(v) else "--" for v in row]
            lines.append(" & ".join(values) + " \\\\")

        lines.append("\\bottomrule")

        if longtable:
            if caption:
                lines.append(f"\\caption{{{caption}}}")
            if label:
                lines.append(f"\\label{{{label}}}")
            lines.append("\\end{longtable}")
        else:
            lines.append("\\end{tabular}")
            if caption:
                lines.append(f"\\caption{{{caption}}}")
            lines.append(f"\\label{{{label or 'tab:' + base_name}}}")
            lines.append("\\end{table}")

        latex_content = "\n".join(lines)
        if output_path:
            Path(output_path).write_text(latex_content, encoding="utf-8")

        return {
            "success": True,
            "latex_content": latex_content,
            "output_path": output_path,
            "rows": len(df),
            "columns": len(df.columns),
        }
    except ImportError:
        return {"success": False, "error": "pandas required: pip install pandas"}
    except Exception as e:
        return {"success": False, "error": str(e)}


def latex_to_csv(
    latex_path: str,
    output_path: Optional[str] = None,
    table_index: int = 0,
) -> dict:
    """Convert LaTeX table to CSV."""
    try:
        import pandas as pd

        latex_file = Path(latex_path)
        if not latex_file.exists():
            return {"success": False, "error": f"LaTeX file not found: {latex_path}"}

        content = latex_file.read_text(encoding="utf-8")
        pattern = r"\\begin\{tabular\}.*?\\end\{tabular\}"
        matches = list(re.finditer(pattern, content, re.DOTALL))

        if not matches:
            return {"success": False, "error": "No tabular environment found"}
        if table_index >= len(matches):
            return {
                "success": False,
                "error": f"Table index {table_index} out of range",
            }

        table_content = matches[table_index].group()
        rows = []
        for line in table_content.split("\\\\"):
            if any(
                x in line
                for x in ["\\begin", "\\end", "\\toprule", "\\midrule", "\\bottomrule"]
            ):
                continue
            cells = [
                re.sub(r"\\[a-zA-Z]+\{([^}]*)\}", r"\1", c.strip())
                for c in line.split("&")
            ]
            if any(cells):
                rows.append(cells)

        if not rows:
            return {"success": False, "error": "Could not parse table"}

        df = pd.DataFrame(rows[1:], columns=rows[0] if rows else None)
        if output_path:
            df.to_csv(output_path, index=False)

        return {
            "success": True,
            "rows": len(df),
            "columns": list(df.columns),
            "preview": df.head(5).to_dict(),
            "output_path": output_path,
        }
    except ImportError:
        return {"success": False, "error": "pandas required: pip install pandas"}
    except Exception as e:
        return {"success": False, "error": str(e)}


# EOF