3b1b-manim/manimlib/utils/tex.py

42 lines
1.3 KiB
Python
Raw Normal View History

from __future__ import annotations
2022-12-20 22:35:41 -08:00
import re
from functools import lru_cache
2022-12-29 10:37:46 -08:00
from manimlib.utils.tex_to_symbol_count import TEX_TO_SYMBOL_COUNT
2022-12-20 22:35:41 -08:00
@lru_cache
2022-12-20 22:35:41 -08:00
def num_tex_symbols(tex: str) -> int:
tex = remove_tex_environments(tex)
commands_pattern = r"""
(?P<sqrt>\\sqrt\[[0-9]+\])| # Special sqrt with number
Video work (#2284) * Comment tweak * Directly print traceback Since the shell.showtraceback is giving some issues * Make InteracrtiveSceneEmbed into a class This way it can keep track of it's internal shell; use of get_ipython has a finicky relationship with reloading. * Move remaining checkpoint_paste logic into scene_embed.py This involved making a few context managers for Scene: temp_record, temp_skip, temp_progress_bar, which seem useful in and of themselves. * Change null key to be the empty string * Ensure temporary svg paths for Text are deleted * Remove unused dict_ops.py functions * Remove break_into_partial_movies from file_writer configuration * Rewrite guarantee_existence using Path * Clean up SceneFileWriter It had a number of vestigial functions no longer used, and some setup that could be made more organized. * Remove --save_pngs CLI arg (which did nothing) * Add --subdivide CLI arg * Remove add_extension_if_not_present * Remove get_sorted_integer_files * Have find_file return Path * Minor clean up * Clean up num_tex_symbols * Fix find_file * Minor cleanup for extract_scene.py * Add preview_frame_while_skipping option to scene config * Use shell.showtraceback function * Move keybindings to config, instead of in-place constants * Replace DEGREES -> DEG * Add arg to clear the cache * Separate out full_tex_to_svg from tex_to_svg And only cache to disk the results of full_tex_to_svg. Otherwise, making edits to the tex_templates would not show up without clearing the cache. * Bug fix in handling BlankScene * Make checkpoint_states an instance variable of CheckpointManager As per https://github.com/3b1b/manim/issues/2272 * Move resizing out of Window.focus, and into Window.init_for_scene * Make default output directory "." instead of "" To address https://github.com/3b1b/manim/issues/2261 * Remove input_file_path arg from SceneFileWriter * Use Dict syntax in place of dict for config more consistently across config.py * Simplify get_output_directory * Swap order of preamble and additional preamble * Minor stylistic tweak * Have UnitInterval pass on kwargs to NumberLine * Add simple get_dist function * Have TracedPath always update to the stroke configuration passed in * Have Mobject.match_points apply to all parts of data in pointlike_data_key * Always call Mobject.update upon adding an updater * Add Surface.uv_to_point * Make sure Surface.set_opacity takes in a recurse option * Update num_tex_symbols to account for \{ and \}
2024-12-26 11:35:34 -06:00
(?P<escaped_brace>\\[{}])| # Escaped braces
(?P<cmd>\\[a-zA-Z!,-/:;<>]+) # Regular commands
2022-12-20 22:35:41 -08:00
"""
total = 0
pos = 0
for match in re.finditer(commands_pattern, tex, re.VERBOSE):
# Count normal characters up to this command
total += sum(1 for c in tex[pos:match.start()] if c not in "^{} \n\t_$\\&")
2022-12-29 10:37:46 -08:00
if match.group("sqrt"):
total += len(match.group()) - 5
Video work (#2284) * Comment tweak * Directly print traceback Since the shell.showtraceback is giving some issues * Make InteracrtiveSceneEmbed into a class This way it can keep track of it's internal shell; use of get_ipython has a finicky relationship with reloading. * Move remaining checkpoint_paste logic into scene_embed.py This involved making a few context managers for Scene: temp_record, temp_skip, temp_progress_bar, which seem useful in and of themselves. * Change null key to be the empty string * Ensure temporary svg paths for Text are deleted * Remove unused dict_ops.py functions * Remove break_into_partial_movies from file_writer configuration * Rewrite guarantee_existence using Path * Clean up SceneFileWriter It had a number of vestigial functions no longer used, and some setup that could be made more organized. * Remove --save_pngs CLI arg (which did nothing) * Add --subdivide CLI arg * Remove add_extension_if_not_present * Remove get_sorted_integer_files * Have find_file return Path * Minor clean up * Clean up num_tex_symbols * Fix find_file * Minor cleanup for extract_scene.py * Add preview_frame_while_skipping option to scene config * Use shell.showtraceback function * Move keybindings to config, instead of in-place constants * Replace DEGREES -> DEG * Add arg to clear the cache * Separate out full_tex_to_svg from tex_to_svg And only cache to disk the results of full_tex_to_svg. Otherwise, making edits to the tex_templates would not show up without clearing the cache. * Bug fix in handling BlankScene * Make checkpoint_states an instance variable of CheckpointManager As per https://github.com/3b1b/manim/issues/2272 * Move resizing out of Window.focus, and into Window.init_for_scene * Make default output directory "." instead of "" To address https://github.com/3b1b/manim/issues/2261 * Remove input_file_path arg from SceneFileWriter * Use Dict syntax in place of dict for config more consistently across config.py * Simplify get_output_directory * Swap order of preamble and additional preamble * Minor stylistic tweak * Have UnitInterval pass on kwargs to NumberLine * Add simple get_dist function * Have TracedPath always update to the stroke configuration passed in * Have Mobject.match_points apply to all parts of data in pointlike_data_key * Always call Mobject.update upon adding an updater * Add Surface.uv_to_point * Make sure Surface.set_opacity takes in a recurse option * Update num_tex_symbols to account for \{ and \}
2024-12-26 11:35:34 -06:00
elif match.group("escaped_brace"):
total += 1 # Count escaped brace as one symbol
else:
total += TEX_TO_SYMBOL_COUNT.get(match.group(), 1)
pos = match.end()
# Count remaining characters
total += sum(1 for c in tex[pos:] if c not in "^{} \n\t_$\\&")
return total
def remove_tex_environments(tex: str) -> str:
# Handle \phantom{...} with any content
tex = re.sub(r"\\phantom\{[^}]*\}", "", tex)
# Handle other environment commands
tex = re.sub(r"\\(begin|end)(\{\w+\})?(\{\w+\})?(\[\w+\])?", "", tex)
return tex