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