Descend into sublists when searching for first open checkbox
This commit is contained in:
parent
21f5988d6a
commit
4a1509981b
@ -1356,7 +1356,7 @@ inserting the checklist."
|
|||||||
nil
|
nil
|
||||||
'region))
|
'region))
|
||||||
|
|
||||||
(db/org-goto-first-open-checkbox-in-subtree)))))
|
(db/org-goto-first-open-checkbox-in-headline)))))
|
||||||
|
|
||||||
(define-obsolete-function-alias 'db/org-copy-template
|
(define-obsolete-function-alias 'db/org-copy-template
|
||||||
'db/org-insert-checklist
|
'db/org-insert-checklist
|
||||||
@ -1429,45 +1429,75 @@ inserted template."
|
|||||||
(looking-at (rx bol (* space) eol)))
|
(looking-at (rx bol (* space) eol)))
|
||||||
(insert "\n"))))
|
(insert "\n"))))
|
||||||
|
|
||||||
(defun db/org-goto-first-open-checkbox-in-subtree (&optional silent)
|
(defun db/org-goto-first-open-checkbox-in-headline (&optional silent)
|
||||||
"Jump to first open checkbox in the current subtree.
|
"Go to first open checkbox in the current subtree.
|
||||||
|
|
||||||
First search for started checkboxes, i.e. [-], and if those are
|
First search for started checkboxes, i.e. [-], and if those are
|
||||||
not found, go to the first open checkbox, i.e. [ ].
|
not found, go to the first open checkbox, i.e. [ ]. If the item
|
||||||
|
thus found contains a sublist of checkbox items on it's own,
|
||||||
|
recursively repeat the search, until no more sublists exist that
|
||||||
|
contain open checkboxes.
|
||||||
|
|
||||||
If there's no such open checkbox, emit a message (unless SILENT
|
If there's no such open checkbox, emit a message (unless SILENT
|
||||||
is non-nil) and stay put.
|
is non-nil) and stay put.
|
||||||
|
|
||||||
Note: when lists are nested, those are not (yet) descended into
|
Do not search through branches, i.e., stop the search when the
|
||||||
to find the logically first open checkbox. This should be fixed
|
first sub-headline is found."
|
||||||
somewhen, though."
|
|
||||||
|
|
||||||
(unless (derived-mode-p 'org-mode)
|
(unless (derived-mode-p 'org-mode)
|
||||||
(user-error "Not in Org buffer, exiting"))
|
(user-error "Not in Org buffer, exiting"))
|
||||||
|
|
||||||
(save-restriction
|
(save-restriction
|
||||||
(let ((original-point (point)))
|
(widen)
|
||||||
(widen)
|
(org-back-to-heading 'invisible-ok)
|
||||||
(org-back-to-heading 'invisible-ok)
|
(org-narrow-to-subtree)
|
||||||
(org-narrow-to-subtree)
|
;; XXX: this needs a description of how the below algorithm works
|
||||||
(unless
|
(let ((ast (org-element-parse-buffer))
|
||||||
;; Yes, those `progn's are not strictly necessary, but it feels
|
checkbox-pos
|
||||||
;; cleaner this way.
|
checkbox-node
|
||||||
(or (progn
|
checkbox-pos-1)
|
||||||
(goto-char (point-min))
|
|
||||||
(re-search-forward " \\[-\\] " nil 'no-error))
|
(while ast
|
||||||
(progn
|
|
||||||
(goto-char (point-min))
|
(when checkbox-pos
|
||||||
(re-search-forward " \\[ \\] " nil 'no-error)))
|
;; `checkbox-pos' might be nil when the found checkbox item is empty; in this case, `ast'
|
||||||
(unless silent
|
;; is not empty, and the following assignment will potentially delete the last known
|
||||||
(message "No open checkbox in subtree"))
|
;; position of a proper checkbox.
|
||||||
(goto-char original-point)))))
|
(setq checkbox-pos-1 checkbox-pos))
|
||||||
|
|
||||||
|
(setq checkbox-pos nil
|
||||||
|
checkbox-node nil)
|
||||||
|
|
||||||
|
(org-element-map ast '(item headline)
|
||||||
|
(lambda (node)
|
||||||
|
(unless (eq node ast)
|
||||||
|
(if (eq 'headline (org-element-type node))
|
||||||
|
nil ; Abort search to ignore headlines and everything that follows.
|
||||||
|
(when (and (null checkbox-pos)
|
||||||
|
(not (memq (org-element-property :checkbox node)
|
||||||
|
'(nil on))))
|
||||||
|
(setq checkbox-pos (org-element-contents-begin node)
|
||||||
|
checkbox-node node))
|
||||||
|
;; Having this `when' separately and at the end of this function results in
|
||||||
|
;; `org-element-map' terminating the search as soon as a “[-]” is found.
|
||||||
|
(when (eq 'trans (org-element-property :checkbox node))
|
||||||
|
(setq checkbox-pos (org-element-contents-begin node)
|
||||||
|
checkbox-node node)))))
|
||||||
|
nil t)
|
||||||
|
|
||||||
|
(setq ast checkbox-node))
|
||||||
|
|
||||||
|
(cond
|
||||||
|
(checkbox-pos (goto-char checkbox-pos))
|
||||||
|
(checkbox-pos-1 (goto-char checkbox-pos-1))
|
||||||
|
(t (unless silent
|
||||||
|
(message "No open checkbox in subtree")))))))
|
||||||
|
|
||||||
(defun db/org-clock-goto-first-open-checkbox (&optional select)
|
(defun db/org-clock-goto-first-open-checkbox (&optional select)
|
||||||
"Go to the currently clocked-in item or most recently clocked item.
|
"Go to the currently clocked-in item or most recently clocked item.
|
||||||
|
|
||||||
Move point to first open checkbox there, if there's one. See
|
Move point to first open checkbox there, if there's one. See
|
||||||
`db/org-goto-first-open-checkbox-in-subtree' for details.
|
`db/org-goto-first-open-checkbox-in-headline' for details.
|
||||||
|
|
||||||
If SELECT is non-nil, offer a choice of the most recently
|
If SELECT is non-nil, offer a choice of the most recently
|
||||||
clocked-in tasks to jump to."
|
clocked-in tasks to jump to."
|
||||||
@ -1494,7 +1524,7 @@ clocked-in tasks to jump to."
|
|||||||
(goto-char m)
|
(goto-char m)
|
||||||
(org-fold-show-entry)
|
(org-fold-show-entry)
|
||||||
(org-fold-hide-drawer-all)
|
(org-fold-hide-drawer-all)
|
||||||
(db/org-goto-first-open-checkbox-in-subtree :silent)
|
(db/org-goto-first-open-checkbox-in-headline :silent)
|
||||||
(org-reveal)
|
(org-reveal)
|
||||||
(if recent
|
(if recent
|
||||||
(message "No running clock, this is the most recently clocked task"))
|
(message "No running clock, this is the most recently clocked task"))
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user