3 # lanuage type for each file extension
35 # languages based on file prefix
40 ('Doxyfile', 'doxygen'),
43 # languages based on #! line of first file
50 # the list of all languages that we detect
51 all_languages
= frozenset(lang_types
.itervalues())
52 all_languages |
= frozenset(lang
for start
,lang
in lang_prefixes
)
53 all_languages |
= frozenset(lang
for start
,lang
in hash_bang
)
55 def lang_type(filename
, firstline
=None, openok
=True):
56 '''identify the language of a given filename and potentially the
57 firstline of the file. If the firstline of the file is not
58 provided and openok is True, open the file and read the first line
61 basename
= os
.path
.basename(filename
)
62 name
,extension
= os
.path
.splitext(basename
)
64 # first try to detect language based on file extension
66 return lang_types
[extension
]
70 # now try to detect language based on file prefix
71 for start
,lang
in lang_prefixes
:
72 if basename
.startswith(start
):
75 # if a first line was not provided but the file is ok to open,
76 # grab the first line of the file.
77 if firstline
is None and openok
:
78 handle
= file(filename
, 'r')
79 firstline
= handle
.readline()
82 # try to detect language based on #! in first line
83 if firstline
and firstline
.startswith('#!'):
84 for string
,lang
in hash_bang
:
85 if firstline
.find(string
) > 0:
88 # sorry, we couldn't detect the language
91 # directories and files to ignore by default
92 default_dir_ignore
= frozenset(('.hg', '.svn', 'build', 'ext'))
93 default_file_ignore
= frozenset(('parsetab.py', ))
95 def find_files(base
, languages
=all_languages
,
96 dir_ignore
=default_dir_ignore
,
97 file_ignore
=default_file_ignore
):
98 '''find all files in a directory and its subdirectories based on a
99 set of languages, ignore directories specified in dir_ignore and
100 files specified in file_ignore'''
104 def update_dirs(dirs
):
105 '''strip the ignored directories out of the provided list'''
106 index
= len(dirs
) - 1
107 for i
,d
in enumerate(reversed(dirs
)):
112 for root
,dirs
,files
in os
.walk(base
):
113 root
= root
.replace(base
, '', 1)
115 # strip ignored directories from the list
118 for filename
in files
:
119 if filename
in file_ignore
:
123 # try to figure out the language of the specified file
124 fullpath
= os
.path
.join(base
, root
, filename
)
125 language
= lang_type(fullpath
)
127 # if the file is one of the langauges that we want return
128 # its name and the language
129 if language
in languages
:
130 yield fullpath
, language
132 def update_file(dst
, src
, language
, mutator
):
133 '''update a file of the specified language with the provided
134 mutator generator. If inplace is provided, update the file in
135 place and return the handle to the updated file. If inplace is
136 false, write the updated file to cStringIO'''
138 # if the source and destination are the same, we're updating in place
141 if isinstance(src
, str):
142 # if a filename was provided, open the file
147 src
= file(src
, mode
)
151 # grab all of the lines of the file and strip them of their line ending
152 old_lines
= list(line
.rstrip('\r\n') for line
in src
.xreadlines())
153 new_lines
= list(mutator(old_lines
, src
.name
, language
))
155 for line
in src
.xreadlines():
159 # if we're updating in place and the file hasn't changed, do nothing
160 if old_lines
== new_lines
:
163 # otherwise, truncate the file and seek to the beginning.
167 elif isinstance(dst
, str):
168 # if we're not updating in place and a destination file name
169 # was provided, create a file object
172 for line
in new_lines
: