From 7730dc4638783dff5784c62069aa34e9f91e803b Mon Sep 17 00:00:00 2001 From: bivirus Date: Thu, 9 May 2024 18:12:21 +0200 Subject: [PATCH 01/15] Chore: added .idea to gitignore to ignore jetbrains project settings Feat: updated to C++ 17 (for later changes) owo --- .gitignore | 1 + Makefile | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 6ee01af..a3a0b6c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ .vscode/ .DS_Store +.idea/ pridecat \ No newline at end of file diff --git a/Makefile b/Makefile index 815c27e..8d5938c 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ CXX ?= clang all: pridecat pridecat: main.cpp - $(CXX) main.cpp -o pridecat -std=c++11 -lstdc++ -Wall -Wextra -O3 + $(CXX) main.cpp -o pridecat -std=c++17 -lstdc++ -Wall -Wextra -O3 install: pridecat cp pridecat /usr/local/bin/pridecat From 79dbae3ff5143182ef5e67b8462f99a9cfe1da7b Mon Sep 17 00:00:00 2001 From: bivirus Date: Thu, 9 May 2024 18:37:36 +0200 Subject: [PATCH 02/15] Chore: fixed some tidy clang warnings --- main.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/main.cpp b/main.cpp index 619b118..3d506b0 100644 --- a/main.cpp +++ b/main.cpp @@ -15,7 +15,7 @@ struct color_t { uint8_t r,g,b; - color_t(uint32_t rgb) + color_t(const uint32_t rgb) : r((rgb >> 16) & 0xff) , g((rgb >> 8) & 0xff) , b(rgb & 0xff) @@ -209,13 +209,13 @@ std::string resolveAlias(const std::string& arg) { color_t adjustForReadability(color_t const& color) { if (g_colorAdjustment == colorAdjust::darken) { - return color_t( + return color_t( // NOLINT(*-return-braced-init-list) (color.r*3)/4, (color.g*3)/4, (color.b*3)/4 ); } else if (g_colorAdjustment == colorAdjust::lighten) { - return color_t( + return color_t( // NOLINT(*-return-braced-init-list) 64+(color.r*3)/4, 64+(color.g*3)/4, 64+(color.b*3)/4 @@ -285,7 +285,7 @@ void parseCommandLine(int argc, char** argv) { bool finishedReadingFlags = false; for (int i = 1; i < argc; ++i) { if (finishedReadingFlags) { - g_filesToCat.push_back(argv[i]); + g_filesToCat.emplace_back(argv[i]); } else if (strEqual(argv[i], "-h") || strEqual(argv[i], "--help")) { printf("pridecat!\n"); @@ -367,10 +367,10 @@ void parseCommandLine(int argc, char** argv) { else if (strEqual(argv[i], "-")) { // use an empty string in the array to represent stdin // so we can still actually have a file called '-' - g_filesToCat.push_back(""); + g_filesToCat.emplace_back(""); } else { - g_filesToCat.push_back(argv[i]); + g_filesToCat.emplace_back(argv[i]); } } } @@ -440,7 +440,7 @@ int main(int argc, char** argv) { catFile(stdin); } else { for (auto const& filepath : g_filesToCat) { - if (filepath == "") { + if (filepath.empty()) { catFile(stdin); } else { FILE* fh = fopen(filepath.c_str(), "rb"); From cc29054f26c5d0bcd35e2bb00f38d8d28304154b Mon Sep 17 00:00:00 2001 From: bivirus Date: Thu, 9 May 2024 20:12:00 +0200 Subject: [PATCH 03/15] Feat: added 2d flag support for the definition and the help message --- main.cpp | 90 +++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 60 insertions(+), 30 deletions(-) diff --git a/main.cpp b/main.cpp index 3d506b0..b98f09c 100644 --- a/main.cpp +++ b/main.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #if defined(_WIN32) #include @@ -25,7 +26,7 @@ struct color_t { }; struct flag_t { - std::vector colors; + std::variant, std::vector>> colors; std::string description; }; @@ -39,75 +40,75 @@ std::map allFlags = { { "lgbt", { // info: https://en.wikipedia.org/wiki/Rainbow_flag_(LGBT) // colors: https://en.wikipedia.org/wiki/File:Gay_Pride_Flag.svg - { 0xE40303, 0xFF8C00, 0xFFED00, 0x008026, 0x004Dff, 0x750787 }, + std::vector { 0xE40303, 0xFF8C00, 0xFFED00, 0x008026, 0x004Dff, 0x750787 }, "Classic 6-color rainbow flag popular since 1979" } }, { "lgbt-1978", { // info: https://en.wikipedia.org/wiki/Rainbow_flag_(LGBT) // colors: https://en.wikipedia.org/wiki/File:Gay_flag_8.svg - { 0xFF69B4, 0xFF0000, 0xFF8E00, 0xFFFF00, 0x008E00, 0x00C0C0, 0x400098, 0x8E008E }, + std::vector { 0xFF69B4, 0xFF0000, 0xFF8E00, 0xFFFF00, 0x008E00, 0x00C0C0, 0x400098, 0x8E008E }, "Original 8-color rainbow flag designed by Gilbert Baker in 1978" } }, { "lgbtpoc", { // info: https://en.wikipedia.org/wiki/Rainbow_flag_(LGBT) // colors: https://en.wikipedia.org/wiki/File:Philadelphia_Pride_Flag.svg - { 0x000000, 0x784F17, 0xE40303, 0xFF8C00, 0xFFED00, 0x008026, 0x004DFF, 0x750787 }, + std::vector { 0x000000, 0x784F17, 0xE40303, 0xFF8C00, 0xFFED00, 0x008026, 0x004DFF, 0x750787 }, "POC-inclusive rainbow flag designed by Philadelphia City Council in 2017" } }, { "transgender", { // info: https://en.wikipedia.org/wiki/Transgender_flags // colors: https://en.wikipedia.org/wiki/File:Transgender_Pride_flag.svg - { 0x5BCEFA, 0xF5A9B8, 0xFFFFFF, 0xF5A9B8, 0x5BCEFA }, + std::vector { 0x5BCEFA, 0xF5A9B8, 0xFFFFFF, 0xF5A9B8, 0x5BCEFA }, "Transgender pride flag designed by Monica Helms in 1999" } }, { "bisexual", { // info: https://en.wikipedia.org/wiki/Bisexual_pride_flag // colors: https://en.wikipedia.org/wiki/File:Bisexual_Pride_Flag.svg - { 0xD60270, 0xD60270, 0x9B4F96, 0x0038A8, 0x0038A8 }, + std::vector { 0xD60270, 0xD60270, 0x9B4F96, 0x0038A8, 0x0038A8 }, "Bisexual pride flag designed by Michael Page in 1998" } }, { "asexual", { // info: https://en.wikipedia.org/wiki/LGBT_symbols#Asexuality // colors: https://en.wikipedia.org/wiki/File:Asexual_Pride_Flag.svg - { 0x000000, 0xA3A3A3, 0xFFFFFF, 0x800080 }, + std::vector { 0x000000, 0xA3A3A3, 0xFFFFFF, 0x800080 }, "Asexual pride flag designed by AVEN user 'standup' in 2010" } }, { "aromantic", { // info/colors: https://cameronwhimsy.tumblr.com/post/75868343112/ive-been-reading-up-on-a-lot-of-the-discussion - { 0x3DA642, 0xA8D379, 0xFFFFFF, 0xA9A9A9, 0x000000 }, + std::vector { 0x3DA642, 0xA8D379, 0xFFFFFF, 0xA9A9A9, 0x000000 }, "Aromantic pride flag designed by Tumblr user 'cameronwhimsy' in 2014" } }, { "aromantic-asexual", { // info: https://www.lgbtqia.wiki/wiki/Aroace // colors: https://en.wikipedia.org/wiki/File:Aroace_flag.svg (also available from lgbtqia.wiki, but this is higher quality) - { 0xE28C00, 0xECCD00, 0xFFFFFF, 0x62AEDC, 0x203856 }, + std::vector { 0xE28C00, 0xECCD00, 0xFFFFFF, 0x62AEDC, 0x203856 }, "Aromantic-asexual pride flag designed by Tumblr user 'aroaesflags' in 2018" } }, { "pansexual", { // info: https://majesticmess.com/2018/12/01/interview-creator-of-the-pan-flag/ // colors: https://web.archive.org/web/20111103184455/http://pansexualflag.tumblr.com/post/1265215452/hex-color-codes-you-dont-have-to-use-these-exact - { 0xFF218C, 0xFF218C, 0xFFD800, 0xFFD800, 0x21B1FF, 0x21B1FF }, + std::vector { 0xFF218C, 0xFF218C, 0xFFD800, 0xFFD800, 0x21B1FF, 0x21B1FF }, "Pansexual pride flag designed by Evie Varney in 2010" } }, { "nonbinary", { // info: https://en.wikipedia.org/wiki/LGBT_symbols#Non-binary // colors: https://en.wikipedia.org/wiki/File:Nonbinary_flag.svg - { 0xFFF430, 0xFFFFFF, 0x9C59D1, 0x000000 }, + std::vector { 0xFFF430, 0xFFFFFF, 0x9C59D1, 0x000000 }, "Non-binary pride flag designed by Kye Rowan in 2014" } }, { "lipstick-lesbian", { // info/colors: https://en.wikipedia.org/wiki/File:Lipstick_Lesbian_flag_without_lips.svg - { 0xA40061, 0xB75592, 0xD063A6, 0xEDEDEB, 0xE4ACCF, 0xC54E54, 0x8A1E04 }, + std::vector { 0xA40061, 0xB75592, 0xD063A6, 0xEDEDEB, 0xE4ACCF, 0xC54E54, 0x8A1E04 }, "Lipstick lesbian pride flag designed by Natalie McCray in 2010" } }, @@ -115,22 +116,36 @@ std::map allFlags = { // info: https://en.wikipedia.org/wiki/LGBT_symbols#Lesbian // colors: https://en.wikipedia.org/wiki/File:Lesbian_pride_flag_2018.svg // second-last color changed from 0xB55690 to 0xB55590 to ensure distinct colors on non-truecolor displays - { 0xD52D00, 0xEF7627, 0xFF9A56, 0xFFFFFF, 0xD162A4, 0xB55590, 0xA30262 }, + std::vector { 0xD52D00, 0xEF7627, 0xFF9A56, 0xFFFFFF, 0xD162A4, 0xB55590, 0xA30262 }, "New lesbian pride flag designed by Emily Gwen in 2018" } }, { "community-lesbian", { // info/colors: https://majesticmess.com/encyclopedia/lesbian-flag-sadlesbeandisaster/ // more info: https://twitter.com/lesflagisracist/status/1107301651403157505 - { 0xD52D00, 0xFF9A56, 0xFFFFFF, 0xD362A4, 0xA30262 }, + std::vector { 0xD52D00, 0xFF9A56, 0xFFFFFF, 0xD362A4, 0xA30262 }, "5-color 'Community' variant designed by Tumblr user 'taqwomen' in 2018" } }, { "genderqueer", { // info/colors: https://genderqueerid.com/about-flag - { 0xB57EDC, 0xB57EDC, 0xFFFFFF, 0xFFFFFF, 0x4A8123, 0x4A8123 }, + std::vector { 0xB57EDC, 0xB57EDC, 0xFFFFFF, 0xFFFFFF, 0x4A8123, 0x4A8123 }, "Genderqueer pride flag designed by Marilyn Roxie in 2011" } }, + + { "progress-pride", { + // info/colors: https://de.wikipedia.org/wiki/Datei:LGBTQ+_rainbow_flag_Quasar_%22Progress%22_variant.svg + std::vector> { + { 0xf5a9b8, 0x5bcefa, 0x603917, 0x000000, 0xee3124, 0xee3124, 0xee3124, 0xee3124, 0xee3124 }, + { 0xffffff, 0xf5a9b8, 0x5bcefa, 0x603917, 0x000000, 0xf57e29, 0xf57e29, 0xf57e29, 0xf57e29 }, + { 0xffffff, 0xffffff, 0xf5a9b8, 0x5bcefa, 0x603917, 0x000000, 0xffee00, 0xffee00, 0xffee00 }, + { 0xffffff, 0xffffff, 0xf5a9b8, 0x5bcefa, 0x603917, 0x000000, 0x58b947, 0x58b947, 0x58b947 }, + { 0xffffff, 0xf5a9b8, 0x5bcefa, 0x603917, 0x000000, 0x0053a6, 0x0053a6, 0x0053a6, 0x0053a6 }, + { 0xf5a9b8, 0x5bcefa, 0x603917, 0x000000, 0x9f248f, 0x9f248f, 0x9f248f, 0x9f248f, 0x9f248f }, + }, + "Progress pride flag designed by Daniel Quasar in 2018" + } + } }; std::map aliases = { @@ -144,12 +159,14 @@ std::map aliases = { { "enby", "nonbinary" }, { "pink-lesbian", "lipstick-lesbian" }, { "lesbian", "community-lesbian" }, + { "gq", "genderqueer" }, + { "progress", "progress-pride" }, }; std::vector g_colorQueue; std::vector g_filesToCat; unsigned int g_currentRow = 0; -colorAdjust g_colorAdjustment = colorAdjust::none; +auto g_colorAdjustment = colorAdjust::none; #if defined(_WIN32) bool g_useColors = _isatty(_fileno(stdout)); @@ -194,14 +211,16 @@ int bestNonTruecolorMatch(color_t const& color) { } void pushFlag(flag_t const& flag) { - for (color_t const& color : flag.colors) { - g_colorQueue.push_back(color); + if (std::holds_alternative>(flag.colors)) { + auto const& colors = std::get>(flag.colors); + for (color_t const& color : colors) { + g_colorQueue.push_back(color); + } } } std::string resolveAlias(const std::string& arg) { - const auto& alias = aliases.find(arg); - if (alias != aliases.end()) { + if (const auto& alias = aliases.find(arg); alias != aliases.end()) { return alias->second; } return arg; @@ -281,7 +300,7 @@ void resetColor() { } } -void parseCommandLine(int argc, char** argv) { +void parseCommandLine(const int argc, char** argv) { bool finishedReadingFlags = false; for (int i = 1; i < argc; ++i) { if (finishedReadingFlags) { @@ -292,23 +311,34 @@ void parseCommandLine(int argc, char** argv) { printf("It's like cat but more colorful :)\n"); printf("\nCurrently available flags:\n"); - for (const auto& flag : allFlags) { - printf(" --%s", flag.first.c_str()); - for (const auto& alias : aliases) { - if (flag.first == alias.second) { - printf(",--%s", alias.first.c_str()); + for (const auto&[name, flag] : allFlags) { + printf(" --%s", name.c_str()); + for (const auto&[short_name, long_name] : aliases) { + if (name == long_name) { + printf(",--%s", short_name.c_str()); } } if (g_useColors) { putc(' ', stdout); - for (const auto& color : flag.second.colors) { - setBackgroundColor(color); - putc(' ', stdout); + if (std::holds_alternative>(flag.colors)) { + for (const color_t color : std::get>(flag.colors)) { + setBackgroundColor(color); + putc(' ', stdout); + } + } else { + for (const std::vector& color_row : std::get>>(flag.colors)) { + printf("\n "); + for (const color_t color : color_row) { + setBackgroundColor(color); + putc(' ', stdout); + } + resetBackgroundColor(); + } } resetBackgroundColor(); } printf("\n"); - printf(" %s\n\n", flag.second.description.c_str()); + printf(" %s\n\n", flag.description.c_str()); } printf("Additional options:\n"); From 9c6d7a2ad5977631273e1d80ca6d1735dd9d4676 Mon Sep 17 00:00:00 2001 From: bivirus Date: Thu, 9 May 2024 21:55:56 +0200 Subject: [PATCH 04/15] Feat: add flag stretching --- main.cpp | 143 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 140 insertions(+), 3 deletions(-) diff --git a/main.cpp b/main.cpp index b98f09c..e0ad46d 100644 --- a/main.cpp +++ b/main.cpp @@ -25,9 +25,22 @@ struct color_t { : r(r), g(g), b(b) {} }; +enum class StretchDirection : uint8_t { + None, // no stretching allowed + Right, // stretch only from the right side (last color in the line is repeated) + Bottom, // stretch only from the bottom side (color of last row is repeated) + Vertical, // stretch vertically (every colums is repeated) + VerticalPreserveCenter, // last and first row are repeated + Horizontal, // stretch horizontally (every row is repeated) + HorizontalPreserveCenter, // last and first column are repeated + All, // stretch in all directions (every row and column is repeated) + AllPreserveCenter // last and first row and column are repeated +}; + struct flag_t { std::variant, std::vector>> colors; std::string description; + StretchDirection stretchDirection = StretchDirection::All; // how to stretch the flag if required (default is all because stripes can be streched without looking weird) }; enum class colorAdjust : uint8_t { @@ -133,7 +146,7 @@ std::map allFlags = { "Genderqueer pride flag designed by Marilyn Roxie in 2011" } }, - { "progress-pride", { + { "progress-pride", { // TODO: strech progress thingy x3 horizontally (leve width at 9) // info/colors: https://de.wikipedia.org/wiki/Datei:LGBTQ+_rainbow_flag_Quasar_%22Progress%22_variant.svg std::vector> { { 0xf5a9b8, 0x5bcefa, 0x603917, 0x000000, 0xee3124, 0xee3124, 0xee3124, 0xee3124, 0xee3124 }, @@ -143,7 +156,8 @@ std::map allFlags = { { 0xffffff, 0xf5a9b8, 0x5bcefa, 0x603917, 0x000000, 0x0053a6, 0x0053a6, 0x0053a6, 0x0053a6 }, { 0xf5a9b8, 0x5bcefa, 0x603917, 0x000000, 0x9f248f, 0x9f248f, 0x9f248f, 0x9f248f, 0x9f248f }, }, - "Progress pride flag designed by Daniel Quasar in 2018" + "Progress pride flag designed by Daniel Quasar in 2018", + StretchDirection::Right } } }; @@ -300,6 +314,124 @@ void resetColor() { } } +flag_t stretch2dFlagTo(const flag_t& flag, const int width, const int height) { // TODO: test this + if (std::holds_alternative>(flag.colors)) { + printf("WARNING: Method for stretching 2D flags called on 1D flag\n"); + return flag; + } + auto stretchedColors = std::get>>(flag.colors); + switch (flag.stretchDirection) { + case StretchDirection::Right: { + for (auto& row : stretchedColors) { + while (static_cast(row.size()) < width) { + row.push_back(row.back()); + } + } + break; + } + case StretchDirection::Bottom: { + while (static_cast(stretchedColors.size()) < height) { + stretchedColors.push_back(stretchedColors.back()); + } + break; + } + case StretchDirection::Vertical: { + const int currentHeight = static_cast(stretchedColors.size()); + const std::vector> unstretchedColors = stretchedColors; + if (currentHeight >= height) { + break; + } + const int stretchFactor = height / currentHeight; + for (int i = 0; i < currentHeight; ++i) { + for (int j = 0; j < stretchFactor; ++j) { + stretchedColors.insert(stretchedColors.begin() + i + j, unstretchedColors[i]); + } + } + break; + } + case StretchDirection::VerticalPreserveCenter: { + const int delta_height = height - static_cast(stretchedColors.size()); + for (int i = 0; i < delta_height / 2; ++i) { + stretchedColors.insert(stretchedColors.begin(), stretchedColors.front()); + stretchedColors.push_back(stretchedColors.back()); + } + break; + } + case StretchDirection::Horizontal: { + const int currentWidth = static_cast(stretchedColors[0].size()); + const std::vector> unstretchedColors = stretchedColors; + if (currentWidth >= width) { + break; + } + const int stretchFactor = width / currentWidth; + for (int row = 0; row < static_cast(unstretchedColors.size()); ++row) { + stretchedColors[row].clear(); + for (int i = 0; i < currentWidth; ++i) { + for (int j = 0; j < stretchFactor; ++j) { + stretchedColors[row].insert(stretchedColors[row].end(), unstretchedColors[row][i]); + } + } + } + break; + } + case StretchDirection::HorizontalPreserveCenter: { + const int delta_width = width - static_cast(stretchedColors[0].size()); + for (auto& row : stretchedColors) { + for (int i = 0; i < delta_width / 2; ++i) { + row.insert(row.begin(), row.front()); + row.push_back(row.back()); + } + } + break; + } + case StretchDirection::All: { // TOO0: fix this + const int currentWidth = static_cast(stretchedColors[0].size()); + const int currentHeight = static_cast(stretchedColors.size()); + const std::vector> unstretchedColors = stretchedColors; + if (currentWidth >= width && currentHeight >= height) { + break; + } + const int stretchFactorWidth = width / currentWidth; + const int stretchFactorHeight = height / currentHeight; + for (int i = 0; i < currentHeight; ++i) { + for (int j = 0; j < stretchFactorHeight; ++j) { + stretchedColors.insert(stretchedColors.begin() + i + j, unstretchedColors[i]); + } + } + for (auto& row : stretchedColors) { + for (int i = 0; i < currentWidth; ++i) { + for (int j = 0; j < stretchFactorWidth; ++j) { + row.insert(row.begin() + i + j, unstretchedColors[&row - &stretchedColors[0]][i]); + } + } + } + break; + } + case StretchDirection::AllPreserveCenter: { + const int delta_width = width - static_cast(stretchedColors[0].size()); + const int delta_height = height - static_cast(stretchedColors.size()); + for (int i = 0; i < delta_height / 2; ++i) { + stretchedColors.insert(stretchedColors.begin(), stretchedColors.front()); + stretchedColors.push_back(stretchedColors.back()); + } + for (auto& row : stretchedColors) { + for (int i = 0; i < delta_width / 2; ++i) { + row.insert(row.begin(), row.front()); + row.push_back(row.back()); + } + } + break; + } + default: + return flag; + } + return flag_t { + .colors = stretchedColors, + .description = flag.description, + .stretchDirection = flag.stretchDirection + }; +} + void parseCommandLine(const int argc, char** argv) { bool finishedReadingFlags = false; for (int i = 1; i < argc; ++i) { @@ -326,7 +458,12 @@ void parseCommandLine(const int argc, char** argv) { putc(' ', stdout); } } else { - for (const std::vector& color_row : std::get>>(flag.colors)) { + auto& colors = std::get>>(flag.colors); + flag_t newFlag = flag; + if (colors[0].size() < 30) { + newFlag.colors = stretch2dFlagTo(flag, 30, 5).colors; + } + for (const std::vector& color_row : std::get>>(newFlag.colors)) { printf("\n "); for (const color_t color : color_row) { setBackgroundColor(color); From be9cc6b7321f8f76ec8b28775bbc1b53f2d8ad05 Mon Sep 17 00:00:00 2001 From: bivirus Date: Fri, 10 May 2024 00:03:42 +0200 Subject: [PATCH 05/15] Feat: better progress pride flag Change: split stretch rule in two components --- main.cpp | 121 +++++++++++++++++++++---------------------------------- 1 file changed, 45 insertions(+), 76 deletions(-) diff --git a/main.cpp b/main.cpp index e0ad46d..b8fe9d8 100644 --- a/main.cpp +++ b/main.cpp @@ -25,22 +25,25 @@ struct color_t { : r(r), g(g), b(b) {} }; -enum class StretchDirection : uint8_t { +enum class StretchRuleVertical : uint8_t { None, // no stretching allowed - Right, // stretch only from the right side (last color in the line is repeated) - Bottom, // stretch only from the bottom side (color of last row is repeated) - Vertical, // stretch vertically (every colums is repeated) - VerticalPreserveCenter, // last and first row are repeated - Horizontal, // stretch horizontally (every row is repeated) - HorizontalPreserveCenter, // last and first column are repeated - All, // stretch in all directions (every row and column is repeated) - AllPreserveCenter // last and first row and column are repeated + ExtendBottom, // stretch only from the bottom side (color of last row is repeated) + Allowed, // stretch vertically (every colums is repeated) + PreserveCenter, // last and first row are repeated +}; + +enum class StretchRuleHorizontal : uint8_t { + None, // no stretching allowed + ExtendRight, // stretch only from the right side (color of last column is repeated) + Allowed, // stretch horizontally (every row is repeated) + PreserveCenter, // last and first column are repeated }; struct flag_t { std::variant, std::vector>> colors; std::string description; - StretchDirection stretchDirection = StretchDirection::All; // how to stretch the flag if required (default is all because stripes can be streched without looking weird) + StretchRuleVertical stretchVertical = StretchRuleVertical::Allowed; + StretchRuleHorizontal stretchHorizontal = StretchRuleHorizontal::Allowed; }; enum class colorAdjust : uint8_t { @@ -146,20 +149,20 @@ std::map allFlags = { "Genderqueer pride flag designed by Marilyn Roxie in 2011" } }, - { "progress-pride", { // TODO: strech progress thingy x3 horizontally (leve width at 9) + { "progress-pride", { // info/colors: https://de.wikipedia.org/wiki/Datei:LGBTQ+_rainbow_flag_Quasar_%22Progress%22_variant.svg std::vector> { - { 0xf5a9b8, 0x5bcefa, 0x603917, 0x000000, 0xee3124, 0xee3124, 0xee3124, 0xee3124, 0xee3124 }, - { 0xffffff, 0xf5a9b8, 0x5bcefa, 0x603917, 0x000000, 0xf57e29, 0xf57e29, 0xf57e29, 0xf57e29 }, - { 0xffffff, 0xffffff, 0xf5a9b8, 0x5bcefa, 0x603917, 0x000000, 0xffee00, 0xffee00, 0xffee00 }, - { 0xffffff, 0xffffff, 0xf5a9b8, 0x5bcefa, 0x603917, 0x000000, 0x58b947, 0x58b947, 0x58b947 }, - { 0xffffff, 0xf5a9b8, 0x5bcefa, 0x603917, 0x000000, 0x0053a6, 0x0053a6, 0x0053a6, 0x0053a6 }, - { 0xf5a9b8, 0x5bcefa, 0x603917, 0x000000, 0x9f248f, 0x9f248f, 0x9f248f, 0x9f248f, 0x9f248f }, + { 0xf5a9b8, 0xf5a9b8, 0xf5a9b8, 0x5bcefa, 0x5bcefa, 0x5bcefa, 0x603917, 0x603917, 0x603917, 0x000000, 0x000000, 0x000000, 0xee3124, 0xee3124, 0xee3124, 0xee3124, 0xee3124, 0xee3124, 0xee3124 }, + { 0xffffff, 0xffffff, 0xffffff, 0xf5a9b8, 0xf5a9b8, 0xf5a9b8, 0x5bcefa, 0x5bcefa, 0x5bcefa, 0x603917, 0x603917, 0x603917, 0x000000, 0x000000, 0x000000, 0xf57e29, 0xf57e29, 0xf57e29, 0xf57e29 }, + { 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xf5a9b8, 0xf5a9b8, 0xf5a9b8, 0x5bcefa, 0x5bcefa, 0x5bcefa, 0x603917, 0x603917, 0x603917, 0x000000, 0x000000, 0x000000, 0xffee00 }, + { 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xffffff, 0xf5a9b8, 0xf5a9b8, 0xf5a9b8, 0x5bcefa, 0x5bcefa, 0x5bcefa, 0x603917, 0x603917, 0x603917, 0x000000, 0x000000, 0x000000, 0x58b947 }, + { 0xffffff, 0xffffff, 0xffffff, 0xf5a9b8, 0xf5a9b8, 0xf5a9b8, 0x5bcefa, 0x5bcefa, 0x5bcefa, 0x603917, 0x603917, 0x603917, 0x000000, 0x000000, 0x000000, 0x0053a6, 0x0053a6, 0x0053a6, 0x0053a6 }, + { 0xf5a9b8, 0xf5a9b8, 0xf5a9b8, 0x5bcefa, 0x5bcefa, 0x5bcefa, 0x603917, 0x603917, 0x603917, 0x000000, 0x000000, 0x000000, 0x9f248f, 0x9f248f, 0x9f248f, 0x9f248f, 0x9f248f, 0x9f248f, 0x9f248f }, }, "Progress pride flag designed by Daniel Quasar in 2018", - StretchDirection::Right - } - } + StretchRuleVertical::Allowed, + StretchRuleHorizontal::ExtendRight, + }} }; std::map aliases = { @@ -320,8 +323,8 @@ flag_t stretch2dFlagTo(const flag_t& flag, const int width, const int height) { return flag; } auto stretchedColors = std::get>>(flag.colors); - switch (flag.stretchDirection) { - case StretchDirection::Right: { + switch (flag.stretchHorizontal) { + case StretchRuleHorizontal::ExtendRight: { for (auto& row : stretchedColors) { while (static_cast(row.size()) < width) { row.push_back(row.back()); @@ -329,35 +332,7 @@ flag_t stretch2dFlagTo(const flag_t& flag, const int width, const int height) { } break; } - case StretchDirection::Bottom: { - while (static_cast(stretchedColors.size()) < height) { - stretchedColors.push_back(stretchedColors.back()); - } - break; - } - case StretchDirection::Vertical: { - const int currentHeight = static_cast(stretchedColors.size()); - const std::vector> unstretchedColors = stretchedColors; - if (currentHeight >= height) { - break; - } - const int stretchFactor = height / currentHeight; - for (int i = 0; i < currentHeight; ++i) { - for (int j = 0; j < stretchFactor; ++j) { - stretchedColors.insert(stretchedColors.begin() + i + j, unstretchedColors[i]); - } - } - break; - } - case StretchDirection::VerticalPreserveCenter: { - const int delta_height = height - static_cast(stretchedColors.size()); - for (int i = 0; i < delta_height / 2; ++i) { - stretchedColors.insert(stretchedColors.begin(), stretchedColors.front()); - stretchedColors.push_back(stretchedColors.back()); - } - break; - } - case StretchDirection::Horizontal: { + case StretchRuleHorizontal::Allowed: { const int currentWidth = static_cast(stretchedColors[0].size()); const std::vector> unstretchedColors = stretchedColors; if (currentWidth >= width) { @@ -365,7 +340,6 @@ flag_t stretch2dFlagTo(const flag_t& flag, const int width, const int height) { } const int stretchFactor = width / currentWidth; for (int row = 0; row < static_cast(unstretchedColors.size()); ++row) { - stretchedColors[row].clear(); for (int i = 0; i < currentWidth; ++i) { for (int j = 0; j < stretchFactor; ++j) { stretchedColors[row].insert(stretchedColors[row].end(), unstretchedColors[row][i]); @@ -374,7 +348,7 @@ flag_t stretch2dFlagTo(const flag_t& flag, const int width, const int height) { } break; } - case StretchDirection::HorizontalPreserveCenter: { + case StretchRuleHorizontal::PreserveCenter: { const int delta_width = width - static_cast(stretchedColors[0].size()); for (auto& row : stretchedColors) { for (int i = 0; i < delta_width / 2; ++i) { @@ -384,51 +358,46 @@ flag_t stretch2dFlagTo(const flag_t& flag, const int width, const int height) { } break; } - case StretchDirection::All: { // TOO0: fix this - const int currentWidth = static_cast(stretchedColors[0].size()); + default: + break; + } + switch (flag.stretchVertical) { + case StretchRuleVertical::ExtendBottom: { + while (static_cast(stretchedColors.size()) < height) { + stretchedColors.push_back(stretchedColors.back()); + } + break; + } + case StretchRuleVertical::Allowed: { const int currentHeight = static_cast(stretchedColors.size()); const std::vector> unstretchedColors = stretchedColors; - if (currentWidth >= width && currentHeight >= height) { + if (currentHeight >= height) { break; } - const int stretchFactorWidth = width / currentWidth; - const int stretchFactorHeight = height / currentHeight; + const int stretchFactor = height / currentHeight; for (int i = 0; i < currentHeight; ++i) { - for (int j = 0; j < stretchFactorHeight; ++j) { + for (int j = 0; j < stretchFactor; ++j) { stretchedColors.insert(stretchedColors.begin() + i + j, unstretchedColors[i]); } } - for (auto& row : stretchedColors) { - for (int i = 0; i < currentWidth; ++i) { - for (int j = 0; j < stretchFactorWidth; ++j) { - row.insert(row.begin() + i + j, unstretchedColors[&row - &stretchedColors[0]][i]); - } - } - } break; } - case StretchDirection::AllPreserveCenter: { - const int delta_width = width - static_cast(stretchedColors[0].size()); + case StretchRuleVertical::PreserveCenter: { const int delta_height = height - static_cast(stretchedColors.size()); for (int i = 0; i < delta_height / 2; ++i) { stretchedColors.insert(stretchedColors.begin(), stretchedColors.front()); stretchedColors.push_back(stretchedColors.back()); } - for (auto& row : stretchedColors) { - for (int i = 0; i < delta_width / 2; ++i) { - row.insert(row.begin(), row.front()); - row.push_back(row.back()); - } - } break; } default: - return flag; + break; } return flag_t { .colors = stretchedColors, .description = flag.description, - .stretchDirection = flag.stretchDirection + .stretchVertical = flag.stretchVertical, + .stretchHorizontal = flag.stretchHorizontal }; } From c0d87641974d8b27da4da399ae180ed24b9ce2f3 Mon Sep 17 00:00:00 2001 From: bivirus Date: Fri, 10 May 2024 00:39:45 +0200 Subject: [PATCH 06/15] Feat: better horizontal stretch that allows for exact stretching --- main.cpp | 43 +++++++++++++++++++++++++++++-------------- 1 file changed, 29 insertions(+), 14 deletions(-) diff --git a/main.cpp b/main.cpp index b8fe9d8..988c3fa 100644 --- a/main.cpp +++ b/main.cpp @@ -27,16 +27,16 @@ struct color_t { enum class StretchRuleVertical : uint8_t { None, // no stretching allowed - ExtendBottom, // stretch only from the bottom side (color of last row is repeated) - Allowed, // stretch vertically (every colums is repeated) - PreserveCenter, // last and first row are repeated + Allowed, // stretch vertically + PreserveTop, // repeat only the lase row so the details in the top of the flag are preserved + PreserveCenter, // last and first row are repeated to preserve the details in the center of the flag }; enum class StretchRuleHorizontal : uint8_t { None, // no stretching allowed - ExtendRight, // stretch only from the right side (color of last column is repeated) - Allowed, // stretch horizontally (every row is repeated) - PreserveCenter, // last and first column are repeated + Allowed, // stretch horizontally + PreserveLeft, // repeat only the last column so the details on the left side are preserved + PreserveCenter, // last and first column are repeated to preserve the details in the center of the flag }; struct flag_t { @@ -161,7 +161,7 @@ std::map allFlags = { }, "Progress pride flag designed by Daniel Quasar in 2018", StretchRuleVertical::Allowed, - StretchRuleHorizontal::ExtendRight, + StretchRuleHorizontal::PreserveLeft, // preserves the details on the left side }} }; @@ -324,7 +324,7 @@ flag_t stretch2dFlagTo(const flag_t& flag, const int width, const int height) { } auto stretchedColors = std::get>>(flag.colors); switch (flag.stretchHorizontal) { - case StretchRuleHorizontal::ExtendRight: { + case StretchRuleHorizontal::PreserveLeft: { for (auto& row : stretchedColors) { while (static_cast(row.size()) < width) { row.push_back(row.back()); @@ -338,12 +338,27 @@ flag_t stretch2dFlagTo(const flag_t& flag, const int width, const int height) { if (currentWidth >= width) { break; } - const int stretchFactor = width / currentWidth; + const double stretchFactor = static_cast(width) / currentWidth; for (int row = 0; row < static_cast(unstretchedColors.size()); ++row) { - for (int i = 0; i < currentWidth; ++i) { - for (int j = 0; j < stretchFactor; ++j) { - stretchedColors[row].insert(stretchedColors[row].end(), unstretchedColors[row][i]); + stretchedColors[row].clear(); + double error = 0.0; + for (int i = 0; i < width; ++i) { + const double exactOriginalIndex = i / stretchFactor; + int originalIndex = static_cast(exactOriginalIndex); + error += exactOriginalIndex - originalIndex; + if (error > 1.0) { + ++originalIndex; + error = 0.0; + } else if (error < -1.0) { + --originalIndex; + error = 0.0; } + if (originalIndex < 0) { + originalIndex = 0; + } else if (originalIndex >= currentWidth) { + originalIndex = currentWidth-1; + } + stretchedColors[row].push_back(unstretchedColors[row][originalIndex]); } } break; @@ -362,7 +377,7 @@ flag_t stretch2dFlagTo(const flag_t& flag, const int width, const int height) { break; } switch (flag.stretchVertical) { - case StretchRuleVertical::ExtendBottom: { + case StretchRuleVertical::PreserveTop: { while (static_cast(stretchedColors.size()) < height) { stretchedColors.push_back(stretchedColors.back()); } @@ -430,7 +445,7 @@ void parseCommandLine(const int argc, char** argv) { auto& colors = std::get>>(flag.colors); flag_t newFlag = flag; if (colors[0].size() < 30) { - newFlag.colors = stretch2dFlagTo(flag, 30, 5).colors; + newFlag.colors = stretch2dFlagTo(flag, 30, 12).colors; } for (const std::vector& color_row : std::get>>(newFlag.colors)) { printf("\n "); From 705d9501b56c2829d648f15b7d20cc474c43847f Mon Sep 17 00:00:00 2001 From: bivirus Date: Fri, 10 May 2024 01:14:19 +0200 Subject: [PATCH 07/15] Feat: better vertical stretch that allows for exact stretching --- main.cpp | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/main.cpp b/main.cpp index 988c3fa..b27fc48 100644 --- a/main.cpp +++ b/main.cpp @@ -25,15 +25,15 @@ struct color_t { : r(r), g(g), b(b) {} }; -enum class StretchRuleVertical : uint8_t { - None, // no stretching allowed +enum class StretchRuleVertical : uint8_t { // TODO: add PreserveBottom + Disallowed, // no stretching allowed Allowed, // stretch vertically PreserveTop, // repeat only the lase row so the details in the top of the flag are preserved PreserveCenter, // last and first row are repeated to preserve the details in the center of the flag }; -enum class StretchRuleHorizontal : uint8_t { - None, // no stretching allowed +enum class StretchRuleHorizontal : uint8_t { // TODO: add PreserveRight + Disallowed, // no stretching allowed Allowed, // stretch horizontally PreserveLeft, // repeat only the last column so the details on the left side are preserved PreserveCenter, // last and first column are repeated to preserve the details in the center of the flag @@ -317,7 +317,7 @@ void resetColor() { } } -flag_t stretch2dFlagTo(const flag_t& flag, const int width, const int height) { // TODO: test this +flag_t stretch2dFlagTo(const flag_t& flag, const int width, const int height) { if (std::holds_alternative>(flag.colors)) { printf("WARNING: Method for stretching 2D flags called on 1D flag\n"); return flag; @@ -389,11 +389,14 @@ flag_t stretch2dFlagTo(const flag_t& flag, const int width, const int height) { if (currentHeight >= height) { break; } - const int stretchFactor = height / currentHeight; - for (int i = 0; i < currentHeight; ++i) { - for (int j = 0; j < stretchFactor; ++j) { - stretchedColors.insert(stretchedColors.begin() + i + j, unstretchedColors[i]); + stretchedColors.clear(); + const double stretchFactor = static_cast(height) / currentHeight; + for (int i = 0; i < height; ++i) { + int originalIndex = static_cast(i / stretchFactor); + if (originalIndex >= currentHeight) { + originalIndex = currentHeight-1; } + stretchedColors.insert(stretchedColors.begin() + i, unstretchedColors[originalIndex]); } break; } @@ -445,7 +448,7 @@ void parseCommandLine(const int argc, char** argv) { auto& colors = std::get>>(flag.colors); flag_t newFlag = flag; if (colors[0].size() < 30) { - newFlag.colors = stretch2dFlagTo(flag, 30, 12).colors; + newFlag.colors = stretch2dFlagTo(flag, 30, 6).colors; } for (const std::vector& color_row : std::get>>(newFlag.colors)) { printf("\n "); From 0780275654b202a3e1f13da3520f8f2eacc06572 Mon Sep 17 00:00:00 2001 From: bivirus Date: Fri, 10 May 2024 01:21:56 +0200 Subject: [PATCH 08/15] Feat: add missing preserve rules for stretching --- main.cpp | 49 +++++++++++++++++++++++++++++++++---------------- 1 file changed, 33 insertions(+), 16 deletions(-) diff --git a/main.cpp b/main.cpp index b27fc48..c738693 100644 --- a/main.cpp +++ b/main.cpp @@ -25,18 +25,20 @@ struct color_t { : r(r), g(g), b(b) {} }; -enum class StretchRuleVertical : uint8_t { // TODO: add PreserveBottom +enum class StretchRuleVertical : uint8_t { Disallowed, // no stretching allowed Allowed, // stretch vertically PreserveTop, // repeat only the lase row so the details in the top of the flag are preserved PreserveCenter, // last and first row are repeated to preserve the details in the center of the flag + PreserveBottom, // repeat only the first row so the details on the bottom side are preserved }; -enum class StretchRuleHorizontal : uint8_t { // TODO: add PreserveRight +enum class StretchRuleHorizontal : uint8_t { Disallowed, // no stretching allowed Allowed, // stretch horizontally PreserveLeft, // repeat only the last column so the details on the left side are preserved PreserveCenter, // last and first column are repeated to preserve the details in the center of the flag + PreserveRight, // repeat only the first column so the details on the right side are preserved }; struct flag_t { @@ -324,14 +326,7 @@ flag_t stretch2dFlagTo(const flag_t& flag, const int width, const int height) { } auto stretchedColors = std::get>>(flag.colors); switch (flag.stretchHorizontal) { - case StretchRuleHorizontal::PreserveLeft: { - for (auto& row : stretchedColors) { - while (static_cast(row.size()) < width) { - row.push_back(row.back()); - } - } - break; - } + case StretchRuleHorizontal::Allowed: { const int currentWidth = static_cast(stretchedColors[0].size()); const std::vector> unstretchedColors = stretchedColors; @@ -363,6 +358,14 @@ flag_t stretch2dFlagTo(const flag_t& flag, const int width, const int height) { } break; } + case StretchRuleHorizontal::PreserveLeft: { + for (auto& row : stretchedColors) { + while (static_cast(row.size()) < width) { + row.push_back(row.back()); + } + } + break; + } case StretchRuleHorizontal::PreserveCenter: { const int delta_width = width - static_cast(stretchedColors[0].size()); for (auto& row : stretchedColors) { @@ -373,16 +376,18 @@ flag_t stretch2dFlagTo(const flag_t& flag, const int width, const int height) { } break; } + case StretchRuleHorizontal::PreserveRight: { + for (auto& row : stretchedColors) { + while (static_cast(row.size()) < width) { + row.insert(row.begin(), row.front()); + } + } + break; + } default: break; } switch (flag.stretchVertical) { - case StretchRuleVertical::PreserveTop: { - while (static_cast(stretchedColors.size()) < height) { - stretchedColors.push_back(stretchedColors.back()); - } - break; - } case StretchRuleVertical::Allowed: { const int currentHeight = static_cast(stretchedColors.size()); const std::vector> unstretchedColors = stretchedColors; @@ -400,6 +405,12 @@ flag_t stretch2dFlagTo(const flag_t& flag, const int width, const int height) { } break; } + case StretchRuleVertical::PreserveTop: { + while (static_cast(stretchedColors.size()) < height) { + stretchedColors.push_back(stretchedColors.back()); + } + break; + } case StretchRuleVertical::PreserveCenter: { const int delta_height = height - static_cast(stretchedColors.size()); for (int i = 0; i < delta_height / 2; ++i) { @@ -408,6 +419,12 @@ flag_t stretch2dFlagTo(const flag_t& flag, const int width, const int height) { } break; } + case StretchRuleVertical::PreserveBottom: { + while (static_cast(stretchedColors.size()) < height) { + stretchedColors.insert(stretchedColors.begin(), stretchedColors.front()); + } + break; + } default: break; } From 6c715b74bbfed3dfebf93ec1be1ec5558f10841e Mon Sep 17 00:00:00 2001 From: bivirus Date: Fri, 10 May 2024 01:59:39 +0200 Subject: [PATCH 09/15] Feat: 2d printing now works --- main.cpp | 50 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 48 insertions(+), 2 deletions(-) diff --git a/main.cpp b/main.cpp index c738693..02e4083 100644 --- a/main.cpp +++ b/main.cpp @@ -178,13 +178,15 @@ std::map aliases = { { "enby", "nonbinary" }, { "pink-lesbian", "lipstick-lesbian" }, { "lesbian", "community-lesbian" }, - { "gq", "genderqueer" }, { "progress", "progress-pride" }, }; std::vector g_colorQueue; std::vector g_filesToCat; unsigned int g_currentRow = 0; +unsigned int g_currentColumn = 0; +bool two_dimensiona_flag = false; +flag_t current2dFlag; auto g_colorAdjustment = colorAdjust::none; #if defined(_WIN32) @@ -235,6 +237,9 @@ void pushFlag(flag_t const& flag) { for (color_t const& color : colors) { g_colorQueue.push_back(color); } + } else { + two_dimensiona_flag = true; + current2dFlag = flag; } } @@ -436,7 +441,7 @@ flag_t stretch2dFlagTo(const flag_t& flag, const int width, const int height) { }; } -void parseCommandLine(const int argc, char** argv) { +void parseCommandLine(const int argc, char** argv) { // TODO: add support for -s ,--stretch to stretch the flag to a certain height bool finishedReadingFlags = false; for (int i = 1; i < argc; ++i) { if (finishedReadingFlags) { @@ -551,7 +556,48 @@ void abortHandler(int signo) { exit(signo); } +void catFile2d(FILE* fh) { + int longestLine = 0; + char* line = nullptr; + size_t len = 0; + ssize_t read; + + while ((read = getline(&line, &len, fh)) != -1) { + if (read > longestLine) { + longestLine = static_cast(read); + } + } + fseek(fh, 0, SEEK_SET); + + const int flagHeight = static_cast(std::get>>(current2dFlag.colors).size()); + const auto flag = stretch2dFlagTo(current2dFlag, longestLine, flagHeight); + const auto& colors = std::get>>(flag.colors); + + + int c; + while ((c = getc(fh)) >= 0) { + setColor(colors[g_currentRow][g_currentColumn]); + putc(c, stdout); + resetColor(); + g_currentColumn++; + if (c == '\n') { + g_currentRow++; + g_currentColumn = 0; + if (g_currentRow == colors.size()) { + g_currentRow = 0; + } + } + } + + if (line) { + free(line); + } +} + void catFile(FILE* fh) { + if (two_dimensiona_flag) { + catFile2d(fh); + } int c; while ((c = getc(fh)) >= 0) { if (c == '\n') { From 8c15940d3cf03c6cee2524c556c99ef5d53f3c31 Mon Sep 17 00:00:00 2001 From: bivirus Date: Fri, 10 May 2024 02:08:30 +0200 Subject: [PATCH 10/15] Feat: fixed bug with backgroud --- main.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/main.cpp b/main.cpp index 02e4083..31b7594 100644 --- a/main.cpp +++ b/main.cpp @@ -576,16 +576,19 @@ void catFile2d(FILE* fh) { int c; while ((c = getc(fh)) >= 0) { - setColor(colors[g_currentRow][g_currentColumn]); - putc(c, stdout); - resetColor(); - g_currentColumn++; if (c == '\n') { g_currentRow++; g_currentColumn = 0; if (g_currentRow == colors.size()) { g_currentRow = 0; } + resetColor(); + putc(c, stdout); + } else { + setColor(colors[g_currentRow][g_currentColumn]); + putc(c, stdout); + resetColor(); + g_currentColumn++; } } From 85dc9cc7a4204c5cc413de632a69b01cd8293daf Mon Sep 17 00:00:00 2001 From: bivirus Date: Fri, 10 May 2024 20:21:07 +0200 Subject: [PATCH 11/15] Feat: added flag to stretch flags --- main.cpp | 322 ++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 202 insertions(+), 120 deletions(-) diff --git a/main.cpp b/main.cpp index 31b7594..c7490ea 100644 --- a/main.cpp +++ b/main.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #if defined(_WIN32) #include #include @@ -181,6 +182,177 @@ std::map aliases = { { "progress", "progress-pride" }, }; +flag_t stretch1dFlagTo(const flag_t& flag, const int height) { + if (std::holds_alternative>>(flag.colors)) { + printf("WARNING: Method for stretching 1D flags called on 2D flag\n"); + return flag; + } + auto stretchedColors = std::get>(flag.colors); + switch (flag.stretchVertical) { + case StretchRuleVertical::Allowed: { + const int currentHeight = static_cast(stretchedColors.size()); + const std::vector unstretchedColors = stretchedColors; + if (currentHeight >= height) { + break; + } + stretchedColors.clear(); + const double stretchFactor = static_cast(height) / currentHeight; + for (int i = 0; i < height; ++i) { + int originalIndex = static_cast(i / stretchFactor); + if (originalIndex >= currentHeight) { + originalIndex = currentHeight-1; + } + stretchedColors.push_back(unstretchedColors[originalIndex]); + } + break; + } + case StretchRuleVertical::PreserveTop: { + while (static_cast(stretchedColors.size()) < height) { + stretchedColors.push_back(stretchedColors.back()); + } + break; + } + case StretchRuleVertical::PreserveCenter: { + const int delta_height = height - static_cast(stretchedColors.size()); + for (int i = 0; i < delta_height / 2; ++i) { + stretchedColors.insert(stretchedColors.begin(), stretchedColors.front()); + stretchedColors.push_back(stretchedColors.back()); + } + break; + } + case StretchRuleVertical::PreserveBottom: { + while (static_cast(stretchedColors.size()) < height) { + stretchedColors.insert(stretchedColors.begin(), stretchedColors.front()); + } + break; + } + default: + break; + } + return flag_t { + .colors = stretchedColors, + .description = flag.description, + .stretchVertical = flag.stretchVertical, + .stretchHorizontal = flag.stretchHorizontal + }; +} + +flag_t stretch2dFlagTo(const flag_t& flag, const int width, const int height) { + if (std::holds_alternative>(flag.colors)) { + printf("WARNING: Method for stretching 2D flags called on 1D flag\n"); + return flag; + } + auto stretchedColors = std::get>>(flag.colors); + switch (flag.stretchHorizontal) { + case StretchRuleHorizontal::Allowed: { + const int currentWidth = static_cast(stretchedColors[0].size()); + const std::vector> unstretchedColors = stretchedColors; + if (currentWidth >= width) { + break; + } + const double stretchFactor = static_cast(width) / currentWidth; + for (int row = 0; row < static_cast(unstretchedColors.size()); ++row) { + stretchedColors[row].clear(); + double error = 0.0; + for (int i = 0; i < width; ++i) { + const double exactOriginalIndex = i / stretchFactor; + int originalIndex = static_cast(exactOriginalIndex); + error += exactOriginalIndex - originalIndex; + if (error > 1.0) { + ++originalIndex; + error = 0.0; + } else if (error < -1.0) { + --originalIndex; + error = 0.0; + } + if (originalIndex < 0) { + originalIndex = 0; + } else if (originalIndex >= currentWidth) { + originalIndex = currentWidth-1; + } + stretchedColors[row].push_back(unstretchedColors[row][originalIndex]); + } + } + break; + } + case StretchRuleHorizontal::PreserveLeft: { + for (auto& row : stretchedColors) { + while (static_cast(row.size()) < width) { + row.push_back(row.back()); + } + } + break; + } + case StretchRuleHorizontal::PreserveCenter: { + const int delta_width = width - static_cast(stretchedColors[0].size()); + for (auto& row : stretchedColors) { + for (int i = 0; i < delta_width / 2; ++i) { + row.insert(row.begin(), row.front()); + row.push_back(row.back()); + } + } + break; + } + case StretchRuleHorizontal::PreserveRight: { + for (auto& row : stretchedColors) { + while (static_cast(row.size()) < width) { + row.insert(row.begin(), row.front()); + } + } + break; + } + default: + break; + } + switch (flag.stretchVertical) { + case StretchRuleVertical::Allowed: { + const int currentHeight = static_cast(stretchedColors.size()); + const std::vector> unstretchedColors = stretchedColors; + if (currentHeight >= height) { + break; + } + stretchedColors.clear(); + const double stretchFactor = static_cast(height) / currentHeight; + for (int i = 0; i < height; ++i) { + int originalIndex = static_cast(i / stretchFactor); + if (originalIndex >= currentHeight) { + originalIndex = currentHeight-1; + } + stretchedColors.insert(stretchedColors.begin() + i, unstretchedColors[originalIndex]); + } + break; + } + case StretchRuleVertical::PreserveTop: { + while (static_cast(stretchedColors.size()) < height) { + stretchedColors.push_back(stretchedColors.back()); + } + break; + } + case StretchRuleVertical::PreserveCenter: { + const int delta_height = height - static_cast(stretchedColors.size()); + for (int i = 0; i < delta_height / 2; ++i) { + stretchedColors.insert(stretchedColors.begin(), stretchedColors.front()); + stretchedColors.push_back(stretchedColors.back()); + } + break; + } + case StretchRuleVertical::PreserveBottom: { + while (static_cast(stretchedColors.size()) < height) { + stretchedColors.insert(stretchedColors.begin(), stretchedColors.front()); + } + break; + } + default: + break; + } + return flag_t { + .colors = stretchedColors, + .description = flag.description, + .stretchVertical = flag.stretchVertical, + .stretchHorizontal = flag.stretchHorizontal + }; +} + std::vector g_colorQueue; std::vector g_filesToCat; unsigned int g_currentRow = 0; @@ -189,6 +361,8 @@ bool two_dimensiona_flag = false; flag_t current2dFlag; auto g_colorAdjustment = colorAdjust::none; +int stretchToHeight = 0; + #if defined(_WIN32) bool g_useColors = _isatty(_fileno(stdout)); bool g_trueColor = true; @@ -233,13 +407,23 @@ int bestNonTruecolorMatch(color_t const& color) { void pushFlag(flag_t const& flag) { if (std::holds_alternative>(flag.colors)) { - auto const& colors = std::get>(flag.colors); + std::vector colors; + if (stretchToHeight != 0) { + const auto& stretchedFlag = stretch1dFlagTo(flag, stretchToHeight); + colors = std::get>(stretchedFlag.colors); + } else { + colors = std::get>(flag.colors); + } for (color_t const& color : colors) { g_colorQueue.push_back(color); } } else { two_dimensiona_flag = true; - current2dFlag = flag; + if (stretchToHeight != 0) { + current2dFlag = stretch2dFlagTo(flag, 0, stretchToHeight); + } else { + current2dFlag = flag; + } } } @@ -324,129 +508,25 @@ void resetColor() { } } -flag_t stretch2dFlagTo(const flag_t& flag, const int width, const int height) { - if (std::holds_alternative>(flag.colors)) { - printf("WARNING: Method for stretching 2D flags called on 1D flag\n"); - return flag; - } - auto stretchedColors = std::get>>(flag.colors); - switch (flag.stretchHorizontal) { - - case StretchRuleHorizontal::Allowed: { - const int currentWidth = static_cast(stretchedColors[0].size()); - const std::vector> unstretchedColors = stretchedColors; - if (currentWidth >= width) { - break; - } - const double stretchFactor = static_cast(width) / currentWidth; - for (int row = 0; row < static_cast(unstretchedColors.size()); ++row) { - stretchedColors[row].clear(); - double error = 0.0; - for (int i = 0; i < width; ++i) { - const double exactOriginalIndex = i / stretchFactor; - int originalIndex = static_cast(exactOriginalIndex); - error += exactOriginalIndex - originalIndex; - if (error > 1.0) { - ++originalIndex; - error = 0.0; - } else if (error < -1.0) { - --originalIndex; - error = 0.0; - } - if (originalIndex < 0) { - originalIndex = 0; - } else if (originalIndex >= currentWidth) { - originalIndex = currentWidth-1; - } - stretchedColors[row].push_back(unstretchedColors[row][originalIndex]); - } - } - break; - } - case StretchRuleHorizontal::PreserveLeft: { - for (auto& row : stretchedColors) { - while (static_cast(row.size()) < width) { - row.push_back(row.back()); - } - } - break; - } - case StretchRuleHorizontal::PreserveCenter: { - const int delta_width = width - static_cast(stretchedColors[0].size()); - for (auto& row : stretchedColors) { - for (int i = 0; i < delta_width / 2; ++i) { - row.insert(row.begin(), row.front()); - row.push_back(row.back()); - } - } - break; - } - case StretchRuleHorizontal::PreserveRight: { - for (auto& row : stretchedColors) { - while (static_cast(row.size()) < width) { - row.insert(row.begin(), row.front()); - } - } - break; - } - default: - break; - } - switch (flag.stretchVertical) { - case StretchRuleVertical::Allowed: { - const int currentHeight = static_cast(stretchedColors.size()); - const std::vector> unstretchedColors = stretchedColors; - if (currentHeight >= height) { - break; - } - stretchedColors.clear(); - const double stretchFactor = static_cast(height) / currentHeight; - for (int i = 0; i < height; ++i) { - int originalIndex = static_cast(i / stretchFactor); - if (originalIndex >= currentHeight) { - originalIndex = currentHeight-1; - } - stretchedColors.insert(stretchedColors.begin() + i, unstretchedColors[originalIndex]); - } - break; - } - case StretchRuleVertical::PreserveTop: { - while (static_cast(stretchedColors.size()) < height) { - stretchedColors.push_back(stretchedColors.back()); - } - break; - } - case StretchRuleVertical::PreserveCenter: { - const int delta_height = height - static_cast(stretchedColors.size()); - for (int i = 0; i < delta_height / 2; ++i) { - stretchedColors.insert(stretchedColors.begin(), stretchedColors.front()); - stretchedColors.push_back(stretchedColors.back()); - } - break; - } - case StretchRuleVertical::PreserveBottom: { - while (static_cast(stretchedColors.size()) < height) { - stretchedColors.insert(stretchedColors.begin(), stretchedColors.front()); - } - break; - } - default: - break; - } - return flag_t { - .colors = stretchedColors, - .description = flag.description, - .stretchVertical = flag.stretchVertical, - .stretchHorizontal = flag.stretchHorizontal - }; -} - -void parseCommandLine(const int argc, char** argv) { // TODO: add support for -s ,--stretch to stretch the flag to a certain height +void parseCommandLine(const int argc, char** argv) { bool finishedReadingFlags = false; for (int i = 1; i < argc; ++i) { if (finishedReadingFlags) { g_filesToCat.emplace_back(argv[i]); } + else if (strEqual(argv[i], "-s") || strEqual(argv[i], "--stretch")) { + if (i + 1 < argc) { + try { + stretchToHeight = std::stoi(argv[++i]); + } catch (std::invalid_argument&) { + fprintf(stderr, "pridecat: Invalid height '%s'\n", argv[i]); + exit(1); + } + } else { + fprintf(stderr, "pridecat: Expected an argument after %s\n", argv[i]); + exit(1); + } + } else if (strEqual(argv[i], "-h") || strEqual(argv[i], "--help")) { printf("pridecat!\n"); printf("It's like cat but more colorful :)\n"); @@ -502,6 +582,8 @@ void parseCommandLine(const int argc, char** argv) { // TODO: add support for -s printf(" Darken colors slightly for improved readability on light backgrounds\n\n"); printf(" -h,--help\n"); printf(" Display this message\n\n"); + printf(" -s,--stretch \n"); + printf(" Stretch the flag to a certain height before repeating\n\n"); printf("Examples:\n"); printf(" pridecat f - g Output f's contents, then stdin, then g's contents.\n"); From ac8d1f2adc797c43f5f4872c95a1bc649c82658f Mon Sep 17 00:00:00 2001 From: bivirus Date: Fri, 10 May 2024 21:54:32 +0200 Subject: [PATCH 12/15] Feat: added installer (Readme only correct after merge) --- README.md | 5 ++++ install.sh | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 91 insertions(+) create mode 100644 install.sh diff --git a/README.md b/README.md index 407b2c8..093d8cd 100644 --- a/README.md +++ b/README.md @@ -77,6 +77,11 @@ Colorize your terminal output with pride! Display the help page ``` +## Installation (Linux) +```bash +curl -s https://raw.githubusercontent.com/lunasorcery/pridecat/main/install.sh | bash +``` + ## Building On any *nix system it _should_ be as simple as: diff --git a/install.sh b/install.sh new file mode 100644 index 0000000..ee0d915 --- /dev/null +++ b/install.sh @@ -0,0 +1,86 @@ +#!/bin/bash + +# Define the colors of the pride flag +RED='\033[38;2;228;3;3m' +ORANGE='\033[38;2;255;140;0m' +YELLOW='\033[38;2;255;237;0m' +GREEN='\033[38;2;0;128;38m' +BLUE='\033[38;2;0;77;255m' +PURPLE='\033[38;2;117;7;135m' +NC='\033[0m' # No Color + +# Print the Pridecat banner with pride flag colors +echo -e "${RED}mmmmm mmmmm mmmmm mmmm mmmmmm mmm mm mmmmmmm${NC}" +echo -e "${ORANGE}# \"# # \"# # # \"m # m\" \" ## # ${NC}" +echo -e "${YELLOW}#mmm#\" #mmmm\" # # # #mmmmm # # # # ${NC}" +echo -e "${GREEN}# # \"m # # # # # #mm# # ${NC}" +echo -e "${BLUE}# # \" mm#mm #mmm\" #mmmmm \"mmm\" # # # ${NC}" +echo -e "${PURPLE}Welcome to the Pridecat installation script!${NC}" + +printf "\n" + +echo -e "${GREEN}Do you want a simple or advanced setup? (s/a; default: s)${NC}" +read setup_type + +if [ "$setup_type" = "a" ]; then + echo -e "${RED}Advanced setup selected. ${NC}" + echo -e "${GREEN}Fetching forks...${NC}" + repos=$(curl -s https://api.github.com/repos/lunasorcery/pridecat/forks | jq -r '.[].full_name') + repos=("lunasorcery/pridecat" $repos) + + echo -e "${GREEN}Please select a repo (1 is the official repo):${NC}" + select repo in "${repos[@]}"; do + if [[ -n $repo ]]; then + echo -e "${GREEN}Using $repo${NC}" + break + else + echo -e "${RED}Invalid option${NC}" + exit 1 + fi + done + + echo -e "${GREEN}Fetching branches...${NC}" + branches=$(curl -s https://api.github.com/repos/$repo/branches | jq -r '.[].name') + if [ ${#branches[@]} -eq 1 ]; then + branch=${branches[0]} + echo -e "${GREEN}Only one branch found: $branch. Using it.${NC}" + else + echo -e "${GREEN}Please select a branch (1 is the main branch):${NC}" + select branch in "${branches[@]}"; do + if [[ -n $branch ]]; then + echo -e "${GREEN}Using $branch${NC}" + break + else + echo -e "${RED}Invalid option${NC}" + exit 1 + fi + done + fi + + echo -e "${GREEN}Setting up the advanced setup...${NC}" + mkdir .temp-pridecat + cd .temp-pridecat + echo -e "${GREEN}Downloading the files...${NC}" + wget https://raw.githubusercontent.com/$repo/$branch/Makefile > /dev/null 2>&1 + wget https://raw.githubusercontent.com/$repo/$branch/main.cpp > /dev/null 2>&1 + echo -e "${GREEN}Building and installing...${NC}" + make && sudo make install + echo -e "${GREEN}Cleaning up...${NC}" + cd .. + rm -rf .temp-pridecat + echo "Done!" | pridecat + +else + echo -e "${GREEN}Setting up the simple setup...${NC}" + mkdir .temp-pridecat + cd .temp-pridecat + echo -e "${GREEN}Downloading the files...${NC}" + wget https://raw.githubusercontent.com/lunasorcery/pridecat/main/Makefile > /dev/null 2>&1 + wget https://raw.githubusercontent.com/lunasorcery/pridecat/main/main.cpp > /dev/null 2>&1 + echo -e "${GREEN}Building and installing...${NC}" + make && sudo make install + echo -e "${GREEN}Cleaning up...${NC}" + cd .. + rm -rf .temp-pridecat + echo "Done!" | pridecat +fi \ No newline at end of file From b358f4e5bfc09c6f6431d5b700d979c565746296 Mon Sep 17 00:00:00 2001 From: bivirus Date: Fri, 10 May 2024 21:57:25 +0200 Subject: [PATCH 13/15] Chore: updated readme --- README.md | 7 +++++++ main.cpp | 4 ++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 093d8cd..6fe8632 100644 --- a/README.md +++ b/README.md @@ -47,6 +47,10 @@ Colorize your terminal output with pride! --pansexual,--pan Pansexual pride flag designed by Evie Varney in 2010 + +--progress-pride,--progress + Progress pride flag designed by Daniel Quasar in 2018 + --transgender,--trans Transgender pride flag designed by Monica Helms in 1999 @@ -73,6 +77,9 @@ Colorize your terminal output with pride! -T,--no-truecolor Force disable truecolor output (even if the terminal does seem to support it) +-s,--stretch + Stretch the flag to a certain height before repeating + -h,--help Display the help page ``` diff --git a/main.cpp b/main.cpp index c7490ea..5844b5c 100644 --- a/main.cpp +++ b/main.cpp @@ -580,10 +580,10 @@ void parseCommandLine(const int argc, char** argv) { printf(" Lighten colors slightly for improved readability on dark backgrounds\n\n"); printf(" -d,--darken\n"); printf(" Darken colors slightly for improved readability on light backgrounds\n\n"); - printf(" -h,--help\n"); - printf(" Display this message\n\n"); printf(" -s,--stretch \n"); printf(" Stretch the flag to a certain height before repeating\n\n"); + printf(" -h,--help\n"); + printf(" Display this message\n\n"); printf("Examples:\n"); printf(" pridecat f - g Output f's contents, then stdin, then g's contents.\n"); From 4edcb4c5701787f6a345db9922a12c021108a769 Mon Sep 17 00:00:00 2001 From: bivirus Date: Fri, 10 May 2024 21:57:25 +0200 Subject: [PATCH 14/15] Chore: updated readme --- README.md | 9 ++++++++- main.cpp | 4 ++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 093d8cd..a4da06b 100644 --- a/README.md +++ b/README.md @@ -47,6 +47,10 @@ Colorize your terminal output with pride! --pansexual,--pan Pansexual pride flag designed by Evie Varney in 2010 + +--progress-pride,--progress + Progress pride flag designed by Daniel Quasar in 2018 + --transgender,--trans Transgender pride flag designed by Monica Helms in 1999 @@ -73,6 +77,9 @@ Colorize your terminal output with pride! -T,--no-truecolor Force disable truecolor output (even if the terminal does seem to support it) +-s,--stretch + Stretch the flag to a certain height before repeating + -h,--help Display the help page ``` @@ -92,7 +99,7 @@ cd pridecat make && make install ``` -This depends on a recent (C++11) C++ compiler being available. If you encounter issues, please let me know. +This depends on a recent (C++17) C++ compiler being available. If you encounter issues, please let me know. ## Windows support? diff --git a/main.cpp b/main.cpp index c7490ea..5844b5c 100644 --- a/main.cpp +++ b/main.cpp @@ -580,10 +580,10 @@ void parseCommandLine(const int argc, char** argv) { printf(" Lighten colors slightly for improved readability on dark backgrounds\n\n"); printf(" -d,--darken\n"); printf(" Darken colors slightly for improved readability on light backgrounds\n\n"); - printf(" -h,--help\n"); - printf(" Display this message\n\n"); printf(" -s,--stretch \n"); printf(" Stretch the flag to a certain height before repeating\n\n"); + printf(" -h,--help\n"); + printf(" Display this message\n\n"); printf("Examples:\n"); printf(" pridecat f - g Output f's contents, then stdin, then g's contents.\n"); From ad19d3139c8b83c296c31a0faa070d5831c203e1 Mon Sep 17 00:00:00 2001 From: bivirus Date: Wed, 31 Jul 2024 16:06:02 +0200 Subject: [PATCH 15/15] chore: add uninstall instructions to README.md --- README.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/README.md b/README.md index a4da06b..2ee306b 100644 --- a/README.md +++ b/README.md @@ -101,6 +101,17 @@ make && make install This depends on a recent (C++17) C++ compiler being available. If you encounter issues, please let me know. +## Uninstall (Linux) +```bash +rm -f /usr/local/bin/pridecat +``` +or +``` +git clone https://github.com/lunasorcery/pridecat.git +cd pridecat +make uninstall +``` + ## Windows support? There's currently no Windows-compatible build setup, but the code should work under the notable windows terminals if you compile it with cl.exe. Tested in cmd, PowerShell, and Windows Terminal.