Refactor logging code

* lisp/org.el (org-log-beginning): New function.
(org-ts-regexp-inactive): New variable.
(org-add-log-setup): Use new function.
(org-skip-over-state-notes): Make function more robust to
customization.
(org-store-log-note): Update function according to previous changes.
Small refactoring.
This commit is contained in:
Nicolas Goaziou 2014-10-28 13:51:36 +01:00
parent 95c2c7f38c
commit b8d8078368
1 changed files with 99 additions and 78 deletions

View File

@ -580,6 +580,10 @@ This works for both table types.")
(defconst org-ts-regexp "<\\([0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\} ?[^\r\n>]*?\\)>"
"Regular expression for fast time stamp matching.")
(defconst org-ts-regexp-inactive
"\\[\\([0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\} ?[^\r\n>]*?\\)\\]"
"Regular expression for fast inactive time stamp matching.")
(defconst org-ts-regexp-both "[[<]\\([0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\} ?[^]\r\n>]*?\\)[]>]"
"Regular expression for fast time stamp matching.")
@ -13510,6 +13514,50 @@ This is done in the same way as adding a state change note."
(interactive)
(org-add-log-setup 'note nil nil 'findpos nil))
(defun org-log-beginning (&optional create)
"Return expected start of log notes in current entry.
When optional argument CREATE is non-nil, the function creates
a drawer to store notes, if necessary. Returned position ignores
narrowing."
(org-with-wide-buffer
(org-back-to-heading t)
;; Skip planning info and property drawer.
(forward-line)
(when (org-looking-at-p org-planning-line-re) (forward-line))
(when (looking-at org-property-drawer-re)
(goto-char (match-end 0))
(forward-line))
(if (org-at-heading-p) (point)
(let ((end (save-excursion (outline-next-heading) (point)))
(drawer (cond ((stringp org-log-into-drawer) org-log-into-drawer)
(org-log-into-drawer "LOGBOOK"))))
(cond
(drawer
(let ((regexp (concat "^[ \t]*:" (regexp-quote drawer) ":[ \t]*$"))
(case-fold-search t))
(catch 'exit
;; Try to find existing drawer.
(while (re-search-forward regexp end t)
(let ((element (org-element-at-point)))
(when (eq (org-element-type element) 'drawer)
(let ((cend (org-element-property :contents-end element)))
(when (and (not org-log-states-order-reversed) cend)
(goto-char cend)))
(throw 'exit nil))))
;; No drawer found. Create one, if permitted.
(when create
(unless (bolp) (insert "\n"))
(let ((beg (point)))
(insert ":" drawer ":\n:END:\n")
(org-indent-region beg (point)))
(end-of-line -1)))))
(org-log-state-notes-insert-after-drawers
(while (and (looking-at org-drawer-regexp)
(progn (goto-char (match-end 0))
(re-search-forward org-property-end-re end t)))
(forward-line)))))
(if (bolp) (point) (line-beginning-position 2)))))
(defun org-add-log-setup (&optional purpose state prev-state findpos how extra)
"Set up the post command hook to take a note.
If this is about to TODO state change, the new state is expected in STATE.
@ -13517,64 +13565,42 @@ When FINDPOS is non-nil, find the correct position for the note in
the current entry. If not, assume that it can be inserted at point.
HOW is an indicator what kind of note should be created.
EXTRA is additional text that will be inserted into the notes buffer."
(let* ((org-log-into-drawer (org-log-into-drawer))
(drawer (cond ((stringp org-log-into-drawer) org-log-into-drawer)
(org-log-into-drawer "LOGBOOK"))))
(org-with-wide-buffer
(when findpos
(org-back-to-heading t)
;; Skip planning info and property drawer.
(forward-line)
(when (org-looking-at-p org-planning-line-re) (forward-line))
(when (looking-at org-property-drawer-re)
(goto-char (match-end 0))
(forward-line))
(let ((end (if (org-at-heading-p) (point)
(save-excursion (outline-next-heading) (point)))))
(cond
(drawer
(let ((regexp (concat "^[ \t]*:" (regexp-quote drawer) ":[ \t]*$"))
(case-fold-search t))
(catch 'exit
;; Try to find existing drawer.
(while (re-search-forward regexp end t)
(let ((element (org-element-at-point)))
(when (eq (org-element-type element) 'drawer)
(when (and (not org-log-states-order-reversed)
(org-element-property :contents-end element))
(goto-char (org-element-property :contents-end element)))
(throw 'exit nil))))
;; No drawer found. Create one.
(unless (bolp) (insert "\n"))
(let ((beg (point)))
(insert ":" drawer ":\n:END:\n")
(org-indent-region beg (point)))
(end-of-line -1))))
(org-log-state-notes-insert-after-drawers
(while (and (looking-at org-drawer-regexp)
(progn (goto-char (match-end 0))
(re-search-forward org-property-end-re end t)))
(forward-line)))))
(unless org-log-states-order-reversed
(and (= (char-after) ?\n) (forward-char 1))
(org-skip-over-state-notes)
(skip-chars-backward " \t\n\r")))
(move-marker org-log-note-marker (point))
(setq org-log-note-purpose purpose
org-log-note-state state
org-log-note-previous-state prev-state
org-log-note-how how
org-log-note-extra extra
org-log-note-effective-time (org-current-effective-time))
(add-hook 'post-command-hook 'org-add-log-note 'append))))
(org-with-wide-buffer
(when findpos
(goto-char (org-log-beginning t))
(unless org-log-states-order-reversed
(org-skip-over-state-notes)
(skip-chars-backward " \t\n\r")
(forward-line)))
(move-marker org-log-note-marker (point))
(setq org-log-note-purpose purpose
org-log-note-state state
org-log-note-previous-state prev-state
org-log-note-how how
org-log-note-extra extra
org-log-note-effective-time (org-current-effective-time))
(add-hook 'post-command-hook 'org-add-log-note 'append)))
(defun org-skip-over-state-notes ()
"Skip past the list of State notes in an entry."
(if (looking-at "\n[ \t]*- State") (forward-char 1))
(when (ignore-errors (goto-char (org-in-item-p)))
(let* ((struct (org-list-struct))
(prevs (org-list-prevs-alist struct)))
(while (looking-at "[ \t]*- State")
(prevs (org-list-prevs-alist struct))
(regexp
(concat "[ \t]*- +"
(replace-regexp-in-string
" +" " +"
(org-replace-escapes
(regexp-quote (cdr (assq 'state org-log-note-headings)))
`(("%d" . ,org-ts-regexp-inactive)
("%D" . ,org-ts-regexp)
("%s" . "\"\\S-+\"")
("%S" . "\"\\S-+\"")
("%t" . ,org-ts-regexp-inactive)
("%T" . ,org-ts-regexp)
("%u" . ".*?")
("%U" . ".*?")))))))
(while (org-looking-at-p regexp)
(goto-char (or (org-list-get-next-item (point) struct prevs)
(org-list-get-item-end (point) struct)))))))
@ -13622,8 +13648,7 @@ EXTRA is additional text that will be inserted into the notes buffer."
"Finish taking a log note, and insert it to where it belongs."
(let ((txt (buffer-string)))
(kill-buffer (current-buffer))
(let ((note (cdr (assq org-log-note-purpose org-log-note-headings)))
lines ind bul)
(let ((note (cdr (assq org-log-note-purpose org-log-note-headings))) lines)
(while (string-match "\\`# .*\n[ \t\n]*" txt)
(setq txt (replace-match "" t t txt)))
(if (string-match "\\s-+\\'" txt)
@ -13653,10 +13678,10 @@ EXTRA is additional text that will be inserted into the notes buffer."
(cons "%S" (if org-log-note-previous-state
(concat "\"" org-log-note-previous-state "\"")
"\"\"")))))
(if lines (setq note (concat note " \\\\")))
(when lines (setq note (concat note " \\\\")))
(push note lines))
(when (or current-prefix-arg org-note-abort)
(when org-log-into-drawer
(when (org-log-into-drawer)
(org-remove-empty-drawer-at org-log-note-marker))
(setq lines nil))
(when lines
@ -13664,28 +13689,24 @@ EXTRA is additional text that will be inserted into the notes buffer."
(save-excursion
(goto-char org-log-note-marker)
(move-marker org-log-note-marker nil)
(end-of-line 1)
(if (not (bolp)) (let ((inhibit-read-only t)) (insert "\n")))
(setq ind (save-excursion
(if (ignore-errors (goto-char (org-in-item-p)))
(let ((struct (org-list-struct)))
(org-list-get-ind
(org-list-get-top-point struct) struct))
(skip-chars-backward " \r\t\n")
(cond
((and (org-at-heading-p)
org-adapt-indentation)
(1+ (org-current-level)))
((org-at-heading-p) 0)
(t (org-get-indentation))))))
(setq bul (org-list-bullet-string "-"))
(org-indent-line-to ind)
(insert bul (pop lines))
(let ((ind-body (+ (length bul) ind)))
(while lines
;; Make sure point is at the beginning of an empty line.
(cond ((not (bolp)) (let ((inhibit-read-only t)) (insert "\n")))
((looking-at "[ \t]*\\S-") (save-excursion (insert "\n"))))
;; In an existing list, add a new item at the top level.
;; Otherwise, indent line like a regular one.
(let ((itemp (org-in-item-p)))
(if itemp
(org-indent-line-to
(let ((struct (save-excursion
(goto-char itemp) (org-list-struct))))
(org-list-get-ind (org-list-get-top-point struct) struct)))
(org-indent-line)))
(insert (org-list-bullet-string "-") (pop lines))
(let ((ind (org-list-item-body-column (line-beginning-position))))
(dolist (line lines)
(insert "\n")
(org-indent-line-to ind-body)
(insert (pop lines))))
(org-indent-line-to ind)
(insert line)))
(message "Note stored")
(org-back-to-heading t)
(org-cycle-hide-drawers 'children))