#!/usr/bin/env python3 # sort_filenames_in_pro_files.py # Copyright 2025 Andreas Nicolai # # Script to automatically sort entries in SOURCES and HEADER sections of all # qmake pro files below the given top-level directory. # # Syntax: sort_filenames_in_pro_files.py [] # # is the top-level directory, below which pro files # are searched for (recursively). If missing, the current working # directory will be used. import os import re from pathlib import Path def find_pro_files(root_dir): pro_files = [] for dirpath, dirnames, filenames in os.walk(root_dir): for filename in filenames: if filename.endswith('.pro'): full_path = os.path.join(dirpath, filename) pro_files.append(full_path) return pro_files def process_multiline_section(lines, start_idx): """Extract, sort, and reformat a multiline += section.""" section_lines = [] idx = start_idx + 1 while idx < len(lines): line = lines[idx].rstrip() if not line or line.startswith("#"): break if re.match(r'^\w+\s*\+=', line): # another section starts break section_lines.append(line.strip(' \\')) idx += 1 # Sort and reformat with backslashes section_lines = sorted(section_lines) for i in range(len(section_lines) - 1): section_lines[i] += ' \\\n' if len(section_lines) > 0: section_lines[-1] += '\n' return section_lines, idx def process_file(filepath): with open(filepath, 'r', encoding='utf-8') as f: lines = f.readlines() i = 0 while i < len(lines): line = lines[i].strip() if line.startswith('SOURCES +='): sorted_section, end_idx = process_multiline_section(lines, i) lines = lines[:i+1] + sorted_section + lines[end_idx:] i = end_idx elif line.startswith('HEADERS +='): sorted_section, end_idx = process_multiline_section(lines, i) lines = lines[:i+1] + sorted_section + lines[end_idx:] i = end_idx else: i += 1 with open(filepath, 'w', encoding='utf-8') as f: f.writelines(lines) if __name__ == "__main__": import argparse parser = argparse.ArgumentParser( description="Sort filenames in all .pro files with a directory tree.") parser.add_argument("directory", nargs="?", default=os.getcwd(), help="Root directory to scan (default: current working directory)") args = parser.parse_args() pro_files = find_pro_files(args.directory) print(f"\nProcessing .pro files below '{args.directory}':") for file in pro_files: print(file) process_file(file)