C and Python API + Smarter account-based wait times
This commit is contained in:
1 parent
35c568333d
commit
10badb282c
18 files changed
+2204
-429
No files matched your search
@@ -16,6 +16,10 @@ installed; otherwise CMake downloads the amalgamation (needs network once).
|
||||
cmake --build build
|
||||
./build/lls [database-file] # default: tasks.db
|
||||
|
||||
This builds three things: the prompt (`lls`), the C API as a shared library
|
||||
(`liblls_api.so` / `lls_api.dll`, header `include/lls_api.h`) and a C example
|
||||
(`lls_example`).
|
||||
|
||||
## Commands
|
||||
|
||||
acc add <name> tsk add <name> [acc] [status]
|
||||
@@ -93,6 +97,11 @@ goes back to `$VISUAL` / `$EDITOR` / nano / vim / vi. The choice is stored in
|
||||
Uploading ones) is listed in the account row as `(wait HH:MM)` or
|
||||
`(limit reset)` and keeps the account Busy. Tasks without an account keep
|
||||
their own wait.
|
||||
* Auto unwait: once an account's limit has reset (its tasks show `Limit reset`),
|
||||
explicitly setting a task on it to `testing` or `prompt` (`tsk add <task> <acc>
|
||||
testing`, `tsk restat <task> testing`) clears that finished wait, because the
|
||||
account is in use again. Adding a task without a status does not, and a wait
|
||||
that is still running is never cleared automatically (use `acc unwait`).
|
||||
* A time is only optional while the account is already waiting: then
|
||||
`tsk restat <task> wait` (or `tsk add <task> <acc> wait`) just makes the task
|
||||
follow that wait. Otherwise (no account, or its wait is over) a time is
|
||||
@@ -101,7 +110,78 @@ goes back to `$VISUAL` / `$EDITOR` / nano / vim / vi. The choice is stored in
|
||||
* Names are case-insensitive; the original spelling is kept.
|
||||
* Notes live in the database (SQLite TEXT, binary-safe, SQLite's default limit is ~1 GB). The task table shows `-` when a task has no notes, otherwise the number of lines (e.g. `3 lines`); open them with `tsk notes <name>`.
|
||||
|
||||
## C API and Python
|
||||
|
||||
`include/lls_api.h` is a plain C API over the same database and the same rules
|
||||
as the prompt (it is built on the same `Tracker` class), so a program written
|
||||
against it behaves exactly like typing the commands. Build it with the project
|
||||
(`liblls_api.so`), link against it from C/C++, or load it from Python.
|
||||
|
||||
#include "lls_api.h"
|
||||
|
||||
lls_db* db;
|
||||
if (lls_open("tasks.db", &db) != LLS_OK) { /* lls_last_error(NULL) */ }
|
||||
|
||||
lls_account_add(db, "Acrux");
|
||||
lls_task_add(db, "Breeze A", "Acrux", "testing");
|
||||
lls_account_set_wait(db, "Acrux", "4:30pm"); /* the account hit its limit */
|
||||
|
||||
lls_task_list* tasks;
|
||||
lls_tasks(db, &tasks); /* display order */
|
||||
for (int i = 0; i < lls_task_list_count(tasks); ++i) {
|
||||
const lls_task_info* t = lls_task_list_get(tasks, i);
|
||||
printf("%s %s\n", t->name, t->status_label); /* "Breeze A Wait 16:30" */
|
||||
}
|
||||
lls_task_list_free(tasks);
|
||||
|
||||
lls_save(db); /* nothing is saved automatically */
|
||||
lls_close(db);
|
||||
|
||||
* Every call that can fail returns `LLS_OK` or an error code (`LLS_E_INVALID`,
|
||||
`LLS_E_NOT_FOUND`, `LLS_E_EXISTS`, `LLS_E_DATABASE`) with the message in
|
||||
`lls_last_error(db)`. No C++ exception crosses the API.
|
||||
* After a change, `lls_last_messages(db)` holds what the prompt would have
|
||||
printed ("Account 'A' is back in use: ..."). Queries do not reset it.
|
||||
* Statuses are the text you would type: `"prompt"`, `"testing"`, `"wait 4:30pm"`,
|
||||
`"wait"` (only while the account is waiting)... Waits belong to the account.
|
||||
* `lls_tasks` / `lls_accounts` return lists in the order of the panels, with the
|
||||
computed status (`status`, `status_label`, `until`) and the stored one underneath
|
||||
(`stored_status`). Strings in a list are valid until `lls_task_list_free`.
|
||||
* `lls_set_clock(db, unix_seconds)` pretends it is another time, handy for
|
||||
tests and simulations; 0 goes back to the real clock.
|
||||
* A `lls_db` must not be shared between threads without your own locking.
|
||||
|
||||
`python/lls.py` is a ctypes binding (no compiler needed):
|
||||
|
||||
import lls # python/ is on sys.path; LLS_LIBRARY=build/liblls_api.so
|
||||
|
||||
with lls.Database("tasks.db") as db:
|
||||
db.add_account("Acrux")
|
||||
db.add_task("Breeze A", account="Acrux", status="testing")
|
||||
db.set_account_wait("Acrux", "4:30pm")
|
||||
for task in db.tasks():
|
||||
print(task.name, task.account, task.status_label, task.until)
|
||||
for account in db.accounts():
|
||||
print(account.name, account.level.name, account.tasks)
|
||||
print(db.messages)
|
||||
db.save()
|
||||
|
||||
Errors are exceptions (`lls.NotFound`, `lls.AlreadyExists`, `lls.InvalidArgument`,
|
||||
`lls.DatabaseError`, all `lls.LLSError`). The library is found through the
|
||||
`LLS_LIBRARY` environment variable, `../build` next to the module, or the
|
||||
current directory's `build`. Run the tests with
|
||||
|
||||
LLS_LIBRARY=build/liblls_api.so python3 python/test_lls.py -v
|
||||
|
||||
## Layout
|
||||
|
||||
include/ headers (declarations only, no inline definitions)
|
||||
src/ implementations
|
||||
include/ headers (declarations only, no inline definitions); lls_api.h is the public C header
|
||||
src/ implementations
|
||||
examples/ example.c - the C API from C
|
||||
python/ lls.py (ctypes binding) and test_lls.py
|
||||
|
||||
Core (static library, shared by the prompt and the C API):
|
||||
Database SQLite storage Tracker all the rules; the only thing that changes data
|
||||
Status statuses, times Views computed task / account views and their order
|
||||
Prompt only: Repl, LineEditor, Completer, Display, Table, Config, ExternalEditor...
|
||||
C API: capi.cpp (wraps Tracker + Views)
|
||||
Reference in new issue
Block a user