alec

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

commitd0bd51c29c05b227b28d71c59c6caf7f9742df8d
parent9dc03661ab1baccce726bd37b704d7ae34a4caa5
authorDimitrije Dobrota <mail@dimitrijedobrota.com>
dateTue, 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|+-
Msrc/CMakeLists.txt|++++++++++++++++++----
Dsrc/alec.hpp|---------------------------------------------------------------------------------
Asrc/alec.rules.hpp|+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/lexer.l|+++++++++++++++++------
Msrc/parser.y|+++++++++++++++++++++++++++++++++------------
Dsrc/rules|---------------------------------------------------------------------------------

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"