這是一份「文學編程」(literate)org 文件。 當 literate 模組被啟用,Doom Emacs 會在啟動時或設定檔改變自動 tangle。讀者應具備對 Emacs 的使用經驗。

原則

  1. 所有的設定檔都應該有註解;
  2. 所有的模組宣告必須寫在 init.el.
  3. 所有的 package! 宣告必須寫在 packages.el.
  4. 所有的其他 LISP code 比需寫在 config.el.

Doom 設定檔概要

Doom Emacs 使用下面三個檔案:

init.el
定義哪些 Doom 模組會被讀取。
packages.el
定義哪些套件應該被安裝。
config.el
包含所有自定的設定檔和程試碼。

所有的設定檔從這個檔案產生,並且盡可能清楚。

設定檔檔頭

這些檔案檔頭來自安裝doom時產生的初始化文件,包含一些 Emacs-LISP 相關的指標,如詞法綁定,或者關於文件內容的說明。

;;; init.el -*- lexical-binding: t; -*-

;; DO NOT EDIT THIS FILE DIRECTLY
;; This is a file generated from a literate programing source file.

;; This file controls what Doom modules are enabled and what order they load
;; in. Remember to run 'doom sync' after modifying it!

;; NOTE Press 'SPC h d h' (or 'C-h d h' for non-vim users) to access Doom's
;;      documentation. There you'll find a "Module Index" link where you'll find
;;      a comprehensive list of Doom's modules and what flags they support.

;; NOTE Move your cursor over a module's name (or its flags) and press 'K' (or
;;      'C-c c k' for non-vim users) to view its documentation. This works on
;;      flags as well (those symbols that start with a plus).
;;
;;      Alternatively, press 'gd' (or 'C-c c d') on a module to browse its
;;      directory (for easy access to its source code).
;; -*- no-byte-compile: t; -*-
;;; $DOOMDIR/packages.el

;; DO NOT EDIT THIS FILE DIRECTLY
;; This is a file generated from a literate programing source file.
;;
;; You should make any changes there and regenerate it from Emacs org-mode
;; using org-babel-tangle (C-c C-v t)

;; To install a package with Doom you must declare them here and run 'doom sync'
;; on the command line, then restart Emacs for the changes to take effect -- or
;; use 'M-x doom/reload'.

;; To install SOME-PACKAGE from MELPA, ELPA or emacsmirror:
;;(package! some-package)

;; To install a package directly from a remote git repo, you must specify a
;; `:recipe'. You'll find documentation on what `:recipe' accepts here:
;; https://github.com/raxod502/straight.el#the-recipe-format
;;(package! another-package
;;  :recipe (:host github :repo "username/repo"))

;; If the package you are trying to install does not contain a PACKAGENAME.el
;; file, or is located in a subdirectory of the repo, you'll need to specify
;; `:files' in the `:recipe':
;;(package! this-package
;;  :recipe (:host github :repo "username/repo"
;;           :files ("some-file.el" "src/lisp/*.el")))

;; If you'd like to disable a package included with Doom, you can do so here
;; with the `:disable' property:
;;(package! builtin-package :disable t)

;; You can override the recipe of a built in package without having to specify
;; all the properties for `:recipe'. These will inherit the rest of its recipe
;; from Doom or MELPA/ELPA/Emacsmirror:
;;(package! builtin-package :recipe (:nonrecursive t))
;;(package! builtin-package-2 :recipe (:repo "myfork/package"))

;; Specify a `:branch' to install a package from a particular branch or tag.
;; This is required for some packages whose default branch isn't 'master' (which
;; our package manager can't deal with; see raxod502/straight.el#279)
;;(package! builtin-package :recipe (:branch "develop"))

;; Use `:pin' to specify a particular commit to install.
;;(package! builtin-package :pin "1a2b3c4d5e")

