diff --git a/Makefile b/Makefile index 43e516a..12bb05e 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,8 @@ CC=g++ SRC=cli-flag-collection.cpp -dynamic-dev: - ${CC} ${SRC} -Wall -march=native -std=c++23 -o cfc-cli-dynamic +debug-dev: + ${CC} ${SRC} -Wall -march=native -DDEBUG -std=c++23 -o cfc-cli-debug static: - ${CC} ${SRC} -Wall -Werror -march=native -O3 -flto -fomit-frame-pointer -static -std=c++23 -o cfc-cli-static + ${CC} ${SRC} -Wall -Werror -march=native -O3 -flto -fomit-frame-pointer -DNDEBUG -static -std=c++23 -o cfc-cli-static release: - ${CC} ${SRC} -Wall -Werror -march=native -O3 -flto -fomit-frame-pointer -std=c++23 -o cfc-cli-release + ${CC} ${SRC} -Wall -Werror -march=native -O3 -flto -fomit-frame-pointer -DNDEBUG -std=c++23 -o cfc-cli-release diff --git a/README.md b/README.md index cc0f412..ed6fb32 100644 --- a/README.md +++ b/README.md @@ -24,26 +24,26 @@ For now my program is not in any repo so you have to build it from source. Firstly you pull this repo with: -``` +```bash git clone https://codeberg.org/MysteryBirb/cli-flag-collection.git ``` then cd into it: -``` +```bash cd cli-flag-collection ``` To compile the dynamic version without any optimizations you just run `make`. For the release and release static build you can run: -``` +```bash make static ``` -or +or (recommended) -``` +```bash make release ``` diff --git a/cfc-cli-debug b/cfc-cli-debug new file mode 100755 index 0000000..4fdc5d5 Binary files /dev/null and b/cfc-cli-debug differ diff --git a/cli-flag-collection.cpp b/cli-flag-collection.cpp index 8c87549..08f0cce 100644 --- a/cli-flag-collection.cpp +++ b/cli-flag-collection.cpp @@ -1,174 +1,183 @@ #include -#include -#include -#include #include -#include +#include #include +#include +#include +#include +#include + +#ifdef DEBUG +#define DEBUG_PRINT(x) std::print x +#else +#define DEBUG_PRINT(x) +#endif #define HELP 1000 #define LIST 1001 -int flagWidth; -int flagHeight; +int flagWidth = 0; +int flagHeight = 0; std::string flagStr(" "); void drawFlag(const unsigned char flagArray[][3], unsigned char flagStripes) { - short i, y, j, uni = 0; - short divLen = flagStr.size(); - - // Hopefully will handle all unicode things in a string - for (int k : flagStr) { - if (k < 0 && uni != 2) { - uni++; - } - if (uni == 2) { - divLen -= 1; - uni = 0; - } - } - //std::println("Divided length: {0} ({1} / {2})", (flagWidth / divLen), flagWidth, divLen); + short i, y, j, uni = 0; + short rest = 0; + short divLen = flagStr.size(); - for (i = 0; i < flagStripes; i++) { - if (flagHeight / flagStripes <= 0) { - std::cerr << "Integer too small!" << std::endl; - break; - } - for (y = 0; y < flagHeight / flagStripes; y++) { - if (flagStr != " ") { - flagStr.shrink_to_fit(); - std::print("\x1b[38;2;{0};{1};{2}m", flagArray[i][0], flagArray[i][1], flagArray[i][2]); - } - else { - std::print("\x1b[48;2;{0};{1};{2}m", flagArray[i][0], flagArray[i][1], flagArray[i][2]); - } - for (j = 0; j < flagWidth / divLen; j++) { - std::print("{0}", flagStr); - } - } - std::println("\x1b[0m"); - } + // Hopefully will handle all unicode things in a string + for (int k : flagStr) { + if (k < 0 && uni != 2) { + uni += 1; + } + if (uni == 2) { + divLen -= 1; + uni = 0; + } + } + rest = (flagWidth % divLen); + DEBUG_PRINT(("Pre: {0}, After {1}\n", flagWidth, (flagWidth % divLen))); + + for (i = 0; i < flagStripes; i++) { + if (flagHeight / flagStripes <= 0) { + std::cerr << "Integer too small!" << std::endl; + break; + } + for (y = 0; y < flagHeight / flagStripes; y++) { + if (flagStr != " ") { + flagStr.shrink_to_fit(); + std::print("\x1b[38;2;{0};{1};{2}m", flagArray[i][0], flagArray[i][1], flagArray[i][2]); + } + else { + std::print("\x1b[48;2;{0};{1};{2}m", flagArray[i][0], flagArray[i][1], flagArray[i][2]); + } + for (j = 0; j < (flagWidth / divLen); j++) { + std::print("{0}", flagStr); + } + for (short l = 0; l < rest; l++) { + std::print("{0}", flagStr.at(l)); + } + } + std::println("\x1b[0m"); + } } int main(int argc, char **argv) { - /* - * TODO: - * - Bi flag handle - * - add more flags for inclusivity - */ + /* + * TODO: + * - Bi flag handle + * - add more flags for inclusivity + */ - //std::setlocale(LC_CTYPE, "de_DE.utf8"); - //std::locale::global(std::locale("de_DE.utf8")); + static struct option long_options[]{ + {"help", no_argument, nullptr, HELP}, + {"list", no_argument, nullptr, LIST}, + {"flag", required_argument, nullptr, 'f'}, + {"height", required_argument, nullptr, 'h'}, + {"string", required_argument, nullptr, 's'}, + {nullptr, 0, nullptr, 0}, + }; - static struct option long_options[] { - {"help", no_argument, nullptr, HELP}, - {"list", no_argument, nullptr, LIST}, - {"flag", required_argument, nullptr, 'f'}, - {"height", required_argument, nullptr, 'h'}, - {"string", required_argument, nullptr, 's'}, - {nullptr, 0, nullptr, 0}, - }; + struct winsize size; + ioctl(STDOUT_FILENO, TIOCGWINSZ, &size); + flagWidth = size.ws_col; + flagHeight = size.ws_row; - struct winsize size; - ioctl(STDOUT_FILENO, TIOCGWINSZ, &size); - flagWidth = size.ws_col; - flagHeight = size.ws_row; - - // All available flags - const unsigned char prideFlag[6][3] = {{255, 30, 38}, {255, 141, 0}, {255, 238, 0}, {2, 129, 33}, {0, 76, 255}, {119, 0, 136}}; - const unsigned char transFlag[5][3] = {{91, 206, 250}, {245, 169, 184}, {255, 255, 255}, {245, 169, 184}, {91, 206, 250}}; - const unsigned char lesbianFlag[5][3] = {{212, 44, 0}, {253, 152, 85}, {255, 255, 255}, {209, 97, 162}, {162, 1, 97}}; - const unsigned char dutchFlag[3][3] = {{220, 16, 46}, {255, 255, 255}, {0, 61, 165}}; - const unsigned char biFlag[3][3] = {{214, 2, 112}, {155, 79, 150}, {0, 56, 168}}; - unsigned char flagStripes; + // All available flags + const unsigned char prideFlag[6][3] = {{255, 30, 38}, {255, 141, 0}, {255, 238, 0}, {2, 129, 33}, {0, 76, 255}, {119, 0, 136}}; + const unsigned char transFlag[5][3] = {{91, 206, 250}, {245, 169, 184}, {255, 255, 255}, {245, 169, 184}, {91, 206, 250}}; + const unsigned char lesbianFlag[5][3] = {{212, 44, 0}, {253, 152, 85}, {255, 255, 255}, {209, 97, 162}, {162, 1, 97}}; + const unsigned char dutchFlag[3][3] = {{220, 16, 46}, {255, 255, 255}, {0, 61, 165}}; + const unsigned char biFlag[3][3] = {{214, 2, 112}, {155, 79, 150}, {0, 56, 168}}; + const unsigned char nonBinaryFlag[4][3] = {{252, 244, 52}, {255, 255, 255}, {156, 89, 209}, {44, 44, 44}}; + unsigned char flagStripes; - // Array of all available flags - const std::string allFlags[] = {"pride", "trans", "lesbian", "dutch", "bi"}; + // Array of all available flags + const std::string allFlags[] = {"pride", "trans", "lesbian", "dutch", "bi", "non-binary"}; - short allFlagsSize = sizeof(allFlags) / sizeof(allFlags[0]); - int opt; + short allFlagsSize = sizeof(allFlags) / sizeof(allFlags[0]); + int opt; - while ((opt = getopt_long(argc, argv, "h:s:f:", long_options, nullptr)) != -1) { - switch (opt) { - case '0': - std::print("{}", opt); - return 1; - case 'h': - if (argc <= 3) { - std::cerr << "You can't run '" << argv[1] << "' alone!\n"; - return 1; - } - else { - flagHeight = atoi(argv[optind - 1]); - } - break; - case 's': - if (argc == 3 || argc == 2) { - std::cerr << "You can't run '" << argv[1] << "' alone!\n"; - return 1; - } - else { - flagStr = argv[optind - 1]; // I will keep this at index 0 so it can't even break it for now - } - break; - case 'f': - if (optind > argc) { - std::cerr << "Missing [flag] argument!\nusage: " << argv[0] << " [-f] [flag]\n"; - return 1; - } - else { - std::string strArgv(argv[(optind - 1)]); - std::transform(strArgv.begin(), strArgv.end(), strArgv.begin(), ::tolower); - - if (strArgv.compare(allFlags[0]) == 0) { - flagStripes = 6; - drawFlag(prideFlag, flagStripes); - } - else if (strArgv.compare(allFlags[1]) == 0) { - flagStripes = 5; - drawFlag(transFlag, flagStripes); - } - else if (strArgv.compare(allFlags[2]) == 0) { - flagStripes = 5; - drawFlag(lesbianFlag, flagStripes); - } - else if (strArgv.compare(allFlags[3]) == 0) { - flagStripes = 3; - drawFlag(dutchFlag, flagStripes); - } - else if (strArgv.compare(allFlags[4]) == 0) { - flagStripes = 3; - drawFlag(biFlag, flagStripes); - } - else { - std::cerr << argv[0] << ": invalid option '" << strArgv << "'\n"; - std::cerr << "Usage: " << argv[0] << " [OPTION] [VALUE] -f [FLAG]\n"; - return 1; - } - } - break; - case LIST: - std::print("All available [FLAGS]:\n"); - for (short k = 0; k < allFlagsSize; k++) { - std::print("{0}\n", allFlags[k]); - } - return 0; - case HELP: - std::cout << "Usage: " << argv[0] << " [OPTION] [ARGUMENT] -f [FLAG]\n" - << "All options:\n" - << "\t-f, --flag [FLAG]\t\tPrints the chosen flag\n" - << "\t-h, --height [Integer]\t\tPrints the flag with the chosen positive integer\n" - << "\t-s, --string \'[String]\'\t\tPrint the chosen flag with the given string (Flag width is not yet perfectly variable)\n" - << "\t--list\t\t\t\tList all available flags\n" - << "\t--help\t\t\t\tPrints out the help screen\n"; - return 0; - case '?': - std::cerr << "No matching [OPTION]!\n"; - return 1; - default: - std::cerr << "Usage: " << argv[0] << " [OPTION] [VALUE] -f [FLAG]" << std::endl; - return 1; - } - } - return 0; + while ((opt = getopt_long(argc, argv, "h:s:f:", long_options, nullptr)) != -1) { + switch (opt) { + case '0': + std::print("{}", opt); + return 1; + case 'h': + if (argc <= 3) { + std::cerr << "You can't run '" << argv[1] << "' alone!\n"; + return 1; + } + else { + flagHeight = atoi(argv[optind - 1]); + } + break; + case 's': + if (argc == 3 || argc == 2) { + std::cerr << "You can't run '" << argv[1] << "' alone!\n"; + return 1; + } + else { + flagStr = argv[optind - 1]; + } + break; + case 'f': + if (optind > argc) { + std::cerr << "Missing [flag] argument!\nusage: " << argv[0] << " [-f] [flag]\n"; + return 1; + } + else { + std::string strArgv(argv[(optind - 1)]); + std::transform(strArgv.begin(), strArgv.end(), strArgv.begin(), ::tolower); + + if (strArgv.compare(allFlags[0]) == 0) { + flagStripes = 6; + drawFlag(prideFlag, flagStripes); + } else if (strArgv.compare(allFlags[1]) == 0) { + flagStripes = 5; + drawFlag(transFlag, flagStripes); + } else if (strArgv.compare(allFlags[2]) == 0) { + flagStripes = 5; + drawFlag(lesbianFlag, flagStripes); + } else if (strArgv.compare(allFlags[3]) == 0) { + flagStripes = 3; + drawFlag(dutchFlag, flagStripes); + } else if (strArgv.compare(allFlags[4]) == 0) { + flagStripes = 3; + drawFlag(biFlag, flagStripes); + } else if (strArgv.compare(allFlags[5]) == 0) { + flagStripes = 4; + drawFlag(nonBinaryFlag, flagStripes); + } else { + std::cerr << argv[0] << ": invalid option '" << strArgv << "'\n"; + std::cerr << "Usage: " << argv[0] << " [OPTION] [VALUE] -f [FLAG]\n"; + return 1; + } + } + break; + case LIST: + std::print("All available [FLAGS]:\n"); + for (short k = 0; k < allFlagsSize; k++) { + std::print("{0}\n", allFlags[k]); + } + return 0; + case HELP: + std::cout + << "Usage: " << argv[0] << " [OPTION] [ARGUMENT] -f [FLAG]\n" + << "All options:\n" + << "\t-f, --flag [FLAG]\t\tPrints the chosen flag\n" + << "\t-h, --height [Integer]\t\tPrints the flag with the chosen positive integer\n" + << "\t-s, --string \'[String]\'\t\tPrint the chosen flag with the given string (Flag width is not yet perfectly variable)\n" + << "\t--list\t\t\t\tList all available flags\n" + << "\t--help\t\t\t\tPrints out the help screen\n"; + return 0; + case '?': + std::cerr << "No matching [OPTION]!\n"; + return 1; + default: + std::cerr << "Usage: " << argv[0] << " [OPTION] [VALUE] -f [FLAG]" << std::endl; + return 1; + } + } + return 0; }