]>
Commit | Line | Data |
---|---|---|
1 | #!/usr/bin/env python3 | |
2 | ||
3 | # Allow direct execution | |
4 | import os | |
5 | import sys | |
6 | ||
7 | sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) | |
8 | ||
9 | ||
10 | import os.path | |
11 | import re | |
12 | ||
13 | from devscripts.utils import ( | |
14 | compose_functions, | |
15 | get_filename_args, | |
16 | read_file, | |
17 | write_file, | |
18 | ) | |
19 | ||
20 | ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) | |
21 | README_FILE = os.path.join(ROOT_DIR, 'README.md') | |
22 | ||
23 | PREFIX = r'''%yt-dlp(1) | |
24 | ||
25 | # NAME | |
26 | ||
27 | yt\-dlp \- A youtube-dl fork with additional features and patches | |
28 | ||
29 | # SYNOPSIS | |
30 | ||
31 | **yt-dlp** \[OPTIONS\] URL [URL...] | |
32 | ||
33 | # DESCRIPTION | |
34 | ||
35 | ''' | |
36 | ||
37 | ||
38 | def filter_excluded_sections(readme): | |
39 | EXCLUDED_SECTION_BEGIN_STRING = re.escape('<!-- MANPAGE: BEGIN EXCLUDED SECTION -->') | |
40 | EXCLUDED_SECTION_END_STRING = re.escape('<!-- MANPAGE: END EXCLUDED SECTION -->') | |
41 | return re.sub( | |
42 | rf'(?s){EXCLUDED_SECTION_BEGIN_STRING}.+?{EXCLUDED_SECTION_END_STRING}\n', | |
43 | '', readme) | |
44 | ||
45 | ||
46 | def move_sections(readme): | |
47 | MOVE_TAG_TEMPLATE = '<!-- MANPAGE: MOVE "%s" SECTION HERE -->' | |
48 | sections = re.findall(r'(?m)^%s$' % ( | |
49 | re.escape(MOVE_TAG_TEMPLATE).replace(r'\%', '%') % '(.+)'), readme) | |
50 | ||
51 | for section_name in sections: | |
52 | move_tag = MOVE_TAG_TEMPLATE % section_name | |
53 | if readme.count(move_tag) > 1: | |
54 | raise Exception(f'There is more than one occurrence of "{move_tag}". This is unexpected') | |
55 | ||
56 | sections = re.findall(rf'(?sm)(^# {re.escape(section_name)}.+?)(?=^# )', readme) | |
57 | if len(sections) < 1: | |
58 | raise Exception(f'The section {section_name} does not exist') | |
59 | elif len(sections) > 1: | |
60 | raise Exception(f'There are multiple occurrences of section {section_name}, this is unhandled') | |
61 | ||
62 | readme = readme.replace(sections[0], '', 1).replace(move_tag, sections[0], 1) | |
63 | return readme | |
64 | ||
65 | ||
66 | def filter_options(readme): | |
67 | section = re.search(r'(?sm)^# USAGE AND OPTIONS\n.+?(?=^# )', readme).group(0) | |
68 | options = '# OPTIONS\n' | |
69 | for line in section.split('\n')[1:]: | |
70 | mobj = re.fullmatch(r'''(?x) | |
71 | \s{4}(?P<opt>-(?:,\s|[^\s])+) | |
72 | (?:\s(?P<meta>(?:[^\s]|\s(?!\s))+))? | |
73 | (\s{2,}(?P<desc>.+))? | |
74 | ''', line) | |
75 | if not mobj: | |
76 | options += f'{line.lstrip()}\n' | |
77 | continue | |
78 | option, metavar, description = mobj.group('opt', 'meta', 'desc') | |
79 | ||
80 | # Pandoc's definition_lists. See http://pandoc.org/README.html | |
81 | option = f'{option} *{metavar}*' if metavar else option | |
82 | description = f'{description}\n' if description else '' | |
83 | options += f'\n{option}\n: {description}' | |
84 | continue | |
85 | ||
86 | return readme.replace(section, options, 1) | |
87 | ||
88 | ||
89 | TRANSFORM = compose_functions(filter_excluded_sections, move_sections, filter_options) | |
90 | ||
91 | ||
92 | def main(): | |
93 | write_file(get_filename_args(), PREFIX + TRANSFORM(read_file(README_FILE))) | |
94 | ||
95 | ||
96 | if __name__ == '__main__': | |
97 | main() |