;; Doom's packages are pinned to a specific commit and updated from release to
;; release. The `unpin!' macro allows you to unpin single packages...
;;(unpin! pinned-package)
;; ...or multiple packages
;;(unpin! pinned-package another-pinned-package)
;; ...Or *all* packages (NOT RECOMMENDED; will likely break things)
;;(unpin! t)
;;; config.el -*- lexical-binding: t; -*-

;; DO NOT EDIT THIS FILE DIRECTLY
;; This is a file generated from a literate programing source file.

;; You should make any changes there and regenerate it from Emacs org-mode
;; using org-babel-tangle (C-c C-v t)

;; Place your private configuration here! Remember, you do not need to run 'doom
;; sync' after modifying this file!

;; Some functionality uses this to identify you, e.g. GPG configuration, email
;; clients, file templates and snippets.
;; (setq user-full-name ""
;;      user-mail-address "")

;; Doom exposes five (optional) variables for controlling fonts in Doom. Here
;; are the three important ones:
;;
;; + `doom-font'
;; + `doom-variable-pitch-font'
;; + `doom-big-font' -- used for `doom-big-font-mode'; use this for
;;   presentations or streaming.
;;
;; They all accept either a font-spec, font string ("Input Mono-12"), or xlfd
;; font string. You generally only need these two:
;; (setq doom-font (font-spec :family "monospace" :size 12 :weight 'semi-light)
;;       doom-variable-pitch-font (font-spec :family "sans" :size 13))

;; There are two ways to load a theme. Both assume the theme is installed and
;; available. You can either set `doom-theme' or manually load a theme with the
;; `load-theme' function. This is the default:
;; (setq doom-theme 'doom-one)

;; If you use `org' and don't want your org files in the default location below,
;; change `org-directory'. It must be set before org loads!
;; (setq org-directory "~/org/")

;; This determines the style of line numbers in effect. If set to `nil', line
;; numbers are disabled. For relative line numbers, set this to `relative'.
;; (setq display-line-numbers-type t)

;; Here are some additional functions/macros that could help you configure Doom:
;;
;; - `load!' for loading external *.el files relative to this one
;; - `use-package!' for configuring packages
;; - `after!' for running code after a package has loaded
;; - `add-load-path!' for adding directories to the `load-path', relative to
;;   this file. Emacs searches the `load-path' when you load packages with
;;   `require' or `use-package'.
;; - `map!' for binding new keys
;;
;; To get information about any of these functions/macros, move the cursor over
;; the highlighted symbol at press 'K' (non-evil users must press 'C-c c k').
;; This will open documentation for it, including demos of how they are used.
;;
;; You can also try 'gd' (or 'C-c c d') to jump to their definition and see how
;; they are implemented.

自定義變數

Doom 不推薦使用 Emacs 內建的機制:

Note: do not use M-x customize or the customize API in general. Doom is designed to be configured programmatically from your config.el, which can conflict with Customize’s way of modifying variables.

If you’re concerned about defcustom setters, Doom has a setq! macro that will trigger them.

所有需要的設定都寫在這個檔案。

Doom 模組

如同 Spaceemacs, Doom Emacs 的社群提供大量設定好的配置讓我們使用。下面這段代碼被寫入 init.el 中,以選擇要加載的模組。

(doom! :input
       ;;chinese
       ;;japanese
       ;;layout            ; auie,ctsrnm is the superior home row

       :completion
       company           ; the ultimate code completion backend
       ;;helm              ; the *other* search engine for love and life
       ;;ido               ; the other *other* search engine...
       ivy               ; a search engine for love and life

       :ui
       deft              ; notational velocity for Emacs
       doom              ; what makes DOOM look the way it does
       doom-dashboard    ; a nifty splash screen for Emacs
       doom-quit         ; DOOM quit-message prompts when you quit Emacs
       ;;(emoji +unicode)  ; 🙂
       ;;fill-column       ; a `fill-column' indicator
       hl-todo           ; highlight TODO/FIXME/NOTE/DEPRECATED/HACK/REVIEW
       ;;hydra
       ;;indent-guides     ; highlighted indent columns
       ligatures         ; ligatures and symbols to make your code pretty again
       ;;minimap           ; show a map of the code on the side
       modeline          ; snazzy, Atom-inspired modeline, plus API
       ;;nav-flash         ; blink cursor line after big motions
       ;;neotree           ; a project drawer, like NERDTree for vim
       ophints           ; highlight the region an operation acts on
       (popup +defaults)   ; tame sudden yet inevitable temporary windows
       ;;tabs              ; a tab bar for Emacs
       treemacs          ; a project drawer, like neotree but cooler
       ;;unicode           ; extended unicode support for various languages
       vc-gutter         ; vcs diff in the fringe
       vi-tilde-fringe   ; fringe tildes to mark beyond EOB
       ;;window-select     ; visually switch windows
       workspaces        ; tab emulation, persistence & separate workspaces
       zen               ; distraction-free coding or writing

       :editor
       (evil +everywhere); come to the dark side, we have cookies
       file-templates    ; auto-snippets for empty files
       fold              ; (nigh) universal code folding
       ;;(format +onsave)  ; automated prettiness
       ;;god               ; run Emacs commands without modifier keys
       ;;lispy             ; vim for lisp, for people who don't like vim
       ;;multiple-cursors  ; editing in many places at once
       ;;objed             ; text object editing for the innocent
       ;;parinfer          ; turn lisp into python, sort of
       ;;rotate-text       ; cycle region at point between text candidates
       snippets          ; my elves. They type so I don't have to
       word-wrap         ; soft wrapping with language-aware indent

       :emacs
       dired             ; making dired pretty [functional]
       electric          ; smarter, keyword-based electric-indent
       ;;ibuffer         ; interactive buffer management
       undo              ; persistent, smarter undo for your inevitable mistakes
       vc                ; version-control and Emacs, sitting in a tree

       :term
       ;;eshell            ; the elisp shell that works everywhere
       ;;shell             ; simple shell REPL for Emacs
       ;;term              ; basic terminal emulator for Emacs
       vterm             ; the best terminal emulation in Emacs

       :checkers
       syntax              ; tasing you for every semicolon you forget
       ;;spell             ; tasing you for misspelling mispelling
       ;;grammar           ; tasing grammar mistake every you make

       :tools
       ;;ansible
       ;;debugger          ; FIXME stepping through code, to help you add bugs
       ;;direnv
       ;;docker
       editorconfig      ; let someone else argue about tabs vs spaces
       ;;ein               ; tame Jupyter notebooks with emacs
       (eval +overlay)     ; run code, run (also, repls)
       ;;gist              ; interacting with github gists
       lookup              ; navigate your code and its documentation
       ;;lsp
       magit             ; a git porcelain for Emacs
       ;;make              ; run make tasks from Emacs
       ;;pass              ; password manager for nerds
       pdf               ; pdf enhancements
       ;;prodigy           ; FIXME managing external services & code builders
       ;;rgb               ; creating color strings
       ;;taskrunner        ; taskrunner for all your projects
       ;;terraform         ; infrastructure as code
       ;;tmux              ; an API for interacting with tmux
       ;;upload            ; map local to remote projects via ssh/ftp

       :os
       (:if IS-MAC macos)  ; improve compatibility with macOS
       ;;tty               ; improve the terminal Emacs experience

       :lang
       ;;agda              ; types of types of types of types...
       ;;cc                ; C/C++/Obj-C madness
       ;;clojure           ; java with a lisp
       ;;common-lisp       ; if you've seen one lisp, you've seen them all
       ;;coq               ; proofs-as-programs
       ;;crystal           ; ruby at the speed of c
       ;;csharp            ; unity, .NET, and mono shenanigans
       ;;data              ; config/data formats
       ;;(dart +flutter)   ; paint ui and not much else
       ;;elixir            ; erlang done right
       ;;elm               ; care for a cup of TEA?
       emacs-lisp        ; drown in parentheses
       ;;erlang            ; an elegant language for a more civilized age
       ;;ess               ; emacs speaks statistics
       ;;faust             ; dsp, but you get to keep your soul
       ;;fsharp            ; ML stands for Microsoft's Language
       ;;fstar             ; (dependent) types and (monadic) effects and Z3
       ;;gdscript          ; the language you waited for
       ;;(go +lsp)         ; the hipster dialect
       ;;(haskell +dante)  ; a language that's lazier than I am
       ;;hy                ; readability of scheme w/ speed of python
       ;;idris             ; a language you can depend on
       json              ; At least it ain't XML
       ;;(java +meghanada) ; the poster child for carpal tunnel syndrome
       javascript        ; all(hope(abandon(ye(who(enter(here))))))
       ;;julia             ; a better, faster MATLAB
       ;;kotlin            ; a better, slicker Java(Script)
       ;;latex             ; writing papers in Emacs has never been so fun
       ;;lean
       ;;factor
       ;;ledger            ; an accounting system in Emacs
       ;;lua               ; one-based indices? one-based indices
       markdown          ; writing docs for people to ignore
       ;;nim               ; python + lisp at the speed of c
       ;;nix               ; I hereby declare "nix geht mehr!"
       ;;ocaml             ; an objective camel
       (org              ; organize your plain life in plain text
        +pretty
        +dragndrop       ; drag & drop files/images into org buffers
        ;;+journal      ; maintain a simple personal diary / journal using in Emacs.
        +roam
        +noter
        +hugo           ; Enables integration with hugo to export from Emacs well-formed (blackfriday) markdown.
        +present        ; using org-mode for presentations
        )
       ;;php               ; perl's insecure younger brother
       plantuml          ; diagrams for confusing people more
       ;;purescript        ; javascript, but functional
       ;;python            ; beautiful is better than ugly
       ;;qt                ; the 'cutest' gui framework ever
       ;;racket            ; a DSL for DSLs
       ;;raku              ; the artist formerly known as perl6
       ;;rest              ; Emacs as a REST client
       ;;rst               ; ReST in peace
       ;;(ruby +rails)     ; 1.step {|i| p "Ruby is #{i.even? ? 'love' : 'life'}"}
       rust              ; Fe2O3.unwrap().unwrap().unwrap().unwrap()
       ;;scala             ; java, but good
       ;;scheme            ; a fully conniving family of lisps
       sh                ; she sells {ba,z,fi}sh shells on the C xor
       ;;sml
       ;;solidity          ; do you need a blockchain? No.
       ;;swift             ; who asked for emoji variables?
       ;;terra             ; Earth and Moon in alignment for performance.
       ;;web               ; the tubes
       yaml              ; JSON, but readable

       :email
       ;;(mu4e +gmail)
       ;;notmuch
       ;;(wanderlust +gmail)

       :app
       calendar
       ;;irc               ; how neckbeards socialize
       ;;(rss +org)        ; emacs as an RSS reader
       ;;twitter           ; twitter client https://twitter.com/vnought

       :config
       literate
       (default +bindings))

一般設定

個人資訊

用來識別我自己的功能。e.g. GPG 設定, Email 客戶端。

(setq user-full-name "Hsin-Yi Chen"
      user-mail-address "ossug.hychen@gmail.com"
      user-blog-basedir "~/github/hychen/blog/"
      user-blog-url "https://hychen.me"
      )

視窗設定

如果由Emacs 指令或桌面文件啟動,則在啟動時將視窗最大化。

(if (eq initial-window-system 'x)
    (toggle-frame-maximized)
  (toggle-frame-fullscreen))

字型設定。 我目前使用 Manaco。

(setq doom-font (font-spec :family "Monaco" :size 16 :weight 'semi-light))

主題使用預設。

(setq doom-theme 'doom-one)

Org Mode

使用 Dropbox 做跨裝置的檔案同步備份。

(setq shared-directory "~/Dropbox")

Org 文件的預設目錄位置

(setq org-directory (expand-file-name "org" shared-directory))

隱藏 ~, *, = 等註記。

(after! org (setq org-hide-emphasis-markers t))

能夠使用 SPC t e 顯示或隱藏。

(defun org-toggle-emphasis ()
  "Toggle hiding/showing of org emphasize markers."
  (interactive)
  (if org-hide-emphasis-markers
      (set-variable 'org-hide-emphasis-markers nil)
    (set-variable 'org-hide-emphasis-markers t)))

文件結構樹

偏好文件過於龐大時,才開使分拆。文件數少,每日消耗的認知也少。

todo.org
個人代辦事項。
projects.org
專案代辦事項。
blog.org
blog 文章。
habits.org
想要陪養的習慣追蹤紀錄。
roam
知識管理系統。
(after! org
  (setq org-todo-file (expand-file-name "todo.org" org-directory))
  (setq org-project-file (expand-file-name "projects.org" org-directory))
  (setq org-post-file (expand-file-name "blog.org" org-directory))
  (setq org-habit-file (expand-file-name "habits.org" org-directory)))

筆記

受 Roam Research 啟發,以使用 Zettelkasten 卡片盒筆記法組織知識連結知識點為目的配置。

org-roam

org-roam 是類似 Roam Research 的 org-mode 實現。

(after! org-roam (setq org-roam-directory (expand-file-name "roam" org-directory)))

org-roam-server

(package! org-roam-server :recipe (:host github :repo "org-roam/org-roam-server" :files ("*")))
(use-package! org-roam-server
  :after org-roam
  :config
  (setq org-roam-server-host "127.0.0.1"
        org-roam-server-port 8080
        org-roam-server-export-inline-images t
        org-roam-server-authenticate nil
        org-roam-server-network-arrows nil
        org-roam-server-network-label-truncate t
        org-roam-server-network-label-truncate-length 60
        org-roam-server-network-label-wrap-length 20)
  (defun org-roam-server-open ()
    "Ensure the server is active, then open the roam graph."
    (interactive)
    (org-roam-server-mode 1)
    (browse-url-xdg-open (format "http://localhost:%d" org-roam-server-port))))

日記

每日日記不僅是作為一天開始的計畫工具,也是一個時間帳本。他促使我深層思考我的時間應該如何花費得更有價值。當我醒來時,我想要坐在桌之前,開始寫今天的日記,想像一下今天會發生什麼事情。寫作不僅助於組織我的思想,還能幫助我計畫我的一天。當我打開日記時,我想看到我應該遵循的晨間慣例,這些慣例是我在一週之初、一月之初、一年之初制訂的,做一個新開始的希望,就像一座燈塔,引導我的靈魂在一個所有算法都在爭奪注意力的世代中生存。

org-roam-daily

(after! org-roam
  (setq org-roam-dailies-capture-templates
        `(("d" "default" entry
         #'org-roam-capture--get-point
         "* %?"
         :file-name "daily/%<%Y-%m-%d>"
         :head ,(concat "#+title: %<%Y-%m-%d>\n"
                        "#+roam_tags: ritual\n\n"
                        "*Don't ignore your dreams; don't work too much; say what you think; cultivate friendships; be happy*\n"
                        "\n"
                        "- tags ::\n"
                        "- month ::\n "
                        "\n"
                        "* Morning Routines [/]\n"
                        " - [ ] Brush my teeth\n"
                        " - [ ] Folded quilts\n"
                        " - [ ] Have a cup of coffe\n"
                        " - [ ] Weighs myself\n"
                        " - [ ] Listen FT times\n"
                        " - [ ] Check [[https://fsinsight.com/members-area-crypto/][Crypto Daily]]\n"
                        " - [ ] Yesterday journal if not done\n"
                        " - [ ] Review this month's goal\n"
                        " - [ ] Restruct TODOs\n"
                        " - [ ] Plan today\n"
                        " - [ ] Shave\n"
                        " - [ ] Put on formal clothes\n"
                        " - [ ] Go to office before 9:30\n"
                        "* Evening Routines [/]\n"
                        " - [ ] Leave office at 18:00\n"
                        " - [ ] Take a bath\n"
                        " - [ ] Put on casual clothes\n"
                        " - [ ] Have dinner on time\n"
                        " - [ ] Have fun (play games, watch TV etc.)\n"
                        "* Night Rotuines [/]\n"
                        " - [ ] Brush my teeth\n"
                        " - [ ] Prepare my outfit for the next day\n"
                        " - [ ] Go to bed before 23:30\n"
                        " - [ ] Read a book at least 30 minutes\n"
                        "* Day Plan\n"
                        "* Journaling\n"
                        "* Brain Dumps\n")
         :unnarrowed t))))

文獻管理

主要用 Org Roam BibTeX(ORB)Zotero 一起管理引文。它允許我使用 Org Roam 管理我的書目註釋,並通過ivy-bibtex訪問org-roam-directory中的註釋,或者通過打開 org-ref 的cite: 鏈接來訪問。

Zotero

預設檔案目錄

(setq zotero-directory (expand-file-name "zotero" shared-directory))

org-ref

(package! org-ref)
(use-package org-ref
    :after org
    :init
    :config
    (setq
         ; Let ivy makes completion.
         org-ref-completion-library 'org-ref-ivy-cite
         ; Use Helm to get pdf filename.
         org-ref-get-pdf-filename-function 'org-ref-get-pdf-filename-helm-bibtex
         ; Use the bibtext file exported from Zotero.
         org-ref-default-bibliography (list (expand-file-name "library.bib" zotero-directory))
         org-ref-bibliography-notes (expand-file-name "bibnotes.org" org-roam-directory)
         ; Use org-roam files as my reading notes.
         org-ref-notes-directory org-roam-directory
         org-ref-notes-function 'orb-edit-notes
         ; Add templates for my reading notes.
         org-ref-note-title-format (concat
                                    "* TODO %y - %t\n"
                                    ":PROPERTIES:\n"
                                    ":Custom_ID: %k\n"
                                    ":NOTER_DOCUMENT: %F\n"
                                    ":ROAM_KEY: cite:%k\n"
                                    ":AUTHOR: %9a\n"
                                    ":JOURNAL: %j\n"
                                    ":YEAR: %y\n"
                                    ":VOLUME: %v\n"
                                    ":PAGES: %p\n"
                                    ":DOI: %D\n"
                                    ":URL: %U\n"
                                    ":END:\n\n"
                                    )
    ))

citeproc-org

在 non-Latex 的輸出過程中用 citeproc-org 將 org-mode 的引文和書目渲染成 Citation Style Language (CSL)風格

(package! citeproc-org)
(use-package citeproc-org
  :ensure t
  :after ox-hugo
  :config
  (citeproc-org-setup))

org-roam-bibtex

讓我能用我的 bibtex 文件在 org-roam 建立筆記。

(package! org-roam-bibtex
  :recipe (:host github :repo "org-roam/org-roam-bibtex"))
;; When using org-roam via the `+roam` flag
(unpin! org-roam company-org-roam)
;; When using bibtex-completion via the `biblio` module
(unpin! bibtex-completion helm-bibtex ivy-bibtex)
(use-package! org-roam-bibtex
  :after org-roam
  :hook (org-roam-mode . org-roam-bibtex-mode)
  :config
  (setq org-roam-bibtex-preformat-keywords
   '("=key=" "title" "url" "file" "author-or-editor" "keywords"))
  (setq orb-templates
        `(("r" "ref" plain (function org-roam-capture--get-point)
           ""
           :file-name "lit/${slug}"
           :head ,(concat
                   "#+TITLE: ${=key=}: ${title}\n"
                   "#+ROAM_KEY: ${ref}\n\n"
                   "* ${title}\n"
                   "  :PROPERTIES:\n"
                   "  :Custom_ID: ${=key=}\n"
                   "  :URL: ${url}\n"
                   "  :AUTHOR: ${author-or-editor}\n"
                   "  :NOTER_DOCUMENT: %(orb-process-file-field \"${=key=}\")\n"
                   "  :NOTER_PAGE: \n"
                   "  :END:\n")
           :unnarrowed t))))

bibtex-completion

(use-package! bibtex-completion
  :config
  (setq bibtex-completion-notes-path org-roam-directory
        bibtex-completion-bibliography org-ref-default-bibliography
        bibtex-completion-pdf-field "file"
        bibtex-completion-notes-template-multiple-files
         (concat
          "#+title: ${title}\n"
          "#+roam_key: cite:${=key=}\n"
          "* TODO Notes\n"
          ":PROPERTIES:\n"
          ":Custom_ID: ${=key=}\n"
          ":NOTER_DOCUMENT: %(orb-process-file-field \"${=key=}\")\n"
          ":AUTHOR: ${author-abbrev}\n"
          ":JOURNAL: ${journaltitle}\n"
          ":DATE: ${date}\n"
          ":YEAR: ${year}\n"
          ":DOI: ${doi}\n"
          ":URL: ${url}\n"
          ":END:\n\n"
          )))

代辦事項

記錄完成時間。

(after! org
  (setq org-log-done t)
  (setq org-log-into-drawer t))

org-agenda

(use-package! org-agenda
  :defer
  :init
  ;; Org Agenda Files
  (setq org-agenda-files (list
                          org-todo-file
                          org-project-file
                          org-post-file
                          org-habit-file
                          org-roam-directory))

  ;; Shorter todo list
  (setq org-agenda-skip-scheduled-if-done t
        org-agenda-skip-deadline-if-done t
        org-agenda-todo-ignore-scheduled 'future
        org-agenda-todo-ignore-deadlines 'future
        org-agenda-todo-ignore-timestamp 'future
        org-agenda-dim-blocked-tasks t
        org-agenda-todo-list-sublevels t)

  ;; Prettify time grid
  (setq org-agenda-time-grid
        (quote
         ((daily today remove-match)
          (700 800 900 1000 1100 1200 1300 1400 1500 1600 1700 1800 1900 2000 2100 2200 2300)
          "......" "----------------")))
  )

org-super-agenda

(package! org-super-agenda)
;; org-super-agenda
;; https://www.reddit.com/r/orgmode/comments/erdb40/doomemacs_can_not_make_orgsuperagenda_work/
(use-package! org-super-agenda
  :after org-agenda
  :init
  ;; for some reason org-agenda evil bindings were being weird with j and k
  (map! :map org-agenda-keymap "j" #'org-agenda-next-line)
  (map! :map org-agenda-mode-map "j" #'org-agenda-next-line)
  (map! :map org-super-agenda-header-map "j" #'org-agenda-next-line)
  (map! :map org-agenda-keymap "k" #'org-agenda-previous-line)
  (map! :map org-agenda-mode-map "k" #'org-agenda-previous-line)
  (map! :map org-super-agenda-header-map "k" #'org-agenda-previous-line)

  (setq org-agenda-custom-commands
        '(
          ("r" "Main View"
           ((agenda "" ((org-agenda-span 'day)
                        (org-agenda-start-day "+0d")
                        (org-agenda-overriding-header "")
                        (org-super-agenda-groups
                         '(
                           (:discard (:todo ("PROJ" "WAIT" "STRT")))
                           (:name "Schedule"
                            :time-grid t
                            :date today
                            :order 1
                            :scheduled today
                            :todo "TODAY")
                           (:name "Reminder"
                            :order 2
                            :anything
                           )
                           ))))
            (alltodo "" ((org-agenda-overriding-header "")
                         (org-super-agenda-groups
                          '(
                            (:log t)
                            (:discard (:category "習慣"))
                            (:discard (:todo "SOMEDAY"))
                            (:discard (:todo "IDEA"))
                            (:discard (:todo "PROJ"))
                            (:name "Next to do"
                             :and (:todo "TODO" :priority>= "A")
                             :order 3)
                            (:name "Due Today"
                             :deadline today
                             :order 4)
                            (:name "Due Soon"
                             :deadline future
                             :order 8)
                            (:name "Started"
                             :todo "STRT")
                            (:name "Overdue"
                             :deadline past
                             :order 20)
                            (:name "Waitting"
                             :todo "WAIT"
                             :order 98)
                            (:discard (:todo "TODO"))
                            ))))))
          ))


  :config
  (org-super-agenda-mode)
  )

行事曆

calfw

行事曆上私人行程以及台灣國定假日。預設不使用 Emacs 提供的國定假日。

(use-package! calfw
  :defer
  :init
  (setq cfw:display-calendar-holidays nil) ; don't show holidays.
)

提供 my-open-calendar 指令打開行事曆。

(defun my-open-calendar ()
  (interactive)
  (cfw:open-calendar-buffer
   :contents-sources
   (list
    (cfw:org-create-source "Green")  ; org-agenda source
    (cfw:ical-create-source "Personal" cfw-gcal-personal "Orange")
    (cfw:ical-create-source "Holidays" cfw-gcal-holidays-tw "Red")
   )))

calfw-org

在行事曆上顯示代辦任務。

(use-package! calfw-org
  :after calfw
  :init
  ;; To speed up the loading, restricts items containing a scheduled TODOs that the date range matching the selected date.
  (setq cfw:org-agenda-schedule-args '(:scheduled :deadline));
)

Hugo

Hugo 是我目前使用的 Blog 系統。發佈流程如下:

  1. 創建一個 orgmode heading 為標題。
  2. 寫文章。
  3. s m e H H 產生 markdown。
  4. s o h 使用 easy-hugo 預覽看結果。
  5. git push 到 github 上的 https://github.com/hychen/blog。 Github Actions 會幫我產生 html 跟 host 在 Github Page 上。

ox-hugo

Hugo 本身雖支援 org 格式,但是 markdown 渲染效果較好,透過 ox-hugo 可以輸出 markdown 給 Hugo 使用。

參考 ox-hugo 的 Org Capture Setup 設定 template。

;; Populates only the EXPORT_FILE_NAME property in the inserted headline.
(after! 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")          ;Place the cursor here finally
                 "\n")))

  (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 org-post-file)
                 (function org-hugo-new-subtree-post-capture-template))))

easy-hugo

(package! easy-hugo)
(use-package! easy-hugo
  :init
  (setq easy-hugo-basedir user-blog-basedir
        easy-hugo-url user-blog-url)
  :config
  ;; make easy-hugo mode keybinds work
  (evil-make-overriding-map easy-hugo-mode-map 'normal))

Plantuml

在 Emacs 執行下列命令下載安裝 plantuml。

plantuml-download-jar

Latex

(after! org
  (setq
   org-preview-latex-default-process 'imagemagick
   ;; latex pdf process.
   org-latex-pdf-process '("latexmk -pdflatex='xelatex -interaction nonstopmode' -pdf -bibtex -f %f")
   ;; use user-defined labels.
   org-latex-prefer-user-labels t
   ;; display tables in formal booktabs style.
   org-latex-tables-booktabs t
   ;; 上下標必須加 { }.
   org-use-sub-superscripts "{}"
  ))

快捷鍵配置

按鍵組 功用 來源
SPC : 打開命令列 doom
SPC X 執行 org-catpure doom
SPC Tab Tab 顯示 tabbar doom
SPC Tab n 建立 workspace doom
SPC Tab d 刪除 workspace doom
SPC Tab $n 切換到第 $n 個 workspace doom
SPC w s 水平切割視窗 doom
SPC w v 垂直切割視窗 doom
SPC w m 最大化當前視窗 doom
SPC o a r 打開 org-agenda Main Repor custom
SPC o p 打開專案 Sidebar doom
SPC o P 在專案 Sidebar 找檔案 doom
SPC o v 開啟 Terminal doom
SPC o h 開啟 Easy Hugo custom
SPC p a 新增專案 doom
SPC p d 移除專案 doom
SPC p p 切換專案 doom
SPC n r f 開起 Roam 筆記 doom
SPC n r i 插入 Roam 筆記 doom
SPC n r I 插入 Roam 筆記 (w/ org-capture) doom
SPC m e H H 輸出文件或單個 Subtree 到 hugo doom
SPC m e H A 輸出文件或全部的 Subtree 到 hugo doom
SPC t e Toogle hidding/showing of org emphasise markers custom
SPC h r r 重新讀取 doom emacs 設定檔
(map! :leader
      :desc "Easy Hugo"
      "o h" #'easy-hugo)
(map! :leader
      :desc "Toogle hidding/showing of org emphasize markers."
      "t e" #'org-toggle-emphasis)

感謝

設定 Emacs 非是易事。 我從其他先進的設定檔中獲得許多靈感。特別感謝

  1. Diego Zamboni’s Literate Configuration Book and his configuration.
  2. Dan Girshovich’s configuration.
  3. An Academic’s Opinionated DOOM Emacs Config
  4. 我的日程计划安排.