Literate Configuration

Table of Contents

##+SETUPFILE: https://fniessen.github.io/org-html-themes/org/theme-readtheorg.setup

1 First to Execute

1.1 set org directory

(setq
 org-directory "~/Notes/"
 )

1.2 full screen on start up, always move to front

;; full screen it
(add-to-list 'initial-frame-alist '(fullscreen . maximized))

;; the following function brings Emacs to the front if on macOS
(defun bring-emacs-to-front ()
  "Bring Emacs to the front using AppleScript."
  (when (eq system-type 'darwin)
    (ns-do-applescript "tell application \"Emacs\" to activate")))
;; Run after startup
(add-hook 'after-init-hook 'bring-emacs-to-front)
;; Optional: Also run when restarting Emacs (if using `restart-emacs`)
(advice-add 'restart-emacs :after #'bring-emacs-to-front)

1.3 Utility Functions

Utility functions that other functions can use.

(defun my-open (filepath)
  (cond
   ((eq system-type 'gnu/linux) (shell-command (format "xdg-open %s &" filepath) nil nil))
   ((eq system-type 'darwin) (shell-command (format "open %s &" filepath) nil nil))
   )
  )

1.4 avoid adding new line automatically

(setq-default require-final-newline nil)

2 General (Evil/Doom)

;; split window and move cursor to right and bottom
(after! evil
  (setq
   evil-split-window-below t
   evil-vsplit-window-right t
   evil-ex-substitute-global t  ;; global replacement by default
   evil-kill-on-visual-paste nil ;; do not put content on kill ring when paste/yank
   )
  )

;; disable debug
(setq
 debug-on-error nil
 edebug-on-error nil
 )

;; change the module suffix so that `zmq` module will look for .so file instead of .dylib module file
(setq module-file-suffix ".so")


(setq doom-localleader-key ",")
;; (add-hook! 'before-save-hook 'whitespace-cleanup)
(setenv "EDITOR" "emacsclient")
(setq tramp-default-method "ssh")

;; spell checking
(setq ispell-personal-dictionary "~/.dotfiles/emacs/ispell-dict")
;; rerun flyspell buffer after diction changes
(defun flyspell-buffer-after-pdict-save (&rest _)
  (flyspell-buffer))
(advice-add 'ispell-pdict-save :after #'flyspell-buffer-after-pdict-save)
;; save dictionary without prompting to confirm
(setq ispell-silently-savep t)

2.1 Gitlab CI command to export to html

emacs config.org --batch --load lib/color.el --load lib/htmlize.el -f org-html-export-to-html --kill

2.2 Authinfo GPG

(setq auth-sources '("~/.authinfo.gpg"))

3 Org-mode

3.1 general

(after! org
  ;; only load after org-mode is loaded

  (require 'org-id)

  ;; org directories
  (setq
   org-default-notes-file (expand-file-name "refile.org" org-directory)
   org-default-meeting-file (expand-file-name "roam/meetings.org" org-directory)
   org-roam-directory (expand-file-name "roam" org-directory)
   )
  ;; org-roam-db-location (expand-file-name "org-roam.db" org-roam-directory)

  ;; count all descendent checkboxes
  ;; Non-nil means checkbox statistics counts only the state of direct children.
  (setq org-checkbox-hierarchical-statistics nil)
  ;; https://orgmode.org/manual/Breaking-down-tasks.html
  (setq org-hierarchical-todo-statistics nil)

  ;; turn on auto-fill-mode for org files
  (add-hook 'org-mode-hook 'turn-on-auto-fill)

  ;; turn on auto-fill-mode for org files
  (add-hook 'org-mode-hook '(lambda () (display-line-numbers-mode 0)))

  ;; when change todo state, save the file
  (add-hook 'org-trigger-hook 'save-buffer)

  ;; create id when copy an link
  (setq org-id-link-to-org-use-id 'create-if-interactive)
  (setq org-id-locations-file (expand-file-name ".orgids" org-directory))
  (setq org-attach-preferred-new-method 'id)

  (setq org-journal-dir (expand-file-name "journal" org-directory))

  (defun weekly-dates()
    "insert dates of current Monday and Sunday for weekly purpose"
    ;; reference: https://sachachua.com/blog/2015/08/org-mode-date-arithmetic/
    ;; reference: https://www.gnu.org/software/emacs/manual/html_node/elisp/Insertion.html
    (interactive)
    (insert
     (concat
      "** "
      (org-read-date nil nil "this monday")
      " "
      (org-read-date nil nil "this sunday")
      "\n"
      "*** log\n"
      "**** Monday\n"
      "**** Tuesday\n"
      "**** Wednesday\n"
      "**** Thursday\n"
      "**** Friday\n"
      )
     )
    )

  ;; automaticall refresh inline images after executing babel block.
  ;; (add-hook! 'org-babel-after-execute-hook 'org-display-inline-images)

  ;; plantuml integration
  (setq org-plantuml-jar-path
        (setq plantuml-jar-path (expand-file-name "~/.dotfiles/plantuml.1.2021.0.jar")))
  (add-to-list
   'org-src-lang-modes '("plantuml" . plantuml))

  (defun my-org-confirm-babel-evaluate (lang body)
    ;; return nil for the languages that don't need confirm
    (cond
     ((string= lang "plantuml") nil)
     ((string= lang "emacs-lisp") nil)
     ((string= lang "http") nil)
     ;; all other languages
     (t t)
     ))
  (setq org-confirm-babel-evaluate #'my-org-confirm-babel-evaluate)

  (add-to-list 'org-structure-template-alist
               '("p" "#+BEGIN_SRC ipython :session :exports both :results raw drawer \n\n#+END_SRC"))


  ;;
  ;; indentation
  ;;
  ;; http://orgmode.org/manual/In_002dbuffer-settings.html#In_002dbuffer-settings
  ;; enable auto-indentation (indent mode)
  (setq org-startup-indented t)
  ;; disable truncated
  (setq org-startup-truncated nil)
  ;; startup folding configuration (see table below)
  (setq org-startup-folded t)

  ;;
  ;; beautification
  ;;

  ;; not leaving empty lines when in collapsed view
  (setq org-cycle-separator-lines 0)
  (setq outline-blank-line nil)

  ;; golden ratio mode https://github.com/roman/golden-ratio.el
  ;; (setq golden-ratio-mode t)

  ;; Misc tips from https://lepisma.github.io/2017/10/28/ricing-org-mode/
  ;; Unicode symbols: https://zhangda.wordpress.com/2016/02/15/configurations-for-beautifying-emacs-org-mode/
  (setq org-startup-indented t
        ;; org-bullets-bullet-list '(" ") ;; no bullets, needs org-bullets package
        ;; org-bullets-bullet-list '("◉" "◎" "◆" "○" "►" "◇")
        ;; org-ellipsis " ⤵ " ;; folding symbol, backup: ⚡
        org-pretty-entities t
        org-hide-emphasis-markers nil ;; show actually italicized text instead of /italicized text/
        org-fontify-whole-heading-line t
        org-fontify-done-headline t
        org-fontify-quote-and-verse-blocks t
        )
  ;; a blank line at the end of the content of each task entry
  ;; https://blog.aaronbieber.com/2016/01/30/dig-into-org-mode.html
  (setq org-blank-before-new-entry (quote ((heading) (plain-list-item))))


  ;; HUGO
  (setq org-hugo-default-section-directory "post")
  )

3.2 refile

(after! org
  (setq org-refile-use-outline-path 'file)
  (setq org-outline-path-complete-in-steps nil)
  ;; Targets include this file and any file contributing to the agenda - up to 2 levels deep
  (setq org-refile-targets (quote
                            (
                             (nil :maxlevel . 2)
                             (org-agenda-files :maxlevel . 4)
                             )
                            )
        )

  ;; when refile, put the note on top of the headings
  (setq org-reverse-note-order t)
  )

3.3 create ID for all headings

Reference: Assign IDs to every entry in Org-mode

;; (after! org
;;   (defun my/org-add-ids-to-headlines-in-file ()
;;     "Add ID properties to all headlines in the current file which
;; do not already have one."
;;     (interactive)
;;     (org-map-entries 'org-id-get-create))
;;   (add-hook 'org-mode-hook
;;             (lambda ()
;;               (add-hook 'before-save-hook 'my/org-add-ids-to-headlines-in-file)))
;;   )

3.4 export

org-export related configuration

(after! org
  (setq org-export-with-toc nil)

  ;; disable smart quote typography changes for markdown
  (setq org-export-with-smart-quotes nil)
  ;; The following doesn't work
  ;; (setq org-pandoc-format-extensions '(markdown-typography))
  (setq org-pandoc-format-extensions '(markdown_strict+pipe_tables))
  (setq org-pandoc-markdown-extension "+yaml_metadata_block")

  ;; HTML
  ;; set default export scope
  (setq org-export-initial-scope 'subtree)
  ;; disable default CSS style
  (setq org-html-head-include-default-style nil)
  ;; include my own CSS style
  (setq org-html-head "<link rel=\"stylesheet\" href=\"https://mingwei.gitlab.io/doom.d/org.css\" type=\"text/css\" />")
  ;; (setq org-html-head "<link rel=\"stylesheet\" href=\"https://sandyuraz.com/styles/org.css\">")
)

3.5 capture

(after! org
  ;; capture items
  (setq org-capture-templates
        '(

          ("r" "Radar Group Meeting" entry (file+headline "roam/cloudflare_radar.org" "Group Meetings")
           "*** Group meeting on %t\n**** Topic:\n\n**** Notes\n\n")

          ("c" "Individual Meeting" entry (file+headline "roam/cloudflare_radar.org" "Individual Meetings")
           "*** Meeting with %^{Person} on %t\n**** Topic\n\n**** Notes\n\n")

          )
        )
  (add-hook 'org-capture-mode-hook 'delete-other-windows)
  )

3.6 keybindings

;; org-agenda shortcut
(define-key global-map "\C-cl" 'org-store-link)
(define-key global-map "\C-cc" 'org-capture)
(define-key global-map "\C-ca" 'org-agenda)

3.7 agenda

3.7.1 general agenda config

(after! org
  ;; flush the tag to right, -77 matches what I had before.
  (setq org-tags-column -77)
  (setq +popup-margin-width 0)
  (set-popup-rule! "^\\*Org Agenda" :side 'right :width 98 :select t :ttl nil)

  ;; set agenda view
  (setq org-agenda-start-day nil        ;; start from current date
        org-agenda-start-on-weekday 1   ;; plotting from Monday
        org-agenda-span 'week           ;; show one week of agenda
        )

  (setq org-agenda-dim-blocked-tasks t)
  (setq org-todo-keywords
        '((sequence
           "TODO(t)"  ; A task that needs doing & is ready to do
           "STRT(s)"  ; A task that is in progress
           "REVW(r)"  ; A task that is in review
           "BLOCKED(b@/@)"  ; Not my choice to pause task
           "WAIT(w@/@)"  ; My choice to pause task
           "HOLD(h@/@)"  ; More passive than WAIT, no intention to do it soon
           "|"
           "DONE(d)"  ; Task successfully completed
           "KILL(k@/@)") ; Task was cancelled, aborted or is no longer applicable
          (sequence
           "[ ](T)"   ; A task that needs doing
           "[-](S)"   ; Task is in progress
           "[-](R)"   ; Task is in review
           "[?](W)"   ; Task is being held up or paused
           "[?](H)"   ; Task is being held up or paused
           "|"
           "[X](D)")) ; Task was completed
        org-todo-keyword-faces
        '(("[-]"  . +org-todo-active)
          ("STRT" . +org-todo-active)
          ("REVW" . +org-todo-active)
          ("[?]"  . +org-todo-onhold)
          ("WAIT" . +org-todo-project)
          ("BLOCKED" . +org-todo-project)
          ("HOLD" . +org-todo-project)
          )
        )

  ;; other configuration
  (setq org-log-into-drawer t
        org-return-follows-link t
        org-use-fast-todo-selection t
        org-treat-S-cursor-todo-selection-as-state-change nil
        org-log-done t ;; log time when mark todo as done
        org-enforce-todo-dependencies t ; Make it impossible to complete a task if subtasks are not done
        org-enforce-todo-checkbox-dependencies t ; Make it impossible to complete a checkbox if subtasks are not done
        org-agenda-dim-blocked-tasks nil
        org-agenda-use-tag-inheritance nil
        )

  ;; TODO: but we still have the \\ at the end of the time line...
  (setq org-log-note-headings
        '((done . "CLOSING NOTE %t")
          (state . "State %-12s from %-12S %t")
          (note . "%t")
          (reschedule . "Rescheduled from %S on %t")
          (delschedule . "Not scheduled, was %S on %t")
          (redeadline . "New deadline from %S on %t")
          (deldeadline . "Removed deadline, was %S on %t")
          (refile . "Refiled on %t")
          (clock-out . ""))
        )


  ;; (setq org-agenda-files
  ;;       (list
  ;;        "~/Notes/refile.org"
  ;;        "~/Notes/inbox.org"
  ;;        "~/Notes/roam/bgpkit.org"
  ;;        "~/Notes/roam/measurement_lab.org"
  ;;        "~/Notes/roam/aats.org"
  ;;        )
  ;;       )
  (setq org-agenda-files (directory-files-recursively "~/Notes/roam/" "\\.org$"))


  ;; customize agenda views
  (defun air-org-skip-subtree-if-priority (priority)
    "Skip an agenda subtree if it has a priority of PRIORITY.
PRIORITY may be one of the characters ?A, ?B, or ?C."
    (let ((subtree-end (save-excursion (org-end-of-subtree t)))
          (pri-value (* 1000 (- org-lowest-priority priority)))
          (pri-current (org-get-priority (thing-at-point 'line t))))
      (if (= pri-value pri-current)
          subtree-end
        nil)))

  ;; Adjust the number of blank lines inserted around headlines:
  ;; http://www.i3s.unice.fr/~malapert/org/tips/emacs_orgmode.html
  ;; (setq org-ascii-headline-spacing (quote (1 . 1)))
  (setq org-agenda-skip-scheduled-if-done t)
  (setq org-agenda-skip-deadline-if-done t)
  ;; (setq org-agenda-block-separator "--------------")
  (setq org-agenda-block-separator "")
  (setq org-tags-match-list-sublevels t)

  )

3.7.2 custom agendas

(after! org

  (setq org-agenda-custom-commands
        '(
          ("t" "Todo View"
           (
            (todo "" ((org-agenda-overriding-header "TODO!")
                      (org-super-agenda-groups
                       '(
                         (:name "Important" :priority "A")
                         (:todo "HOLD" :order 1)
                         ))))))
          ))

  (org-super-agenda-mode)
  ;; (setq org-super-agenda-header-map evil-org-agenda-mode-map)
  )

3.8 other todo changes

3.8.1 clear out scheduled time after changing TODO to WAIT

Currenlty, the (*org-schedule t) still prompts for date while according to the documentation it should just remove the schedule since the second parameter exists.

https://emacs.stackexchange.com/questions/26679/toggle-scheduled-keyword#comment40635_26687 (org-schedule '(4)) for some reason works.

With one universal prefix argument, remove any scheduling date from the item. With two universal prefix arguments, prompt for a delay cookie. With argument TIME, scheduled at the corresponding date. TIME can either be an Org date like "2011-07-24" or a delta like "+2d".

(setq org-after-todo-state-change-hook
      '(lambda ()
         (if (member org-state '("WAIT" "BLOCKED" "HOLD")) (org-schedule '(4)))))

3.9 org-roam

(after! org
  (setq
   org-roam-directory (expand-file-name "roam" org-directory)
   org-roam-db-location (expand-file-name "org-roam.db" org-roam-directory)
   ;; make sure new agenda files do not have the date time prefix in file name
   org-roam-capture-templates '(
                               ("d" "default" plain "%?" :target
                                (file+head "${slug}.org" "#+title: ${title}\n")
                                :unnarrowed t)
                               )
   )
  )

3.10 fix search issue

(after! org
  (setq org-fold-core-style 'overlays)
  (evil-select-search-module 'evil-search-module 'evil-search)
  )

4 Key-Bindings

Mode descriptor reference

mode meaning
n normal
v visual
i insert
e emacs
o operator
m motion
r replace
g global

for more, see file ~/.emacs.d/modules/config/default/+bindings.el

4.1 <SPACE> commands

(map!
 (:leader

  ;; SPC-SPC to run commands
  :desc "M-x"                     :nv "SPC"  #'execute-extended-command
  :desc "Find file in project"    :n  ":"    #'projectile-find-file

  (:prefix "TAB"
   :desc "Previous workspace"    :n  "h" #'+workspace/switch-left
   :desc "Next workspace"        :n  "l" #'+workspace/switch-right
   :desc "Load workspace"        :n  "L" #'+workspace/load
   )

  (:desc "git" :prefix "g"
   :desc "Git status"            :n  "s" #'magit-status
   :desc "Git stage hunk"        :n  "S" #'git-gutter:stage-hunk
   )

  (:desc "+toggle" :prefix "t"
   :desc "Flycheck"              :n  "c" #'flycheck-mode
   :desc "Focus"                 :n  "f" #'focus-mode
   :desc "Center"                :n  "w" #'centered-window-mode
   :desc "LSP iMenu"             :n  "i" #'lsp-ui-imenu
   )
  )
 )

4.2 evil

(use-package! evil-escape)
(setq-default evil-escape-key-sequence "fd")
(map!
 (:after evil
  (:map evil-window-map ; prefix "C-w"
   "d"       #'+workspace/close-window-or-workspace
   "g"       #'golden-ratio
   "G"       #'balance-windows
   ;; "m"       #'delete-other-windows
   "w"       #'other-window
   "u"       #'winner-undo
   "r"       #'winner-redo
   )
  (:map evil-motion-state-map
   ";"       #'ignore
   )
  (:map evil-normal-state-map
   "zi"      #'ispell-word
   "zI"      #'ispell-buffer
   "s-["     #'evil-goto-last-change
   "s-]"     #'evil-goto-last-change-reverse
   ;; "gG"      #'centaur-tabs-counsel-switch-group
   ;; "gk"      #'centaur-tabs-kill-other-buffers-in-current-group
   ;; "gK"      #'centaur-tabs-kill-all-buffers-in-current-group
   )
  )
 )

4.3 org

(define-key global-map "\C-cl" 'org-store-link)
(define-key global-map "\C-ca" 'org-agenda)
(define-key global-map "\C-cc" 'org-capture)
(map!
 (:after evil-org
  (:map evil-org-mode-map
   (:localleader
    :n "n" #'org-toggle-narrow-to-subtree
    :n "A" #'org-archive-subtree
    :n "S" #'org-sort
    :n "T" #'org-babel-tangle
    :n "#" #'org-update-checkbox-count
    )
   :ni  "M-j" #'org-metadown
   :ni  "M-k" #'org-metaup
   :ni  "M-h" #'org-promote-subtree
   :ni  "M-l" #'org-demote-subtree
   :n   "t"   #'org-todo
   :n   "zi"  #'ispell-word
   )
  )
 (:map evil-org-agenda-mode-map
  (:localleader
   :n "A" #'org-agenda-archive-default-with-confirmation
   )
  )
 )

4.4 other functions

4.4.1 macos

(when IS-MAC
  (setq mac-command-modifier 'super)
  (setq mac-option-modifier 'meta)
  )

4.4.2 magit

(after! magit
  (define-key magit-mode-map (kbd "Q") 'delete-frame)
  )

4.4.3 unfill paragraph

;;; Stefan Monnier <foo at acm.org>. It is the opposite of fill-paragraph
(defun unfill-paragraph (&optional region)
  "Takes a multi-line paragraph and makes it into a single line of text."
  (interactive (progn (barf-if-buffer-read-only) '(t)))
  (let ((fill-column (point-max))
        ;; This would override `fill-column' if it's an integer.
        (emacs-lisp-docstring-fill-column t))
    (fill-paragraph nil region)))
;; Handy key definition
(define-key global-map "\M-Q" 'unfill-paragraph)

5 Theme

Load doom-themes package:

(require 'doom-themes)

5.1 font

;; good font choices:
;; - JetBrains Mono font: https://www.jetbrains.com/lp/mono/
;; - Mozilla Fira Mono Font: https://github.com/mozilla/Fira
(setq doom-font (font-spec :family "Jetbrains Mono" :size 15))
;; revert to nil if font no exists
(unless (doom-font-exists-p doom-font)
  (setq doom-font nil))

;; (setq doom-unicode-font (font-spec :family "Jetbrains Mono"))
(setq doom-unicode-font
      (font-spec :family "all-the-icons" :size 15)
      ;; Fallback to your main font if icons aren't available
      doom-unicode-fallback-font (font-spec :family "JetBrains Mono"))

;; revert to nil if font no exists
(unless (doom-font-exists-p doom-unicode-font)
  (setq doom-unicode-font nil))

(setq line-spacing 0.2) ;; recommended 1.2 line spacing, `line-spacing` variable sets the *additional* space, thus 0.2

5.2 theme

;; Global settings (defaults)
(setq doom-themes-enable-bold t    ; if nil, bold is universally disabled
      doom-themes-enable-italic t) ; if nil, italics is universally disabled
;; Load the theme (doom-one, doom-molokai, etc); keep in mind that each theme
;; may have their own settings.
;;
;; DARK THEMES
;;
;; (load-theme 'doom-vibrant t)
;; (load-theme 'doom-opera t)
(load-theme 'doom-dracula t)
;; (load-theme 'doom-tomorrow-night t)
;; (load-theme 'doom-city-lights t)
;; (load-theme 'doom-nord t)
;; (load-theme 'doom-dark+ t)
;; (load-theme 'doom-Iosvkem t)
;; (load-theme 'doom-one t)
;; (load-theme 'doom-outrun-electric t)
;; (load-theme 'doom-acario-dark t)
;; (load-theme 'leuven-dark t) ;; perfect fit for org-mode
;;
;; LIGHT THEMES
;;
;; (load-theme 'doom-acario-light t)
;; (load-theme 'leuven t) ;; perfect fit for org-mode
;; (load-theme 'doom-one-light t)
;; (load-theme 'doom-solarized-light t)

;;
;; (set-frame-parameter (selected-frame) 'alpha '(100 98))

;; (setq window-divider-default-right-width 3)
;; (setq window-divider-default-bottom-width 3)

;; Enable flashing mode-line on errors
(doom-themes-visual-bell-config)
(doom-themes-treemacs-config)

;; Corrects (and improves) org-mode's native fontification.
(doom-themes-org-config)

5.3 misc

Show relative line numbers visual style.

(setq display-line-numbers-type 'visual)

6 Coding

6.1 flycheck

Change flycheck temporary file prefix to .flycheck instead of flycheck.

;; Change flycheck temporary file prefix to ~.flycheck~ instead of ~flycheck~.
(setq flycheck-temp-prefix ".flycheck")

6.2 unixtime

My utility unix functions at here: https://github.com/digizeph/unix-ts-el

(use-package! unix-ts)

6.3 syslog mode

(add-to-list 'auto-mode-alist '("syslog\\'" . syslog-mode) t)

6.4 toml

enable visual line mode for toml files

(add-hook 'conf-toml-mode-hook 'visual-line-mode)

6.5 rust

(after! rustic
  (setq
   rustic-format-on-save t
   rustic-cargo-build-arguments "--all-features"
   rustic-rustfmt-args "--edition 2024"
   lsp-rust-analyzer-display-parameter-hints t
   lsp-rust-all-features t
   lsp-ui-sideline-show-hover nil
   )
  (map!
   (:map rustic-mode-map
         (:localleader
          (:prefix ("t" . "cargo test")
           :desc "related test"     "r" #'lsp-rust-analyzer-related-tests
          :desc "current test"      "t" #'lsp-rust-analyzer-run)
         )
   )
  )
)

7 Q&A

7.1 What happens if seeing file not found in path error?

Searching for program: No such file or directory, /usr/bin/security

Try run doom env first.

Author: root

Created: 2025-05-27 Tue 21:41

Validate