diff options
-rw-r--r-- | gnosis.el | 218 |
1 files changed, 35 insertions, 183 deletions
@@ -45,6 +45,7 @@ (require 'gnosis-algorithm) (require 'gnosis-string-edit) +(require 'gnosis-dashboard) (require 'animate) @@ -136,9 +137,6 @@ a string describing the action." (defvar gnosis-testing nil "When t, warn user he is in a testing environment.") -(defvar gnosis-dashboard-note-ids nil - "Store note ids for dashboard.") - (defconst gnosis-db-version 3 "Gnosis database version.") @@ -1366,6 +1364,40 @@ provided, use it as the default value." (setf gnosis-previous-note-tags tags) (if (equal tags '("")) '("untagged") tags))) +;; Collecting note ids + +;; TODO: Rewrite. Tags should be an input of strings, interactive +;; handling should be done by "helper" funcs +(cl-defun gnosis-collect-note-ids (&key (tags nil) (due nil) (deck nil) (query nil)) + "Return list of note ids based on TAGS, DUE, DECKS, QUERY. + +TAGS: boolean value, t to specify tags. +DUE: boolean value, t to specify due notes. +DECK: Integer, specify deck id. +QUERY: String value," + (cl-assert (and (booleanp due) (booleanp tags) (or (numberp deck) (null deck)) (or (stringp query) (null query))) + nil "Incorrect value passed to `gnosis-collect-note-ids'") + (cond ((and (null tags) (null due) (null deck) (null query)) + (gnosis-select 'id 'notes '1=1 t)) + ;; All due notes + ((and (null tags) due (null deck)) + (gnosis-review-get-due-notes)) + ;; All notes for tags + ((and tags (null due) (null deck)) + (gnosis-select-by-tag (gnosis-tag-prompt))) + ;; All due notes for tags + ((and tags due (null deck)) + (gnosis-select-by-tag (gnosis-tag-prompt) t)) + ;; All notes for deck + ((and (null tags) (null due) deck) + (gnosis-get-deck-notes deck nil)) + ;; All due notes for deck + ((and (null tags) deck due) + (gnosis-get-deck-notes deck t)) + ;; Query + ((and (null tags) (null due) (null deck) query) + (gnosis-search-note query)))) + ;; Review ;;;;;;;;;; (defun gnosis-review-is-due-p (note-id) @@ -2112,186 +2144,6 @@ Return note ids for notes that match QUERY." words)))) (gnosis-select 'id 'notes clause t))) -;; Dashboard - -(defun gnosis-dashboard-output-note (id) - "Output contents for note with ID, formatted for gnosis dashboard." - (cl-loop for item in (append (gnosis-select '[main options answer tags type] 'notes `(= id ,id) t) - (gnosis-select 'suspend 'review-log `(= id ,id) t)) - if (listp item) - collect (mapconcat #'identity item ",") - else - collect (replace-regexp-in-string "\n" " " (format "%s" item)))) - -;; TODO: Rewrite. Tags should be an input of strings, interactive -;; handling should be done by "helper" funcs -(cl-defun gnosis-collect-note-ids (&key (tags nil) (due nil) (deck nil) (query nil)) - "Return list of note ids based on TAGS, DUE, DECKS, QUERY. - -TAGS: boolean value, t to specify tags. -DUE: boolean value, t to specify due notes. -DECK: Integer, specify deck id. -QUERY: String value," - (cl-assert (and (booleanp due) (booleanp tags) (or (numberp deck) (null deck)) (or (stringp query) (null query))) - nil "Incorrect value passed to `gnosis-collect-note-ids'") - (cond ((and (null tags) (null due) (null deck) (null query)) - (gnosis-select 'id 'notes '1=1 t)) - ;; All due notes - ((and (null tags) due (null deck)) - (gnosis-review-get-due-notes)) - ;; All notes for tags - ((and tags (null due) (null deck)) - (gnosis-select-by-tag (gnosis-tag-prompt))) - ;; All due notes for tags - ((and tags due (null deck)) - (gnosis-select-by-tag (gnosis-tag-prompt) t)) - ;; All notes for deck - ((and (null tags) (null due) deck) - (gnosis-get-deck-notes deck nil)) - ;; All due notes for deck - ((and (null tags) deck due) - (gnosis-get-deck-notes deck t)) - ;; Query - ((and (null tags) (null due) (null deck) query) - (gnosis-search-note query)))) - -(defun gnosis-dashboard-output-notes (note-ids) - "Return NOTE-IDS contents on gnosis dashboard." - (cl-assert (listp note-ids) t "`note-ids' must be a list of note ids.") - (pop-to-buffer "*gnosis-dashboard*") - (gnosis-dashboard-mode) - (setf tabulated-list-format `[("Main" ,(/ (window-width) 4) t) - ("Options" ,(/ (window-width) 6) t) - ("Answer" ,(/ (window-width) 6) t) - ("Tags" ,(/ (window-width) 5) t) - ("Type" ,(/ (window-width) 10) T) - ("Suspend" ,(/ (window-width) 6) t)] - tabulated-list-entries (cl-loop for id in note-ids - for output = (gnosis-dashboard-output-note id) - when output - collect (list (number-to-string id) (vconcat output))) - gnosis-dashboard-note-ids note-ids) - (tabulated-list-init-header) - ;; Keybindings, for editing, suspending, deleting notes. - ;; We use `local-set-key' to bind keys to the buffer to avoid - ;; conflicts when using the dashboard for displaying either notes - ;; or decks. - (local-set-key (kbd "e") #'gnosis-dashboard-edit-note) - (local-set-key (kbd "s") #'(lambda () (interactive) - (gnosis-suspend-note (string-to-number (tabulated-list-get-id))) - (gnosis-dashboard-output-notes gnosis-dashboard-note-ids) - (revert-buffer t t t))) - (local-set-key (kbd "a") #'gnosis-add-note) - (local-set-key (kbd "r") #'gnosis-dashboard) - (local-set-key (kbd "d") #'(lambda () (interactive) - (gnosis-delete-note (string-to-number (tabulated-list-get-id))) - (gnosis-dashboard-output-notes gnosis-dashboard-note-ids) - (revert-buffer t t t))) - (local-unset-key (kbd "RET"))) - -(defun gnosis-dashboard-deck-note-count (id) - "Return total note count for deck with ID." - (let ((note-count (caar (emacsql gnosis-db (format "SELECT COUNT(*) FROM notes WHERE deck_id=%s" id))))) - (when (gnosis-select 'id 'decks `(= id ,id)) - (list (number-to-string note-count))))) - -(defun gnosis-dashboard-output-deck (id) - "Output contents from deck with ID, formatted for gnosis dashboard." - (cl-loop for item in (append (gnosis-select - '[name failure-factor ef-increase ef-decrease ef-threshold initial-interval] - 'decks `(= id ,id) t) - (mapcar 'string-to-number (gnosis-dashboard-deck-note-count id))) - when (listp item) - do (cl-remove-if (lambda (x) (and (vectorp x) (zerop (length x)))) item) - collect (format "%s" item))) - -(defun gnosis-dashboard-output-decks () - "Return deck contents for gnosis dashboard." - (pop-to-buffer "*gnosis-dashboard*") - (gnosis-dashboard-mode) - (setq tabulated-list-format [("Name" 15 t) - ("failure-factor" 15 t) - ("ef-increase" 15 t) - ("ef-decrease" 15 t) - ("ef-threshold" 15 t) - ("Initial Interval" 20 t) - ("Total Notes" 10 t)]) - (tabulated-list-init-header) - (setq tabulated-list-entries - (cl-loop for id in (gnosis-select 'id 'decks '1=1 t) - for output = (gnosis-dashboard-output-deck id) - when output - collect (list (number-to-string id) (vconcat output)))) - (local-set-key (kbd "e") #'gnosis-dashboard-edit-deck) - (local-set-key (kbd "a") #'(lambda () "Add deck & refresh" (interactive) - (gnosis-add-deck (read-string "Deck name: ")) - (gnosis-dashboard-output-decks) - (revert-buffer t t t))) - (local-set-key (kbd "s") #'(lambda () "Suspend notes" (interactive) - (gnosis-suspend-deck - (string-to-number (tabulated-list-get-id))) - (gnosis-dashboard-output-decks) - (revert-buffer t t t))) - (local-set-key (kbd "d") #'(lambda () "Delete deck" (interactive) - (gnosis-delete-deck (string-to-number (tabulated-list-get-id))) - (gnosis-dashboard-output-decks) - (revert-buffer t t t))) - (local-set-key (kbd "RET") #'(lambda () "View notes of deck" (interactive) - (gnosis-dashboard "notes" - (gnosis-collect-note-ids - :deck (string-to-number (tabulated-list-get-id))))))) - -(defun gnosis-dashboard-edit-note (&optional dashboard) - "Get note id from tabulated list and edit it. - -DASHBOARD: Dashboard to return to after editing." - (interactive) - (let ((id (tabulated-list-get-id)) - (dashboard (or dashboard "notes"))) - (gnosis-edit-note (string-to-number id) nil dashboard) - (message "Editing note with id: %s" id))) - -(defun gnosis-dashboard-edit-deck () - "Get deck id from tabulated list and edit it." - (interactive) - (let ((id (tabulated-list-get-id))) - (gnosis-edit-deck (string-to-number id)))) - -(defvar-keymap gnosis-dashboard-mode-map - :doc "gnosis-dashboard keymap" - "q" #'quit-window) - -(define-derived-mode gnosis-dashboard-mode tabulated-list-mode "Gnosis Dashboard" - "Major mode for displaying Gnosis dashboard." - :keymap gnosis-dashboard-mode-map - (setq tabulated-list-padding 2 - tabulated-list-sort-key nil)) - -;;;###autoload -(cl-defun gnosis-dashboard (&optional dashboard-type (note-ids nil)) - "Display gnosis dashboard. - -NOTE-IDS: List of note ids to display on dashboard. When nil, prompt -for dashboard type. - -DASHBOARD-TYPE: either 'Notes' or 'Decks' to display the respective dashboard." - (interactive) - (let ((dashboard-type (or dashboard-type - (cadr (read-multiple-choice - "Display dashboard for:" - '((?n "notes") - (?d "decks") - (?t "tags") - (?s "search"))))))) - (if note-ids (gnosis-dashboard-output-notes note-ids) - (pcase dashboard-type - ("notes" (gnosis-dashboard-output-notes (gnosis-collect-note-ids))) - ("decks" (gnosis-dashboard-output-decks)) - ("tags" (gnosis-dashboard-output-notes (gnosis-collect-note-ids :tags t))) - ("search" (gnosis-dashboard-output-notes - (gnosis-collect-note-ids :query (read-string "Search for note: ")))))) - (tabulated-list-print t))) - (defun gnosis-db-init () "Create gnosis essential directories & database." (let ((gnosis-curr-version (caar (emacsql gnosis-db (format "PRAGMA user_version"))))) |