alec

Abstraction Layer for Escape Codes
git clone git://git.dimitrijedobrota.com/alec.git
Log | Files | Refs | README | LICENSE

commit 7cf8942434418b36e88adc926265c5be9f488375
parent 22c370f54016fa15ea40033194db9ba0e5894acd
Author: Dimitrije Dobrota <mail@dimitrijedobrota.com>
Date:   Sun, 31 Dec 2023 15:45:59 +0000

Streamline generation process

Diffstat:
MCMakeLists.txt | 2+-
Mdemo/demo.cpp | 17+++++++++--------
Msrc/alec.hpp | 266+++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------------
3 files changed, 201 insertions(+), 84 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt @@ -3,7 +3,7 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON) project( Alec - VERSION 0.0.1 + VERSION 0.0.2 DESCRIPTION "Abstraction Layer for Escape Codes" HOMEPAGE_URL https://git.dimitrijedobrota.com/alec.git LANGUAGES CXX diff --git a/demo/demo.cpp b/demo/demo.cpp @@ -2,19 +2,20 @@ #include <iostream> int main(void) { + std::cout << ALEC::ABUF_SHOW << ALEC::CURSOR_HIDE; - std::cout << ALEC::CURSOR_POSITION(1, 1) << ALEC::FOREGROUND(91) << "HELLO!\n"; + std::cout << ALEC::CURSOR_POSITION<1, 1> << ALEC::FOREGROUND<91> << "HELLO!\n"; - std::cout << ALEC::CURSOR_DOWN(3); - std::cout << ALEC::FOREGROUND(30) << ALEC::BACKGROUND(196) << "WORLD!\n"; + std::cout << ALEC::CURSOR_DOWN<3>; + std::cout << ALEC::FOREGROUND<30> << ALEC::BACKGROUND<196> << "WORLD!\n"; - std::cout << ALEC::BACKGROUND(ALEC::DEFAULT) << "testing 1...\n" << ALEC::FOREGROUND(ALEC::DEFAULT); - std::cout << ALEC::DECOR_SET(ALEC::INVERSE) << "testing 2...\n" << ALEC::DECOR_RESET(ALEC::INVERSE); + std::cout << ALEC::BACKGROUND<ALEC::DEFAULT> << "testing 1...\n" << ALEC::FOREGROUND<ALEC::DEFAULT>; + std::cout << ALEC::DECOR_SET<ALEC::INVERSE> << "testing 2...\n" << ALEC::DECOR_RESET<ALEC::INVERSE>; - std::cout << ALEC::CURSOR_UP(5) << "Hello there!" << ALEC::CURSOR_SAVE; - std::cout << ALEC::CURSOR_DOWN(10) << "General Kenobi!"; - std::cout << ALEC::CURSOR_POSITION(10, 40) << "no pain no gain" << ALEC::CURSOR_LOAD; + std::cout << ALEC::CURSOR_UP<5> << "Hello there!" << ALEC::CURSOR_SAVE; + std::cout << ALEC::CURSOR_DOWN<10> << "General Kenobi!"; + std::cout << ALEC::CURSOR_POSITION<10, 40> << "no pain no gain" << ALEC::CURSOR_LOAD; getchar(); diff --git a/src/alec.hpp b/src/alec.hpp @@ -1,8 +1,9 @@ #ifndef ALEC_ALEC_H #define ALEC_ALEC_H -#include <format> +#include <array> #include <iostream> +#include <string_view> namespace ALEC { @@ -18,7 +19,7 @@ enum CTRL { DEL = 0x7F, }; -enum COLOR { +enum class COLOR { BLACK = 0, RED = 1, GREEN = 2, @@ -30,7 +31,7 @@ enum COLOR { DEFAULT = 9, }; -enum DECOR { +enum class DECOR { RESET = 0, BOLD = 1, DIM = 2, @@ -42,120 +43,235 @@ enum DECOR { STRIKE = 9, }; -template <typename... Args> class CMD { - public: - constexpr CMD(const char c) : c(c) {} - constexpr std::string operator()(Args... args) const { - return std::format(fmt, (char)CTRL::ESC, args..., c); +using enum COLOR; +using enum DECOR; + +template <std::string_view const &...Strs> struct join { + static constexpr auto impl() noexcept { + constexpr std::size_t len = (Strs.size() + ... + 0); + std::array<char, len + 1> arr{}; + auto append = [i = 0, &arr](auto const &s) mutable { + for (auto c : s) + arr[i++] = c; + }; + (append(Strs), ...); + arr[len] = 0; + return arr; } + static constexpr auto arr = impl(); + static constexpr std::string_view value{arr.data(), arr.size() - 1}; +}; - private: - const char c; +static constexpr const std::string_view OP_ESC = "\033["; - static constexpr auto arr = []() { - constexpr std::size_t len = sizeof...(Args) * 3 + 4; - std::array<char, len + 1> arr = {'{', '}', '['}; - for (std::size_t i = 3; i < len - 1; i += 3) { - arr[i] = '{', arr[i + 1] = '}', arr[i + 2] = ';'; - } - arr[len - 2] = '{', arr[len - 1] = '}', arr[len] = 0; - return arr; - }(); - static constexpr auto fmt = std::string_view(arr.data(), arr.size() - 1); +template <std::string_view const &...Strs> static constexpr auto concatenate = join<Strs...>::value; +template <std::string_view const &...Strs> static constexpr auto escape = join<OP_ESC, Strs...>::value; + +static constexpr const std::array<std::string_view, 256> l = { + "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", + "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", + "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "40", "41", "42", "43", "44", + "45", "46", "47", "48", "49", "50", "51", "52", "53", "54", "55", "56", "57", "58", "59", + "60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "70", "71", "72", "73", "74", + "75", "76", "77", "78", "79", "80", "81", "82", "83", "84", "85", "86", "87", "88", "89", + "90", "91", "92", "93", "94", "95", "96", "97", "98", "99", "100", "101", "102", "103", "104", + "105", "106", "107", "108", "109", "110", "111", "112", "113", "114", "115", "116", "117", "118", "119", + "120", "121", "122", "123", "124", "125", "126", "127", "128", "129", "130", "131", "132", "133", "134", + "135", "136", "137", "138", "139", "140", "141", "142", "143", "144", "145", "146", "147", "148", "149", + "150", "151", "152", "153", "154", "155", "156", "157", "158", "159", "160", "161", "162", "163", "164", + "165", "166", "167", "168", "169", "170", "171", "172", "173", "174", "175", "176", "177", "178", "179", + "180", "181", "182", "183", "184", "185", "186", "187", "188", "189", "190", "191", "192", "193", "194", + "195", "196", "197", "198", "199", "200", "201", "202", "203", "204", "205", "206", "207", "208", "209", + "210", "211", "212", "213", "214", "215", "216", "217", "218", "219", "220", "221", "222", "223", "224", + "225", "226", "227", "228", "229", "230", "231", "232", "233", "234", "235", "236", "237", "238", "239", + "240", "241", "242", "243", "244", "245", "246", "247", "248", "249", "250", "251", "252", "253", "254", + "255", +}; + +static constexpr const std::array<std::string_view, 256> lp = { + "0;", "1;", "2;", "3;", "4;", "5;", "6;", "7;", "8;", "9;", "10;", "11;", "12;", + "13;", "14;", "15;", "16;", "17;", "18;", "19;", "20;", "21;", "22;", "23;", "24;", "25;", + "26;", "27;", "28;", "29;", "30;", "31;", "32;", "33;", "34;", "35;", "36;", "37;", "38;", + "39;", "40;", "41;", "42;", "43;", "44;", "45;", "46;", "47;", "48;", "49;", "50;", "51;", + "52;", "53;", "54;", "55;", "56;", "57;", "58;", "59;", "60;", "61;", "62;", "63;", "64;", + "65;", "66;", "67;", "68;", "69;", "70;", "71;", "72;", "73;", "74;", "75;", "76;", "77;", + "78;", "79;", "80;", "81;", "82;", "83;", "84;", "85;", "86;", "87;", "88;", "89;", "90;", + "91;", "92;", "93;", "94;", "95;", "96;", "97;", "98;", "99;", "100;", "101;", "102;", "103;", + "104;", "105;", "106;", "107;", "108;", "109;", "110;", "111;", "112;", "113;", "114;", "115;", "116;", + "117;", "118;", "119;", "120;", "121;", "122;", "123;", "124;", "125;", "126;", "127;", "128;", "129;", + "130;", "131;", "132;", "133;", "134;", "135;", "136;", "137;", "138;", "139;", "140;", "141;", "142;", + "143;", "144;", "145;", "146;", "147;", "148;", "149;", "150;", "151;", "152;", "153;", "154;", "155;", + "156;", "157;", "158;", "159;", "160;", "161;", "162;", "163;", "164;", "165;", "166;", "167;", "168;", + "169;", "170;", "171;", "172;", "173;", "174;", "175;", "176;", "177;", "178;", "179;", "180;", "181;", + "182;", "183;", "184;", "185;", "186;", "187;", "188;", "189;", "190;", "191;", "192;", "193;", "194;", + "195;", "196;", "197;", "198;", "199;", "200;", "201;", "202;", "203;", "204;", "205;", "206;", "207;", + "208;", "209;", "210;", "211;", "212;", "213;", "214;", "215;", "216;", "217;", "218;", "219;", "220;", + "221;", "222;", "223;", "224;", "225;", "226;", "227;", "228;", "229;", "230;", "231;", "232;", "233;", + "234;", "235;", "236;", "237;", "238;", "239;", "240;", "241;", "242;", "243;", "244;", "245;", "246;", + "247;", "248;", "249;", "250;", "251;", "252;", "253;", "254;", "255;", }; -static constexpr const CMD<int> CURSOR_UP('A'); -static constexpr const CMD<int> CURSOR_DOWN('B'); -static constexpr const CMD<int> CURSOR_FRWD('C'); -static constexpr const CMD<int> CURSOR_BACK('D'); -static constexpr const CMD<int> CURSOR_LINE_NEXT('E'); -static constexpr const CMD<int> CURSOR_LINE_PREV('F'); -static constexpr const CMD<int> CURSOR_COLUMN('G'); -static constexpr const CMD<int> ERASE_DISPLAY('J'); -static constexpr const CMD<int> ERASE_LINE('K'); -static constexpr const CMD<int> SCROLL_UP('S'); -static constexpr const CMD<int> SCROLL_DOWN('T'); +static constexpr const std::string_view OP_A = "A"; +static constexpr const std::string_view OP_B = "B"; +static constexpr const std::string_view OP_C = "C"; +static constexpr const std::string_view OP_D = "D"; +static constexpr const std::string_view OP_E = "E"; +static constexpr const std::string_view OP_F = "F"; +static constexpr const std::string_view OP_G = "G"; +static constexpr const std::string_view OP_H = "H"; +static constexpr const std::string_view OP_J = "J"; +static constexpr const std::string_view OP_K = "K"; +static constexpr const std::string_view OP_S = "S"; +static constexpr const std::string_view OP_T = "T"; +static constexpr const std::string_view OP_h = "h"; +static constexpr const std::string_view OP_l = "l"; +static constexpr const std::string_view OP_m = "m"; +static constexpr const std::string_view OP_s = "s"; +static constexpr const std::string_view OP_u = "u"; +static constexpr const std::string_view buffer = "?1049"; +static constexpr const std::string_view cursor = "?25"; + +// Move cursor up/down/frwd/back +template <int n, class CharT, class Traits> +static constexpr auto &CURSOR_UP(std::basic_ostream<CharT, Traits> &bos) { + return bos << escape<l[n], OP_A>; +} + +template <int n, class CharT, class Traits> +static constexpr auto &CURSOR_DOWN(std::basic_ostream<CharT, Traits> &bos) { + return bos << escape<l[n], OP_B>; +} + +template <int n, class CharT, class Traits> +static constexpr auto &CURSOR_FRWD(std::basic_ostream<CharT, Traits> &bos) { + return bos << escape<l[n], OP_C>; +} + +template <int n, class CharT, class Traits> +static constexpr auto &CURSOR_BACK(std::basic_ostream<CharT, Traits> &bos) { + return bos << escape<l[n], OP_D>; +} + +// Move cursor to the next/prev line +template <int n, class CharT, class Traits> +static constexpr auto &CURSOR_LINE_NEXT(std::basic_ostream<CharT, Traits> &bos) { + return bos << escape<l[n], OP_E>; +} + +template <int n, class CharT, class Traits> +static constexpr auto &CURSOR_LINE_PREV(std::basic_ostream<CharT, Traits> &bos) { + return bos << escape<l[n], OP_F>; +} + +// Set cursor to specific column +template <int n, class CharT, class Traits> +static constexpr auto &CURSOR_COLUMN(std::basic_ostream<CharT, Traits> &bos) { + return bos << escape<l[n], OP_G>; +} + +// Erase functions +template <int n, class CharT, class Traits> +static constexpr auto &ERASE_DISPLAY(std::basic_ostream<CharT, Traits> &bos) { + return bos << escape<l[n], OP_J>; +} -static constexpr const CMD<int, int> CURSOR_POSITION('H'); +template <int n, class CharT, class Traits> +static constexpr auto &ERASE_LINE(std::basic_ostream<CharT, Traits> &bos) { + return bos << escape<l[n], OP_K>; +} + +// Scroll up/down +template <int n, class CharT, class Traits> +static constexpr auto &SCROLL_UP(std::basic_ostream<CharT, Traits> &bos) { + return bos << escape<l[n], OP_S>; +} + +template <int n, class CharT, class Traits> +static constexpr auto &SCROLL_DOWN(std::basic_ostream<CharT, Traits> &bos) { + return bos << escape<l[n], OP_T>; +} + +// Set cursor to a specific position +template <int n, int m, class CharT, class Traits> +static constexpr auto &CURSOR_POSITION(std::basic_ostream<CharT, Traits> &bos) { + return bos << escape<lp[n], l[m], OP_H>; +} // palet colors -static constexpr auto FOREGROUND(COLOR color) { - static constexpr const CMD<int> bootstrap('m'); - return bootstrap(30 + color); +template <COLOR color, class CharT, class Traits> +static constexpr auto &FOREGROUND(std::basic_ostream<CharT, Traits> &bos) { + return bos << escape<l[static_cast<uint>(color) + 30], OP_m>; } -static constexpr auto BACKGROUND(COLOR color) { - static constexpr const CMD<int> bootstrap('m'); - return bootstrap(40 + color); +template <COLOR color, class CharT, class Traits> +static constexpr auto &BACKGROUND(std::basic_ostream<CharT, Traits> &bos) { + return bos << escape<l[static_cast<uint>(color) + 40], OP_m>; } // 256-color palette -static constexpr auto FOREGROUND(int idx) { - static constexpr const CMD<int, int, int> bootstrap('m'); - return bootstrap(38, 5, idx); +template <int idx, class CharT, class Traits> +static constexpr auto &FOREGROUND(std::basic_ostream<CharT, Traits> &bos) { + return bos << escape<lp[38], lp[5], l[idx], OP_m>; } -static constexpr auto BACKGROUND(int idx) { - static constexpr const CMD<int, int, int> bootstrap('m'); - return bootstrap(48, 5, idx); +template <int idx, class CharT, class Traits> +static constexpr auto &BACKGROUND(std::basic_ostream<CharT, Traits> &bos) { + return bos << escape<lp[48], lp[5], l[idx], OP_m>; } // RGB colors -static constexpr auto FOREGROUND(int r, int g, int b) { - static constexpr const CMD<int, int, int, int, int> bootstrap('m'); - return bootstrap(38, 5, r, g, b); +template <int R, int G, int B, class CharT, class Traits> +static constexpr auto &FOREGROUND(std::basic_ostream<CharT, Traits> &bos) { + return bos << escape<lp[38], lp[5], lp[R], lp[G], l[B], OP_m>; } -static constexpr auto BACKGROUND(int r, int g, int b) { - static constexpr const CMD<int, int, int, int, int> bootstrap('m'); - return bootstrap(48, 5, r, g, b); +template <int R, int G, int B, class CharT, class Traits> +static constexpr auto &BACKGROUND(std::basic_ostream<CharT, Traits> &bos) { + return bos << escape<lp[48], lp[5], lp[R], lp[G], l[B], OP_m>; } -// Set/Reset text decorators -static constexpr auto DECOR_SET(DECOR decor) { - static constexpr const CMD<int> bootstrap('m'); - return bootstrap(static_cast<int>(decor)); +// Set/reset text decorators +template <DECOR decor, class CharT, class Traits> +static constexpr auto &DECOR_SET(std::basic_ostream<CharT, Traits> &bos) { + return bos << escape<l[static_cast<uint>(decor)], OP_m>; } -static constexpr auto DECOR_RESET(DECOR decor) { - static constexpr const CMD<int> bootstrap('m'); - return bootstrap(static_cast<int>(decor) + 20); +template <DECOR decor, class CharT, class Traits> +static constexpr auto &DECOR_RESET(std::basic_ostream<CharT, Traits> &bos) { + return bos << escape<l[static_cast<uint>(decor) + 20], OP_m>; } +// Savle/load cursor position template <class CharT, class Traits> -static constexpr std::basic_ostream<CharT, Traits> &CURSOR_SAVE(std::basic_ostream<CharT, Traits> &bos) { - static auto sequence = CMD<>('s')(); - return bos << sequence; +static constexpr auto &CURSOR_SAVE(std::basic_ostream<CharT, Traits> &bos) { + return bos << escape<OP_s>; } template <class CharT, class Traits> -static constexpr std::basic_ostream<CharT, Traits> &CURSOR_LOAD(std::basic_ostream<CharT, Traits> &bos) { - static auto sequence = CMD<>('u')(); - return bos << sequence; +static constexpr auto &CURSOR_LOAD(std::basic_ostream<CharT, Traits> &bos) { + return bos << escape<OP_u>; } +// Show/hide cursor template <class CharT, class Traits> -static constexpr std::basic_ostream<CharT, Traits> &CURSOR_SHOW(std::basic_ostream<CharT, Traits> &bos) { - static auto sequence = CMD<const char *>('h')("?25"); - return bos << sequence; +static constexpr auto &CURSOR_SHOW(std::basic_ostream<CharT, Traits> &bos) { + return bos << escape<cursor, OP_h>; } template <class CharT, class Traits> -static constexpr std::basic_ostream<CharT, Traits> &CURSOR_HIDE(std::basic_ostream<CharT, Traits> &bos) { - static auto sequence = CMD<const char *>('l')("?25"); - return bos << sequence; +static constexpr auto &CURSOR_HIDE(std::basic_ostream<CharT, Traits> &bos) { + return bos << escape<cursor, OP_l>; } +// Show/hide alternate buffer template <class CharT, class Traits> -static constexpr std::basic_ostream<CharT, Traits> &ABUF_SHOW(std::basic_ostream<CharT, Traits> &bos) { - static auto sequence = CMD<const char *>('h')("?1049"); - return bos << sequence; +static constexpr auto &ABUF_SHOW(std::basic_ostream<CharT, Traits> &bos) { + return bos << escape<buffer, OP_h>; } template <class CharT, class Traits> -static constexpr std::basic_ostream<CharT, Traits> &ABUF_HIDE(std::basic_ostream<CharT, Traits> &bos) { - static auto sequence = CMD<const char *>('l')("?1049"); - return bos << sequence; +static constexpr auto &ABUF_HIDE(std::basic_ostream<CharT, Traits> &bos) { + return bos << escape<buffer, OP_l>; } } // namespace ALEC