Push functionality for selecting unisolated substrings up into StringMobject

This commit is contained in:
Grant Sanderson 2022-12-21 12:47:48 -08:00
parent 10d53c82e1
commit 958c34c705
2 changed files with 30 additions and 35 deletions

View file

@ -201,7 +201,7 @@ class MTex(StringMobject):
def get_parts_by_tex(self, selector: Selector) -> VGroup:
return self.select_parts(selector)
def get_part_by_tex(self, selector: Selector, index: int = 0) -> VGroup:
def get_part_by_tex(self, selector: Selector, index: int = 0) -> VMobject:
return self.select_part(selector, index)
def set_color_by_tex(self, selector: Selector, color: ManimColor):
@ -212,41 +212,13 @@ class MTex(StringMobject):
):
return self.set_parts_color_by_dict(color_map)
def select_parts(self, selector: Selector) -> VGroup:
result = super().select_parts(selector)
if len(result) == 0 and isinstance(selector, str):
log.warning(f"Accessing unisolated substring: {selector}")
return self.dirty_select(selector)
return result
def dirty_select(self, substr: str) -> VGroup:
"""
Tries to pull out substrings based on guessing how
many symbols are associated with a given tex string.
This can fail in cases where the order of symbols does
not match the order in which they're drawn by latex.
For example, `\\underbrace{text}' orders the brace
after the text.
"""
def substr_to_path_count(self, substr: str) -> int:
tex = self.get_tex()
result = []
if len(self) != num_tex_symbols(tex):
log.warning(
f"Estimated size of {tex} does not match true size",
)
for match in re.finditer(substr.replace("\\", R"\\"), tex):
index = match.start()
start = num_tex_symbols(tex[:index])
end = start + num_tex_symbols(substr)
result.append(self[start:end])
return VGroup(*result)
def __getitem__(self, value: int | slice | str | re.Pattern) -> VMobject:
# TODO, maybe move this functionality up to StringMobject
if isinstance(value, (str, re.Pattern)):
return self.select_parts(value)
return super().__getitem__(value)
return num_tex_symbols(substr)
def get_tex(self) -> str:
return self.get_string()

View file

@ -538,13 +538,36 @@ class StringMobject(SVGMobject, ABC):
])
def select_parts(self, selector: Selector) -> VGroup:
return self.build_parts_from_indices_lists(
self.get_submob_indices_lists_by_selector(selector)
)
indices_list = self.get_submob_indices_lists_by_selector(selector)
if indices_list:
return self.build_parts_from_indices_lists(indices_list)
elif isinstance(selector, str):
# Otherwise, try finding substrings which weren't specifically isolated
log.warning("Accessing unisolated substring, results may not be as expected")
return self.select_unisolated_substring(selector)
else:
return VGroup()
def select_part(self, selector: Selector, index: int = 0) -> VGroup:
def __getitem__(self, value: int | slice | Selector) -> VMobject:
if isinstance(value, (int, slice)):
return super().__getitem__(value)
return self.select_parts(value)
def select_part(self, selector: Selector, index: int = 0) -> VMobject:
return self.select_parts(selector)[index]
def substr_to_path_count(self, substr: str) -> int:
return len(re.sub(R"\s", "", substr))
def select_unisolated_substring(self, substr: str) -> VGroup:
result = []
for match in re.finditer(substr.replace("\\", r"\\"), self.string):
index = match.start()
start = self.substr_to_path_count(self.string[:index])
end = start + self.substr_to_path_count(substr)
result.append(self[start:end])
return VGroup(*result)
def set_parts_color(self, selector: Selector, color: ManimColor):
self.select_parts(selector).set_color(color)
return self