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

397 lines
14 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.el --- org-mode config -*- lexical-binding: t -*-
;;; Commentary:
;;; Code:
(use-package org)
;; 一些随org-mode加载的基础配置
(add-hook 'org-mode-hook
(lambda ()
(require 'org-tempo)
(require 'init-org-refile)
(org-indent-mode)
(visual-line-mode)
(setq-local electric-pair-inhibit-predicate
(lambda (char)
(or (eq char ?<)
(electric-pair-default-inhibit char))))))
;; 预加载防止windows的org-mode加载卡顿
(if *is-windows*
(progn (run-with-idle-timer
0.5 nil
(lambda ()
(with-temp-buffer
(org-mode)
(org-mode))
(message "Org preloaded")))))
;; 设置标题字体大小
;; (with-eval-after-load 'org
;; (dolist (face org-level-faces)
;; (set-face-attribute face nil :height 1)))
;; log默认放入drawer中
(setq org-log-done t)
(setq org-log-into-drawer t)
;; 将系统时间(星期)设为英文,防止中文乱码
(setq system-time-locale "C")
;; 设置todo关键字
(setq org-todo-keywords
(quote ((sequence "TODO(t)" "STARTED(s)" "|" "DONE(d!/!)")
(sequence "WAITING(w@/!)" "SOMEDAY(S)" "|" "CANCELLED(c@/!)" "MEETING(m)" "PHONE(p)"))))
;; agenda相关
(cond
(*is-windows*
(setq org-agenda-files '("h:/emacs/hugo/this-is-my-blog/all-blog.org"
"h:/emacs/my-org-daily/"
"h:/emacs/my-org-note/")))
(*is-mac*
(setq org-agenda-files '("~/org/my-org-daily"
"~/org/my-org-note/")))
(*is-linux*
(setq org-agenda-files '("~/org/my-org-daily/"
"~/org/my-org-note/"))))
(setq org-agenda-span 'day)
(setq org-default-priority ?C)
(setq org-agenda-skip-function-global
'(org-agenda-skip-entry-if 'todo '("COMMENT")))
;; 批量调整表格
(defun org-table-align-all ()
"Ajust all table in current buffer."
(interactive)
(save-excursion
(goto-char (point-min))
(org-table-map-tables 'org-table-align t)))
;; org-babel scheme
(use-package ob-scheme
:straight (:type built-in)
:config
(add-to-list 'org-babel-load-languages '(scheme . t))
(org-babel-do-load-languages
'org-babel-load-languages
org-babel-load-languages))
;; org-contrib 和 org-checklist
(use-package org-contrib
:straight (org-contrib :type git :host github :repo "emacsmirror/org-contrib"
:depth 1)
:config
(add-hook 'org-mode-hook
(lambda ()
(require 'org-checklist nil t))))
;; org-download
(use-package org-download
:config
(when *is-mac*
(setq org-download-image-dir "./images")
(unless (file-exists-p "./images")
(make-directory "./images" t))
(setq org-download-link-format "[[file:%s]]\n")
(setq org-download-timestamp "%Y%m%d_%H%M%S_")
(setq org-download-dragndrop t)
(setq org-image-actual-width nil)
(setq org-download-image-html-width 600)
(add-hook 'org-mode-hook 'org-display-inline-images))
(with-eval-after-load 'org
(require 'org-download)
(setq org-return-follows-link t)))
;; org-journal
(use-package org-journal
:config
(setq org-journal-file-format "%Y-%m-%d.org"
org-journal-file-header "#+category: journal\n#+STARTUP: content\n\n"
org-journal-time-prefix "\n*** TODO "
org-journal-time-format "%m-%d \n<%Y-%m-%d %a %H:%M:%S>\n"
org-journal-hide-entries-p t
org-journal-date-format (lambda (time)
(format "* %s %s\n\n[%s]\n"
(format-time-string "%Y-%m-%d" time)
(format-time-string "%a" time)
(format-time-string "%Y-%m-%d %a" time)))
org-journal-carryover-items "TODO=\"TODO\"|TODO=\"STARTED\"|TODO=\"WAITING\"|TODO=\"SOMEDAY\"")
(if *is-windows*
(setq org-journal-dir "h:/emacs/my-org-daily/")
(setq org-journal-dir "~/org/my-org-daily/"))
(add-hook 'org-journal-mode-hook 'font-lock-update)
(defun my/journal-setup-new-day ()
(save-excursion
(org-back-to-heading)
(let ((day-end (save-excursion (org-end-of-subtree) (point))))
(unless (search-forward "** daily" day-end t)
(goto-char day-end)
(unless (bolp) (insert "\n"))
(insert "\n\n** daily\n\n\n")
(insert "** tasks\n")))))
(add-hook 'org-journal-after-header-create-hook #'my/journal-setup-new-day)
(defun my/journal-position-cursor-after-time ()
(when (derived-mode-p 'org-journal-mode)
(org-back-to-heading)
(end-of-line)))
(add-hook 'org-journal-after-entry-create-hook #'my/journal-position-cursor-after-time)
(defun org-journal-open-entry-for-editing (&optional event)
"Open journal entry for the date under cursor in calendar for editing."
(interactive
(list last-nonmenu-event))
(let* ((date (calendar-cursor-to-date t event))
(time (org-journal--calendar-date->time date))
(org-journal-file (org-journal--get-entry-path time)))
(if (file-exists-p org-journal-file)
(progn
(funcall org-journal-find-file org-journal-file)
(unless (org-journal--daily-p)
(org-journal--goto-entry date)))
(message "No journal entry for this date."))))
(defun my/org-journal-mark-old-todos-as-comment (entries)
"Change TODO entry's TODO keyword to COMMENT after carryover."
(save-excursion
(let* ((todo-keywords (cl-remove-if
(lambda (kw) (member kw org-done-keywords))
org-todo-keywords-1))
(todo-pattern (when todo-keywords
(regexp-opt todo-keywords 'words))))
(when todo-pattern
(mapc (lambda (entry)
(let ((start (car entry))
(end (set-marker (make-marker) (cadr entry))))
(goto-char start)
(while (re-search-forward (concat "^\\(\\*+ \\)" todo-pattern) end t)
(replace-match "\\1COMMENT" t nil))
(set-marker end nil)))
(reverse entries))))
(save-buffer)))
(setq org-journal-handle-old-carryover-fn #'my/org-journal-mark-old-todos-as-comment)
;; 在org-journal加载cns-mode
(add-hook 'org-journal-mode-hook
(lambda ()
(global-cns-mode-enable-in-buffer))))
;; org-ql
(use-package org-ql
:config
(with-eval-after-load 'org-ql-view
(keymap-set org-ql-view-map (kbd "q") 'org-agenda-Quit))
(setq org-ql-views
'(("tags: emacs category:note"
:buffers-files org-agenda-files
:query (and (tags "emacs") (category "note"))
:sort date)
("group by time"
:buffers-files org-agenda-files
:query (and (ts :to "today") (tags "root"))
:sort date
:super-groups ((:auto-ts t)))
("group by category"
:buffers-files org-agenda-files
:query (tags "root")
:super-groups ((:auto-property "CATEGORY"))))))
;; org-super-agenda 配置
(use-package org-super-agenda
:config
(org-super-agenda-mode))
;; 自定义已完成任务视图
(setq org-agenda-custom-commands
'(("pa" "Priority >= A"
((tags-todo "+PRIORITY=\"A\"")))
("pb" "Priority >= B"
((tags-todo "+PRIORITY<=\"B\"")))
("pc" "Priority >= C"
((tags-todo "+PRIORITY<=\"C\"")))
("qd" "TODO entries sort by closed time"
((org-ql-block '(closed)
((org-ql-block-header "Closed TODOs")
(org-ql-sort '(closed))
(org-super-agenda-groups
'((:auto-ts t)))))))
("qS" "SOMEDAYs"
((org-ql-block '(todo "SOMEDAY")
((org-ql-block-header "SOMEDAYs")
(org-ql-sort '(start-time))
(org-super-agenda-groups
'((:auto-ts t)))))))
("qs" "STARTEDs"
((org-ql-block '(todo "STARTED")
((org-ql-block-header "STARTEDs")
(org-ql-sort '(start-time))
(org-super-agenda-groups
'((:auto-ts t)))))))
("qt" "TODOs sort by start time"
((org-ql-block '(todo)
((org-ql-block-header "TODOs")
(org-ql-sort '(start-time))
(org-super-agenda-groups
'((:auto-ts t)))))))
("qa" "all TODO entries"
((org-ql-block '(and (not (done)) (todo))
((org-ql-block-header "all TODOs")
(org-super-agenda-groups
'((:name "started" :todo "STARTED")
(:name "priority = A" :priority "A")
(:name "priority = B" :priority "B")
(:name "other priority" :priority< "B")
(:name "someday" :todo "SOMEDAY")
))))))))
(setq org-tag-alist '(
("scheme" . ?s)
("emacs" . ?e)
("elisp" . ?E)
("org" . ?o)
("linux" . ?l)
("computer-stuff" . ?c)
("philosophy" . ?p)
("game" . ?g)
("gamestudies" . ?G)
("masterpiece" . ?m)
))
;; (setq org-tags-exclude-from-inheritance '())
;; capture模板
(defvar my-org-capture-temp-title "" "Temporarily store the org-capture filename.")
(setq org-capture-templates
'(("n" "New Note" plain
(file (lambda ()
(setq my-org-capture-temp-title (read-string "Filename (without .org): "))
(expand-file-name (if *is-windows*
(format "%s/%s-%s.org"
"h:/emacs/my-org-note/"
(format-time-string "%Y%m%d")
my-org-capture-temp-title)
(format "%s/%s-%s.org"
"~/org/my-org-note/"
(format-time-string "%Y%m%d")
my-org-capture-temp-title)))))
"
#+title: %(symbol-value 'my-org-capture-temp-title)
#+date: %U
#+category: %^{Category|none|project|book|article|note|wisdom|fun|data}
* %(symbol-value 'my-org-capture-temp-title) :root%^g
:PROPERTIES:
:END:
%U
%?
# Local Variables:
# org-use-tag-inheritance: nil
# End:
"
:jump-to-captured t)))
(setq org-bookmark-names-plist nil)
;; hugo
;; 安装ox-hugo
(use-package ox-hugo)
(with-eval-after-load 'org-capture
(defun org-hugo-new-subtree-post-capture-template ()
"Returns `org-capture' template string for new Hugo post.
See `org-capture-templates' for more information."
(let* ((title (read-from-minibuffer "Post Title: ")) ;Prompt to enter the post title
(fname (org-hugo-slug title)))
(mapconcat #'identity
`(
,(concat "* TODO " title)
":PROPERTIES:"
,(concat ":EXPORT_FILE_NAME: " fname)
":END:"
"\n\n") ;Place the cursor here finally
"\n")))
(if *is-windows*
(add-to-list 'org-capture-templates
'("h" ;`org-capture' binding + h
"Hugo post"
entry
;; It is assumed that below file is present in `org-directory'
;; and that it has a "Blog Ideas" heading. It can even be a
;; symlink pointing to the actual location of all-posts.org!
(file+headline "h:/emacs/hugo/this-is-my-blog/all-blog.org" "Blog Ideas")
(function org-hugo-new-subtree-post-capture-template)))
(add-to-list 'org-capture-templates
'("h" ;`org-capture' binding + h
"Hugo post"
entry
;; It is assumed that below file is present in `org-directory'
;; and that it has a "Blog Ideas" heading. It can even be a
;; symlink pointing to the actual location of all-posts.org!
(file+headline "~/org/hugo/this-is-my-blog/all-blog.org" "Blog Ideas")
(function org-hugo-new-subtree-post-capture-template)))))
;; 快速部署
(defun my-blog-publish ()
"Publish blog , git add/commit/push , generate commit message."
(interactive)
(let* ((blog-dir (if *is-windows*
"h:/emacs/hugo/this-is-my-blog/"
"~/org/hugo/this-is-my-blog/"))
(timestamp (format-time-string "%Y-%m-%d %H:%M:%S"))
(default-directory blog-dir))
;; save buffer
(save-buffer)
;; git add
(message "Adding files...")
(eshell-command "git add .")
;; git commit with timestamp
(message "Committing: %s" timestamp)
(eshell-command (format "git commit -m \"Update: %s\"" timestamp))
;; git push
(message "Pushing to remote...")
(let ((exit-code (eshell-command "git push")))
(if (eq exit-code t)
(message "Push may have failed or nothing to push, check *Messages* buffer for details")
(message "Push successfully %s" timestamp)))))
;; 预览博客
(defun my-blog-preview ()
"Save and preview blog."
(interactive)
(save-buffer)
(let ((default-directory (if *is-windows*
"h:/emacs/hugo/this-is-my-blog/"
"~/org/hugo/this-is-my-blog/")))
;; 启动 Hugo server
(start-process "hugo-server" "*hugo-server*"
"hugo" "server" "-D" "--bind" "0.0.0.0" "--port" "1313")
;; 等待服务器启动
(sleep-for 2)
;; 自动打开浏览器
(browse-url "http://localhost:1313")))
(provide 'init-org)
;;; init-org.el ends here