2 # Copyright (c) 2011 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
6 """Given a filename as an argument, sort the #include/#imports in that file.
8 Shows a diff and prompts for confirmation before doing the deed.
18 """Prompts with a yes/no question, returns True if yes."""
21 # http://code.activestate.com/recipes/134892/
22 fd
= sys
.stdin
.fileno()
23 old_settings
= termios
.tcgetattr(fd
)
26 tty
.setraw(sys
.stdin
.fileno())
27 ch
= sys
.stdin
.read(1)
29 termios
.tcsetattr(fd
, termios
.TCSADRAIN
, old_settings
)
31 return ch
in ('Y', 'y')
34 def IncludeCompareKey(line
):
35 """Sorting comparator key used for comparing two #include lines.
36 Returns the filename without the #include/#import prefix.
38 for prefix
in ('#include ', '#import '):
39 if line
.startswith(prefix
):
40 line
= line
[len(prefix
):]
43 # The win32 api has all sorts of implicit include order dependencies :-/
44 # Give a few headers special sort keys that make sure they appear before all
46 if line
.startswith('<windows.h>'): # Must be before e.g. shellapi.h
48 if line
.startswith('<unknwn.h>'): # Must be before e.g. intshcut.h
55 """Returns True if the line is an #include/#import line."""
56 return line
.startswith('#include ') or line
.startswith('#import ')
59 def SortHeader(infile
, outfile
):
60 """Sorts the headers in infile, writing the sorted file to outfile."""
64 while IsInclude(line
):
65 headerblock
.append(line
)
67 for header
in sorted(headerblock
, key
=IncludeCompareKey
):
69 # Intentionally fall through, to write the line that caused
70 # the above while loop to exit.
75 parser
= optparse
.OptionParser(usage
='%prog filename1 filename2 ...')
76 opts
, args
= parser
.parse_args()
83 fixfilename
= filename
+ '.new'
84 infile
= open(filename
, 'r')
85 outfile
= open(fixfilename
, 'w')
86 SortHeader(infile
, outfile
)
88 outfile
.close() # Important so the below diff gets the updated contents.
91 diff
= os
.system('diff -u %s %s' % (filename
, fixfilename
))
92 if diff
>> 8 == 0: # Check exit code.
93 print '%s: no change' % filename
96 if YesNo('Use new file (y/N)?'):
97 os
.rename(fixfilename
, filename
)
100 os
.remove(fixfilename
)
102 # If the file isn't there, we don't care.
106 if __name__
== '__main__':