2
2
from argparse import ArgumentParser
3
3
from pathlib import Path
4
4
5
+ from PIL import Image
6
+
5
7
INFO : dict [str , tuple [int , str ]] = dict (
6
8
heading_code = (550 , "## Heading 2" ),
7
9
list_table = (550 , "" ),
12
14
13
15
14
16
def main (name : str ) -> None :
15
- in_file = Path (f"demo/{ name } .md" )
16
- assert in_file .exists ()
17
+ file = Path (f"demo/{ name } .md" )
18
+ assert file .exists ()
19
+
20
+ create_gif (name , file )
21
+ create_screenshot (name )
22
+
17
23
18
- out_file = Path (f"demo/{ name } .gif" )
19
- if out_file .exists ():
20
- out_file .unlink ()
24
+ def create_gif (name : str , file : Path ) -> None :
25
+ gif = Path (f"demo/{ name } .gif" )
26
+ if gif .exists ():
27
+ gif .unlink ()
21
28
22
29
height , content = INFO [name ]
23
30
24
31
tape = Path ("demo/demo.tape" )
25
- tape .write_text (tape_content (in_file , out_file , height , content ))
32
+ tape .write_text (tape_content (file , gif , height , content ))
26
33
result = subprocess .run (["vhs" , tape ])
27
34
assert result .returncode == 0
28
35
tape .unlink ()
29
36
30
37
31
- def tape_content (in_file : Path , out_file : Path , height : int , to_write : str ) -> str :
32
- content = Path ("demo/format.tape" ).read_text ()
33
- content = content .replace ("INPUT" , str (in_file ))
34
- content = content .replace ("OUTPUT" , str (out_file ))
35
- content = content .replace ("WIDTH" , str (550 ))
36
- content = content .replace ("HEIGHT" , str (height ))
37
- content = content .replace ("WRITE" , get_write (to_write ))
38
- content = content .replace ("MOVE" , get_move (in_file ))
39
- return content
38
+ def create_screenshot (name : str ) -> None :
39
+ screenshot = Path (f"demo/{ name } .png" )
40
+ if screenshot .exists ():
41
+ screenshot .unlink ()
42
+
43
+ default , rendered = Path ("default.png" ), Path ("rendered.png" )
44
+ assert default .exists () and rendered .exists ()
45
+
46
+ left , right = Image .open (default ), Image .open (rendered )
47
+
48
+ mode , width , height = left .mode , left .width , left .height
49
+ assert mode == right .mode and width == right .width and height == right .height
50
+
51
+ combined = Image .new (mode , (2 * width , height ))
52
+ combined .paste (left , (0 , 0 ))
53
+ combined .paste (right , (width , 0 ))
54
+ combined .save (screenshot )
55
+
56
+ default .unlink ()
57
+ rendered .unlink ()
58
+
59
+
60
+ def tape_content (file : Path , gif : Path , height : int , content : str ) -> str :
61
+ result = Path ("demo/format.tape" ).read_text ()
62
+ result = result .replace ("INPUT" , str (file ))
63
+ result = result .replace ("OUTPUT" , str (gif ))
64
+ result = result .replace ("WIDTH" , str (550 ))
65
+ result = result .replace ("HEIGHT" , str (height ))
66
+ result = result .replace ("WRITE" , get_write (content ))
67
+ result = result .replace ("MOVE" , get_move (file ))
68
+ return result
40
69
41
70
42
71
def get_write (content : str ) -> str :
@@ -49,10 +78,10 @@ def get_write(content: str) -> str:
49
78
return "\n " .join (write )
50
79
51
80
52
- def get_move (in_file : Path ) -> str :
81
+ def get_move (file : Path ) -> str :
53
82
move : list [str ] = []
54
- # Get lines so we know how to scroll down, account for starting on first line
55
- lines : list [str ] = Path ( in_file ) .read_text ().splitlines ()[1 :]
83
+ # Get lines so we know how to scroll down, account for starting on second line
84
+ lines : list [str ] = file .read_text ().splitlines ()[2 :]
56
85
for line in lines :
57
86
skip = (" " , "def" , "if" )
58
87
duration = 0.1 if line == "" or line .startswith (skip ) else 0.75
0 commit comments