Advertisement
Guest User

Untitled

a guest
Oct 13th, 2018
139
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 13.25 KB | None | 0 0
  1. ;;main.lisp
  2.  
  3. (ql:quickload :inferior-shell)
  4. (ql:quickload :cl-store)
  5. (ql:quickload :parachute)
  6. (ql:quickload :postmodern)
  7.  
  8. (defpackage :todo
  9. (:use :cl :parachute :postmodern)
  10. (:export :select :complete :deselect :add-todo))
  11.  
  12. (in-package :todo)
  13.  
  14. (defun run-all-package-tests ()
  15. (test 'select-group-test)
  16. (test 'add-todo-test)
  17. (test 'find-todo-test)
  18. (test 'test-select))
  19.  
  20. (defun init ()
  21. (load "todo/globals.lisp")
  22. (load "todo/todo.lisp")
  23. (load "todo/todo-list.lisp")
  24. (load "todo/printing.lisp")
  25. (load "todo/api.lisp")
  26. (load "todo/storage.lisp")
  27. (load "todo/hooks.lisp"))
  28.  
  29. (init)
  30.  
  31. ;; 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
  32.  
  33.  
  34. ;;todo.lisp
  35.  
  36. (defclass todo ()
  37. ((description :accessor todo-description
  38. :initarg :description)
  39. (priority :accessor todo-priority
  40. :initarg :priority
  41. :initform 0)
  42. (groups :accessor todo-groups
  43. :initarg :groups
  44. :initform 0)
  45. (selected-duration :accessor todo-selected-duration
  46. :initarg :selected-duration
  47. :initform 0)
  48. (last-selected-time :accessor last-selected-time)
  49. (parent :accessor todo-parent
  50. :initarg :parent
  51. :initform nil)))
  52.  
  53.  
  54. (defun accumulate-work-time (the-todo)
  55. (let ((time-diff (- (get-universal-time) (last-selected-time the-todo))))
  56. (setf (todo-selected-duration the-todo)
  57. (+ (todo-selected-duration the-todo) time-diff))
  58. (if (not (null (todo-parent the-todo)))
  59. (setf (todo-selected-duration (todo-parent the-todo))
  60. (+ (todo-selected-duration
  61. (todo-parent the-todo))
  62. time-diff)))
  63.  
  64. (values (todo-selected-duration the-todo) time-diff)))
  65.  
  66.  
  67. (defun symbol-exists-p (sym)
  68. (fboundp sym))
  69.  
  70.  
  71. (defun todo->a-symbol-name (description)
  72. (reduce
  73. #'(lambda (str1 str2)
  74. (concatenate 'string str1 str2))
  75. (let ((x 0))
  76. (mapcar
  77. #'(lambda (to-be-sym)
  78. (if (= 0 x)
  79. (progn
  80. (incf x)
  81. (if (not (integerp to-be-sym))
  82. (if (listp to-be-sym)
  83. (todo->a-symbol-name to-be-sym)
  84. (symbol-name to-be-sym))
  85. (write-to-string to-be-sym)))
  86. (progn
  87. (incf x)
  88. (concatenate 'string "_" (if (not (integerp to-be-sym))
  89. (if (listp to-be-sym)
  90. (todo->a-symbol-name to-be-sym)
  91. (symbol-name to-be-sym))
  92. (write-to-string to-be-sym))))))
  93. description))))
  94.  
  95.  
  96. (defun make-todo-action-hook-symbol (action description)
  97. (intern (concatenate 'string "HOOK-" (string action)
  98. "-"
  99. (todo->a-symbol-name description))))
  100.  
  101.  
  102.  
  103. (defun todo-complete (the-todo)
  104. (let ((the-hook-sym
  105. (make-todo-action-hook-symbol 'complete
  106. (todo-description the-todo))))
  107. (if (symbol-exists-p the-hook-sym)
  108. (funcall (symbol-function the-hook-sym) the-todo))))
  109.  
  110. (defun todo-select (the-todo)
  111. (let ((the-hook-sym
  112. (make-todo-action-hook-symbol 'select
  113. (todo-description the-todo))))
  114. (if (symbol-exists-p the-hook-sym)
  115. (funcall (symbol-function the-hook-sym) the-todo))))
  116.  
  117. (defun add-todos (&optional (todos '()))
  118. ;;todos is a list of todos
  119. (loop for todo in todos
  120. do (add-todo todo)))
  121.  
  122. (defun say-selected-todo ()
  123. (let ((words (format nil "~a" (todo-description *selected-todo*))))
  124. (progn words nil)))
  125.  
  126.  
  127. ;;api.lisp
  128.  
  129. (in-package :todo)
  130.  
  131. (defun complete ()
  132. (let ((selected-todo *selected-todo*))
  133. (complete-todo *selected-todo*)
  134. (format t "You spent ~d seconds in total working on this todo~%"
  135. (todo-selected-duration selected-todo)))
  136. (save-and-redisplay))
  137.  
  138. (defun delete-selected ()
  139. (delete-todo *selected-todo*))
  140.  
  141. (defun select-group (group)
  142. (cond
  143. ((integerp group) (setf *selected-group* (nth group (current-groups))))
  144. ((symbolp group) (if (find group (current-groups)) (setf *selected-group* group)
  145. (error "That group doesn't exist")))
  146. (t (error "Group is not of type integer or symbol"))))
  147.  
  148. (define-test select-group-test
  149. (define-test select-group-by-integer-test
  150. (let ((*selected-group* nil))
  151. (select-group (- (length *group-list*) 3))
  152. (true (eq *selected-group* 'all))))
  153. (define-test select-group-symbol-test
  154. (let ((*selected-group* nil))
  155. (select-group 'all)
  156. (true (eq *selected-group* 'all))))
  157. (define-test select-group-error-test
  158. (fail (select-group "winning"))))
  159.  
  160. (defun deselect ()
  161. (multiple-value-bind (accumulated-time time-diff) (accumulate-work-time *selected-todo*)
  162. (format t "You just spent ~d seconds on this incomplete todo, for a total of ~d ~%" time-diff accumulated-time)
  163. (setf *selected-todo* nil)
  164. time-diff))
  165.  
  166. (defun select (&optional (index 0))
  167. (let ((todo (nth index (filter-todos-by-group *todo-list* *selected-group*))))
  168. (select-todo todo)
  169. (setf (last-selected-time todo) (get-universal-time))
  170. (say-selected-todo))
  171. (todos))
  172.  
  173. (define-test test-select
  174. (let ((*todo-list* '())
  175. (*selected-todo* nil))
  176. (add-todo '(test select))
  177. (select)
  178. (true (eq '(test select) (todo-description *selected-todo*)))
  179. (setf todo::*selected-todo* nil)
  180. (add-todo '(test select 2))
  181. (select 1)
  182. (true (eq '(test select) (todo-description *selected-todo*)))))
  183.  
  184. (defun todos ()
  185. (print-current-todo)
  186. (print-todo-list)
  187. (print-todo-menu))
  188.  
  189. (defun groups ()
  190. (print-current-groups))
  191.  
  192.  
  193. (defun add-group (group)
  194. (if (not (find group *group-list*))
  195. (progn (push group *group-list*)
  196. (save-groups))))
  197.  
  198.  
  199. (defun delete-group (group)
  200. (if (find group (groups-in-todo-list))
  201. (error "This group cannot be deleted because a live todo is in it"))
  202. (setf *group-list* (delete group *group-list*))
  203. (save-groups))
  204.  
  205.  
  206. ;;globals.lisp
  207.  
  208. (defparameter *todo-list* '())
  209. (defparameter *group-list* '(all daemon karl))
  210. (defparameter *selected-todo* nil)
  211. (defparameter *selected-group* 'all)
  212. (defparameter *global-save-file* "current.todo-list")
  213. (defparameter *morning-template* "todo/resources/morning.todos")
  214. (defparameter *work-template* "todo/resources/work.todos")
  215. (defparameter *sleep-template* "todo/sleep.todo-template")
  216. (defparameter *test-template* "todo/small.todo-template")
  217. (defparameter *global-group-file* "todo/groups.list")
  218.  
  219. ;; hooks.lisp
  220.  
  221. (ql:quickload :trivial-open-browser)
  222.  
  223. (in-package :todo)
  224.  
  225. (defun hook-complete-smile (the-todo)
  226. (format t "Please smile~%")
  227. (sleep 1)
  228. (loop for x from 0 to 3
  229. do (progn (format t "~a~%" x) (sleep 1)))
  230. (format t "Snap!!!!!~%"))
  231.  
  232. (defun www (url)
  233. (sb-thread:make-thread (lambda () (trivial-open-browser:open-browser url))))
  234.  
  235.  
  236. (defun hook-select-WRITE_DOWN_GOALS (the-todo)
  237. (www "https://www.deviantart.com/renny08/art/Avengers-About-Tony-Stark-303404558?offset=0"))
  238.  
  239.  
  240. (defun hook-complete-WRITE_DOWN_GOALS (the-todo)
  241. (www "https://www.deviantart.com/anna-kokoro/art/Cyborgs-78509781"))
  242.  
  243.  
  244. (defun hook-select-WRITE_SOME_CODE (the-todo)
  245. (www "http://www.lispworks.com/documentation/HyperSpec/Front/"))
  246.  
  247. (defun hook-select-DO_25_PUSHUPS (the-todo)
  248. (www "https://www.youtube.com/watch?v=2ajpEcD3qkE"))
  249.  
  250.  
  251. ;; printing.lisp
  252.  
  253. (defun print-current-todo ()
  254. (if *selected-todo*
  255. (format t "~a~%~%" (todo-description *selected-todo*))))
  256.  
  257. (defun print-todo-list ()
  258. (if *todo-list*
  259. (progn
  260. (format t "TODO List (~a):~%" *selected-group*)
  261. (loop for todo in (filter-todos-by-group *todo-list* *selected-group*)
  262. for i from 0 to (length *todo-list*)
  263. do (format t "~a) ~dXP: ~a ~%" i
  264. (todo-priority todo)
  265. (todo-description todo))))))
  266.  
  267. (defun print-current-groups ()
  268. (format t "-----<Groups>-----~%~%")
  269. (let ((current-groups (current-groups)))
  270. (loop for group in current-groups
  271. for i from 0 to (length current-groups)
  272. do (format t "~d) ~a~%" i group)))
  273.  
  274. (format t "~%-----</Groups>-----~%~%"))
  275.  
  276.  
  277. (defun print-current-groups ()
  278. (format t "-----<Groups>-----~%~%")
  279. (let ((current-groups (current-groups)))
  280. (loop for group in current-groups
  281. for i from 0 to (length current-groups)
  282. do (format t "~d) ~a~%" i group)))
  283.  
  284. (format t "~%-----</Groups>-----~%~%"))
  285.  
  286. (defun print-todo-menu ()
  287. (format t "~%----------------------------<COMMANDS>-----------------------------~%")
  288. (format t "SELECT <#> | COMPLETE | DESELECT | DELETE-SELECTED ~%")
  289. (format t "-------------------------------------------------------------------~%")
  290. (format t "GROUPS | SELECT-GROUP <#> | REMIND <#> <SEC> <MIN> <HOUR>")
  291. (format t "~%----------------------------<COMMANDS>-----------------------------~%~%"))
  292.  
  293.  
  294.  
  295.  
  296. ;;storage.lisp
  297.  
  298. (in-package :todo)
  299. (ql:quickload :postmodern)
  300. (ql:quickload :chirp)
  301.  
  302.  
  303.  
  304. (defun save-completed-todo (todo)
  305. (sb-thread:make-thread
  306. #'(lambda ()
  307. (chirp:statuses/update
  308. (format nil "~a" (todo-description todo)))))))
  309.  
  310.  
  311. ;; todo-list.lisp
  312.  
  313. (defun remove-nth (n list)
  314. (declare
  315. (type (integer 0) n)
  316. (type list list))
  317. (if (or (zerop n) (null list))
  318. (cdr list)
  319. (cons (car list) (remove-nth (1- n) (cdr list)))))
  320.  
  321. (defun save-groups (&optional (file-name *global-group-file*))
  322. (cl-store:store *group-list* file-name))
  323.  
  324. (defun load-groups (&optional (file-name *global-group-file*))
  325. (setf *group-list* (cl-store:restore file-name)))
  326.  
  327. (defun save-todos (&optional (file-name *global-save-file*))
  328. (cl-store:store *todo-list* file-name))
  329.  
  330. (defun save-and-redisplay ()
  331. (save-todos)
  332. (todos))
  333.  
  334. (defun delete-todos (&rest indicies)
  335. (loop for i in indicies do (setf *todo-list* (remove-nth i *todo-list*))))
  336.  
  337. (defun load-todos (&optional (file-name *global-save-file*))
  338. (setf *todo-list* (cl-store:restore file-name)))
  339.  
  340. (defun add-new-groups-to-group-list (groups)
  341. (loop for group in groups
  342. do (if (not (find group *group-list*))
  343. (add-group group))))
  344.  
  345. (defun push-todo-and-re-sort (todo-instance)
  346. (push todo-instance *todo-list*)
  347. (setf *todo-list* (sort-by-priority *todo-list*)))
  348.  
  349. (defun add-todo (item &key (priority 0) (todo-groups '()) (parent nil))
  350. (push 'all todo-groups)
  351. (if (not (eq *selected-group* 'all)) (push *selected-group* todo-groups))
  352. (add-new-groups-to-group-list todo-groups)
  353. (push-todo-and-re-sort
  354. (make-instance 'todo
  355. :description item
  356. :priority priority
  357. :groups todo-groups
  358. :parent (if (not (integerp parent))
  359. (find-todo parent)
  360. (nth parent
  361. (filter-todos-by-group *todo-list*
  362. *selected-group*)))))
  363. (save-and-redisplay))
  364.  
  365. (define-test add-todo-test
  366. (let ((*todo-list* '())
  367. (*group-list* '()))
  368. (add-todo '(all i do is test) :todo-groups '(test))
  369. (true (find 'test *group-list*))
  370. (true (= 1 (length *todo-list*)))))
  371.  
  372. (defun add-templated-todos (fname)
  373. (with-open-file (f fname :direction :input)
  374. (loop for todo in (read f)
  375. do (add-todo todo :priority 9001 :todo-groups '(templated))))
  376. (todos))
  377.  
  378. (defun sort-by-priority (l)
  379. (sort l
  380. (lambda (a b) (> (todo-priority a)
  381. (todo-priority b)))))
  382.  
  383. (defun complete-todo (item)
  384. (accumulate-work-time *selected-todo*)
  385. (save-completed-todo *selected-todo*)
  386. (todo-complete *selected-todo*)
  387. (setf *selected-todo* nil)
  388. (setf *todo-list*
  389. (delete item *todo-list* :test #'equal)))
  390.  
  391. (defun delete-todo (item)
  392. (setf *selected-todo* nil)
  393. (setf *todo-list*
  394. (delete item *todo-list* :test #'equal)))
  395.  
  396. (defun filter-todos-by-group (l g)
  397. (remove-if-not (lambda (t-d)
  398. (find g (todo-groups t-d)))
  399. l))
  400.  
  401. (defun current-groups () *group-list*)
  402.  
  403. (defun groups-in-todo-list ()
  404. (let ((current-groups '()))
  405. (loop for todo in *todo-list*
  406. do (loop for group in (todo-groups todo)
  407. do (setf current-groups
  408. (adjoin group current-groups))))
  409. current-groups))
  410.  
  411. (defun select-todo (item)
  412. (if (find item *todo-list* :test #'equal)
  413. (progn
  414. (setf *selected-todo* item)
  415. (todo-select *selected-todo*))
  416. (format t "Item does not exist in todo list")))
  417.  
  418. (defun find-todo (description)
  419. (find
  420. description
  421. *todo-list*
  422. :test
  423. #'(lambda (item todo)
  424. (if (equal item (todo-description todo)) t nil))))
  425.  
  426.  
  427. (define-test find-todo-test
  428. (let ((*todo-list* '()))
  429. (add-todo '(all i do is test))
  430. (true (equal
  431. '(all i do is test)
  432. (todo-description (find-todo '(all i do is test)))))
  433. (true (equal nil (find-todo '(this is not a todo))))))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement