alecAbstraction Layer for Escape Codes |
git clone git://git.dimitrijedobrota.com/alec.git |
Log | Files | Refs | README | LICENSE | HACKING | CONTRIBUTING | CODE_OF_CONDUCT | BUILDING | |
commit | 16f46c1915dd9520555d47d04dd038c8f781804f |
parent | 7cf8942434418b36e88adc926265c5be9f488375 |
author | Dimitrije Dobrota <mail@dimitrijedobrota.com> |
date | Sun, 31 Dec 2023 16:49:18 +0000 |
Number conversion without lookup table
Diffstat:M | CMakeLists.txt | | | +- |
M | demo/demo.cpp | | | ++++++++++++---------- |
M | src/alec.hpp | | | ++++++++++++++++++++++++++++++++++++---------------------------------------------- |
3 files changed, 84 insertions(+), 101 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
@@ -3,7 +3,7 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
project(
Alec
VERSION 0.0.2
VERSION 0.0.3
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
@@ -1,25 +1,27 @@
#include "alec.hpp"
#include <iostream>
using namespace ALEC;
int main(void) {
std::cout << ALEC::ABUF_SHOW << ALEC::CURSOR_HIDE;
std::cout << ABUF_SHOW << CURSOR_HIDE;
std::cout << ALEC::CURSOR_POSITION<1, 1> << ALEC::FOREGROUND<91> << "HELLO!\n";
std::cout << CURSOR_POSITION<1, 1> << FOREGROUND<91> << "HELLO!\n";
std::cout << ALEC::CURSOR_DOWN<3>;
std::cout << ALEC::FOREGROUND<30> << ALEC::BACKGROUND<196> << "WORLD!\n";
std::cout << CURSOR_DOWN<3>;
std::cout << FOREGROUND<30> << 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 << BACKGROUND<DEFAULT> << "testing 1...\n" << FOREGROUND<DEFAULT>;
std::cout << DECOR_SET<INVERSE> << "testing 2...\n" << DECOR_RESET<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 << CURSOR_UP<5> << "Hello there!" << CURSOR_SAVE;
std::cout << CURSOR_DOWN<10> << "General Kenobi!";
std::cout << CURSOR_POSITION<10, 40> << "no pain no gain" << CURSOR_LOAD << CURSOR_SHOW;
getchar();
std::cout << ALEC::CURSOR_SHOW << ALEC::ABUF_HIDE;
std::cout << ABUF_HIDE;
return 0;
}
diff --git a/src/alec.hpp b/src/alec.hpp
@@ -2,6 +2,7 @@
#define ALEC_ALEC_H
#include <array>
#include <cstdint>
#include <iostream>
#include <string_view>
@@ -47,7 +48,7 @@ using enum COLOR;
using enum DECOR;
template <std::string_view const &...Strs> struct join {
static constexpr auto impl() noexcept {
static constexpr auto arr = []() {
constexpr std::size_t len = (Strs.size() + ... + 0);
std::array<char, len + 1> arr{};
auto append = [i = 0, &arr](auto const &s) mutable {
@@ -57,221 +58,201 @@ template <std::string_view const &...Strs> struct join {
(append(Strs), ...);
arr[len] = 0;
return arr;
}
static constexpr auto arr = impl();
}();
static constexpr std::string_view value{arr.data(), arr.size() - 1};
};
static constexpr const std::string_view OP_ESC = "\033[";
template <std::intmax_t N> class to_string_t {
public:
constexpr operator const auto &() const { return value; }
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",
private:
static constexpr auto buf = []() {
constexpr const auto len = []() {
std::size_t len = 1;
for (auto n = N; n; len++, n /= 10)
;
return len;
}();
std::array<char, len> arr{};
auto ptr = arr.data() + len;
*--ptr = '\0';
arr[0] = 0;
for (auto n = N; n; n /= 10)
*--ptr = '0' + n % 10;
return arr;
}();
static constexpr std::string_view value{buf.data(), buf.size() - 1};
};
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;",
template <char C> class to_string_c {
public:
constexpr operator const auto &() const { return value; }
private:
static constexpr auto c = C;
static constexpr std::string_view value{&c, 1};
};
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";
static constexpr const std::string_view esc = "\033[";
static constexpr const std::string_view sep = ";";
template <std::string_view const &...Strs> static constexpr auto concatenate = join<Strs...>::value;
template <std::string_view const &...Strs> static constexpr auto escape = join<esc, Strs...>::value;
template <std::intmax_t N> constexpr to_string_t<N> to_string;
template <char C> constexpr to_string_c<C> to_stringc;
template <std::intmax_t N> static constexpr auto to_stringp = join<to_string<N>, sep>::value;
// 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>;
return bos << escape<to_string<n>, to_stringc<'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>;
return bos << escape<to_string<n>, to_stringc<'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>;
return bos << escape<to_string<n>, to_stringc<'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>;
return bos << escape<to_string<n>, to_stringc<'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>;
return bos << escape<to_string<n>, to_stringc<'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>;
return bos << escape<to_string<n>, to_stringc<'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>;
return bos << escape<to_string<n>, to_stringc<'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>;
return bos << escape<to_string<n>, to_stringc<'J'>>;
}
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>;
return bos << escape<to_string<n>, to_stringc<'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>;
return bos << escape<to_string<n>, to_stringc<'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>;
return bos << escape<to_string<n>, to_stringc<'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>;
return bos << escape<to_stringp<n>, to_string<m>, to_stringc<'H'>>;
}
// palet colors
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>;
return bos << escape<to_string<static_cast<uint>(color) + 30>, to_stringc<'m'>>;
}
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>;
return bos << escape<to_string<static_cast<uint>(color) + 40>, to_stringc<'m'>>;
}
// 256-color palette
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>;
return bos << escape<to_stringp<38>, to_stringp<5>, to_string<idx>, to_stringc<'m'>>;
}
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>;
return bos << escape<to_stringp<48>, to_stringp<5>, to_string<idx>, to_stringc<'m'>>;
}
// RGB colors
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>;
return bos << escape<to_stringp<38>, to_stringp<5>, to_stringp<R>, to_stringp<G>, to_string<B>,
to_stringc<'m'>>;
}
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>;
return bos << escape<to_stringp<48>, to_stringp<5>, to_stringp<R>, to_stringp<G>, to_string<B>,
to_stringc<'m'>>;
}
// 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>;
return bos << escape<to_string<static_cast<uint>(decor)>, to_stringc<'m'>>;
}
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>;
return bos << escape<to_string<static_cast<uint>(decor) + 20>, to_stringc<'m'>>;
}
// Savle/load cursor position
template <class CharT, class Traits>
static constexpr auto &CURSOR_SAVE(std::basic_ostream<CharT, Traits> &bos) {
return bos << escape<OP_s>;
return bos << escape<to_stringc<'s'>>;
}
template <class CharT, class Traits>
static constexpr auto &CURSOR_LOAD(std::basic_ostream<CharT, Traits> &bos) {
return bos << escape<OP_u>;
return bos << escape<to_stringc<'u'>>;
}
// Show/hide cursor
template <class CharT, class Traits>
static constexpr auto &CURSOR_SHOW(std::basic_ostream<CharT, Traits> &bos) {
return bos << escape<cursor, OP_h>;
return bos << escape<cursor, to_stringc<'h'>>;
}
template <class CharT, class Traits>
static constexpr auto &CURSOR_HIDE(std::basic_ostream<CharT, Traits> &bos) {
return bos << escape<cursor, OP_l>;
return bos << escape<cursor, to_stringc<'l'>>;
}
// Show/hide alternate buffer
template <class CharT, class Traits>
static constexpr auto &ABUF_SHOW(std::basic_ostream<CharT, Traits> &bos) {
return bos << escape<buffer, OP_h>;
return bos << escape<buffer, to_stringc<'h'>>;
}
template <class CharT, class Traits>
static constexpr auto &ABUF_HIDE(std::basic_ostream<CharT, Traits> &bos) {
return bos << escape<buffer, OP_l>;
return bos << escape<buffer, to_stringc<'l'>>;
}
} // namespace ALEC