TexSoup
repository·master·Indexed 43 days ago
https://github.com/alvinwan/texsoupA fault-tolerant Python 3 package for searching, navigating, and modifying LaTeX documents by treating them as a searchable tree structure. Similar to BeautifulSoup, it parses LaTeX source code into a navigable hierarchy of TexNode objects, including TexCmd, TexEnv, and TexGroup, allowing for programmatic data extraction, format conversion, and document manipulation even with invalid LaTeX sources.
What's inside TexSoup
- TexSoup is a Python 3 library designed for extracting data from $\LaTeX$ files. It parses $\LaTeX$ source code into a navigable, searchable, and modifiable structure similar to BeautifulSoup. A key feature is its ability to handle even invalid $\LaTeX$ sources by turning them into a structured format.
Access environment contents and views
masterTexSoup provides several ways to view the contents of an environment or command. Use these attributes depending on whether you need to reconstruct the source exactly or just extract text.
Attribute Description .childrenNested Tex expressions. Does not include floating text. .contentsNested Tex expressions and text. Does not contain whitespace-only text. .expr.allAll information needed to reconstruct the original source (includes all whitespace). .descendantsTex expressions nested inside of other Tex expressions. .textReturns text from all descendants, stripping all Tex expressions (useful for "detexing"). .stringIf a command has exactly one required argument (or an environment has one child), this returns that argument as a string. Warning: Modifying the
.contentslist in-place will not affect the actual environment structure.from TexSoup import TexSoup tex_doc = """ \begin{document} \section{Hello \textit{world}.} \end{document} """ soup = TexSoup(tex_doc) # Access the string argument of \textit print(soup.textit.string) # Output: 'world' # Access all text without LaTeX commands print(soup.text) # Output: 'Hello world.'Integrate TexSoup with LaTex2Python or Tex2Ipy
masterTexSoup powers several specialized conversion tools:
- LaTex2Python (
tex2py): Uses TexSoup to convert $\LaTeX$ into a document tree, organizing content based on a default or custom hierarchy. - Tex2Ipy: A tool by Prabhu Ramachandran that leverages TexSoup to convert $\LaTeX$ Beamer files into Jupyter notebooks.
- LaTex2Python (
Understand TexSoup data structures
masterTexSoup represents LaTeX documents using a hierarchical tree of specialized data structures found inTexSoup.data. The core building blocks areTexNodeobjects, which can represent various LaTeX elements such as commands, environments, groups, and raw text. This tree structure allows for programmatic traversal and manipulation of LaTeX source code.Explore TexSoup usage examples
masterTexSoup can be used for a variety of $\LaTeX$ processing tasks, ranging from simple reference counting to complex document conversions. Key practical applications include:
- Reference Counting: Counting occurrences of references within a document.
- Format Conversion: Exporting $\LaTeX$ content to JSON or XML formats.
- HTML Rendering: Converting $\LaTeX$ papers (e.g., from arXiv) into rich HTML.
- Data Extraction: Parsing key-value groups and grouping text blocks.
- Document Manipulation: Resolving imports and calculating solution lengths.
Detailed implementation scripts for these use cases are available in the
examples/directory of the repository.Install TexSoup from source
masterTo install from the source repository, clone the repository and use
pip install .from within the directory.$ git clone https://github.com/alvinwan/TexSoup.git $ cd TexSoup $ pip install .Install TexSoup via pip
masterYou can install the
TexSouppackage directly from PyPi usingpip.$ pip install texsoupModify LaTeX environments
masterEnvironments can be modified using text-based or list-based operations:
- Text-only environments: For environments containing only text (such as
verbatimor math environments like\text{...}), use the.stringattribute to replace the content. - Structural modifications: For environments containing multiple elements (like
itemize), you can treat the environment's contents as a list. Use methods like.append(),.remove(),.insert(), and.extend()to add or remove elements (e.g., removing an\itemand then re-inserting it elsewhere).
>>> soup = TexSoup(r'\begin{verbatim}Huehue\end{verbatim}') >>> soup.verbatim.string = 'HUEHUE' >>> soup \begin{verbatim}HUEHUE\end{verbatim} >>> soup = TexSoup(r'$$\text{math}$$') >>> soup.text.string = '' >>> from TexSoup import TexSoup >>> soup = TexSoup(r''' ... \begin{itemize} ... \item Hello ... \item Bye ... \end{itemize}''') >>> tmp = soup.item >>> soup.itemize.remove(soup.item) >>> soup.itemize \begin{itemize} \item Bye \end{itemize} >>> soup.insert(1, tmp) >>> soup \begin{itemize} \item Hello \item Bye \end{itemize}- Text-only environments: For environments containing only text (such as
Navigate up to a parent expression
masterTo find the expression that contains the current one, use the
.parentattribute.from TexSoup import TexSoup tex_doc = """ \begin{document} \section{Hello \textit{world}.} \end{document} """ soup = TexSoup(tex_doc) # Find the parent of the \textit command print(soup.textit.parent) # Output: \section{Hello \textit{world}.}Search for commands and extract text
masterTexSoup provides utilities for searching specific patterns and extracting content:
- Counting occurrences: Use
.count(pattern)to find how many times a specific command or pattern appears. - Finding specific patterns: Use
.find_all(pattern)to locate commands. For example, to find references, search for the\ref{label}pattern. - Line number mapping: Use
soup.char_pos_to_line(cmd.position)to convert a command's character position into a(line, column)tuple. - Text extraction: Access the
.textattribute to get a list of all text segments within the document, effectively stripping LaTeX commands.
# Count and find references count = soup.count(r'\ref{table:synonyms}') for cmd in soup.find_all(r'\ref{table:synonyms}'): print(soup.char_pos_to_line(cmd.position)) # Extract all text all_text = list(soup.text)- Counting occurrences: Use
Parse LaTeX documents with TexSoup
masterTo parse a LaTeX document, pass the LaTeX string to the
TexSoupconstructor. This converts the string into a nested data structure that can be navigated and queried.from TexSoup import TexSoup tex_doc = """ \begin{document} \section{Hello \textit{world}.} \end{document} """ soup = TexSoup(tex_doc)Create a TexSoup from a file or string
masterTo parse a $\LaTeX$ document, you can pass an open filehandle or a raw string into the
TexSoupconstructor. If you only want to compute the data structure without the full soup object, use thereadfunction.To handle $\LaTeX$ documents with syntax errors, use the
toleranceparameter in theTexSoupconstructor. Settingtolerance=1allows TexSoup to make a best-effort guess to parse the content despite errors.from TexSoup import TexSoup, read # From a filehandle with open("main.tex") as f: soup = TexSoup(f) # From a string soup2 = TexSoup(r'\begin{document}Hello world!\end{document}') # Compute data structure only soup3, _ = read(r'\begin{document}Hello world!\end{document}') # With error tolerance soup4 = TexSoup(r'\begin{itemize}\item hullo\end{enumerate}', tolerance=1)