mkvoya / emacs.d

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Emacs Main Configuration File

Core

Literal Configuration Bootstrap

(setq .org "~/.emacs.d/emacs-config.org")
(setq .el (concat (file-name-sans-extension .org) ".el"))
(defun mk/sync-emacs-config()
  "Synchronize config from org to el and compile to elc."
  (interactive)
  ;; Avoid running hooks when tangling. From https://delta.re/emacs-config-org/
  (let ((prog-mode-hook nil))
    (require 'ob-tangle)
    ;; Tangle the file. It's fast.
    (org-babel-tangle-file .org .el "emacs-lisp")
    (message "[CONFIG] Config is synchronized.")
    ;; Async compile the config.
    (async-start
     ;; What to do in the child process
     ;; the backquote and the set are necessary to capture vars
     `(lambda () ; ` is necessary to capture vars.
        (set 'el-file ,.el) ; Get the captured var.
        (byte-compile-file el-file) ; Compile the el file.
        el-file) ; Return the file name.
     ;; What to do when it finishes
     (lambda (res) (message "[CONFIG] Config %s is async-compiled." res))
     )))

;; Sync config when the config file is saved.
(add-hook 'after-save-hook
          (lambda ()
            (if (equal (buffer-file-name) (expand-file-name .org))
                (mk/sync-emacs-config))))

Fonts

We need to setup fonts early.

(when (eq system-type 'darwin)
  (dolist (charset '(kana han symbol cjk-misc bopomofo))
    (set-fontset-font (frame-parameter nil 'font)
                      charset (font-spec :family "LXGW WenKai Screen")))
  (setq face-font-rescale-alist '(("LXGW WenKai Screen" . 1.24)))
  (set-fontset-font t 'emoji (font-spec :family "Apple Color Emoji") nil 'prepend)
  (set-fontset-font t '(#x2ff0 . #x9ffc) (font-spec :name "TsangerJinKai01" :size 14))
  )

Bootstrap

Custom Files

(setq custom-file "~/.emacs.d/customs.el")
(load custom-file t)

Packages

straight.el replacing package.el

straight.elhttps://github.com/raxod502/straight.el
package.elbuilt-in package system
quelpahttps://github.com/quelpa/quelpa
quelpa-use-packagehttps://github.com/quelpa/quelpa-use-package
paradoxA modern interface for package.el
(defvar bootstrap-version)
(let ((bootstrap-file
       (expand-file-name "straight/repos/straight.el/bootstrap.el" user-emacs-directory))
      (bootstrap-version 6))
  (unless (file-exists-p bootstrap-file)
    (with-current-buffer
        (url-retrieve-synchronously
         "https://raw.githubusercontent.com/radian-software/straight.el/develop/install.el"
         'silent 'inhibit-cookies)
      (goto-char (point-max))
      (eval-print-last-sexp)))
  (load bootstrap-file nil 'nomessage))

use-package: A use-package declaration for simplifying your .emacs

use-packagehttps://github.com/jwiegley/use-package
(setq use-package-compute-statistics t)
(straight-use-package 'use-package)
(setq straight-use-package-by-default t) ; Ensure :straight t

Benchmarks

(cl-letf (((symbol-function 'define-obsolete-function-alias) #'defalias))
  (use-package benchmark-init
    :init
    (require 'benchmark-init-modes) ; explicitly required
    ;; To disable collection of benchmark data after init is done.
    (add-hook 'after-init-hook #'benchmark-init/deactivate)))

Emacs Server

;;; The server part may not be configured so early.
(load "server") ; Load and start server if it's not running
(unless (server-running-p) (server-start))

The PATH

;;; Get shell env from user shell.
;; https://apple.stackexchange.com/questions/51677/how-to-set-path-for-finder-launched-applications
;; $ sudo launchctl config user path /usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
;; We need to at least make the /usr/local/bin in the path so that imagemagick can use rsgv rather than its built-in svg renderer.
;; The above command works.
(use-package exec-path-from-shell
  :init
  (exec-path-from-shell-initialize))

Options

(defvar mk-feature/bibliography t "Enable bibliography.")
(defvar mk-feature/gui t "Enable GUI-related packages.")
(defvar mk-feature/noteman t "Enable note management.")
(defvar mk-feature/light t "Use light mode.")
(defvar mk-feature/news-mail t "Enable news and mails.")

SETQs

(setq
 ;; Backups
 backup-by-copying t
 backup-directory-alist '(("." . "~/.emacs.d/backups"))
 delete-old-versions t
 kept-new-versions 6
 kept-old-versions 2
 version-control t
 vc-make-backup-files t
 ;;(setq backup-directory-alist '(("." . "~/.emacs.d/backups")))
 ;;(setq delete-old-versiojns -1)
 ;;(setq version-control t)
 auto-save-file-name-transforms '((".*" "~/.emacs.d/auto-save-list/" t))
 ;; History
 savehist-file "~/.emacs.d/savehist"
 history-length t
 history-delete-duplicates t
 savehist-save-minibuffer-history 1
 savehist-additional-variables '(kill-ring search-ring regex-search-ring))
(savehist-mode 1)
(setq-default
 ;; From: https://stackoverflow.com/questions/4657142/how-do-i-encourage-emacs-to-follow-the-compilation-buffer
 compilation-scroll-output t
 ;; (setq compilation-scroll-output 'first-error)
 ;; Prevent Extraneous Tabs
 indent-tabs-mode nil
 fill-column 100
 ;; line-spacing 0.1
 )
(setq enable-recursive-minibuffers t)
(minibuffer-depth-indicate-mode 1)
(defun mkvoya/better-wrap ()
  "Make the word wrap better."
  (interactive)
  (progn
    (visual-line-mode t)
    (setq word-wrap nil)
    ))

(blink-cursor-mode 1)

(when (> emacs-major-version 28)
  (pixel-scroll-precision-mode))
(setq delete-by-moving-to-trash t)
(use-package ns-win
  :if (memq window-system '(mac ns))
  :straight nil
  :init
  ;; (setq mac-right-command-modifier 'control)
  ;; (setq mac-right-option-modifier 'control)
  )

Basic libraries

(use-package async :defer t)
(use-package bind-key :defer t)
(use-package marquee-header :defer t)  ; This is really an interesting package.
(use-package dash :defer t)
(use-package ts :defer t)
(use-package s :defer t)
(use-package reveal-in-osx-finder :defer t)
(use-package crux :defer t)
(use-package ranger :defer t)  ; The ranger mode
(use-package vlf :defer t)  ; View large files

Private-built Top-bar

(when (eq system-type 'darwin)

  (require 'top-bar)

  (defun mk/enable-top-bar (frame)
    "Setup top-bar for FRAME."
    (set-frame-parameter frame 'top-bar-lines 1)
    (mk/set-frame-top-bar-format mk/default-frame-top-bar-format)
    )
  (defun mk/disable-top-bar (frame)
    "Setup top-bar for FRAME."
    (set-frame-parameter frame 'top-bar-lines 0)
    )

  (mk/enable-top-bar nil)
  (add-hook 'after-make-frame-function #'mk/enable-top-bar)

  (set-face-attribute 'top-bar nil :background "#EFEFEF" :font "Menlo-12") ;; default
  ;; (set-face-attribute 'top-bar nil :background "#2F2F2F" :foreground "#fFeF5F" :font "Menlo-12")
  )

M-x and Auto-completion

M-x: Vertico

Alternatives (Check the selectrum repo README)

Ido
Helm
Ivy
Icomplete
Icicles
Snallet
Raven
Swiper
Selectrumhttps://github.com/raxod502/selectrum
verticohttps://github.com/minad/vertico
Snailshttps://github.com/manateelazycat/snails
For Selectrum/vertico
consulthttps://github.com/minad/consult
marginaliahttps://github.com/minad/marginaliaAlternative to ivy-rich
Embarkhttps://github.com/oantolin/embark/Minibuffer actions (ivy has builtin alternative)
(use-package vertico
  :init

  (setq vertico-scroll-margin 0)
  (setq vertico-count 20)  ; Show more candidates.
  (setq vertico-resize nil)  ; Do NOT grow and shrink the Vertico minibuffer.
  (setq vertico-cycle t)  ; Cycling the candidates. E.g., the next to the last is the first.

  ;; Do not allow the cursor in the minibuffer prompt
  (setq minibuffer-prompt-properties
        '(read-only t cursor-intangible t face minibuffer-prompt))
  (add-hook 'minibuffer-setup-hook #'cursor-intangible-mode)

  (setq enable-recursive-minibuffers nil)
  (vertico-mode)
  )
(use-package orderless
  :init
  (setq completion-styles '(orderless))
  (setq completion-category-defaults nil)
  (setq completion-category-overrides '((file (styles partial-completion))))
  )
(use-package marginalia
  :init
  (marginalia-mode))

(use-package consult
  :bind (
         ;; C-x bindings (ctl-x-map)
         ("C-x M-:" . consult-complex-command)     ;; orig. repeat-complex-command
         ("C-x b" . consult-buffer)                ;; orig. switch-to-buffer
         ("C-x 4 b" . consult-buffer-other-window) ;; orig. switch-to-buffer-other-window
         ("C-x 5 b" . consult-buffer-other-frame)  ;; orig. switch-to-buffer-other-frame
         ("C-x r b" . consult-bookmark)            ;; orig. bookmark-jump
         ("C-x p b" . consult-project-buffer)      ;; orig. project-switch-to-buffer
         ;; Custom M-# bindings for fast register access
         ;; Other custom bindings
         ("M-g i" . consult-imenu)
         ("M-g I" . consult-imenu-multi)
         ;; M-s bindings (search-map)
         ("M-s d" . consult-find)
         ("M-s D" . consult-locate)
         ("M-s g" . consult-grep)
         ("M-s G" . consult-git-grep)
         ("M-s r" . consult-ripgrep)
         ("M-s l" . consult-line)
         ("M-s L" . consult-line-multi)
         ("M-s m" . consult-multi-occur)
         ("M-s k" . consult-keep-lines)
         ("M-s u" . consult-focus-lines)
         ;; Isearch integration
         ("M-s e" . consult-isearch-history)
         :map isearch-mode-map
         ("M-e" . consult-isearch-history)         ;; orig. isearch-edit-string
         ("M-s e" . consult-isearch-history)       ;; orig. isearch-edit-string
         ("M-s l" . consult-line)                  ;; needed by consult-line to detect isearch
         ("M-s L" . consult-line-multi))           ;; needed by consult-line to detect isearch

  :hook (completion-list-mode . consult-preview-at-point-mode)
  :init
  ;; Configure the register formatting
  (setq register-preview-delay 0)
  (setq register-preview-function #'consult-register-format)
  ;; Use Consult to select xref locations with preview
  (setq xref-show-xrefs-function #'consult-xref)
  (setq xref-show-definitions-function #'consult-xref)

  ;; Optionally tweak the register preview window.
  ;; This adds thin lines, sorting and hides the mode line of the window.
  (advice-add #'register-preview :override #'consult-register-window)
  )

(use-package all-the-icons-completion
  :after (all-the-icons marginalia)
  :init
  (all-the-icons-completion-mode)
  (add-hook 'marginalia-mode-hook #'all-the-icons-completion-marginalia-setup))

;; (use-package mini-popup
;;   :straight (:host github :repo "minad/mini-popup")
;;   :config
;;   ;; Configure a height function (Example for Vertico)
;;   (defun mini-popup-height-resize ()
;;     (* (1+ (min vertico--total vertico-count)) (default-line-height)))
;;   (defun mini-popup-height-fixed ()
;;     (* (1+ (if vertico--input vertico-count 0)) (default-line-height)))
;;   (setq mini-popup--height-function #'mini-popup-height-fixed)

;;   ;; Disable the minibuffer resizing of Vertico (HACK)
;;   (advice-add #'vertico--resize-window :around
;;               (lambda (&rest args)
;;                 (unless mini-popup-mode
;;                   (apply args))))

;;   ;; Ensure that the popup is updated after refresh (Consult-specific)
;;   (add-hook 'consult--completion-refresh-hook
;;             (lambda (&rest _) (mini-popup--setup)) 99)
;;   (mini-popup-mode 1))
(use-package mini-frame
  :disabled
  :init
  (setq mini-frame-internal-border-color "blue")
  (setq mini-frame-show-parameters
        '((top . 50)
          (width . 0.9)
          (left . 0.5)
          (background-color . "ivory")
          ))
  ;; (mini-frame-mode 1)
  )

(use-package embark
  :disabled
  :demand
  :bind
  (("C-." . embark-act)         ;; pick some comfortable binding
   ("C-;" . embark-dwim)        ;; good alternative: M-.
   ("C-h B" . embark-bindings)) ;; alternative for `describe-bindings'
  :init
  ;; Optionally replace the key help with a completing-read interface
  (setq prefix-help-command #'embark-prefix-help-command)
  :config
  ;; Hide the mode line of the Embark live/completions buffers
  (add-to-list 'display-buffer-alist
               '("\\`\\*Embark Collect \\(Live\\|Completions\\)\\*"
                 nil
                 (window-parameters (mode-line-format . none)))))

;; Consult users will also want the embark-consult package.
(use-package embark-consult
  :disabled
  :after (embark consult)
  :demand t ; only necessary if you have the hook below
  ;; if you want to have consult previews as you move around an
  ;; auto-updating embark collect buffer
  :hook
  (embark-collect-mode . consult-preview-at-point-mode))

Auto-completion

company-modehttps://github.com/company-mode/company-mode
Corfuhttps://github.com/minad/corfu
Cape (use with Corfu)https://github.com/minad/cape
(use-package corfu
  ;; Optional customizations
  :custom
  (corfu-cycle t)                ;; Enable cycling for `corfu-next/previous'
  (corfu-auto t)                 ;; Enable auto completion
  (corfu-separator ?\s)          ;; Orderless field separator
  (corfu-quit-at-boundary nil)   ;; Never quit at completion boundary
  :bind (:map corfu-map
              ("C-n"      . corfu-next)
              ("C-p"      . corfu-previous))
  :init
  (global-corfu-mode))

;; Add extensions
(use-package cape
  :custom
  (cape-line-buffer-function #'current-buffer)
  ;; Bind dedicated completion commands
  ;; Alternative prefix keys: C-c p, M-p, M-+, ...
  :bind (("C-c e p" . completion-at-point) ;; capf
         ("C-c e t" . complete-tag)        ;; etags
         ("C-c e d" . cape-dabbrev)        ;; or dabbrev-completion
         ("C-c e h" . cape-history)
         ("C-c e f" . cape-file)
         ("C-c e k" . cape-keyword)
         ("C-c e s" . cape-symbol)
         ("C-c e a" . cape-abbrev)
         ("C-c e i" . cape-ispell)
         ("C-c e l" . cape-line)
         ("C-c e w" . cape-dict)
         ("C-c e \\" . cape-tex)
         ("C-c e _" . cape-tex)
         ("C-c e ^" . cape-tex)
         ("C-c e &" . cape-sgml)
         ("C-c e r" . cape-rfc1345))
  :init
  ;; Add `completion-at-point-functions', used by `completion-at-point'.
  (add-to-list 'completion-at-point-functions #'cape-file)
  (add-to-list 'completion-at-point-functions #'cape-dabbrev)
  (add-to-list 'completion-at-point-functions #'cape-history)
  (add-to-list 'completion-at-point-functions #'cape-keyword)
  (add-to-list 'completion-at-point-functions #'cape-tex)
  (add-to-list 'completion-at-point-functions #'cape-sgml)
  (add-to-list 'completion-at-point-functions #'cape-rfc1345)
  (add-to-list 'completion-at-point-functions #'cape-abbrev)
  ;; (add-to-list 'completion-at-point-functions #'cape-ispell)
  ;; (add-to-list 'completion-at-point-functions #'cape-dict)
  ;; (add-to-list 'completion-at-point-functions #'cape-symbol)
  ;; (add-to-list 'completion-at-point-functions #'cape-line)
  )

;; Use Dabbrev with Corfu!
(use-package dabbrev
  ;; Swap M-/ and C-M-/
  :bind (("M-/" . dabbrev-completion)
         ("C-M-/" . dabbrev-expand))
  ;; Other useful Dabbrev configurations.
  :custom
  (dabbrev-ignored-buffer-regexps '("\\.\\(?:pdf\\|jpe?g\\|png\\)\\'")))

(use-package kind-icon
  :ensure t
  :after corfu
  :custom
  (kind-icon-default-face 'corfu-default) ; to compute blended backgrounds correctly
  :config
  (add-to-list 'corfu-margin-formatters #'kind-icon-margin-formatter))

Templating: Yasnippet

yasnippethttps://github.com/joaotavora/yasnippet
TempElhttps://github.com/minad/tempel
(use-package yasnippet
  :init (yas-global-mode 1))
(use-package yasnippet-snippets
  :after yasnippet)
;; Configure Tempel
(use-package tempel
  ;; Require trigger prefix before template name when completing.
  ;; :custom
  ;; (tempel-trigger-prefix "<")
  ;; :bind (("M-+" . tempel-complete) ;; Alternative tempel-expand
  ;;        ("M-*" . tempel-insert))

  :init

  ;; Setup completion at point
  (defun tempel-setup-capf ()
    ;; Add the Tempel Capf to `completion-at-point-functions'.
    ;; `tempel-expand' only triggers on exact matches. Alternatively use
    ;; `tempel-complete' if you want to see all matches, but then you
    ;; should also configure `tempel-trigger-prefix', such that Tempel
    ;; does not trigger too often when you don't expect it. NOTE: We add
    ;; `tempel-expand' *before* the main programming mode Capf, such
    ;; that it will be tried first.
    (setq-local completion-at-point-functions
                (cons #'tempel-expand
                      completion-at-point-functions)))

  (add-hook 'prog-mode-hook 'tempel-setup-capf)
  (add-hook 'text-mode-hook 'tempel-setup-capf)

  ;; Optionally make the Tempel templates available to Abbrev,
  ;; either locally or globally. `expand-abbrev' is bound to C-x '.
  ;; (add-hook 'prog-mode-hook #'tempel-abbrev-mode)
  ;; (global-tempel-abbrev-mode)
  )

LSP

lsp-modehttps://github.com/emacs-lsp/lsp-mode
eglotBuilt-in since Emacs 29
nox
LSPCEhttps://github.com/zbelial/lspce
flycheckpopular alternative to flymake
flymakeThe rewritten built-in flymake is sufficient good
flyspellThis is the real spell checker
flycheck-languagetoolhttps://github.com/emacs-languagetool/flycheck-languagetool
flycheck-grammarlyhttps://github.com/emacs-grammarly/flycheck-grammarly
lsp-ltexhttps://github.com/emacs-languagetool/lsp-ltex/
languagetoolhttps://github.com/PillFall/Emacs-LanguageTool.el
(use-package flymake
  :straight (:type built-in)  ; built-in
  :config
  (setq flymake-no-changes-timeout 2)
  )

(use-package flyspell-correct
  :after flyspell
  :bind (:map flyspell-mode-map ("C-;" . flyspell-correct-wrapper)))

(use-package grammarly
  :straight (:host github :repo "emacs-grammarly/grammarly")
  :config
  ;; (require 'grammarly)
  (grammarly-load-from-authinfo)
  )
(use-package eglot
  :straight (:type built-in)  ; built-in
  ;; :after (flymake)
  :init
  (use-package eglot-grammarly
    :after (grammarly)
    :straight (:host github :repo "emacs-grammarly/eglot-grammarly")
    :defer t  ; defer package loading
    ;; :hook ((text-mode markdown-mode). (lambda ()
    ;;                                     (require 'eglot-grammarly)
    ;;                                     (eglot-ensure)))
    :config
    (defun mk/enable-grammarly ()
      "Enable grammarly for the current buffer."
      (interactive)
      (require 'eglot-grammarly)
      (eglot-ensure))
    )
  )

;; Two other flymake grammarly checkers
(use-package flymake-grammarly
  :disabled t  ; use eglot
  :straight (:host github :repo "emacs-grammarly/flymake-grammarly")
  :init
  :config
  ;; (flymake-grammarly-setup)
  (setq flymake-grammarly-check-time 2)
  )
(use-package flymake-languagetool
  ;; :disabled t
  :after flymake
  :hook ((text-mode       . flymake-languagetool-load)
         (latex-mode      . flymake-languagetool-load)
         (org-mode        . flymake-languagetool-load)
         (markdown-mode   . flymake-languagetool-load))
  :init
  ;; Remote server config with LanguageTool's free API
  ;; (setq flymake-languagetool-url "https://api.languagetool.org")
  ;; (setq flymake-languagetool-server-port nil)
  ;; (setq flymake-languagetool-server-jar nil)

  ;; Local server config
  (setq flymake-languagetool-server-jar "/usr/local/Cellar/languagetool/5.9/libexec/languagetool-server.jar")
  )

Language and spelling

Input method

pyimEmacs input methodhttps://github.com/tumashu/pyim
sisSmart input source
emacs-rime
(use-package rime
  :straight (rime :type git
                  :host github
                  :repo "DogLooksGood/emacs-rime"
                  :files ("*.el" "Makefile" "lib.c"))
  :custom
  (default-input-method "rime")
  (rime-librime-root "~/.emacs.d/librime/dist")
  (rime-share-data-dir "~/Library/Rime")
  (rime-user-data-dir "~/Library/Rime")
  (rime-show-candidate 'posframe)
  (rime-posframe-properties
   (list :background-color "#000000"  ; 不要在这里设置字体,会影响后面 face 里字体的
         :foreground-color "#f33333"
         :internal-border-width 10))
  :config
  (set-face-attribute 'rime-default-face nil
                      :background "#000000"
                      :foreground "honeydew1"
                      :font "Hei-20")
  (set-face-attribute 'rime-highlight-candidate-face nil
                      ;; :background "#f33333"
                      :foreground "#FFFF00"
                      :font "Hei-20")
  (set-face-attribute 'rime-code-face nil
                      :font "Hei-20")
  )

CJK font jumping

(use-package jieba
  :delight
  :after (evil)
  :straight (:host github :repo "mkvoya/jieba.el" :files ("*"))
  :init  ; We need to enable jieba during init so that it can construct the jieba in background, rather than when autoloading the functions.
  (jieba-mode)
  (defun mk/forward-word()
    "mk's better forward-word."
    (interactive)
    (let ((char (char-after)))
      (if (memq char (string-to-list " \n\r\\"))
          (re-search-forward "\\\s+")
        (jieba-forward-word))))
  (define-key evil-motion-state-map (kbd "w") #'mk/forward-word)
  (define-key evil-motion-state-map (kbd "b") #'jieba-backward-word)
  )

CJK font alignment

(use-package valign
  :hook (org-mode-hook . valign-mode)
  )

Word count

(load-file "~/.emacs.d/site-lisp/wc.el")

Navigation in code

Citre: Tag jumps

(use-package citre
  :defer t
  :after (evil)
  :init
  ;; This is needed in `:init' block for lazy load to work.
  (require 'citre-config)
  :config
  ;; Bind your frequently used commands.
  (global-set-key (kbd "C-x c j") 'citre-jump)
  (global-set-key (kbd "C-x c J") 'citre-jump-back)
  (global-set-key (kbd "C-x c p") 'citre-ace-peek)
  (global-set-key (kbd "C-]") 'citre-jump)
  (global-set-key (kbd "C-t") 'citre-jump-back)
  (define-key evil-motion-state-map (kbd "C-]") 'citre-jump)
  (define-key evil-motion-state-map (kbd "C-t") 'citre-jump-back)
  (define-key evil-normal-state-map (kbd "C-]") 'citre-jump)
  (define-key evil-normal-state-map (kbd "C-t") 'citre-jump-back)
  (setq citre-project-root-function
        #'(lambda ()
            (when-let ((project (project-current nil)))
              (expand-file-name (nth 2 project)))))
  )

Config

Save hist

;; Persist history over Emacs restarts. Vertico sorts by history position.
(use-package savehist
  :straight nil
  :config
  (savehist-mode))

delight: altering mode appearences on mode line

diminish
delight (better)https://elpa.gnu.org/packages/delight.html
(use-package delight)  ; Actually, we don't even show minor modes in the modeline.

Scroll bar

nyan-modehttps://github.com/TeMPOraL/nyan-mode/
yascroll.elhttps://github.com/emacsorphanage/yascroll

Currently, yascroll won’t show upon mouse-triggerred scrolling.

(use-package yascroll
  :disabled t  ; This sometimes causes 99% CPU usage.
  :delight
  :config
  ;; (advice-add :after 'pixel-scroll-up 'run-window-scroll-functions)
  ;; (advice-add :after 'pixel-scroll-down 'run-window-scroll-functions)
  (global-yascroll-bar-mode 1)
  )
;; (use-package nyan-mode :disabled t :config (nyan-mode t))

Magit

diff-hlHightlight uncommitted changeshttps://github.com/dgutov/diff-hl
(use-package magit
  :straight nil  ; built-in
  :after (project)
  :defer t
  :init
  (setq magit-diff-refine-hunk t)
  :config
  (use-package magit-extras
    :straight nil
    :init
    (setq magit-bind-magit-project-status t)
    )
  )
(use-package git-link :defer t)
(use-package forge :after (magit) :defer t)
;; (use-package git-timemachine)

(use-package diff-hl
  :defer t
  :after (magit)
  :config
  (global-diff-hl-mode)
  (add-hook 'magit-pre-refresh-hook 'diff-hl-magit-pre-refresh)
  (add-hook 'magit-post-refresh-hook 'diff-hl-magit-post-refresh))
;; Winner mode
(use-package winner :defer t :config (winner-mode 1))

;;minibuffer editing
;;(use-package miniedit
;;  :defer t
;;  :commands minibuffer-edit
;;  :init (miniedit-install))
(use-package blamer
  :ensure t
  :bind (("s-i" . blamer-show-commit-info))
  :defer 20
  :custom
  (blamer-idle-time 0.3)
  (blamer-min-offset 70)
  :custom-face
  (blamer-face ((t :foreground "#7a88cf"
                   :background nil
                   :height 110
                   :italic t)))
  :config
  ;; (global-blamer-mode 1)
  )

Undo

undo-treebuilt-in
undo-fu
(use-package undo-fu :ensure t)
(use-package undo-tree
  :disabled
  :config
  (setq undo-tree-visualizer-timestamps t)
  (setq undo-tree-visualizer-diff t)
  (global-undo-tree-mode))

Evil

(use-package evil
  :straight t
  :after (undo-fu)
  :init
  (setq evil-want-C-i-jump nil)
  :config
  ;; Use man (instead of WoMan) for man pages, although is slow in Emacs.
  ;; Install man-db, check this: https://www.reddit.com/r/emacs/comments/mfmg3x/disabling_ivy_for_a_specific_command/
  (evil-define-motion evil-lookup ()
    "Look up the keyword at point. Calls `evil-lookup-func'."
    (call-interactively #'man))

  (setq evil-want-fine-undo t)
  (define-key evil-normal-state-map (kbd "C-u") 'evil-scroll-up)
  (evil-set-undo-system 'undo-fu)
  (use-package evil-numbers
    :demand t
    :config
    (define-key evil-normal-state-map (kbd "C-a") 'evil-numbers/inc-at-pt)
    (define-key evil-normal-state-map (kbd "C-S-a") 'evil-numbers/dec-at-pt))
  ;; Evil rebind
  ;; :q should kill the current buffer rather than quitting emacs entirely
  (defun mk/ex-quit ()
    "Evil ex quit."
    (interactive)
    (if (one-window-p "visible")
        (kill-this-buffer)
      (evil-window-delete)))
  (evil-ex-define-cmd "q" #'mk/ex-quit)
  ;; Need to type out :quit to close emacs
  (evil-ex-define-cmd "quit" 'evil-quit)
  ;; (setq evil-emacs-state-cursor '("SkyBlue2" bar))
  ;; (setq evil-emacs-state-cursor '(hollow))
  (setq evil-emacs-state-cursor '(bar . 3))
  ;; Disable Evil in snails-mode

  (dolist (nonevil-mode '(snails-mode
                          notdeft-mode
                          vterm-mode
                          netease-cloud-music-mode
                          cnfonts-ui-mode
                          Ilist-mode
                          TeX-output-mode
                          ebib-index-mode
                          ebib-entry-mode
                          ebib-strings-mode
                          minibuffer-mode
                          corfu-mode
                          motd-message-mode
                          special-mode
                          ))
    (evil-set-initial-state nonevil-mode 'emacs))

  (evil-mode 1))

Evil: Easy Motion

evil-easymotionhttps://github.com/PythonNut/evil-easymotion
evil-snipehttps://github.com/hlissner/evil-snipe
avyhttps://github.com/abo-abo/avy
(use-package evil-easymotion
  :after (evil)
  :demand t
  :config
  (evilem-default-keybindings "SPC")

  (defun avy-goto-char (char &optional arg)
    "Jump to the currently visible CHAR.
     The window scope is determined by `avy-all-windows' (ARG negates it)."
    (interactive (list (read-char "char: " t)
                       current-prefix-arg))
    (if (= ?  char)
        (counsel-M-x)
      (avy-with avy-goto-char
        (avy-jump
         (if (= 13 char)
             "\n"
           (regexp-quote (string char)))
         :window-flip arg))))
  (define-key evil-normal-state-map (kbd "SPC") 'avy-goto-char))

Evil: Magit

;; optional: this is the evil state that evil-magit will use
;; (setq evil-magit-state 'normal)
;; optional: disable additional bindings for yanking text
;; (setq evil-magit-use-y-for-yank nil)
(use-package evil-magit
  :after (evil magit)
  :defer t)

Dir

(use-package neotree :defer t)
;; (use-package perspective :config (persp-mode))

Ctrl-f

(use-package ctrlf
  :defer t
  :config
  (ctrlf-mode +1))

smart-tab

;;; Smart Tab
(use-package smart-tab
  :straight nil
  :defer t
  :config
  (smart-tabs-insinuate 'c 'javascript))

Which-Key: Emacs package that displays available keybindings in popup

which-keyhttps://github.com/justbur/emacs-which-key
;; which-key is a fork of guide-key
(use-package which-key
  :bind (
         ("C-h ,m" . which-key-show-major-mode)
         ("C-h ,t" . which-key-show-top-level)
         ("C-h ,n" . which-key-show-next-page)
         )
  :init
  (setq which-key-show-remaining-keys t)

  (setq which-key-show-early-on-C-h t)
  (setq which-key-idle-delay 2)
  (setq which-key-allow-imprecise-window-fit t)
  (setq which-key-sort-order 'which-key-prefix-then-key-order)
  ;; (which-key-setup-minibuffer)
  (which-key-mode)
  )

Calendar

(use-package calendar
  :init
  (setq calendar-longitude 121.4737
        calendar-latitude 31.2304
        calendar-location-name "SH")

  (use-package celestial-mode-line
    :disabled
    :init
    ;; (defvar celestial-mode-line-phase-representation-alist '((0 . "○") (1 . "☽") (2 . "●") (3 . "☾")))
    ;; (defvar celestial-mode-line-sunrise-sunset-alist '((sunrise . "☀↑") (sunset . "☀↓")))
    :config
    ;; add to end of global-mode-string
    (if (null global-mode-string)
        (setq global-mode-string '("" celestial-mode-line-string))
      (add-to-list 'global-mode-string 'celestial-mode-line-string t))
    (celestial-mode-line-start-timer)
    )
  :config
  (defun mk/notmuch-open-unread-view()
    "Open notmuch panel for unread mails."
    (interactive)
    (require 'notmuch)
    (notmuch-search "tag:unread"))
  (defun mk/notmuch-count-unread()
    "Get the notmuch unread mail count if notmuch is loaded."
    (if (fboundp 'notmuch-command-to-string)
        (replace-regexp-in-string "\n" ""
                                  (notmuch-command-to-string "count"
                                                             "tag:unread"))
      "?"))
  (defun mk/mode-line-mail ()
    "Show the unread mail count in the mode line."
    )
  (setq display-time-string-forms
        '((format-time-string "%F %H:%M")
          (propertize
            (format " [M:%s]" (mk/notmuch-count-unread))
            'help-echo  "Unread!"
            'keymap  (let ((map (make-sparse-keymap)))
                      (define-key map [mouse-1]
                                  #'mk/notmuch-open-unread-view)
                      map))))
  (display-time-mode 1))

Rainbow

(use-package rainbow-mode
  :defer t
  :config (rainbow-mode t))
(use-package rainbow-delimiters
  :hook (prog-mode . rainbow-delimiters-mode))

Calender

(setq calendar-chinese-all-holidays-flag t)
(use-package cal-china-x
  :defer t
  :config
  (setq mark-holidays-in-calendar t)
  (setq cal-china-x-important-holidays cal-china-x-chinese-holidays)
  (setq cal-china-x-general-holidays '((holiday-lunar 1 15 "元宵节")))
  (setq calendar-holidays
        (append cal-china-x-important-holidays
                cal-china-x-general-holidays))
  )

Calfw - A calendar framework for Emacs

Calfwhttps://github.com/kiwanami/emacs-calfw
(use-package calfw
  :init
  (use-package calfw-org :after (org))
  :config
  (defun mk/open-calendar ()
    (interactive)
    (cfw:open-calendar-buffer
     :contents-sources
     (list
      (cfw:org-create-source "Green")  ; orgmode source
      ;; (cfw:howm-create-source "Blue")  ; howm source
      ;; (cfw:cal-create-source "Orange") ; diary source
      ;; (cfw:ical-create-source "Moon" "~/moon.ics" "Gray")  ; ICS source1
      ;; (cfw:ical-create-source "gcal" "https://..../basic.ics" "IndianRed") ; google calendar ICS
      )))
  )

whitespace

whitespaceBuilt-inhttp://ergoemacs.org/emacs/whitespace-mode.html
;;; Use whitespace (instead of column-marker, column-enforce-mode)
(use-package whitespace
  :ensure nil
  :config
  (setq whitespace-style
        '(face trailing tabs newline tab-mark newline-mark))
  ;; '(face trailing tabs newline tab-mark newline-mark lines-tail)
  (setq whitespace-display-mappings
        '((newline-mark 10 [8617 10])
          (tab-mark 9 [8594 9] [92 9])))
  (set-face-background 'trailing-whitespace "#ffaf5f")
  (set-face-background 'whitespace-trailing "#ffaf5f")
  (if mk-feature/gui
      (set-face-background 'whitespace-tab "#FAFAFA")
    (set-face-background 'whitespace-tab "undefined")
    )
  ;; (global-whitespace-mode t)
  (add-hook 'prog-mode-hook 'whitespace-mode)
  )

Appearance

(use-package emacs
  :straight nil
  :config
  (setq-default prettify-symbols-alist '(("#+BEGIN_SRC" . "λ")  ; previously ✎
                                         ("#+END_SRC" . "")
                                         ("#+begin_src" . "λ")
                                         ("#+end_src" . "")
                                         ("#+begin_quote" . )
                                         ("#+end_quote" . )
                                         ("#+BEGIN_QUOTE" . )
                                         ("#+END_QUOTE" . )
                                         ))
  (global-prettify-symbols-mode)
  (setq-default indicate-buffer-boundaries 'left)
  )

Theme and modeline

monokai-theme
grandshell-theme
alect-themes
airline-themes
manoj-light
doom-one-light
hemisu-light
doom-modeline
smart-mode-line
awesome-tray
spaceline
(use-package emacs
  :straight nil
  :config
  (setq window-divider-default-right-width 2)
  (setq window-divider-default-bottom-width 2)
  (setq window-divider-default-places t)
  (window-divider-mode 1))

(defun mk/modeline-setup ()
  "Setup my modeline."
  (progn
    ;; mode line
    (column-number-mode 1)
    (if mk-feature/light
        (progn
          ;; light theme
          (set-face-attribute 'mode-line           nil :background "#CFEF9F")
          (set-face-attribute 'mode-line-buffer-id nil :background "#3F2F1F" :foreground "white")
          (set-face-attribute 'mode-line-highlight nil :box nil :background "black")
          (set-face-attribute 'mode-line-inactive  nil :inherit 'default)
          (when (eq system-type 'darwin)
            (set-face-attribute 'top-bar nil :background "#EFEFEF" :foreground "#333333" :font "Menlo-12")
            )
          )
      ;; dark theme
      (set-face-attribute 'mode-line           nil :background "#CF3F1F")
      (set-face-attribute 'mode-line-buffer-id nil :background "#3F2F1F" :foreground "white")
      (set-face-attribute 'mode-line-highlight nil :box nil :background "black")
      (set-face-attribute 'mode-line-inactive  nil :inherit 'default)
      (when (eq system-type 'darwin)
        (set-face-attribute 'top-bar nil :background "#2F2F2F" :foreground "#fFeF5F" :font "Menlo-12")
        )
      )

    ;; Thank https://emacs.stackexchange.com/a/37270/30542
    (defun simple-mode-line-render (left right)
      "Return a string of `window-width' length. Containing LEFT, and RIGHT aligned respectively."
      (let ((available-width (- (window-total-width)
                                (+ (length (format-mode-line left))
                                   (length (format-mode-line right))
                                   ))))
        (append left
                (list (format (format "%%%ds" available-width) ""))
                right)))

    (require 'uniquify)
    (setq uniquify-buffer-name-style 'forward)

    (setq-default mode-line-format
                  '((:eval
                     (simple-mode-line-render
                      ;; Left.
                      '("[%*]"
                        evil-mode-line-tag
                        mode-line-buffer-identification
                        )
                      ;; Right.
                      '(" %e %o %l:%c "
                        mode-line-frame-identification
                        ;; mode-line-modes
                        " %m "
                        mode-line-misc-info
                        " ")))))
    ))

(use-package hemisu-theme
  :straight (:host github :repo "mkvoya/hemisu-theme" :files ("*.el"))
  :disabled
  :config
  ;; (load-theme (if mk-feature/light 'hemisu-light 'hemisu-dark) t)
  )
(use-package abyss-theme)
(use-package dracula-theme
  :after (org)
  :config
  ;; (load-theme 'dracula t)
  ;; (setq mk-feature/light nil)
  )

(use-package emacs
  :after (org)
  :config
  (set-face-attribute 'org-level-1 nil :height 1.1)
  (set-face-attribute 'fringe nil :background nil) ; Visually hide left-right margins
  (mk/modeline-setup)
  )

(use-package keycast
  :disabled
  :straight (:type git :host github :repo "tarsius/keycast")
  :init
  (keycast-mode)
  )

Beacon - A light that follows your cursor around so you don’t lose it!

beaconhttps://github.com/Malabarba/beacon
(use-package beacon
  :defer t
  :config
  (setq beacon-color "#00ff00")
  ;; (setq beacon-size 40)
  (beacon-mode 1))

Smooth scrolling

sublimity
smooth-scrolling
good-scroll
;; Mouse scrolling in terminal emacs
(unless (display-graphic-p)
  ;; activate mouse-based scrolling
  ;; ensure mouse
  (xterm-mouse-mode t)
  (global-set-key (kbd "<mouse-4>") 'scroll-down-line)
  (global-set-key (kbd "<mouse-5>") 'scroll-up-line))

Dashboard

(use-package xkcd :defer)
(use-package all-the-icons
  :if (display-graphic-p))
(use-package dashboard
  :if (< (length command-line-args) 2)
  :diminish dashboard-mode
  :init
  (use-package page-break-lines :ensure t :defer nil)
  :config
  (setq dashboard-banner-logo-title "What a nice day!")
  ;;(setq dashboard-startup-banner "/path/to/image")
  (setq dashboard-projects-backend 'project-el)
  (setq dashboard-items '((recents  . 10)
                          ;; (bookmarks . 10)
                          (projects . 5)
                          (agenda . 5)
                          ;; (registers . 5)
                          ))
  (setq dashboard-set-heading-icons t)
  (setq dashboard-set-file-icons t)
  (setq dashboard-agenda-sort-strategy '(time-up todo-state-up))
  (setq initial-buffer-choice (lambda () (get-buffer "*dashboard*")))
  (dashboard-setup-startup-hook))

Symbol Overlay

;; Thank https://github.com/Eason0210/emacs.d
(use-package symbol-overlay
  :hook ((prog-mode html-mode yaml-mode conf-mode) . symbol-overlay-mode)
  :bind (:map symbol-overlay-mode-map
              ("M-i" . symbol-overlay-put)
              ("M-n" . symbol-overlay-jump-next)
              ("M-p" . symbol-overlay-jump-prev)))

Volatile highlights

(use-package volatile-highlights
  :delight
  :straight (:host github :repo "k-talo/volatile-highlights.el")
  :config
  ;;-----------------------------------------------------------------------------
  ;; Supporting evil-mode.
  ;;-----------------------------------------------------------------------------
  (vhl/define-extension 'evil 'evil-paste-after 'evil-paste-before
                        'evil-paste-pop 'evil-move)
  (vhl/install-extension 'evil)
  (volatile-highlights-mode t)
  )

Programming Languages

Programming mode

Better line number from https://github.com/Eason0210/emacs.d/blob/330d530f56659338ff1fdf8f8089a7a6f66beed2/init.el#L796-L800

(defun make-underscore-part-of-words () (modify-syntax-entry ?_ "w"))
(add-hook 'prog-mode-hook #'make-underscore-part-of-words)

(use-package display-line-numbers
  :straight nil
  :hook (prog-mode . display-line-numbers-mode)
  :config
  ;; (setq-default display-line-numbers-width 3)
  )

C

(add-hook 'c-mode-hook
          (lambda() (setq tab-width 8
                          c-default-style "linux"
                          c-basic-offset 8
                          c-indent-tabs-mode t)))

C++

(add-to-list 'auto-mode-alist '("\\.h\\'" . c++-mode))
;; style I want to use in c++ mode
(c-add-style "my-style"
             '("stroustrup"
               (c-basic-offset . 4)            ; indent by four spaces
               (tab-width . 4)
               (indent-tabs-mode . t)        ; use tabs
               (c-offsets-alist . ((inline-open . 0)  ; custom indentation rules
                                   (brace-list-open . 0)
                                   (innamespace . [0])
                                   (statement-case-open . +)))))
(c-add-style "my-ycsb-c++-style"
             '("stroustrup"
               (c-basic-offset . 2)            ; indent by four spaces
               (tab-width . 2)
               (indent-tabs-mode . nil)        ; use tabs
               (c-offsets-alist . ((inline-open . 0)  ; custom indentation rules
                                   (brace-list-open . 0)
                                   (innamespace . [0])
                                   (statement-case-open . +)))))
(defun my-c++-mode-hook ()
  (c-set-style "my-ycsb-c++-style"))        ; use my-style defined above
(add-hook 'c++-mode-hook 'my-c++-mode-hook)
(use-package modern-cpp-font-lock
  :defer t
  :ensure t)

Markdown

(use-package markdown-mode
  :defer t
  :mode (("README\\.md\\'" . gfm-mode)
         ("\\.md\\'" . markdown-mode)
         ("\\.markdown\\'" . markdown-mode))
  :init (setq markdown-command "multimarkdown")
  :config
  ;; (custom-set-variables '(markdown-command "/usr/local/bin/pandoc"))
  (setq markdown-command "/usr/local/bin/pandoc")

  (setq markdown-preview-stylesheets (list "https://raw.githubusercontent.com/sindresorhus/github-markdown-css/gh-pages/github-markdown.css"))
  ;;"http://thomasf.github.io/solarized-css/solarized-light.min.css"
  )
(use-package flymd
  :after (markdown-mode))

LaTeX

(use-package tex
  :straight auctex
  :defer t
  :init
  (setq TeX-source-correlate-method 'synctex)
  (setq TeX-source-correlate-mode t)
  (setq TeX-source-correlate-start-server t)
  (provide 'tex-buf)  ; We don't have tex-buf anymore, just add this to make some packages happy.

  :config
  ;; make latexmk available via C-c C-c
  ;; Note: SyncTeX is setup via ~/.latexmkrc (see below)
  ;; (add-to-list 'TeX-command-list '("latexmk" "latexmk -pdf -escape-shell %s" TeX-run-TeX nil t :help "Run latexmk on file"))
  (add-to-list 'TeX-command-list '("Make" "make" TeX-run-command nil t))
  (add-to-list 'TeX-command-list '("Make Clean" "make clean" TeX-run-command nil t))
  (add-to-list 'TeX-command-list '("Make Clean & Make" "make clean && make" TeX-run-command nil t))
  ;; (setq-default TeX-command-default "Make")
  ;; from https://gist.github.com/stefano-meschiari/9217695
  (setq TeX-auto-save t)
  (setq Tex-parse-self t)
  ;; Guess/Ask for the master file.
  (setq-default TeX-master nil)


  ;; Thank https://tex.stackexchange.com/a/167097/122482
  (defun mk/shadow-iffalse-block ()
    (font-lock-add-keywords
     'latex-mode
     '(("\\\\iffalse\\(\\(.\\|\n\\)*\\)\\\\fi" 0 'font-lock-comment-face append))
     t))
  (add-hook 'latex-mode-hook #'mk/shadow-iffalse-block)

  (add-hook 'TeX-mode-hook (lambda () (setq TeX-command-default "Make")))
  (add-hook 'LaTeX-mode-hook (lambda()
                               (mkvoya/better-wrap)
                               (flyspell-mode)
                               (LaTeX-math-mode)
                               (darkroom-mode)
                               (visual-line-mode)
                               (visual-line-mode)
                               ))
  ;; (add-hook 'TeX-output-mode (lambda () (goto-char (point-max))))

  (setq reftex-refstyle "\\ref")
  (setq reftex-plug-into-AUCTeX t)
  (setq TeX-PDF-mode t)

  (setq TeX-view-program-selection '((output-pdf "PDF Viewer")))
  (setq TeX-view-program-list
        '(("PDF Viewer" "/Applications/Skim.app/Contents/SharedSupport/displayline -b -g %n %o %b")))

  (setq TeX-error-overview-open-after-TeX-run t)
  ;; (setq mkvoya/tex-auto-compile nil)
  ;; (defun mkvoya/tex-try-auto-compile ()
  ;;   (when (and (eq major-mode 'TeX-mode)
  ;;              (mkvoya/tex-auto-compile))
  ;;     (TeX-command-run))
  ;;   )
  ;; (add-hook 'after-save-hook #'mkvoya/tex-try-auto-compile)

  (add-hook 'TeX-after-compilation-finished-functions #'TeX-revert-document-buffer)

  (use-package reftex
    :defer t
    :config
    (add-hook 'LaTeX-mode-hook 'turn-on-reftex)   ; with AUCTeX LaTeX mode
    (add-hook 'latex-mode-hook 'turn-on-reftex)   ; with Emacs latex mode
    ;; (setq reftex-default-bibliography '("./references.bib"))
    )
  (use-package company-auctex :defer t :after (company) :config (company-auctex-init))
  (use-package company-reftex :defer t :after (company reftex)
    :config
    (add-to-list 'company-backends 'company-reftex-labels)
    (add-to-list 'company-backends 'company-reftex-citations))
  ;; (use-package auctex-latexmk :config (auctex-latexmk-setup))
  )

PDF Tools

(use-package pdf-tools :defer t
  :if mk-feature/gui
  :init
  :mode ("\\.pdf\\'" . pdf-view-mode)
  :magic ("%PDF" . pdf-view-mode)
  :bind (:map pdf-view-mode-map
         ("<wheel-right>" . image-forward-hscroll)
         ("<wheel-left>" . image-backward-hscroll)
         ("<pinch>" . mk/pdf-tools-scale-pinch)
         )
  :config

  (defun mk/pdf-tools-scale-pinch (event)
    "Adjust the height of the default face by the scale in the pinch event EVENT."
    (interactive "e")
    (when (not (eq (event-basic-type event) 'pinch))
      (error "bad event type"))
    (let ((window (posn-window (nth 1 event)))
          (scale (nth 4 event))
          (dx (nth 2 event))
          (dy (nth 3 event))
          (angle (nth 5 event)))
      (with-selected-window window
        (when (< scale 1)
          (pdf-view-shrink 1.1))
        (when (> scale 1)
          (pdf-view-enlarge 1.1)))))
  (pdf-loader-install)
  (add-hook 'pdf-view-mode-hook #'(lambda () (pixel-scroll-precision-mode -1)))
  )
;; (use-package pdf-tools
;;   :magic ("%PDF" . pdf-view-mode)
;;   :config
;;   (pdf-tools-install :no-query))
;; https://emacs.stackexchange.com/questions/45546/per-mode-value-for-fill-column
(defun mkvoya/tex-mode-hook ()
  (setq fill-column 1024))
(add-hook 'TeX-mode-hook #'mkvoya/tex-mode-hook)

Python & Web

;; Python Support
(use-package elpy :defer t)
(use-package py-autopep8
  :defer t
  :config
  (setq py-autopep8-options '("--max-line-length=120")))
(use-package blacken
  :defer t
  :config
  (setq blacken-line-length 120))
(use-package ein :defer t)
(use-package live-py-mode :defer t)
(use-package jinja2-mode :mode "\\.jinja2\\'" :defer t)
(use-package vue-mode :mode "\\.vue\\'" :defer t)

Asciidoc

(use-package adoc-mode
  :defer t
  :straight (:host github :repo "sensorflo/adoc-mode"))

Tramp

(use-package tramp
  :straight nil
  :init
  (use-package tramp-sh :straight nil :defer t)
  ;; (setq tramp-debug-buffer t)
  (setq tramp-verbose 10)
  (setq tramp-ssh-controlmaster-options
        (concat
         "-o ControlPath=/Volumes/ramfs/ssh-ControlPath-%%r@%%h:%%p "
         "-o ControlMaster=auto -o ControlPersist=yes"))

  :defer t
  :config

  (setq tramp-remote-path
        (append tramp-remote-path
                '(tramp-own-remote-path)))

  ;; Speedup the C++ file over Tramp.
  (setq remote-file-name-inhibit-cache nil)
  (setq vc-ignore-dir-regexp
        (format "%s\\|%s"
                vc-ignore-dir-regexp
                tramp-file-name-regexp))
  (setq tramp-verbose 1)
  )
(modify-syntax-entry ?_ "w")

Built in packages

Check https://emacs-china.org/t/emacs-builtin-mode/11937

(use-package paren
  :defer t
  :config
  (setq show-paren-when-point-inside-paren t
        show-paren-when-point-in-periphery t)
  (show-paren-mode)
  )
(use-package so-long
  :defer t
  :config (global-so-long-mode 1))
(use-package simple
  :straight nil
  :hook (after-init . (lambda ()
                        (line-number-mode)
                        (column-number-mode)
                        (size-indication-mode)
                        ;; better line wrapping for cjk. Try =toggle-word-wrap=
                        (setq-default word-wrap nil)
                        (setq word-wrap nil)
                        )))

Mail Client

notmuch
WanderLust
;; Mails
(use-package notmuch
  :if mk-feature/news-mail
  :after (exec-path-from-shell)
  :ensure nil
  :defer 5)  ; start after being idle for 5s

Feeding (RSS & Atom)

elfeedhttps://github.com/skeeto/elfeed
(use-package elfeed
  :if mk-feature/news-mail
  :defer t
  :config
  ;; Global key
  (global-set-key (kbd "C-x w") 'elfeed)
  ;; The feed list
  (setq elfeed-feeds
        '(("http://nullprogram.com/feed/" blog emacs)
          "http://www.50ply.com/atom.xml"  ; no autotagging
          ("http://nedroid.com/feed/" webcomic)
          "http://planet.emacsen.org/atom.xml"))
  ;; (setq-default elfeed-search-filter "@1-week-ago +unread ")
  )

Org-mode

Org

;; Enable Org mode
(use-package org
  :straight nil
  :defer 2
  :mode ("\\.org\\'" . org-mode)
  :bind (("C-c a" . #'org-agenda)
         ("C-c c" . #'org-capture)
         )
  :init
  ;; (setq org-latex-create-formula-image-program 'dvisvgm)
  (setq org-latex-create-formula-image-program 'imagemagick)
  (setq org-support-shift-select t)  ; Use shift to select region when possible.
  (setq org-clock-idle-time 10)  ; Clock will prompt to stop after 10 min of idle.
  ;; Thanks! https://emacs.stackexchange.com/a/68321/30542
  (defun org-syntax-table-modify ()
    "Modify `org-mode-syntax-table' for the current org buffer."
    (modify-syntax-entry ?< "." org-mode-syntax-table)
    (modify-syntax-entry ?> "." org-mode-syntax-table))
  (add-hook 'org-mode-hook #'org-syntax-table-modify)

  ;; Thank https://emacs-china.org/t/org-link-echo-area-link/19927/2
  (defun org-show-link-when-idle()
    ;; 在echo area中显示链接详情
    (require 'help-at-pt)
    (setq help-at-pt-display-when-idle t) ;; 不会立即生效
    (setq help-at-pt-timer-delay 0.5)
    (help-at-pt-set-timer) ;; 调用才会生效
    )
  (add-hook 'org-mode-hook #'org-show-link-when-idle)

  (setq org-modules '(ol-doi
                      ;; ol-w3m o-bbdb ol-gnus ol-mhe ol-rmail ol-eww
                      ol-bibtex
                      ol-docview
                      ol-irc
                      ol-info))
  (setq org-element-use-cache nil)  ; cache sometimes causes problems
  (use-package org-num-mode
    :defer t
    :straight nil  ; built-in with org-mode
    :hook (org-mode . org-num-mode))
  :config

  (setq org-display-remote-inline-images 'download)

  ;; Auto add DONE TIME, from https://orgmode.org/guide/Progress-Logging.html
  (setq org-log-done 'time)

  ;; Org mode TODO states
  (setq org-todo-keywords
        '((sequence
           "TODO(t)"  ; New task
           "HAND(h)"  ; Doing
           "WAIT(w)"  ; Procrastinated on purpose
           "LONG-TERM(l)"  ; Long-term
           "DELEGATE(g)"   ; Delegated
           "IDEA(i)" "EXP(e)" "TIP(i)" "COLL(C)"
           "CONFDDL(C)"
           "PROJECT(p)"
           "GOAL(G)"
           "|"
           "DONE(d!)"      ; Done
           "CANCELED(c@)"  ; Eliminated
           )))
  ;; Keyword colors
  (setf org-todo-keyword-faces
        '(
          ;; Many styles from https://github.com/GTrunSec/my-profile/blob/master/dotfiles/doom-emacs/config.org
          ;; ("TODO" . (:foreground "#ff39a3" :weight bold))
          ("TODO" . (:foreground "#dfffff" :background "#ff19a3" :weight bold))
          ("HAND"  . "orangered")
          ("WAIT" . "pink")
          ;; ("CANCELED" . (:foreground "white" :background "#4d4d4d" :weight bold :strike-through "#0d0d0d"))
          ("CANCELED" . (:foreground "white" :background "#4d4d4d"))
          ;; ("DONE" . "#008080")
          ("DONE" . (:foreground "#008080"))
          ("DELEGATE"  . "DeepSkyBlue")
          ))

  ;; Strike through the whole line with DONE entry
  ;; (font-lock-add-keywords
  ;;  'org-mode
  ;;  '(
  ;;    ("\\* \\<DONE .*" 0 'shr-strike-through append)
  ;;    ("\\* \\<CANCELED .*" 0 'shr-strike-through append))
  ;;  t)

  ;; …, ➡, ⚡, ▼, ↴, , ∞, ⬎, ⤷, ⤵ "↴▾▽▼↩↘↸"
  (setq org-ellipsis "")

  ;; https://stackoverflow.com/questions/17590784/how-to-let-org-mode-open-a-link-like-file-file-org-in-current-window-inste
  (defun org-force-open-current-window ()
    "Open at current window."
    (interactive)
    (let ((org-link-frame-setup (quote
                                 ((vm . vm-visit-folder)
                                  (vm-imap . vm-visit-imap-folder)
                                  (file . find-file)
                                  (wl . wl)))
                                ))
      (org-open-at-point)))

  ;; Depending on universal argument try opening link
  (defun org-open-maybe (&optional arg)
    "Open maybe ARG."
    (interactive "P")
    (if arg (org-open-at-point)
      (org-force-open-current-window)))
  ;; Redefine file opening without clobbering universal argument
  (define-key org-mode-map "\C-c\C-o" 'org-open-maybe)

  (org-babel-do-load-languages
   'org-babel-load-languages
   '((dot . t)
     (C . t)
     (python . t)))

  ;; https://emacs.stackexchange.com/questions/3302/live-refresh-of-inline-images-with-org-display-inline-images
  ;; Always redisplay inline images after executing SRC block
  (add-hook 'org-babel-after-execute-hook 'org-redisplay-inline-images)


  (require 'color)

  (when mk-feature/gui
    (set-face-attribute 'org-block nil :background
                        (color-darken-name
                         (face-attribute 'default :background) 3))
    (set-face-attribute 'org-code nil :background
                        (color-darken-name
                         (face-attribute 'default :background) 3))
    (set-face-attribute 'org-quote nil :background
                        (color-darken-name
                         (face-attribute 'default :background) 3))
    (set-face-attribute 'org-block-begin-line nil :background
                        "#F1E6F8")
    (set-face-attribute 'org-block-end-line nil :background
                        (color-darken-name
                         (face-attribute 'default :background) 4)))
  (setq org-fontify-quote-and-verse-blocks t)

  (add-hook 'org-mode-hook
            (lambda ()
              ;; (org-shifttab 5)
              ;; (add-to-list 'write-file-functions 'delete-trailing-whitespace)
              (electric-indent-local-mode -1)
              (mkvoya/better-wrap)
              (prettify-symbols-mode)
              ;; (org-hide-properties)
              ))

  ;; According to https://orgmode.org/manual/Hard-indentation.html#Hard-indentation
  ;; But I don't need the odd levels only
  (setq org-adapt-indentation t
        org-hide-leading-stars t)
  ;;org-odd-levels-only t

  (use-package org-contrib :disabled)
  (use-package org-inline-pdf :defer t)
  (use-package org-super-agenda
    :init
    (org-super-agenda-mode)
    :config
    (setq org-super-agenda-groups
          '((:name "Next Items"
                   :time-grid t
                   :tag ("NEXT" "outbox"))
            (:name "Important"
                   :priority "A")
            (:name "Quick Picks"
                   :effort< "0:30")
            (:priority<= "B"
                         :scheduled future
                         :order 1)))
    )
  (set-face-attribute 'outline-1 nil :foreground "purple2")
  (set-face-attribute 'org-level-1 nil :height 1.2)
  (set-face-attribute 'org-level-1 nil :height 1.1)
  (set-face-attribute 'outline-2 nil :foreground "violetRed2")
  (set-face-attribute 'outline-3 nil :foreground "cyan4")
  (set-face-attribute 'outline-4 nil :foreground "springgreen4")
  )

SVG checkboxs

Add svg checkbox that can be clicked.

An example:

[X] item1 [ ] item2 [X] item 3 [X] item3

(use-package svg-lib :demand t)
(use-package svg-tag-mode
  :disabled t
  :if mk-feature/gui
  :commands svg-tag-mode
  :hook (org-mode . svg-tag-mode)
  :demand t
  :after (svg-lib org)
  :straight (:host github :repo "rougier/svg-tag-mode" :files ("svg-tag-mode.el"))
  :config

  (defun mk/svg-prop-drawer(props)
    (let* ((svg (svg-create 14 14)))
      (svg-rectangle svg 0 0 14 14 :fill 'white :rx 2 :stroke-width 2.5 :stroke-color 'black)
      (svg-image svg :ascent 'center)
      ))

  (defun mk/svg-checkbox-empty()
    (let* ((svg (svg-create 14 14)))
      (svg-rectangle svg 0 0 14 14 :fill 'white :rx 2 :stroke-width 2.5 :stroke-color 'black)
      (svg-image svg :ascent 'center)
      ))

  (defun mk/svg-checkbox-filled()
    (let* ((svg (svg-create 14 14)))
      (svg-rectangle svg 0 0 14 14 :fill "#FFFFFF" :rx 2)
      (svg-polygon svg '((5.5 . 11) (12 . 3.5) (11 . 2) (5.5 . 9) (1.5 . 5) (1 . 6.5))
                   :stroke-color 'black :stroke-width 1 :fill 'black)
      (svg-image svg :ascent 'center)
      ))
  ;; (insert-image (svg-checkbox-empty))
  ;; (insert-image (svg-checkbox-filled))
  (defun mk/svg-checkbox-toggle()
    (interactive)
    (save-excursion
      (let* ((start-pos (line-beginning-position))
             (end-pos (line-end-position))
             (text (buffer-substring-no-properties start-pos end-pos))
             (case-fold-search t)  ; Let X and x be the same in search
             )
        (beginning-of-line)
        (cond ((string-match-p "\\[X\\]" text)
               (progn
                 (re-search-forward "\\[X\\]" end-pos)
                 (replace-match "[ ]")))
              ((string-match-p "\\[ \\]" text)
               (progn
                 (search-forward "[ ]" end-pos)
                 (replace-match "[X]")))
              ))))

  (defconst date-re "[0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\}")
  (defconst time-re "[0-9]\\{2\\}:[0-9]\\{2\\}")
  (defconst day-re "[A-Za-z]\\{3\\}")
  (defconst day-time-re (format "\\(%s\\)? ?\\(%s\\)?" day-re time-re))

  (setq svg-tag-tags
        `(
          ;; Properties
          ;; ("^:PROPERTIES:\n\\(:ID:.*\n\\)*?:END:$" . ((lambda (tag)
          ;;                                               (string-match ":ID:[[:space:]]*\\(.*\\)$" tag)
          ;;                                               (svg-tag-make (concat "⚙ ID: " (match-string 1 tag))))))
          ;; Org tags
          ;; (":\\([A-Za-z0-9]+\\)" . ((lambda (tag) (svg-tag-make tag))))
          ;; (":\\([A-Za-z0-9]+[ \-]\\)" . ((lambda (tag) tag)))

          ;; Task priority
          ("\\[#[A-Z]\\]" . ( (lambda (tag)
                                (svg-tag-make tag :face 'org-priority
                                              :beg 2 :end -1 :margin 0))))

          ;; TODO / DONE
          ("TODO" . ((lambda (tag) (svg-tag-make "TODO" :face 'org-todo :inverse t :margin 0))))
          ("DONE" . ((lambda (tag) (svg-tag-make "DONE" :face 'org-done :margin 0))))

          ;; Active date (with or without day name, with or without time)
          (,(format "\\(<%s>\\)" date-re) .
           ((lambda (tag)
              (svg-tag-make tag :beg 1 :end -1 :margin 0))))
          (,(format "\\(<%s \\)%s>" date-re day-time-re) .
           ((lambda (tag)
              (svg-tag-make tag :beg 1 :inverse nil :crop-right t :margin 0))))
          (,(format "<%s \\(%s>\\)" date-re day-time-re) .
           ((lambda (tag)
              (svg-tag-make tag :end -1 :inverse t :crop-left t :margin 0))))

          ;; Inactive date  (with or without day name, with or without time)
          (,(format "\\(\\[%s\\]\\)" date-re) .
           ((lambda (tag)
              (svg-tag-make tag :beg 1 :end -1 :margin 0 :face 'org-date))))
          (,(format "\\(\\[%s \\)%s\\]" date-re day-time-re) .
           ((lambda (tag)
              (svg-tag-make tag :beg 1 :inverse nil :crop-right t :margin 0 :face 'org-date))))
          (,(format "\\[%s \\(%s\\]\\)" date-re day-time-re) .
           ((lambda (tag)
              (svg-tag-make tag :end -1 :inverse t :crop-left t :margin 0 :face 'org-date))))

          ;; TODO-list
          ("\\[ \\]" . ((lambda (_tag) (mk/svg-checkbox-empty))
                        (lambda () (interactive) (mk/svg-checkbox-toggle))
                        "Click to toggle."
                        ))
          ("\\(\\[[Xx]\\]\\)" . ((lambda (_tag) (mk/svg-checkbox-filled))
                                 (lambda () (interactive) (mk/svg-checkbox-toggle))
                                 "Click to toggle."))
          ))
  )
    ;;; Org Style
;; from https://www.lijigang.com/blog/2018/08/08/神器-org-mode/#org4288876
(setq org-startup-indented t)
(use-package org-superstar
  :defer t
  :disabled t  ; disable for now
  :after (org)
  :hook (org-mode . org-superstar-mode)
  :config
  ;; Stop cycling bullets to emphasize hierarchy of headlines.
  (setq org-superstar-cycle-headline-bullets nil)
  ;; Hide away leading stars on terminal.
  (setq org-superstar-leading-fallback ?\s)
  (setq org-indent-mode-turns-on-hiding-stars nil)
  (setq org-hide-leading-stars t)
  (setq org-superstar-item-bullet-alist
        '((?* . ?⌬) ; * ; previously used: 8226
          (?+ . ?⋇) ; + ; previously used: 10210
          (?- . ?▪))) ; - ; previously used: 8211
  ;; ●◆◼►▸▮▪■⚈⚉⌫⌦☑ ◉◈○▷①②③④⑤⑥⑦⑧⑨⎋〄


  (setq org-superstar-headline-bullets-list
        '(9673 9675 ?◇ 10047 10040))
  )


(use-package org-bars
  :straight (:host github :repo "tonyaldon/org-bars")
  :defer t
  :after (org)
  :config
  (setq org-bars-with-dynamic-stars-p nil)
  )
;; agenda 里面时间块彩色显示
;; From: https://emacs-china.org/t/org-agenda/8679/3
(defun ljg/org-agenda-time-grid-spacing ()
  "Set different line spacing w.r.t. time duration."
  (save-excursion
    (let* ((background (alist-get 'background-mode (frame-parameters)))
           (background-dark-p (string= background "dark"))
           (colors (list "#1ABC9C" "#2ECC71" "#3498DB" "#9966ff"))
           pos
           duration)
      (nconc colors colors)
      (goto-char (point-min))
      (while (setq pos (next-single-property-change (point) 'duration))
        (goto-char pos)
        (when (and (not (equal pos (point-at-eol)))
                   (setq duration (org-get-at-bol 'duration)))
          (let ((line-height (if (< duration 30) 1.0 (+ 0.5 (/ duration 60))))
                (ov (make-overlay (point-at-bol) (1+ (point-at-eol)))))
            (overlay-put ov 'face `(:background ,(car colors)
                                                :foreground
                                                ,(if background-dark-p "black" "white")))
            (setq colors (cdr colors))
            (overlay-put ov 'line-height line-height)
            (overlay-put ov 'line-spacing (1- line-height))))))))
(add-hook 'org-agenda-finalize-hook #'ljg/org-agenda-time-grid-spacing)
;;; Paste Image From https://emacs-china.org/t/topic/6601/4
(defun org-insert-image ()
  "Insert a image from clipboard."
  (interactive)
  (let* ((path (concat default-directory
                       (buffer-name)
                       ".assets/"))
         (image-file (concat
                      path
                      (buffer-name)
                      (format-time-string "_%Y%m%d_%H%M%S.png"))))
    (if (not (file-exists-p path))
        (mkdir path))
    (do-applescript (concat
                     "set the_path to \"" image-file "\" \n"
                     "set png_data to the clipboard as «class PNGf» \n"
                     "set the_file to open for access (POSIX file the_path as string) with write permission \n"
                     "write png_data to the_file \n"
                     "close access the_file"))
    ;; (shell-command (concat "pngpaste " image-file))
    (org-insert-link nil
                     (concat "file:" image-file)
                     "")
    (message image-file))
  (org-display-inline-images)
  )
apptMELPA, Appointment package
(use-package ox-html
  :straight nil
  :after (org)
  :defer t
  :config
  ;; Org export code style
  (setq org-html-htmlize-output-type 'css)
  (setq-default org-html-doctype "html5")
  (setq-default org-html-html5-fancy t)
  )

Calender sync

(use-package ox-icalendar
  :defer t
  :straight nil
  :after (org)
  :config
  (setq org-icalendar-alarm-time 5)
  (setq org-icalendar-combined-agenda-file "~/Dropbox/Dreams/Org/org.ics"
        org-icalendar-include-todo 'all
        org-icalendar-store-UID t
        org-icalendar-timezone ""
        org-icalendar-use-deadline
        '(event-if-not-todo event-if-todo event-if-todo-not-done todo-due)
        org-icalendar-use-scheduled
        '(event-if-not-todo event-if-todo event-if-todo-not-done todo-start))
  )
(use-package org-caldav
  :defer t
  ;; :after (async)
  :init
  (require 'async)
  ;; (setq org-caldav-url "https://dong.mk/radicale/mkvoya/")
  (setq org-caldav-url "https://mail.sjtu.edu.cn/dav/mingkaidong@sjtu.edu.cn/")
  (setq org-caldav-calendars
        '(
          (:calendar-id "9d6f9f39-cba5-fe5b-bd49-c61168d64f81"
                        :inbox "~/Dropbox/Dreams/Org/Caldav.inbox.org"
                        :files ("~/Dropbox/Dreams/Org/Main.org"
                                "~/Dropbox/Dreams/Org/Inbox.org"
                                )
                        :type-regex "VEVENT")
          (:calendar-id "e08e1f91-e359-0e59-3a72-b8b0ea70a783"
                        :inbox "~/Dropbox/Dreams/Org/Caldav.inbox.org"
                        :files (
                                ;; "~/Dropbox/Dreams/Org/Main.org"
                                ;; "~/Dropbox/Dreams/Org/Inbox.org"
                                "~/Dropbox/Dreams/Org/Ebib-ReadingList.org"
                                )
                        :type-regex "VTODO")
          ))
  ;; (setq org-caldav-calendar-id "f846603c-c54c-c73f-f009-e7331ef16216")
  ;; (setq org-caldav-inbox "~/Dropbox/Dreams/Org/Caldav.inbox.org")
  ;; (setq org-caldav-files '("~/Dropbox/Dreams/Org/Main.org"
  ;;                          "~/Dropbox/Dreams/Org/Inbox.org"
  ;;                          ))
  ;; (setq org-icalendar-timezone "America/Los_Angeles")
  (setq org-icalendar-timezone "Asia/Shanghai")
  )

OrgRoam

org-roam
org-roam-ui
org-roam-server(use org-roam-ui)
org-mindmapcreates graphviz directed graphs from headings of an org file

Org-transclusion

Modes to embed one buffer in another buffer and keep them in sync

Freexhttps://github.com/gregdetre/emacs-freex
transclusion-minor-modehttp://github.com/whacked/transclusion-minor-mode
(use-package org-transclusion
  :defer t
  :after org
  :config
  (set-face-attribute
   'org-transclusion-fringe nil
   :foreground "lightgrey"
   :background "lightgreen")
  (set-face-attribute
   'org-transclusion-source-fringe nil
   :foreground "lightblue"
   :background "blue")
  )
;; :bind (("<f12>" . #'org-transclusion-add))
;; ("C-n t" . #'org-transclusion-mode)

NotDeft

(use-package notdeft
  :if mk-feature/noteman
  :defer t
  :straight (:host github :repo "hasu/notdeft" :files ("*.el" "xapian"))
  :config
  (setq notdeft-directories '("~/Dropbox/Dreams" "~/Dropbox/IPADS"))
  (setq notdeft-extension "org")
  (setq notdeft-secondary-extensions '("md" "txt" "scrbl"))
  (setq notdeft-allow-org-property-drawers t)
  )

Denote

(use-package websocket :defer t)
(use-package simple-httpd :defer t)
(use-package denote
  :if mk-feature/noteman
  :straight (:type git :host github :repo "protesilaos/denote")
  :config
  ;; Remember to check the doc strings of those variables.
  (setq denote-directory (expand-file-name "~/Dropbox/Dreams/Org/"))
  (setq denote-known-keywords '("emacs" "philosophy" "research" "economics"))
  (setq denote-infer-keywords t)
  (setq denote-sort-keywords t)
  (setq denote-file-type nil) ; Org is the default, set others here
  (setq denote-prompts '(title keywords))
  (setq denote-excluded-directories-regexp nil)
  (setq denote-date-prompt-use-org-read-date t) ; Pick dates, where relevant, with Org's advanced interface
  (setq denote-allow-multi-word-keywords t) ; Allow multi-word keywords
  (setq denote-date-format nil) ; read doc string

  ;; By default, we do not show the context of links.  We just display
  ;; file names.  This provides a more informative view.
  (setq denote-backlinks-show-context t)
  ;; We use different ways to specify a path for demo purposes.
  (setq denote-dired-directories
        (list denote-directory
              (thread-last denote-directory (expand-file-name "attachments"))
              (expand-file-name "~/Documents/books")))
  (add-hook 'dired-mode-hook #'denote-dired-mode-in-directories)
  ;; Here is a custom, user-level command from one of the examples we
  ;; showed in this manual.  We define it here and add it to a key binding
  ;; below.
  (defun my-denote-journal ()
    "Create an entry tagged 'journal', while prompting for a title."
    (interactive)
    (denote
     (denote--title-prompt)
     '("journal")))
  )
(use-package org-capture
  :if mk-feature/noteman
  :straight nil
  :after (denote)
  :config
  (setq denote-org-capture-specifiers "%l\n%i\n%?")
  (defvar mk/org-capture-people-path)
  (defun mk/org-capture-people ()
    (interactive)
    (format "* %s\n%%?" (read-string "姓名: " nil))
    )

  (setq org-capture-templates
        '(("n" "New DeNote" plain (file denote-last-path)
           #'denote-org-capture
           :no-save t
           :immediate-finish nil
           :kill-buffer t
           :jump-to-captured t)
          ("p" "New People" entry (file+headline "~/Dropbox/Dreams/Org/People/General.org" "People")
           #'mk/org-capture-people
           )))
  )
(use-package consult-notes
  :straight (:type git :host github :repo "mclear-tools/consult-notes")
  :commands (consult-notes
             consult-notes-search-in-all-notes)
  :bind ("C-c d f" . consult-notes)
  :config
  (setq consult-notes-sources
        '(("denote"          ?d "~/Dropbox/Dreams/Org")
          ))
  )

Bibliography

;; Common
(setq mk/bib-main-file "~/Dropbox/Dreams/Research/Papers/Papers.bib")
(setq mk/bib-pdf-dir "~/Dropbox/Dreams/Research/Papers/")

(setq reftex-default-bibliography `("paper.bib" "references.bib" ,mk/bib-main-file))

Bibtex

(use-package bibtex
  :if mk-feature/bibliography
  :straight nil  ; built in
  :defer
  :init
  (setq bibtex-dialect 'biblatex)
  ;; Bibtex autokey is used by Ebib.
  (setq bibtex-autokey-year-length 4  ; Full year format
        bibtex-autokey-name-year-separator "-"
        bibtex-autokey-year-title-separator "-"
        bibtex-autokey-titleword-separator "-"
        bibtex-autokey-titlewords 2  ; Use two words from the title
        bibtex-autokey-titlewords-stretch 0
        bibtex-autokey-titleword-length nil  ; Use whole word
        )
  (setq bibtex-autokey-titleword-ignore
        '("A" "An" "On" "The" "Eine?" "Der" "Die" "Das"
          "The" "on"
          "a" "an"
          "and" "the" "of" ".*[^[:upper:][:lower:]0-9].*"))

  (setq bibtex-completion-bibliography `(,mk/bib-main-file)
        bibtex-completion-library-path nil  ; TODO
        bibtex-completion-notes-path nil)  ; TODO
  (setq bibtex-completion-notes-template-multiple-files
        "* ${author-or-editor}, ${title}, ${journal}, (${year}) :${=type=}: \n\nSee [[cite:&${=key=}]]\n"
        bibtex-completion-additional-search-fields '(keywords)
        bibtex-completion-display-formats
        '((article       . "${=has-pdf=:1}${=has-note=:1} ${year:4} ${author:36} ${title:*} ${journal:40}")
          (inbook        . "${=has-pdf=:1}${=has-note=:1} ${year:4} ${author:36} ${title:*} Chapter ${chapter:32}")
          (incollection  . "${=has-pdf=:1}${=has-note=:1} ${year:4} ${author:36} ${title:*} ${booktitle:40}")
          (inproceedings . "${=has-pdf=:1}${=has-note=:1} ${year:4} ${author:36} ${title:*} ${booktitle:40}")
          (t             . "${=has-pdf=:1}${=has-note=:1} ${year:4} ${author:36} ${title:*}")))
  (setq bibtex-completion-pdf-open-function
        (lambda (fpath) (call-process "open" nil 0 nil fpath)))
  :config
  (use-package bibtex-completion
    :defer
    :config
    (bibtex-completion-init)  ; This will set the XXX-format-internal variable
    )
  )

Citar

Org-refhttps://github.com/jkitchin/org-ref
Citarhttps://github.com/bdarcus/citarAlternative to org-ref
;; citar
(use-package citar
  :if mk-feature/bibliography
  :straight (:host github :repo "bdarcus/citar")
  :defer
  :demand
  :bind (("C-c b" . citar-insert-citation)
         :map minibuffer-local-map
         ("M-b" . citar-insert-preset))
  :init
  (setq citar-notes-paths '("~/Dropbox/Dreams/Org/PaperNotes"))
  (setq org-cite-global-bibliography `(,(expand-file-name mk/bib-main-file)))
  (setq org-cite-insert-processor 'citar)
  (setq org-cite-follow-processor 'citar)
  (setq org-cite-activate-processor 'citar)
  (setq citar-bibliography org-cite-global-bibliography)
  (setq citar-symbols
        `((file ,(all-the-icons-faicon "file-o" :face 'all-the-icons-green :v-adjust -0.1) . " ")
          (note ,(all-the-icons-material "speaker_notes" :face 'all-the-icons-blue :v-adjust -0.3) . " ")
          (link ,(all-the-icons-octicon "link" :face 'all-the-icons-orange :v-adjust 0.01) . " ")))
  (setq citar-symbol-separator "  ")
  ;; (require 'embark)
  ;; (setq citar-at-point-function 'embark-act)
  ;; (use-package citar-embark
  ;;   :after citar embark
  ;;   :no-require
  ;;   :config (citar-embark-mode))
  :config
  (use-package org-roam-bibtex
    :defer
    :after org-roam
    :config
    (setq orb-roam-ref-format 'org-cite)
    (setq orb-use-bibdesk-attachments 't)
    )
  (require 'org-roam-bibtex)
  (setq citar-open-note-function #'(lambda (key entry) (orb-edit-note key)))
  ;; (citar-filenotify-setup '(LaTeX-mode-hook org-mode-hook))
  )

Biblio

bibliohttps://github.com/cpitclaudel/biblio.elLookup & import bib
(use-package biblio
  :if mk-feature/bibliography
  :defer
  :init

  (setq biblio-arxiv-bibtex-header "misc")
  (setq biblio-bibtex-use-autokey nil)  ; Don't use autokey of biblio

  ;; Some backends fail upon async queries.
  (setq biblio-synchronous t)

  :config

  ;; Override
  (defun biblio--completing-read-function ()
    "Override to always return the defualt one"
    completing-read-function)

  ;; Override to add url
  (defun biblio-arxiv--build-bibtex-1 (metadata)
    "Create an unformated BibTeX record for METADATA."
    (let-alist metadata
      (format "@%s{NO_KEY,
author = {%s},
title = {{%s}},
year = {%s},
url = {%s},
series = {arXiv %s},
archivePrefix = {arXiv},
eprint = {%s},
primaryClass = {%s}}"
              biblio-arxiv-bibtex-header
              (biblio-join-1 " AND " .authors)
              .title .year .url .year .identifier .category)))
  )

Ebib

Ebibhttps://github.com/joostkremers/ebibBib Manager
(use-package ebib
  :if mk-feature/bibliography
  :defer
  ;; :after (biblio bibtex citar)
  :init
  (require 'biblio)
  (require 'bibtex)
  (require 'citar)
  (require 'dbus)  ; A function from dbus is used in ebib.
  (defun mk/ebib-create-org-schedule (_key _db)
    (format "SCHEDULED: <%s>" (org-read-date nil nil "+1d"))
    )
  (setq ebib-reading-list-template-specifiers '((?K . ebib-reading-list-create-org-identifier)
                                                (?T . ebib-create-org-title)
                                                (?M . ebib-reading-list-todo-marker)
                                                (?L . ebib-create-org-link)
                                                (?F . ebib-create-org-file-link)
                                                (?D . ebib-create-org-doi-link)
                                                (?U . ebib-create-org-url-link)
                                                (?S . mk/ebib-create-org-schedule)))
  (setq ebib-reading-list-template "* %M %T\n%S\n:PROPERTIES:\n%K\n:END:\n%F\n")
  (setq ebib-autogenerate-keys t)  ; Use bibtex autokey.
  (setq ebib-uniquify-keys t)
  (setq ebib-bibtex-dialect 'biblatex)  ; biblatex is better than xxx.
  (setq ebib-index-window-size 10)
  (setq ebib-preload-bib-files `(,mk/bib-main-file))
  (setq ebib-file-search-dirs `(,mk/bib-pdf-dir))
  (setq ebib-notes-storage 'one-file-per-note)
  (setq ebib-reading-list-file "~/Dropbox/Dreams/Org/Ebib-ReadingList.org")
  (setq ebib-notes-directory "~/Dropbox/Dreams/Org/PaperNotes/")
  (setq ebib-notes-locations `(,ebib-notes-directory))
  ;; ebib-keywords-file "~/Dropbox/Bibliography/ebib-keywords.txt"
  (setq ebib-keywords-field-keep-sorted t)
  (setq ebib-keywords-file-save-on-exit 'always)
  ;; ebib-file-associations '(("pdf")) "using Emacs to open pdf"
  (setq ebib-use-timestamp t)  ; recording the time that entries are added
  (setq ebib-index-columns '(("Year" 4 t)
                             ("Entry Key" 30 t)
                             ("Title" 50 t)
                             ("Series/Journal" 20 t)
                             ("Author/Editor" 40 nil)))
  (setq ebib-index-default-sort '("timestamp" . descend))

  (defun mk/ebib-display-series-or-journal (field key db)
    "Return series/journal FIELD content from KEY and DB."
    (or (ebib-get-field-value "Series" key db 'noerror 'unbraced 'xref)
        (ebib-get-field-value "Journal" key db "(No Series/Journal)" 'unbraced 'xref))
    )
  (setq ebib-field-transformation-functions
        '(("Title" . ebib-clean-TeX-markup-from-entry)
          ("Doi" . ebib-display-www-link)
          ("Url" . ebib-display-www-link)
          ("Note" . ebib-notes-display-note-symbol)
          ("Series/Journal" . mk/ebib-display-series-or-journal)
          ))
  :config
  (setq ebib-index-mode-line '("%e"
                               mode-line-front-space
                               ebib--mode-line-modified
                               mode-line-buffer-identification
                               (:eval (if (and ebib--cur-db (ebib-db-dependent-p ebib--cur-db))
                                          (format " [%s]" (ebib-db-get-filename (ebib-db-get-main ebib--cur-db) t))))
                               (:eval (format "  (%s)" (ebib--get-dialect ebib--cur-db)))
                               (:eval (if (and ebib--cur-db (ebib--get-key-at-point))
                                          (format "     Entry %d/%d" (line-number-at-pos) (count-lines (point-min) (point-max)))
                                        "     No Entries"))
                               (:eval (if (and ebib--cur-db (ebib-db-get-filter ebib--cur-db))
                                          (format "  |%s|" (ebib--filters-pp-filter (ebib-db-get-filter ebib--cur-db)))
                                        ""))))
  (defun mk/ebib--clean-string (str)
    "Clean the format of STR."
    (or (substring-no-properties (remove ?\n (format "%s" str))) ""))
  (defun mk/ebib--clean-field (key db field)
    "Clean the format of FIELD of KEY in DB."
    (mk/ebib--clean-string (ebib-get-field-value field key db 'noerror 'unbraced 'xref)))

  (defun mk/read-file-content (filename)
    "Read the file content of FILENAME."
    (with-temp-buffer
      (insert-file-contents filename)
      (buffer-string)))
  (defun mk/ebib-complete-rest-note-content (key db)
    "Gerneate the rest content of the note template accroding to KEY in DB."
    (let ((template (mk/read-file-content "~/.emacs.d/snippets/ebib/ebib-notes-template.org"))
          (title (mk/ebib--clean-field key db "title"))
          (date (format-time-string "%FT%T%z"))
          (authors (mk/ebib--clean-field key db "author"))
          (series (mk/ebib--clean-field key db "series")))
      (setq template (string-replace "${citekey}" key template))
      (setq template (string-replace "${orgid}" (org-id-new) template))
      (setq template (string-replace "${title}" title template))
      (setq template (string-replace "${date}" date template))
      (setq template (string-replace "${authors}" authors template))
      (setq template (string-replace "${series}" series template))
      template))
  (setq ebib-notes-template-specifiers '((?K . ebib-create-org-identifier)
                                         (?T . ebib-create-org-description)
                                         (?X . ebib-create-org-title)
                                         (?C . ebib-create-org-cite)
                                         (?L . ebib-create-org-link)
                                         (?F . ebib-create-org-file-link)
                                         (?D . ebib-create-org-doi-link)
                                         (?U . ebib-create-org-url-link)
                                         (?P . mk/ebib-complete-rest-note-content)))
  (setq ebib-notes-template "%%?%P\n")

  )

(defun mk/ebib-reading-list-show-entry ()
  "Jump to the ebib entry from the current reading list item."
  (interactive)
  (let ((custom-id (org-entry-get (point) "Custom_id")))
    (when (string-prefix-p "reading_" custom-id)
      (let ((ebib-key (substring custom-id 8)))
        (message "Jumping to ebib entry with key: %s" ebib-key)
        (ebib nil ebib-key)
        ))))

(use-package ebib-biblio
  :if mk-feature/bibliography
  :after (ebib biblio)
  :straight nil
  :demand
  :bind (:map biblio-selection-mode-map
              ("e" . ebib-biblio-selection-import)))

Paper and Research

(use-package emacs
  :if mk-feature/bibliography
  :after (ebib)
  :init
  ;; My source code for bib
  (setq paper-root-dir (expand-file-name "~/Dropbox/Dreams/Research/Papers"))
  (defun mk/normalize-paper-title (title)
    "Remove bad chars in the paper TITLE."
    (replace-regexp-in-string
     "[\s\n]+" " " (replace-regexp-in-string
                    "/" "" (replace-regexp-in-string
                            ":" "," title)))
    )

  (defun paper-root()
    "Open the paper root."
    (interactive)
    (find-file paper-root-dir))

  (defun paper-find (&optional initial)
    "Search a paper in your Dreamland, by title, with INITIAL input."
    (interactive "P")
    (let ((consult-find-args (concat
                              (expand-file-name "~/.emacs.d/bin/paperfind.sh")
                              " "
                              paper-root-dir)))
      (find-file (concat (file-name-as-directory paper-root-dir)
                         (consult--find "Dreamland's Paper Find: "
                                        #'consult--find-builder initial)))))

  (defun paper-open ()
    "Open the file in PDF Expert. Code borrowed from the crux package."
    (interactive)
    (let ((current-file-name
           (if (eq major-mode 'dired-mode)
               (dired-get-file-for-visit)
             buffer-file-name)))
      (call-process "open" nil 0 nil "-a" "/Applications/PDF Expert.app" current-file-name))
    )

  ;; Automatically choose the file to link with according to the selected text.
  (defvar autolink-directory "~/Dropbox/Dreams")
  (defun autolink--get-candidates (text)
    "Search for the file name with TEXT."
    (let* ((cmd (concat "find " autolink-directory " -iname \"*" (string-replace ":" "?" text) "*\""))
           (candidates (mapcar 'abbreviate-file-name (delete "" (split-string (shell-command-to-string cmd) "\n")))))
      (completing-read "Choose the one to link: " candidates)))
  (defun paper-link (start end)
    "Try to guess the file to link according to the region between START and END."
    (interactive "r") ; The "r" here will fill the start and end automatically.
    (let* ((text (buffer-substring start end))
           (file (autolink--get-candidates text)))
      (goto-char end)
      (insert "]]")
      (goto-char start)
      (insert (concat "[[" file "]["))))

  (setq mk/ebib-dir-root "~/Dropbox/Dreams/Research/Papers")

  (defun mk/ebib--format-full-dir (dir title)
    "Get the full dir name from DIR and TITLE."
    (format "%s/%s/%s" mk/ebib-dir-root dir title))

  (defun mk/ebib-get-series-dirname-candidate (title series journal year publisher)
    "Form the name of given TITLE, SERIES, JOURNAL, YEAR, PUBLISHER"
    (cond
     ;; Use series if set
     ((not (string= series "no-series")) (string-replace " " "." (string-replace " '" "" series)))
     ;; Hard coded
     ((string= journal "scientific reports") (format "nat.sci.rep.%s" year))
     ((string= journal "commun. acm") (format "commun.acm.%s" year))
     ((string= journal "nature communications") (format "nat.comm.%s" year))
     ((string= journal "acs nano") (format "acs.nano.%s" year))
     ((string= journal "bmc bioinformatics") (format "bioinfo.%s" year))
     ((string= journal "ieee transactions on computer-aided design of integrated circuits and systems") (format "tcad.%s" year))
     ((string= journal "ieee transactions on parallel and distributed systems") (format "tpds.%s" year))
     ((string= journal "ieee transactions on computers") (format "tc.%s" year))
     ((string= journal "briefings in bioinformatics") (format "bib.%s" year))
     ((string= journal "acs synthetic biology") (format "acs.syn.bio.%s" year))

     ;; arXiv
     ((string= publisher "arxiv") (format "arxiv%s" year))
     (t "XXXX")))

  (defun mk/ebib-get-dir (title series journal year publisher)
    "Calculate the directory for TITLE and SERIES and JOURNAL and PUBLISHER."
    (let* ((series-dir (mk/ebib-get-series-dirname-candidate title series journal year publisher))
           (fulldir (mk/ebib--format-full-dir series-dir title)))
      (if (file-exists-p fulldir) fulldir nil)
      ))

  (defun mk/ebib-open-dir (key)
    "Open the directory for KEY."
    (interactive (list (ebib--get-key-at-point)))
    (ebib--execute-when
      (entries
       (let* ((title (mk/normalize-paper-title (ebib-get-field-value "title" key ebib--cur-db nil t)))
              (series (downcase (ebib-get-field-value "series" key ebib--cur-db "no-series" t)))
              (publisher (downcase (ebib-get-field-value "publisher" key ebib--cur-db "no-publisher" t)))
              (journal (downcase (ebib-get-field-value "journal" key ebib--cur-db "no-journal" t)))
              (year (ebib-get-field-value "year" key ebib--cur-db "0000" t))
              (series-dirname (mk/ebib-get-series-dirname-candidate title series journal year publisher))
              (cand (mk/ebib-get-dir title series journal year publisher)))
         (if cand (find-file cand)
           (print "No such dir, creating with prompt...")
           (let* ((conf (string-trim (read-string "The conf abbr: " series-dirname)))
                  (target (format "%s/%s/%s" mk/ebib-dir-root conf title)))
             (make-directory target t)
             (find-file target)
             ))))
      (default
       (beep))))

  (define-key ebib-index-mode-map (kbd "O") #'mk/ebib-open-dir)

  (defun mk/paper-get-dirs ()
    "Get all conf dirs."
    (let* ((cmd (format "find %s -type d -maxdepth 1 -exec realpath --relative-to %s {} \\;" mk/ebib-dir-root mk/ebib-dir-root))
           (candidates (mapcar 'abbreviate-file-name (delete "" (split-string (shell-command-to-string cmd) "\n"))))
           (choice (completing-read "Choose the one to link: " candidates)))
      (print choice)
      ))

  (defun mk/ebib-open-file (key)
    "Open files for KEY."
    (interactive (list (ebib--get-key-at-point)))
    (ebib--execute-when
      (entries
       (let* ((title (mk/normalize-paper-title (ebib-get-field-value "title" key ebib--cur-db nil t)))
              (cmd (format "find %s -type d -iname \"%s\"" mk/ebib-dir-root title))
              (candidates (mapcar 'abbreviate-file-name (delete "" (split-string (shell-command-to-string cmd) "\n"))))
              (cand (cond
                     ((= 0 (length candidates)) nil)
                     ((= 1 (length candidates)) (car candidates))
                     (t (completing-read "Choose the one to link: " candidates)))))
         (if cand (find-file cand)
           ())))
      (default
       (beep))))
  )

MISC

(use-package image-click-mode
  :if mk-feature/gui
  :delight
  :ensure t
  :after (org)
  :straight (:host github :repo "mkvoya/image-click-mode" :files ("*.el"))
  :config
  (setq org-image-actual-width 400)
  (add-hook 'org-mode-hook (lambda () (image-click-mode))))

Popweb

(use-package popweb
  :if mk-feature/gui
  :defer t
  :disabled t
  :straight (:type git :host github :repo "manateelazycat/popweb" :files ("*"))
  :config
  (setq popweb-root (file-name-directory (locate-library "popweb.el")))
  (add-to-list 'load-path (concat popweb-root "extension/latex"))
  (require 'popweb-latex)
  (add-to-list 'load-path (concat popweb-root "extension/dict"))
  (require 'popweb-dict-bing)
  (require 'popweb-dict-youdao)
  )

vterm

(use-package vterm
  :defer t
  :config
  (defun vterm-new()
    "Add a new vterm session with given name."
    (interactive)
    (let ((session-name (string-trim (read-string "Enter the name for the session: "))))
      (vterm session-name)
      )
    )
  )
(use-package highlight-indent-guides :defer t)
(use-package hl-line
  :config
  (set-face-background 'hl-line "#d0fed0")
  (set-face-foreground 'hl-line nil)
  (set-face-foreground 'highlight nil)
  ;; (global-hl-line-mode t)
  )
(use-package gitlab-ci-mode :defer t)
(use-package dockerfile-mode :mode "Dockerfile" :defer t)
(use-package imenu-list
  :after (org)
  :demand
  :bind (("C-\"" . #'imenu-list-smart-toggle))
  :config
  (setq imenu-list-auto-resize nil)
  (setq imenu-list-position 'left)
  (setq org-imenu-depth 5)
  )
(use-package org-sidebar :defer t)

Custom functions

Interactive Utilities

(defun mk/insert-datetime()
  "Insert the current date and time."
  (interactive)
  (insert (format-time-string "%F %T")))
;; From https://emacs.stackexchange.com/questions/47627/identify-buffer-by-part-of-its-name
(defun switch-to-existing-buffer-other-window (part)
  "Switch to buffer with PART in its name."
  (interactive
   (list (read-buffer-to-switch "Switch to buffer in other window: ")))
  (let ((candidates
         (cl-remove
          nil
          (mapcar (lambda (buf)
                    (let ((pos (string-match part (buffer-name buf))))
                      (when pos
                        (cons pos buf))))
                  (buffer-list)))))
    (unless candidates
      (user-error "There is no buffers with %S in its name." part))
    (setq candidates (cl-sort candidates #'< :key 'car))
    (switch-to-buffer-other-window (cdr (car candidates)))))

(defun mk/open-orgroam-panel()
  "Open the Org-roam client at [http://127.0.0.1:35901]."
  (interactive)
  ;; Ensure the server is running.
  (unless org-roam-ui-mode (org-roam-ui-mode))
  ;; Ensure the session is running.
  (xwidget-webkit-browse-url "http://127.0.0.1:35901" nil)
  ;; Switch to the buffer
  (switch-to-existing-buffer-other-window "Roam Server")
  )
(defun mk/webkit-new-url (url &optional new-session)
  "Create a new session to browse the URL."
  (interactive (progn
                 (require 'browse-url)
                 (browse-url-interactive-arg "xwidget-webkit URL: ")))
  (xwidget-webkit-browse-url url t)
  )

Notionify

(defun mk/notionify-turn-to-page (@begin @end)
  "Turn the selected text to a page link. If the function is called in the page =file.org=, a directory called =file.org.dir= will be auto created if not exists. A new file will be created with the name of selected text + '.org' (@BEGIN -to- @END .org) suffix. This mimics the action of turning the selected line into a new page in Notion.so, while this function is better since the page does not need to be a single line. The text will be turned into a hyperlink to the new file."
  (interactive
   (if (use-region-p)
       (list (region-beginning) (region-end))
     (list (line-beginning-position) (line-end-position))))
  (save-excursion
    (save-restriction
      (narrow-to-region @begin @end)
      (let (($dir (concat (string-trim-right (buffer-name) ".dir"))
                  ($subpage (buffer-substring-no-properties (point-min) (point-max))))
            (make-directory $dir t)
            (goto-char (point-min))
            (insert (concat "[[file:./" $dir "/" $subpage) ".org][")
            (goto-char (point-max))
            (insert "]]")))
      )))

Launcher

(defun is-floating-frame(f)
  (equal (frame-parameter f 'name) "*Floating*")
  )
(defun get-floating-frame()
  (car (filtered-frame-list #'is-floating-frame)))

(defun toggle-floating-frame ()
  "Make/Delete a frame that is floating."
  (interactive)
  ;; ((w (display-pixel-width))
  ;; (h (/ (display-pixel-height) 2)))
  (let* ((geo (cdr (assq 'geometry (car (display-monitor-attributes-list)))))
         (x (nth 0 geo))
         (y (nth 1 geo))
         (w (nth 2 geo))
         (h (nth 3 geo))
         (f (get-floating-frame)))
    (if f
        (progn
          ;; (keyboard-quit)
          ;; (make-frame-invisible f)
          (delete-frame)
          )
      (progn
        (setq f (make-frame '((undecorated . 1)
                              (name . "*Floating*"))))  ; TODO: do not make-frame every time.
        (set-frame-position f 0 0)
        (set-frame-size f w (/ h 2) t)
        (make-frame-visible f)
        (select-frame f)
        (select-frame-set-input-focus f)
        (switch-to-buffer "*scratch*")
        ;; (call-interactively (global-key-binding "\M-x"))
        ))))

(use-package popwin
  :disabled t
  :config
  (popwin-mode 1)
  )

Custom key-bindings

;; from https://stackoverflow.com/questions/1250846/wrong-type-argument-commandp-error-when-binding-a-lambda-to-a-key
(global-set-key (kbd "C-h c") #'describe-char)
(global-set-key (kbd "C-c h") (lambda () (interactive) (find-file "~/Dropbox/Dreams/Org/Main.org")))
(global-set-key (kbd "C-c r") (lambda () (interactive) (find-file "~/.emacs.d/emacs-config.org")))
(global-set-key (kbd "C-c p") (lambda () (interactive) (find-file "~/Dropbox/Dreams/Org/Projects.org")))
(global-set-key (kbd "M-s-<left>") 'tab-previous)
(global-set-key (kbd "M-s-<right>") 'tab-next)
(global-set-key (kbd "M-s-n") 'tab-new)
(global-set-key (kbd "C-c w") (lambda () (interactive) (find-file "~/Dropbox/Dreams/Org/Weights.org")))
;; Open ibuffer upon "C-c i"
(global-set-key (kbd "C-c i") 'ibuffer)
;; (global-set-key (kbd "C-c C-m e") (lambda () (interactive) (find-file "~/.emacs.d/emacs-config.org")))
;; (global-unset-key [mouse-3])
;; (global-set-key [down-mouse-3]
;;                 `(menu-item ,(purecopy "Menu Bar") ignore
;;                             :filter (lambda (_)
;;                                       (if (zerop (or (frame-parameter nil 'menu-bar-lines) 0))
;;                                           (mouse-menu-bar-map)
;;                                         (mouse-menu-major-mode-map)))))

Publish & Blog

Org-based Blog

(use-package org-static-blog
  :defer t
  :init
  (use-package htmlize)
  :config

  (setq org-static-blog-publish-title "Mika.blog")
  (setq org-static-blog-publish-url "https://blog.dong.mk/")
  (setq org-static-blog-publish-directory "~/Dropbox/Dreams/Org/Blog/Publish/")
  (setq org-static-blog-posts-directory "~/Dropbox/Dreams/Org/Blog/Posts/")
  (setq org-static-blog-drafts-directory "~/Dropbox/Dreams/Org/Blog/Drafts/")
  (setq org-static-blog-use-preview t)  ; enable preview

  ;; Use “#+filetags: τ₁ τ₂ … τₙ”
  (setq org-static-blog-enable-tags t)

  ;; I'd like to have tocs and numbered headings
  (setq org-export-with-toc t)
  (setq org-export-with-section-numbers t)

  (setq org-static-blog-page-header
        "<meta name=\"author\" content=\"Mingkai Dong\">
                <meta name=\"referrer\" content=\"no-referrer\">
                <link href= \"static/style.css\" rel=\"stylesheet\" type=\"text/css\" />
                <link rel=\"icon\" href=\"static/favicon.ico\">")

  (setq org-static-blog-page-preamble "")
  ;;  ("<div class=\"header\">
  ;;       <a href=\"https://blog.dong.mk\">Mika, Mika, Mika.</a>
  ;;     </div>")

  (setq org-static-blog-page-postamble "")
  ;; (setq org-static-blog-page-postamble
  ;;       "<div id=\"archive\">
  ;;       <a href=\"https://blog.dong.mk/archive.html\">Other posts</a>
  ;;     </div>
  ;;     <center></center>")

  (setq org-static-blog-index-front-matter "")
        ;; "<h1> Hey it is </h1>\n"
  )

Org Publish

Do we still use this?

(use-package ox-publish
  :defer t
  :straight nil
  :after (org)
  :config
  (setq org-publish-project-alist
        '(
          ("org-notes"
           :base-directory "~/Dropbox/Dreams/Org/Public"
           :base-extension "org"
           :publishing-directory "/Volumes/ramfs/public_html/"
           :recursive t
           :publishing-function org-html-publish-to-html
           :headline-levels 4             ; Just the default for this project.
           :auto-preamble t
           )
          ("org-static"
           :base-directory "~/Dropbox/Dreams/Org/Public"
           :base-extension "css\\|js\\|png\\|jpg\\|gif\\|pdf\\|mp3\\|ogg\\|swf"
           :publishing-directory "/Volumes/ramfs/public_html/"
           :recursive t
           :publishing-function org-publish-attachment
           )
          ("org" :components ("org-notes" "org-static"))
          )))

Disabled Pool

(use-package maple-explorer :disabled t)
(use-package org-brain :disabled t)
(use-package deft :disabled t)
(use-package zettledeft :disabled t)
(use-package org-real :disabled t) ; https://gitlab.com/tygrdev/org-real
(use-package explain-pause-mode :disabled t)
(use-package keystrokes :disabled t
  :straight (:type git :host gitlab :repo "marcowahl/keystrokes"))
(use-package netease-cloud-music :disabled t
  :straight (:host github :repo "SpringHan/netease-cloud-music.el"))
(use-package peep-dired :disabled t)  ; Preview files in dired, but we use ranger instead.
(use-package ns-auto-titlebar :disabled t)  ; We used a better patch.
(use-package telega :disabled t)  ; Prefer the GUI
(use-package elgantt
  :disabled
  :straight (:type git :host github :repo "legalnonsense/elgantt"))
(use-package paper :disabled t
  :straight (:host github :repo "ymarco/paper-mode" :files("*.el" "*.so")))

Fancy Libraries

Less (if ever) used

(use-package chronos :defer t)
(use-package elquery :defer)
(use-package citeproc :defer)
(use-package lua-mode :defer)
;; (use-package xenops)  ; the package causes highlighting issues for latex
(use-package org-download :defer)
(use-package symbol-overlay :defer)
(use-package read-aloud
  :disabled
  :config
  (setq read-aloud-engine "say"))
(use-package emacs-badge
  :defer t
  :straight (:type git :host github :repo "mkvoya/emacs-badge" :files ("*"))
  )
(use-package elnode
  :defer
  :straight (:type git :host github :repo "jcaw/elnode"))
(use-package multiple-cursors
  :bind (("C-!" . mc/mark-next-like-this)))
(defun mk/ns-get-window-title-and-buffer ()
  (interactive)
  ;; Apple script from the activitywatch project
  (do-applescript "
global frontApp, frontAppName, windowTitle
set windowTitle to \"\"
tell application \"System Events\"
        set frontApp to first application process whose frontmost is true
        set frontAppName to name of frontApp
        tell process frontAppName
                try
                        tell (1st window whose value of attribute \"AXMain\" is true)
                                set windowTitle to value of attribute \"AXTitle\"
                        end tell
                end try
        end tell
end tell
return frontAppName & \"
\" & windowTitle"))
(defun mk/dired-curl ()
  "Get file from url to dired."
  (interactive)
  (when (equal major-mode 'dired-mode)
    (let* ((url (read-string "URL: "))
           (cwd (dired-current-directory))
           (target (concat (file-name-as-directory cwd) (file-name-nondirectory url))))
      (url-copy-file url target)
      )))
(defun mk/frame-pin ()
  "Pin current frame to always-on-top."
  (interactive)
  (modify-frame-parameters
   nil '((z-group . above))))
(defun mk/frame-unpin ()
  "Unpin current frame to always-on-top."
  (interactive)
  (modify-frame-parameters
   nil '((z-group . nil))))


(defun mk/make-pinned-frame ()
  "Make a new pined frame."
  (interactive)
  (make-frame '((undecorated . 1)
                (z-group . above)
                (width . 80)
                (height . 10)
                (user-size . t)
                (left . 1)
                (top . 1)
                (user-position . t)
                (tab-bar-lines . 0)
                (drag-with-header-line . t)
                (drag-with-tab-line . t)
                (drag-with-mode-line . t))))
;; (load-file "~/.emacs.d/site-lisp/wc.el")
(use-package motd
  :if mk-feature/noteman
  :straight nil
  :ensure nil
  :load-path "~/.emacs.d/site-lisp/"
  :config
  (if mk-feature/light
      (progn
        (setq motd-background-color "#EFE0C0")
        (setq motd-border-color "#910471")
        )
    (setq motd-background-color "#204230")
    (setq motd-border-color "#444444")
    )
  (setq motd--git-commit-dir "~/Dropbox/Dreams")
  (motd-start-timer)
  )
(defun mk/--pick-project ()
  "Pick a project to do."
  (seq-random-elt
   (mapcar #'(lambda (h)
               (let* ((headline (plist-get h 'headline))
                      (title (substring-no-properties (car (plist-get headline :title)))))
                 title))
           (org-ql-query
             :select 'element
             :from "~/Dropbox/Dreams/Org/Projects.org"
             :where '(todo "PROJECT")
             :order-by 'deadline))))

(defun mk/pick-project ()
  "Pick a project to do."
  (interactive)
  (message (mk/--pick-project)))
(use-package xcscope)
(setq python-shell-completion-native-disabled-interpreters nil)

Rust

(use-package rustic
  :custom
  (rustic-lsp-setup-p . nil))
;; (use-package ox-pandoc)
(defun mk/dired-open-pdf ()
  "In dired, open the file named on this line."
  (interactive)
  (let* ((file (dired-get-filename nil t)))
    (message "Opening %s..." file)
    (call-process "open" nil 0 nil "-a" "PDF Expert" file)
    (message "Opening %s done" file)))
(use-package diredfl
  :config
  (diredfl-global-mode))
(use-package linux-kernel-coding-style
  :straight (:type git :host github :repo "mkvoya/linux-kernel-coding-style.el")
  )
(use-package tree-sitter
  :init
  (use-package tree-sitter-langs)
  (global-tree-sitter-mode)
  (add-hook 'tree-sitter-after-on-hook #'tree-sitter-hl-mode)
  )
(use-package swift-mode)
(use-package org-timeline
  :after org
  :config
  (add-hook 'org-agenda-finalize-hook 'org-timeline-insert-timeline :append)
  )
(use-package darkroom)

Anki-like

(use-package org-drill
  :disabled t)

(use-package org-anki
  :after (org)
  :config
  ;; Override the cloze function
  ;; The below function does not work since Anki does not show the back of the card for clozes.
  ;; (defun org-anki--region-to-cloze (begin end arg hint)
  ;;   "Cloze region from BEGIN to END with number ARG."
  ;;   (let ((region (buffer-substring begin end)))
  ;;     (save-excursion
  ;;       (delete-region begin end)
  ;;       (insert (with-output-to-string
  ;;                 (princ (format "{{c%d::%s" (or arg 1) region))
  ;;                 (unless (string-blank-p hint) (princ (format "::%s" hint)))
  ;;                 (princ "}}")))
  ;;       (org-end-of-subtree)
  ;;       (insert "\n" region ": " hint)
  ;;       )))
  )
(use-package define-word)
(use-package sdcv
  :disabled t)

;; via http://www.emacswiki.org/emacs/ThesauriAndSynonyms
;; The file names are absolute, not relative, locations
;;     - e.g. /foobar/mthesaur.txt.cache, not mthesaur.txt.cache
(use-package synonyms
  :ensure t ;; install package if not found
  :init ;; executed before loading package
  (setq synonyms-file        "~/.emacs.d/data/mthesaur.txt")
  (setq synonyms-cache-file  "~/.emacs.d/data/synonyms.cache")
  :config
  (defun my-synonym-current-word ()
    "Lookup synonyms for current word."
    (interactive)
    (synonyms-lookup (thing-at-point 'word) nil nil))
  :bind (:map my-map ("s" . my-synonym-current-word))
  )
(use-package ox-hugo
  :after ox
  :init
  (defun mk/sync-to-server (&optional all-subtrees async visible-only noerror)
    (async-shell-command "cd ~/Dropbox/Public/essay && hugo -D && rsync -rvP ~/Dropbox/Public/essay/public/ dong.mk:/srv/http/essay"))
  (advice-add 'org-hugo-export-wim-to-md :after #'mk/sync-to-server)
  )
(use-package org-pomodoro)

About


Languages

Language:Emacs Lisp 82.1%Language:CSS 9.9%Language:YASnippet 3.2%Language:Shell 2.7%Language:Lua 2.2%