diff options
| author | dam <dam@gudinoff> | 2024-05-05 02:34:33 +0100 |
|---|---|---|
| committer | dam <dam@gudinoff> | 2024-05-05 02:34:33 +0100 |
| commit | 36af624cdd9cb54454587bfae21b30096986d22e (patch) | |
| tree | 89fb9d3eb79ff68f047bd30dbcb680e6dce8abc3 /modules | |
| parent | cb6c3caaa285bc8bd12c356d57bbfad86d70c0eb (diff) | |
| download | task-time-tracker-36af624cdd9cb54454587bfae21b30096986d22e.tar.zst task-time-tracker-36af624cdd9cb54454587bfae21b30096986d22e.zip | |
WIP : Cleanup TUI module and improved assert/error messages.
Diffstat (limited to 'modules')
| -rw-r--r-- | modules/TUI/module.jai | 137 | ||||
| -rw-r--r-- | modules/TUI/unix.jai | 14 | ||||
| -rw-r--r-- | modules/TUI/windows.jai | 34 |
3 files changed, 81 insertions, 104 deletions
diff --git a/modules/TUI/module.jai b/modules/TUI/module.jai index ab2567d..07d121f 100644 --- a/modules/TUI/module.jai +++ b/modules/TUI/module.jai @@ -15,36 +15,46 @@ #assert(false, "Unsupported OS."); } +#if COLOR_MODE_BITS == { + case 4; + #load "palette_4b.jai"; + case 8; + #load "palette_8b.jai"; + case 24; + #load "palette_24b.jai"; + _; + assert(false, "Invalid COLOR_MODE_BITS. Valid values are 4, 8, or 24 (default)."); +} + #import "Basic"; #import "String"; #import "Thread"; #import "UTF8"; #load "key_map.jai"; +active := false; +input_override : Key; +input_string : string; +input_buffer : [1024] u8; + KEY_SIZE :: #run type_info(Key).runtime_size; -#run { - assert(COLOR_MODE_BITS == 4 || COLOR_MODE_BITS == 8 || COLOR_MODE_BITS == 24, "Invalid COLOR_MODE_BITS. Valid values are 4, 8, or 24 (default)."); - 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)."); -} +#assert(input_buffer.count >= KEY_SIZE); // The input buffer size must be capable to hold an entire Key. -active := false; -input_buffer : [1024] u8; -input_string : string; -input_override : Key; -previous_logger : (message: string, data: *void, info: Log_Info); +#scope_module -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."); } +log_tui_error :: (format_string: string, args: .. Any) { + write_strings(Commands.SaveCursorPosition, Commands.MainScreenBuffer); + log_error(format_string, args); + write_strings(Commands.AlternateScreenBuffer, Commands.RestoreCursorPosition); +} + #scope_export; @@ -141,56 +151,7 @@ Commands :: struct #type_info_none { CursorNormalMode :: "\e[?1l"; } -// 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"; - - set_colors :: inline (foreground: Palette, background: Palette) { - print( - #run sprint("%0%0", Commands.SetGraphicsRendition, Commands.SetGraphicsRendition), - cast(u8)foreground + 30, cast(u8)background + 40); - } -} -else #if COLOR_MODE_BITS == 8 { - #load "palette_8b.jai"; - - set_colors :: inline (foreground: Palette, background: Palette) { - print( - #run sprint(Commands.SetGraphicsRendition, "38;5;%;48;5;%"), - cast(u8)foreground, cast(u8)background); - } -} -else { - #load "palette_24b.jai"; - - set_colors :: inline (foreground: Color_24b, background: Color_24b) { - print( - #run sprint(Commands.SetGraphicsRendition, "38;2;%;%;%;48;2;%;%;%"), - foreground.r, foreground.g, foreground.b, - background.r, background.g, background.b); - } -} - -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 - +#add_context terminal_style: Style; Style :: struct { #if COLOR_MODE_BITS == 4 || COLOR_MODE_BITS == 8 { @@ -214,11 +175,32 @@ Style :: struct { negative: bool; } -#add_context terminal_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); + print( + #run sprint(Commands.SetGraphicsRendition, "%;%;%;%"), + ifx style.bold then 1 else 22, + ifx style.underline then 4 else 24, + ifx style.strike_through then 9 else 29, + ifx style.negative then 7 else 27); + + #if COLOR_MODE_BITS == { + case 4; + print( + #run sprint("%0%0", Commands.SetGraphicsRendition, Commands.SetGraphicsRendition), + cast(u8)style.foreground + 30, cast(u8)style.background + 40); + + case 8; + print( + #run sprint(Commands.SetGraphicsRendition, "38;5;%;48;5;%"), + cast(u8)style.foreground, cast(u8)style.background); + + case 24; + print( + #run sprint(Commands.SetGraphicsRendition, "38;2;%;%;%;48;2;%;%;%"), + style.foreground.r, style.foreground.g, style.foreground.b, + style.background.r, style.background.g, style.background.b); + } + context.terminal_style = style; } @@ -286,7 +268,7 @@ Keys :: struct #type_info_none { } 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); + assert(str.count <= KEY_SIZE, "Invalid arguments passed to to_key(): 'str' has more than % bytes and cannot be stored as a Key.", KEY_SIZE); k: Key; for 0..str.count-1 { @@ -325,9 +307,6 @@ setup_terminal :: () -> success := true #must { input_string.count = 0; input_override = xx Keys.None; - previous_logger = context.logger; - context.logger = module_logger; - setup_key_map(); write_strings( @@ -355,8 +334,6 @@ reset_terminal :: () -> success := true #must { if !OS_reset_terminal() then return false; - context.logger = previous_logger; - write_strings( Commands.MainScreenBuffer, Commands.RestoreCursorPosition, @@ -446,8 +423,8 @@ get_key :: (timeout_milliseconds: s32 = -1) -> Key { // At least one of the arguments must be properly setup to avoid an infinite-loop reading the input. read_input :: (count_limit: int = -1, terminators: .. u8) -> string { assert_is_active(); - assert(count_limit >= 0 || terminators.count > 0, "Invalid arguments passed to read_input() will result in infinite-loop."); - + assert(count_limit >= 0 || terminators.count > 0, "Invalid arguments passed to read_input(): when 'count_limit' is less-than 0 (ignored), you need to provide 'terminators' to avoid an infinite-loop."); + // Read until one of the terminator characters is found. // Since we don't know the resulting size of the returned string, we must keep the string builder growing. if count_limit < 0 { @@ -504,7 +481,7 @@ read_input :: (count_limit: int = -1, terminators: .. u8) -> string { // Resize discards the input returning an empty string and a Resize key. read_input_line :: (count_limit: int, is_visible: bool = true) -> string, Key { assert_is_active(); - assert(count_limit >= 0, "Invalid value passed to count_limit(): %.", count_limit); + assert(count_limit >= 0, "Invalid arguments passed to read_input_line(): 'count_limit' must be greater-than or equal to 0."); builder := String_Builder.{ allocator = temporary_allocator }; @@ -604,7 +581,7 @@ flush_input :: () { draw_box :: (x: int, y: int, width: int, height: int) { assert_is_active(); - assert(x > 0 && y > 0 && width > 1 && height > 1, "Invalid arguments passed to draw_box(): (%, %, %, %).\n", x, y, width, height); + assert(x > 0 && y > 0 && width > 1 && height > 1, "Invalid arguments passed to draw_box(): 'x' and 'y' must be greater-than 0; 'width' and 'height' must be greater-than 1."); auto_release_temp(); @@ -674,7 +651,7 @@ get_terminal_size :: () -> width: int, height: int { assert(input.count >= 3 && 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."); + "Failed to query window size: invalid response."); parts := split(input, ";",, temporary_allocator); rows = parse_int(*parts[1]); @@ -723,7 +700,7 @@ get_cursor_position :: () -> x: int, y: int { assert(input.count >= 2 && input[0] == FORMAT[0] && input[1] == FORMAT[1] && input[input.count-1] == FORMAT[FORMAT.count-1], - "Query cursor position returned invalid response."); + "Failed to query cursor position: invalid response."); advance(*input, 2); parts := split(input, ";",, temporary_allocator); diff --git a/modules/TUI/unix.jai b/modules/TUI/unix.jai index 940ac80..99cc61d 100644 --- a/modules/TUI/unix.jai +++ b/modules/TUI/unix.jai @@ -230,7 +230,7 @@ restore_resize_handler :: () { //////////////////////////////////////////////////////////////////////////////// -#scope_export +#scope_module OS_prepare_terminal :: () -> success := true { error: int = ---; @@ -238,7 +238,7 @@ OS_prepare_terminal :: () -> success := true { error = tcgetattr(STDIN_FILENO, *initial_tio_mode); if error { error_code, error_string := get_error_value_and_string(); - log_error("Failed to get initial_tio_mode: code %, %", error_code, error_string); + log_tui_error("Failed to get initial_tio_mode: code %, %", error_code, error_string); return false; } @@ -254,7 +254,7 @@ OS_prepare_terminal :: () -> success := true { error = tcsetattr(STDIN_FILENO, xx Optional_Actions.TCSANOW, *raw_tio_mode); if error { error_code, error_string := get_error_value_and_string(); - log_error("Failed to set raw_tio_mode: code %, %", error_code, error_string); + log_tui_error("Failed to set raw_tio_mode: code %, %", error_code, error_string); return false; } @@ -268,7 +268,7 @@ OS_reset_terminal :: () -> success := true { error := tcsetattr(STDIN_FILENO, xx Optional_Actions.TCSANOW, *initial_tio_mode); if error { error_code, error_string := get_error_value_and_string(); - log_error("Failed to set initial_tio_mode: code %, %", error_code, error_string); + log_tui_error("Failed to set initial_tio_mode: code %, %", error_code, error_string); return false; } return; @@ -278,7 +278,7 @@ OS_flush_input :: () -> success := true { error := tcflush(STDIN_FILENO, xx Queue_Selector.TCIFLUSH); if error { error_code, error_string := get_error_value_and_string(); - log_error("Failed to flush input: code %, %", error_code, error_string); + log_tui_error("Failed to flush input: code %, %", error_code, error_string); return false; } return; @@ -288,7 +288,7 @@ OS_read_input :: (buffer: *u8, bytes_to_read: s64) -> bytes_read: s64, success : bytes_read := read(STDIN_FILENO, buffer, xx bytes_to_read); if bytes_read < 0 { error_code, error_string := get_error_value_and_string(); - log_error("Failed to read input: code %, %", error_code, error_string); + log_tui_error("Failed to read input: code %, %", error_code, error_string); return 0, false; } return bytes_read; @@ -306,7 +306,7 @@ OS_wait_for_input :: (timeout_milliseconds: s32 = -1) -> is_input_available: boo error_code, error_string := get_error_value_and_string(); // Ignore window resize events (error_code 4). if error_code != 4 { - log_error("Unexpected error while waiting for input: code %, %", error_code, error_string); + log_tui_error("Unexpected error while waiting for input: code %, %", error_code, error_string); return false, false; } } diff --git a/modules/TUI/windows.jai b/modules/TUI/windows.jai index fb50e49..f8d8bc8 100644 --- a/modules/TUI/windows.jai +++ b/modules/TUI/windows.jai @@ -142,7 +142,7 @@ peek_input :: () -> INPUT_RECORD, success := true { records_read: u32; if PeekConsoleInputW(stdin, *record, 1, *records_read) == false { error_code, error_string := get_error_value_and_string(); - log_error("Failed to peek input: code %, %", error_code, error_string); + log_tui_error("Failed to peek input: code %, %", error_code, error_string); return record, false; } return record; @@ -153,7 +153,7 @@ read_input :: () -> INPUT_RECORD, success := true { records_read: u32; if ReadConsoleInputW(stdin, *record, 1, *records_read) == false { error_code, error_string := get_error_value_and_string(); - log_error("Failed to read input: code %, %", error_code, error_string); + log_tui_error("Failed to read input: code %, %", error_code, error_string); return record, false; } return record; @@ -163,7 +163,7 @@ count_input :: () -> u32, success := true { count: u32; if GetNumberOfConsoleInputEvents(stdin, *count) == false { error_code, error_string := get_error_value_and_string(); - log_error("Failed to count input: code %, %", error_code, error_string); + log_tui_error("Failed to count input: code %, %", error_code, error_string); return 0, false; } return count; @@ -171,7 +171,7 @@ count_input :: () -> u32, success := true { //////////////////////////////////////////////////////////////////////////////// -#scope_export +#scope_module OS_prepare_terminal :: () -> success := true { @@ -179,12 +179,12 @@ OS_prepare_terminal :: () -> success := true { stdin = GetStdHandle(STD_INPUT_HANDLE); if stdin == INVALID_HANDLE_VALUE { error_code, error_string := get_error_value_and_string(); - log_error("Invalid input handler: code %, %", error_code, error_string); + log_tui_error("Invalid input handler: code %, %", error_code, error_string); return false; } if xx GetConsoleMode(stdin, *initial_stdin_mode) == false { error_code, error_string := get_error_value_and_string(); - log_error("Failed to get input mode: code %, %", error_code, error_string); + log_tui_error("Failed to get input mode: code %, %", error_code, error_string); return false; } raw_stdin_mode = (cast(Console_Input_Mode) initial_stdin_mode); @@ -193,7 +193,7 @@ OS_prepare_terminal :: () -> success := true { if xx SetConsoleMode(stdin, xx raw_stdin_mode) == false { error_code, error_string := get_error_value_and_string(); - log_error("Failed to set input mode: code %, %", error_code, error_string); + log_tui_error("Failed to set input mode: code %, %", error_code, error_string); return false; } @@ -201,12 +201,12 @@ OS_prepare_terminal :: () -> success := true { stdout = GetStdHandle(STD_OUTPUT_HANDLE); if stdout == INVALID_HANDLE_VALUE { error_code, error_string := get_error_value_and_string(); - log_error("Invalid output handler: code %, %", error_code, error_string); + log_tui_error("Invalid output handler: code %, %", error_code, error_string); return false; } if xx GetConsoleMode(stdout, *initial_stdout_mode) == false { error_code, error_string := get_error_value_and_string(); - log_error("Failed to get output mode: code %, %", error_code, error_string); + log_tui_error("Failed to get output mode: code %, %", error_code, error_string); return false; } raw_stdout_mode = (cast(Console_Output_Mode) initial_stdout_mode); @@ -214,7 +214,7 @@ OS_prepare_terminal :: () -> success := true { if xx SetConsoleMode(stdout, xx raw_stdout_mode) == false { error_code, error_string := get_error_value_and_string(); - log_error("Failed to set output mode: code %, %", error_code, error_string); + log_tui_error("Failed to set output mode: code %, %", error_code, error_string); return false; } @@ -231,12 +231,12 @@ OS_prepare_terminal :: () -> success := true { OS_reset_terminal :: () -> success := true { if xx SetConsoleMode(stdin, initial_stdin_mode) == false { error_code, error_string := get_error_value_and_string(); - log_error("Failed to reset input mode: code %, %", error_code, error_string); + log_tui_error("Failed to reset input mode: code %, %", error_code, error_string); return false; } if xx SetConsoleMode(stdout, initial_stdout_mode) == false { error_code, error_string := get_error_value_and_string(); - log_error("Failed to reset output mode: code %, %", error_code, error_string); + log_tui_error("Failed to reset output mode: code %, %", error_code, error_string); return false; } return; @@ -247,7 +247,7 @@ OS_flush_input :: () { // Attempting to empty the input queue all at once can destroy state in the queue in an unexpected manner. if FlushConsoleInputBuffer(stdin) == false { error_code, error_string := get_error_value_and_string(); - log_error("Failed to flush input: code %, %", error_code, error_string); + log_tui_error("Failed to flush input: code %, %", error_code, error_string); } } @@ -255,7 +255,7 @@ OS_read_input :: (buffer: *u8, bytes_to_read: s64) -> bytes_read: s64, success : S32_MAX :: 0x7fff_ffff; if (bytes_to_read > S32_MAX) { - log_error("The Windows API only allows to read up to 2^32 bytes from the standard input. Clamping input argument."); + log_tui_error("The Windows API only allows to read up to 2^32 bytes from the standard input. Clamping input argument."); bytes_to_read = S32_MAX; } @@ -288,14 +288,14 @@ OS_read_input :: (buffer: *u8, bytes_to_read: s64) -> bytes_read: s64, success : success = ReadConsoleW(stdin, widechar_view.data, chars_to_read, *widechar_view.count, null); if success == false { error_code, error_string := get_error_value_and_string(); - log_error("Failed to read console: code %, %", error_code, error_string); + log_tui_error("Failed to read console: code %, %", error_code, error_string); return 0, false; } result:, success = wide_to_utf8_new(widechar_view.data, xx widechar_view.count); if success == false { error_code, error_string := get_error_value_and_string(); - log_error("Failed to convert from wide to utf8: code %, %", error_code, error_string); + log_tui_error("Failed to convert from wide to UTF8: code %, %", error_code, error_string); return 0, false; } @@ -338,7 +338,7 @@ OS_wait_for_input :: (timeout_milliseconds: s32 = -1) -> is_input_available: boo if wait_result == WAIT_FAILED { error_code, error_string := get_error_value_and_string(); - log_error("Error while waiting for input: code %, %", error_code, error_string); + log_tui_error("Error while waiting for input: code %, %", error_code, error_string); return false, false; } |
