/
thomas-king
/
Raze
Обзор
Документация
Войти
/
thomas-king
/
Raze
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
main
main.cpp
402 строки
11 KB
Ace Rodstin
Update app to version 2.0.1
23 ноя 2023, 13:38
23 ноя 2023, 13:38
7798b38
Код
Авторство
О чём код?
// // main.cpp // Raze // // Created by Ace Rodstin on 11/15/23. // Updated by Ace Rodstin on 11/28/23. // // Copyright (C) Ace Rodstin 2023. All rights reserved. // #include "ArgumentsParser/Services/ArgumentsParser.h" #include "ArgumentsParser/Models/ArgumentBundle.h" #include "Manual/Services/ManualBuilder.h" #include "Raze/Services/CommandsBuilder.h" #include "Raze/Services/Logger.h" #include "Library/Shell.h" #include "Library/ProgressIndicatorBuilder.h" #include <iostream> #include <string> #include <termios.h> #include <unistd.h> using namespace std; using namespace manual; using namespace lib; namespace args { ArgumentBundle help { "--help" }; ArgumentBundle version { "--version" }; ArgumentBundle includeDirectory { "-i", "--include-directory", }; ArgumentBundle libraryDirectory { "-l", "--library-directory" }; ArgumentBundle exclude { "-e", "--exclude" }; ArgumentBundle buildDirectory { "-b", "--build-directory" }; ArgumentBundle target { "-t", "--target" }; ArgumentBundle debugInfo { "-d", "--debug-info" }; ArgumentBundle verbose { "-v", "--verbose" }; ArgumentBundle ignoreCache { "--ignore-cache" }; ArgumentBundle disableLogs { "--logs-disabled" }; } struct termios snapshot; struct termios current; void configureTerminal(); void restoreTerminal(void); void showHint(); void showHelp(); void showAbout(); void showWarning(string argument); void showProgressIndicator( ProgressIndicatorBuilder builder, ProgressIndicatorBuilder::BuildOptions buildOptions ); void hideProgressIndicator(ProgressIndicatorBuilder builder); void run(CommandsBuilder::BuildOptions buildOptions); int main(int argc, char** argv) { configureTerminal(); ArgumentsParser argumentsParser {}; auto arguments = argumentsParser.parse(argc, argv); auto argument = arguments.next(); // Skip current directory argument if (!arguments.hasMore()) { showHint(); return EXIT_SUCCESS; } CommandsBuilder::BuildOptions commandsBuildOptions; while (arguments.hasMore()) { auto argument = arguments.next(); if (args::help.contains(argument)) { showHelp(); return EXIT_SUCCESS; } if (args::version.contains(argument)) { showAbout(); return EXIT_SUCCESS; } if (args::includeDirectory.contains(argument)) { argument = arguments.next(); commandsBuildOptions.includeDirectory = argument; continue; } if (args::libraryDirectory.contains(argument)) { argument = arguments.next(); commandsBuildOptions.libraryDirectory = argument; continue; } if (args::exclude.contains(argument)) { argument = arguments.next(); commandsBuildOptions.excluded.push_back(argument); continue; } if (args::buildDirectory.contains(argument)) { argument = arguments.next(); commandsBuildOptions.buildDirectory = argument; continue; } if (args::target.contains(argument)) { argument = arguments.next(); commandsBuildOptions.target = argument; argument = arguments.next(); commandsBuildOptions.sourceFile = argument; continue; } if (args::debugInfo.contains(argument)) { commandsBuildOptions.emitDebugInfo = true; continue; } if (args::verbose.contains(argument)) { commandsBuildOptions.isVerbose = true; continue; } if (args::ignoreCache.contains(argument)) { commandsBuildOptions.ignoreCache = true; continue; } if (args::disableLogs.contains(argument)) { commandsBuildOptions.isLogsEnabled = false; continue; } showWarning(argument); showHint(); return EXIT_SUCCESS; } run(commandsBuildOptions); return EXIT_SUCCESS; } void configureTerminal() { tcgetattr(STDIN_FILENO, &snapshot); atexit(restoreTerminal); tcgetattr(STDIN_FILENO, ¤t); current.c_lflag &= ~ECHO; tcsetattr(STDIN_FILENO, TCSAFLUSH, ¤t); } void restoreTerminal() { tcsetattr(STDIN_FILENO, TCSANOW, &snapshot); } void showHint() { string hint = "Run the app with \"--help\" argument to show help info for."; cout << hint << endl; } void showHelp() { Table table { Column { Cell { "ARGUMENTS" }, Cell { "--help" }, Cell { "--version" }, Cell { "-i, --include-directory" }, Cell { "-l, --library-directory" }, Cell { "-e, --exclude" }, Cell { "-b, --build-directory" }, Cell { "-t, --target" }, Cell { "-d, --debug-info" }, Cell { "-v, --verbose" }, Cell { "--ignore-cache" }, Cell { "--logs-disabled" } }, Column { Cell { "OPTIONS" }, Cell { "" }, Cell { "" }, Cell { "<dir>" }, Cell { "<dir>" }, Cell { "<dir> or <file>" }, Cell { "<dir>" }, Cell { "<name> <source file>" }, Cell { "" }, Cell { "" }, Cell { "" }, Cell { "" }, }, Column { Cell { "DESCRIPTION" }, Cell { "Show this help message." }, Cell { "Show about app info." }, Cell { "Set directory to search header files for." }, Cell { "Set directory to search library files for." }, Cell { "Exclude directory or source file against compilation process." }, Cell { "Set directory for produced build files." }, Cell { "Set target name for specific source file." }, Cell { "Emit debug info." }, Cell { "Show building process" }, Cell { "Build ignoring cache." }, Cell { "Disable logging of build process to a file." } } }; ManualBuilder builder { table }; auto manual = builder.build(); cout << manual << endl; } void showAbout() { string appName = "Raze"; string appVersion = "v2.0.1"; string copyright = "Copyright (C) Ace Rodstin 2023. All rights reserved."; cout << appName << " " << appVersion << endl; cout << copyright << endl; } void showWarning(string argument) { cout << "Invalid argument \"" << argument << "\"." << endl; } void showProgressIndicator( ProgressIndicatorBuilder builder, ProgressIndicatorBuilder::BuildOptions buildOptions ) { hideProgressIndicator(builder); builder.setBuildOptions(buildOptions); cout << builder.build() << flush; if (int(buildOptions.progress) == 1) { cout << endl; } } void hideProgressIndicator(ProgressIndicatorBuilder builder) { auto prevIndicator = builder.build(); auto clearingStr = string(prevIndicator.size(), ' '); cout << "\r" << clearingStr << flush; cout << "\r" << flush; } void run(CommandsBuilder::BuildOptions commandsBuildOptions) { CommandsBuilder commandsBuilder {}; ProgressIndicatorBuilder indicatorBuilder {}; ProgressIndicatorBuilder::BuildOptions indicatorBuildOptions {}; indicatorBuildOptions.barWidth = 30; path logsDirectory { commandsBuildOptions.buildDirectory }; Logger logger { logsDirectory }; logger.removeLogs(); try { commandsBuilder.validate(commandsBuildOptions); } catch (const CommandsBuilder::ServiceError& error) { cout << error.message() << endl; return; } if (!commandsBuildOptions.isVerbose) { indicatorBuildOptions.label = "Prepearing"; indicatorBuildOptions.progress = 0.0; showProgressIndicator(indicatorBuilder, indicatorBuildOptions); } if (commandsBuildOptions.isLogsEnabled) { stringstream event; event << "Building a target \"" << commandsBuildOptions.target << "\"."; logger.log(event.str()); } commandsBuilder.setBuildOptions(commandsBuildOptions); auto commands = commandsBuilder.build(); auto commandsCount = commands.size(); for (int i = 0; i < commandsCount; i++) { auto command = commands[i]; if (commandsBuildOptions.isVerbose) { cout << command.rawValue << endl; } else { switch (command.kind) { case Command::Kind::COMPILE: indicatorBuildOptions.label = "Compiling"; break; case Command::Kind::BUILD: indicatorBuildOptions.label = "Building"; break; } indicatorBuildOptions.progress = double(i) / double(commandsCount); showProgressIndicator(indicatorBuilder, indicatorBuildOptions); } if (commandsBuildOptions.isLogsEnabled) { logger.log(command.rawValue); } try { auto output = Shell::execute(command.rawValue); } catch (const Shell::ServiceError& error) { auto reason = error.getReason(); auto output = error.getOutput(); if (!commandsBuildOptions.isVerbose) { hideProgressIndicator(indicatorBuilder); } string errorMessage = ""; switch (reason) { case Shell::ServiceError::Reason::EXECUTION_FAILED: errorMessage = "Internal error. Contact support team."; break; case Shell::ServiceError::Reason::RESULT_FAILURE: errorMessage = output; break; } cout << errorMessage << endl; if (commandsBuildOptions.isLogsEnabled) { logger.log(errorMessage); } return; } catch (...) { if (!commandsBuildOptions.isVerbose) { hideProgressIndicator(indicatorBuilder); } string errorMessage = "Internal error. Contact support team."; cout << errorMessage << endl; if (commandsBuildOptions.isLogsEnabled) { logger.log(errorMessage); } return; } } if (!commandsBuildOptions.isVerbose) { indicatorBuildOptions.label = "Done"; indicatorBuildOptions.progress = 1.0; showProgressIndicator(indicatorBuilder, indicatorBuildOptions); } if (commandsBuildOptions.isLogsEnabled) { stringstream event; event << "The target \"" << commandsBuildOptions.target << "\" has been successfully built."; logger.log(event.str()); } }