1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 """Grep XLIFF, Gettext PO and TMX localization files
23
24 Matches are output to snippet files of the same type which can then be reviewed
25 and later merged using pomerge
26
27 See: http://translate.sourceforge.net/wiki/toolkit/pogrep for examples and
28 usage instructions
29 """
30
31 from translate.storage import factory
32 from translate.misc import optrecurse
33 from translate.misc.multistring import multistring
34 from translate.lang import data
35 import re
36 import locale
37
39 - def __init__(self, searchstring, searchparts, ignorecase=False, useregexp=False, invertmatch=False, accelchar=None, encoding='utf-8', includeheader=False):
40 """builds a checkfilter using the given checker"""
41 if isinstance(searchstring, unicode):
42 self.searchstring = searchstring
43 else:
44 self.searchstring = searchstring.decode(encoding)
45 self.searchstring = data.normalize(self.searchstring)
46 if searchparts:
47
48
49 self.search_source = ('source' in searchparts) or ('msgid' in searchparts)
50 self.search_target = ('target' in searchparts) or ('msgstr' in searchparts)
51 self.search_notes = ('notes' in searchparts) or ('comment' in searchparts)
52 self.search_locations = 'locations' in searchparts
53 else:
54 self.search_source = True
55 self.search_target = True
56 self.search_notes = False
57 self.search_locations = False
58 self.ignorecase = ignorecase
59 if self.ignorecase:
60 self.searchstring = self.searchstring.lower()
61 self.useregexp = useregexp
62 if self.useregexp:
63 self.searchpattern = re.compile(self.searchstring)
64 self.invertmatch = invertmatch
65 self.accelchar = accelchar
66 self.includeheader = includeheader
67
69 teststr = data.normalize(teststr)
70 if self.ignorecase:
71 teststr = teststr.lower()
72 if self.accelchar:
73 teststr = re.sub(self.accelchar + self.accelchar, "#", teststr)
74 teststr = re.sub(self.accelchar, "", teststr)
75 if self.useregexp:
76 found = self.searchpattern.search(teststr)
77 else:
78 found = teststr.find(self.searchstring) != -1
79 if self.invertmatch:
80 found = not found
81 return found
82
84 """runs filters on an element"""
85 if unit.isheader(): return []
86
87 if self.search_source:
88 if isinstance(unit.source, multistring):
89 strings = unit.source.strings
90 else:
91 strings = [unit.source]
92 for string in strings:
93 if self.matches(string):
94 return True
95
96 if self.search_target:
97 if isinstance(unit.target, multistring):
98 strings = unit.target.strings
99 else:
100 strings = [unit.target]
101 for string in strings:
102 if self.matches(string):
103 return True
104
105 if self.search_notes:
106 return self.matches(unit.getnotes())
107 if self.search_locations:
108 return self.matches(u" ".join(unit.getlocations()))
109 return False
110
112 """runs filters on a translation file object"""
113 thenewfile = type(thefile)()
114 for unit in thefile.units:
115 if self.filterunit(unit):
116 thenewfile.addunit(unit)
117 if self.includeheader and thenewfile.units > 0:
118 if thefile.units[0].isheader():
119 thenewfile.units.insert(0, thefile.units[0])
120 else:
121 thenewfile.units.insert(0, thenewfile.makeheader())
122 return thenewfile
123
125 """a specialized Option Parser for the grep tool..."""
127 """parses the command line options, handling implicit input/output args"""
128 (options, args) = optrecurse.optparse.OptionParser.parse_args(self, args, values)
129
130 if args:
131 options.searchstring = args[0]
132 args = args[1:]
133 else:
134 self.error("At least one argument must be given for the search string")
135 if args and not options.input:
136 if not options.output:
137 options.input = args[:-1]
138 args = args[-1:]
139 else:
140 options.input = args
141 args = []
142 if args and not options.output:
143 options.output = args[-1]
144 args = args[:-1]
145 if args:
146 self.error("You have used an invalid combination of --input, --output and freestanding args")
147 if isinstance(options.input, list) and len(options.input) == 1:
148 options.input = options.input[0]
149 return (options, args)
150
152 """sets the usage string - if usage not given, uses getusagestring for each option"""
153 if usage is None:
154 self.usage = "%prog searchstring " + " ".join([self.getusagestring(option) for option in self.option_list])
155 else:
156 super(GrepOptionParser, self).set_usage(usage)
157
166
167 -def rungrep(inputfile, outputfile, templatefile, checkfilter):
168 """reads in inputfile, filters using checkfilter, writes to outputfile"""
169 fromfile = factory.getobject(inputfile)
170 tofile = checkfilter.filterfile(fromfile)
171 if tofile.isempty():
172 return False
173 outputfile.write(str(tofile))
174 return True
175
177 formats = {"po":("po", rungrep), "pot":("pot", rungrep),
178 "xliff":("xliff", rungrep), "xlf":("xlf", rungrep), "xlff":("xlff", rungrep),
179 "tmx":("tmx", rungrep),
180 None:("po", rungrep)}
181 parser = GrepOptionParser(formats)
182 parser.add_option("", "--search", dest="searchparts",
183 action="append", type="choice", choices=["source", "target", "notes", "locations", "msgid", "msgstr", "comment" ],
184 metavar="SEARCHPARTS", help="searches the given parts (source, target, notes and locations)")
185 parser.add_option("-I", "--ignore-case", dest="ignorecase",
186 action="store_true", default=False, help="ignore case distinctions")
187 parser.add_option("-e", "--regexp", dest="useregexp",
188 action="store_true", default=False, help="use regular expression matching")
189 parser.add_option("-v", "--invert-match", dest="invertmatch",
190 action="store_true", default=False, help="select non-matching lines")
191 parser.add_option("", "--accelerator", dest="accelchar",
192 action="store", type="choice", choices=["&", "_", "~"],
193 metavar="ACCELERATOR", help="ignores the given accelerator when matching")
194 parser.add_option("", "--header", dest="includeheader",
195 action="store_true", default=False,
196 help="include a PO header in the output")
197 parser.set_usage()
198 parser.passthrough.append('checkfilter')
199 parser.description = __doc__
200 return parser
201
203 parser = cmdlineparser()
204 parser.run()
205
206 if __name__ == '__main__':
207 main()
208