__all__ = ["Itemize","ItemizeItem","Enumeration","EnumerationItem"]
from .core import *
from .splitting import *
#enum_styles = {"\\roman":enum_style_roman,"\\Roman":enum_style_Roman,"\\arabic":enum_style_arabic,"\\alph":enum_style_alph,"\\Alph":enum_style_Alph}
[docs]
class ItemizeItem(Element):
"""
Represents an item in a LaTeX itemize environment.
Example:
>>> item = ItemizeItem("First item", None)
>>> print(item.to_string())
• First item
"""
def __init__(self, modifiable_content: str, parent: Element, enum_item: str = "*"):
super().__init__("",parent)
self.enum_item = enum_item
self.children = [Undefined(self.enum_item,self),Undefined(modifiable_content,self)]
[docs]
def label_name(self) -> str:
"""
Returns the label of the item.
Returns:
str: The label.
Example:
>>> item = ItemizeItem("abc", None)
>>> item.label_name()
'•'
"""
return self.enum_item#self.children[0].to_string()
[docs]
def to_string(self) -> str:
"""
Converts the item to a formatted string.
Returns:
str: The formatted item string.
Example:
>>> item = ItemizeItem("abc", None)
>>> isinstance(item.to_string(), str)
True
"""
#string_len = len(self.children[0].to_string()) + 2
out = self.children[0].to_string()+" "
tmp = self.children[1].to_string().lstrip().rstrip()
for i, line in enumerate(tmp.split("\n")):
if i==0:
out += line.strip() + "\n"
else:
out += " " + line.strip() + "\n"
out = out.rstrip()
return out
[docs]
@staticmethod
def position(string: str) -> int:
"""
Finds the position of '\\item' in the string.
Args:
string (str): The input string.
Returns:
int: The position index.
Example:
>>> ItemizeItem.position("\\item abc")
0
"""
return position_of(string,"\\item")
[docs]
@staticmethod
def split_and_create(string: str, parent: Element) -> tuple:
"""
Splits the string on '\\item' and creates an ItemizeItem.
Args:
string (str): The input string.
parent (Element): The parent element.
Returns:
tuple: (pre, ItemizeItem, post)
Example:
>>> pre, item, post = ItemizeItem.split_and_create("\\item abc", None)
>>> isinstance(item, ItemizeItem)
True
"""
pre,content = split_on_next(string,"\\item")
if "\\item" in content:
content,post = split_on_next(content,"\\item")
post = "\\item" + post
else:
post = ""
enum_item = ""
if first_char_brace(content,"["):
enum_item,content = split_on_first_brace(content,"[","]")
elem_out = ItemizeItem(content,parent,enum_item)
return pre,elem_out,post
[docs]
class Itemize(Element):
"""
Represents a LaTeX itemize environment.
Example:
>>> itemize = Itemize("content", None)
>>> isinstance(itemize.to_string(), str)
True
"""
current_index = 0
def __init__(self, modifiable_content: str, parent: Element):
"""
Args:
modifiable_content (str): The content of the itemize.
parent (Element): The parent element.
Example:
>>> itemize = Itemize("abc", None)
>>> isinstance(itemize, Itemize)
True
"""
super().__init__(modifiable_content,parent)
[docs]
def to_string(self) -> str:
"""
Converts the itemize to a formatted string.
Returns:
str: The formatted itemize string.
Example:
>>> itemize = Itemize("abc", None)
>>> isinstance(itemize.to_string(), str)
True
"""
out = "\n"
for child in self.children:
out += child.to_string().rstrip().lstrip() + "\n"
return out
[docs]
@staticmethod
def position(string: str) -> int:
"""
Finds the position of '\\begin{itemize}' in the string.
Args:
string (str): The input string.
Returns:
int: The position index.
Example:
>>> Itemize.position("\\begin{itemize}abc")
0
"""
return position_of(string,"\\begin{itemize}")
[docs]
@staticmethod
def split_and_create(string: str, parent: Element) -> tuple:
"""
Splits the string on itemize environment and creates an Itemize.
Args:
string (str): The input string.
parent (Element): The parent element.
Returns:
tuple: (pre, Itemize, post)
Example:
>>> pre, itemize, post = Itemize.split_and_create("\\begin{itemize}abc\\end{itemize}", None)
>>> isinstance(itemize, Itemize)
True
"""
pre,content,post = begin_end_split(string,"\\begin{itemize}","\\end{itemize}")
elem_out = Itemize(content,parent)
elem_out.expand([ItemizeItem])
return pre,elem_out,post
def parse_label_pattern(pattern: str, counter_value: int) -> str:
"""
Parses LaTeX label patterns and converts them to formatted strings.
Args:
pattern (str): LaTeX label pattern like '\textup{({\sffamily SF\arabic*})}'
counter_value (int): Current counter value
Returns:
str: Formatted label string
Example:
>>> parse_label_pattern('\\textup{({\\sffamily SF\\arabic*})}', 1)
'SF1'
"""
result = pattern
# Remove common LaTeX formatting commands
formatting_commands = [
'\\sffamily', '\\bfseries', '\\itshape', '\\rmfamily',
'\\small', '\\large', '\\Large', '\\LARGE', '\\huge', '\\Huge',
'\\textup', '\\textbf', '\\textit', '\\textrm', '\\textsf', '\\texttt'
]
for cmd in formatting_commands:
result = result.replace(cmd, '')
result = result.replace('{', '').replace('}', '')
counter_patterns = {
'\\arabic*': str(counter_value),
'\\roman*': to_roman_lower(counter_value),
'\\Roman*': to_roman_upper(counter_value),
'\\alph*': to_alpha_lower(counter_value),
'\\Alph*': to_alpha_upper(counter_value)
}
for pattern_key, replacement in counter_patterns.items():
result = result.replace(pattern_key, replacement)
return result.strip()
def to_roman_lower(num: int) -> str:
"""Convert integer to lowercase Roman numeral."""
values = [1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1]
symbols = ['m', 'cm', 'd', 'cd', 'c', 'xc', 'l', 'xl', 'x', 'ix', 'v', 'iv', 'i']
result = ''
for i in range(len(values)):
count = num // values[i]
result += symbols[i] * count
num -= values[i] * count
return result
def to_roman_upper(num: int) -> str:
"""Convert integer to uppercase Roman numeral."""
return to_roman_lower(num).upper()
def to_alpha_lower(num: int) -> str:
"""Convert integer to lowercase letter (1=a, 2=b, etc.)."""
if num <= 0 or num > 26:
return str(num)
return chr(ord('a') + num - 1)
def to_alpha_upper(num: int) -> str:
"""Convert integer to uppercase letter (1=A, 2=B, etc.)."""
return to_alpha_lower(num).upper()
[docs]
class EnumerationItem(Element):
"""
Represents an item in a LaTeX enumerate environment.
Example:
>>> enum_item = EnumerationItem("First", None)
>>> isinstance(enum_item.to_string(), str)
True
"""
def __init__(self, modifiable_content: str, parent: Element, enum_item: str = None):
"""
Args:
modifiable_content (str): The content of the item.
parent (Element): The parent element.
enum_item (str, optional): The label for the item.
Example:
>>> enum_item = EnumerationItem("abc", None)
>>> enum_item.label
''
"""
super().__init__("",parent)
modifiable_content = modifiable_content.lstrip().rstrip()
self.enum_item = ""
if enum_item is None:
enumeration: Enumeration = self.search_class(Enumeration)
self.enum_item = enumeration.generate_enum_item()
else:
self.enum_item = enum_item
self.label = None
if modifiable_content.startswith("\\label"):
label,modifiable_content = split_on_first_brace(modifiable_content[len("\\label"):],"{" ,"}")
self.label = label_call(label,LabelType.ENUMERATION_ITEM)
self.children = [Undefined(self.enum_item.strip(), self), Undefined(modifiable_content, self)]
[docs]
def to_string(self) -> str:
out = "\n\n"
if self.label is not None:
out += "(" + self.label + ")=\n"
out += self.children[0].to_string().strip()+"\n: "
tmp = self.children[1].to_string().strip()
for i, line in enumerate(tmp.split("\n")):
if i==0:
out += line.strip() + "\n"
else:
out += " " + line.strip() + "\n"
out = out.rstrip()
return out
[docs]
@staticmethod
def position(string: str) -> int:
"""
Finds the position of '\\item' in the string.
Args:
string (str): The input string.
Returns:
int: The position index.
Example:
>>> EnumerationItem.position("\\item abc")
0
"""
return position_of(string,"\\item")
[docs]
@staticmethod
def split_and_create(string: str, parent: Element) -> tuple:
"""
Splits the string on '\\item' and creates an EnumerationItem.
Args:
string (str): The input string.
parent (Element): The parent element.
Returns:
tuple: (pre, EnumerationItem, post)
Example:
>>> pre, enum_item, post = EnumerationItem.split_and_create("\\item abc", None)
>>> isinstance(enum_item, EnumerationItem)
True
"""
pre,content = split_on_next(string,"\\item")
if "\\item" in content:
content,post = split_on_next(content,"\\item")
post = "\\item" + post
else:
post = ""
content = content.lstrip()
enum_item = None
if first_char_brace(content,"["):
enum_item,content = split_on_first_brace(content,"[","]")
elem_out = EnumerationItem(content,parent,enum_item)
return pre,elem_out,post
[docs]
class Enumeration(Element):
"""
Represents a LaTeX enumerate environment.
Example:
>>> enum = Enumeration("content", None, enum_style_arabic, "(", ")")
>>> isinstance(enum.to_string(), str)
True
"""
def __init__(self, modifiable_content: str, parent: Element,start,label_part):
"""
Example:
>>> enum = Enumeration("abc", None, enum_style_arabic, "(", ")")
>>> isinstance(enum, Enumeration)
True
"""
super().__init__(modifiable_content,parent)
self.current_index = start
self.label_part = label_part
[docs]
def generate_enum_item(self) -> str:
if self.label_part is not None:
out = parse_label_pattern(self.label_part,self.current_index)
self.current_index += 1
return out
out = str(self.current_index) + "."
self.current_index += 1
return out
[docs]
def to_string(self) -> str:
"""
Converts the enumerate to a formatted string.
Returns:
str: The formatted enumerate string.
Example:
>>> enum = Enumeration("abc", None, enum_style_arabic, "(", ")")
>>> isinstance(enum.to_string(), str)
True
"""
out = "\n"
for child in self.children:
out += child.to_string().rstrip().lstrip() + "\n"
return out
[docs]
@staticmethod
def position(string: str) -> int:
"""
Finds the position of '\\begin{enumerate}' in the string.
Args:
string (str): The input string.
Returns:
int: The position index.
Example:
>>> Enumeration.position("\\begin{enumerate}abc")
0
"""
return position_of(string,"\\begin{enumerate}")
[docs]
@staticmethod
def split_and_create(string: str, parent: Element) -> tuple:
"""
Splits the string on enumerate environment and creates an Enumeration.
Args:
string (str): The input string.
parent (Element): The parent element.
Returns:
tuple: (pre, Enumeration, post)
Example:
>>> pre, enum, post = Enumeration.split_and_create("\\begin{enumerate}abc\\end{enumerate}", None)
>>> isinstance(enum, Enumeration)
True
"""
pre,content,post = begin_end_split(string,"\\begin{enumerate}","\\end{enumerate}")
content = content.lstrip().rstrip()
start = 1
label_part = None
if content.startswith("["):
_pre,_content,_post = begin_end_split(content,"[","]")
content = _post.lstrip().rstrip()
if "label" in _content:
label_part = _content.split("label")[1].split("=")[1].strip().split(",")[0].strip()
# Here you could implement parsing of label_str to set style_func, left, right
if "start" in _content:
start_str = _content.split("start")[1].split("=")[1].strip().split(",")[0].strip()
try:
start = int(start_str)
except:
start = 1
elem_out = Enumeration(content,parent,start,label_part)
elem_out.expand([EnumerationItem])
return pre,elem_out,post
def get_all_filters():
"""
Returns all filter classes for enum environments.
Returns:
list: List of filter classes.
Example:
>>> filters = get_all_filters()
>>> isinstance(filters, list)
True
"""
return [Itemize, Enumeration]