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

commit 001f8a3880c44976a8d7605a4bab4dcd5e0e106b
parent 25a60ee9a228faff7f1aa38a5821f6e6db46541b
author Dimitrije Dobrota < mail@dimitrijedobrota.com >
date Sun, 25 Feb 2024 23:49:10 +0000

Add run-time version of all functions

* Extraction of logic
* New demo program, currently just the copy of the previous one

Diffstat:
M CMakeLists.txt | + -
M demo/CMakeLists.txt | +++++++++
A demo/demo_runtime.cpp | ++++++++++++++++++++++++++++
M src/alec.hpp | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ---

4 files changed, 183 insertions(+), 5 deletions(-)


diff --git a/ CMakeLists.txt b/ CMakeLists.txt

@@ -3,7 +3,7 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON)


project(
Alec
VERSION 0.0.7
VERSION 0.0.8
DESCRIPTION "Abstraction Layer for Escape Codes"
HOMEPAGE_URL https://git.dimitrijedobrota.com/alec.git
LANGUAGES CXX

diff --git a/ demo/CMakeLists.txt b/ demo/CMakeLists.txt

@@ -6,3 +6,12 @@ set_target_properties(demo PROPERTIES

SOVERSION ${PROJECT_VERSION_MAJOR}
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin"
)

add_executable(demo_runtime demo_runtime.cpp)
target_link_libraries(demo_runtime alec)

set_target_properties(demo_runtime PROPERTIES
VERSION ${PROJECT_VERSION}
SOVERSION ${PROJECT_VERSION_MAJOR}
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin"
)

diff --git a/ demo/demo_runtime.cpp b/ demo/demo_runtime.cpp

@@ -0,0 +1,28 @@

#include "alec.hpp"
#include <iostream>

using namespace ALEC;
using enum COLOR;
using enum DECOR;

int main(void) {
std::cout << abuf_show() << cursor_hide();

std::cout << cursor_position(1, 1) << foreground(91) << "HELLO!\n";

std::cout << cursor_down(3);
std::cout << foreground(30) << background(196, 53, 64) << "WORLD!\n";

std::cout << background(DEFAULT) << "testing 1...\n" << foreground(DEFAULT);
std::cout << decor_set(INVERSE) << "testing 2...\n" << decor_reset(INVERSE);

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 << abuf_hide();

return 0;
}

diff --git a/ src/alec.hpp b/ src/alec.hpp

@@ -3,9 +3,10 @@


#include <algorithm>
#include <array>
#include <assert.h>
#include <cstdint>
#include <string>
#include <type_traits>

namespace ALEC {

enum CTRL {

@@ -59,7 +60,7 @@ template <std::size_t N> struct string_literal {

char value[N];
};

template <auto... Args> struct escape_t {
struct helper {
template <typename T> static consteval std::size_t size(T val);
template <typename T> static constexpr char *append(char *ptr, T val);

@@ -90,10 +91,22 @@ template <auto... Args> struct escape_t {

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 = (size(Args) + ... + 2);
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 = append(ptr, s); };
auto map = [ptr = arr.data() + 2](auto const &s) mutable { ptr = helper::append(ptr, s); };
(map(Args), ...);
arr[len] = 0;
return arr;

@@ -113,6 +126,8 @@ concept limit_256 = n >= 0 && n < 256;

template <int n>
concept limit_pos = n >= 0;

/* Template compile-time variables */

// Move cursor up/down/frwd/back
template <int n>
requires limit_pos<n>

@@ -222,6 +237,132 @@ static constexpr auto cursor_hide_v = details::escape_literal<"?25l">;

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(n >= 0);
return details::helper::make(n, 'A');
}

static constexpr auto cursor_down(int n) {
assert(n >= 0);
return details::helper::make(n, 'B');
}

static constexpr auto cursor_frwd(int n) {
assert(n >= 0);
return details::helper::make(n, 'C');
}

static constexpr auto cursor_back(int n) {
assert(n >= 0);
return details::helper::make(n, 'D');
}

// Move cursor to the next/prev line
static constexpr auto cursor_line_next(int n) {
assert(n >= 0);
return details::helper::make(n, 'E');
}

static constexpr auto cursor_line_prev(int n) {
assert(n >= 0);
return details::helper::make(n, 'F');
}

// Set cursor to specific column
static constexpr auto cursor_column(int n) {
assert(n >= 0);
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), 'J'); }

// Scroll up/down
static constexpr auto scroll_up(int n) {
assert(n >= 0);
return details::helper::make(n, 'S');
}

static constexpr auto scroll_down(int n) {
assert(n >= 0);
return details::helper::make(n, 'T');
}

// Set cursor to a specific position
static constexpr auto cursor_position(int n, int m) {
assert(n >= 0 && m >= 0);
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(n >= 0 && n < 256);
return details::helper::make(38, ';', 5, ';', idx, 'm');
}

static constexpr auto background(int idx) {
assert(n >= 0 && n < 256);
return details::helper::make(48, ';', 5, ';', idx, 'm');
}

// RGB colors
static constexpr auto foreground(int R, int G, int B) {
assert(R >= 0 && R < 256);
assert(G >= 0 && G < 256);
assert(B >= 0 && B < 256);
return details::helper::make(38, ';', 5, ';', R, ';', G, ';', B, 'm');
}

static constexpr auto background(int R, int G, int B) {
assert(R >= 0 && R < 256);
assert(G >= 0 && G < 256);
assert(B >= 0 && B < 256);
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(n >= 0);
return details::helper::make('=', n, 'h');
}

static constexpr auto screen_mode_reset(int n) {
assert(n >= 0);
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