alec

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

commit d0bd51c29c05b227b28d71c59c6caf7f9742df8d
parent 9dc03661ab1baccce726bd37b704d7ae34a4caa5
Author: Dimitrije Dobrota <mail@dimitrijedobrota.com>
Date:   Tue, 27 Feb 2024 22:58:45 +0000

Code generation works!!!

* devide document into 3 sections with %%, same as with flex and bison
    ~ first section is copied over, as is, before the generated code
    ~ second section contains the rules for generating
    ~ third section is copied over, as is, after the generated code
* Configure cmake to generate alec.hpp

Diffstat:
MCMakeLists.txt | 2+-
Msrc/CMakeLists.txt | 22++++++++++++++++++----
Dsrc/alec.hpp | 374-------------------------------------------------------------------------------
Asrc/alec.rules.hpp | 325+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/lexer.l | 23+++++++++++++++++------
Msrc/parser.y | 45+++++++++++++++++++++++++++++++++------------
Dsrc/rules | 183-------------------------------------------------------------------------------
7 files changed, 394 insertions(+), 580 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt @@ -3,7 +3,7 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON) project( Alec - VERSION 0.0.10 + VERSION 0.0.11 DESCRIPTION "Abstraction Layer for Escape Codes" HOMEPAGE_URL https://git.dimitrijedobrota.com/alec.git LANGUAGES C CXX diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt @@ -17,19 +17,33 @@ ADD_FLEX_BISON_DEPENDENCY(LEXER PARSER) add_executable(generator "${LEXER_OUT}" "${PARSER_OUT}") target_include_directories(generator PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_BINARY_DIR}") +set(GENERATE_OUT "${CMAKE_BINARY_DIR}/bin") + set_target_properties(generator PROPERTIES VERSION ${PROJECT_VERSION} SOVERSION ${PROJECT_VERSION_MAJOR} - RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin" + RUNTIME_OUTPUT_DIRECTORY "${GENERATE_OUT}" +) + +set(RULES_NAME "alec.rules.hpp") +set(RULES_FILE "${CMAKE_BINARY_DIR}/${RULES_NAME}") + +configure_file(alec.rules.hpp ${RULES_FILE} COPYONLY) + +add_custom_command( + OUTPUT ${GENERATE_OUT}/alec.hpp + COMMAND generator ${RULES_FILE} > ${GENERATE_OUT}/alec.hpp + DEPENDS generator ${RULES_NAME} + COMMENT "Generating include file" ) -add_library(alec INTERFACE) -target_include_directories(alec INTERFACE .) +add_library(alec INTERFACE ${GENERATE_OUT}/alec.hpp) +target_include_directories(alec INTERFACE ${GENERATE_OUT}) set_target_properties(alec PROPERTIES VERSION ${PROJECT_VERSION} SOVERSION ${PROJECT_VERSION_MAJOR} - PUBLIC_HEADER alec.hpp + PUBLIC_HEADER ${GENERATE_OUT}/alec.hpp ) install(TARGETS alec diff --git a/src/alec.hpp b/src/alec.hpp @@ -1,374 +0,0 @@ -#ifndef ALEC_ALEC_H -#define ALEC_ALEC_H - -#include <algorithm> -#include <array> -#include <assert.h> -#include <cstdint> -#include <string> -#include <type_traits> -namespace ALEC { - -enum CTRL { - BELL = 0x07, - BS = 0x08, - HT = 0x09, - LF = 0x0A, - VT = 0x0B, - FF = 0x0C, - CR = 0x0D, - ESC = 0x1B, - DEL = 0x7F, -}; - -enum class COLOR { - BLACK = 0, - RED = 1, - GREEN = 2, - YELLOW = 3, - BLUE = 4, - MAGENTA = 5, - CYAN = 6, - WHITE = 7, - DEFAULT = 9, -}; - -enum class DECOR { - RESET = 0, - BOLD = 1, - DIM = 2, - ITALIC = 3, - UNDERLINE = 4, - BLINK = 5, - INVERSE = 7, - HIDE = 8, - STRIKE = 9, -}; - -enum class MOTION { - END = 0, - BEGIN = 1, - WHOLE = 2, -}; - -namespace details { - -template <std::size_t N> struct string_literal { - consteval string_literal(const char (&str)[N]) { std::copy_n(str, N, value); } - consteval std::size_t size() const { return N; } - - char value[N]; -}; - -struct helper { - template <typename T> static consteval std::size_t size(T val); - template <typename T> static constexpr char *append(char *ptr, T val); - - template <std::size_t N> static constexpr std::size_t size(string_literal<N> val) { return val.size(); } - static constexpr std::size_t size(char val) { return 1; } - static constexpr std::size_t size(int val) { - std::size_t len = 1; - while (val /= 10) - len++; - return len; - } - - template <std::size_t N> static constexpr char *append(char *ptr, string_literal<N> val) { - std::copy_n(val.value, N, ptr); - return ptr + N; - } - - static constexpr char *append(char *ptr, char val) { - *ptr++ = val; - return ptr; - } - - static constexpr char *append(char *ptr, int val) { - char *tmp = ptr += size(val); - do { - *--tmp = '0' + (val % 10); - } while (val /= 10); - return ptr; - } - - static const std::string make(auto... args) { - std::size_t len = (helper::size(args) + ... + 2); - std::string res(len, 'a'); - res[0] = CTRL::ESC, res[1] = '['; - auto map = [ptr = res.data() + 2](auto const &s) mutable { ptr = helper::append(ptr, s); }; - (map(args), ...); - res[len] = 0; - return res; - } -}; - -template <auto... Args> struct escape_t { - static constexpr const auto value = []() { - constexpr std::size_t len = (helper::size(Args) + ... + 2); - std::array<char, len + 1> arr{CTRL::ESC, '[', 0}; - auto map = [ptr = arr.data() + 2](auto const &s) mutable { ptr = helper::append(ptr, s); }; - (map(Args), ...); - arr[len] = 0; - return arr; - }(); -}; - -template <auto... Strs> static constexpr auto escape = escape_t<Strs...>::value.data(); -template <details::string_literal... Strs> static constexpr auto escape_literal = escape<Strs...>; - -} // namespace details - -// Tamplate parameter constraints - -template <int n> -concept limit_256_v = n >= 0 && n < 256; - -template <int n> -concept limit_pos_v = n >= 0; - -static inline bool limit_pos(int n) { return n >= 0; }; -static inline bool limit_256(int n) { return n >= 0 && n < 256; }; - -/* Template compile-time variables */ - -// Move cursor up/down/frwd/back -template <int n> - requires limit_pos_v<n> -static constexpr auto cursor_up_v = details::escape<n, 'A'>; - -template <int n> - requires limit_pos_v<n> -static constexpr auto cursor_down_v = details::escape<n, 'B'>; - -template <int n> - requires limit_pos_v<n> -static constexpr auto cursor_frwd_v = details::escape<n, 'C'>; - -template <int n> - requires limit_pos_v<n> -static constexpr auto cursor_back_v = details::escape<n, 'D'>; - -// Move cursor to the next/prev line -template <int n> - requires limit_pos_v<n> -static constexpr auto cursor_line_next_v = details::escape<n, 'E'>; - -template <int n> - requires limit_pos_v<n> -static constexpr auto cursor_line_prev_v = details::escape<n, 'F'>; - -// Set cursor to specific column -template <int n> - requires limit_pos_v<n> -static constexpr auto cursor_column_v = details::escape<n, 'G'>; - -// Erase functions -template <MOTION m> static constexpr auto erase_display_v = details::escape<(int)m, 'J'>; -template <MOTION m> static constexpr auto erase_line_v = details::escape<(int)m, 'K'>; - -// Scroll up/down -template <int n> - requires limit_pos_v<n> -static constexpr auto scroll_up_v = details::escape<n, 'S'>; - -template <int n> - requires limit_pos_v<n> -static constexpr auto scroll_down_v = details::escape<n, 'T'>; - -// Set cursor to a specific position -template <int n, int m> - requires limit_pos_v<n> && limit_pos_v<m> -static constexpr auto cursor_position_v = details::escape<n, ';', m, 'H'>; - -// color -template <auto... val> static const char *foreground_v; -template <auto... val> static const char *background_v; - -// palet colors -template <COLOR color> static constexpr auto foreground_v<color> = details::escape<(int)color + 30, 'm'>; -template <COLOR color> static constexpr auto background_v<color> = details::escape<(int)color + 40, 'm'>; - -// 256-color palette -template <int idx> - requires limit_256_v<idx> -static constexpr auto foreground_v<idx> = details::escape<38, ';', 5, ';', idx, 'm'>; - -template <int idx> - requires limit_256_v<idx> -static constexpr auto background_v<idx> = details::escape<48, ';', 5, ';', idx, 'm'>; - -// RGB colors -template <int R, int G, int B> - requires limit_256_v<R> && limit_256_v<G> && limit_256_v<B> -static constexpr auto foreground_v<R, G, B> = - details::escape<38, ';', 5, ';', R, ';', G, ';', B, 'm'>; - -template <int R, int G, int B> - requires limit_256_v<R> && limit_256_v<G> && limit_256_v<B> -static constexpr auto background_v<R, G, B> = - details::escape<48, ';', 5, ';', R, ';', G, ';', B, 'm'>; - -// Set/reset text decorators -template <DECOR decor> static constexpr auto decor_set_v = details::escape<(int)decor, 'm'>; -template <DECOR decor> static constexpr auto decor_reset_v = details::escape<(int)decor + 20, 'm'>; - -// Save/load cursor position; -static constexpr auto cursor_save_v = details::escape<'s'>; -static constexpr auto cursor_load_v = details::escape<'u'>; - -// Set screen modes - -template <int n> - requires limit_pos_v<n> -static constexpr auto screen_mode_set_v = details::escape<'=', n, 'h'>; - -template <int n> - requires limit_pos_v<n> -static constexpr auto screen_mode_reset_v = details::escape<'=', n, 'l'>; - -// Private screen modes supported by most terminals - -// Save/load screen -static constexpr auto screen_show_v = details::escape_literal<"?47h">; -static constexpr auto screen_hide_v = details::escape_literal<"?47l">; - -// Show/hide cursor -static constexpr auto cursor_show_v = details::escape_literal<"?25h">; -static constexpr auto cursor_hide_v = details::escape_literal<"?25l">; - -// Show/hide alternate buffer -static constexpr auto abuf_show_v = details::escape_literal<"?1049h">; -static constexpr auto abuf_hide_v = details::escape_literal<"?1049l">; - -/* Run-time functions */ - -// Move cursor up/down/frwd/back -static constexpr auto cursor_up(int n) { - assert(limit_pos(n)); - return details::helper::make(n, 'A'); -} - -static constexpr auto cursor_down(int n) { - assert(limit_pos(n)); - return details::helper::make(n, 'B'); -} - -static constexpr auto cursor_frwd(int n) { - assert(limit_pos(n)); - return details::helper::make(n, 'C'); -} - -static constexpr auto cursor_back(int n) { - assert(limit_pos(n)); - return details::helper::make(n, 'D'); -} - -// Move cursor to the next/prev line -static constexpr auto cursor_line_next(int n) { - assert(limit_pos(n)); - return details::helper::make(n, 'E'); -} - -static constexpr auto cursor_line_prev(int n) { - assert(limit_pos(n)); - return details::helper::make(n, 'F'); -} - -// Set cursor to specific column -static constexpr auto cursor_column(int n) { - assert(limit_pos(n)); - return details::helper::make(n, 'G'); -} - -// Erase functions -static constexpr auto erase_display(MOTION m) { return details::helper::make((int)m, 'J'); } -static constexpr auto erase_line(MOTION m) { return details::helper::make((int)m, 'K'); } - -// Scroll up/down -static constexpr auto scroll_up(int n) { - assert(limit_pos(n)); - return details::helper::make(n, 'S'); -} - -static constexpr auto scroll_down(int n) { - assert(limit_pos(n)); - return details::helper::make(n, 'T'); -} - -// Set cursor to a specific position -static constexpr auto cursor_position(int n, int m) { - assert(limit_pos(n)); - assert(limit_pos(m)); - return details::helper::make(n, ';', m, 'H'); -} - -// color - -// palet colors -static constexpr auto foreground(COLOR color) { return details::helper::make((int)color + 30, 'm'); } -static constexpr auto background(COLOR color) { return details::helper::make((int)color + 40, 'm'); } - -// 256-color palette -static constexpr auto foreground(int idx) { - assert(limit_256(idx)); - return details::helper::make(38, ';', 5, ';', idx, 'm'); -} - -static constexpr auto background(int idx) { - assert(limit_256(idx)); - return details::helper::make(48, ';', 5, ';', idx, 'm'); -} - -// RGB colors -static constexpr auto foreground(int R, int G, int B) { - assert(limit_256(R)); - assert(limit_256(G)); - assert(limit_256(B)); - return details::helper::make(38, ';', 5, ';', R, ';', G, ';', B, 'm'); -} - -static constexpr auto background(int R, int G, int B) { - assert(limit_256(R)); - assert(limit_256(G)); - assert(limit_256(B)); - return details::helper::make(48, ';', 5, ';', R, ';', G, ';', B, 'm'); -} - -// Set/reset text decorators -static constexpr auto decor_set(DECOR decor) { return details::helper::make((int)decor, 'm'); } -static constexpr auto decor_reset(DECOR decor) { return details::helper::make((int)decor + 20, 'm'); } - -// Save/load cursor position; -static constexpr auto cursor_save() { return cursor_save_v; } -static constexpr auto cursor_load() { return cursor_load_v; } - -// Set screen modes -static constexpr auto screen_mode_set(int n) { - assert(limit_pos(n)); - return details::helper::make('=', n, 'h'); -} - -static constexpr auto screen_mode_reset(int n) { - assert(limit_pos(n)); - return details::helper::make('=', n, 'l'); -} - -// Private screen modes supported by most terminals - -// Save/load screen -static constexpr auto screen_show() { return screen_show_v; } -static constexpr auto screen_hide() { return screen_hide_v; } - -// Show/hide cursor -static constexpr auto cursor_show() { return cursor_show_v; } -static constexpr auto cursor_hide() { return cursor_hide_v; } - -// Show/hide alternate buffer -static constexpr auto abuf_show() { return abuf_show_v; } -static constexpr auto abuf_hide() { return abuf_hide_v; } - -// Keyboard string TODO - -} // namespace ALEC - -#endif diff --git a/src/alec.rules.hpp b/src/alec.rules.hpp @@ -0,0 +1,325 @@ +#ifndef ALEC_ALEC_H +#define ALEC_ALEC_H + +#include <algorithm> +#include <array> +#include <assert.h> +#include <cstdint> +#include <string> +#include <type_traits> +namespace ALEC { + +enum CTRL { + BELL = 0x07, + BS = 0x08, + HT = 0x09, + LF = 0x0A, + VT = 0x0B, + FF = 0x0C, + CR = 0x0D, + ESC = 0x1B, + DEL = 0x7F, +}; + +enum class COLOR { + BLACK = 0, + RED = 1, + GREEN = 2, + YELLOW = 3, + BLUE = 4, + MAGENTA = 5, + CYAN = 6, + WHITE = 7, + DEFAULT = 9, +}; + +enum class DECOR { + RESET = 0, + BOLD = 1, + DIM = 2, + ITALIC = 3, + UNDERLINE = 4, + BLINK = 5, + INVERSE = 7, + HIDE = 8, + STRIKE = 9, +}; + +enum class MOTION { + END = 0, + BEGIN = 1, + WHOLE = 2, +}; + +namespace details { + +template <std::size_t N> struct string_literal { + consteval string_literal(const char (&str)[N]) { std::copy_n(str, N, value); } + consteval std::size_t size() const { return N; } + + char value[N]; +}; + +struct helper { + template <typename T> static consteval std::size_t size(T val); + template <typename T> static constexpr char *append(char *ptr, T val); + + template <std::size_t N> static constexpr std::size_t size(string_literal<N> val) { return val.size(); } + static constexpr std::size_t size(char val) { return 1; } + static constexpr std::size_t size(int val) { + std::size_t len = 1; + while (val /= 10) + len++; + return len; + } + + template <std::size_t N> static constexpr char *append(char *ptr, string_literal<N> val) { + std::copy_n(val.value, N, ptr); + return ptr + N; + } + + static constexpr char *append(char *ptr, char val) { + *ptr++ = val; + return ptr; + } + + static constexpr char *append(char *ptr, int val) { + char *tmp = ptr += size(val); + do { + *--tmp = '0' + (val % 10); + } while (val /= 10); + return ptr; + } + + static const std::string make(auto... args) { + std::size_t len = (helper::size(args) + ... + 2); + std::string res(len, 'a'); + res[0] = CTRL::ESC, res[1] = '['; + auto map = [ptr = res.data() + 2](auto const &s) mutable { ptr = helper::append(ptr, s); }; + (map(args), ...); + res[len] = 0; + return res; + } +}; + +template <auto... Args> struct escape_t { + static constexpr const auto value = []() { + constexpr std::size_t len = (helper::size(Args) + ... + 2); + std::array<char, len + 1> arr{CTRL::ESC, '[', 0}; + auto map = [ptr = arr.data() + 2](auto const &s) mutable { ptr = helper::append(ptr, s); }; + (map(Args), ...); + arr[len] = 0; + return arr; + }(); +}; + +template <auto... Strs> static constexpr auto escape = escape_t<Strs...>::value.data(); +template <details::string_literal... Strs> static constexpr auto escape_literal = escape<Strs...>; + +} // namespace details + +// Tamplate parameter constraints + +template <int n> +concept limit_256_v = n >= 0 && n < 256; + +template <int n> +concept limit_pos_v = n >= 0; + +static inline bool limit_pos(int n) { return n >= 0; }; +static inline bool limit_256(int n) { return n >= 0 && n < 256; }; + +%% + +// Move cursor up/down/frwd/back + + cursor_up + int n + limit_pos + n, 'A' + + cursor_down + int n + limit_pos + n, 'B' + + cursor_frwd + int n + limit_pos + n, 'C' + + cursor_back + int n + limit_pos + n, 'D' + +// Move cursor to the next/prev line + + cursor_line_next + int n + limit_pos + n, 'E' + + cursor_line_prev + int n + limit_pos + n, 'F' + +// Set cursor to specific column + + cursor_column + int n + limit_pos + n, 'G' + +// Erase functions + + erase_display + MOTION m + | + (int)m, 'J' + + erase_line + MOTION m + | + (int)m, 'K' + +// Scroll up/down + + scroll_up + int n + limit_pos + n, 'S' + + scroll_down + int n + limit_pos + n, 'T' + +// Set cursor to a specific position + + cursor_position + int n, int m + limit_pos + n, ';', m, 'H' + +// color + +// palet colors + + foreground + COLOR color + | + (int)color + 30, 'm' + + background + COLOR color + | + (int)color + 40, 'm' + +// 256-color palette + + foreground + int idx + limit_256 + 38, ';', 5, ';', idx, 'm' + + background + int idx + limit_256 + 48, ';', 5, ';', idx, 'm' + +// RGB colors + + foreground + int R, int G, int B + limit_256 + 38, ';', 5, ';', R, ';', G, ';', B, 'm' + + background + int R, int G, int B + limit_256 + 48, ';', 5, ';', R, ';', G, ';', B, 'm' + +// Set/reset text decorators + + decor_set + DECOR decor + | + (int)decor, 'm' + + decor_reset + DECOR decor + | + (int)decor + 20, 'm' + +// Save/load cursor position; + + cursor_save + | + | + 's' + + cursor_load + | + | + 'u' + +// Set screen modes + + screen_mode_set + int n + limit_pos + '=', n, 'h' + + screen_mode_reset + int n + limit_pos + '=', n, 'l' + +// Private screen modes supported by most terminals + +// Save/load screen + + screen_show + | + | + "?47h" + + screen_hide + | + | + "?47l" + +// Show/hide cursor + + cursor_show + | + | + "?25h" + + cursor_hide + | + | + "?25l" + +// Show/hide alternate buffer + + abuf_show + | + | + "?1049h" + + abuf_hide + | + | + "?1049l" + +%% + +// Keyboard string TODO + +} // namespace ALEC + + +#endif diff --git a/src/lexer.l b/src/lexer.l @@ -8,22 +8,33 @@ LINE_END (\n|\r|\r\n) +%x GEN +%x LAST + %% -{LINE_END} { return EOL; } -^[\t ]*{LINE_END} { return EOL; } -^[\t ]*\|*[\t ]*{LINE_END} { return EOL; } -^[\t ]*"//".* { yylval.n = strdup(yytext); return COMMENT; } +"%%"{LINE_END} { BEGIN GEN; return SWITCH; } +.*{LINE_END} { yylval.n = strdup(yytext); return BEFORE; } + +<GEN>{LINE_END} { return EOL; } +<GEN>^[\t ]*{LINE_END} { return EOL; } +<GEN>^[\t ]*\|*[\t ]*{LINE_END} { return EOL; } + +<GEN>^[\t ]*"//".* { yylval.n = strdup(yytext); return COMMENT; } -, { return COMMA; } +<GEN>, { return COMMA; } -[^,\n]* { +<GEN>[^,\n]* { char *p = yytext + strlen(yytext) - 1; while(isspace(*p)) *p-- = '\0'; while(*yytext && isspace(*yytext)) yytext++; yylval.n = strdup(yytext); return LITERAL; } +<GEN>"%%"{LINE_END} { BEGIN LAST; return SWITCH; } + +<LAST>.*{LINE_END} { yylval.n = strdup(yytext); return AFTER; } + %% diff --git a/src/parser.y b/src/parser.y @@ -7,7 +7,9 @@ void yyrestart(FILE *); int yylex_destroy(void); - struct list *records; + struct list *records = NULL; + struct list *before = NULL; + struct list *after = NULL; %} %union { @@ -16,8 +18,8 @@ char *n; } -%token <n> LITERAL COMMENT -%token EOL COMMA +%token <n> LITERAL COMMENT BEFORE AFTER +%token EOL COMMA SWITCH %type <r> record %type <l> list @@ -27,15 +29,23 @@ %% -document: %empty - | EOL document - | record document { records = list_new((char *)$1, records); } - | COMMENT document { - records = list_new((char *)record_new( - $1, NULL, NULL, NULL - ), records); - } - ; +document: before SWITCH mid SWITCH after + +before: %empty + | BEFORE before { before = list_new($1, before); } + +after: %empty + | AFTER after { after = list_new($1, after); } + +mid: %empty + | EOL mid + | record mid { records = list_new((char *)$1, records); } + | COMMENT mid { + records = list_new((char *)record_new( + $1, NULL, NULL, NULL + ), records); + } + ; record: name list list list { $$ = record_new($1, $2, $3, $4); } ; @@ -73,6 +83,12 @@ int main(const int argc, char *argv[]) { fclose(f); } + + // print before section + for(struct list *p = before; p; p = p->next) { + printf("%s", p->data); + } + struct list *dupes = record_dupes(records); record_print_dupes(dupes); @@ -88,6 +104,11 @@ int main(const int argc, char *argv[]) { record_print_function(r); } + // print after section + for(struct list *p = after; p; p = p->next) { + printf("%s", p->data); + } + list_free(records, record_free); list_free(dupes, 0); diff --git a/src/rules b/src/rules @@ -1,183 +0,0 @@ -// Move cursor up/down/frwd/back - - cursor_up - int n - limit_pos - n, 'A' - - cursor_down - int n - limit_pos - n, 'B' - - cursor_frwd - int n - limit_pos - n, 'C' - - cursor_back - int n - limit_pos - n, 'D' - -// Move cursor to the next/prev line - - cursor_line_next - int n - limit_pos - n, 'E' - - cursor_line_prev - int n - limit_pos - n, 'F' - -// Set cursor to specific column - - cursor_column - int n - limit_pos - n, 'G' - -// Erase functions - - erase_display - MOTION m - | - (int)m, 'J' - - erase_line - MOTION m - | - (int)m, 'K' - -// Scroll up/down - - scroll_up - int n - limit_pos - n, 'S' - - scroll_down - int n - limit_pos - n, 'T' - -// Set cursor to a specific position - - cursor_position - int n, int m - limit_pos - n, ';', m, 'H' - -// color - -// palet colors - - foreground - COLOR color - | - (int)color + 30, 'm' - - background - COLOR color - | - (int)color + 40, 'm' - -// 256-color palette - - foreground - int idx - limit_256 - 38, ';', 5, ';', idx, 'm' - - background - int idx - limit_256 - 48, ';', 5, ';', idx, 'm' - -// RGB colors - - foreground - int R, int G, int B - limit_256 - 38, ';', 5, ';', R, ';', G, ';', B, 'm' - - background - int R, int G, int B - limit_256 - 48, ';', 5, ';', R, ';', G, ';', B, 'm' - -// Set/reset text decorators - - decor_set - DECOR decor - | - (int)decor, 'm' - - decor_reset - DECOR decor - | - (int)decor + 20, 'm' - -// Save/load cursor position; - - cursor_save - | - | - 's' - - cursor_load - | - | - 'u' - -// Set screen modes - - screen_mode_set - int n - limit_pos - '=', n, 'h' - - screen_mode_reset - int n - limit_pos - '=', n, 'l' - -// Private screen modes supported by most terminals - -// Save/load screen - - screen_show - | - | - "?47h" - - screen_hide - | - | - "?47l" - -// Show/hide cursor - - cursor_show - | - | - "?25h" - - cursor_hide - | - | - "?25l" - -// Show/hide alternate buffer - - abuf_show - | - | - "?1049h" - - abuf_hide - | - | - "?1049l"