aboutsummaryrefslogtreecommitdiff
path: root/modules/TUI
diff options
context:
space:
mode:
authordam <dam@gudinoff>2024-05-05 00:31:46 +0100
committerdam <dam@gudinoff>2024-05-05 00:31:46 +0100
commitcb6c3caaa285bc8bd12c356d57bbfad86d70c0eb (patch)
treebeb732467422fea0edc55b1dd4069f06f632167a /modules/TUI
parentb87e4a141da53cf903a0ab9fc9eb693c85a5c0b4 (diff)
downloadtask-time-tracker-cb6c3caaa285bc8bd12c356d57bbfad86d70c0eb.tar.zst
task-time-tracker-cb6c3caaa285bc8bd12c356d57bbfad86d70c0eb.zip
WIP : Cleanup TUI module scope.
Diffstat (limited to 'modules/TUI')
-rw-r--r--modules/TUI/module.jai222
-rw-r--r--modules/TUI/palette_24b.jai6
2 files changed, 123 insertions, 105 deletions
diff --git a/modules/TUI/module.jai b/modules/TUI/module.jai
index 772b30c..ab2567d 100644
--- a/modules/TUI/module.jai
+++ b/modules/TUI/module.jai
@@ -1,7 +1,9 @@
#module_parameters(COLOR_MODE_BITS := 24);
+
#scope_file
+
#if OS == {
case .LINUX;
#load "unix.jai";
@@ -26,8 +28,27 @@ KEY_SIZE :: #run type_info(Key).runtime_size;
assert(input_buffer.count >= KEY_SIZE, "The input buffer size must be capable to hold an entire Key, which should be able to hold an UTF8 code (4 bytes) or a terminal escape code (6 bytes).");
}
+active := false;
+input_buffer : [1024] u8;
+input_string : string;
+input_override : Key;
+
+previous_logger : (message: string, data: *void, info: Log_Info);
+
+module_logger :: (message: string, data: *void, info: Log_Info) {
+ write_strings(Commands.SaveCursorPosition, Commands.MainScreenBuffer);
+ previous_logger(message, data, info);
+ write_strings(Commands.AlternateScreenBuffer, Commands.RestoreCursorPosition);
+}
+
+assert_is_active :: inline () {
+ assert(active, "Please call setup_terminal() to start using this module.");
+}
+
+
#scope_export;
+
// Special Graphics Characters.
Drawings :: struct #type_info_none {
Blank :: "\x5F";
@@ -123,6 +144,12 @@ Commands :: struct #type_info_none {
// TODO Check which procedures need the assert_is_active call.
// TODO Review the error messages on the asserts.
+////////////////////////////////////////////////////////////////////////////////
+
+
+#scope_file
+
+
#if COLOR_MODE_BITS == 4 {
#load "palette_4b.jai";
@@ -144,12 +171,6 @@ else #if COLOR_MODE_BITS == 8 {
else {
#load "palette_24b.jai";
- Color_24b :: struct {
- r: u8;
- g: u8;
- b: u8;
- }
-
set_colors :: inline (foreground: Color_24b, background: Color_24b) {
print(
#run sprint(Commands.SetGraphicsRendition, "38;2;%;%;%;48;2;%;%;%"),
@@ -158,6 +179,19 @@ else {
}
}
+set_font_style :: inline (bold: bool, underline: bool = false, strike_through: bool = false, negative: bool = false) {
+ print(
+ #run sprint(Commands.SetGraphicsRendition, "%;%;%;%"),
+ ifx bold then 1 else 22,
+ ifx underline then 4 else 24,
+ ifx strike_through then 9 else 29,
+ ifx negative then 7 else 27);
+}
+
+
+#scope_export
+
+
Style :: struct {
#if COLOR_MODE_BITS == 4 || COLOR_MODE_BITS == 8 {
background: Palette;
@@ -180,16 +214,9 @@ Style :: struct {
negative: bool;
}
-set_font_style :: inline (bold: bool, underline: bool = false, strike_through: bool = false, negative: bool = false) {
- print(
- #run sprint(Commands.SetGraphicsRendition, "%;%;%;%"),
- ifx bold then 1 else 22,
- ifx underline then 4 else 24,
- ifx strike_through then 9 else 29,
- ifx negative then 7 else 27);
-}
+#add_context terminal_style: Style;
-set_style :: (style: Style) {
+set_style :: inline (style: Style) {
set_font_style(style.bold, style.underline, style.strike_through, style.negative);
set_colors(style.foreground, style.background);
context.terminal_style = style;
@@ -205,6 +232,9 @@ using_style :: (style: Style) #expand {
`defer set_style(__style);
}
+
+////////////////////////////////////////////////////////////////////////////////
+
/*
We wanted the Key type to represent either UTF-8 encoded characters and also keyboard keys.
The UTF-8 only requires up to 4 bytes, but some keyboard keys return up to 6 bytes.
@@ -216,34 +246,7 @@ using_style :: (style: Style) #expand {
key/u64 |0|0|c|b|a| -> that in memory lays as (BE:|0|0|c|b|a|) and (LE:|a|b|c|0|0|)
*/
-Key :: u64; // Terminal key-codes have 1 to 6 bytes so we'll use 8 bytes.
-
-to_key :: (str: $T) -> Key #modify { return T == ([]u8) || T == string; } {
- assert(str.count <= KEY_SIZE, "Invalid argument passed to to_key(): 'str.count' must be less-than or equal to %, but it was %.", KEY_SIZE, str.count);
-
- k: Key;
- for 0..str.count-1 {
- k |= ((cast(u64)str[it]) << (it*8));
- }
- return k;
-}
-
-to_string :: (key: Key) -> string {
- str := alloc_string(KEY_SIZE);
- str.count = 0;
- while key != 0 {
- str.count += 1;
- str[str.count-1] = xx key & 0xFF;
- key >>= 8;
- }
- return str;
-}
-
-is_escape_code :: (key: Key) -> bool {
- beginsWithEscape := ((key & 0xFF) ^ #char "#") == 0;
- hasSomethingElse := (key & (~0xFF)) != 0;
- return beginsWithEscape && hasSomethingElse;
-}
+Key :: u64;
Keys :: struct #type_info_none {
None : Key : #run to_key("#none");
@@ -282,29 +285,86 @@ Keys :: struct #type_info_none {
F12 : Key : #run to_key("#f12");
}
-#add_context terminal_style: Style;
+to_key :: (str: $T) -> Key #modify { return T == ([]u8) || T == string; } {
+ assert(str.count <= KEY_SIZE, "Invalid argument passed to to_key(): 'str.count' must be less-than or equal to %, but it was %.", KEY_SIZE, str.count);
+
+ k: Key;
+ for 0..str.count-1 {
+ k |= ((cast(u64)str[it]) << (it*8));
+ }
+ return k;
+}
-active := false;
+to_string :: (key: Key) -> string {
+ str := alloc_string(KEY_SIZE);
+ str.count = 0;
+ while key != 0 {
+ str.count += 1;
+ str[str.count-1] = xx key & 0xFF;
+ key >>= 8;
+ }
+ return str;
+}
-input_buffer : [1024] u8;
-input_string : string;
-input_override : Key;
+is_escape_code :: (key: Key) -> bool {
+ beginsWithEscape := ((key & 0xFF) ^ #char "#") == 0;
+ hasSomethingElse := (key & (~0xFF)) != 0;
+ return beginsWithEscape && hasSomethingElse;
+}
-previous_logger : (message: string, data: *void, info: Log_Info);
+////////////////////////////////////////////////////////////////////////////////
-module_logger :: (message: string, data: *void, info: Log_Info) {
- write_strings(Commands.SaveCursorPosition, Commands.MainScreenBuffer);
- previous_logger(message, data, info);
- write_strings(Commands.AlternateScreenBuffer, Commands.RestoreCursorPosition);
+is_active :: inline () -> bool {
+ return active;
}
-assert_is_active :: inline () {
- assert(active, "Please call setup_terminal() to start using this module.");
+setup_terminal :: () -> success := true #must {
+ if active == true return;
+
+ input_string.data = input_buffer.data;
+ input_string.count = 0;
+ input_override = xx Keys.None;
+
+ previous_logger = context.logger;
+ context.logger = module_logger;
+
+ setup_key_map();
+
+ write_strings(
+ Commands.HideCursor,
+ Commands.SaveCursorPosition,
+ Commands.AlternateScreenBuffer,
+ Commands.EncodingUTF8,
+ Commands.CursorNormalMode,
+ Commands.KeypadNumMode
+ );
+
+ if !OS_prepare_terminal() then return false;
+
+ active = true;
+
+ return;
}
-////////////////////////////////////////////////////////////////////////////////
+reset_terminal :: () -> success := true #must {
+ if active == false return;
+
+ active = false;
-// #scope_export TODO Setup the scope_export and scope_file
+ clear_style();
+
+ if !OS_reset_terminal() then return false;
+
+ context.logger = previous_logger;
+
+ write_strings(
+ Commands.MainScreenBuffer,
+ Commands.RestoreCursorPosition,
+ Commands.ShowCursor
+ );
+
+ return;
+}
set_next_key :: inline (key: Key) {
assert_is_active();
@@ -535,54 +595,6 @@ read_input_line :: (count_limit: int, is_visible: bool = true) -> string, Key {
return result, key;
}
-setup_terminal :: () -> success := true #must {
- if active == true return;
-
- input_string.data = input_buffer.data;
- input_string.count = 0;
- input_override = xx Keys.None;
-
- previous_logger = context.logger;
- context.logger = module_logger;
-
- setup_key_map();
-
- write_strings(
- Commands.HideCursor,
- Commands.SaveCursorPosition,
- Commands.AlternateScreenBuffer,
- Commands.EncodingUTF8,
- Commands.CursorNormalMode,
- Commands.KeypadNumMode
- );
-
- if !OS_prepare_terminal() then return false;
-
- active = true;
-
- return;
-}
-
-reset_terminal :: () -> success := true #must {
- if active == false return;
-
- active = false;
-
- clear_style();
-
- if !OS_reset_terminal() then return false;
-
- context.logger = previous_logger;
-
- write_strings(
- Commands.MainScreenBuffer,
- Commands.RestoreCursorPosition,
- Commands.ShowCursor
- );
-
- return;
-}
-
flush_input :: () {
assert_is_active();
OS_flush_input();
diff --git a/modules/TUI/palette_24b.jai b/modules/TUI/palette_24b.jai
index ea0191c..7545a0b 100644
--- a/modules/TUI/palette_24b.jai
+++ b/modules/TUI/palette_24b.jai
@@ -1,4 +1,10 @@
// https://www.ditig.com/publications/256-colors-cheat-sheet
+Color_24b :: struct {
+ r: u8;
+ g: u8;
+ b: u8;
+}
+
Palette :: struct #type_info_none {
BLACK :: Color_24b.{0x00, 0x00, 0x00};
MAROON :: Color_24b.{0x80, 0x00, 0x00};