Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(573)

Side by Side Diff: grit/format/rc.py

Issue 9924009: Add c_format as a format option. (Closed) Base URL: https://grit-i18n.googlecode.com/svn/trunk
Patch Set: Created 8 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « grit/format/c_format_unittest.py ('k') | grit/format/rc_unittest.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be 3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file. 4 # found in the LICENSE file.
5 5
6 '''Support for formatting an RC file for compilation. 6 '''Support for formatting an RC file for compilation.
7 ''' 7 '''
8 8
9 import os 9 import os
10 import types 10 import types
11 import re 11 import re
12 12
13 from grit import lazy_re 13 from grit import lazy_re
14 from grit import util 14 from grit import util
15 from grit.format import interface 15 from grit.format import interface
16 16
17 # Matches all different types of linebreaks.
18 _LINEBREAKS = lazy_re.compile('\r\n|\n|\r')
19
20 ''' 17 '''
21 This dictionary defines the langauge charset pair lookup table, which is used 18 This dictionary defines the langauge charset pair lookup table, which is used
22 for replacing the GRIT expand variables for language info in Product Version 19 for replacing the GRIT expand variables for language info in Product Version
23 resource. The key is the language ISO country code, and the value 20 resource. The key is the language ISO country code, and the value
24 is the language and character-set pair, which is a hexadecimal string 21 is the language and character-set pair, which is a hexadecimal string
25 consisting of the concatenation of the language and character-set identifiers. 22 consisting of the concatenation of the language and character-set identifiers.
26 The first 4 digit of the value is the hex value of LCID, the remaining 23 The first 4 digit of the value is the hex value of LCID, the remaining
27 4 digits is the hex value of character-set id(code page)of the language. 24 4 digits is the hex value of character-set id(code page)of the language.
28 25
29 We have defined three GRIT expand_variables to be used in the version resource 26 We have defined three GRIT expand_variables to be used in the version resource
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
180 177
181 def GetUnifiedLangCode(language) : 178 def GetUnifiedLangCode(language) :
182 r = re.compile('([a-z]{1,2})_([a-z]{1,2})') 179 r = re.compile('([a-z]{1,2})_([a-z]{1,2})')
183 if r.match(language) : 180 if r.match(language) :
184 underscore = language.find('_') 181 underscore = language.find('_')
185 return language[0:underscore] + '-' + language[underscore + 1:].upper() 182 return language[0:underscore] + '-' + language[underscore + 1:].upper()
186 else : 183 else :
187 return language 184 return language
188 185
189 186
190 def _MakeRelativePath(base_path, path_to_make_relative):
191 '''Returns a relative path such from the base_path to
192 the path_to_make_relative.
193
194 In other words, os.join(base_path,
195 MakeRelativePath(base_path, path_to_make_relative))
196 is the same location as path_to_make_relative.
197
198 Args:
199 base_path: the root path
200 path_to_make_relative: an absolute path that is on the same drive
201 as base_path
202 '''
203
204 def _GetPathAfterPrefix(prefix_path, path_with_prefix):
205 '''Gets the subpath within in prefix_path for the path_with_prefix
206 with no beginning or trailing path separators.
207
208 Args:
209 prefix_path: the base path
210 path_with_prefix: a path that starts with prefix_path
211 '''
212 assert path_with_prefix.startswith(prefix_path)
213 path_without_prefix = path_with_prefix[len(prefix_path):]
214 normalized_path = os.path.normpath(path_without_prefix.strip(os.path.sep))
215 if normalized_path == '.':
216 normalized_path = ''
217 return normalized_path
218
219 def _GetCommonBaseDirectory(*args):
220 '''Returns the common prefix directory for the given paths
221
222 Args:
223 The list of paths (at least one of which should be a directory)
224 '''
225 prefix = os.path.commonprefix(args)
226 # prefix is a character-by-character prefix (i.e. it does not end
227 # on a directory bound, so this code fixes that)
228
229 # if the prefix ends with the separator, then it is prefect.
230 if len(prefix) > 0 and prefix[-1] == os.path.sep:
231 return prefix
232
233 # We need to loop through all paths or else we can get
234 # tripped up by "c:\a" and "c:\abc". The common prefix
235 # is "c:\a" which is a directory and looks good with
236 # respect to the first directory but it is clear that
237 # isn't a common directory when the second path is
238 # examined.
239 for path in args:
240 assert len(path) >= len(prefix)
241 # If the prefix the same length as the path,
242 # then the prefix must be a directory (since one
243 # of the arguements should be a directory).
244 if path == prefix:
245 continue
246 # if the character after the prefix in the path
247 # is the separator, then the prefix appears to be a
248 # valid a directory as well for the given path
249 if path[len(prefix)] == os.path.sep:
250 continue
251 # Otherwise, the prefix is not a directory, so it needs
252 # to be shortened to be one
253 index_sep = prefix.rfind(os.path.sep)
254 # The use "index_sep + 1" because it includes the final sep
255 # and it handles the case when the index_sep is -1 as well
256 prefix = prefix[:index_sep + 1]
257 # At this point we backed up to a directory bound which is
258 # common to all paths, so we can quit going through all of
259 # the paths.
260 break
261 return prefix
262
263 prefix = _GetCommonBaseDirectory(base_path, path_to_make_relative)
264 # If the paths had no commonality at all, then return the absolute path
265 # because it is the best that can be done. If the path had to be relative
266 # then eventually this absolute path will be discovered (when a build breaks)
267 # and an appropriate fix can be made, but having this allows for the best
268 # backward compatibility with the absolute path behavior in the past.
269 if len(prefix) <= 0:
270 return path_to_make_relative
271 # Build a path from the base dir to the common prefix
272 remaining_base_path = _GetPathAfterPrefix(prefix, base_path)
273
274 # The follow handles two case: "" and "foo\\bar"
275 path_pieces = remaining_base_path.split(os.path.sep)
276 base_depth_from_prefix = len([d for d in path_pieces if len(d)])
277 base_to_prefix = (".." + os.path.sep) * base_depth_from_prefix
278
279 # Put add in the path from the prefix to the path_to_make_relative
280 remaining_other_path = _GetPathAfterPrefix(prefix, path_to_make_relative)
281 return base_to_prefix + remaining_other_path
282
283
284 class TopLevel(interface.ItemFormatter): 187 class TopLevel(interface.ItemFormatter):
285 '''Writes out the required preamble for RC files.''' 188 '''Writes out the required preamble for RC files.'''
286 def Format(self, item, lang='en', begin_item=True, output_dir='.'): 189 def Format(self, item, lang='en', begin_item=True, output_dir='.'):
287 assert isinstance(lang, types.StringTypes) 190 assert isinstance(lang, types.StringTypes)
288 if not begin_item: 191 if not begin_item:
289 return '' 192 return ''
290 else: 193 else:
291 # Find the location of the resource header file, so that we can include 194 # Find the location of the resource header file, so that we can include
292 # it. 195 # it.
293 resource_header = 'resource.h' # fall back to this 196 resource_header = 'resource.h' # fall back to this
294 language_directive = '' 197 language_directive = ''
295 for output in item.GetRoot().GetOutputFiles(): 198 for output in item.GetRoot().GetOutputFiles():
296 if output.attrs['type'] == 'rc_header': 199 if output.attrs['type'] == 'rc_header':
297 resource_header = os.path.abspath(output.GetOutputFilename()) 200 resource_header = os.path.abspath(output.GetOutputFilename())
298 resource_header = _MakeRelativePath(output_dir, resource_header) 201 resource_header = util.MakeRelativePath(output_dir, resource_header)
299 if output.attrs['lang'] != lang: 202 if output.attrs['lang'] != lang:
300 continue 203 continue
301 if output.attrs['language_section'] == '': 204 if output.attrs['language_section'] == '':
302 # If no language_section is requested, no directive is added 205 # If no language_section is requested, no directive is added
303 # (Used when the generated rc will be included from another rc 206 # (Used when the generated rc will be included from another rc
304 # file that will have the appropriate language directive) 207 # file that will have the appropriate language directive)
305 language_directive = '' 208 language_directive = ''
306 elif output.attrs['language_section'] == 'neutral': 209 elif output.attrs['language_section'] == 'neutral':
307 # If a neutral language section is requested (default), add a 210 # If a neutral language section is requested (default), add a
308 # neutral language directive 211 # neutral language directive
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
349 if not begin_item: 252 if not begin_item:
350 return '' 253 return ''
351 254
352 assert isinstance(lang, types.StringTypes) 255 assert isinstance(lang, types.StringTypes)
353 assert isinstance(item, message.MessageNode) 256 assert isinstance(item, message.MessageNode)
354 257
355 message = item.ws_at_start + item.Translate(lang) + item.ws_at_end 258 message = item.ws_at_start + item.Translate(lang) + item.ws_at_end
356 # Escape quotation marks (RC format uses doubling-up 259 # Escape quotation marks (RC format uses doubling-up
357 message = message.replace('"', '""') 260 message = message.replace('"', '""')
358 # Replace linebreaks with a \n escape 261 # Replace linebreaks with a \n escape
359 message = _LINEBREAKS.sub(r'\\n', message) 262 message = util.LINEBREAKS.sub(r'\\n', message)
360 263
361 name_attr = item.GetTextualIds()[0] 264 name_attr = item.GetTextualIds()[0]
362 265
363 return ' %-15s "%s"\n' % (name_attr, message) 266 return ' %-15s "%s"\n' % (name_attr, message)
364 267
365 268
366 class RcSection(interface.ItemFormatter): 269 class RcSection(interface.ItemFormatter):
367 '''Writes out an .rc file section.''' 270 '''Writes out an .rc file section.'''
368 271
369 def Format(self, item, lang='en', begin_item=True, output_dir='.'): 272 def Format(self, item, lang='en', begin_item=True, output_dir='.'):
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
428 # sharing the resulting .rc files is possible. 331 # sharing the resulting .rc files is possible.
429 # 332 #
430 # The FileForLanguage() Function has the side effect of generating the file 333 # The FileForLanguage() Function has the side effect of generating the file
431 # if needed (e.g. if it is an HTML file include). 334 # if needed (e.g. if it is an HTML file include).
432 filename = os.path.abspath(item.FileForLanguage(lang, output_dir)) 335 filename = os.path.abspath(item.FileForLanguage(lang, output_dir))
433 if self.flatten_html: 336 if self.flatten_html:
434 filename = item.Flatten(output_dir) 337 filename = item.Flatten(output_dir)
435 elif self.filenameWithoutPath: 338 elif self.filenameWithoutPath:
436 filename = os.path.basename(filename) 339 filename = os.path.basename(filename)
437 elif self.relative_path_: 340 elif self.relative_path_:
438 filename = _MakeRelativePath(output_dir, filename) 341 filename = util.MakeRelativePath(output_dir, filename)
439 342
440 filename = filename.replace('\\', '\\\\') # escape for the RC format 343 filename = filename.replace('\\', '\\\\') # escape for the RC format
441 344
442 if isinstance(item, structure.StructureNode) and item.IsExcludedFromRc(): 345 if isinstance(item, structure.StructureNode) and item.IsExcludedFromRc():
443 return '' 346 return ''
444 else: 347 else:
445 return '%-18s %-18s "%s"\n' % (item.attrs['name'], self.type_, filename) 348 return '%-18s %-18s "%s"\n' % (item.attrs['name'], self.type_, filename)
446 349
OLDNEW
« no previous file with comments | « grit/format/c_format_unittest.py ('k') | grit/format/rc_unittest.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698