Add MTex.dirty_select

A more general way to select subparts by tex. Not as reliable as select_parts, but useful in many cases.
This commit is contained in:
Grant Sanderson
2022-12-20 17:02:29 -08:00
parent e357885da0
commit 81e6ab5b1d

View File

@ -209,6 +209,39 @@ class MTex(StringMobject):
):
return self.set_parts_color_by_dict(color_map)
@staticmethod
def n_symbols(tex) -> int:
"""
This function attempts to estimate the number of symbols that
a given string of tex would produce.
No guarantees this is accurate.
"""
count_to_subtrs = [
(0, ["emph", "textbf", "big", "Big", "small", "Small"]),
(2, ["sqrt", "ne"]),
(6, ["underbrace"]),
# Replace all other \expressions (like "\pi") with a single character
# Deliberately put this last.
(1, ["[a-zA-Z]+"])
]
for count, substrs in count_to_subtrs:
# Replace occurances of the given substrings with `count` characters
pattern = "|".join((R"\\" + s for s in substrs ))
tex = re.sub(pattern, "X" * count, tex)
# Ignore various control characters
return len(list(filter(lambda c: c not in "^{} \n\t_", tex)))
def dirty_select(self, substr: str) -> VGroup:
tex = self.get_tex()
result = []
for match in re.finditer(substr.replace("\\", R"\\"), tex):
index = match.start()
start = self.n_symbols(tex[:index])
end = start + self.n_symbols(substr)
result.append(self[start:end])
return VGroup(*result)
def get_tex(self) -> str:
return self.get_string()