123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113 |
- #!/usr/bin/env python3
- # -*- coding: utf-8 -*-
- #
- # 2014, By konstin (http://github/konstin)
- # 2015, Modified by leyyin
- #
- # Removes all trailing whitespaces and replaces all tabs with four spaces, the
- # files with a given extension in a recursively searched directory.
- # It can also count the number of code lines excluding comments and blank
- # lines.
- #
- # Tested with python 2.7 and python 3
- import os
- import argparse
- import sys
- def main(directory, is_statistics, is_dry_run, extensions, comments_start):
- lines_total = 0
- lines_comments = 0
- file_counter = 0
- files_affected = 0
- for dir_path, _, file_names in os.walk(directory):
- if is_statistics:
- file_counter += len(file_names)
- for file_name in file_names:
- _, file_extension = os.path.splitext(file_name)
- # File does not have an extension
- if not file_extension:
- continue
- # Not a valid extension. Note: extensions have in the 0 position a dot, eg: '.hpp', '.cpp'
- if file_extension[1:] not in extensions:
- continue
- if is_statistics:
- files_affected += 1
- # Read whole file
- path_file = os.path.join(dir_path, file_name)
- with open(path_file, 'r') as f:
- lines = f.readlines()
- if is_statistics:
- lines_total += len(lines)
- # Scan lines
- is_modified = False
- for i, line in enumerate(lines):
- original_line = line
- # Replace tabs with four spaces
- line = line.replace('\t', ' ')
- line_rstrip = line.rstrip()
- if line_rstrip: # Don't de-indent empty lines
- line = line_rstrip + '\n'
- # Count the number of comments
- if is_statistics:
- line_lstrip = line.lstrip()
- if any([line_lstrip.startswith(c) for c in comments_start]):
- lines_comments += 1
- # Indicate that we want to write to the current file
- if original_line != line:
- lines[i] = line # Replace original line
- if not is_modified:
- is_modified = True
- # Write back modified lines
- if not is_dry_run and is_modified:
- with open(path_file, 'w') as f:
- f.writelines(lines)
- if is_statistics:
- print('Total number of files in {0}: {1}'.format(directory, file_counter))
- print('Total number of files affected in {0}: {1}'.format(directory, files_affected))
- print('Lines in total: {0}'.format(lines_total))
- print(' empty/comments: {0}'.format(lines_comments))
- print('↳ excluding comments and blank lines: {0}'.format(lines_total - lines_comments), end='\n' * 2)
- print('Finished.')
- if __name__ == '__main__':
- parser = argparse.ArgumentParser(description='Remove whitespace from C/C++ files.')
- parser.add_argument('directory', default='../src', nargs='?',
- help='the directory where all the source files are located. (default: %(default)s)')
- parser.add_argument('--dry-run', dest='dry_run', action='store_true',
- help='do a dry run. Do not modify/write any files. (default: %(default)s)')
- parser.add_argument('--statistics', dest='statistics', action='store_true',
- help='display statistics (count files and lines if enabled). On by default.')
- parser.add_argument('--no-statistics', dest='statistics', action='store_false', help='do not display statistics.')
- parser.add_argument('--extensions', default=["cpp", "hpp", "c", "h"], nargs='+',
- help='set file extensions. Eg: --extensions cpp hpp (default: %(default)s).')
- parser.add_argument('--comments-start', default=['//', '/*', '*'], nargs='+',
- help='set how line comments start. Eg: --comments-start // \'*\'. (default: %(default)s).')
- parser.set_defaults(statistics=True)
- parser.set_defaults(dry_run=False)
- args = parser.parse_args()
- if not os.path.exists(args.directory):
- print('ERROR: The directory {0} does not exist'.format(args.directory))
- sys.exit(1)
- print(args)
- main(args.directory, args.statistics, args.dry_run, args.extensions, args.comments_start)
|