aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordam <dam@gudinoff>2024-01-01 18:42:24 +0000
committerdam <dam@gudinoff>2024-01-01 18:42:24 +0000
commit6dd12d2c8b81cd5719fb0ecdcbf678e08460fbeb (patch)
tree1112631efd1cd0c87d5da755d575fb65fb16e5f8
parent2a20d715b56cf60f090b856ba6f1c98a3c87fe9f (diff)
downloadtask-time-tracker-6dd12d2c8b81cd5719fb0ecdcbf678e08460fbeb.tar.zst
task-time-tracker-6dd12d2c8b81cd5719fb0ecdcbf678e08460fbeb.zip
Fixed bug that was clamping terminal sequences to 6 bytes. Added style formatting.
-rw-r--r--TUI/module.jai269
-rw-r--r--ttt.jai47
2 files changed, 266 insertions, 50 deletions
diff --git a/TUI/module.jai b/TUI/module.jai
index 37c0f31..95ab8dc 100644
--- a/TUI/module.jai
+++ b/TUI/module.jai
@@ -50,18 +50,17 @@ Commands :: struct {
TextMode :: "\e(B";
ClearScreen :: "\e[2J";
ClearLine :: "\e[2K";
+ ClearScrollBack :: "\e[3J";
Bell :: "\x07";
- SetWindowTitle :: "\e]0;%\x07";
+ SetWindowTitle :: "\e]0;%\e\\";
RefreshWindow :: "\e[7t"; // TODO Not yet tested.
SetUTF8 :: "\e%G"; // TODO TEST ME PLEASE
- // WIP WIP WIP
- // Add commands to change StyleNormal/Italic/Bold/Color/WhatNot!
-
+ SetGraphicsRendition :: "\e[%m";
// Cursor Position
SetCursorPosition :: "\e[%;%H";
@@ -93,18 +92,44 @@ Commands :: struct {
QueryCursorPosition :: "\e[6n"; // Emits the cursor position as: "ESC [ <r> ; <c> R" Where <r> = row and <c> = column.
QueryDeviceAttributes :: "\e[0c";
QueryWindowSizeInChars :: "\e[18t"; // Emits the window size as: "ESC [ 8 <r> ; <c> t" Where <r> = row and <c> = column. TODO Does not work on windows.
-
}
-GraphicsStyle :: struct {
- BackgroundColor : u8;
- ForegroundColor : u8;
- Bold : bool;
- Italic : bool;
- Underline : bool;
- Blinking : bool;
- Inverse : bool;
- StrikeThrough : bool;
+clear_style :: () {
+ write_string(#run sprint(Commands.SetGraphicsRendition, "0"));
+}
+
+Colors8b :: struct {
+ Black :: 0;
+ Maroon :: 1;
+ Green :: 2;
+ Olive :: 3;
+ Navy :: 4;
+ Purple :: 5;
+ Teal :: 6;
+ Silver :: 7;
+ Gray :: 8;
+ Red :: 9;
+ Lime :: 10;
+ Yellow :: 11;
+ Blue :: 12;
+ Magenta :: 13;
+ Cyan :: 14;
+ White :: 15;
+}
+
+// TODO Maybe rename.
+set_style_colors :: (foreground: u8, background: u8) {
+ print(
+ #run sprint(Commands.SetGraphicsRendition, "38;5;%;48;5;%"),
+ foreground, background);
+}
+
+// set_colors_24b :: (foreground_r: u255) // TODO https://en.wikipedia.org/wiki/ANSI_escape_code#8-bit
+
+set_style :: (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);
}
// TODO Maybe make the OS_* procedures as inline?!
@@ -124,18 +149,187 @@ Key :: u64;
KEY_SIZE :: #run type_info(Key).runtime_size;
-Keys :: struct {
+Keys :: struct #type_info_none {
// Terminal key-codes have 1 to 6 bytes, so we can signal special cases setting the edge-bytes.
- None : Key : 0xF0000000_0000000F;
- Resize : Key : 0xF0000000_0000001F;
+ None : Key : 0xF0000000_0000000F;
+ Resize : Key : 0xF0000000_0000001F;
- Up : Key : #run to_key("\e[A");
- Down : Key : #run to_key("\e[B");
- Right : Key : #run to_key("\e[C");
- Left : Key : #run to_key("\e[D");
-
- PgUp : Key : #run to_key("\e[5~");
- PgDown : Key : #run to_key("\e[6~");
+ Space : Key : #char " ";
+ Enter : Key : #char "\r";
+ Tab : Key : #char "\t";
+
+ Up : Key : #run to_key("\e[A");
+ Down : Key : #run to_key("\e[B");
+ Right : Key : #run to_key("\e[C");
+ Left : Key : #run to_key("\e[D");
+
+ MetaUp : Key : #run to_key("\e[1;1A");
+ MetaDown : Key : #run to_key("\e[1;1B");
+ MetaRight : Key : #run to_key("\e[1;1C");
+ MetaLeft : Key : #run to_key("\e[1;1D");
+
+ ShiftUp : Key : #run to_key("\e[1;2A");
+ ShiftDown : Key : #run to_key("\e[1;2B");
+ ShiftRight : Key : #run to_key("\e[1;2C");
+ ShiftLeft : Key : #run to_key("\e[1;2D");
+
+ AltUp : Key : #run to_key("\e[1;3A");
+ AltDown : Key : #run to_key("\e[1;3B");
+ AltRight : Key : #run to_key("\e[1;3C");
+ AltLeft : Key : #run to_key("\e[1;3D");
+
+ AltShiftUp : Key : #run to_key("\e[1;4A");
+ AltShiftDown : Key : #run to_key("\e[1;4B");
+ AltShiftRight : Key : #run to_key("\e[1;4C");
+ AltShiftLeft : Key : #run to_key("\e[1;4D");
+
+ CtrlUp : Key : #run to_key("\e[1;5A");
+ CtrlDown : Key : #run to_key("\e[1;5B");
+ CtrlRight : Key : #run to_key("\e[1;5C");
+ CtrlLeft : Key : #run to_key("\e[1;5D");
+
+ CtrlShiftUp : Key : #run to_key("\e[1;6A");
+ CtrlShiftDown : Key : #run to_key("\e[1;6B");
+ CtrlShiftRight : Key : #run to_key("\e[1;6C");
+ CtrlShiftLeft : Key : #run to_key("\e[1;6D");
+
+ CtrlAltUp : Key : #run to_key("\e[1;7A");
+ CtrlAltDown : Key : #run to_key("\e[1;7B");
+ CtrlAltRight : Key : #run to_key("\e[1;7C");
+ CtrlAltLeft : Key : #run to_key("\e[1;7D");
+
+ CtrlAltShiftUp : Key : #run to_key("\e[1;7A");
+ CtrlAltShiftDown : Key : #run to_key("\e[1;7B");
+ CtrlAltShiftRight : Key : #run to_key("\e[1;7C");
+ CtrlAltShiftLeft : Key : #run to_key("\e[1;7D");
+
+ Home : Key : #run to_key("\e[H");
+ End : Key : #run to_key("\e[F");
+
+ Escape : Key : 0x00000000_0000001B;
+ Backspace : Key : 0x00000000_0000007F;
+ Pause : Key : 0x00000000_0000001A;
+ Insert : Key : #run to_key("\e[2~");
+ Delete : Key : #run to_key("\e[3~");
+ PgUp : Key : #run to_key("\e[5~");
+ PgDown : Key : #run to_key("\e[6~");
+
+ F1 : Key : #run to_key("\eOP");
+ F2 : Key : #run to_key("\eOQ");
+ F3 : Key : #run to_key("\eOR");
+ F4 : Key : #run to_key("\eOS");
+ F5 : Key : #run to_key("\e[15~");
+ F6 : Key : #run to_key("\e[17~");
+ F7 : Key : #run to_key("\e[18~");
+ F8 : Key : #run to_key("\e[19~");
+ F9 : Key : #run to_key("\e[20~");
+ F10 : Key : #run to_key("\e[21~");
+ F11 : Key : #run to_key("\e[23~");
+ F12 : Key : #run to_key("\e[24~");
+
+ MetaF1 : Key : #run to_key("\eO1P");
+ MetaF2 : Key : #run to_key("\eO1Q");
+ MetaF3 : Key : #run to_key("\eO1R");
+ MetaF4 : Key : #run to_key("\eO1S");
+ MetaF5 : Key : #run to_key("\e[15;1~");
+ MetaF6 : Key : #run to_key("\e[17;1~");
+ MetaF7 : Key : #run to_key("\e[18;1~");
+ MetaF8 : Key : #run to_key("\e[19;1~");
+ MetaF9 : Key : #run to_key("\e[20;1~");
+ MetaF10 : Key : #run to_key("\e[21;1~");
+ MetaF11 : Key : #run to_key("\e[23;1~");
+ MetaF12 : Key : #run to_key("\e[24;1~");
+
+ ShiftF1 : Key : #run to_key("\eO2P");
+ ShiftF2 : Key : #run to_key("\eO2Q");
+ ShiftF3 : Key : #run to_key("\eO2R");
+ ShiftF4 : Key : #run to_key("\eO2S");
+ ShiftF5 : Key : #run to_key("\e[15;2~");
+ ShiftF6 : Key : #run to_key("\e[17;2~");
+ ShiftF7 : Key : #run to_key("\e[18;2~");
+ ShiftF8 : Key : #run to_key("\e[19;2~");
+ ShiftF9 : Key : #run to_key("\e[20;2~");
+ ShiftF10 : Key : #run to_key("\e[21;2~");
+ ShiftF11 : Key : #run to_key("\e[23;2~");
+ ShiftF12 : Key : #run to_key("\e[24;2~");
+
+ AltF1 : Key : #run to_key("\eO3P");
+ AltF2 : Key : #run to_key("\eO3Q");
+ AltF3 : Key : #run to_key("\eO3R");
+ AltF4 : Key : #run to_key("\eO3S");
+ AltF5 : Key : #run to_key("\e[15;3~");
+ AltF6 : Key : #run to_key("\e[17;3~");
+ AltF7 : Key : #run to_key("\e[18;3~");
+ AltF8 : Key : #run to_key("\e[19;3~");
+ AltF9 : Key : #run to_key("\e[20;3~");
+ AltF10 : Key : #run to_key("\e[21;3~");
+ AltF11 : Key : #run to_key("\e[23;3~");
+ AltF12 : Key : #run to_key("\e[24;3~");
+
+ AltShiftF1 : Key : #run to_key("\eO4P");
+ AltShiftF2 : Key : #run to_key("\eO4Q");
+ AltShiftF3 : Key : #run to_key("\eO4R");
+ AltShiftF4 : Key : #run to_key("\eO4S");
+ AltShiftF5 : Key : #run to_key("\e[15;4~");
+ AltShiftF6 : Key : #run to_key("\e[17;4~");
+ AltShiftF7 : Key : #run to_key("\e[18;4~");
+ AltShiftF8 : Key : #run to_key("\e[19;4~");
+ AltShiftF9 : Key : #run to_key("\e[20;4~");
+ AltShiftF10 : Key : #run to_key("\e[21;4~");
+ AltShiftF11 : Key : #run to_key("\e[23;4~");
+ AltShiftF12 : Key : #run to_key("\e[24;4~");
+
+ CtrlF1 : Key : #run to_key("\eO5P");
+ CtrlF2 : Key : #run to_key("\eO5Q");
+ CtrlF3 : Key : #run to_key("\eO5R");
+ CtrlF4 : Key : #run to_key("\eO5S");
+ CtrlF5 : Key : #run to_key("\e[15;5~");
+ CtrlF6 : Key : #run to_key("\e[17;5~");
+ CtrlF7 : Key : #run to_key("\e[18;5~");
+ CtrlF8 : Key : #run to_key("\e[19;5~");
+ CtrlF9 : Key : #run to_key("\e[20;5~");
+ CtrlF10 : Key : #run to_key("\e[21;5~");
+ CtrlF11 : Key : #run to_key("\e[23;5~");
+ CtrlF12 : Key : #run to_key("\e[24;5~");
+
+ CtrlShiftF1 : Key : #run to_key("\eO6P");
+ CtrlShiftF2 : Key : #run to_key("\eO6Q");
+ CtrlShiftF3 : Key : #run to_key("\eO6R");
+ CtrlShiftF4 : Key : #run to_key("\eO6S");
+ CtrlShiftF5 : Key : #run to_key("\e[15;6~");
+ CtrlShiftF6 : Key : #run to_key("\e[17;6~");
+ CtrlShiftF7 : Key : #run to_key("\e[18;6~");
+ CtrlShiftF8 : Key : #run to_key("\e[19;6~");
+ CtrlShiftF9 : Key : #run to_key("\e[20;6~");
+ CtrlShiftF10 : Key : #run to_key("\e[21;6~");
+ CtrlShiftF11 : Key : #run to_key("\e[23;6~");
+ CtrlShiftF12 : Key : #run to_key("\e[24;6~");
+
+ CtrlAltF1 : Key : #run to_key("\eO7P");
+ CtrlAltF2 : Key : #run to_key("\eO7Q");
+ CtrlAltF3 : Key : #run to_key("\eO7R");
+ CtrlAltF4 : Key : #run to_key("\eO7S");
+ CtrlAltF5 : Key : #run to_key("\e[15;7~");
+ CtrlAltF6 : Key : #run to_key("\e[17;7~");
+ CtrlAltF7 : Key : #run to_key("\e[18;7~");
+ CtrlAltF8 : Key : #run to_key("\e[19;7~");
+ CtrlAltF9 : Key : #run to_key("\e[20;7~");
+ CtrlAltF10 : Key : #run to_key("\e[21;7~");
+ CtrlAltF11 : Key : #run to_key("\e[23;7~");
+ CtrlAltF12 : Key : #run to_key("\e[24;7~");
+
+ CtrlAltShiftF1 : Key : #run to_key("\eO8P");
+ CtrlAltShiftF2 : Key : #run to_key("\eO8Q");
+ CtrlAltShiftF3 : Key : #run to_key("\eO8R");
+ CtrlAltShiftF4 : Key : #run to_key("\eO8S");
+ CtrlAltShiftF5 : Key : #run to_key("\e[15;8~");
+ CtrlAltShiftF6 : Key : #run to_key("\e[17;8~");
+ CtrlAltShiftF7 : Key : #run to_key("\e[18;8~");
+ CtrlAltShiftF8 : Key : #run to_key("\e[19;8~");
+ CtrlAltShiftF9 : Key : #run to_key("\e[20;8~");
+ CtrlAltShiftF10 : Key : #run to_key("\e[21;8~");
+ CtrlAltShiftF11 : Key : #run to_key("\e[23;8~");
+ CtrlAltShiftF12 : Key : #run to_key("\e[24;8~");
}
to_key :: inline (str: $T) -> Key #modify { return T == ([]u8) || T == string; } {
@@ -160,6 +354,7 @@ to_string :: inline (key: Key) -> string {
return str;
}
+// TODO FIXME DEBUG HACK
test_union :: ()
{
// ti := type_info(K);
@@ -209,8 +404,9 @@ input_string : string;
input_override : Key;
#run {
+ // TODO FIXME DEBUG HACK or maybe... let it be?!
// Some tests.
- assert(input_buffer.count >= 6, "The input buffer size must be capable to hold an entire terminal (6 bytes) or UTF8 (4 bytes) code.");
+ assert(input_buffer.count >= KEY_SIZE, "The input buffer size must be capable to hold an entire terminal (6 bytes) or UTF8 (4 bytes) code.");
}
assert_is_initialized :: inline () {
@@ -314,7 +510,8 @@ get_key :: (timeout_milliseconds: s32 = -1) -> Key {
// Must be a terminal escape sequence.
if utf8_bytes == 1 && input_string[0] == #char "\e" {
- to_parse.count = ifx input_string.count > 6 then 6 else input_string.count; // TODO We should look into the input_string and search for the following escape sequence or somehting!?
+ assert(input_string.count <= KEY_SIZE, "Received oversized terminal sequence."); // TODO
+ to_parse.count = ifx input_string.count > KEY_SIZE then KEY_SIZE else input_string.count; // TODO We should look into the input_string and search for the following escape sequence or somehting!?
}
key := to_key(to_parse);
@@ -345,13 +542,11 @@ get_key :: (timeout_milliseconds: s32 = -1) -> Key {
return xx Keys.None;
}
-get_str :: (count_limit: int = -1, allocator: Allocator = temp) -> string {
+get_str :: (count_limit: int = -1) -> string {
assert_is_initialized();
- assert(allocator.proc != null, "Argument 'allocator.proc' has invalid null value.");
if count_limit < 0 {
- builder: String_Builder();
- builder.allocator = allocator;
+ builder: String_Builder;
init_string_builder(*builder);
while(1) {
@@ -361,10 +556,10 @@ get_str :: (count_limit: int = -1, allocator: Allocator = temp) -> string {
if buffer.count < buffer.allocated break;
expand(*builder);
}
- return builder_to_string(*builder, allocator);
+ return builder_to_string(*builder);
}
else {
- buffer := alloc_string(count_limit, allocator);
+ buffer := alloc_string(count_limit);
buffer.count = OS_read_input(buffer.data, count_limit);
return buffer;
}
@@ -395,7 +590,7 @@ flush_input :: () {
OS_flush_input();
}
-// WIP WIP WIP
+// TODO move style related procedures here!
// set_style :: () {
// print("", Commands.) --
// }
@@ -463,7 +658,7 @@ get_terminal_size :: () -> rows: int, columns: int {
flush_input();
write_string(Commands.QueryWindowSizeInChars);
- input := get_str(64);
+ input := get_str(64,, temporary_allocator);
// Expected response format: \e[8;<r>;<c>t
// where <r> is the number of rows and <c> of columns.
@@ -483,7 +678,7 @@ get_terminal_size :: () -> rows: int, columns: int {
input[0] == FORMAT[0] && input[1] == FORMAT[1] && input[2] == FORMAT[2] && input[input.count-1] == FORMAT[FORMAT.count-1],
"Query window size in chars returned invalid response.");
- parts := split(input, ";");
+ parts := split(input, ";",, temporary_allocator);
rows = parse_int(*parts[1]);
columns = parse_int(*parts[2]);
}
@@ -504,7 +699,7 @@ get_cursor_position :: () -> row: int, column: int {
flush_input();
write_string(Commands.QueryCursorPosition);
- input := get_str(64);
+ input := get_str(64,, temporary_allocator);
// Expected response format: \e[<r>;<c>R
// where <r> is the number of rows and <c> of columns.
@@ -526,7 +721,7 @@ get_cursor_position :: () -> row: int, column: int {
advance(*input, 2);
- parts := split(input, ";");
+ parts := split(input, ";",, temporary_allocator);
row := parse_int(*parts[0]);
column := parse_int(*parts[1]);
return row, column;
diff --git a/ttt.jai b/ttt.jai
index b5dca56..2e5af82 100644
--- a/ttt.jai
+++ b/ttt.jai
@@ -392,7 +392,7 @@ delete_task :: (using db: *Database, index: s64) -> bool { // TODO Maybe use `us
size_of_task := size_of(Task);
if (tasks.allocated >> 2) > tasks.count && tasks.allocated * size_of_task > 2_000_000 {
new_capacity := tasks.allocated >> 1;
- new_tasks_data := realloc(tasks.data, new_capacity * size_of_task, tasks.allocated * size_of_task, tasks.allocator);
+ new_tasks_data := realloc(tasks.data, new_capacity * size_of_task, tasks.allocated * size_of_task,, tasks.allocator);
if new_tasks_data != null {
tasks.data = new_tasks_data;
tasks.allocated = new_capacity;
@@ -713,7 +713,7 @@ import_from_csv :: (db: *Database, path: string) -> bool {
// Thus this works on both 'dos' and 'unix'-style files.
s := << sp;
- found, result, right := split_from_left(s, 10);
+ found, result, right := split_from_left(s, 10,, temporary_allocator);
if !found {
// This is the last line; there may not have been a linefeed after that,
@@ -761,7 +761,7 @@ import_from_csv :: (db: *Database, path: string) -> bool {
if success == false break;
task: Task;
- csv_values := split(line, ","); // TODO Temporary memory... if file is too big this may break.
+ csv_values := split(line, ",",, temporary_allocator); // TODO Temporary memory... if file is too big this may break.
// Import task name.
name_length := min(task.name.count, csv_values[0].count);
@@ -1069,11 +1069,16 @@ draw_tui :: (db: *Database, layout: *Layout) {
// Apply theme.
if (task == active_task && task == selected_task) {
// attron(COLOR_PAIR(xx Styles.ACTIVE_SELECTED) | A_BOLD); TODO DAM
+ TUI.set_style_colors(TUI.Colors8b.Red, 6); // TODO TESTING COLORS
+ TUI.set_style(true, true, true, false);
}
else if (task == selected_task) {
// attron(COLOR_PAIR(xx Styles.SELECTED)); TODO DAM
+ TUI.set_style_colors(4, 6); // TODO TESTING COLORS
}
else if (task == active_task) {
+ TUI.set_style_colors(TUI.Colors8b.Red, 6); // TODO TESTING COLORS
+ TUI.set_style(false, false, false, true); // TODO TESTING STYLE
// attron(COLOR_PAIR(xx Styles.ACTIVE) | A_BOLD); TODO DAM
}
@@ -1081,16 +1086,18 @@ draw_tui :: (db: *Database, layout: *Layout) {
x += 1;
column_width = layout.columns[L_TITLE_IDX].width;
// mvprintw(xx y, xx x, "%-*.*s", column_width, column_width, temp_c_string(xx task.name)); //task.name); TODO Fix required for LLVM/Cncurses. TODO DAM
- TUI.set_cursor_position(y, x);
// TODO FIXME OH MY GOD SUCH BAD CODEZ
+ TUI.set_cursor_position(y, x);
+ white_spaces := column_width;
+ // FIXME Improve by using buffer instead of printing one char at the time.
+ while white_spaces > 0 {
+ print_character(#char " ");
+ white_spaces -= 1;
+ }
+ TUI.set_cursor_position(y, x);
task_name: string = cast(string)task.name;
task_name.count = ifx task_name.count > column_width then column_width else task_name.count;
print("%", task_name);
- diff := column_width - task_name.count;
- while diff > 0 {
- diff -= 1;
- print_character(#char " ");
- }
x += column_width;
// Task times.
@@ -1111,6 +1118,7 @@ draw_tui :: (db: *Database, layout: *Layout) {
// Reset theme.
//attrset(A_NORMAL); TODO DAM
+ TUI.clear_style();
}
@@ -1302,7 +1310,7 @@ main :: () {
last_none_char := "X";
drop_down := 0;
while(key != #char "q") {
- // __mark := get_temporary_storage_mark();
+ __mark := get_temporary_storage_mark();
if key == {
case TUI.Keys.None; {
@@ -1316,16 +1324,27 @@ main :: () {
TUI.clear_terminal();
drop_down = 0;
}
+
+ case TUI.Keys.MetaF7; {
+ TUI.set_cursor_position(3+drop_down, 2);
+ drop_down += 1;
+ write_string("META F7");
+ }
case; {
TUI.set_cursor_position(3+drop_down, 2);
str := TUI.to_string(key);
for 0..str.count-1 {
+ print("'%'", FormatInt.{value = cast(u8)str[it], base=16});
+ }
+ write_string(":> ");
+ for 0..str.count-1 {
if str[it] == #char "\e" {
str[it] = #char "?";
}
}
write_string(str);
+ write_string(" <EOL");
drop_down += 1;
}
}
@@ -1337,6 +1356,8 @@ main :: () {
print("size(CxR): %x%\n", size_c, size_r);
key = TUI.get_key(3000);
+
+ set_temporary_storage_mark(__mark);
}
TUI.stop();
print("size(CxR): %x%\n", xcolumns, xrows);
@@ -1757,14 +1778,14 @@ main :: () {
if (active_task == null) continue;
select_task(db, db.active_idx);
- case #char "\n"; #through;
- case #char " ";
+ case TUI.Keys.Enter; #through;
+ case TUI.Keys.Space;
if (db != *database || selected_task == null) continue;
set_active_task(db, ifx db.active_idx == db.selected_idx then -1 else db.selected_idx);
active_task = get_active_task(db);
trigger_autosave();
- case #char "\t";
+ case TUI.Keys.Tab;
if (db == *database) {
if (import_from_csv(*archive, ar_file_path) == false) {
reset_database(*archive);