sacha-load.el 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. (defun sacha/org-show-load ()
  2. "Show my unscheduled time and free time for the day."
  3. (interactive)
  4. (let ((time (sacha/org-calculate-free-time
  5. ;; today
  6. (calendar-gregorian-from-absolute (time-to-days (current-time)))
  7. ;; now
  8. (let* ((now (decode-time))
  9. (cur-hour (nth 2 now))
  10. (cur-min (nth 1 now)))
  11. (+ (* cur-hour 60) cur-min))
  12. ;; until the last time in my time grid
  13. (let ((last (car (last (elt org-agenda-time-grid 2)))))
  14. (+ (* (/ last 100) 60) (% last 100))))))
  15. (message "%.1f%% load: %d minutes to be scheduled, %d minutes free, %d minutes gap\n"
  16. (/ (car time) (* .01 (cdr time)))
  17. (car time)
  18. (cdr time)
  19. (- (cdr time) (car time)))))
  20. (defun sacha/org-agenda-load (match)
  21. "Can be included in `org-agenda-custom-commands'."
  22. (let ((inhibit-read-only t)
  23. (time (sacha/org-calculate-free-time
  24. ;; today
  25. (calendar-gregorian-from-absolute org-starting-day)
  26. ;; now if today, else start of day
  27. (if (= org-starting-day
  28. (time-to-days (current-time)))
  29. (let* ((now (decode-time))
  30. (cur-hour (nth 2 now))
  31. (cur-min (nth 1 now)))
  32. (+ (* cur-hour 60) cur-min))
  33. (let ((start (car (elt org-agenda-time-grid 2))))
  34. (+ (* (/ start 100) 60) (% start 100))))
  35. ;; until the last time in my time grid
  36. (let ((last (car (last (elt org-agenda-time-grid 2)))))
  37. (+ (* (/ last 100) 60) (% last 100))))))
  38. (goto-char (point-max))
  39. (insert (format
  40. "%.1f%% load: %d minutes to be scheduled, %d minutes free, %d minutes gap\n"
  41. (/ (car time) (* .01 (cdr time)))
  42. (car time)
  43. (cdr time)
  44. (- (cdr time) (car time))))))
  45. (defun sacha/org-calculate-free-time (date start-time end-of-day)
  46. "Return a cons cell of the form (TASK-TIME . FREE-TIME) for DATE, given START-TIME and END-OF-DAY.
  47. DATE is a list of the form (MONTH DAY YEAR).
  48. START-TIME and END-OF-DAY are the number of minutes past midnight."
  49. (save-window-excursion
  50. (let ((files org-agenda-files)
  51. (total-unscheduled 0)
  52. (total-gap 0)
  53. file
  54. rtn
  55. rtnall
  56. entry
  57. (last-timestamp start-time)
  58. scheduled-entries)
  59. (while (setq file (car files))
  60. (catch 'nextfile
  61. (org-check-agenda-file file)
  62. (setq rtn (org-agenda-get-day-entries file date :scheduled :timestamp))
  63. (setq rtnall (append rtnall rtn)))
  64. (setq files (cdr files)))
  65. ;; For each item on the list
  66. (while (setq entry (car rtnall))
  67. (let ((time (get-text-property 1 'time entry)))
  68. (cond
  69. ((and time (string-match "\\([^-]+\\)-\\([^-]+\\)" time))
  70. (setq scheduled-entries (cons (cons
  71. (save-match-data (appt-convert-time (match-string 1 time)))
  72. (save-match-data (appt-convert-time (match-string 2 time))))
  73. scheduled-entries)))
  74. ((and time
  75. (string-match "\\([^-]+\\)\\.+" time)
  76. (string-match "^[A-Z]+ \\(\\[#[A-Z]\\]\\)? \\([0-9]+\\)" (get-text-property 1 'txt entry)))
  77. (setq scheduled-entries
  78. (let ((start (and (string-match "\\([^-]+\\)\\.+" time)
  79. (appt-convert-time (match-string 1 time)))))
  80. (cons (cons start
  81. (and (string-match "^[A-Z]+ \\(\\[#[A-Z]\\]\\)? \\([0-9]+\\) " (get-text-property 1 'txt entry))
  82. (+ start (string-to-number (match-string 2 (get-text-property 1 'txt entry))))))
  83. scheduled-entries))))
  84. ((string-match "^[A-Z]+ \\([0-9]+\\)" (get-text-property 1 'txt entry))
  85. (setq total-unscheduled (+ (string-to-number
  86. (match-string 1 (get-text-property 1 'txt entry)))
  87. total-unscheduled)))))
  88. (setq rtnall (cdr rtnall)))
  89. ;; Sort the scheduled entries by time
  90. (setq scheduled-entries (sort scheduled-entries (lambda (a b) (< (car a) (car b)))))
  91. (while scheduled-entries
  92. (let ((start (car (car scheduled-entries)))
  93. (end (cdr (car scheduled-entries))))
  94. (cond
  95. ;; are we in the middle of this timeslot?
  96. ((and (>= last-timestamp start)
  97. (< = last-timestamp end))
  98. ;; move timestamp later, no change to time
  99. (setq last-timestamp end))
  100. ;; are we completely before this timeslot?
  101. ((< last-timestamp start)
  102. ;; add gap to total, skip to the end
  103. (setq total-gap (+ (- start last-timestamp) total-gap))
  104. (setq last-timestamp end)))
  105. (setq scheduled-entries (cdr scheduled-entries))))
  106. (if (< last-timestamp end-of-day)
  107. (setq total-gap (+ (- end-of-day last-timestamp) total-gap)))
  108. (cons total-unscheduled total-gap))))