M config/pkg-org.el => config/pkg-org.el +93 -0
@@ 139,6 139,99 @@ Format: ((key label file ((subkey sublabel headline template override-file) ...)
;; Org Workflow Configuration
;; Agenda, refile, and capture setup
(with-eval-after-load 'org
+ ;; --- Custom Agenda Views ---
+ ;; 将"想读"的书转为"正在读"(创建书籍笔记并删除原条目)
+ (defun my/reading-start-book ()
+ "Start reading a book: create a note entry and remove from wishlist."
+ (interactive)
+ (org-agenda-check-type t 'agenda 'tags)
+ (let* ((marker (or (org-get-at-bol 'org-marker)
+ (org-agenda-error)))
+ (buffer (marker-buffer marker))
+ (pos (marker-position marker))
+ book-name)
+ ;; 获取书名
+ (with-current-buffer buffer
+ (goto-char pos)
+ (setq book-name (org-get-heading t t t t)))
+ ;; 确认操作
+ (when (y-or-n-p (format "开始阅读《%s》?" book-name))
+ ;; 删除原条目
+ (org-agenda-kill)
+ ;; 创建书籍笔记
+ (let ((org-capture-templates
+ `(("b" "书籍笔记" entry
+ (file+headline ,(expand-file-name "reading.org" org-directory) "书籍笔记")
+ ,(format "** 《%s》笔记 %%^{序号}: %%^{标题}\n%%U\n\n%%?" book-name)))))
+ (org-capture nil "b")))))
+
+ ;; 将"正在读"的书标记为"读完"(创建读后感)
+ (defun my/reading-finish-book ()
+ "Finish reading a book: create a review entry."
+ (interactive)
+ (org-agenda-check-type t 'agenda 'tags)
+ (let* ((marker (or (org-get-at-bol 'org-marker)
+ (org-agenda-error)))
+ (buffer (marker-buffer marker))
+ (pos (marker-position marker))
+ book-name)
+ ;; 从标题中提取书名(格式:《书名》笔记 X: 标题)
+ (with-current-buffer buffer
+ (goto-char pos)
+ (let ((heading (org-get-heading t t t t)))
+ (if (string-match "《\\([^》]+\\)》" heading)
+ (setq book-name (match-string 1 heading))
+ (setq book-name (read-string "书名: ")))))
+ ;; 创建读后感
+ (let ((org-capture-templates
+ `(("d" "读后感" entry
+ (file+headline ,(expand-file-name "reading.org" org-directory) "读完")
+ ,(format "** 《%s》读后感\n:PROPERTIES:\n:FINISHED: %%U\n:END:\n\n%%?" book-name)))))
+ (org-capture nil "d"))))
+
+ ;; 辅助函数:跳过不在指定父标题下的条目
+ (defun my/org-agenda-skip-unless-parent (parent-headline)
+ "Skip entry unless its parent headline matches PARENT-HEADLINE."
+ (let ((dominated nil))
+ (save-excursion
+ (while (and (not dominated) (org-up-heading-safe))
+ (when (string= (org-get-heading t t t t) parent-headline)
+ (setq dominated t))))
+ (if dominated
+ nil ; 不跳过
+ (save-excursion (org-end-of-subtree t))))) ; 跳过
+
+ (setq org-agenda-custom-commands
+ '(;; Reading lists
+ ("r" . "Reading (书单)")
+ ("rw" "想读的书" tags "LEVEL=2"
+ ((org-agenda-files (list (expand-file-name "reading.org" org-directory)))
+ (org-agenda-overriding-header "想读的书")
+ (org-agenda-prefix-format " ")
+ (org-agenda-skip-function '(my/org-agenda-skip-unless-parent "想读"))))
+ ("rb" "正在读 (书籍笔记)" tags "LEVEL=2"
+ ((org-agenda-files (list (expand-file-name "reading.org" org-directory)))
+ (org-agenda-overriding-header "正在读的书")
+ (org-agenda-prefix-format " ")
+ (org-agenda-skip-function '(my/org-agenda-skip-unless-parent "书籍笔记"))))
+ ("rd" "读完的书" tags "LEVEL=2"
+ ((org-agenda-files (list (expand-file-name "reading.org" org-directory)))
+ (org-agenda-overriding-header "读完的书")
+ (org-agenda-prefix-format " ")
+ (org-agenda-skip-function '(my/org-agenda-skip-unless-parent "读完"))))
+ ;; Inbox items
+ ("i" . "Inbox")
+ ("is" "分享项目" tags "LEVEL=2"
+ ((org-agenda-files (list (expand-file-name "inbox.org" org-directory)))
+ (org-agenda-overriding-header "分享的项目/工具")
+ (org-agenda-prefix-format " ")
+ (org-agenda-skip-function '(my/org-agenda-skip-unless-parent "分享"))))))
+
+ ;; Agenda 快捷键:书单操作
+ (with-eval-after-load 'org-agenda
+ (define-key org-agenda-mode-map (kbd "S") #'my/reading-start-book)
+ (define-key org-agenda-mode-map (kbd "F") #'my/reading-finish-book))
+
;; --- Refile Configuration ---
;; 强化 Refile 功能,允许将条目移动到项目或分类的具体标题下
(setq org-refile-use-outline-path 'file)
M org-structure.org => org-structure.org +12 -0
@@ 182,12 182,24 @@
:HEADLINE: Inbox
:TEMPLATE: * TODO Read: %^{Title}\n :PROPERTIES:\n :SOURCE: %^{Source|Web|Book|Paper|Other}\n :URL: %^{Url}\n :ADDED: %U\n :END:\n %?
:END:
+** 想读
+ :PROPERTIES:
+ :KEY: w
+ :HEADLINE: 想读
+ :TEMPLATE: ** %^{书名}\n:PROPERTIES:\n:SOURCE: %^{来源}\n:ADDED: %U\n:END:\n%?
+ :END:
** 书籍笔记
:PROPERTIES:
:KEY: b
:HEADLINE: 书籍笔记
:TEMPLATE: ** 《%^{书名}》笔记 %^{序号}: %^{标题}\n%U\n\n%?
:END:
+** 读完
+ :PROPERTIES:
+ :KEY: d
+ :HEADLINE: 读完
+ :TEMPLATE: ** 《%^{书名}》读后感\n:PROPERTIES:\n:FINISHED: %U\n:END:\n\n%?
+ :END:
** 课程笔记
:PROPERTIES:
:KEY: c