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 | 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