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