Utensil's Zettelkasten-style forest of evergreen notes on math and tech. utensil.tngl.sh/forest/
0

Configure Feed

Select the types of activity you want to include in your feed.

forest / fize.py
2.7 kB 77 lines
1#!/usr/bin/env -S uv run 2# /// script 3# requires-python = ">=3.11,<3.12" 4# dependencies = [] 5# /// 6import sys 7import re 8 9# foresterize a tree with LaTeX math 10 11if len(sys.argv) != 2: 12 print("Usage: python3 fize.py <tree>") 13 sys.exit(1) 14 15TREE = f"trees/{sys.argv[1]}.tree" 16 17with open(TREE, 'r+') as file: 18 content = file.read() 19 # Fix enumerate and itemize 20 content = re.sub(r'\\begin\{enumerate\}', r'\\ol{', content) 21 content = re.sub(r'\\end\{enumerate\}', r'}', content) 22 content = re.sub(r'\\begin\{itemize\}', r'\\ul{', content) 23 content = re.sub(r'\\end\{itemize\}', r'}', content) 24 content = re.sub(r'\\item (.*)', r'\\li{\1}', content) 25 content = re.sub(r'\\ii (.*)', r'\\li{\1}', content) 26 27 # Convert some LaTeX commands to forester commands 28 content = re.sub(r'\\emph\{([^}]*)\}', r'\\em{\1}', content) 29 30 # Replace all line breaks to `\r` to handle multiline replacements 31 content.replace('\n', '\r') 32 33 # Replace display math `$$...$$` with `##{...}` 34 content = re.sub(r'\$\$([^$]+)\$\$', r'##{\1}', content) 35 36 # Replace inline math `$...$` with `#{...}` 37 content = re.sub(r'\$([^$]+)\$', r'#{\1}', content) 38 39 # Replace LaTeX block openning with a forester block openning, plus a paragraph openning 40 # Particularly, this introduce a line break after the block openning 41 content = re.sub(r'\\texdef\{([^\}]*)\}\{([^\}]*)\}\{', r'\\refdef{\1}{\2}{\n\n\\p{', content) 42 content = re.sub(r'\\texnote\{([^\}]*)\}\{([^\}]*)\}\{', r'\\refnote{\1}{\2}{\n\n\\p{', content) 43 content = re.sub(r'\\minitex\{', r'{\n\n\\p{', content) 44 45 # Before the line containing \refdef, skip; after the line, replace \r\r with }\r\r\\p{ 46 content = content.split('\n') 47 skip = True 48 for i in range(len(content)): 49 if re.search(r'\\(refdef|refnote)', content[i]): 50 skip = False 51 continue 52 if not skip: 53 content[i] = content[i].replace('\r\r', '}\r\r\\p{') 54 content = '\n'.join(content) 55 56 # Replace an ending } with } }, the inserted } is to close the paragraph 57 content = re.sub(r'}\s*$', r'}\r\r}\r', content) 58 59 # Replace \( with #{ -- obsolete 60 # content = re.sub(r'\\\(', r'#\{', content) 61 62 # Replace \) with } -- obsolete 63 # content = re.sub(r'\\\)', r'}', content) 64 65 # Replace \[ with ##{ -- obsolete 66 # content = re.sub(r'\\\[', r'##\{', content) 67 68 # Replace \] with } -- obsolete 69 # content = re.sub(r'\\\]', r'}', content) 70 71 # Replace \texdef with \refdef 72 content = re.sub(r'\\texdef', r'\\refdef', content) 73 74 # Replace the file content 75 file.seek(0) 76 file.write(content) 77 file.truncate()