mirror of
https://git.savannah.gnu.org/git/emacs/org-mode.git
synced 2024-09-22 12:10:44 +00:00
Merge branch '3-org-archive-loop'
This commit is contained in:
commit
a6c95474d3
|
@ -190,158 +190,166 @@ If the cursor is not at a headline when this command is called, try all level
|
||||||
1 trees. If the cursor is on a headline, only try the direct children of
|
1 trees. If the cursor is on a headline, only try the direct children of
|
||||||
this heading."
|
this heading."
|
||||||
(interactive "P")
|
(interactive "P")
|
||||||
(if find-done
|
(if (and (org-region-active-p) org-loop-over-headlines-in-active-region)
|
||||||
(org-archive-all-done)
|
(let ((cl (if (eq org-loop-over-headlines-in-active-region 'start-level)
|
||||||
;; Save all relevant TODO keyword-relatex variables
|
'region-current-level 'region))
|
||||||
|
org-loop-over-headlines-in-active-region)
|
||||||
|
(org-map-entries
|
||||||
|
`(progn (setq org-map-continue-from (progn (org-back-to-heading) (point)))
|
||||||
|
(org-archive-subtree ,find-done))
|
||||||
|
org-loop-over-headlines-in-active-region
|
||||||
|
cl (if (outline-invisible-p) (org-end-of-subtree nil t))))
|
||||||
|
(if find-done
|
||||||
|
(org-archive-all-done)
|
||||||
|
;; Save all relevant TODO keyword-relatex variables
|
||||||
|
(let ((tr-org-todo-line-regexp org-todo-line-regexp) ; keep despite compiler
|
||||||
|
(tr-org-todo-keywords-1 org-todo-keywords-1)
|
||||||
|
(tr-org-todo-kwd-alist org-todo-kwd-alist)
|
||||||
|
(tr-org-done-keywords org-done-keywords)
|
||||||
|
(tr-org-todo-regexp org-todo-regexp)
|
||||||
|
(tr-org-todo-line-regexp org-todo-line-regexp)
|
||||||
|
(tr-org-odd-levels-only org-odd-levels-only)
|
||||||
|
(this-buffer (current-buffer))
|
||||||
|
;; start of variables that will be used for saving context
|
||||||
|
;; The compiler complains about them - keep them anyway!
|
||||||
|
(file (abbreviate-file-name
|
||||||
|
(or (buffer-file-name (buffer-base-buffer))
|
||||||
|
(error "No file associated to buffer"))))
|
||||||
|
(olpath (mapconcat 'identity (org-get-outline-path) "/"))
|
||||||
|
(time (format-time-string
|
||||||
|
(substring (cdr org-time-stamp-formats) 1 -1)
|
||||||
|
(current-time)))
|
||||||
|
category todo priority ltags itags atags
|
||||||
|
;; end of variables that will be used for saving context
|
||||||
|
location afile heading buffer level newfile-p infile-p visiting)
|
||||||
|
|
||||||
(let ((tr-org-todo-line-regexp org-todo-line-regexp) ; keep despite compiler
|
;; Find the local archive location
|
||||||
(tr-org-todo-keywords-1 org-todo-keywords-1)
|
(setq location (org-get-local-archive-location)
|
||||||
(tr-org-todo-kwd-alist org-todo-kwd-alist)
|
afile (org-extract-archive-file location)
|
||||||
(tr-org-done-keywords org-done-keywords)
|
heading (org-extract-archive-heading location)
|
||||||
(tr-org-todo-regexp org-todo-regexp)
|
infile-p (equal file (abbreviate-file-name afile)))
|
||||||
(tr-org-todo-line-regexp org-todo-line-regexp)
|
(unless afile
|
||||||
(tr-org-odd-levels-only org-odd-levels-only)
|
(error "Invalid `org-archive-location'"))
|
||||||
(this-buffer (current-buffer))
|
|
||||||
;; start of variables that will be used for saving context
|
|
||||||
;; The compiler complains about them - keep them anyway!
|
|
||||||
(file (abbreviate-file-name
|
|
||||||
(or (buffer-file-name (buffer-base-buffer))
|
|
||||||
(error "No file associated to buffer"))))
|
|
||||||
(olpath (mapconcat 'identity (org-get-outline-path) "/"))
|
|
||||||
(time (format-time-string
|
|
||||||
(substring (cdr org-time-stamp-formats) 1 -1)
|
|
||||||
(current-time)))
|
|
||||||
category todo priority ltags itags atags
|
|
||||||
;; end of variables that will be used for saving context
|
|
||||||
location afile heading buffer level newfile-p infile-p visiting)
|
|
||||||
|
|
||||||
;; Find the local archive location
|
(if (> (length afile) 0)
|
||||||
(setq location (org-get-local-archive-location)
|
(setq newfile-p (not (file-exists-p afile))
|
||||||
afile (org-extract-archive-file location)
|
visiting (find-buffer-visiting afile)
|
||||||
heading (org-extract-archive-heading location)
|
buffer (or visiting (find-file-noselect afile)))
|
||||||
infile-p (equal file (abbreviate-file-name afile)))
|
(setq buffer (current-buffer)))
|
||||||
(unless afile
|
(unless buffer
|
||||||
(error "Invalid `org-archive-location'"))
|
(error "Cannot access file \"%s\"" afile))
|
||||||
|
(if (and (> (length heading) 0)
|
||||||
|
(string-match "^\\*+" heading))
|
||||||
|
(setq level (match-end 0))
|
||||||
|
(setq heading nil level 0))
|
||||||
|
(save-excursion
|
||||||
|
(org-back-to-heading t)
|
||||||
|
;; Get context information that will be lost by moving the tree
|
||||||
|
(setq category (org-get-category nil 'force-refresh)
|
||||||
|
todo (and (looking-at org-todo-line-regexp)
|
||||||
|
(match-string 2))
|
||||||
|
priority (org-get-priority
|
||||||
|
(if (match-end 3) (match-string 3) ""))
|
||||||
|
ltags (org-get-tags)
|
||||||
|
itags (org-delete-all ltags (org-get-tags-at))
|
||||||
|
atags (org-get-tags-at))
|
||||||
|
(setq ltags (mapconcat 'identity ltags " ")
|
||||||
|
itags (mapconcat 'identity itags " "))
|
||||||
|
;; We first only copy, in case something goes wrong
|
||||||
|
;; we need to protect `this-command', to avoid kill-region sets it,
|
||||||
|
;; which would lead to duplication of subtrees
|
||||||
|
(let (this-command) (org-copy-subtree 1 nil t))
|
||||||
|
(set-buffer buffer)
|
||||||
|
;; Enforce org-mode for the archive buffer
|
||||||
|
(if (not (eq major-mode 'org-mode))
|
||||||
|
;; Force the mode for future visits.
|
||||||
|
(let ((org-insert-mode-line-in-empty-file t)
|
||||||
|
(org-inhibit-startup t))
|
||||||
|
(call-interactively 'org-mode)))
|
||||||
|
(when newfile-p
|
||||||
|
(goto-char (point-max))
|
||||||
|
(insert (format "\nArchived entries from file %s\n\n"
|
||||||
|
(buffer-file-name this-buffer))))
|
||||||
|
;; Force the TODO keywords of the original buffer
|
||||||
|
(let ((org-todo-line-regexp tr-org-todo-line-regexp)
|
||||||
|
(org-todo-keywords-1 tr-org-todo-keywords-1)
|
||||||
|
(org-todo-kwd-alist tr-org-todo-kwd-alist)
|
||||||
|
(org-done-keywords tr-org-done-keywords)
|
||||||
|
(org-todo-regexp tr-org-todo-regexp)
|
||||||
|
(org-todo-line-regexp tr-org-todo-line-regexp)
|
||||||
|
(org-odd-levels-only
|
||||||
|
(if (local-variable-p 'org-odd-levels-only (current-buffer))
|
||||||
|
org-odd-levels-only
|
||||||
|
tr-org-odd-levels-only)))
|
||||||
|
(goto-char (point-min))
|
||||||
|
(show-all)
|
||||||
|
(if heading
|
||||||
|
(progn
|
||||||
|
(if (re-search-forward
|
||||||
|
(concat "^" (regexp-quote heading)
|
||||||
|
(org-re "[ \t]*\\(:[[:alnum:]_@#%:]+:\\)?[ \t]*\\($\\|\r\\)"))
|
||||||
|
nil t)
|
||||||
|
(goto-char (match-end 0))
|
||||||
|
;; Heading not found, just insert it at the end
|
||||||
|
(goto-char (point-max))
|
||||||
|
(or (bolp) (insert "\n"))
|
||||||
|
(insert "\n" heading "\n")
|
||||||
|
(end-of-line 0))
|
||||||
|
;; Make the subtree visible
|
||||||
|
(show-subtree)
|
||||||
|
(if org-archive-reversed-order
|
||||||
|
(progn
|
||||||
|
(org-back-to-heading t)
|
||||||
|
(outline-next-heading))
|
||||||
|
(org-end-of-subtree t))
|
||||||
|
(skip-chars-backward " \t\r\n")
|
||||||
|
(and (looking-at "[ \t\r\n]*")
|
||||||
|
(replace-match "\n\n")))
|
||||||
|
;; No specific heading, just go to end of file.
|
||||||
|
(goto-char (point-max)) (insert "\n"))
|
||||||
|
;; Paste
|
||||||
|
(org-paste-subtree (org-get-valid-level level (and heading 1)))
|
||||||
|
;; Shall we append inherited tags?
|
||||||
|
(and itags
|
||||||
|
(or (and (eq org-archive-subtree-add-inherited-tags 'infile)
|
||||||
|
infile-p)
|
||||||
|
(eq org-archive-subtree-add-inherited-tags t))
|
||||||
|
(org-set-tags-to atags))
|
||||||
|
;; Mark the entry as done
|
||||||
|
(when (and org-archive-mark-done
|
||||||
|
(looking-at org-todo-line-regexp)
|
||||||
|
(or (not (match-end 2))
|
||||||
|
(not (member (match-string 2) org-done-keywords))))
|
||||||
|
(let (org-log-done org-todo-log-states)
|
||||||
|
(org-todo
|
||||||
|
(car (or (member org-archive-mark-done org-done-keywords)
|
||||||
|
org-done-keywords)))))
|
||||||
|
|
||||||
(if (> (length afile) 0)
|
;; Add the context info
|
||||||
(setq newfile-p (not (file-exists-p afile))
|
(when org-archive-save-context-info
|
||||||
visiting (find-buffer-visiting afile)
|
(let ((l org-archive-save-context-info) e n v)
|
||||||
buffer (or visiting (find-file-noselect afile)))
|
(while (setq e (pop l))
|
||||||
(setq buffer (current-buffer)))
|
(when (and (setq v (symbol-value e))
|
||||||
(unless buffer
|
(stringp v) (string-match "\\S-" v))
|
||||||
(error "Cannot access file \"%s\"" afile))
|
(setq n (concat "ARCHIVE_" (upcase (symbol-name e))))
|
||||||
(if (and (> (length heading) 0)
|
(org-entry-put (point) n v)))))
|
||||||
(string-match "^\\*+" heading))
|
|
||||||
(setq level (match-end 0))
|
|
||||||
(setq heading nil level 0))
|
|
||||||
(save-excursion
|
|
||||||
(org-back-to-heading t)
|
|
||||||
;; Get context information that will be lost by moving the tree
|
|
||||||
(setq category (org-get-category nil 'force-refresh)
|
|
||||||
todo (and (looking-at org-todo-line-regexp)
|
|
||||||
(match-string 2))
|
|
||||||
priority (org-get-priority
|
|
||||||
(if (match-end 3) (match-string 3) ""))
|
|
||||||
ltags (org-get-tags)
|
|
||||||
itags (org-delete-all ltags (org-get-tags-at))
|
|
||||||
atags (org-get-tags-at))
|
|
||||||
(setq ltags (mapconcat 'identity ltags " ")
|
|
||||||
itags (mapconcat 'identity itags " "))
|
|
||||||
;; We first only copy, in case something goes wrong
|
|
||||||
;; we need to protect `this-command', to avoid kill-region sets it,
|
|
||||||
;; which would lead to duplication of subtrees
|
|
||||||
(let (this-command) (org-copy-subtree 1 nil t))
|
|
||||||
(set-buffer buffer)
|
|
||||||
;; Enforce org-mode for the archive buffer
|
|
||||||
(if (not (eq major-mode 'org-mode))
|
|
||||||
;; Force the mode for future visits.
|
|
||||||
(let ((org-insert-mode-line-in-empty-file t)
|
|
||||||
(org-inhibit-startup t))
|
|
||||||
(call-interactively 'org-mode)))
|
|
||||||
(when newfile-p
|
|
||||||
(goto-char (point-max))
|
|
||||||
(insert (format "\nArchived entries from file %s\n\n"
|
|
||||||
(buffer-file-name this-buffer))))
|
|
||||||
;; Force the TODO keywords of the original buffer
|
|
||||||
(let ((org-todo-line-regexp tr-org-todo-line-regexp)
|
|
||||||
(org-todo-keywords-1 tr-org-todo-keywords-1)
|
|
||||||
(org-todo-kwd-alist tr-org-todo-kwd-alist)
|
|
||||||
(org-done-keywords tr-org-done-keywords)
|
|
||||||
(org-todo-regexp tr-org-todo-regexp)
|
|
||||||
(org-todo-line-regexp tr-org-todo-line-regexp)
|
|
||||||
(org-odd-levels-only
|
|
||||||
(if (local-variable-p 'org-odd-levels-only (current-buffer))
|
|
||||||
org-odd-levels-only
|
|
||||||
tr-org-odd-levels-only)))
|
|
||||||
(goto-char (point-min))
|
|
||||||
(show-all)
|
|
||||||
(if heading
|
|
||||||
(progn
|
|
||||||
(if (re-search-forward
|
|
||||||
(concat "^" (regexp-quote heading)
|
|
||||||
(org-re "[ \t]*\\(:[[:alnum:]_@#%:]+:\\)?[ \t]*\\($\\|\r\\)"))
|
|
||||||
nil t)
|
|
||||||
(goto-char (match-end 0))
|
|
||||||
;; Heading not found, just insert it at the end
|
|
||||||
(goto-char (point-max))
|
|
||||||
(or (bolp) (insert "\n"))
|
|
||||||
(insert "\n" heading "\n")
|
|
||||||
(end-of-line 0))
|
|
||||||
;; Make the subtree visible
|
|
||||||
(show-subtree)
|
|
||||||
(if org-archive-reversed-order
|
|
||||||
(progn
|
|
||||||
(org-back-to-heading t)
|
|
||||||
(outline-next-heading))
|
|
||||||
(org-end-of-subtree t))
|
|
||||||
(skip-chars-backward " \t\r\n")
|
|
||||||
(and (looking-at "[ \t\r\n]*")
|
|
||||||
(replace-match "\n\n")))
|
|
||||||
;; No specific heading, just go to end of file.
|
|
||||||
(goto-char (point-max)) (insert "\n"))
|
|
||||||
;; Paste
|
|
||||||
(org-paste-subtree (org-get-valid-level level (and heading 1)))
|
|
||||||
;; Shall we append inherited tags?
|
|
||||||
(and itags
|
|
||||||
(or (and (eq org-archive-subtree-add-inherited-tags 'infile)
|
|
||||||
infile-p)
|
|
||||||
(eq org-archive-subtree-add-inherited-tags t))
|
|
||||||
(org-set-tags-to atags))
|
|
||||||
;; Mark the entry as done
|
|
||||||
(when (and org-archive-mark-done
|
|
||||||
(looking-at org-todo-line-regexp)
|
|
||||||
(or (not (match-end 2))
|
|
||||||
(not (member (match-string 2) org-done-keywords))))
|
|
||||||
(let (org-log-done org-todo-log-states)
|
|
||||||
(org-todo
|
|
||||||
(car (or (member org-archive-mark-done org-done-keywords)
|
|
||||||
org-done-keywords)))))
|
|
||||||
|
|
||||||
;; Add the context info
|
;; Save and kill the buffer, if it is not the same buffer.
|
||||||
(when org-archive-save-context-info
|
(when (not (eq this-buffer buffer))
|
||||||
(let ((l org-archive-save-context-info) e n v)
|
(save-buffer))))
|
||||||
(while (setq e (pop l))
|
;; Here we are back in the original buffer. Everything seems to have
|
||||||
(when (and (setq v (symbol-value e))
|
;; worked. So now cut the tree and finish up.
|
||||||
(stringp v) (string-match "\\S-" v))
|
(let (this-command) (org-cut-subtree))
|
||||||
(setq n (concat "ARCHIVE_" (upcase (symbol-name e))))
|
(when (featurep 'org-inlinetask)
|
||||||
(org-entry-put (point) n v)))))
|
(org-inlinetask-remove-END-maybe))
|
||||||
|
(setq org-markers-to-move nil)
|
||||||
;; Save and kill the buffer, if it is not the same buffer.
|
(message "Subtree archived %s"
|
||||||
(when (not (eq this-buffer buffer))
|
(if (eq this-buffer buffer)
|
||||||
(save-buffer))))
|
(concat "under heading: " heading)
|
||||||
;; Here we are back in the original buffer. Everything seems to have
|
(concat "in file: " (abbreviate-file-name afile))))))
|
||||||
;; worked. So now cut the tree and finish up.
|
(org-reveal)
|
||||||
(let (this-command) (org-cut-subtree))
|
(if (looking-at "^[ \t]*$")
|
||||||
(when (featurep 'org-inlinetask)
|
(outline-next-visible-heading 1))))
|
||||||
(org-inlinetask-remove-END-maybe))
|
|
||||||
(setq org-markers-to-move nil)
|
|
||||||
(message "Subtree archived %s"
|
|
||||||
(if (eq this-buffer buffer)
|
|
||||||
(concat "under heading: " heading)
|
|
||||||
(concat "in file: " (abbreviate-file-name afile))))))
|
|
||||||
(org-reveal)
|
|
||||||
(if (looking-at "^[ \t]*$")
|
|
||||||
(outline-next-visible-heading 1)))
|
|
||||||
|
|
||||||
(defun org-archive-to-archive-sibling ()
|
(defun org-archive-to-archive-sibling ()
|
||||||
"Archive the current heading by moving it under the archive sibling.
|
"Archive the current heading by moving it under the archive sibling.
|
||||||
|
@ -349,55 +357,69 @@ The archive sibling is a sibling of the heading with the heading name
|
||||||
`org-archive-sibling-heading' and an `org-archive-tag' tag. If this
|
`org-archive-sibling-heading' and an `org-archive-tag' tag. If this
|
||||||
sibling does not exist, it will be created at the end of the subtree."
|
sibling does not exist, it will be created at the end of the subtree."
|
||||||
(interactive)
|
(interactive)
|
||||||
(save-restriction
|
(if (and (org-region-active-p) org-loop-over-headlines-in-active-region)
|
||||||
(widen)
|
(let ((cl (when (eq org-loop-over-headlines-in-active-region 'start-level)
|
||||||
(let (b e pos leader level)
|
'region-current-level 'region))
|
||||||
(org-back-to-heading t)
|
org-loop-over-headlines-in-active-region)
|
||||||
(looking-at org-outline-regexp)
|
(org-map-entries
|
||||||
(setq leader (match-string 0)
|
'(progn (setq org-map-continue-from
|
||||||
level (funcall outline-level))
|
(progn (org-back-to-heading)
|
||||||
(setq pos (point))
|
(if (looking-at (concat "^.*:" org-archive-tag ":.*$"))
|
||||||
(condition-case nil
|
(org-end-of-subtree t)
|
||||||
(outline-up-heading 1 t)
|
(point))))
|
||||||
(error (setq e (point-max)) (goto-char (point-min))))
|
(when (org-at-heading-p)
|
||||||
(setq b (point))
|
(org-archive-to-archive-sibling)))
|
||||||
(unless e
|
org-loop-over-headlines-in-active-region
|
||||||
|
cl (if (outline-invisible-p) (org-end-of-subtree nil t))))
|
||||||
|
(save-restriction
|
||||||
|
(widen)
|
||||||
|
(let (b e pos leader level)
|
||||||
|
(org-back-to-heading t)
|
||||||
|
(looking-at org-outline-regexp)
|
||||||
|
(setq leader (match-string 0)
|
||||||
|
level (funcall outline-level))
|
||||||
|
(setq pos (point))
|
||||||
(condition-case nil
|
(condition-case nil
|
||||||
(org-end-of-subtree t t)
|
(outline-up-heading 1 t)
|
||||||
(error (goto-char (point-max))))
|
(error (setq e (point-max)) (goto-char (point-min))))
|
||||||
(setq e (point)))
|
(setq b (point))
|
||||||
(goto-char b)
|
(unless e
|
||||||
(unless (re-search-forward
|
(condition-case nil
|
||||||
(concat "^" (regexp-quote leader)
|
(org-end-of-subtree t t)
|
||||||
"[ \t]*"
|
(error (goto-char (point-max))))
|
||||||
org-archive-sibling-heading
|
(setq e (point)))
|
||||||
"[ \t]*:"
|
(goto-char b)
|
||||||
org-archive-tag ":") e t)
|
(unless (re-search-forward
|
||||||
(goto-char e)
|
(concat "^" (regexp-quote leader)
|
||||||
(or (bolp) (newline))
|
"[ \t]*"
|
||||||
(insert leader org-archive-sibling-heading "\n")
|
org-archive-sibling-heading
|
||||||
(beginning-of-line 0)
|
"[ \t]*:"
|
||||||
(org-toggle-tag org-archive-tag 'on))
|
org-archive-tag ":") e t)
|
||||||
(beginning-of-line 1)
|
(goto-char e)
|
||||||
(if org-archive-reversed-order
|
(or (bolp) (newline))
|
||||||
(outline-next-heading)
|
(insert leader org-archive-sibling-heading "\n")
|
||||||
(org-end-of-subtree t t))
|
(beginning-of-line 0)
|
||||||
(save-excursion
|
(org-toggle-tag org-archive-tag 'on))
|
||||||
(goto-char pos)
|
(beginning-of-line 1)
|
||||||
(let ((this-command this-command)) (org-cut-subtree)))
|
(if org-archive-reversed-order
|
||||||
(org-paste-subtree (org-get-valid-level level 1))
|
(outline-next-heading)
|
||||||
(org-set-property
|
(org-end-of-subtree t t))
|
||||||
"ARCHIVE_TIME"
|
(save-excursion
|
||||||
(format-time-string
|
(goto-char pos)
|
||||||
(substring (cdr org-time-stamp-formats) 1 -1)
|
(let ((this-command this-command)) (org-cut-subtree)))
|
||||||
(current-time)))
|
(org-paste-subtree (org-get-valid-level level 1))
|
||||||
(outline-up-heading 1 t)
|
(org-set-property
|
||||||
(hide-subtree)
|
"ARCHIVE_TIME"
|
||||||
(org-cycle-show-empty-lines 'folded)
|
(format-time-string
|
||||||
(goto-char pos)))
|
(substring (cdr org-time-stamp-formats) 1 -1)
|
||||||
(org-reveal)
|
(current-time)))
|
||||||
(if (looking-at "^[ \t]*$")
|
(outline-up-heading 1 t)
|
||||||
(outline-next-visible-heading 1)))
|
(hide-subtree)
|
||||||
|
(org-cycle-show-empty-lines 'folded)
|
||||||
|
(goto-char pos)))
|
||||||
|
(org-reveal)
|
||||||
|
(if (looking-at "^[ \t]*$")
|
||||||
|
(outline-next-visible-heading 1))))
|
||||||
|
|
||||||
(defun org-archive-all-done (&optional tag)
|
(defun org-archive-all-done (&optional tag)
|
||||||
"Archive sublevels of the current tree without open TODO items.
|
"Archive sublevels of the current tree without open TODO items.
|
||||||
|
@ -448,20 +470,36 @@ When TAG is non-nil, don't move trees, but mark them with the ARCHIVE tag."
|
||||||
With prefix ARG, check all children of current headline and offer tagging
|
With prefix ARG, check all children of current headline and offer tagging
|
||||||
the children that do not contain any open TODO items."
|
the children that do not contain any open TODO items."
|
||||||
(interactive "P")
|
(interactive "P")
|
||||||
(if find-done
|
(if (and (org-region-active-p) org-loop-over-headlines-in-active-region)
|
||||||
(org-archive-all-done 'tag)
|
(let ((cl (if (eq org-loop-over-headlines-in-active-region 'start-level)
|
||||||
(let (set)
|
'region-current-level 'region))
|
||||||
(save-excursion
|
org-loop-over-headlines-in-active-region)
|
||||||
(org-back-to-heading t)
|
(org-map-entries
|
||||||
(setq set (org-toggle-tag org-archive-tag))
|
`(org-toggle-archive-tag ,find-done)
|
||||||
(when set (hide-subtree)))
|
org-loop-over-headlines-in-active-region
|
||||||
(and set (beginning-of-line 1))
|
cl (if (outline-invisible-p) (org-end-of-subtree nil t))))
|
||||||
(message "Subtree %s" (if set "archived" "unarchived")))))
|
(if find-done
|
||||||
|
(org-archive-all-done 'tag)
|
||||||
|
(let (set)
|
||||||
|
(save-excursion
|
||||||
|
(org-back-to-heading t)
|
||||||
|
(setq set (org-toggle-tag org-archive-tag))
|
||||||
|
(when set (hide-subtree)))
|
||||||
|
(and set (beginning-of-line 1))
|
||||||
|
(message "Subtree %s" (if set "archived" "unarchived"))))))
|
||||||
|
|
||||||
(defun org-archive-set-tag ()
|
(defun org-archive-set-tag ()
|
||||||
"Set the ARCHIVE tag."
|
"Set the ARCHIVE tag."
|
||||||
(interactive)
|
(interactive)
|
||||||
(org-toggle-tag org-archive-tag 'on))
|
(if (and (org-region-active-p) org-loop-over-headlines-in-active-region)
|
||||||
|
(let ((cl (if (eq org-loop-over-headlines-in-active-region 'start-level)
|
||||||
|
'region-current-level 'region))
|
||||||
|
org-loop-over-headlines-in-active-region)
|
||||||
|
(org-map-entries
|
||||||
|
'org-archive-set-tag
|
||||||
|
org-loop-over-headlines-in-active-region
|
||||||
|
cl (if (outline-invisible-p) (org-end-of-subtree nil t))))
|
||||||
|
(org-toggle-tag org-archive-tag 'on)))
|
||||||
|
|
||||||
;;;###autoload
|
;;;###autoload
|
||||||
(defun org-archive-subtree-default ()
|
(defun org-archive-subtree-default ()
|
||||||
|
|
37
lisp/org.el
37
lisp/org.el
|
@ -410,6 +410,10 @@ XEmacs user should have this variable set to nil, because
|
||||||
When set to `t', some commands will be performed in all headlines
|
When set to `t', some commands will be performed in all headlines
|
||||||
within the active region.
|
within the active region.
|
||||||
|
|
||||||
|
When set to `start-level', some commands will be performed in all
|
||||||
|
headlines within the active region, provided that these headlines
|
||||||
|
are of the same level than the first one.
|
||||||
|
|
||||||
When set to a string, those commands will be performed on the
|
When set to a string, those commands will be performed on the
|
||||||
matching headlines within the active region. Such string must be
|
matching headlines within the active region. Such string must be
|
||||||
a tags/property/todo match as it is used in the agenda tags view.
|
a tags/property/todo match as it is used in the agenda tags view.
|
||||||
|
@ -419,6 +423,7 @@ The list of commands is:
|
||||||
- `org-deadline'"
|
- `org-deadline'"
|
||||||
:type '(choice (const :tag "Don't loop" nil)
|
:type '(choice (const :tag "Don't loop" nil)
|
||||||
(const :tag "All headlines in active region" t)
|
(const :tag "All headlines in active region" t)
|
||||||
|
(const :tag "In active region, headlines at the same level than the first one" 'start-level)
|
||||||
(string :tag "Tags/Property/Todo matcher"))
|
(string :tag "Tags/Property/Todo matcher"))
|
||||||
:group 'org-todo
|
:group 'org-todo
|
||||||
:group 'org-archive)
|
:group 'org-archive)
|
||||||
|
@ -12718,7 +12723,7 @@ obtain a list of properties. Building the tags list for each entry in such
|
||||||
a file becomes an N^2 operation - but with this variable set, it scales
|
a file becomes an N^2 operation - but with this variable set, it scales
|
||||||
as N.")
|
as N.")
|
||||||
|
|
||||||
(defun org-scan-tags (action matcher &optional todo-only)
|
(defun org-scan-tags (action matcher &optional todo-only start-level)
|
||||||
"Scan headline tags with inheritance and produce output ACTION.
|
"Scan headline tags with inheritance and produce output ACTION.
|
||||||
|
|
||||||
ACTION can be `sparse-tree' to produce a sparse tree in the current buffer,
|
ACTION can be `sparse-tree' to produce a sparse tree in the current buffer,
|
||||||
|
@ -12728,9 +12733,17 @@ this case the return value is a list of all return values from these calls.
|
||||||
|
|
||||||
MATCHER is a Lisp form to be evaluated, testing if a given set of tags
|
MATCHER is a Lisp form to be evaluated, testing if a given set of tags
|
||||||
qualifies a headline for inclusion. When TODO-ONLY is non-nil,
|
qualifies a headline for inclusion. When TODO-ONLY is non-nil,
|
||||||
only lines with a TODO keyword are included in the output."
|
only lines with a TODO keyword are included in the output.
|
||||||
|
|
||||||
|
START-LEVEL can be a string with asterisks, reducing the scope to
|
||||||
|
headlines matching this string."
|
||||||
(require 'org-agenda)
|
(require 'org-agenda)
|
||||||
(let* ((re (concat "^" org-outline-regexp " *\\(\\<\\("
|
(let* ((re (concat "^"
|
||||||
|
(if start-level
|
||||||
|
;; Get the correct level to match
|
||||||
|
(concat "\\*\\{" (number-to-string start-level) "\\} ")
|
||||||
|
org-outline-regexp)
|
||||||
|
" *\\(\\<\\("
|
||||||
(mapconcat 'regexp-quote org-todo-keywords-1 "\\|")
|
(mapconcat 'regexp-quote org-todo-keywords-1 "\\|")
|
||||||
(org-re
|
(org-re
|
||||||
"\\>\\)\\)? *\\(.*?\\)\\(:[[:alnum:]_@#%:]+:\\)?[ \t]*$")))
|
"\\>\\)\\)? *\\(.*?\\)\\(:[[:alnum:]_@#%:]+:\\)?[ \t]*$")))
|
||||||
|
@ -13724,6 +13737,9 @@ SCOPE determines the scope of this command. It can be any of:
|
||||||
nil The current buffer, respecting the restriction if any
|
nil The current buffer, respecting the restriction if any
|
||||||
tree The subtree started with the entry at point
|
tree The subtree started with the entry at point
|
||||||
region The entries within the active region, if any
|
region The entries within the active region, if any
|
||||||
|
region-start-level
|
||||||
|
The entries within the active region, but only those at
|
||||||
|
the same level than the first one.
|
||||||
file The current buffer, without restriction
|
file The current buffer, without restriction
|
||||||
file-with-archives
|
file-with-archives
|
||||||
The current buffer, and any archives associated with it
|
The current buffer, and any archives associated with it
|
||||||
|
@ -13752,13 +13768,15 @@ with `org-get-tags-at'. If your function gets properties with
|
||||||
to t around the call to `org-entry-properties' to get the same speedup.
|
to t around the call to `org-entry-properties' to get the same speedup.
|
||||||
Note that if your function moves around to retrieve tags and properties at
|
Note that if your function moves around to retrieve tags and properties at
|
||||||
a *different* entry, you cannot use these techniques."
|
a *different* entry, you cannot use these techniques."
|
||||||
(unless (and (eq scope 'region) (not (org-region-active-p)))
|
(unless (and (or (eq scope 'region) (eq scope 'region-start-level))
|
||||||
|
(not (org-region-active-p)))
|
||||||
(let* ((org-agenda-archives-mode nil) ; just to make sure
|
(let* ((org-agenda-archives-mode nil) ; just to make sure
|
||||||
(org-agenda-skip-archived-trees (memq 'archive skip))
|
(org-agenda-skip-archived-trees (memq 'archive skip))
|
||||||
(org-agenda-skip-comment-trees (memq 'comment skip))
|
(org-agenda-skip-comment-trees (memq 'comment skip))
|
||||||
(org-agenda-skip-function
|
(org-agenda-skip-function
|
||||||
(car (org-delete-all '(comment archive) skip)))
|
(car (org-delete-all '(comment archive) skip)))
|
||||||
(org-tags-match-list-sublevels t)
|
(org-tags-match-list-sublevels t)
|
||||||
|
(start-level (eq scope 'region-start-level))
|
||||||
matcher file res
|
matcher file res
|
||||||
org-todo-keywords-for-agenda
|
org-todo-keywords-for-agenda
|
||||||
org-done-keywords-for-agenda
|
org-done-keywords-for-agenda
|
||||||
|
@ -13777,7 +13795,14 @@ a *different* entry, you cannot use these techniques."
|
||||||
(org-back-to-heading t)
|
(org-back-to-heading t)
|
||||||
(org-narrow-to-subtree)
|
(org-narrow-to-subtree)
|
||||||
(setq scope nil))
|
(setq scope nil))
|
||||||
((and (eq scope 'region) (org-region-active-p))
|
((and (or (eq scope 'region) (eq scope 'region-start-level))
|
||||||
|
(org-region-active-p))
|
||||||
|
;; If needed, set start-level to a string like "2"
|
||||||
|
(when start-level
|
||||||
|
(save-excursion
|
||||||
|
(goto-char (region-beginning))
|
||||||
|
(unless (org-at-heading-p) (outline-next-heading))
|
||||||
|
(setq start-level (org-current-level))))
|
||||||
(narrow-to-region (region-beginning)
|
(narrow-to-region (region-beginning)
|
||||||
(save-excursion
|
(save-excursion
|
||||||
(goto-char (region-end))
|
(goto-char (region-end))
|
||||||
|
@ -13790,7 +13815,7 @@ a *different* entry, you cannot use these techniques."
|
||||||
(progn
|
(progn
|
||||||
(org-prepare-agenda-buffers
|
(org-prepare-agenda-buffers
|
||||||
(list (buffer-file-name (current-buffer))))
|
(list (buffer-file-name (current-buffer))))
|
||||||
(setq res (org-scan-tags func matcher)))
|
(setq res (org-scan-tags func matcher nil start-level)))
|
||||||
;; Get the right scope
|
;; Get the right scope
|
||||||
(cond
|
(cond
|
||||||
((and scope (listp scope) (symbolp (car scope)))
|
((and scope (listp scope) (symbolp (car scope)))
|
||||||
|
|
Loading…
Reference in a new issue