如何在org-mode emacs中将子树移动到另一个子树

时间:2011-09-22 04:09:54

标签: emacs org-mode

我想执行一项简单的任务,但似乎没有明确的解决方案:

我有这样的子树结构:

* Tree A
** Subtree A1
** Subtree A2
* Tree B
** Subtree B1
** Subtree B2

我想设置一个关键的快捷方式,将树丛从树A移动到树B.移动到存档似乎很容易,但你有任何线索如何在一个文件中做到这一点?

任何帮助表示赞赏!谢谢!

6 个答案:

答案 0 :(得分:11)

您可以尝试使用 C-c C-w 重新填充子树(它也可以将子树移动到另一个文件)。

另一种方法是折叠子树,然后用 C-k C-k 杀死它并将其粘贴到应该的位置。

我使用的第三个解决方案是用 M-left 更改子树的级别,然后用 M-up M移动它-down ,然后 M-right 再次将它放在正确的级别上。第三种方法的缺点是有时它会使树的其他部分移动。

答案 1 :(得分:6)

我还希望org-refile能够轻松地重新编译为子树,所以我编写了一些代码并对其进行了概括,以便它可以在任何地方设置任意的直接目标(而不仅仅是在同一个文件中)。

基本用法是移动到Tree B中的某个位置并键入 Cc Cx Cm 以标记要重新映射的目标,然后移动到要重新编译的Tree A中的条目并输入 Cc Cw ,除非您使用前缀arg Cu Cc Cx Cm调用Tree B,否则它将立即重新进入您在org-refile-immediate-target中设置的目标位置而不提示您。

请注意,如果您快速连续按 Cc Cw 重新排列多个条目,即使org-reverse-note-order设置为t,它也会保留您的条目顺序,但是您可以关闭它以尊重org-reverse-note-order的设置,使用双前缀arg Cu Cu Cc Cx Cm

(defvar org-refile-immediate nil
  "Refile immediately using `org-refile-immediate-target' instead of prompting.")
(make-local-variable 'org-refile-immediate)

(defvar org-refile-immediate-preserve-order t
  "If last command was also `org-refile' then preserve ordering.")
(make-local-variable 'org-refile-immediate-preserve-order)

(defvar org-refile-immediate-target nil)
"Value uses the same format as an item in `org-refile-targets'."
(make-local-variable 'org-refile-immediate-target)

(defadvice org-refile (around org-immediate activate)
  (if (not org-refile-immediate)
      ad-do-it
    ;; if last command was `org-refile' then preserve ordering
    (let ((org-reverse-note-order
           (if (and org-refile-immediate-preserve-order
                    (eq last-command 'org-refile)) nil org-reverse-note-order)))
      (ad-set-arg 2 (assoc org-refile-immediate-target (org-refile-get-targets)))
      (prog1 ad-do-it
        (setq this-command 'org-refile)))))

(defadvice org-refile-cache-clear (after org-refile-history-clear activate)
  (setq org-refile-targets (default-value 'org-refile-targets))
  (setq org-refile-immediate nil)
  (setq org-refile-immediate-target nil)
  (setq org-refile-history nil))

;;;###autoload
(defun org-refile-immediate-target (&optional arg)
  "Set current entry as `org-refile' target.
Non-nil turns off `org-refile-immediate', otherwise `org-refile'
will immediately refile without prompting for target using most
recent entry in `org-refile-targets' that matches
`org-refile-immediate-target' as the default."
  (interactive "P")
  (if (equal arg '(16))
      (progn
        (setq org-refile-immediate-preserve-order
              (not org-refile-immediate-preserve-order))
        (message "Order preserving is turned: %s"
                 (if org-refile-immediate-preserve-order
                     "on" "off")))

    (setq org-refile-immediate (unless arg t))
    (make-local-variable 'org-refile-targets)
    (let* ((components (org-heading-components))
           (level (first components))
           (heading (nth 4 components))
           (string (substring-no-properties heading)))
      (add-to-list 'org-refile-targets
                   (append (list (buffer-file-name))
                           (cons :regexp
                                 (format "^%s %s$"
                                         (make-string level ?*)
                                         string))))
      (setq org-refile-immediate-target heading))))

(define-key org-mode-map "\C-c\C-x\C-m" 'org-refile-immediate-target)

很难在 Cc Cx 前缀上找到一个免费的密钥,所以我使用 m 和助记符i * mm * ediate

答案 2 :(得分:4)

如果文件结构不太复杂,我使用 M-left M-up / down 然后 M-right 。但请记住,如果您尝试使用此方法将子树A1移动到树B,您将丢失其子子子A1.1,除非您使用 MS-left / right 移动它:

* Tree A
** Subtree A1             <=== move this heading with M-S-left
*** Subsubtree A1.1       <=== or you will leave this heading behind
** Subtree A2

* Tree B
** Subtree B1
** Subtree B2

答案 3 :(得分:4)

您可以使用 C-c C-w 重新构建子树,具体取决于您如何设置refile。根据您目的地的深度,您可能无法将其用作有效目的地。

您可以使用kill / copy子命令命令来删除或复制子树,而不必折叠结构: Cc Cx Cw Cc Cx Mw ,从而划分子树是 Cc Cx Cy 或只是 Cy

答案 4 :(得分:2)

可以使用org-refile在同一缓冲区内移动子树。移动时,您甚至可以更改原始层次(星数)。但是,它可能无法开箱即用,主要是因为您正在使用的缓冲区不在org-refile-targets中。您可以使用C-[在refile目标中添加该文件,然后使用org-refile运行C-c C-w,最后使用C-]从refile目标中删除该文件。这可能太多了(如果maxlevel设置太低,可能会失败 - 无论如何都可以更改)。或者,要一次性自动执行此过程,首先必须定义如下函数:

(defun refile-in-current ()
"refile current item in current buffer"
(interactive)
(let ((org-refile-use-outline-path t)
    (org-refile-targets '((nil . (:maxlevel . 5)))))
(org-refile)))

那里的nil表示“当前缓冲区”。 let仅在本地重新定义变量。然后,您必须添加一个快捷方式来运行该功能。以下是将其绑定到C-c m的一种方法:

(add-hook 'org-mode-hook (lambda ()
        (local-set-key "\C-c m" 'refile-in-current)

答案 5 :(得分:1)

(require 'org-archive)                                                                               
(setq org-archive-save-context-info nil)                                                             
(setq org-archive-location "::* Archived Tasks")

在要移动的子树上运行(org-archive-subtree),它将被移动到&#34; *存档任务&#34;标题