Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ;;main.lisp
- (ql:quickload :inferior-shell)
- (ql:quickload :cl-store)
- (ql:quickload :parachute)
- (ql:quickload :postmodern)
- (defpackage :todo
- (:use :cl :parachute :postmodern)
- (:export :select :complete :deselect :add-todo))
- (in-package :todo)
- (defun run-all-package-tests ()
- (test 'select-group-test)
- (test 'add-todo-test)
- (test 'find-todo-test)
- (test 'test-select))
- (defun init ()
- (load "todo/globals.lisp")
- (load "todo/todo.lisp")
- (load "todo/todo-list.lisp")
- (load "todo/printing.lisp")
- (load "todo/api.lisp")
- (load "todo/storage.lisp")
- (load "todo/hooks.lisp"))
- (init)
- ;; A way to integrate todo with the rest of alexandria is to provide a macro with-todos that dynamically lets *todo-list* to the todo
- ;;todo.lisp
- (defclass todo ()
- ((description :accessor todo-description
- :initarg :description)
- (priority :accessor todo-priority
- :initarg :priority
- :initform 0)
- (groups :accessor todo-groups
- :initarg :groups
- :initform 0)
- (selected-duration :accessor todo-selected-duration
- :initarg :selected-duration
- :initform 0)
- (last-selected-time :accessor last-selected-time)
- (parent :accessor todo-parent
- :initarg :parent
- :initform nil)))
- (defun accumulate-work-time (the-todo)
- (let ((time-diff (- (get-universal-time) (last-selected-time the-todo))))
- (setf (todo-selected-duration the-todo)
- (+ (todo-selected-duration the-todo) time-diff))
- (if (not (null (todo-parent the-todo)))
- (setf (todo-selected-duration (todo-parent the-todo))
- (+ (todo-selected-duration
- (todo-parent the-todo))
- time-diff)))
- (values (todo-selected-duration the-todo) time-diff)))
- (defun symbol-exists-p (sym)
- (fboundp sym))
- (defun todo->a-symbol-name (description)
- (reduce
- #'(lambda (str1 str2)
- (concatenate 'string str1 str2))
- (let ((x 0))
- (mapcar
- #'(lambda (to-be-sym)
- (if (= 0 x)
- (progn
- (incf x)
- (if (not (integerp to-be-sym))
- (if (listp to-be-sym)
- (todo->a-symbol-name to-be-sym)
- (symbol-name to-be-sym))
- (write-to-string to-be-sym)))
- (progn
- (incf x)
- (concatenate 'string "_" (if (not (integerp to-be-sym))
- (if (listp to-be-sym)
- (todo->a-symbol-name to-be-sym)
- (symbol-name to-be-sym))
- (write-to-string to-be-sym))))))
- description))))
- (defun make-todo-action-hook-symbol (action description)
- (intern (concatenate 'string "HOOK-" (string action)
- "-"
- (todo->a-symbol-name description))))
- (defun todo-complete (the-todo)
- (let ((the-hook-sym
- (make-todo-action-hook-symbol 'complete
- (todo-description the-todo))))
- (if (symbol-exists-p the-hook-sym)
- (funcall (symbol-function the-hook-sym) the-todo))))
- (defun todo-select (the-todo)
- (let ((the-hook-sym
- (make-todo-action-hook-symbol 'select
- (todo-description the-todo))))
- (if (symbol-exists-p the-hook-sym)
- (funcall (symbol-function the-hook-sym) the-todo))))
- (defun add-todos (&optional (todos '()))
- ;;todos is a list of todos
- (loop for todo in todos
- do (add-todo todo)))
- (defun say-selected-todo ()
- (let ((words (format nil "~a" (todo-description *selected-todo*))))
- (progn words nil)))
- ;;api.lisp
- (in-package :todo)
- (defun complete ()
- (let ((selected-todo *selected-todo*))
- (complete-todo *selected-todo*)
- (format t "You spent ~d seconds in total working on this todo~%"
- (todo-selected-duration selected-todo)))
- (save-and-redisplay))
- (defun delete-selected ()
- (delete-todo *selected-todo*))
- (defun select-group (group)
- (cond
- ((integerp group) (setf *selected-group* (nth group (current-groups))))
- ((symbolp group) (if (find group (current-groups)) (setf *selected-group* group)
- (error "That group doesn't exist")))
- (t (error "Group is not of type integer or symbol"))))
- (define-test select-group-test
- (define-test select-group-by-integer-test
- (let ((*selected-group* nil))
- (select-group (- (length *group-list*) 3))
- (true (eq *selected-group* 'all))))
- (define-test select-group-symbol-test
- (let ((*selected-group* nil))
- (select-group 'all)
- (true (eq *selected-group* 'all))))
- (define-test select-group-error-test
- (fail (select-group "winning"))))
- (defun deselect ()
- (multiple-value-bind (accumulated-time time-diff) (accumulate-work-time *selected-todo*)
- (format t "You just spent ~d seconds on this incomplete todo, for a total of ~d ~%" time-diff accumulated-time)
- (setf *selected-todo* nil)
- time-diff))
- (defun select (&optional (index 0))
- (let ((todo (nth index (filter-todos-by-group *todo-list* *selected-group*))))
- (select-todo todo)
- (setf (last-selected-time todo) (get-universal-time))
- (say-selected-todo))
- (todos))
- (define-test test-select
- (let ((*todo-list* '())
- (*selected-todo* nil))
- (add-todo '(test select))
- (select)
- (true (eq '(test select) (todo-description *selected-todo*)))
- (setf todo::*selected-todo* nil)
- (add-todo '(test select 2))
- (select 1)
- (true (eq '(test select) (todo-description *selected-todo*)))))
- (defun todos ()
- (print-current-todo)
- (print-todo-list)
- (print-todo-menu))
- (defun groups ()
- (print-current-groups))
- (defun add-group (group)
- (if (not (find group *group-list*))
- (progn (push group *group-list*)
- (save-groups))))
- (defun delete-group (group)
- (if (find group (groups-in-todo-list))
- (error "This group cannot be deleted because a live todo is in it"))
- (setf *group-list* (delete group *group-list*))
- (save-groups))
- ;;globals.lisp
- (defparameter *todo-list* '())
- (defparameter *group-list* '(all daemon karl))
- (defparameter *selected-todo* nil)
- (defparameter *selected-group* 'all)
- (defparameter *global-save-file* "current.todo-list")
- (defparameter *morning-template* "todo/resources/morning.todos")
- (defparameter *work-template* "todo/resources/work.todos")
- (defparameter *sleep-template* "todo/sleep.todo-template")
- (defparameter *test-template* "todo/small.todo-template")
- (defparameter *global-group-file* "todo/groups.list")
- ;; hooks.lisp
- (ql:quickload :trivial-open-browser)
- (in-package :todo)
- (defun hook-complete-smile (the-todo)
- (format t "Please smile~%")
- (sleep 1)
- (loop for x from 0 to 3
- do (progn (format t "~a~%" x) (sleep 1)))
- (format t "Snap!!!!!~%"))
- (defun www (url)
- (sb-thread:make-thread (lambda () (trivial-open-browser:open-browser url))))
- (defun hook-select-WRITE_DOWN_GOALS (the-todo)
- (www "https://www.deviantart.com/renny08/art/Avengers-About-Tony-Stark-303404558?offset=0"))
- (defun hook-complete-WRITE_DOWN_GOALS (the-todo)
- (www "https://www.deviantart.com/anna-kokoro/art/Cyborgs-78509781"))
- (defun hook-select-WRITE_SOME_CODE (the-todo)
- (www "http://www.lispworks.com/documentation/HyperSpec/Front/"))
- (defun hook-select-DO_25_PUSHUPS (the-todo)
- (www "https://www.youtube.com/watch?v=2ajpEcD3qkE"))
- ;; printing.lisp
- (defun print-current-todo ()
- (if *selected-todo*
- (format t "~a~%~%" (todo-description *selected-todo*))))
- (defun print-todo-list ()
- (if *todo-list*
- (progn
- (format t "TODO List (~a):~%" *selected-group*)
- (loop for todo in (filter-todos-by-group *todo-list* *selected-group*)
- for i from 0 to (length *todo-list*)
- do (format t "~a) ~dXP: ~a ~%" i
- (todo-priority todo)
- (todo-description todo))))))
- (defun print-current-groups ()
- (format t "-----<Groups>-----~%~%")
- (let ((current-groups (current-groups)))
- (loop for group in current-groups
- for i from 0 to (length current-groups)
- do (format t "~d) ~a~%" i group)))
- (format t "~%-----</Groups>-----~%~%"))
- (defun print-current-groups ()
- (format t "-----<Groups>-----~%~%")
- (let ((current-groups (current-groups)))
- (loop for group in current-groups
- for i from 0 to (length current-groups)
- do (format t "~d) ~a~%" i group)))
- (format t "~%-----</Groups>-----~%~%"))
- (defun print-todo-menu ()
- (format t "~%----------------------------<COMMANDS>-----------------------------~%")
- (format t "SELECT <#> | COMPLETE | DESELECT | DELETE-SELECTED ~%")
- (format t "-------------------------------------------------------------------~%")
- (format t "GROUPS | SELECT-GROUP <#> | REMIND <#> <SEC> <MIN> <HOUR>")
- (format t "~%----------------------------<COMMANDS>-----------------------------~%~%"))
- ;;storage.lisp
- (in-package :todo)
- (ql:quickload :postmodern)
- (ql:quickload :chirp)
- (defun save-completed-todo (todo)
- (sb-thread:make-thread
- #'(lambda ()
- (chirp:statuses/update
- (format nil "~a" (todo-description todo)))))))
- ;; todo-list.lisp
- (defun remove-nth (n list)
- (declare
- (type (integer 0) n)
- (type list list))
- (if (or (zerop n) (null list))
- (cdr list)
- (cons (car list) (remove-nth (1- n) (cdr list)))))
- (defun save-groups (&optional (file-name *global-group-file*))
- (cl-store:store *group-list* file-name))
- (defun load-groups (&optional (file-name *global-group-file*))
- (setf *group-list* (cl-store:restore file-name)))
- (defun save-todos (&optional (file-name *global-save-file*))
- (cl-store:store *todo-list* file-name))
- (defun save-and-redisplay ()
- (save-todos)
- (todos))
- (defun delete-todos (&rest indicies)
- (loop for i in indicies do (setf *todo-list* (remove-nth i *todo-list*))))
- (defun load-todos (&optional (file-name *global-save-file*))
- (setf *todo-list* (cl-store:restore file-name)))
- (defun add-new-groups-to-group-list (groups)
- (loop for group in groups
- do (if (not (find group *group-list*))
- (add-group group))))
- (defun push-todo-and-re-sort (todo-instance)
- (push todo-instance *todo-list*)
- (setf *todo-list* (sort-by-priority *todo-list*)))
- (defun add-todo (item &key (priority 0) (todo-groups '()) (parent nil))
- (push 'all todo-groups)
- (if (not (eq *selected-group* 'all)) (push *selected-group* todo-groups))
- (add-new-groups-to-group-list todo-groups)
- (push-todo-and-re-sort
- (make-instance 'todo
- :description item
- :priority priority
- :groups todo-groups
- :parent (if (not (integerp parent))
- (find-todo parent)
- (nth parent
- (filter-todos-by-group *todo-list*
- *selected-group*)))))
- (save-and-redisplay))
- (define-test add-todo-test
- (let ((*todo-list* '())
- (*group-list* '()))
- (add-todo '(all i do is test) :todo-groups '(test))
- (true (find 'test *group-list*))
- (true (= 1 (length *todo-list*)))))
- (defun add-templated-todos (fname)
- (with-open-file (f fname :direction :input)
- (loop for todo in (read f)
- do (add-todo todo :priority 9001 :todo-groups '(templated))))
- (todos))
- (defun sort-by-priority (l)
- (sort l
- (lambda (a b) (> (todo-priority a)
- (todo-priority b)))))
- (defun complete-todo (item)
- (accumulate-work-time *selected-todo*)
- (save-completed-todo *selected-todo*)
- (todo-complete *selected-todo*)
- (setf *selected-todo* nil)
- (setf *todo-list*
- (delete item *todo-list* :test #'equal)))
- (defun delete-todo (item)
- (setf *selected-todo* nil)
- (setf *todo-list*
- (delete item *todo-list* :test #'equal)))
- (defun filter-todos-by-group (l g)
- (remove-if-not (lambda (t-d)
- (find g (todo-groups t-d)))
- l))
- (defun current-groups () *group-list*)
- (defun groups-in-todo-list ()
- (let ((current-groups '()))
- (loop for todo in *todo-list*
- do (loop for group in (todo-groups todo)
- do (setf current-groups
- (adjoin group current-groups))))
- current-groups))
- (defun select-todo (item)
- (if (find item *todo-list* :test #'equal)
- (progn
- (setf *selected-todo* item)
- (todo-select *selected-todo*))
- (format t "Item does not exist in todo list")))
- (defun find-todo (description)
- (find
- description
- *todo-list*
- :test
- #'(lambda (item todo)
- (if (equal item (todo-description todo)) t nil))))
- (define-test find-todo-test
- (let ((*todo-list* '()))
- (add-todo '(all i do is test))
- (true (equal
- '(all i do is test)
- (todo-description (find-todo '(all i do is test)))))
- (true (equal nil (find-todo '(this is not a todo))))))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement