#include "resources/config.h" #include #include #include #include #include #include #include #include #include using namespace std; using namespace CppUtilities; using namespace CppUtilities::EscapeCodes; void addStringsFromFiles(bool enableDebugOutput, set &to, const vector &files, const char *searchPattern, initializer_list relevantCaptures) { const regex searchRegex(searchPattern); thread_local smatch match; for (const auto &file : files) { if (enableDebugOutput) { cerr << Phrases::Info << "Processing " << file << Phrases::End; } try { const auto fileContents = readFile(file.c_str()); for(auto searchPosition = fileContents.cbegin(); regex_search(searchPosition, fileContents.cend(), match, searchRegex); searchPosition = match.suffix().first) { for (const auto captureIndex : relevantCaptures) { to.insert(match[captureIndex]); } if (enableDebugOutput) { for (size_t i = 0, end = match.size(); i != end; ++i) { cerr << i << ": " << match[i] << '\n'; } } } } catch (const std::ios_base::failure &failure) { cerr << Phrases::Warning << "Unable to read " << file << ": " << failure.what() << Phrases::End; } } } int main(int argc, char *argv[]) { // setup argument parser SET_APPLICATION_INFO; ArgumentParser parser; Argument projectDirsArg("project-dirs", 'd', "specifies the project directories to search for icons"); projectDirsArg.setValueNames({ "path" }); projectDirsArg.setRequiredValueCount(Argument::varValueCount); projectDirsArg.setConstraints(1, 1); projectDirsArg.setImplicit(true); ConfigValueArgument debugArg("debug", '\0', "enables debug output"); HelpArgument helpArg(parser); parser.setMainArguments({ &projectDirsArg, &debugArg, &helpArg }); // parse specified arguments parser.parseArgs(argc, argv); // find relevant files vector uiFiles, cppFiles, qmlFiles; for (const auto *projectDir : projectDirsArg.values()) { for(const auto &item: filesystem::recursive_directory_iterator(projectDir)) { if (!item.is_regular_file() && !item.is_symlink()) { continue; } auto path(item.path()); const auto extension(path.extension()); if (extension == ".ui") { uiFiles.emplace_back(path); } else if (extension == ".cpp" || extension == ".cxx") { cppFiles.emplace_back(path); } else if (extension == ".qml") { qmlFiles.emplace_back(path); } } } // search files for patterns set iconNames; addStringsFromFiles(debugArg.isPresent(), iconNames, uiFiles, "", { 1 }); addStringsFromFiles(debugArg.isPresent(), iconNames, cppFiles, "QIcon::fromTheme\\(QStringLiteral\\(\"([^\"]+)\"\\)\\)", { 1 }); addStringsFromFiles(debugArg.isPresent(), iconNames, qmlFiles, "(icon|icon\\.name|iconName|source)\\: (\"([^\"]+)\"|[^\\?]* \\? \"([^\"]+)\" : \"([^\"]+)\"|[^\\?]* \\? \\([^\\?]* \\? \"([^\"]+)\" : \"([^\"]+)\"\\) : \\([^\\?]* \\? \"([^\"]+)\" : \"([^\"]+)\"\\))", { 3, 4, 5, 6, 7, 8, 9 }); // print results iconNames.erase(string()); for (const auto &iconName : iconNames) { cout << iconName << '\n'; } }