aboutsummaryrefslogtreecommitdiff
path: root/ttt.jai
diff options
context:
space:
mode:
Diffstat (limited to 'ttt.jai')
-rw-r--r--ttt.jai125
1 files changed, 63 insertions, 62 deletions
diff --git a/ttt.jai b/ttt.jai
index 23d370c..33d5282 100644
--- a/ttt.jai
+++ b/ttt.jai
@@ -33,13 +33,9 @@ DEBUG_MEMORY :: true;
#import "UTF8";
TUI :: #import "TUI"(COLOR_MODE_BITS=4);
-// - fix/implement/finish TODO : use `dirty_bit_flag` to only update ehat has been changed
-
VERSION :: "2.0"; // Use only 3 chars (to fit layouts).
YEAR :: "2024";
-FIRST_DAY_OF_WEEK :: 1; // (0-6, Sunday = 0).
-NUM_WEEK_DAYS :: 7; // TODO This has to go - Just to be more clear about what we're looping about.
-NAME_SIZE :: 72; // TODO Use this instead of Task.name.count ?
+NUM_WEEK_DAYS :: 7;
APP_FOLDER_NAME :: ".task_time_tracker_test"; // TODO Using different folder to avoid erasing my work data.
DB_FILE_NAME :: "database.bin";
@@ -74,6 +70,7 @@ database : Database;
archive : Database;
is_autosave_enabled := true;
countdown_to_autosave := -1;
+first_day_of_week := 1; // (0-6, Sunday = 0, Monday = 1, ...)
app_directory : string;
db_file_path : string;
ar_file_path : string;
@@ -262,7 +259,7 @@ print_time :: (y: int, x: int, time: s64, space: int) -> int {
ifx time >= #run mul_f64_s64(9.995, SECONDS_IN_DAY) then 1 else
2;
print_padding(left_padding);
- print("%d", FormatFloat.{value = value, trailing_width=decimals, width=4});
+ print("%d", FormatFloat.{value = value, trailing_width=decimals, width=4, zero_removal=.NO});
print_padding(right_padding);
return 0;
}
@@ -273,7 +270,7 @@ print_time :: (y: int, x: int, time: s64, space: int) -> int {
ifx time >= #run mul_f64_s64(9.995, SECONDS_IN_YEAR) then 1 else
2;
print_padding(left_padding);
- print("%y", FormatFloat.{value = value, trailing_width=decimals, width=4});
+ print("%y", FormatFloat.{value = value, trailing_width=decimals, width=4, zero_removal=.NO});
print_padding(right_padding);
return 0;
}
@@ -318,7 +315,7 @@ add_task :: (db: *Database, task: *Task = null) -> task: *Task, index: s64 {
// Deletes task from database.
// If possible, shrinks the database capacity.
// Returns success.
-delete_task :: (using db: *Database, index: s64) -> bool { // TODO Maybe use `using db`.
+delete_task :: (using db: *Database, index: s64) -> bool {
assert(db != null, ASSERT_NOT_NULL, "db");
assert(is_valid_index(db, index), ASSERT_INVALID_INDEX, index);
@@ -361,40 +358,40 @@ delete_task :: (using db: *Database, index: s64) -> bool { // TODO Maybe use `us
// Moves task from source to target.
// Source and target get clamped to database size.
-move_task :: (db: *Database, source: s64, target: s64) { // TODO Maybe `using db`
+move_task :: (using db: *Database, source: s64, target: s64) {
assert(db != null, ASSERT_NOT_NULL, "db");
- source = clamp(source, 0, db.tasks.count-1);
- target = clamp(target, 0, db.tasks.count-1);
+ source = clamp(source, 0, tasks.count-1);
+ target = clamp(target, 0, tasks.count-1);
if (source == target) return;
// Move task to new location, but first, shift the others to allow some space.
- temp_task := db.tasks[source];
+ temp_task := tasks[source];
move_size := abs(target - source);
if target > source {
for 0..move_size-1
- db.tasks[source + it] = db.tasks[source + it + 1];
+ tasks[source + it] = tasks[source + it + 1];
}
else {
for < move_size-1..0
- db.tasks[target + it + 1] = db.tasks[target + it];
+ tasks[target + it + 1] = tasks[target + it];
}
- db.tasks[target] = temp_task;
+ tasks[target] = temp_task;
// Adjust active and selected tasks.
- if (db.active_idx == source) {
- db.active_idx = target;
+ if (active_idx == source) {
+ active_idx = target;
}
- else if (source < db.active_idx && db.active_idx <= target) {
- db.active_idx -= 1;
+ else if (source < active_idx && active_idx <= target) {
+ active_idx -= 1;
}
- else if (target <= db.active_idx && db.active_idx < source) {
- db.active_idx += 1;
+ else if (target <= active_idx && active_idx < source) {
+ active_idx += 1;
}
- db.selected_idx = target;
+ selected_idx = target;
}
// Find similar task and return it's index, or -1 if not found.
@@ -506,7 +503,7 @@ add_task_time :: (db: *Database, index: s64, day: int, time: s64) {
}
// Adds the time on the day and task provided (and adjusts database totals).
-add_task_times :: (db: *Database, index: s64, times: [7] s64) {
+add_task_times :: (db: *Database, index: s64, times: [NUM_WEEK_DAYS] s64) {
assert(db != null, ASSERT_NOT_NULL, "db");
assert(is_valid_index(db, index), ASSERT_INVALID_INDEX, index);
@@ -900,35 +897,36 @@ update_layout :: () {
}
}
+// Pagination based on currently selected task (show page where selected task is).
+// Display up to rows allowed by the layout, or less if reached end of database.
+get_visible_tasks_indices :: (db: Database) -> first_visible_index: int, last_visible_index: int {
+ first_visible_index :=
+ (db.selected_idx / layout_tasks_rows) * layout_tasks_rows;
+
+ last_visible_index :=
+ first_visible_index +
+ (ifx layout_tasks_rows > db.tasks.count - first_visible_index
+ then db.tasks.count - first_visible_index
+ else layout_tasks_rows);
+
+ return first_visible_index, last_visible_index;
+}
+
+get_day_index_from_layout_index :: inline (layout_index: int) -> int {
+ return (layout_index + first_day_of_week) % NUM_WEEK_DAYS;
+}
+
+// Convert indices to allow using different days as the first-day-of-the-week.
+get_layout_index_from_day_index :: inline (day_index: int) -> int {
+ return (day_index - first_day_of_week + NUM_WEEK_DAYS) % NUM_WEEK_DAYS;
+}
+
dbg_average := 0; // DEBUG
dbg_count := 0; // DEBUG
buffer: String_Builder; // TODO
draw_user_interface :: (db: *Database, layout: *Layout, redraw_all: bool = true) {
- // Pagination based on currently selected task (show page where selected task is).
- // Display up to rows allowed by the layout, or less if reached end of database.
- get_visible_tasks_indices :: (db: Database) -> first_visible_index: int, last_visible_index: int {
- first_visible_index :=
- (db.selected_idx / layout_tasks_rows) * layout_tasks_rows;
-
- last_visible_index :=
- first_visible_index +
- (ifx layout_tasks_rows > db.tasks.count - first_visible_index
- then db.tasks.count - first_visible_index
- else layout_tasks_rows);
-
- return first_visible_index, last_visible_index;
- }
-
- get_day_index_from_layout_index :: inline (layout_index: int) -> int {
- return (layout_index + FIRST_DAY_OF_WEEK) % 7;
- }
-
- // Convert indices to allow using different days as the first-day-of-the-week.
- get_layout_index_from_day_index :: inline (day_index: int) -> int {
- return (day_index - FIRST_DAY_OF_WEEK + 7) % 7;
- }
-
+
auto_release_temp();
@@ -1119,7 +1117,7 @@ draw_user_interface :: (db: *Database, layout: *Layout, redraw_all: bool = true)
total_time = 0;
for 0..NUM_WEEK_DAYS-1 {
x += 1;
- day_idx := (it + FIRST_DAY_OF_WEEK) % NUM_WEEK_DAYS;
+ day_idx := get_day_index_from_layout_index(it);
column_width = layout.columns[L_DAYS_IDX + day_idx].width;
task_time := task.times[day_idx];
total_time = add(total_time, task_time);
@@ -1188,15 +1186,10 @@ free_memory :: () {
free(ar_file_path);
}
-read_input_string :: (x: int, y: int, input_limit: int, padding: int = 0) -> value: string, success: bool {
-
- // TODO Draw padding (at end of inputbox)... padding was renamed to input_width... is this the best name?
- // TODO Maybe add another optional arg with the placeholder text (to be preset on the input)?
- // TODO COULD CACHE... but there's not need...
-
+read_input_string :: (x: int, y: int, input_limit: int, input_width: int = 0) -> value: string, success: bool {
TUI.set_cursor_position(x + input_limit, y);
write_string(TUI.Commands.DrawingMode);
- for 1..padding {
+ for 1..input_width {
write_string(TUI.Drawings.Checkerboard);
}
write_string(TUI.Commands.TextMode);
@@ -1208,7 +1201,6 @@ read_input_string :: (x: int, y: int, input_limit: int, padding: int = 0) -> val
value, key := TUI.read_input_line(input_limit);
return value, key == TUI.Keys.Enter;
-
}
// Returns success.
@@ -1312,6 +1304,7 @@ main :: () {
"Usage: ttt [OPTION]... [FILE]...\n",
" -i, --import-csv [FILE] Import CSV file to database (discard first row).\n",
" -e, --export-csv [FILE] Export database to CSV file.\n",
+ " -s, --start-of-week [NUMBER] Set first day of week (0 = Sunday, 1 = Monday ...).\n",
" -n, --no-autosave Disable autosave feature (only save on exit).\n",
" -h, --help Display this help and exit.\n",
" -v, --version Output version information and exit.\n",
@@ -1411,6 +1404,16 @@ main :: () {
is_exit_requested = true;
continue;
}
+
+ if is_equal_to_any(args[it], "--start-of-week", "-s") {
+ it += 1;
+ if it >= args.count {
+ print_error("Missing number for starting day of week.");
+ exit(1);
+ }
+ first_day_of_week = parse_int(*args[it]);
+ continue;
+ }
if is_equal_to_any(args[it], "--no-autosave", "-n") {
is_autosave_enabled = false;
@@ -1422,8 +1425,7 @@ main :: () {
}
if is_exit_requested {
- // exit(0); // TODO fucking exit does not report memory leaks.
- return;
+ exit(0);
}
}
@@ -1649,7 +1651,7 @@ TUI.tui_print("Average % us (% / % : % bytes) ---------", dbg_average/1000, cont
// Apply changes.
time := cast(s64)input_time;
- day := (selected_day + FIRST_DAY_OF_WEEK) % NUM_WEEK_DAYS;
+ day := get_day_index_from_layout_index(selected_day);
if is_assign set_task_time(db, db.selected_idx, day, time);
else add_task_time(db, db.selected_idx, day, time);
@@ -1765,7 +1767,6 @@ TUI.tui_print("Average % us (% / % : % bytes) ---------", dbg_average/1000, cont
// Sort by.
case #char "s"; #through;
case #char "S";
- // TODO The initial part should only decide what's the sorting procedure... then we would would all in a single place.
TUI.using_style(action_style);
sort_by := prompt_user_key(selected_task_row, "Sort by (n) name, (1..7) day, or (t) total time.");
show_processing();
@@ -1789,8 +1790,8 @@ TUI.tui_print("Average % us (% / % : % bytes) ---------", dbg_average/1000, cont
case #char "5"; #through;
case #char "6"; #through;
case #char "7";
- sort_by_idx := sort_by - #char "1";
- day := (sort_by_idx + FIRST_DAY_OF_WEEK) % NUM_WEEK_DAYS;
+ sort_by_idx := cast(int)(sort_by - #char "1");
+ day := get_day_index_from_layout_index(sort_by_idx);
if day == {
case 0; sort_procedure = (x, y) => x.times[0] - y.times[0];
case 1; sort_procedure = (x, y) => x.times[1] - y.times[1];