aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordam <dam@gudinoff>2023-04-18 01:29:19 +0100
committerdam <dam@gudinoff>2023-04-18 01:29:19 +0100
commit36c91454f2c5678bb648c23bcbc58feb12a006f7 (patch)
tree4c5405d995d14a9a873ee6c3ff51f2ff35020029
parentf0d4c9a424c2346da6209fad19dde88905cb012a (diff)
downloadtask-time-tracker-36c91454f2c5678bb648c23bcbc58feb12a006f7.tar.zst
task-time-tracker-36c91454f2c5678bb648c23bcbc58feb12a006f7.zip
Using task index instead of pointer on helper functions.
-rw-r--r--ttt.jai219
1 files changed, 99 insertions, 120 deletions
diff --git a/ttt.jai b/ttt.jai
index bc81901..68e4e50 100644
--- a/ttt.jai
+++ b/ttt.jai
@@ -41,6 +41,7 @@ DB_FILE_SIGN_STR :: "TTT:B:02";
ASSERT_NOT_NULL :: "Parameter '%' is null.";
ASSERT_NOT_EMPTY :: "Parameter '%' is empty.";
ASSERT_NOT_CONTAIN :: "'%' does not contain '%'.";
+ASSERT_INVALID_INDEX:: "Invalid index '%'.";
SECONDS_IN_MINUTE :: cast(s64)60;
SECONDS_IN_HOUR :: cast(s64)60*SECONDS_IN_MINUTE;
@@ -282,7 +283,10 @@ mvprintw_time :: (y: s32, x: s32, time: s64, space: s32) -> int { // BUG Setting
return mvprintw(y, x, "%*s%4.*fy%*s", left_padding, "", decimals, value, right_padding, "");
}
else {
- return mvprintw(y, x, "%*s ∞ %*s", left_padding, "", right_padding, "");
+ // TODO Solve unicode emoji gone wild.
+ //return mvprintw(y, x, "%*s ∞ %*s", left_padding, "", right_padding, "");
+ //return mvprintw(y, x, "%*s \xE2\x99\xBE %*s", left_padding, "", right_padding, "");
+ return mvprintw(y, x, "%*s inf %*s", left_padding, "", right_padding, "");
}
}
@@ -310,14 +314,11 @@ get_selected_task :: inline (db: Database) -> *Task {
return ifx db.selected_idx >= 0 then *db.tasks[db.selected_idx] else null;
}
-// TODO Add description.
-contains_task :: inline (db: Database, task: *Task) -> bool {
- return task >= db.tasks.data && task - db.tasks.data < db.tasks.count;
-}
+is_valid_index :: inline(db: Database, index: s64) -> bool { return index >= 0 && index < db.tasks.count; }
// Adds a task to the database and returns it.
// If necessary, expands database capacity.
-add_task :: (db: *Database, task: Task = .{}) -> task: *Task {
+add_task :: (db: *Database, task: Task = .{}) -> task: *Task, index: s64 {
assert(db != null, ASSERT_NOT_NULL, "db");
array_add(*db.tasks, task);
@@ -325,47 +326,46 @@ add_task :: (db: *Database, task: Task = .{}) -> task: *Task {
<<it = add_int64(<<it, task.times[it_index]);
}
- return *db.tasks[db.tasks.count-1];
+ idx := db.tasks.count-1;
+ return *db.tasks[idx], idx;
}
// Deletes task from database.
// If possible, shrinks the database capacity.
// Returns success.
-delete_task :: (db: *Database, task: *Task) -> bool {
+delete_task :: (using db: *Database, index: s64) -> bool { // TODO Maybe use `using db`.
assert(db != null, ASSERT_NOT_NULL, "db");
- assert(task != null, ASSERT_NOT_NULL, "task");
- assert(contains_task(db, task), ASSERT_NOT_CONTAIN, "db", "task");
+ assert(is_valid_index(db, index), ASSERT_INVALID_INDEX, index);
// Remove task timer values from total timers.
- for task.times {
- db.total_times[it_index] = sub_int64(db.total_times[it_index], it);
+ for tasks[index].times {
+ total_times[it_index] = sub_int64(total_times[it_index], it);
}
// Move tasks after the index position to their new positions.
- index := task - db.tasks.data;
- for index..db.tasks.count-2
- db.tasks[it] = db.tasks[it+1];
- db.tasks.count -= 1;
+ for index..tasks.count-2
+ tasks[it] = tasks[it+1];
+ tasks.count -= 1;
// Adjust selected task.
- if (db.selected_idx >= db.tasks.count) {
- db.selected_idx -= 1;
+ if (selected_idx >= tasks.count) {
+ selected_idx -= 1;
}
// Adjust active task.
- if (db.active_idx > index) {
- db.active_idx -= 1;
+ if (active_idx > index) {
+ active_idx -= 1;
}
- else if (db.active_idx == index) {
- db.active_idx = -1;
+ else if (active_idx == index) {
+ active_idx = -1;
}
// If possible, shrink database capacity.
// TODO Do we really want to make this fuss?
- current_capacity := db.tasks.allocated;
- if (db.tasks.count < (current_capacity >> 2)) {
- new_capacity := 1 << (get_msb(db.tasks.count) + 2);
- my_array_reserve_nonpoly(xx *db.tasks, new_capacity, SIZE_OF_TASK);
+ current_capacity := tasks.allocated;
+ if (tasks.count < (current_capacity >> 2)) {
+ new_capacity := 1 << (get_msb(tasks.count) + 2);
+ my_array_reserve_nonpoly(xx *tasks, new_capacity, SIZE_OF_TASK);
}
get_msb :: (value: s64) -> msb: s64, found: bool {
@@ -391,48 +391,42 @@ delete_task :: (db: *Database, task: *Task) -> bool {
return true;
}
-// Moves task to index.
-// Index gets clamped to [0, db->count[.
-move_task_to_index :: (db: *Database, task: *Task, index: s64) {
+// 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`
assert(db != null, ASSERT_NOT_NULL, "db");
- assert(task != null, ASSERT_NOT_NULL, "task");
- assert(contains_task(db, task), ASSERT_NOT_CONTAIN, "db", "task");
-
- target_index := clamp(index, 0, db.tasks.count-1);
- target_task := *db.tasks[target_index];
-
- if (target_task == task) return;
-
- // Move task to new location.
- temp_task := <<task;
- if target_task > task {
- //memmove(task, task + 1, (target_task - task) * SIZEOF_TASK_ST); TODO Maybe simplify this moves.
- offset := task - db.tasks.data;
- size := target_task - task;
- for 0..size-1
- db.tasks[offset + it] = db.tasks[offset + it + 1];
+
+ source = clamp(source, 0, db.tasks.count-1);
+ target = clamp(target, 0, db.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];
+ move_size := abs(target - source);
+
+ if target > source {
+ for 0..move_size-1
+ db.tasks[source + it] = db.tasks[source + it + 1];
}
else {
- //memmove(target_task + 1, target_task, (task - target_task) * SIZEOF_TASK_ST); TODO Maybe simplify this moves.
- offset := target_task - db.tasks.data;
- size := task - target_task;
- for < size-1..0
- db.tasks[offset + it + 1] = db.tasks[offset + it];
+ for < move_size-1..0
+ db.tasks[target + it + 1] = db.tasks[target + it];
}
- <<target_task = temp_task;
+
+ db.tasks[target] = temp_task;
// Adjust active and selected tasks.
- source_index := task - db.tasks.data;
- if (db.active_idx == source_index) {
- db.active_idx = target_index;
+ if (db.active_idx == source) {
+ db.active_idx = target;
}
- else if (source_index < db.active_idx && db.active_idx <= target_index) {
+ else if (source < db.active_idx && db.active_idx <= target) {
db.active_idx -= 1;
}
- else if (target_index <= db.active_idx && db.active_idx < source_index) {
+ else if (target <= db.active_idx && db.active_idx < source) {
db.active_idx += 1;
}
- db.selected_idx = target_index;
+ db.selected_idx = target;
}
// Updates the times on the active task (and adjusts database totals).
@@ -491,44 +485,41 @@ update_total_times :: (db: *Database) {
}
// Resets the times of the provided task (and adjusts database totals).
-reset_task_times :: (db: *Database, task: *Task) {
+reset_task_times :: (db: *Database, index: s64) {
assert(db != null, ASSERT_NOT_NULL, "db");
- assert(task != null, ASSERT_NOT_NULL, "task");
- assert(contains_task(db, task), ASSERT_NOT_CONTAIN, "db", "task");
+ assert(is_valid_index(db, index), ASSERT_INVALID_INDEX, index);
// Make sure we sync before applying the changes.
update_times(db);
- for * task.times {
+ for * db.tasks[index].times {
db.total_times[it_index] = sub_int64(db.total_times[it_index], <<it);
<<it = 0;
}
}
// Sets the time on the day and task provided (and adjusts database totals).
-set_task_time :: (db: *Database, task: *Task, day: int, time: s64) {
+set_task_time :: (db: *Database, index: s64, day: int, time: s64) {
assert(db != null, ASSERT_NOT_NULL, "db");
- assert(task != null, ASSERT_NOT_NULL, "task");
- assert(contains_task(db, task), ASSERT_NOT_CONTAIN, "db", "task");
+ assert(is_valid_index(db, index), ASSERT_INVALID_INDEX, index);
// Make sure we sync before applying the changes.
update_times(db);
- db.total_times[day] = add_int64(db.total_times[day], time - task.times[day]);
- task.times[day] = time;
+ db.total_times[day] = add_int64(db.total_times[day], time - db.tasks[index].times[day]);
+ db.tasks[index].times[day] = time;
}
// Adds the time on the day and task provided (and adjusts database totals).
-add_task_time :: (db: *Database, task: *Task, day: int, time: s64) {
+add_task_time :: (db: *Database, index: s64, day: int, time: s64) {
assert(db != null, ASSERT_NOT_NULL, "db");
- assert(task != null, ASSERT_NOT_NULL, "task");
- assert(contains_task(db, task), ASSERT_NOT_CONTAIN, "db", "task");
+ assert(is_valid_index(db, index), ASSERT_INVALID_INDEX, index);
// Make sure we sync before applying the changes.
update_times(db);
db.total_times[day] = add_int64(db.total_times[day], time);
- task.times[day] = add_int64(task.times[day], time);
+ db.tasks[index].times[day] = add_int64(db.tasks[index].times[day], time);
}
// Resets database to the initial state and deallocates all memory taken by tasks.
@@ -790,43 +781,28 @@ append_to_csv :: (task: Task, path: string) -> success: bool {
// Selects task by index.
// Index gets clamped to [0, db->count[.
-select_task_by_index :: (db: *Database, index: s64) {
+select_task :: (db: *Database, index: s64) {
assert(db != null, ASSERT_NOT_NULL, "db");
- db.selected_idx = ifx db.tasks.count == 0 then -1 else
- ifx index < 0 then 0 else
- ifx index >= db.tasks.count then db.tasks.count - 1 else
- index;
+ db.selected_idx = ifx db.tasks.count == 0 then -1 else clamp(index, 0, db.tasks.count-1);
}
// Selects task by delta relative to currently selected task.
select_task_by_delta :: (db: *Database, delta: s64) {
assert(db != null, ASSERT_NOT_NULL, "db");
- // TODO I bet there's a better way to do this... maybe use a clamp or range or something.
idx :=
ifx (delta > 0 && db.selected_idx > S64_MAX - delta) then S64_MAX else
ifx (delta < 0 && db.selected_idx < S64_MIN - delta) then S64_MIN else
db.selected_idx + delta;
- select_task_by_index(db, idx);
-}
-
-
-
-// Selects task.
-select_task :: (db: *Database, task: *Task) {
- assert(db != null, ASSERT_NOT_NULL, "db");
- assert(task != null, ASSERT_NOT_NULL, "task");
- assert(contains_task(db, task), ASSERT_NOT_CONTAIN, "db", "task");
- db.selected_idx = task - db.tasks.data;
+ select_task(db, idx);
}
// Set active task.
-// Passing task as NULL de-activates any previously active task.
-set_active_task :: (db: *Database, task: *Task) {
+// Passing -1 de-activates any previously active task.
+set_active_task :: (db: *Database, index: s64) {
assert(db != null, ASSERT_NOT_NULL, "db");
- if task != null
- assert(contains_task(db, task), ASSERT_NOT_CONTAIN, "db", "task");
+ assert(index == -1 || is_valid_index(db, index), ASSERT_INVALID_INDEX, index);
update_times(db);
- db.active_idx = ifx (task == null) then -1 else task - db.tasks.data;
+ db.active_idx = index;
}
// Returns true when database is full.
@@ -1377,17 +1353,23 @@ main :: () {
if key == #char "q" || key == #char "Q" break;
update_times(*database);
timeout(INPUT_AWAIT_INF);
-
- active_task := get_active_task(db);
+
+ // TODO WIP Remove `selected_task` and `active_task` and helper functions.
selected_task := get_selected_task(db);
- action_style := A_BOLD | COLOR_PAIR(xx ifx selected_task == active_task && selected_task != null
- then Styles.ACTIVE
- else Styles.SELECTED_INVERTED);
- error_style := A_BOLD | COLOR_PAIR(xx Styles.ERROR);
- selected_task_row : int = ifx is_terminal_too_small then 0
- else ifx (db.selected_idx < 0) then 1
- else (db.selected_idx % layout_tasks_rows) + NUM_HEADER_ROWS;
-
+ active_task := get_active_task(db);
+ action_style: s32;
+ error_style: s32;
+ selected_task_row: int;
+ { // TODO Recheck this code.
+ using db;
+ action_style = A_BOLD | COLOR_PAIR(xx
+ ifx selected_idx == active_idx && selected_idx != -1 then Styles.ACTIVE
+ else Styles.SELECTED_INVERTED);
+ error_style = A_BOLD | COLOR_PAIR(xx Styles.ERROR);
+ selected_task_row = ifx is_terminal_too_small then 0
+ else ifx (selected_idx < 0) then 1
+ else (selected_idx % layout_tasks_rows) + NUM_HEADER_ROWS;
+ }
if key == {
// When getch() times out.
@@ -1422,11 +1404,11 @@ main :: () {
now_utc := current_time_consensus();
now_local := to_calendar(now_utc, .LOCAL);
name := calendar_to_iso_string(now_local);
- new_task := add_task(db);
- memcpy(new_task.name.data, name.data, min(Task.name.count, name.count));
+ task, index := add_task(db);
+ memcpy(task.name.data, name.data, min(Task.name.count, name.count));
// Select new task.
- select_task(db, new_task);
+ select_task(db, index);
selected_task = get_selected_task(db);
trigger_autosave();
@@ -1449,7 +1431,7 @@ main :: () {
if (selected_task == null) continue;
if (read_enter_confirmation(selected_task_row, action_style, " Press enter to reset task. ") == true) {
- reset_task_times(db, selected_task);
+ reset_task_times(db, db.selected_idx);
trigger_autosave();
}
@@ -1457,7 +1439,7 @@ main :: () {
if (selected_task == null || selected_task == active_task) continue;
if (read_enter_confirmation(selected_task_row, action_style, " Press enter to delete task. ") == true) {
- delete_task(db, selected_task);
+ delete_task(db, db.selected_idx);
trigger_autosave();
}
@@ -1525,8 +1507,8 @@ main :: () {
// Apply changes.
time := cast(s64)input_time;
day := (selected_day + FIRST_DAY_OF_WEEK) % NUM_WEEK_DAYS;
- if is_assign set_task_time(db, selected_task, day, time);
- else add_task_time(db, selected_task, day, time);
+ if is_assign set_task_time(db, db.selected_idx, day, time);
+ else add_task_time(db, db.selected_idx, day, time);
trigger_autosave();
@@ -1536,9 +1518,7 @@ main :: () {
value, success := read_input_int(selected_task_row, action_style, " Move to: ");
if success == false continue;
-
- target_index := clamp(value, 1, MAX_DATABASE_TASKS) - 1;
- move_task_to_index(db, selected_task, target_index);
+ move_task(db, db.selected_idx, value-1); // -1 to adjust for zero based index
trigger_autosave();
case #char "g"; #through;
@@ -1547,9 +1527,8 @@ main :: () {
value, success := read_input_int(selected_task_row, action_style, " Go to: ");
if success == false continue;
-
target_index := clamp(value, 1, MAX_DATABASE_TASKS) - 1;
- select_task_by_index(db, target_index);
+ select_task(db, target_index);
case #char "d"; #through;
case #char "D";
@@ -1571,12 +1550,12 @@ main :: () {
case #char "t"; #through;
case #char "T";
if (active_task == null) continue;
- select_task(db, active_task);
+ select_task(db, db.active_idx);
case #char "\n"; #through;
case #char " ";
if (db != *database || selected_task == null) continue;
- set_active_task(db, ifx (active_task == selected_task) then null else selected_task);
+ 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();
@@ -1606,7 +1585,7 @@ main :: () {
print_error("Failed to archive entry.");
continue;
}
- delete_task(*database, selected_task);
+ delete_task(db, db.selected_idx);
trigger_autosave();
case #char "r"; #through;
@@ -1622,11 +1601,11 @@ main :: () {
print_error("Failed to restore entry.");
continue;
}
- delete_task(*archive, selected_task);
+ delete_task(db, db.selected_idx);
trigger_autosave();
case KEY_HOME;
- select_task_by_index(db, 0);
+ select_task(db, 0);
case KEY_UP;
select_task_by_delta(db, -1);
@@ -1635,7 +1614,7 @@ main :: () {
select_task_by_delta(db, -layout_tasks_rows);
case KEY_END;
- select_task_by_index(db, db.tasks.count-1);
+ select_task(db, db.tasks.count-1);
case KEY_DOWN;
select_task_by_delta(db, 1);