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 | e584d30759cc8d1233906f107c9c2e07683a66ca | 
| parent | b02e0ba34e3a27238bfa660bedf1e87fb6313f15 | 
| author | Dimitrije Dobrota < mail@dimitrijedobrota.com > | 
| date | Sun, 15 Jun 2025 18:18:50 +0200 | 
Greatly simplify the implementation
| M | CMakeLists.txt | | | + - | 
| M | example/alec_runtime.cpp | | | + - | 
| M | include/alec/alec.hpp | | | +++++++++++++++++++++++++++++++++++++ --------------------------------------------- | 
3 files changed, 156 insertions(+), 189 deletions(-)
diff --git a/ CMakeLists.txt b/ CMakeLists.txt
          @@ -4,7 +4,7 @@ 
          include(cmake/prelude.cmake)
        
        
          project(
              alec
              VERSION 0.2.0
              VERSION 0.2.1
              DESCRIPTION "Abstraction Layer for Escape Codes"
              HOMEPAGE_URL "git://git.dimitrijedobrota.com/alec.git"
              LANGUAGES CXX
        
        diff --git a/ example/alec_runtime.cpp b/ example/alec_runtime.cpp
          @@ -12,7 +12,7 @@ 
          int main()
        
        
            std::cout << cursor_position(1, 1) << foreground(91) << "HELLO!\n";
            std::cout << cursor_down(3);
            std::cout << foreground(30) << background(96, 53, 64) << "WORLD!\n";
            std::cout << foreground(30) << background(196, 53, 64) << "WORLD!\n";
            std::cout << background(color::def) << "testing 1...\n"
                      << foreground(color::def);
        
        diff --git a/ include/alec/alec.hpp b/ include/alec/alec.hpp
@@ -1,13 +1,13 @@
#pragma once
          #include <algorithm>
          #include <array>
          #include <cassert>
          #include <string>
          #include <based/enum/enum.hpp>
          #include <based/string/literal.hpp>
          #include <based/string/to_string.hpp>
          #include <based/types/types.hpp>
          #include <based/utility/static_view.hpp>
          namespace alec
          {
        
        
          @@ -32,198 +32,63 @@ 
          BASED_DEFINE_ENUM(motion, based::bu8, 0, ENUM_MOTION)
        
        
          namespace detail
          {
          template<std::size_t n>
          static constexpr std::size_t size(based::string_literal<n> /*val*/)
          {
            return n;
          }
          static constexpr std::size_t size(char /*val*/)
          {
            return 1;
          }
          static constexpr std::string start = "\x01B[";
          template<class T>
          static constexpr std::size_t size(T val)
          constexpr void append(std::string& res, const auto& arg)
          {
            std::size_t len = 1;
            while ((val /= 10) != 0) {
              len++;
            }
            return len;
            res += based::to_string(arg);
            res += ';';
          }
          template<std::size_t n>
          static constexpr char* append(char* ptr, based::string_literal<n> val)
          template<class... Args>
          constexpr std::string test(char chr, Args... args)
          {
            std::copy_n(val.data(), n, ptr);
            return ptr + n;  // NOLINT
          }
            auto res = start;
          static constexpr char* append(char* ptr, char val)
          {
            *ptr++ = val;  // NOLINT
            return ptr;
          }
          template<class T>
          static constexpr char* append(char* ptr, T val)
          {
            char* tmp = ptr += size(val);  // NOLINT
            do {  // NOLINT
              *--tmp = '0' + static_cast<char>(val % 10);  // NOLINT
            } while ((val /= 10) != 0);
            return ptr;
          }
            (append(res, args), ...);
            res.back() = chr;
          static constexpr std::string make(auto... args)
          {
            std::string res((size(args) + ... + 2), 0);
            res[0] = 0x1B, res[1] = '[';
            auto* ptr = res.data() + 2;  // NOLINT
            ((ptr = append(ptr, args)), ...);
            return res;
          }
          template<auto... args>
          struct escape_t
          {
            static constexpr const auto value = []()
            {
              std::array<char, (size(args) + ... + 3)> arr = {};
              arr[0] = 0x1B, arr[1] = '[';
              auto* ptr = arr.data() + 2;
              ((ptr = append(ptr, args)), ...);
              return arr;
            }();
            static constexpr auto data = value.data();
          };
          template<auto... args>
          static constexpr auto escape = alec::detail::escape_t<args...>::data;
          template<based::string_literal... strs>
          static constexpr auto escape_literal = escape<strs...>;
          template<auto func, auto... args>
          static constexpr std::string_view escape = based::to_string_view(
              []()
              {
                return func(args...);
              }
          );
          template<based::string_literal str>
          static constexpr std::string_view escape_literal = based::to_string_view(
              []
              {
                return start + std::string(str);
              }
          );
          }  // namespace detail
          // Template compile-time variables
          // Forward-declare templates
          template<auto... val>
          static const char* const background_v = "";
          template<auto... val>
          static const char* const foreground_v = "";
          // Template specializations
          // Move cursor up/down/frwd/back
          template<unsigned cnt>
          static constexpr auto cursor_up_v = detail::escape<cnt, 'A'>;
          template<unsigned cnt>
          static constexpr auto cursor_down_v = detail::escape<cnt, 'B'>;
          template<unsigned cnt>
          static constexpr auto cursor_frwd_v = detail::escape<cnt, 'C'>;
          template<unsigned cnt>
          static constexpr auto cursor_back_v = detail::escape<cnt, 'D'>;
          // Move cursor to the next/prev line
          template<unsigned cnt>
          static constexpr auto cursor_line_next_v = detail::escape<cnt, 'E'>;
          template<unsigned cnt>
          static constexpr auto cursor_line_prev_v = detail::escape<cnt, 'F'>;
          // Set cursor to specific column
          template<unsigned col>
          static constexpr auto cursor_column_v = detail::escape<col, 'G'>;
          // Erase functions
          template<motion::enum_type motion>
          static constexpr auto erase_display_v = detail::escape<motion(), 'J'>;
          template<motion::enum_type motion>
          static constexpr auto erase_line_v = detail::escape<motion(), 'K'>;
          // Scroll up/down
          template<unsigned cnt>
          static constexpr auto scroll_up_v = detail::escape<cnt, 'S'>;
          template<unsigned cnt>
          static constexpr auto scroll_down_v = detail::escape<cnt, 'T'>;
          // Set cursor to a specific position
          template<unsigned row, unsigned col>
          static constexpr auto cursor_position_v = detail::escape<row, ';', col, 'H'>;
          // color
          // palet colors
          template<color::enum_type color>
          static constexpr auto foreground_v<color> = detail::escape<color() + 30, 'm'>;
          template<color::enum_type color>
          static constexpr auto background_v<color> = detail::escape<color() + 40, 'm'>;
          // 256-color palette
          template<based::bu8 idx>
          static constexpr auto foreground_v<idx> =
              detail::escape<38, ';', 5, ';', idx, 'm'>;
          template<based::bu8 idx>
          static constexpr auto background_v<idx> =
              detail::escape<48, ';', 5, ';', idx, 'm'>;
          // RGB colors
          template<based::bu8 red, based::bu8 green, based::bu8 blue>
          static constexpr auto foreground_v<red, green, blue> =
              detail::escape<38, ';', 2, ';', red, ';', green, ';', blue, 'm'>;
          template<based::bu8 red, based::bu8 green, based::bu8 blue>
          static constexpr auto background_v<red, green, blue> =
              detail::escape<48, ';', 2, ';', red, ';', green, ';', blue, 'm'>;
          // Set/reset text decorators
          template<decor::enum_type decor>
          static constexpr auto decor_set_v = detail::escape<decor(), 'm'>;
          template<decor::enum_type decor>
          static constexpr auto decor_reset_v = detail::escape<decor() + 20, 'm'>;
          // Save/restore cursor position;
          static constexpr auto cursor_save_v = detail::escape<'s'>;
          static constexpr auto cursor_restore_v = detail::escape<'u'>;
          // Set screen modes
          template<unsigned mode>
          static constexpr auto screen_mode_set_v = detail::escape<'=', mode, 'h'>;
          template<unsigned mode>
          static constexpr auto screen_mode_reset_v = detail::escape<'=', mode, 'l'>;
          // Private screen modes supported by most terminals
          // Save/restore screen
          static constexpr auto screen_save_v = detail::escape_literal<"?47h">;
          static constexpr auto screen_restore_v = detail::escape_literal<"?47l">;
          // Show/hide cursor
          static constexpr auto cursor_show_v = detail::escape_literal<"?25h">;
          static constexpr auto cursor_hide_v = detail::escape_literal<"?25l">;
          // Save/restore cursor
          static constexpr auto cursor_save_v = detail::escape_literal<"s">;
          static constexpr auto cursor_restore_v = detail::escape_literal<"u">;
          // Enable/disable alternate buffer
          static constexpr auto abuf_enable_v = detail::escape_literal<"?1049h">;
          static constexpr auto abuf_disable_v = detail::escape_literal<"?1049l">;
          // Enable/disable bracketed paste mode
          static constexpr auto paste_enable_v = detail::escape_literal<"?2004h">;
          static constexpr auto paste_disable_v = detail::escape_literal<"?2004l">;
          // Run-time functions
        
        
          @@ -231,90 +96,90 @@ 
          static constexpr auto paste_disable_v = detail::escape_literal<"?2004l">;
        
        
          // Move cursor up/down/frwd/back
          static constexpr auto cursor_up(unsigned cnt)
          {
            return detail::make(cnt, 'A');
            return detail::test('A', cnt);
          }
          static constexpr auto cursor_down(unsigned cnt)
          {
            return detail::make(cnt, 'B');
            return detail::test('B', cnt);
          }
          static constexpr auto cursor_frwd(unsigned cnt)
          {
            return detail::make(cnt, 'C');
            return detail::test('C', cnt);
          }
          static constexpr auto cursor_back(unsigned cnt)
          {
            return detail::make(cnt, 'D');
            return detail::test('D', cnt);
          }
          // Move cursor to the next/prev line
          static constexpr auto cursor_line_next(unsigned cnt)
          {
            return detail::make(cnt, 'E');
            return detail::test('E', cnt);
          }
          static constexpr auto cursor_line_prev(unsigned cnt)
          {
            return detail::make(cnt, 'F');
            return detail::test('F', cnt);
          }
          // Set cursor to specific column
          static constexpr auto cursor_column(unsigned col)
          {
            return detail::make(col, 'G');
            return detail::test('G', col);
          }
          // Erase functions
          static constexpr auto erase_display(motion::enum_type motion)
          {
            return detail::make(motion(), 'J');
            return detail::test('J', motion());
          }
          static constexpr auto erase_line(motion::enum_type motion)
          {
            return detail::make(motion(), 'K');
            return detail::test('K', motion());
          }
          // Scroll up/down
          static constexpr auto scroll_up(unsigned cnt)
          {
            return detail::make(cnt, 'S');
            return detail::test('S', cnt);
          }
          static constexpr auto scroll_down(unsigned cnt)
          {
            return detail::make(cnt, 'T');
            return detail::test('T', cnt);
          }
          // Set cursor to a specific position
          static constexpr auto cursor_position(unsigned row, unsigned col)
          {
            return detail::make(row, ';', col, 'H');
            return detail::test('H', row, col);
          }
          // color
          // palet colors
          static constexpr auto foreground(color::enum_type color)
          {
            return detail::make(color() + 30, 'm');
            return detail::test('m', color() + 30);
          }
          static constexpr auto background(color::enum_type color)
          {
            return detail::make(color() + 40, 'm');
            return detail::test('m', color() + 40);
          }
          // 256-color palette
          static constexpr auto foreground(based::bu8 idx)
          {
            return detail::make(38, ';', 5, ';', idx, 'm');
            return detail::test('m', 38, 5, idx);
          }
          static constexpr auto background(based::bu8 idx)
          {
            return detail::make(48, ';', 5, ';', idx, 'm');
            return detail::test('m', 48, 5, idx);
          }
          // RGB colors
        
        
          @@ -322,36 +187,138 @@ 
          static constexpr auto foreground(
        
        
              based::bu8 red, based::bu8 green, based::bu8 blue
          )
          {
            return detail::make(38, ';', 2, ';', red, ';', green, ';', blue, 'm');
            return detail::test('m', 38, 2, red, green, blue);
          }
          static constexpr auto background(
              based::bu8 red, based::bu8 green, based::bu8 blue
          )
          {
            return detail::make(48, ';', 2, ';', red, ';', green, ';', blue, 'm');
            return detail::test('m', 48, 2, red, green, blue);
          }
          // Set/reset text decorators
          static constexpr auto decor_set(decor::enum_type decor)
          {
            return detail::make(decor(), 'm');
            return detail::test('m', decor());
          }
          static constexpr auto decor_reset(decor::enum_type decor)
          {
            return detail::make(decor() + 20, 'm');
            return detail::test('m', decor() + 20);
          }
          // Set screen modes
          static constexpr auto screen_mode_set(unsigned mode)
          {
            return detail::make('=', mode, 'h');
            return detail::test('h', '=', mode);
          }
          static constexpr auto screen_mode_reset(unsigned mode)
          {
            return detail::make('=', mode, 'l');
            return detail::test('l', '=', mode);
          }
          // Template specializations
          // Move cursor up/down/frwd/back
          template<unsigned cnt>
          static constexpr auto cursor_up_v = detail::escape<cursor_up, cnt>;
          template<unsigned cnt>
          static constexpr auto cursor_down_v = detail::escape<cursor_down, cnt>;
          template<unsigned cnt>
          static constexpr auto cursor_frwd_v = detail::escape<cursor_frwd, cnt>;
          template<unsigned cnt>
          static constexpr auto cursor_back_v = detail::escape<cursor_back, cnt>;
          // Move cursor to the next/prev line
          template<unsigned cnt>
          static constexpr auto cursor_line_next_v =
              detail::escape<cursor_line_next, cnt>;
          template<unsigned cnt>
          static constexpr auto cursor_line_prev_v =
              detail::escape<cursor_line_prev, cnt>;
          // Set cursor to specific column
          template<unsigned cnt>
          static constexpr auto cursor_column_v = detail::escape<cursor_column, cnt>;
          // Erase functions
          template<motion::enum_type motion>
          static constexpr auto erase_display_v = detail::escape<erase_display, motion>;
          template<motion::enum_type motion>
          static constexpr auto erase_line_v = detail::escape<erase_line, motion>;
          // Scroll up/down
          template<unsigned cnt>
          static constexpr auto scroll_up_v = detail::escape<scroll_up, cnt>;
          template<unsigned cnt>
          static constexpr auto scroll_down_v = detail::escape<scroll_down, cnt>;
          // Set cursor to a specific position
          template<unsigned row, unsigned col>
          static constexpr auto cursor_position_v =
              detail::escape<cursor_position, row, col>;
          // Color
          template<auto... val>
          static constexpr std::string_view foreground_v;
          template<auto... val>
          static constexpr std::string_view background_v;
          template<color::enum_type color>
          static constexpr auto foreground_v<color> = detail::
              escape<static_cast<std::string (*)(color::enum_type)>(foreground), color>;
          template<color::enum_type color>
          static constexpr auto background_v<color> = detail::
              escape<static_cast<std::string (*)(color::enum_type)>(background), color>;
          template<based::bu8 idx>
          static constexpr auto foreground_v<idx> =
              detail::escape<static_cast<std::string (*)(based::bu8)>(foreground), idx>;
          template<based::bu8 idx>
          static constexpr auto background_v<idx> =
              detail::escape<static_cast<std::string (*)(based::bu8)>(background), idx>;
          template<based::bu8 red, based::bu8 green, based::bu8 blue>
          static constexpr auto foreground_v<red, green, blue> = detail::escape<
              static_cast<std::string (*)(based::bu8, based::bu8, based::bu8)>(foreground
              ),
              red,
              green,
              blue>;
          template<based::bu8 red, based::bu8 green, based::bu8 blue>
          static constexpr auto background_v<red, green, blue> = detail::escape<
              static_cast<std::string (*)(based::bu8, based::bu8, based::bu8)>(background
              ),
              red,
              green,
              blue>;
          // Set/reset text decorators
          template<decor::enum_type decor>
          static constexpr auto decor_set_v = detail::escape<decor_set, decor>;
          template<decor::enum_type decor>
          static constexpr auto decor_reset_v = detail::escape<decor_reset, decor>;
          // Set screen modes
          template<unsigned mode>
          static constexpr auto screen_mode_set_v = detail::escape<screen_mode_set, mode>;
          template<unsigned mode>
          static constexpr auto screen_mode_reset_v =
              detail::escape<screen_mode_reset, mode>;
          }  // namespace alec