1#!/usr/bin/python3 2import re 3import argparse 4 5parser = argparse.ArgumentParser() 6parser.add_argument('inputs', nargs='+', help='Input filename') 7parser.add_argument('--min_lines', type=int, default=1, help='Specify the min number of lines to rearrange') 8args = parser.parse_args() 9 10min_num_lines = args.min_lines 11 12filename_regex = '(src|source|unit_test|include)/.*$' 13 14# caveat: Does fully not handle numbers with different number of digits. 15def compare_strs(str1, str2, num_sort=True): 16 winner = 0 # which one's bigger 17 num_sort_mode = False 18 for i in range(min(len(str1),len(str2))): 19 if winner == 0: 20 if num_sort: 21 if str1[i].isdigit() and str2[i].isdigit(): 22 if num_sort_mode: 23 str1_num += str1[i] 24 str2_num += str2[i] 25 else: 26 num_sort_mode = True 27 str1_num = str1[i] 28 str2_num = str2[i] 29 elif num_sort_mode: 30 if str1[i].isdigit(): str1_num += str1[i] 31 if str2[i].isdigit(): str2_num += str2[i] 32 winner = int(str1_num) - int(str2_num) 33 num_sort_mode = False 34 if winner != 0: break 35 if str1[i] != str2[i] and not num_sort_mode: 36 if str2[i].isdigit(): 37 winner = -1 38 elif str1[i].isdigit() or str1[i] > str2[i]: 39 winner = 1 40 else: 41 winner = -1 42 if num_sort_mode: # if it's still in num_sort_mode then find the results 43 if len(str1)-1 > i: 44 i += 1 45 if str1[i].isdigit(): str1_num += str1[i] 46 elif len(str2)-1 > i: 47 i += 1 48 if str2[i].isdigit(): str2_num += str2[i] 49 if int(str1_num) > int(str2_num): 50 winner = 1 51 elif int(str1_num) < int(str2_num): 52 winner = -1 53 num_sort_mode = False 54 55 if winner == 0: 56 if str2[i].isdigit(): 57 winner = -1 58 elif str1[i].isdigit() or str1[i] > str2[i]: 59 winner = 1 60 else: 61 winner = -1 62 return winner 63 64 65def cmp_to_key(mycmp): 66 'Convert a cmp= function into a key= function' 67 class K: 68 def __init__(self, obj, *args): 69 self.obj = obj 70 def __lt__(self, other): 71 return mycmp(self.obj, other.obj) < 0 72 def __gt__(self, other): 73 return mycmp(self.obj, other.obj) > 0 74 def __eq__(self, other): 75 return mycmp(self.obj, other.obj) == 0 76 def __le__(self, other): 77 return mycmp(self.obj, other.obj) <= 0 78 def __ge__(self, other): 79 return mycmp(self.obj, other.obj) >= 0 80 def __ne__(self, other): 81 return mycmp(self.obj, other.obj) != 0 82 return K 83 84def custom_sort(listy): 85 for _ in range(len(listy)-1+1): 86 for i in range(len(listy)-1): 87 bigger = compare_strs(listy[i], listy[i+1]) 88 if bigger > 0: 89 tmp_str = listy[i] 90 listy[i] = listy[i+1] 91 listy[i+1] = tmp_str 92 return listy 93 94# file_lines = [l.strip(stripchars) for l in file_lines] 95# currently sorting by first number in filename. smallest numbers first 96# this thing may need the ability to recognize filenames 97# file_lines = sorted(file_lines, key=lambda line: int(re.search('\d+', line.split('/')[-1] + ' 0').group(0))) 98input_filenames=args.inputs 99for input_filename in input_filenames: 100 with open(input_filename,'r') as file: 101 file_lines = file.read().split('\n') 102 output_filename=input_filename 103 files_range = [] # is a tuple 104 filenames_ranges = [] 105 for i, line in enumerate(file_lines): 106 if re.search(filename_regex, line): 107 if files_range == []: 108 files_range.append(i) 109 else: 110 if files_range != []: 111 files_range.append(i-1) 112 # manages min num lines 113 if files_range[1] - files_range[0] + 1 >= min_num_lines:filenames_ranges.append(files_range) 114 files_range = [] 115 if files_range != []: 116 files_range.append(i-1) 117 # manages min num lines 118 if files_range[1] - files_range[0] + 1 >= min_num_lines:filenames_ranges.append(files_range) 119 files_range = [] 120 121 122 for x in filenames_ranges: 123 # accommodate for a close bracket at the end of the last filename 124 if file_lines[x[1]][-1] == ')': 125 append_chars = ')' 126 file_lines[x[1]] = file_lines[x[1]][:-1] 127 else: 128 append_chars = '' 129 130 new_lines = sorted(file_lines[x[0]:x[1]+1], key=cmp_to_key(compare_strs)) 131 for i, l in enumerate(range(x[0], x[1]+1)): 132 file_lines[l] = new_lines[i] 133 if l == x[1]: 134 file_lines[l] += append_chars 135 136 with open(output_filename, 'w') as file: 137 file.write('\n'.join(file_lines)) 138