Function: org-habit-parse-todo

org-habit-parse-todo is a byte-compiled function defined in org-habit.el.gz.

Signature

(org-habit-parse-todo &optional POM)

Documentation

Parse the TODO surrounding point for its habit-related data.

Returns a list with the following elements:

  0: Scheduled date for the habit (may be in the past)
  1: ".+"-style repeater for the schedule, in days
  2: Optional deadline (nil if not present)
  3: If deadline, the repeater for the deadline, otherwise nil
  4: A list of all the past dates this todo was mark closed
  5: Repeater type as a string

This list represents a "habit" for the rest of this module.

Source Code

;; Defined in /usr/src/emacs/lisp/org/org-habit.el.gz
(defun org-habit-parse-todo (&optional pom)
  "Parse the TODO surrounding point for its habit-related data.
Returns a list with the following elements:

  0: Scheduled date for the habit (may be in the past)
  1: \".+\"-style repeater for the schedule, in days
  2: Optional deadline (nil if not present)
  3: If deadline, the repeater for the deadline, otherwise nil
  4: A list of all the past dates this todo was mark closed
  5: Repeater type as a string

This list represents a \"habit\" for the rest of this module."
  (save-excursion
    (if pom (goto-char pom))
    (cl-assert (org-is-habit-p (point)))
    (let* ((scheduled (org-get-scheduled-time (point)))
	   (scheduled-repeat (org-get-repeat (org-entry-get (point) "SCHEDULED")))
	   (end (org-entry-end-position))
	   (habit-entry (org-no-properties (nth 4 (org-heading-components))))
	   closed-dates deadline dr-days sr-days sr-type)
      (if scheduled
	  (setq scheduled (time-to-days scheduled))
	(error "Habit %s has no scheduled date" habit-entry))
      (unless scheduled-repeat
	(error
	 "Habit `%s' has no scheduled repeat period or has an incorrect one"
	 habit-entry))
      (setq sr-days (org-habit-duration-to-days scheduled-repeat)
	    sr-type (progn (string-match "[\\.+]?\\+" scheduled-repeat)
			   (match-string-no-properties 0 scheduled-repeat)))
      (unless (> sr-days 0)
	(error "Habit %s scheduled repeat period is less than 1d" habit-entry))
      (when (string-match "/\\([0-9]+[dwmy]\\)" scheduled-repeat)
	(setq dr-days (org-habit-duration-to-days
		       (match-string-no-properties 1 scheduled-repeat)))
	(if (<= dr-days sr-days)
	    (error "Habit %s deadline repeat period is less than or equal to scheduled (%s)"
		   habit-entry scheduled-repeat))
	(setq deadline (+ scheduled (- dr-days sr-days))))
      (org-back-to-heading t)
      (let* ((maxdays (+ org-habit-preceding-days org-habit-following-days))
	     (reversed org-log-states-order-reversed)
	     (search (if reversed 're-search-forward 're-search-backward))
	     (limit (if reversed end (point)))
	     (count 0)
	     (re (format
		  "^[ \t]*-[ \t]+\\(?:State \"%s\".*%s%s\\)"
		  (regexp-opt org-done-keywords)
		  org-ts-regexp-inactive
		  (let ((value (cdr (assq 'done org-log-note-headings))))
		    (if (not value) ""
		      (concat "\\|"
			      (org-replace-escapes
			       (regexp-quote value)
			       `(("%d" . ,org-ts-regexp-inactive)
				 ("%D" . ,org-ts-regexp)
				 ("%s" . "\"\\S-+\"")
				 ("%S" . "\"\\S-+\"")
				 ("%t" . ,org-ts-regexp-inactive)
				 ("%T" . ,org-ts-regexp)
				 ("%u" . ".*?")
				 ("%U" . ".*?")))))))))
	(unless reversed (goto-char end))
	(while (and (< count maxdays) (funcall search re limit t))
	  (push (time-to-days
		 (org-time-string-to-time
		  (or (match-string-no-properties 1)
		      (match-string-no-properties 2))))
		closed-dates)
	  (setq count (1+ count))))
      (list scheduled sr-days deadline dr-days closed-dates sr-type))))