aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordam <dam@gudinoff>2023-09-12 01:04:16 +0100
committerdam <dam@gudinoff>2023-09-12 01:04:16 +0100
commit7469ce1ab6c761e81334b918a34972fedba0923e (patch)
treef1554542318dd54b7b91e1df482fa5d105476fe0
parent76f3be800b9306a0a63c9f888b5e61c27ea35c0e (diff)
downloadtask-time-tracker-7469ce1ab6c761e81334b918a34972fedba0923e.tar.zst
task-time-tracker-7469ce1ab6c761e81334b918a34972fedba0923e.zip
Adding a terminal user interface module (like ncurses but way simpler).
-rw-r--r--ttt.jai60
-rw-r--r--tui.jai106
2 files changed, 155 insertions, 11 deletions
diff --git a/ttt.jai b/ttt.jai
index 7431ac6..53a3e01 100644
--- a/ttt.jai
+++ b/ttt.jai
@@ -27,7 +27,8 @@
#import "String";
// #import "curses";
// #import "kscurses";
-TUI :: #import "tio"; // TODO Rename module to "tui.jai"
+TIO :: #import "tio"; // TODO Move things into TUI.
+TUI :: #import "tui";
#load "Integer_Saturating_Arithmetic.jai";
@@ -901,7 +902,7 @@ initialize_tui :: () {
}
// TODO DAM
- TUI.initialize();
+ TIO.initialize();
// stdscr = initscr(); // Start curses mode. TODO DAM
// cbreak(); // Line buffering disabled; pass on everty thing to me. TODO DAM
// keypad(stdscr, true); // I need those nifty F1..F12. TODO DAM
@@ -955,7 +956,7 @@ draw_tui :: (db: *Database, layout: *Layout) {
// Reset theme and clear screen.
//attrset(A_NORMAL); TODO DAM
- TUI.tui_clear_screen();
+ TIO.tui_clear_screen();
// Draw outer border.
//box(stdscr, 0, 0); TODO DAM
@@ -1179,6 +1180,43 @@ read_enter_confirmation :: inline (row: int, style: int, message: string) -> boo
}
main :: () {
+
+ // https://learn.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences
+ // https://learn.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences#designate-character-set
+ // https://github.com/MicrosoftDocs/Console-Docs/blob/main/docs/console-virtual-terminal-sequences.md
+ TUI.start();
+ TUI.clear_screen();
+ TUI.draw_box(1,1,13,13);
+ sleep_milliseconds(10000);
+ write_string(TUI.Commands.ShowCursor);
+ TUI.stop();
+ return;
+
+ str: string;
+
+ write_string("\e(0"); // Enter Line drawing mode
+ write_string("\e[104;93m"); // bright yellow on bright blue
+ write_string("x"); // in line drawing mode, \x78 -> \u2502 "Vertical Bar"
+ write_string("\e[10m"); // restore color
+ write_string("\e(B"); // exit line drawing mode
+ sleep_milliseconds(1000);
+
+
+ // str = "\e[sWOW\e[u\e[1P";
+ str = "\e[sWOW";
+ // write(STDIN_FILENO, str.data, xx str.count);
+ write_string(str);
+ sleep_milliseconds(1000);
+
+ str = "\e[?25l";
+ // write(STDIN_FILENO, str.data, xx str.count);
+ write_string(str);
+ sleep_milliseconds(1000);
+
+ str = "\e[?25h";
+ // write(STDIN_FILENO, str.data, xx str.count);
+ write_string(str);
+ return;
// TODO Implement signal handling and see modules/Debug.jai for examples.
@@ -1361,7 +1399,7 @@ main :: () {
layout := *layouts[Layouts.COMPACT];
//flushinp(); TODO DAM
- TUI.tui_ungetch(KEY_RESIZE); // TODO DAM
+ TIO.tui_ungetch(KEY_RESIZE); // TODO DAM
while (true) {
if (is_terminal_too_small) {
@@ -1375,7 +1413,7 @@ main :: () {
reset_temporary_storage();
//timeout(INPUT_TIMEOUT_MS); TODO DAM
- key := TUI.tui_getch(); // getch(); TODO DAM
+ key := TIO.tui_getch(); // getch(); TODO DAM
if key == #char "q" || key == #char "Q" break;
update_times(*database);
//timeout(INPUT_AWAIT_INF); TODO DAM
@@ -1413,13 +1451,13 @@ main :: () {
// When terminal is resized.
case KEY_RESIZE;
- TUI.tui_clear_screen();
+ TIO.tui_clear_screen();
//getmaxyx(stdscr, *size_y, *size_x);
- TUI.update_terminal_size(); // TODO DAM
- size_x = TUI.terminal_state.width;
- size_y = TUI.terminal_state.height;
+ TIO.update_terminal_size(); // TODO DAM
+ size_x = TIO.terminal_state.width;
+ size_y = TIO.terminal_state.height;
print("resize:%x%", size_x, size_y);
- asd := TUI.tui_getch();
+ asd := TIO.tui_getch();
is_terminal_too_small = size_x < 60 || size_y < 3;
update_layout();
layout = *layouts[ifx size_x > 100 then Layouts.NORMAL else Layouts.COMPACT];
@@ -1770,7 +1808,7 @@ main :: () {
//getch(); TODO DAM
}
- TUI.terminate(); // TODO DAM
+ TIO.terminate(); // TODO DAM
exit(xx ifx error_saving then 1 else 0);
}
diff --git a/tui.jai b/tui.jai
new file mode 100644
index 0000000..a0eb025
--- /dev/null
+++ b/tui.jai
@@ -0,0 +1,106 @@
+#import "Basic";
+
+Drawings :: struct {
+ CornerBR :: "\x6A";
+ CornerTR :: "\x6B";
+ CornerTL :: "\x6C";
+ CornerBL :: "\x6D";
+ Cross :: "\x6E";
+ LineH :: "\x71";
+ TeeL :: "\x74";
+ TeeR :: "\x75";
+ TeeB :: "\x76";
+ TeeT :: "\x77";
+ LineV :: "\x78";
+}
+
+Commands :: struct {
+ EnterAlternateBuffer :: "\e[?1049h";
+ EnterMainBuffer :: "\e[?1049l";
+
+ EnterDrawingMode :: "\e(0";
+ EnterNormalMode :: "\e(B";
+ ClearScreen :: "\e[2J";
+
+ // Cursor Visibility
+ ShowCursor :: "\e[?25h";
+ HideCursor :: "\e[?25l";
+ StartBlinking :: "\e[?25h]";
+ StopBlinking :: "\e[?25l]";
+
+ // Cursor Shape
+ DefaultShape :: "\e[0 q";
+ BlinkingBlockShape :: "\e[1 q";
+ SteadyBlockShape :: "\e[2 q";
+ BlinkingUnderlineShape :: "\e[3 q";
+ SteadyUnderlineShape :: "\e[4 q";
+ BlinkingBarShape :: "\e[5 q";
+ SteadyBarShape :: "\e[6 q";
+
+ // Input Mode
+ KeypadAppMode :: "\e=";
+ KeypadNumMode :: "\e>";
+ CursorAppMode :: "\e[?1h";
+ CursorNormalMode :: "\e[?1l";
+
+ // Query State
+ QueryCursorPos :: "\e[6n"; // Emits the cursor position as: ESC [ <r> ; <c> R Where <r> = row and <c> = column.
+ QueryDeviceAttributes :: "\e[0c";
+}
+
+start :: () {
+ write_string(Commands.EnterAlternateBuffer);
+}
+
+stop :: () {
+ write_string(Commands.EnterMainBuffer);
+}
+
+draw_box :: (x: int, y: int, width: int, height: int, to_standard_error := false) {
+
+ write_string(Commands.HideCursor);
+ write_strings(
+ // Commands.EnterNormalMode,
+ Commands.EnterDrawingMode,
+ "\e[1;1H", // Move to position 1,1
+ // TODO // Move pointer to top-left corner.
+ Drawings.CornerTL,
+ to_standard_error = to_standard_error);
+
+ for 1..width-2 {
+ write_string(Drawings.LineH, to_standard_error = to_standard_error);
+ }
+ write_string(Drawings.CornerTR, to_standard_error = to_standard_error);
+
+
+ // TODO Take care of the temporary allocations.
+ for idx: 2..height-1 {
+ tmpL := tprint("\e[%;%H", idx, 1);
+ tmpR := tprint("\e[%;%H", idx, width);
+ write_strings(
+ tmpL,
+ Drawings.LineV,
+ tmpR,
+ Drawings.LineV,
+ to_standard_error = to_standard_error);
+ }
+
+ tmpBL := tprint("\e[%;%H", height, 1);
+ write_strings(
+ tmpBL,
+ Drawings.CornerBL,
+ to_standard_error = to_standard_error);
+ for 1..width-2 {
+ write_string(Drawings.LineH, to_standard_error = to_standard_error);
+ }
+ write_string(Drawings.CornerBR, to_standard_error = to_standard_error);
+
+ write_strings(
+ // TODO // print
+ Commands.EnterNormalMode,
+ to_standard_error = to_standard_error);
+}
+
+clear_screen :: inline () {
+ write_string(Commands.ClearScreen);
+}