Как переместить поддерево в другое поддерево в org-mode emacs

Я хотел бы выполнить одну простую задачу, но, похоже, для нее нет четкого решения:

У меня есть структура таких поддеревьев:

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

Я хотел бы создать один ключевой ярлык для перемещения поддеревьев из дерева A в дерево B. Перемещение в архив кажется простым, но знаете ли вы, как это сделать в одном файле?

Любая помощь ценится! Спасибо!

Ответ 1

Вы можете попробовать пополнить поддерево с помощью C-c C-w (он также работает, чтобы переместить поддерево в другой файл).

Другой способ - свернуть поддерево, а затем убить его с помощью C-k C-k и вставить его там, где он должен быть.

Третье решение, которое я использую некоторое время, это изменить уровень поддерева с помощью M-left, затем переместить его с помощью M-up и M-down, затем M-right снова направить его на правильный уровень. Этот третий путь имеет недостаток, что некоторое время он заставляет другую часть дерева двигаться.

Ответ 2

Я также хотел, чтобы org-refile легко поддавался поддерево, поэтому я написал некоторый код и обобщил его так, чтобы он установил произвольную ближайшую цель в любом месте (не только в том же файле).

Основное использование - это перемещение где-то в Tree B и введите C-c C-x C-m, чтобы пометить цель для перепрофилирования, затем перейдите к записи в Tree A, которую вы хотите перефилировать, и введите C-c C-w, который будет немедленно повторно вставлен в целевое местоположение, установленное в Tree B, без запроса, если вы не вызвали org-refile-immediate-target с префиксом arg C-u C-c C-x C-m.

Обратите внимание, что если вы нажмете C-c C-w в быстрой последовательности для повторного набора нескольких записей, он сохранит порядок ваших записей, даже если для параметра org-reverse-note-order установлено значение t, но вы можете отключить его, чтобы соблюдать настройку org-reverse-note-order с двойным префиксом arg C-u C-u C-c C-x C-m.

(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)

Трудно было найти ключ, свободный от префикса C-c C-x, поэтому я использовал m с мнемонической я * mm * ediate

Ответ 3

Я использую M-left, M-up/down, а затем M-right, если структура файла не слишком сложна. Но имейте в виду, что если вы попытаетесь переместить Subtree A1 в Tree B с помощью этого метода, вы потеряете его дочерний Subsubtree A1.1, если вы не переместите его с помощью M-S-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

Ответ 4

Вы можете подделать поддерево, используя C-c C-w, в зависимости от того, как вы настроили рефикс. В зависимости от глубины вашего адресата вы не сможете использовать его в качестве действительного адресата.

Вы можете убить или скопировать поддерево, не сворачивая структуру, используя команды поддерева kill/copy: C-c C-x C-w и C-c C-x M-w соответственно, yanking поддерева либо C-c C-x C-y, либо просто C-y

Ответ 5

Перемещение поддерева в том же буфере можно сделать с помощью org-refile. Во время перемещения вы можете даже изменить иерархию оригинала (количество звезд). Тем не менее, это может не работать из коробки, потому что буфер, с которым вы работаете, находится не в org-refile-targets. Вы можете добавить файл в целевые объекты refile с помощью C-[, затем запустите org-refile с помощью C-c C-w и, наконец, удалите файл из целевых файлов refile с помощью C-]. Это может быть слишком много (и может потерпеть неудачу, если ваш параметр 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)

Ответ 6

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

run (org-archive-subtree) в поддереве, который вы хотите переместить, он будет перемещен в заголовок "* Архивные задачи"