We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
ManimDirective needs a `ref_methods`
Some of the current documentation uses `:ref_functions:` in the example documentation which is supposed to link to the proper function; however, it is often the case that the function is actually a method. In these instances, a ref_methods would be appropriate to have, and the usage of this in the examples should be updated accordingly.

See https://github.com/ManimCommunity/manim/blob/master/docs/source/manim_directive.py#L133-L135

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `docs/source/manim_directive.py`
Content:
```
1 r"""
2 A directive for including Manim videos in a Sphinx document
3 ===========================================================
4 
5 When rendering the HTML documentation, the ``.. manim::`` directive
6 implemented here allows to include rendered videos.
7 
8 Its basic usage that allows processing **inline content**
9 looks as follows::
10 
11     .. manim:: MyScene
12 
13         class MyScene(Scene):
14             def construct(self):
15                 ...
16 
17 It is required to pass the name of the class representing the
18 scene to be rendered to the directive.
19 
20 As a second application, the directive can also be used to
21 render scenes that are defined within doctests, for example::
22 
23     .. manim:: DirectiveDoctestExample
24         :ref_classes: Dot
25 
26         >>> dot = Dot(color=RED)
27         >>> dot.color
28         <Color #fc6255>
29         >>> class DirectiveDoctestExample(Scene):
30         ...     def construct(self):
31         ...         self.play(Create(dot))
32 
33 
34 Options
35 -------
36 
37 Options can be passed as follows::
38 
39     .. manim:: <Class name>
40         :<option name>: <value>
41 
42 The following configuration options are supported by the
43 directive:
44 
45     hide_source
46         If this flag is present without argument,
47         the source code is not displayed above the rendered video.
48 
49     quality : {'low', 'medium', 'high', 'fourk'}
50         Controls render quality of the video, in analogy to
51         the corresponding command line flags.
52 
53     save_as_gif
54         If this flag is present without argument,
55         the scene is rendered as a gif.
56 
57     save_last_frame
58         If this flag is present without argument,
59         an image representing the last frame of the scene will
60         be rendered and displayed, instead of a video.
61 
62     ref_classes
63         A list of classes, separated by spaces, that is
64         rendered in a reference block after the source code.
65 
66     ref_functions
67         A list of functions and methods, separated by spaces,
68         that is rendered in a reference block after the source code.
69 
70 """
71 from docutils import nodes
72 from docutils.parsers.rst import directives, Directive
73 from docutils.statemachine import StringList
74 
75 import jinja2
76 import os
77 from os.path import relpath
78 from pathlib import Path
79 from typing import List
80 
81 import shutil
82 
83 from manim import QUALITIES
84 
85 classnamedict = {}
86 
87 
88 class skip_manim_node(nodes.Admonition, nodes.Element):
89     pass
90 
91 
92 def visit(self, node, name=""):
93     self.visit_admonition(node, name)
94 
95 
96 def depart(self, node):
97     self.depart_admonition(node)
98 
99 
100 def process_name_list(option_input: str, reference_type: str) -> List[str]:
101     r"""Reformats a string of space separated class names
102     as a list of strings containing valid Sphinx references.
103 
104     Tests
105     -----
106 
107     ::
108 
109         >>> process_name_list("Tex TexTemplate", "class")
110         [":class:`~.Tex`", ":class:`~.TexTemplate`"]
111         >>> process_name_list("Scene.play Mobject.rotate", "func")
112         [":func:`~.Scene.play`", ":func:`~.Mobject.rotate`"]
113     """
114     return [f":{reference_type}:`~.{name}`" for name in option_input.split()]
115 
116 
117 class ManimDirective(Directive):
118     r"""The manim directive, rendering videos while building
119     the documentation.
120 
121     See the module docstring for documentation.
122     """
123     has_content = True
124     required_arguments = 1
125     optional_arguments = 0
126     option_spec = {
127         "hide_source": bool,
128         "quality": lambda arg: directives.choice(
129             arg, ("low", "medium", "high", "fourk")
130         ),
131         "save_as_gif": bool,
132         "save_last_frame": bool,
133         "ref_modules": lambda arg: process_name_list(arg, "mod"),
134         "ref_classes": lambda arg: process_name_list(arg, "class"),
135         "ref_functions": lambda arg: process_name_list(arg, "func"),
136     }
137     final_argument_whitespace = True
138 
139     def run(self):
140         if "skip-manim" in self.state.document.settings.env.app.builder.tags.tags:
141             node = skip_manim_node()
142             self.state.nested_parse(
143                 StringList(self.content[0]), self.content_offset, node
144             )
145             return [node]
146 
147         from manim import config
148 
149         global classnamedict
150 
151         clsname = self.arguments[0]
152         if clsname not in classnamedict:
153             classnamedict[clsname] = 1
154         else:
155             classnamedict[clsname] += 1
156 
157         hide_source = "hide_source" in self.options
158         save_as_gif = "save_as_gif" in self.options
159         save_last_frame = "save_last_frame" in self.options
160         assert not (save_as_gif and save_last_frame)
161 
162         ref_content = (
163             self.options.get("ref_modules", [])
164             + self.options.get("ref_classes", [])
165             + self.options.get("ref_functions", [])
166         )
167         if ref_content:
168             ref_block = f"""
169 .. admonition:: Example References
170     :class: example-reference
171 
172     {' '.join(ref_content)}"""
173         else:
174             ref_block = ""
175 
176         if "quality" in self.options:
177             quality = f'{self.options["quality"]}_quality'
178         else:
179             quality = "example_quality"
180         frame_rate = QUALITIES[quality]["frame_rate"]
181         pixel_height = QUALITIES[quality]["pixel_height"]
182         pixel_width = QUALITIES[quality]["pixel_width"]
183         qualitydir = f"{pixel_height}p{frame_rate}"
184 
185         state_machine = self.state_machine
186         document = state_machine.document
187 
188         source_file_name = document.attributes["source"]
189         source_rel_name = relpath(source_file_name, setup.confdir)
190         source_rel_dir = os.path.dirname(source_rel_name)
191         while source_rel_dir.startswith(os.path.sep):
192             source_rel_dir = source_rel_dir[1:]
193 
194         dest_dir = os.path.abspath(
195             os.path.join(setup.app.builder.outdir, source_rel_dir)
196         )
197         if not os.path.exists(dest_dir):
198             os.makedirs(dest_dir)
199 
200         source_block = [
201             ".. code-block:: python",
202             "",
203             *["    " + line for line in self.content],
204         ]
205         source_block = "\n".join(source_block)
206 
207         config.media_dir = Path(setup.confdir) / "media"
208         config.images_dir = "{media_dir}/images"
209         config.video_dir = "{media_dir}/videos/{quality}"
210         output_file = f"{clsname}-{classnamedict[clsname]}"
211         config.assets_dir = Path("_static")
212 
213         config_code = [
214             f'config["frame_rate"] = {frame_rate}',
215             f'config["pixel_height"] = {pixel_height}',
216             f'config["pixel_width"] = {pixel_width}',
217             f'config["save_last_frame"] = {save_last_frame}',
218             f'config["save_as_gif"] = {save_as_gif}',
219             f'config["output_file"] = r"{output_file}"',
220         ]
221 
222         user_code = self.content
223         if user_code[0].startswith(">>> "):  # check whether block comes from doctest
224             user_code = [
225                 line[4:] for line in user_code if line.startswith((">>> ", "... "))
226             ]
227 
228         code = [
229             "from manim import *",
230             *config_code,
231             *user_code,
232             f"{clsname}().render()",
233         ]
234         exec("\n".join(code), globals())
235 
236         # copy video file to output directory
237         if not (save_as_gif or save_last_frame):
238             filename = f"{output_file}.mp4"
239             filesrc = config.get_dir("video_dir") / filename
240             destfile = os.path.join(dest_dir, filename)
241             shutil.copyfile(filesrc, destfile)
242         elif save_as_gif:
243             filename = f"{output_file}.gif"
244             filesrc = config.get_dir("video_dir") / filename
245         elif save_last_frame:
246             filename = f"{output_file}.png"
247             filesrc = config.get_dir("images_dir") / filename
248         else:
249             raise ValueError("Invalid combination of render flags received.")
250 
251         rendered_template = jinja2.Template(TEMPLATE).render(
252             clsname=clsname,
253             clsname_lowercase=clsname.lower(),
254             hide_source=hide_source,
255             filesrc_rel=os.path.relpath(filesrc, setup.confdir),
256             output_file=output_file,
257             save_last_frame=save_last_frame,
258             save_as_gif=save_as_gif,
259             source_block=source_block,
260             ref_block=ref_block,
261         )
262         state_machine.insert_input(
263             rendered_template.split("\n"), source=document.attributes["source"]
264         )
265 
266         return []
267 
268 
269 def setup(app):
270     import manim
271 
272     app.add_node(skip_manim_node, html=(visit, depart))
273 
274     setup.app = app
275     setup.config = app.config
276     setup.confdir = app.confdir
277 
278     app.add_directive("manim", ManimDirective)
279 
280     metadata = {"parallel_read_safe": False, "parallel_write_safe": True}
281     return metadata
282 
283 
284 TEMPLATE = r"""
285 {% if not hide_source %}
286 .. raw:: html
287 
288     <div class="manim-example">
289 
290 {% endif %}
291 
292 {% if not (save_as_gif or save_last_frame) %}
293 .. raw:: html
294 
295     <video id="{{ clsname_lowercase }}" class="manim-video" controls loop autoplay src="./{{ output_file }}.mp4"></video>
296 {% elif save_as_gif %}
297 .. image:: /{{ filesrc_rel }}
298     :align: center
299     :name: {{ clsname_lowercase }}
300 {% elif save_last_frame %}
301 .. image:: /{{ filesrc_rel }}
302     :align: center
303     :name: {{ clsname_lowercase }}
304 {% endif %}
305 {% if not hide_source %}
306 .. raw:: html
307 
308     <h5 class="example-header">{{ clsname }}<a class="headerlink" href="#{{ clsname_lowercase }}">¶</a></h5>
309 
310 {{ source_block }}
311 {{ ref_block }}
312 {% endif %}
313 
314 .. raw:: html
315 
316     </div>
317 """
318
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/docs/source/manim_directive.py b/docs/source/manim_directive.py
--- a/docs/source/manim_directive.py
+++ b/docs/source/manim_directive.py
@@ -64,7 +64,11 @@
         rendered in a reference block after the source code.
 
     ref_functions
-        A list of functions and methods, separated by spaces,
+        A list of functions, separated by spaces,
+        that is rendered in a reference block after the source code.
+
+    ref_methods
+        A list of methods, separated by spaces,
         that is rendered in a reference block after the source code.
 
 """
@@ -133,6 +137,7 @@
         "ref_modules": lambda arg: process_name_list(arg, "mod"),
         "ref_classes": lambda arg: process_name_list(arg, "class"),
         "ref_functions": lambda arg: process_name_list(arg, "func"),
+        "ref_methods": lambda arg: process_name_list(arg, "meth"),
     }
     final_argument_whitespace = True
 
@@ -163,6 +168,7 @@
             self.options.get("ref_modules", [])
             + self.options.get("ref_classes", [])
             + self.options.get("ref_functions", [])
+            + self.options.get("ref_methods", [])
         )
         if ref_content:
             ref_block = f"""

{"golden_diff": "diff --git a/docs/source/manim_directive.py b/docs/source/manim_directive.py\n--- a/docs/source/manim_directive.py\n+++ b/docs/source/manim_directive.py\n@@ -64,7 +64,11 @@\n         rendered in a reference block after the source code.\n \n     ref_functions\n-        A list of functions and methods, separated by spaces,\n+        A list of functions, separated by spaces,\n+        that is rendered in a reference block after the source code.\n+\n+    ref_methods\n+        A list of methods, separated by spaces,\n         that is rendered in a reference block after the source code.\n \n \"\"\"\n@@ -133,6 +137,7 @@\n         \"ref_modules\": lambda arg: process_name_list(arg, \"mod\"),\n         \"ref_classes\": lambda arg: process_name_list(arg, \"class\"),\n         \"ref_functions\": lambda arg: process_name_list(arg, \"func\"),\n+        \"ref_methods\": lambda arg: process_name_list(arg, \"meth\"),\n     }\n     final_argument_whitespace = True\n \n@@ -163,6 +168,7 @@\n             self.options.get(\"ref_modules\", [])\n             + self.options.get(\"ref_classes\", [])\n             + self.options.get(\"ref_functions\", [])\n+            + self.options.get(\"ref_methods\", [])\n         )\n         if ref_content:\n             ref_block = f\"\"\"\n", "issue": "ManimDirective needs a `ref_methods`\nSome of the current documentation uses `:ref_functions:` in the example documentation which is supposed to link to the proper function; however, it is often the case that the function is actually a method. In these instances, a ref_methods would be appropriate to have, and the usage of this in the examples should be updated accordingly.\r\n\r\nSee https://github.com/ManimCommunity/manim/blob/master/docs/source/manim_directive.py#L133-L135\n", "before_files": [{"content": "r\"\"\"\nA directive for including Manim videos in a Sphinx document\n===========================================================\n\nWhen rendering the HTML documentation, the ``.. manim::`` directive\nimplemented here allows to include rendered videos.\n\nIts basic usage that allows processing **inline content**\nlooks as follows::\n\n    .. manim:: MyScene\n\n        class MyScene(Scene):\n            def construct(self):\n                ...\n\nIt is required to pass the name of the class representing the\nscene to be rendered to the directive.\n\nAs a second application, the directive can also be used to\nrender scenes that are defined within doctests, for example::\n\n    .. manim:: DirectiveDoctestExample\n        :ref_classes: Dot\n\n        >>> dot = Dot(color=RED)\n        >>> dot.color\n        <Color #fc6255>\n        >>> class DirectiveDoctestExample(Scene):\n        ...     def construct(self):\n        ...         self.play(Create(dot))\n\n\nOptions\n-------\n\nOptions can be passed as follows::\n\n    .. manim:: <Class name>\n        :<option name>: <value>\n\nThe following configuration options are supported by the\ndirective:\n\n    hide_source\n        If this flag is present without argument,\n        the source code is not displayed above the rendered video.\n\n    quality : {'low', 'medium', 'high', 'fourk'}\n        Controls render quality of the video, in analogy to\n        the corresponding command line flags.\n\n    save_as_gif\n        If this flag is present without argument,\n        the scene is rendered as a gif.\n\n    save_last_frame\n        If this flag is present without argument,\n        an image representing the last frame of the scene will\n        be rendered and displayed, instead of a video.\n\n    ref_classes\n        A list of classes, separated by spaces, that is\n        rendered in a reference block after the source code.\n\n    ref_functions\n        A list of functions and methods, separated by spaces,\n        that is rendered in a reference block after the source code.\n\n\"\"\"\nfrom docutils import nodes\nfrom docutils.parsers.rst import directives, Directive\nfrom docutils.statemachine import StringList\n\nimport jinja2\nimport os\nfrom os.path import relpath\nfrom pathlib import Path\nfrom typing import List\n\nimport shutil\n\nfrom manim import QUALITIES\n\nclassnamedict = {}\n\n\nclass skip_manim_node(nodes.Admonition, nodes.Element):\n    pass\n\n\ndef visit(self, node, name=\"\"):\n    self.visit_admonition(node, name)\n\n\ndef depart(self, node):\n    self.depart_admonition(node)\n\n\ndef process_name_list(option_input: str, reference_type: str) -> List[str]:\n    r\"\"\"Reformats a string of space separated class names\n    as a list of strings containing valid Sphinx references.\n\n    Tests\n    -----\n\n    ::\n\n        >>> process_name_list(\"Tex TexTemplate\", \"class\")\n        [\":class:`~.Tex`\", \":class:`~.TexTemplate`\"]\n        >>> process_name_list(\"Scene.play Mobject.rotate\", \"func\")\n        [\":func:`~.Scene.play`\", \":func:`~.Mobject.rotate`\"]\n    \"\"\"\n    return [f\":{reference_type}:`~.{name}`\" for name in option_input.split()]\n\n\nclass ManimDirective(Directive):\n    r\"\"\"The manim directive, rendering videos while building\n    the documentation.\n\n    See the module docstring for documentation.\n    \"\"\"\n    has_content = True\n    required_arguments = 1\n    optional_arguments = 0\n    option_spec = {\n        \"hide_source\": bool,\n        \"quality\": lambda arg: directives.choice(\n            arg, (\"low\", \"medium\", \"high\", \"fourk\")\n        ),\n        \"save_as_gif\": bool,\n        \"save_last_frame\": bool,\n        \"ref_modules\": lambda arg: process_name_list(arg, \"mod\"),\n        \"ref_classes\": lambda arg: process_name_list(arg, \"class\"),\n        \"ref_functions\": lambda arg: process_name_list(arg, \"func\"),\n    }\n    final_argument_whitespace = True\n\n    def run(self):\n        if \"skip-manim\" in self.state.document.settings.env.app.builder.tags.tags:\n            node = skip_manim_node()\n            self.state.nested_parse(\n                StringList(self.content[0]), self.content_offset, node\n            )\n            return [node]\n\n        from manim import config\n\n        global classnamedict\n\n        clsname = self.arguments[0]\n        if clsname not in classnamedict:\n            classnamedict[clsname] = 1\n        else:\n            classnamedict[clsname] += 1\n\n        hide_source = \"hide_source\" in self.options\n        save_as_gif = \"save_as_gif\" in self.options\n        save_last_frame = \"save_last_frame\" in self.options\n        assert not (save_as_gif and save_last_frame)\n\n        ref_content = (\n            self.options.get(\"ref_modules\", [])\n            + self.options.get(\"ref_classes\", [])\n            + self.options.get(\"ref_functions\", [])\n        )\n        if ref_content:\n            ref_block = f\"\"\"\n.. admonition:: Example References\n    :class: example-reference\n\n    {' '.join(ref_content)}\"\"\"\n        else:\n            ref_block = \"\"\n\n        if \"quality\" in self.options:\n            quality = f'{self.options[\"quality\"]}_quality'\n        else:\n            quality = \"example_quality\"\n        frame_rate = QUALITIES[quality][\"frame_rate\"]\n        pixel_height = QUALITIES[quality][\"pixel_height\"]\n        pixel_width = QUALITIES[quality][\"pixel_width\"]\n        qualitydir = f\"{pixel_height}p{frame_rate}\"\n\n        state_machine = self.state_machine\n        document = state_machine.document\n\n        source_file_name = document.attributes[\"source\"]\n        source_rel_name = relpath(source_file_name, setup.confdir)\n        source_rel_dir = os.path.dirname(source_rel_name)\n        while source_rel_dir.startswith(os.path.sep):\n            source_rel_dir = source_rel_dir[1:]\n\n        dest_dir = os.path.abspath(\n            os.path.join(setup.app.builder.outdir, source_rel_dir)\n        )\n        if not os.path.exists(dest_dir):\n            os.makedirs(dest_dir)\n\n        source_block = [\n            \".. code-block:: python\",\n            \"\",\n            *[\"    \" + line for line in self.content],\n        ]\n        source_block = \"\\n\".join(source_block)\n\n        config.media_dir = Path(setup.confdir) / \"media\"\n        config.images_dir = \"{media_dir}/images\"\n        config.video_dir = \"{media_dir}/videos/{quality}\"\n        output_file = f\"{clsname}-{classnamedict[clsname]}\"\n        config.assets_dir = Path(\"_static\")\n\n        config_code = [\n            f'config[\"frame_rate\"] = {frame_rate}',\n            f'config[\"pixel_height\"] = {pixel_height}',\n            f'config[\"pixel_width\"] = {pixel_width}',\n            f'config[\"save_last_frame\"] = {save_last_frame}',\n            f'config[\"save_as_gif\"] = {save_as_gif}',\n            f'config[\"output_file\"] = r\"{output_file}\"',\n        ]\n\n        user_code = self.content\n        if user_code[0].startswith(\">>> \"):  # check whether block comes from doctest\n            user_code = [\n                line[4:] for line in user_code if line.startswith((\">>> \", \"... \"))\n            ]\n\n        code = [\n            \"from manim import *\",\n            *config_code,\n            *user_code,\n            f\"{clsname}().render()\",\n        ]\n        exec(\"\\n\".join(code), globals())\n\n        # copy video file to output directory\n        if not (save_as_gif or save_last_frame):\n            filename = f\"{output_file}.mp4\"\n            filesrc = config.get_dir(\"video_dir\") / filename\n            destfile = os.path.join(dest_dir, filename)\n            shutil.copyfile(filesrc, destfile)\n        elif save_as_gif:\n            filename = f\"{output_file}.gif\"\n            filesrc = config.get_dir(\"video_dir\") / filename\n        elif save_last_frame:\n            filename = f\"{output_file}.png\"\n            filesrc = config.get_dir(\"images_dir\") / filename\n        else:\n            raise ValueError(\"Invalid combination of render flags received.\")\n\n        rendered_template = jinja2.Template(TEMPLATE).render(\n            clsname=clsname,\n            clsname_lowercase=clsname.lower(),\n            hide_source=hide_source,\n            filesrc_rel=os.path.relpath(filesrc, setup.confdir),\n            output_file=output_file,\n            save_last_frame=save_last_frame,\n            save_as_gif=save_as_gif,\n            source_block=source_block,\n            ref_block=ref_block,\n        )\n        state_machine.insert_input(\n            rendered_template.split(\"\\n\"), source=document.attributes[\"source\"]\n        )\n\n        return []\n\n\ndef setup(app):\n    import manim\n\n    app.add_node(skip_manim_node, html=(visit, depart))\n\n    setup.app = app\n    setup.config = app.config\n    setup.confdir = app.confdir\n\n    app.add_directive(\"manim\", ManimDirective)\n\n    metadata = {\"parallel_read_safe\": False, \"parallel_write_safe\": True}\n    return metadata\n\n\nTEMPLATE = r\"\"\"\n{% if not hide_source %}\n.. raw:: html\n\n    <div class=\"manim-example\">\n\n{% endif %}\n\n{% if not (save_as_gif or save_last_frame) %}\n.. raw:: html\n\n    <video id=\"{{ clsname_lowercase }}\" class=\"manim-video\" controls loop autoplay src=\"./{{ output_file }}.mp4\"></video>\n{% elif save_as_gif %}\n.. image:: /{{ filesrc_rel }}\n    :align: center\n    :name: {{ clsname_lowercase }}\n{% elif save_last_frame %}\n.. image:: /{{ filesrc_rel }}\n    :align: center\n    :name: {{ clsname_lowercase }}\n{% endif %}\n{% if not hide_source %}\n.. raw:: html\n\n    <h5 class=\"example-header\">{{ clsname }}<a class=\"headerlink\" href=\"#{{ clsname_lowercase }}\">\u00b6</a></h5>\n\n{{ source_block }}\n{{ ref_block }}\n{% endif %}\n\n.. raw:: html\n\n    </div>\n\"\"\"\n", "path": "docs/source/manim_directive.py"}], "after_files": [{"content": "r\"\"\"\nA directive for including Manim videos in a Sphinx document\n===========================================================\n\nWhen rendering the HTML documentation, the ``.. manim::`` directive\nimplemented here allows to include rendered videos.\n\nIts basic usage that allows processing **inline content**\nlooks as follows::\n\n    .. manim:: MyScene\n\n        class MyScene(Scene):\n            def construct(self):\n                ...\n\nIt is required to pass the name of the class representing the\nscene to be rendered to the directive.\n\nAs a second application, the directive can also be used to\nrender scenes that are defined within doctests, for example::\n\n    .. manim:: DirectiveDoctestExample\n        :ref_classes: Dot\n\n        >>> dot = Dot(color=RED)\n        >>> dot.color\n        <Color #fc6255>\n        >>> class DirectiveDoctestExample(Scene):\n        ...     def construct(self):\n        ...         self.play(Create(dot))\n\n\nOptions\n-------\n\nOptions can be passed as follows::\n\n    .. manim:: <Class name>\n        :<option name>: <value>\n\nThe following configuration options are supported by the\ndirective:\n\n    hide_source\n        If this flag is present without argument,\n        the source code is not displayed above the rendered video.\n\n    quality : {'low', 'medium', 'high', 'fourk'}\n        Controls render quality of the video, in analogy to\n        the corresponding command line flags.\n\n    save_as_gif\n        If this flag is present without argument,\n        the scene is rendered as a gif.\n\n    save_last_frame\n        If this flag is present without argument,\n        an image representing the last frame of the scene will\n        be rendered and displayed, instead of a video.\n\n    ref_classes\n        A list of classes, separated by spaces, that is\n        rendered in a reference block after the source code.\n\n    ref_functions\n        A list of functions, separated by spaces,\n        that is rendered in a reference block after the source code.\n\n    ref_methods\n        A list of methods, separated by spaces,\n        that is rendered in a reference block after the source code.\n\n\"\"\"\nfrom docutils import nodes\nfrom docutils.parsers.rst import directives, Directive\nfrom docutils.statemachine import StringList\n\nimport jinja2\nimport os\nfrom os.path import relpath\nfrom pathlib import Path\nfrom typing import List\n\nimport shutil\n\nfrom manim import QUALITIES\n\nclassnamedict = {}\n\n\nclass skip_manim_node(nodes.Admonition, nodes.Element):\n    pass\n\n\ndef visit(self, node, name=\"\"):\n    self.visit_admonition(node, name)\n\n\ndef depart(self, node):\n    self.depart_admonition(node)\n\n\ndef process_name_list(option_input: str, reference_type: str) -> List[str]:\n    r\"\"\"Reformats a string of space separated class names\n    as a list of strings containing valid Sphinx references.\n\n    Tests\n    -----\n\n    ::\n\n        >>> process_name_list(\"Tex TexTemplate\", \"class\")\n        [\":class:`~.Tex`\", \":class:`~.TexTemplate`\"]\n        >>> process_name_list(\"Scene.play Mobject.rotate\", \"func\")\n        [\":func:`~.Scene.play`\", \":func:`~.Mobject.rotate`\"]\n    \"\"\"\n    return [f\":{reference_type}:`~.{name}`\" for name in option_input.split()]\n\n\nclass ManimDirective(Directive):\n    r\"\"\"The manim directive, rendering videos while building\n    the documentation.\n\n    See the module docstring for documentation.\n    \"\"\"\n    has_content = True\n    required_arguments = 1\n    optional_arguments = 0\n    option_spec = {\n        \"hide_source\": bool,\n        \"quality\": lambda arg: directives.choice(\n            arg, (\"low\", \"medium\", \"high\", \"fourk\")\n        ),\n        \"save_as_gif\": bool,\n        \"save_last_frame\": bool,\n        \"ref_modules\": lambda arg: process_name_list(arg, \"mod\"),\n        \"ref_classes\": lambda arg: process_name_list(arg, \"class\"),\n        \"ref_functions\": lambda arg: process_name_list(arg, \"func\"),\n        \"ref_methods\": lambda arg: process_name_list(arg, \"meth\"),\n    }\n    final_argument_whitespace = True\n\n    def run(self):\n        if \"skip-manim\" in self.state.document.settings.env.app.builder.tags.tags:\n            node = skip_manim_node()\n            self.state.nested_parse(\n                StringList(self.content[0]), self.content_offset, node\n            )\n            return [node]\n\n        from manim import config\n\n        global classnamedict\n\n        clsname = self.arguments[0]\n        if clsname not in classnamedict:\n            classnamedict[clsname] = 1\n        else:\n            classnamedict[clsname] += 1\n\n        hide_source = \"hide_source\" in self.options\n        save_as_gif = \"save_as_gif\" in self.options\n        save_last_frame = \"save_last_frame\" in self.options\n        assert not (save_as_gif and save_last_frame)\n\n        ref_content = (\n            self.options.get(\"ref_modules\", [])\n            + self.options.get(\"ref_classes\", [])\n            + self.options.get(\"ref_functions\", [])\n            + self.options.get(\"ref_methods\", [])\n        )\n        if ref_content:\n            ref_block = f\"\"\"\n.. admonition:: Example References\n    :class: example-reference\n\n    {' '.join(ref_content)}\"\"\"\n        else:\n            ref_block = \"\"\n\n        if \"quality\" in self.options:\n            quality = f'{self.options[\"quality\"]}_quality'\n        else:\n            quality = \"example_quality\"\n        frame_rate = QUALITIES[quality][\"frame_rate\"]\n        pixel_height = QUALITIES[quality][\"pixel_height\"]\n        pixel_width = QUALITIES[quality][\"pixel_width\"]\n        qualitydir = f\"{pixel_height}p{frame_rate}\"\n\n        state_machine = self.state_machine\n        document = state_machine.document\n\n        source_file_name = document.attributes[\"source\"]\n        source_rel_name = relpath(source_file_name, setup.confdir)\n        source_rel_dir = os.path.dirname(source_rel_name)\n        while source_rel_dir.startswith(os.path.sep):\n            source_rel_dir = source_rel_dir[1:]\n\n        dest_dir = os.path.abspath(\n            os.path.join(setup.app.builder.outdir, source_rel_dir)\n        )\n        if not os.path.exists(dest_dir):\n            os.makedirs(dest_dir)\n\n        source_block = [\n            \".. code-block:: python\",\n            \"\",\n            *[\"    \" + line for line in self.content],\n        ]\n        source_block = \"\\n\".join(source_block)\n\n        config.media_dir = Path(setup.confdir) / \"media\"\n        config.images_dir = \"{media_dir}/images\"\n        config.video_dir = \"{media_dir}/videos/{quality}\"\n        output_file = f\"{clsname}-{classnamedict[clsname]}\"\n        config.assets_dir = Path(\"_static\")\n\n        config_code = [\n            f'config[\"frame_rate\"] = {frame_rate}',\n            f'config[\"pixel_height\"] = {pixel_height}',\n            f'config[\"pixel_width\"] = {pixel_width}',\n            f'config[\"save_last_frame\"] = {save_last_frame}',\n            f'config[\"save_as_gif\"] = {save_as_gif}',\n            f'config[\"output_file\"] = r\"{output_file}\"',\n        ]\n\n        user_code = self.content\n        if user_code[0].startswith(\">>> \"):  # check whether block comes from doctest\n            user_code = [\n                line[4:] for line in user_code if line.startswith((\">>> \", \"... \"))\n            ]\n\n        code = [\n            \"from manim import *\",\n            *config_code,\n            *user_code,\n            f\"{clsname}().render()\",\n        ]\n        exec(\"\\n\".join(code), globals())\n\n        # copy video file to output directory\n        if not (save_as_gif or save_last_frame):\n            filename = f\"{output_file}.mp4\"\n            filesrc = config.get_dir(\"video_dir\") / filename\n            destfile = os.path.join(dest_dir, filename)\n            shutil.copyfile(filesrc, destfile)\n        elif save_as_gif:\n            filename = f\"{output_file}.gif\"\n            filesrc = config.get_dir(\"video_dir\") / filename\n        elif save_last_frame:\n            filename = f\"{output_file}.png\"\n            filesrc = config.get_dir(\"images_dir\") / filename\n        else:\n            raise ValueError(\"Invalid combination of render flags received.\")\n\n        rendered_template = jinja2.Template(TEMPLATE).render(\n            clsname=clsname,\n            clsname_lowercase=clsname.lower(),\n            hide_source=hide_source,\n            filesrc_rel=os.path.relpath(filesrc, setup.confdir),\n            output_file=output_file,\n            save_last_frame=save_last_frame,\n            save_as_gif=save_as_gif,\n            source_block=source_block,\n            ref_block=ref_block,\n        )\n        state_machine.insert_input(\n            rendered_template.split(\"\\n\"), source=document.attributes[\"source\"]\n        )\n\n        return []\n\n\ndef setup(app):\n    import manim\n\n    app.add_node(skip_manim_node, html=(visit, depart))\n\n    setup.app = app\n    setup.config = app.config\n    setup.confdir = app.confdir\n\n    app.add_directive(\"manim\", ManimDirective)\n\n    metadata = {\"parallel_read_safe\": False, \"parallel_write_safe\": True}\n    return metadata\n\n\nTEMPLATE = r\"\"\"\n{% if not hide_source %}\n.. raw:: html\n\n    <div class=\"manim-example\">\n\n{% endif %}\n\n{% if not (save_as_gif or save_last_frame) %}\n.. raw:: html\n\n    <video id=\"{{ clsname_lowercase }}\" class=\"manim-video\" controls loop autoplay src=\"./{{ output_file }}.mp4\"></video>\n{% elif save_as_gif %}\n.. image:: /{{ filesrc_rel }}\n    :align: center\n    :name: {{ clsname_lowercase }}\n{% elif save_last_frame %}\n.. image:: /{{ filesrc_rel }}\n    :align: center\n    :name: {{ clsname_lowercase }}\n{% endif %}\n{% if not hide_source %}\n.. raw:: html\n\n    <h5 class=\"example-header\">{{ clsname }}<a class=\"headerlink\" href=\"#{{ clsname_lowercase }}\">\u00b6</a></h5>\n\n{{ source_block }}\n{{ ref_block }}\n{% endif %}\n\n.. raw:: html\n\n    </div>\n\"\"\"\n", "path": "docs/source/manim_directive.py"}]}