Function: org-clocktable-steps

org-clocktable-steps is a byte-compiled function defined in org-clock.el.gz.

Signature

(org-clocktable-steps PARAMS)

Documentation

Create one or more clock tables, according to PARAMS.

Step through the range specifications in plist PARAMS to make a number of clock tables.

Source Code

;; Defined in /usr/src/emacs/lisp/org/org-clock.el.gz
(defun org-clocktable-steps (params)
  "Create one or more clock tables, according to PARAMS.
Step through the range specifications in plist PARAMS to make
a number of clock tables."
  (let* ((ignore-empty-tables (plist-get params :stepskip0))
         (step (plist-get params :step))
         (step-header
          (pcase step
            (`day "Daily report: ")
            (`week "Weekly report starting on: ")
            (`semimonth "Semimonthly report starting on: ")
            (`month "Monthly report starting on: ")
            (`year "Annual report starting on: ")
            (`quarter "Quarterly report starting on: ")
            (_ (user-error "Unknown `:step' specification: %S" step))))
         (week-start (or (plist-get params :wstart) 1))
         (month-start (or (plist-get params :mstart) 1))
         (range
          (pcase (plist-get params :block)
            (`nil nil)
            (range
             (org-clock-special-range range nil t week-start month-start))))
         ;; For both START and END, any number is an absolute day
         ;; number from Agenda.  Otherwise, consider value to be an Org
         ;; timestamp string.  The `:block' property has precedence
         ;; over `:tstart' and `:tend'.
         (start
          (pcase (if range (car range) (plist-get params :tstart))
            ((and (pred numberp) n)
             (pcase-let ((`(,m ,d ,y) (calendar-gregorian-from-absolute n)))
               (org-encode-time 0 0 org-extend-today-until d m y)))
            (timestamp
	     (seconds-to-time
	      (org-matcher-time (or timestamp
				    ;; The year Org was born.
				    "<2003-01-01 Thu 00:00>"))))))
         (end
          (pcase (if range (nth 1 range) (plist-get params :tend))
            ((and (pred numberp) n)
             (pcase-let ((`(,m ,d ,y) (calendar-gregorian-from-absolute n)))
               (org-encode-time 0 0 org-extend-today-until d m y)))
            (timestamp (seconds-to-time (org-matcher-time timestamp))))))
    (while (time-less-p start end)
      (unless (bolp) (insert "\n"))
      ;; Insert header before each clock table.
      (insert "\n"
              step-header
              (format-time-string (org-time-stamp-format nil t) start)
	      "\n")
      ;; Compute NEXT, which is the end of the current clock table,
      ;; according to step.
      (let* ((next
              ;; In Emacs-27 and Emacs-28 `encode-time' does not support 6 elements
              ;; list argument so `org-encode-time' can not be outside of `pcase'.
              (pcase-let
                  ((`(,_ ,_ ,_ ,d ,m ,y ,dow . ,_) (decode-time start)))
                (pcase step
                  (`day (org-encode-time 0 0 org-extend-today-until (1+ d) m y))
                  (`week
                   (let ((offset (if (= dow week-start) 7
                                   (mod (- week-start dow) 7))))
                     (org-encode-time 0 0 org-extend-today-until (+ d offset) m y)))
                  (`semimonth (org-encode-time 0 0 0
                                               (if (< d 16) 16 1)
                                               (if (< d 16) m (1+ m)) y))
                  (`month (org-encode-time 0 0 0 month-start (1+ m) y))
                  (`quarter (org-encode-time 0 0 0 month-start (+ 3 m) y))
                  (`year (org-encode-time 0 0 org-extend-today-until 1 1 (1+ y))))))
             (table-begin (line-beginning-position 0))
	     (step-time
              ;; Write clock table between START and NEXT.
	      (org-dblock-write:clocktable
	       (org-combine-plists
                params (list :header ""
                             :step nil
                             :block nil
                             :tstart (format-time-string
                                      (org-time-stamp-format t t)
                                      start)
                             :tend (format-time-string
                                    (org-time-stamp-format t t)
                                    ;; Never include clocks past END.
                                    (if (time-less-p end next) end next)))))))
	(let ((case-fold-search t)) (re-search-forward "^[ \t]*#\\+END:"))
	;; Remove the table if it is empty and `:stepskip0' is
	;; non-nil.
	(when (and ignore-empty-tables (equal step-time 0))
	  (delete-region (line-beginning-position) table-begin))
        (setq start next))
      (end-of-line 0))))