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