Files
.emacs.d/lisp/init-org-refile.el

143 lines
4.9 KiB
EmacsLisp
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
;;; init-org-refile.el --- org-refile config -*- lexical-binding: t -*-
;;; Commentary:
;;; Code:
(defun my-org-refile-to-new-file ()
"org-refile as a separate org file with custom template."
(interactive)
(require 'org-element)
(org-back-to-heading t)
(let* ((heading-components (org-heading-components))
;; (todo (nth 2 heading-components)) ; 保留todo状态
(raw-title (nth 4 heading-components)) ; 纯标题文本
(tags (org-get-tags nil t))
(begin (point))
(end (save-excursion (org-end-of-subtree t t) (point)))
(original-content (buffer-substring begin end))
;; 检测原条目是否有属性不包括logbook
(has-properties-p
(with-temp-buffer
(insert original-content)
(goto-char (point-min))
(forward-line 1) ; 跳过headline
(looking-at org-property-drawer-re)))
;; 如果有属性则提取内容
(original-props
(when has-properties-p
(with-temp-buffer
(insert original-content)
(goto-char (point-min))
(forward-line 1)
(let ((start (point)))
(when (re-search-forward ":END:" nil t)
(forward-line 1)
(buffer-substring start (point)))))))
;; 询问文件名,保留中文,只替换空格和特殊字符
(default-name (replace-regexp-in-string "[ \\/:*?\"<>|]" "_" raw-title))
(user-filename (read-string "Filename (without .org): " default-name))
(filename (format "%s-%s.org"
(format-time-string "%Y%m%d")
user-filename))
(target-dir (if *is-windows*
"h:/emacs/my-org-note/"
"~/org/my-org-note/"))
(filepath (expand-file-name filename target-dir))
;; 询问category
(category (completing-read "Category: "
'("none" "note" "project")
nil t "project"))
;; 询问 Tags原有标签作为默认值
(tag-input (read-string "Tags (space separated): "
(mapconcat #'identity tags " ")))
(formatted-tags
(if (and tag-input (not (string= tag-input "")))
(concat ":" (replace-regexp-in-string " " ":" tag-input) ":")
""))
;; 提取body
(body
(with-temp-buffer
(insert original-content)
(goto-char (point-min))
(forward-line 1)
;; 如果有属性抽屉则跳过
(when (looking-at org-property-drawer-re)
(while (not (looking-at org-property-end-re))
(forward-line 1))
(forward-line 1))
;; 跳过schedule和deadline
;; (when (looking-at org-planning-line-re)
;; (forward-line 1))
;; 清理开头的空行
(skip-chars-forward "\n")
(buffer-substring (point) (point-max)))))
;; 检查文件是否存在
(when (and (file-exists-p filepath)
(not (y-or-n-p (format "File %s exists. Overwrite? " filename))))
(error "Refile canceled"))
(unless (file-exists-p target-dir)
(make-directory target-dir t))
;; 将原条目的TODO关键字改为COMMENT如果有
(let ((todo (nth 2 heading-components)))
(when todo
(save-excursion
(goto-char begin)
(when (re-search-forward (concat "^\\(\\*+ \\s-*\\)" (regexp-quote todo)) (save-excursion (forward-line 1) (point)) t)
(replace-match "\\1COMMENT" t nil)))))
;; 创建新文件
(condition-case err
(with-temp-file filepath
;; 文件头
(insert (format "#+title: %s\n" user-filename))
(insert (format "#+date: %s\n" (format-time-string "[%Y-%m-%d %a %H:%M]")))
(insert (format "#+category: %s\n\n" category))
;; 插入标题和tag
(insert (format "* STARTED %s %s\n"
;; (if todo (concat todo " ") "")
user-filename
formatted-tags))
;; 只有原条目有属性时才插入
(when original-props
(insert original-props))
;; 插入body
(insert body)
;; 确保格式正确,添加文件尾局部变量
(unless (bolp) (insert "\n"))
(insert "\n# Local Variables:\n# org-use-tag-inheritance: nil\n# End:\n"))
(error
(goto-char begin)
(insert original-content)
(error "Failed to create file: %s" err)))
(find-file-other-window filepath)
(message "Successfully refiled to %s" filepath)))
(with-eval-after-load 'org
(define-key org-mode-map (kbd "C-c o w") #'my-org-refile-to-new-file))
(provide 'init-org-refile)
;;; init-org-refile.el ends here