File size: 4,637 Bytes
f65fe85
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
#!/usr/bin/env python
# update-snippets.py
#
# This file is part of LilyPond, the GNU music typesetter.
#
# Copyright (C) 2007--2020 John Mandereau <[email protected]>>
#
# LilyPond is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# LilyPond is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with LilyPond.  If not, see <http://www.gnu.org/licenses/>.


# USAGE:  update-snippets.py REFERENCE-DIR TARGET-DIR FILES
#
# update ly snippets in TARGET-DIR/FILES with snippets from REFERENCE-DIR/FILES
#
# More precisely, each existing FILE in TARGET-DIR is matched to the FILE in
# REFERENCE-DIR (it the latter does not exist, a warning is given).
#
# Shell wildcards expansion is performed on FILES.
# This script currently supports Texinfo format.
# Ly snippets preceded with a line containing '@c KEEP LY' in TARGET-DIR/FILES
# will not be updated.
# An error occurs if REFERENCE-DIR/FILE and TARGET-DIR/FILE do not have the
# same snippets count.

import sys
import os
import glob
import re
from functools import reduce

print("update-snippets.py")

comment_re = re.compile(
    r'(?<!@)(@c(?:omment)? .*?\n|^@ignore\n.*?\n@end ignore\n)', re.M | re.S)
snippet_re = re.compile(
    r'^(@lilypond(?:file)?(?:\[.*?\])?\s*\{.+?\}|@lilypond(?:\[.*?\])?(?:.|\n)+?@end lilypond)', re.M)


def snippet_split(l):
    r = []
    for s in [s for s in l if s]:
        if s.startswith('@c ') or s.startswith('@ignore\n') or s.startswith('@comment '):
            r.append(s)
        else:
            r += [t for t in snippet_re.split(s) if t]
    return r


def count_snippet(l):
    k = 0
    for s in l:
        if s.startswith('@lilypond'):
            k += 1
    return k


def find_next_snippet(l, k):
    while not l[k].startswith('@lilypond'):
        k += 1
    return k


exit_code = 0


def update_exit_code(code):
    global exit_code
    exit_code = max(code, exit_code)


ref_dir, target_dir = sys.argv[1:3]
file_patterns = sys.argv[3:]

total_snippet_count = 0
changed_snippets_count = 0

for pattern in file_patterns:
    files = glob.glob(os.path.join(target_dir, pattern))
    for file in files:
        ref_file = os.path.join(ref_dir, os.path.basename(file))
        if not os.path.isfile(ref_file):
            sys.stderr.write(
                "Warning: %s: no such file.\nReference file for %s not found.\n" % (ref_file, file))
            continue
        f = open(file, 'r', encoding='utf8')
        target_source = comment_re.split(f.read())
        f.close()
        if reduce(lambda x, y: x or y, ['-- SKELETON FILE --' in s for s in target_source]):
            sys.stderr.write("Skipping skeleton file %s\n" % file)
            continue
        g = open(ref_file, 'r', encoding='utf8')
        ref_source = comment_re.split(g.read())
        target_source = snippet_split(target_source)
        ref_source = snippet_split(ref_source)
        if '' in target_source or '' in ref_source:
            raise RuntimeError(
                "target_source and ref_source must not be empty")
        snippet_count = count_snippet(target_source)
        if not snippet_count == count_snippet(ref_source):
            update_exit_code(1)
            sys.stderr.write("Error: %s and %s have different snippet counts.\n\
Update translation by at least adding a @lilypond block where necessary, then rerun this script.\n" % (ref_file, file))
            continue
        total_snippet_count += snippet_count
        c = 0
        k = -1
        for j in range(len(target_source)):
            if target_source[j].startswith('@lilypond'):
                k = find_next_snippet(ref_source, k+1)
                if j > 0 and (not target_source[j-1].startswith('@c KEEP LY')) and target_source[j] != ref_source[k]:
                    target_source[j] = ref_source[k]
                    c += 1
                    changed_snippets_count += 1
        f = open(file, 'w', encoding='utf8')
        f.write(''.join(target_source))
        sys.stderr.write('%s: %d/%d snippets updated\n' %
                         (file, c, snippet_count))

sys.stderr.write('\nTotal: %d snippets, %d updated snippets.\n' %
                 (total_snippet_count, changed_snippets_count))
sys.exit(exit_code)