Skip to content

Instantly share code, notes, and snippets.

@xcodebuild
Last active January 13, 2019 16:24
Show Gist options
  • Save xcodebuild/87b116291aa87fde72cb to your computer and use it in GitHub Desktop.
Save xcodebuild/87b116291aa87fde72cb to your computer and use it in GitHub Desktop.
Keeping the context when archiving in Emacs org-mode
;; org-archive-subtree-hierarchical.el
;; modified from https://lists.gnu.org/archive/html/emacs-orgmode/2014-08/msg00109.html
;; In orgmode
;; * A
;; ** AA
;; *** AAA
;; ** AB
;; *** ABA
;; Archiving AA will remove the subtree from the original file and create
;; it like that in archive target:
;; * AA
;; ** AAA
;; And this give you
;; * A
;; ** AA
;; *** AAA
(require 'org-archive)
(defun org-archive-subtree-hierarchical--line-content-as-string ()
"Returns the content of the current line as a string"
(save-excursion
(beginning-of-line)
(buffer-substring-no-properties
(line-beginning-position) (line-end-position))))
(defun org-archive-subtree-hierarchical--org-child-list ()
"This function returns all children of a heading as a list. "
(interactive)
(save-excursion
;; this only works with org-version > 8.0, since in previous
;; org-mode versions the function (org-outline-level) returns
;; gargabe when the point is not on a heading.
(if (= (org-outline-level) 0)
(outline-next-visible-heading 1)
(org-goto-first-child))
(let ((child-list (list (org-archive-subtree-hierarchical--line-content-as-string))))
(while (org-goto-sibling)
(setq child-list (cons (org-archive-subtree-hierarchical--line-content-as-string) child-list)))
child-list)))
(defun org-archive-subtree-hierarchical--org-struct-subtree ()
"This function returns the tree structure in which a subtree
belongs as a list."
(interactive)
(let ((archive-tree nil))
(save-excursion
(while (org-up-heading-safe)
(let ((heading
(buffer-substring-no-properties
(line-beginning-position) (line-end-position))))
(if (eq archive-tree nil)
(setq archive-tree (list heading))
(setq archive-tree (cons heading archive-tree))))))
archive-tree))
(defun org-archive-subtree-hierarchical ()
"This function archives a subtree hierarchical"
(interactive)
(let ((org-tree (org-archive-subtree-hierarchical--org-struct-subtree))
(this-buffer (current-buffer))
(file (abbreviate-file-name
(or (buffer-file-name (buffer-base-buffer))
(error "No file associated to buffer")))))
(save-excursion
(setq location (org-get-local-archive-location)
afile (org-extract-archive-file location)
heading (org-extract-archive-heading location)
infile-p (equal file (abbreviate-file-name (or afile ""))))
(unless afile
(error "Invalid `org-archive-location'"))
(if (> (length afile) 0)
(setq newfile-p (not (file-exists-p afile))
visiting (find-buffer-visiting afile)
buffer (or visiting (find-file-noselect afile)))
(setq buffer (current-buffer)))
(unless buffer
(error "Cannot access file \"%s\"" afile))
(org-cut-subtree)
(set-buffer buffer)
(org-mode)
(goto-char (point-min))
(while (not (equal org-tree nil))
(let ((child-list (org-archive-subtree-hierarchical--org-child-list)))
(if (member (car org-tree) child-list)
(progn
(search-forward (car org-tree) nil t)
(setq org-tree (cdr org-tree)))
(progn
(goto-char (point-max))
(newline)
(org-insert-struct org-tree)
(setq org-tree nil)))))
(newline)
(org-yank)
(when (not (eq this-buffer buffer))
(save-buffer))
(message "Subtree archived %s"
(concat "in file: " (abbreviate-file-name afile))))))
(defun org-insert-struct (struct)
"TODO"
(interactive)
(when struct
(insert (car struct))
(newline)
(org-insert-struct (cdr struct))))
(defun org-archive-subtree ()
(org-archive-subtree-hierarchical)
)
@lengyueyang
Copy link

CodeFalling,问一下,我把上面的代码加到usr-config可以用,我把代码放到org-archive-subtree-hierarchical.el文件,再
(add-to-load-path "~/.spacemacs.d/package/org-archive-subtree-hierarchical")
(require 'org-archive-subtree-hierarchical)
打开emacs就会出现错误,不知你遇到过这个问题吗

@edgimar
Copy link

edgimar commented Mar 2, 2017

This code does not work correctly when org-archive-location is set to something like ::* Archived (that is, archive to the same file beneath the Archived headline). Would you be able to update it to handle prefix headlines as target locations?

@nerrons
Copy link

nerrons commented Mar 7, 2017

您好。添加到 init.el 后,用 org-archive-subtree 来归档,结果出现错误: Wrong type argument: commandp, org-archive-subtree。

GNU Emacs 25.1.1 (x86_64-apple-darwin16.1.0, NS appkit-1504.60 Version 10.12.1 (Build 16B2555)) of 2016-11-27
Org mode version 9.0.5 (9.0.5-elpa @ /Users/Nerrons/.emacs.d/elpa/org-20170210/)

谢谢解答!很期望能用上这个功能!

@yxsongbo
Copy link

我也遇到同样的问题,系统环境和nerrons一样,我用spacemacs的配置,代码复制到user-config

@hitlye
Copy link

hitlye commented Jul 1, 2017

我加上(interactive) 不报错了

@anacn
Copy link

anacn commented Dec 17, 2017

和二楼有同样需求,设置location后不报错,但没反应,原条目还在

@SimonAM
Copy link

SimonAM commented Nov 5, 2018

Firstly,
I could not use spacemacs default keybindings to use this.
I added:
(setq org-archive-default-command 'org-archive-subtree-hierarchical)
and used C-c C-x C-a.

When a subheading has been archived prior to a parent heading, it will create a duplicate parent heading.

I have a .org-file that looks like this:

* 1a-heading
** 2a-Heading
Foo bar text
*** 3a-heading
*** 3b-heading

When i archive *** 3b it correctly creates the following archive:

* 1a-heading
** 2a-Heading
*** 3b-heading

However, when i later archive the parent heading (** 2a)
The archive looks like the following:

* 1a-heading
** 2a-Heading
Foo bar text
*** 3a-heading
** 2a-Heading
*** 3b-heading

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment