File size: 2,180 Bytes
872cf4d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
"""Mechanical sanity check on report.tex.



There is no LaTeX engine on this machine, so this catches the errors a

compile would have caught: dangling \\ref, missing \\input or figure files,

unbalanced braces or environments, and unclosed inline math.



    python report/check_tex.py

"""

import re
import sys
from collections import Counter
from pathlib import Path

HERE = Path(__file__).resolve().parent


def main():
    src = (HERE / 'report.tex').read_text(encoding='utf-8')
    # strip comments, so commented-out examples don't trip the checks
    body = '\n'.join(re.sub(r'(?<!\\)%.*$', '', ln) for ln in src.splitlines())

    problems = 0

    labels = set(re.findall(r'\\label\{([^}]+)\}', body))
    refs = set(re.findall(r'\\(?:eq)?ref\{([^}]+)\}', body))
    dangling = sorted(refs - labels)
    print('undefined refs :', dangling or 'none')
    problems += len(dangling)
    print('unused labels  :', sorted(labels - refs) or 'none')

    missing = [f for f in re.findall(r'\\input\{([^}]+)\}', body)
               if not (HERE / (f + '.tex')).exists()]
    print('missing inputs :', missing or 'none')
    problems += len(missing)

    figs = re.findall(r'\\includegraphics(?:\[[^\]]*\])?\{([^}]+)\}', body)
    missing = [f for f in figs if not (HERE / 'figures' / f).exists()]
    print('missing figures:', missing or 'none')
    problems += len(missing)

    balance = body.count('{') - body.count('}')
    print('brace balance  :', balance)
    problems += abs(balance)

    counts = Counter()
    for kind, name in re.findall(r'\\(begin|end)\{([^}]+)\}', body):
        counts[name] += 1 if kind == 'begin' else -1
    bad_envs = {k: v for k, v in counts.items() if v}
    print('unbalanced envs:', bad_envs or 'none')
    problems += len(bad_envs)

    odd = [i + 1 for i, ln in enumerate(body.splitlines())
           if len(re.findall(r'(?<!\\)\$', ln)) % 2]
    print('odd $ lines    :', odd or 'none')
    problems += len(odd)

    print()
    print('OK' if problems == 0 else f'{problems} problem(s)')
    return 0 if problems == 0 else 1


if __name__ == '__main__':
    sys.exit(main())