// localize_tool.cpp #include #include #include #include #include #include #include // Read a single character without waiting for Enter (disable canonical mode and echo) char getch() { char buf = 0; struct termios old = {0}; if (tcgetattr(STDIN_FILENO, &old) < 0) { perror("tcgetattr"); return 0; } struct termios raw = old; raw.c_lflag &= ~(ICANON | ECHO); raw.c_cc[VMIN] = 1; raw.c_cc[VTIME] = 0; if (tcsetattr(STDIN_FILENO, TCSANOW, &raw) < 0) { perror("tcsetattr"); return 0; } if (read(STDIN_FILENO, &buf, 1) < 0) { perror("read"); buf = 0; } // Restore terminal settings if (tcsetattr(STDIN_FILENO, TCSANOW, &old) < 0) { perror("tcsetattr restore"); } return buf; } int main(int argc, char* argv[]) { if (argc != 3) { std::cerr << "Usage: " << argv[0] << " \n"; return 1; } const std::string inPath = argv[1]; const std::string outPath = argv[2]; // Read entire file into a string std::ifstream ifs(inPath); if (!ifs) { std::cerr << "Error: cannot open input file: " << inPath << "\n"; return 1; } std::ostringstream buf; buf << ifs.rdbuf(); std::string content = buf.str(); // Regex for C-style string literals: "…" std::regex re(R"("([^"\\]|\\.)*")"); std::string result; std::smatch m; std::string::const_iterator searchStart(content.cbegin()); size_t processedUpTo = 0; while (std::regex_search(searchStart, content.cend(), m, re)) { auto litPos = m.position(0) + processedUpTo; auto litLen = m.length(0); std::string lit = m.str(0); // Copy up to the literal result.append(content, processedUpTo, litPos - processedUpTo); // Check if already wrapped bool already = false; if (litPos >= 11 && content.substr(litPos - 11, 11) == "__LOCALIZE(") || (litPos >= 18 && content.substr(litPos - 18, 18) == "__LOCALIZE_VERFMT(")) { already = true; } if (already) { result += lit; } else { // Extract full line for context size_t lineStart = content.rfind('\n', litPos); lineStart = (lineStart == std::string::npos ? 0 : lineStart + 1); size_t lineEnd = content.find('\n', litPos); if (lineEnd == std::string::npos) lineEnd = content.size(); std::string line = content.substr(lineStart, lineEnd - lineStart); // Prompt user std::cout << "\nIn file `" << inPath << "`, line:\n" << line << "\n" << "Wrap this string literal " << lit << "? [y/N] "; char ans = getch(); std::cout << ans << '\n'; if (ans == 'y' || ans == 'Y') { result += "__LOCALIZE(" + lit + ",\"section\")"; } else { result += lit; } } processedUpTo = litPos + litLen; searchStart = content.cbegin() + processedUpTo; } // Append remainder result.append(content, processedUpTo, content.size() - processedUpTo); // Write out std::ofstream ofs(outPath); if (!ofs) { std::cerr << "Error: cannot open output file: " << outPath << "\n"; return 1; } ofs << result; std::cout << "\nDone! Written to " << outPath << "\n"; return 0; }