;;; emacs-config.el --- Main Emacs Configuration -*- lexical-binding: t -*-
;;; Commentary:
;;; Code:
(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.")
(when is-android
(setq mk-feature/bibliography nil
mk-feature/gui nil
mk-feature/news-mail nil
mk-feature/noteman nil))
;;; early-init.el --- Early Emacs configuration -*- lexical-binding: t -*-
;;; Commentary:
;;; Code:
(defvar is-android (string= system-type "android") "Whether on Anroid.")
;; (setq debug-on-error t)
;; (setq debug-on-signal t)
(setq-default
;; Package
load-prefer-newer t ; Load newer packages when available.
package-enable-at-startup nil ; do not load packege.el
package-quickstart nil
package-native-compile nil
;; GC
gc-cons-threshold most-positive-fixnum
gc-cons-percentage 0.6
;; Resizing the Emacs frame can be a terribly expensive part of changing the
;; font. By inhibiting this, we easily halve startup times with fonts that are
;; larger than the system default.
frame-inhibit-implied-resize t
)
(fset 'yes-or-no-p 'y-or-n-p)
(setq confirm-kill-emacs 'y-or-n-p)
(setq comp-deferred-compilation nil)
(when is-android
(setenv "PATH" (format "%s:%s" "/data/data/com.termux/files/usr/bin"
(getenv "PATH")))
(setenv "LD_LIBRARY_PATH" (format "%s:%s"
"/data/data/com.termux/files/usr/lib"
(getenv "LD_LIBRARY_PATH")))
(push "/data/data/com.termux/files/usr/bin" exec-path)
)
(when (string-equal system-type "android")
;; Add Termux binaries to PATH environment
(let ((termuxpath "/data/data/com.termux/files/usr/bin"))
(setenv "PATH" (concat (getenv "PATH") ":" termuxpath))
(setq exec-path (append exec-path (list termuxpath)))))
(unless is-android
(when (display-graphic-p)
(tool-bar-mode nil) ; t for enable, nil for disable, -1 for toggle
(scroll-bar-mode nil)
(menu-bar-mode nil))
(setq source-directory (expand-file-name "~/Library/Caches/Homebrew/emacs-plus@30--git"))
(setq-default
default-frame-alist
`(
(left-fringe . 8) ;; Thin left fringe
(menu-bar-lines . 0) ; No menu bar
(right-divider-width . 1) ;; Thin vertical window divider
(right-fringe . 3) ;; Thin right fringe
(tool-bar-lines . 0) ; No tool bar
(tab-bar-lines . 0) ; No tab bar
;; (undecorated . 1) ; this will completely remove the titlebar
(ns-titlebar-height-adjust . -10) ; this is actually not used
(ns-title-hidden . 1) ; hide the title text in the titlebar
(ns-fullsize-content . 1) ; make the content full size
(ns-transparent-titlebar . 1) ; make the titlebar transparent
(vertical-scroll-bars . nil) ; No vertical scroll-bars
(horizontal-scroll-bars . nil) ; No horizontal scroll-bars
(undecorated . t)
(width . 120)
(height . 50)
(font . "Monaco-12")
(minibuffer . t)
(drag-with-header-line . t)
(drag-with-mode-line . t)
(drag-with-internal-border . t)
))
;; (set-frame-font "Monaco-12" nil t)
(set-face-attribute 'fixed-pitch nil :family "Monaco")
) ; End of unless is-android
;; (when window-system (set-frame-size (selected-frame) 120 50))
;; UTF-8
(prefer-coding-system 'utf-8)
(when (display-graphic-p)
(setq x-select-request-type '(UTF8_STRING COMPUND_TEXT TEXT STRING)))
;; Unicode
(set-language-environment "UTF-8")
(set-default-coding-systems 'utf-8)
(setq locale-coding-system 'utf-8)
(set-terminal-coding-system 'utf-8)
(set-keyboard-coding-system 'utf-8)
(set-selection-coding-system 'utf-8)
(setq current-language-environment "UTF-8")
;; (setq default-input-method "rfc1345")
;; Sentence
(setq sentence-end-double-space nil) ; Use only one space to end a sentence
(provide 'early-init)
;;; early-init.el ends here
;;; init.el --- -*- lexical-binding: t -*-
;;; Commentary:
;;; Code:
(setq gc-cons-threshold (* 4 (expt 2 20))
gc-cons-percentage 0.6)
(let* (;; (file-name-handler-alist nil) ; This causes loading issues. Check: https://lists.gnu.org/archive/html/emacs-devel/2022-08/msg00218.html
(read-process-output-max (expt 2 22)))
;; 将lisp目录放到加载路径的前面以加快启动速度
(let ((dir (locate-user-emacs-file "init-lisp")))
(add-to-list 'load-path (file-name-as-directory dir)))
(let ((dir (locate-user-emacs-file "lisp")))
(add-to-list 'load-path (file-name-as-directory dir)))
(load "~/.emacs.d/emacs-config.el")
;; Collect garbage when all else is done
;; (garbage-collect)
)
(setq gc-cons-threshold (expt 2 23)
gc-cons-percentage 0.1)
(setq gc-cons-threshold (expt 2 28)
gc-cons-percentage 0.3)
(message "Everything is up. Wish you a nice day. :)")
(put 'narrow-to-region 'disabled nil)
(provide 'init)
;;; init.el ends here
(defvar mkconfig/.org "~/.emacs.d/emacs-config.org")
(defvar mkconfig/.el (concat (file-name-sans-extension mkconfig/.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 mkconfig/.org)
(message "[CONFIG] Config is synchronized.")
;; Async compile the config.
(async-byte-compile-file mkconfig/.el)))
;; Sync config when the config file is saved.
(add-hook 'after-save-hook
(lambda ()
(if (equal (buffer-file-name) (expand-file-name mkconfig/.org))
(mk/sync-emacs-config))))
(setq custom-file "~/.emacs.d/customs.el")
(load custom-file t)
straight.el | https://github.com/raxod502/straight.el |
package.el | built-in package system |
quelpa | https://github.com/quelpa/quelpa |
quelpa-use-package | https://github.com/quelpa/quelpa-use-package |
paradox | A 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 | https://github.com/jwiegley/use-package |
diminish | |
delight | better: altering mode appearance on modeline |
(straight-use-package 'use-package)
(setq straight-use-package-by-default t) ; Ensure :straight t
(setq use-package-compute-statistics t)
(when is-android
(setq straight-disable-compile t)
)
(unless is-android
(straight-use-package 'org))
(use-package use-package-ensure-system-package :ensure t)
(use-package delight)
(use-package benchmark-init
:ensure t
:config
;; To disable collection of benchmark data after init is done.
(add-hook 'after-init-hook 'benchmark-init/deactivate))
(unless is-android
;;; 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))
)
;;; 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))
(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)
(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)
)
We need to setup fonts early.
(use-package fontaine
:if (not is-android)
:ensure t
:when (and (display-graphic-p) (not is-android))
;; :hook (kill-emacs . fontaine-store-latest-preset)
:config
(setq fontaine-latest-state-file
(locate-user-emacs-file "etc/fontaine-latest-state.eld"))
(setq fontaine-presets
'((regular
:default-height 120
:default-weight regular
:fixed-pitch-height 1.0
:variable-pitch-height 1.0
)
(large
:default-height 140
:default-weight normal
:fixed-pitch-height 1.0
:variable-pitch-height 1.05
)
(t
:default-family "Monaco"
:fixed-pitch-family "Monaco"
:variable-pitch-family "Monaco"
:italic-family "Monaco"
:variable-pitch-weight normal
:bold-weight bold
:italic-slant italic
:line-spacing 0.1)
))
;; (fontaine-set-preset (or (fontaine-restore-latest-preset) 'regular))
(fontaine-set-preset 'regular)
;; set emoji font
(set-fontset-font
t
(if (version< emacs-version "28.1")
'(#x1f300 . #x1fad0)
'emoji)
(cond
((member "Segoe UI Emoji" (font-family-list)) "Segoe UI Emoji")
((member "Noto Emoji" (font-family-list)) "Noto Emoji")
((member "Symbola" (font-family-list)) "Symbola")
((member "Apple Color Emoji" (font-family-list)) "Apple Color Emoji")
((member "Noto Color Emoji" (font-family-list)) "Noto Color Emoji")
))
;; set Chinese font
(dolist (charset '(kana han symbol cjk-misc bopomofo))
(set-fontset-font
(frame-parameter nil 'font)
charset
(font-spec :family
(cond
((member "LXGW WenKai Screen" (font-family-list)) "LXGW WenKai Screen")
((member "Sarasa Mono SC Nerd" (font-family-list)) "Sarasa Mono SC Nerd")
((member "PingFang SC" (font-family-list)) "PingFang SC")
((member "WenQuanYi Zen Hei" (font-family-list)) "WenQuanYi Zen Hei")
((member "Microsoft YaHei" (font-family-list)) "Microsoft YaHei")
))))
;; (set-face-attribute 'default nil :font (font-spec :family "ia Writer" :size 14))
;; (set-fontset-font t 'unicode (font-spec :family "Noto Color Emoji" :size 14))
;; (set-fontset-font t '(#x2ff0 . #x9ffc) (font-spec :family "LXGW WenKai Screen" :size 18 :weight 'bold))
;; (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))
;; (set-fontset-font t 'unicode-bmp (font-spec :name "JuliaMono" :size 12) nil 'prepend)
;; set Chinese font scale
(setq face-font-rescale-alist `(
("LXGW WenKai Screen" . 1.24)
("Symbola" . 1.3)
("Microsoft YaHei" . 1.2)
("WenQuanYi Zen Hei" . 1.2)
("Sarasa Mono SC Nerd" . 1.2)
("PingFang SC" . 1.16)
("Lantinghei SC" . 1.16)
("Kaiti SC" . 1.16)
("Yuanti SC" . 1.16)
("Apple Color Emoji" . 0.91)
))
)
(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 :if (not is-android) :defer t)
(use-package crux :defer t)
(use-package ranger :defer t) ; The ranger mode
(use-package vlf :defer t) ; View large files
;; Persist history over Emacs restarts. Vertico sorts by history position.
(use-package savehist :straight nil :hook (after-init . savehist-mode))
;; Check https://emacs-china.org/t/emacs-builtin-mode/11937
;; Winner mode
(use-package winner :straight nil :hook (after-init . winner-mode))
;; Highlight current line
(use-package hl-line :straight nil :hook (after-init . global-hl-line-mode))
;; Remember the cursor position of files
(use-package saveplace :straight nil :hook (after-init . save-place-mode))
(use-package so-long :straight nil :config (global-so-long-mode 1))
(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 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)
)))
(modify-syntax-entry ?_ "w")
nyan-mode | https://github.com/TeMPOraL/nyan-mode/ |
yascroll.el | https://github.com/emacsorphanage/yascroll |
diff-hl | Hightlight uncommitted changes | https://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)
)
(add-hook 'magit-diff-mode-hook #'(lambda () (visual-line-mode t)))
(add-hook 'magit-status-mode-hook #'(lambda () (visual-line-mode 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))
(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 unspecified
:height 110
:italic t)))
:config
;; (global-blamer-mode 1)
)
undo-tree | built-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))
(use-package evil
:straight t
:after (undo-fu)
:init
(setq evil-want-C-i-jump nil)
(setq evil-move-beyond-eol t)
: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)
(if (featurep 'ef-themes)
(ef-themes-with-colors
(setq evil-emacs-state-cursor `((bar . 3) ,cursor))
(setq evil-insert-state-cursor `((bar . 1) ,cursor)))
(setq evil-emacs-state-cursor '((bar . 3) "#E90074"))
(setq evil-insert-state-cursor '((bar . 1) "#874CCC"))
)
;; 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
elfeed-search-mode
elfeed-show-mode
special-mode
))
(evil-set-initial-state nonevil-mode 'emacs))
(evil-mode 1))
evil-easymotion | https://github.com/PythonNut/evil-easymotion |
evil-snipe | https://github.com/hlissner/evil-snipe |
avy | https://github.com/abo-abo/avy |
(use-package 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)
(call-interactively 'execute-extended-command)
(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))
;; 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)
(use-package neotree :defer t)
;; (use-package perspective :config (persp-mode))
(use-package ctrlf
:defer t
:config
(ctrlf-mode +1))
;;; Smart Tab
(use-package smart-tab
:straight nil
:defer t
:config
(smart-tabs-insinuate 'c 'javascript))
whitespace | Built-in | http://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)
)
Emacs package that displays available keybindings in popup
which-key | https://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)
)
(use-package rainbow-mode
:defer t
:config (rainbow-mode t))
(use-package rainbow-delimiters
:defer t
:hook (prog-mode . rainbow-delimiters-mode))
(use-package highlight-indent-guides :defer t)
;; https://raw.githubusercontent.com/wowhxj/emacs-from-scratch/master/emacs-config.org
(use-package calendar
:init
(setq calendar-longitude 121.4737
calendar-latitude 31.2304
calendar-location-name "SH")
:ensure nil
:hook (calendar-today-visible . calendar-mark-today)
:custom
;; 是否显示中国节日,我们使用 `cal-chinese-x' 插件
(calendar-chinese-all-holidays-flag nil)
;; 是否显示节日
(calendar-mark-holidays-flag t)
;; 是否显示Emacs的日记,我们使用org的日记
(calendar-mark-diary-entries-flag nil)
;; 数字方式显示时区,如 +0800,默认是字符方式如 CST
(calendar-time-zone-style 'numeric)
;; 日期显示方式:year/month/day
(calendar-date-style 'iso)
;; 中文天干地支设置
(calendar-chinese-celestial-stem ["甲" "乙" "丙" "丁" "戊" "己" "庚" "辛" "壬" "癸"])
(calendar-chinese-terrestrial-branch ["子" "丑" "寅" "卯" "辰" "巳" "午" "未" "申" "酉" "戌" "亥"])
;; 设置中文月份
(calendar-month-name-array ["一月" "二月" "三月" "四月" "五月" "六月" "七月" "八月" "九月" "十月" "十一月" "十二月"])
;; 设置星期标题显示
(calendar-day-name-array ["日" "一" "二" "三" "四" "五" "六"])
;; 周一作为一周第一天
(calendar-week-start-day 0)
)
;; 时间解析增加中文拼音
(use-package parse-time
:ensure nil
:defer t
:config
(setq parse-time-months
(append '(("yiy" . 1) ("ery" . 2) ("sany" . 3)
("siy" . 4) ("wuy" . 5) ("liuy" . 6)
("qiy" . 7) ("bay" . 8) ("jiuy" . 9)
("shiy" . 10) ("shiyiy" . 11) ("shiery" . 12)
("yiyue" . 1) ("eryue" . 2) ("sanyue" . 3)
("siyue" . 4) ("wuyue" . 5) ("liuyue" . 6)
("qiyue" . 7) ("bayue" . 8) ("jiuyue" . 9)
("shiyue" . 10) ("shiyiyue" . 11) ("shieryue" . 12))
parse-time-months))
(setq parse-time-weekdays
(append '(("zri" . 0) ("zqi" . 0)
("zyi" . 1) ("zer" . 2) ("zsan" . 3)
("zsi" . 4) ("zwu" . 5) ("zliu" . 6)
("zr" . 0) ("zq" . 0)
("zy" . 1) ("ze" . 2) ("zs" . 3)
("zsi" . 4) ("zw" . 5) ("zl" . 6))
parse-time-weekdays)))
;; 中国节日设置
(use-package cal-china-x
:ensure t
:commands cal-china-x-setup
:hook (after-init . cal-china-x-setup)
:config
;; 重要节日设置
(setq cal-china-x-important-holidays cal-china-x-chinese-holidays)
;; 所有节日设置
(setq cal-china-x-general-holidays
'(;;公历节日
(holiday-fixed 1 1 "元旦")
(holiday-fixed 2 14 "情人节")
(holiday-fixed 3 8 "妇女节")
(holiday-fixed 4 1 "愚人节")
(holiday-fixed 5 1 "劳动节")
(holiday-fixed 5 4 "青年节")
(holiday-float 5 0 2 "母亲节")
(holiday-fixed 6 1 "儿童节")
(holiday-float 6 0 3 "父亲节")
(holiday-fixed 9 10 "教师节")
(holiday-fixed 10 1 "国庆节")
(holiday-fixed 12 25 "圣诞节")
;; 农历节日
(holiday-lunar 12 30 "除夕" 0)
(holiday-lunar 1 1 "春节" 0)
(holiday-lunar 1 15 "元宵" 0)
(holiday-solar-term "清明" "清明")
(holiday-solar-term "小寒" "小寒")
(holiday-solar-term "大寒" "大寒")
(holiday-solar-term "立春" "立春")
(holiday-solar-term "雨水" "雨水")
(holiday-solar-term "惊蛰" "惊蛰")
(holiday-solar-term "春分" "春分")
(holiday-solar-term "谷雨" "谷雨")
(holiday-solar-term "立夏" "立夏")
(holiday-solar-term "小满" "小满")
(holiday-solar-term "芒种" "芒种")
(holiday-solar-term "夏至" "夏至")
(holiday-solar-term "小暑" "小暑")
(holiday-solar-term "大暑" "大暑")
(holiday-solar-term "立秋" "立秋")
(holiday-solar-term "处暑" "处暑")
(holiday-solar-term "白露" "白露")
(holiday-solar-term "秋分" "秋分")
(holiday-solar-term "寒露" "寒露")
(holiday-solar-term "霜降" "霜降")
(holiday-solar-term "立冬" "立冬")
(holiday-solar-term "小雪" "小雪")
(holiday-solar-term "大雪" "大雪")
(holiday-solar-term "冬至" "冬至")
(holiday-lunar 5 5 "端午" 0)
(holiday-lunar 8 15 "中秋" 0)
(holiday-lunar 7 7 "七夕" 0)
(holiday-lunar 9 9 "重阳" 0)))
;; 设置日历的节日,通用节日已经包含了所有节日
(setq calendar-holidays (append cal-china-x-general-holidays)))
;; (setq mark-holidays-in-calendar t)
Calfw | https://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
)))
)
(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 vterm-toggle
:straight (:host github :repo "jixiuf/vterm-toggle")
:config
(global-set-key (kbd "C-c t") 'vterm-toggle)
(global-set-key [C-f2] 'vterm-toggle-cd)
;; you can cd to the directory where your previous buffer file exists
;; after you have toggle to the vterm buffer with `vterm-toggle'.
(define-key vterm-mode-map [(control return)] #'vterm-toggle-insert-cd)
;Switch to next vterm buffer
(define-key vterm-mode-map (kbd "s-n") 'vterm-toggle-forward)
;Switch to previous vterm buffer
(define-key vterm-mode-map (kbd "s-p") 'vterm-toggle-backward)
)
(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)
Alternatives (Check the selectrum repo README)
Ido | ||
Helm | ||
Ivy | ||
Icomplete | ||
Icicles | ||
Snallet | ||
Raven | ||
Swiper | ||
Selectrum | https://github.com/raxod502/selectrum | |
vertico | https://github.com/minad/vertico | |
Snails | https://github.com/manateelazycat/snails | |
---|---|---|
For Selectrum/vertico | ||
consult | https://github.com/minad/consult | |
marginalia | https://github.com/minad/marginalia | Alternative to ivy-rich |
Embark | https://github.com/oantolin/embark/ | Minibuffer actions (ivy has builtin alternative) |
mini-popup | “minad/mini-popup” | |
mini-frame |
(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 rg
:ensure-system-package
(rg . ripgrep))
(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 embark
: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
: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))
company-mode | https://github.com/company-mode/company-mode |
Corfu | https://github.com/minad/corfu |
Cape (use with Corfu) | https://github.com/minad/cape |
lsp-bridge |
;; A few more useful configurations...
(use-package emacs
:init
;; TAB cycle if there are only few candidates
;; (setq completion-cycle-threshold 3)
;; Enable indentation+completion using the TAB key.
;; `completion-at-point' is often bound to M-TAB.
(setq tab-always-indent 'complete)
;; Emacs 30 and newer: Disable Ispell completion function. As an alternative,
;; try `cape-dict'.
(setq text-mode-ispell-word-completion nil)
;; Hide commands in M-x which do not apply to the current mode. Corfu
;; commands are hidden, since they are not used via M-x. This setting is
;; useful beyond Corfu.
(setq read-extended-command-predicate #'command-completion-default-include-p))
yasnippet | https://github.com/joaotavora/yasnippet |
TempEl | https://github.com/minad/tempel |
(use-package yasnippet
:init (yas-global-mode 1))
(use-package yasnippet-snippets
:after yasnippet)
lsp-mode | |
eglot | Built-in since Emacs 29 |
nox | |
LSPCE | |
flycheck | popular alternative to flymake |
flymake | The rewritten built-in flymake is sufficient good |
flyspell | This is the real spell checker |
flycheck-languagetool | |
flycheck-grammarly | |
grammarly | the reverse-engineered API lib |
flymake-grammarly | |
flymake-languagetool | |
lsp-ltex | |
languagetool |
(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
(grammarly-load-from-authinfo)
)
(use-package flymake-grammarly
:straight (:host github :repo "emacs-grammarly/flymake-grammarly")
:after grammarly
:config
)
(use-package lsp-grammarly
:disabled t
:ensure t
:hook (text-mode . (lambda ()
(require 'lsp-grammarly)
(lsp)))) ; or lsp-deferred
(use-package lsp-bridge
:straight '(lsp-bridge :type git :host github :repo "manateelazycat/lsp-bridge"
:files (:defaults "*.el" "*.py" "acm" "core" "langserver" "multiserver" "resources")
:build (:not compile))
:init
;; (setq lsp-bridge-tex-lsp-server "texlab-grammarly")
(setq lsp-bridge-enable-hover-diagnostic t)
(setq acm-enable-capf t)
(setq acm-enable-doc t)
(setq acm-enable-doc-markdown-render 'async)
(setq acm-enable-icon t)
(setq acm-enable-tabnine t)
(setq acm-enable-quick-access t)
(setq acm-enable-citre t)
(setq acm-backend-search-file-words-candidate-min-length 3)
(setq acm-backend-lsp-show-progress t)
(setq acm-backend-yas-candidate-min-length 2)
(setq acm-backend-elisp-candidate-min-length 2)
(setq acm-backend-search-file-words-enable-fuzzy-match t)
(setq acm-backend-search-file-words-enable-fuzzy-match-threshold 1)
(setq acm-backend-lsp-match-mode "prefix")
(setq acm-backend-lsp-frontend-filter-p t)
(global-lsp-bridge-mode))
(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)))))
)
;; Built-in native line number display
(use-package display-line-numbers
:straight nil
:hook (prog-mode . display-line-numbers-mode)
:config
;; (setq-default display-line-numbers-width 3)
)
(use-package ws-butler
:delight ws-butler-mode
:config (progn
;; adding it to prog-mode-hook causes problems for emacsclient
(add-hook 'cython-mode-hook #'ws-butler-mode)
(add-hook 'LaTeX-mode-hook #'ws-butler-mode)
(add-hook 'emacs-lisp-mode-hook #'ws-butler-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 . +)))))
(use-package c-ts-mode
:bind (:map c-ts-base-mode-map
("M-<up>" . drag-stuff-up)
("M-<down>" . drag-stuff-down)
("<home>" . malb/beginning-of-line-dwim))
:hook ((c-ts-base-mode . hs-minor-mode)
(c-ts-base-mode . display-line-numbers-mode)
(c-ts-base-mode . ws-butler-mode)
;; (c-ts-base-mode . ggtags-mode)
;; (c-ts-base-mode . helm-gtags-mode)
(c-ts-base-mode . clang-format+-mode))
:init (progn
(add-to-list 'major-mode-remap-alist '(c-mode . c-ts-mode))
(add-to-list 'major-mode-remap-alist '(c++-mode . c++-ts-mode))
(add-to-list 'auto-mode-alist '("\\.inl\\'" . c++-ts-mode))))
(use-package clang-format :config (setq clang-format-executable "clang-format"))
(use-package clang-format+ :commands clang-format+-mode)
(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"))
(message "OK")
(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))
;; "texcount article.tex -inc -incbib -sum"
(add-to-list 'TeX-command-list '("Make Count" "make count" 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)
;; (add-hook 'after-save-hook #'flyspell-buffer)
(LaTeX-math-mode)
(darkroom-mode)
(setq buffer-face-mode-face '(:family "iA Writer Quattro V"))
(buffer-face-mode)
(visual-line-mode)
(visual-line-mode)
(darkroom-decrease-margins 0.8)
))
;; (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 auctex-latexmk :config (auctex-latexmk-setup))
;; https://emacs.stackexchange.com/a/63195/30542
(defun my-LaTeX-mode-setup ()
(font-latex-add-keywords '(("autoref" "*{") ("Autoref" "{") ("nameref" "*{"))
'reference))
(add-hook 'LaTeX-mode-hook #'my-LaTeX-mode-setup)
)
;; Show build progress in modeline
(use-package procress
:straight (:host github :repo "haji-ali/procress")
:commands procress-auctex-mode
:init
(add-hook 'LaTeX-mode-hook #'procress-auctex-mode)
:config
(procress-load-default-svg-images))
;; 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)
(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 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)
)
notmuch | |
WanderLust |
elfeed | https://github.com/skeeto/elfeed |
(use-package elfeed
:if mk-feature/news-mail
:defer t
:bind ("C-c f" . elfeed)
:config
;; The feed list
(setq elfeed-feeds
'(("http://nullprogram.com/feed/" blog emacs)
"http://www.50ply.com/atom.xml" ; no autotagging
;; Apple news
("https://feeds.macrumors.com/MacRumors-All" apple)
;; storage news
("https://thessdguy.com/feed/" storage)
("https://thememoryguy.com/feed/" storage)
("https://blocksandfiles.com/feed/" storage)
;; ("https://thesanguy.com/feed/" storage) website down
;;
("https://www.nextplatform.com/feed/" it)
("https://devclass.com/feed/" it)
("https://www.theregister.com/headlines.atom" it)
("http://ithare.com/rssfeed/" it)
("http://nedroid.com/feed/" webcomic)
"http://planet.emacsen.org/atom.xml"))
(setq-default elfeed-search-filter "@1-week-ago +unread ")
)
pyim | Emacs input method |
sis | Smart 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-emacs-module-header-root "/opt/homebrew/opt/emacs-plus@30/include")
(rime-show-candidate 'posframe)
(rime-posframe-properties
(list :background-color "#000000" ; 不要在这里设置字体,会影响后面 face 里字体的
:foreground-color "#f33333"
:internal-border-width 3
:internal-border-color "#5fc187"))
:config
(set-face-attribute 'rime-default-face nil
:background "#000000"
:foreground "honeydew1"
:font "Hei-20")
(set-face-attribute 'rime-highlight-candidate-face nil
:background "#5fc187"
:foreground "#efefef"
:font "Hei-20")
(set-face-attribute 'rime-candidate-num-face nil
:background "#000000"
:foreground "#5fc187"
:font "Hei-20")
(set-face-attribute 'rime-code-face nil
:background "#719ae7"
:foreground "#efefef"
:font "Hei-20")
)
(setq word-wrap-by-category t)
(use-package jieba
:disabled t
:if (not is-android)
: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)
)
(use-package emt
:if (not is-android)
:straight (:host github :repo "roife/emt"
:files ("*.el" "module/*" "module"))
:hook (after-init . emt-mode)
:config
(define-key evil-motion-state-map (kbd "w") #'emt-forward-word)
(define-key evil-motion-state-map (kbd "b") #'emt-backward-word)
)
(use-package valign
:hook (org-mode . valign-mode)
)
(load-file "~/.emacs.d/site-lisp/wc.el")
(provide 'init-writing)
(load-file "~/.emacs.d/site-lisp/tex-autogen.el")
(use-package svg-lib :ensure t)
(load-file "~/.emacs.d/site-lisp/big-timer.el")
(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)
(setq window-divider-default-right-width 2)
(setq window-divider-default-bottom-width 2)
(setq window-divider-default-places t)
(window-divider-mode 1))
(use-package doom-modeline
:init (doom-modeline-mode 1)
:config
(setq inhibit-compacting-font-caches t)
(setq mode-line-right-align-edge 'right-fringe)
(setq doom-modeline-icon t)
(setq doom-modeline-major-mode-icon t)
(setq doom-modeline-major-mode-color-icon t)
(setq doom-modeline-buffer-state-icon t)
(setq doom-modeline-buffer-modification-icon t)
(setq doom-modeline-time t)
(setq doom-modeline-time-icon t)
(setq doom-modeline-time-live-icon t)
(setq doom-modeline-minor-modes nil)
(setq doom-modeline-enable-word-count nil)
(setq doom-modeline-modal t)
(setq doom-modeline-modal-icon nil)
(setq doom-modeline-modal-modern-icon t)
(setq doom-modeline-unicode-fallback t)
(setq doom-modeline-enable-word-count t)
(setq doom-modeline-continuous-word-count-modes '(markdown-mode gfm-mode org-mode))
(setq doom-modeline-always-show-macro-register t)
(setq doom-modeline-support-imenu t)
(setq doom-modeline-bar-width 2)
;; (setq doom-modeline-window-width-limit 85)
(setq doom-modeline-height 1) ; optional
(custom-set-faces
'(mode-line ((t (:height 0.95))))
'(mode-line-active ((t (:height 0.95)))) ; For 29+
'(mode-line-inactive ((t (:height 0.95))))
'(doom-modeline-evil-emacs-state ((t (:italic nil)))))
)
(use-package ef-themes :straight (:host github :repo "protesilaos/ef-themes")
:after (hl-todo doom-modeline)
:config
(setq ef-cyprus-palette-overrides '((bg-main "#fdfefd")))
(setq ef-themes-to-toggle '(ef-cyprus ef-frost))
(setq ef-themes-headings ; read the manual's entry or the doc string
'((0 variable-pitch light 1.9)
(1 variable-pitch light 1.8)
(2 variable-pitch regular 1.7)
(3 variable-pitch regular 1.6)
(4 variable-pitch regular 1.5)
(5 variable-pitch 1.4) ; absence of weight means `bold'
(6 variable-pitch 1.3)
(7 variable-pitch 1.2)
(t variable-pitch 1.1)))
(setq ef-themes-mixed-fonts t
ef-themes-variable-pitch-ui t)
(defun my-ef-themes-hl-todo-faces ()
"Configure `hl-todo-keyword-faces' with Ef themes colors.
The exact color values are taken from the active Ef theme."
(ef-themes-with-colors
(setq hl-todo-keyword-faces
`(("HOLD" . ,yellow)
("TODO" . ,red)
("NEXT" . ,blue)
("THEM" . ,magenta)
("PROG" . ,cyan-warmer)
("OKAY" . ,green-warmer)
("DONT" . ,yellow-warmer)
("FAIL" . ,red-warmer)
("BUG" . ,red-warmer)
("DONE" . ,green)
("NOTE" . ,blue-warmer)
("KLUDGE" . ,cyan)
("HACK" . ,cyan)
("TEMP" . ,red)
("FIXME" . ,red-warmer)
("XXX+" . ,red-warmer)
("REVIEW" . ,red)
("DEPRECATED" . ,yellow)))))
(add-hook 'ef-themes-post-load-hook #'my-ef-themes-hl-todo-faces)
;; Disable all other themes to avoid awkward blending:
(mapc #'disable-theme custom-enabled-themes)
(ef-themes-select 'ef-cyprus)
)
(use-package hl-todo :straight (:host github :repo "tarsius/hl-todo"))
;; (use-package org-margin :straight (:host github :repo "rougier/org-margin")
;; :disabled t
;; :after (org)
;; :hook (org-mode . org-margin-mode)
;; )
;; (set-face-attribute 'org-level-1 nil :height 1.1)
;; (set-face-attribute 'fringe nil :background nil) ; Visually hide left-right margins
(use-package keycast :straight (:type git :host github :repo "tarsius/keycast")
:disabled
:init (keycast-mode))
Use holo lyaer
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))
(use-package xkcd :defer)
(use-package all-the-icons)
(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))
;; 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)))
(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)
)
(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))))
appt | MELPA, Appointment package |
;; 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)
;; 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
(setq org-startup-indented t) ; disable org-indent-mode for org-margin
(setq org-latex-create-formula-image-program 'dvisvgm)
;; (setq org-latex-create-formula-image-program 'dvipng)
(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-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
"知识(K)" ; pieces of knowledge
"讨论(D)" ; Discussion records
"技术技巧(S)"
"IDEA(I)"
"PROJECT(p)" ; Project
"SUBMITTED(s)"; Project
"ONGOING(g)" ; Doing
"WAIT(w)" ; Procrastinated on purpose
"LONG-TERM(l)" ; Long-term
"DELEGATE(z)" ; Delegated
"CONFDDL(C)"
"GOAL(G)"
"|"
"ACCEPTED(a)" ; Project
"DONE(d!)" ; Done
"CANCELED(c@)" ; Eliminated
)))
;; Always change the task to IN-PROGRESS.
;; (setq org-clock-in-switch-to-state "IN-PROGRESS")
;; (setq org-clock-out-switch-to-state #'(lambda (_)
;; (completing-read "Finishing a clock, change task state to?" '("DONE" "TODO"))))
;; 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))
("ONGOING" . "orangered")
("ACCEPTED" . "darkgreen")
("SUBMITTED" . "blue")
("WAIT" . "pink")
;; ("CANCELED" . (:foreground "white" :background "#4d4d4d" :weight bold :strike-through "#0d0d0d"))
("CANCELED" . (:foreground "white" :background "#4d4d4d"))
;; ("DONE" . "#008080")
("DONE" . (:foreground "#008080"))
("DELEGATE" . "DeepSkyBlue")
))
(setq org-log-into-drawer t)
;; 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 "▾")
(setq org-ellipsis "↴")
;; (setq org-ellipsis "...")
(set-face-attribute 'org-ellipsis nil :foreground "grey86")
;; 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)
(shell . 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))
)
(set-face-attribute 'outline-1 nil :foreground "firebrick")
(set-face-attribute 'org-level-1 nil :height 1.1)
(set-face-attribute 'outline-2 nil :foreground "purple2")
(set-face-attribute 'outline-3 nil :foreground "violetRed2")
(set-face-attribute 'outline-4 nil :foreground "cyan4")
;; (set-face-attribute 'outline-4 nil :foreground "springgreen4")
(setq org-fontify-quote-and-verse-blocks t)
(add-hook 'org-mode-hook
(lambda ()
(electric-indent-local-mode -1)
(mkvoya/better-wrap)
(prettify-symbols-mode)
;; (org-hide-properties)
))
(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)))
)
(setq org-hide-emphasis-markers nil) ; don’t hide markers for like *foo*
;; (setq org-hide-emphasis-markers t)
(setq org-emphasis-alist
'(("*" bold)
("/" italic)
("_" underline)
("=" org-verbatim verbatim)
;; ("@" (:foreground "red" :background "black"))
("&" (:foreground "red"))
("~" org-code verbatim)
("+"
(:strike-through t))))
(use-package ov)
(load-file "~/.emacs.d/site-lisp/org-colored-text.el")
)
(use-package org-sticky-header
:straight (:host github :repo "alphapapa/org-sticky-header")
:defer t
:after (org)
)
;; Org Cite
(use-package oc
:straight nil
:ensure nil
:after org)
(font-lock-add-keywords
'org-mode
'(("^[[:space:]]*\\(-\\) "
(0 (prog1 () (compose-region (match-beginning 1) (match-end 1) "•"))))))
(use-package org-bars
:straight (:host github :repo "tonyaldon/org-bars")
:defer t
:after (org)
:config
(setq org-bars-with-dynamic-stars-p nil)
)
(use-package highlight-indent-guides)
(use-package nerd-icons
:custom
;; The Nerd Font you want to use in GUI
;; "Symbols Nerd Font Mono" is the default and is recommended
;; but you can use any other Nerd Font if you want
(nerd-icons-font-family "Symbols Nerd Font Mono")
(nerd-icons-scale-factor 1.1)
)
(use-package org-tag-beautify
:ensure t
:custom (org-tag-beautify-data-dir "~/.emacs.d/straight/repos/org-tag-beautify/data/")
:init (org-tag-beautify-mode 1))
(use-package org-rainbow-tags
:ensure t
:custom
(org-rainbow-tags-hash-start-index 10)
(org-rainbow-tags-extra-face-attributes
;; Default is '(:weight 'bold)
'(:inverse-video t :box t :weight 'bold))
:hook
(org-mode . org-rainbow-tags-mode))
;; agenda 里面时间块彩色显示
;; From: https://emacs-china.org/t/org-agenda/8679/3
(defun my: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 (if background-dark-p
(list "#aa557f" "DarkGreen" "DarkSlateGray" "DarkSlateBlue")
(list "#F6B1C3" "#FFCF9D" "#BEEB9F" "#ADD5F7")))
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 #'my:org-agenda-time-grid-spacing)
(setq org-agenda-start-with-log-mode t)
;; Paste Image From https://emacs-china.org/t/topic/6601/4
(defun org-insert-image ()
"Insert a image from clipboard."
(interactive)
(let* ((buf-name (if (and (fboundp 'denote-file-is-note-p)
(fboundp 'denote-retrieve-filename-identifier)
(denote-file-is-note-p (buffer-file-name)))
(denote-retrieve-filename-identifier (buffer-name))
(buffer-name)))
(path (concat default-directory
buf-name
".assets/"))
(image-file (concat
path
buf-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)
)
(use-package ox-html
:straight nil
:after (org)
:defer t
:config
;; Org export code style
(setq org-html-htmlize-output-type 'css)
(setq org-src-preserve-indentation nil)
(setq-default org-html-doctype "html5")
(setq-default org-html-html5-fancy t)
(setq org-html-validation-link nil)
;; https://emacs.stackexchange.com/a/3512/30542
(defun my-org-inline-css-hook (exporter)
"Insert custom inline css"
(when (eq exporter 'html)
(let* ((dir (ignore-errors (file-name-directory (buffer-file-name))))
(path (concat dir "style.css"))
(homestyle (or (null dir) (null (file-exists-p path))))
(final (if homestyle "~/.emacs.d/misc/ox-html-code-style.css" path)))
(setq org-html-head-include-default-style t)
(setq org-html-head (concat
"<style type=\"text/css\">\n"
"<!--/*--><![CDATA[/*><!--*/\n"
(with-temp-buffer
(insert-file-contents final)
(buffer-string))
"/*]]>*/-->\n"
"</style>\n")))))
(add-hook 'org-export-before-processing-hook 'my-org-inline-css-hook)
;;; Add summary support, from Sachachua
(setq org-babel-exp-code-template "#+begin_src %lang%switches%flags :summary %summary\n%body\n#+end_src")
(defun my-org-html-src-block (src-block _contents info)
(let* ((result (org-html-src-block src-block _contents info))
(block-info
(org-with-point-at (org-element-property :begin src-block)
(org-babel-get-src-block-info)))
(summary (assoc-default :summary (elt block-info 2))))
(if (member summary '("%summary" ""))
result
(format "<details><summary>%s</summary>%s</details>"
summary
result))))
(with-eval-after-load 'ox-html
(map-put!
(org-export-backend-transcoders (org-export-get-backend 'html))
'src-block 'my-org-html-src-block))
)
(use-package ox-twbs
:after ox-html
:config
(defun my-org-html-src-block2 (src-block _contents info)
(let* ((result (org-twbs-src-block src-block _contents info))
(block-info
(org-with-point-at (org-element-property :begin src-block)
(org-babel-get-src-block-info)))
(summary (assoc-default :summary (elt block-info 2))))
(if (member summary '("%summary" ""))
result
(format "<details><summary>%s</summary>%s</details>"
summary
result))))
(with-eval-after-load 'ox-twbs
(map-put!
(org-export-backend-transcoders (org-export-get-backend 'twbs))
'src-block 'my-org-html-src-block2))
)
(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-todo-percent-states
'(
(0 "TODO")
(100 "DONE")
(0 "IDEA")
(100 "CANCELED")))
(setq org-caldav-calendars
'(
(
:calendar-id "9d6f9f39-cba5-fe5b-bd49-c61168d64f81"
;; :calendar-id "OrgSync"
:inbox "~/Dropbox/Dreams/Org/Caldav.inbox.org"
:files ("~/Dropbox/Dreams/Org/Main.org"
"~/Dropbox/Dreams/Org/Inbox.org"
"~/Dropbox/Dreams/Org/Ebib-ReadingList.org"
))
))
(setq org-icalendar-timezone "Asia/Shanghai")
)
Modes to embed one buffer in another buffer and keep them in sync
Freex | https://github.com/gregdetre/emacs-freex |
transclusion-minor-mode | http://github.com/whacked/transclusion-minor-mode |
(use-package org-transclusion
:after (org org-modern)
:hook (org-mode . org-transclusion-mode)
:config
;; (setq org-transclusion-fringe-bitmap 'empty-line)
(setq org-transclusion-fringe-bitmap 'right-triangle)
(set-face-attribute
'org-transclusion-fringe nil
:foreground "blue"
:background "orange")
(set-face-attribute
'org-transclusion-source-fringe nil
:foreground "lightblue"
:background "blue")
)
;; :bind (("<f12>" . #'org-transclusion-add))
;; ("C-n t" . #'org-transclusion-mode)
note taking | org-roam | |
org-roam-ui | ||
org-roam-server | (use org-roam-ui) | |
org-mindmap | creates graphviz directed graphs from headings of an org file | |
denote | ||
note search | notdeft | https://github.com/hasu/notdeft |
consult-ripgrep | consult built-in | |
org-brain |
(use-package websocket :defer t)
(use-package simple-httpd :defer t)
(use-package org-roam
:ensure t
:custom
(org-roam-directory (file-truename "~/Dropbox/Dreams/Org/"))
;; (org-roam-dailies-directory "Journals/")
;; (org-roam-dailies-capture-templates '(("d" "default" entry
;; "* %<%H:%M>: %?"
;; :target (file+datetree "LatestJournal.org" week))))
:bind (("C-c n l" . org-roam-buffer-toggle)
("C-c n f" . org-roam-node-find)
("C-c n g" . org-roam-graph)
("C-c n i" . org-roam-node-insert)
("C-c n c" . org-roam-capture)
;; Dailies
;; ("C-c n j" . org-roam-dailies-capture-today)
;; ("C-c n J" . org-roam-dailies-goto-today)
;; ("C-c j" . org-roam-dailies-capture-today)
;; ("C-c J" . org-roam-dailies-goto-today)
)
:config
;; If you're using a vertical completion framework, you might want a more informative completion interface
(setq org-roam-node-display-template (concat "${title:*} " (propertize "${tags:10}" 'face 'org-tag)))
(org-roam-db-autosync-mode)
;; If using org-roam-protocol
(require 'org-roam-protocol)
)
(use-package org-journal
:ensure t
:bind (("C-c j" . org-journal-open-current-journal-file)
("C-c J" . org-journal-new-entry))
:config
(bind-key "C-c s" 'org-journal-search-forever org-journal-mode-map)
(unbind-key "C-c C-s" org-journal-mode-map)
(setq org-journal-file-format "%Y-%m-%d-w%V.org")
(setq org-journal-enable-agenda-integration t)
(setq org-journal-file-type 'weekly)
(setq org-journal-dir "~/Dropbox/Dreams/Org/Journals/"
org-journal-date-format "%A, %d %B %Y")
;; org capture integration
(defun org-journal-find-location ()
;; Open today's journal, but specify a non-nil prefix argument in order to
;; inhibit inserting the heading; org-capture will insert the heading.
(org-journal-new-entry t)
(unless (eq org-journal-file-type 'daily)
(org-narrow-to-subtree))
(goto-char (point-max)))
(defvar org-journal--date-location-scheduled-time nil)
(defun org-journal-date-location (&optional scheduled-time)
(let ((scheduled-time (or scheduled-time (org-read-date nil nil nil "Date:"))))
(setq org-journal--date-location-scheduled-time scheduled-time)
(org-journal-new-entry t (org-time-string-to-time scheduled-time))
(unless (eq org-journal-file-type 'daily)
(org-narrow-to-subtree))
(goto-char (point-max))))
(setq org-capture-templates '(("j" "Journal entry" plain (function org-journal-date-location)
"** TODO %?\n <%(princ org-journal--date-location-scheduled-time)>\n"
:jump-to-captured t)
("J" "Journal entry" plain (function org-journal-find-location)
"** %(format-time-string org-journal-time-format)%^{Title}\n%i%?"
:jump-to-captured t :immediate-finish t)))
)
(use-package org-roam-ui
:straight
(:host github :repo "org-roam/org-roam-ui" :branch "main" :files ("*.el" "out"))
:after org-roam
;; normally we'd recommend hooking orui after org-roam, but since org-roam does not have
;; a hookable mode anymore, you're advised to pick something yourself
;; if you don't care about startup time, use
;; :hook (after-init . org-roam-ui-mode)
:config
(setq org-roam-ui-sync-theme t
org-roam-ui-follow t
org-roam-ui-update-on-save t
org-roam-ui-open-on-start t))
(use-package org-capture
:if mk-feature/noteman
:straight nil
:config
(defvar mk/org-capture-people-path)
(defun mk/org-capture-people ()
(interactive)
(format "* %s\n%%?" (read-string "姓名: " nil))
)
(setq org-capture-templates
'(("p" "New People" entry (file+headline "~/Dropbox/Dreams/Org/People/General.org" "People")
#'mk/org-capture-people
)
("r" "New Research Snippet" entry (file+headline "~/Dropbox/Dreams/Research/Snippets.org" "Research Snippets")
"* %?\n%i %a"
)
))
)
(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")
("People" ?d "~/Dropbox/Dreams/Org/People")
))
)
Publish & Blog
(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)
)
;; 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))
(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
)
)
Org-ref | https://github.com/jkitchin/org-ref | |
Citar | https://github.com/bdarcus/citar | Alternative 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 | https://github.com/cpitclaudel/biblio.el | Lookup & 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 | https://github.com/joostkremers/ebib | Bib 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-file-associations '(("pdf" . "open -a \"PDF Expert\" %s")))
(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-notes-symbol "📘")
(setq ebib-index-columns '(("Year" 4 t)
("Entry Key" 30 t)
("Note" 2 nil)
("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)))
(use-package zotra
:config
(setq zotra-backend 'zotra-server)
(setq zotra-local-server-directory "~/.emacs.d/third-parties/zotra-server/")
)
(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."
(let ((clean-title
(string-replace "}" "" (string-replace "{" "" title))))
(format "%s/%s/%s" mk/ebib-dir-root dir clean-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 "science") (format "science.%s" year))
((string= journal "commun. acm") (format "commun.acm.%s" year))
((string= journal "nature communications") (format "nat.comm.%s" year))
((string= journal "nature") (format "nature.%s" year))
((string= journal "advanced science") (format "advs.%s" year))
((string= journal "acs nano") (format "acs.nano.%s" year))
((string= journal "nano select") (format "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 "ieee transactions on information theory") (format "tit.%s" year))
((string= journal "briefings in bioinformatics") (format "bib.%s" year))
((string= journal "acs synthetic biology") (format "acs.syn.bio.%s" year))
((string= journal "angewandte chemie international edition") (format "anie.%s" year))
((string= journal "computational and structural biotechnology journal") (format "csbj.%s" year))
((string= journal "the australian universities' review") (format "aur.%s" year))
((string= journal "nature computational science") (format "nat.comput.sci.%s" year))
((string= journal "nature reviews genetics") (format "nat.rev.genet.%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 (mk/ebib--format-full-dir 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))))
)
(use-package popweb
:if mk-feature/gui
:defer t
:disabled t
:straight (:type git :host github :repo "manateelazycat/popweb" :files ("*"))
:init
(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)
)
(use-package chronos :defer t)
(use-package elquery :defer)
(use-package citeproc :defer)
(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
:if (not is-android)
:defer t
:straight (:type git :host github :repo "mkvoya/emacs-badge" :files ("*"))
:config
(require 'emacs-badge)
(setq emacs-badge-timer
(run-with-timer
30 30
'(lambda()
(emacs-badge-update (format "%s" (mk/count-today-todos))))))
)
(use-package elnode
:defer
:straight (:type git :host github :repo "jcaw/elnode"))
(use-package multiple-cursors
:bind (("C-!" . mc/mark-next-like-this)))
;; (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)
)
(use-package xwidget-apps
:if mk-feature/noteman
:straight nil
:ensure nil
:load-path "~/.emacs.d/site-lisp/xwidget-apps/"
:config
(xwidget-dict-mode)
)
(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)))
(setq python-shell-completion-native-disabled-interpreters nil)
(use-package ox-pandoc)
(use-package treesit-auto
:custom
(treesit-auto-install 'prompt)
:config
(setq treesit-font-lock-level 4)
(treesit-auto-add-to-auto-mode-alist 'all)
(global-treesit-auto-mode))
(use-package org-timeline
:after org
:config
(add-hook 'org-agenda-finalize-hook 'org-timeline-insert-timeline :append)
)
(use-package darkroom
:config
(setq darkroom-keep-lines t)
)
(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 org-pomodoro)
(use-package wwg
:straight (:type git :host github :repo "ag91/writer-word-goals")
:config
)
(defun how-many-str (regexp str)
(cl-loop with start = 0
for count from 0
while (string-match regexp str start)
do (setq start (match-end 0))
finally return count))
(defun how-many-checked (str)
(+ (how-many-str "\\[[^[:blank:]]\\]" str)
(how-many-str "([^[:blank:]])" str)))
(defun how-many-unchecked (str)
(+ (how-many-str "\\[ \\]" str)
(how-many-str "( )" str)))
(defun mk/org-columns--summary-pomodoro-count (check-boxes _)
"Summarize pomodoro CHECK-BOXES with a check-box cookie."
(let ((checked (cl-reduce '+ (cl-mapcar #'how-many-checked check-boxes)))
(unchecked (cl-reduce '+ (cl-mapcar #'how-many-unchecked check-boxes))))
(format "[%d/%d]" checked (+ checked unchecked))))
(setq org-columns-summary-types
'(("P/" . mk/org-columns--summary-pomodoro-count))
)
(defun mk/org-clocking-on-state-change ()
"Auto clock-in/-out when state changes."
(unless (string= org-last-state org-state)
(cond
((string= org-state "ONGOING")
(org-clock-in))
((string= org-last-state "ONGOING")
(org-clock-out)
))))
(add-hook 'org-after-todo-state-change-hook #'mk/org-clocking-on-state-change)
(use-package format-all)
(use-package unkillable-scratch
:config (progn (unkillable-scratch 1)))
(use-package scratch)
;; Speedy reading
(use-package spray
:config (progn
(setq spray-wpm 400
spray-margin-left 4
spray-margin-top 12)
(bind-key "+" 'spray-faster spray-mode-map)
(bind-key "-" 'spray-slower spray-mode-map)
(add-to-list 'spray-unsupported-minor-modes 'beacon-mode)))
(use-package synosaurus
:ensure-system-package ((wn . wordnet))
;; :bind (("C-c w s" . synosaurus-lookup)
;; ("C-c w S" . synosaurus-choose-and-replace))
:custom
(synosaurus-prefix (kbd "C-c S"))
:config (progn
(setq synosaurus-choose-method 'popup)
(unbind-key "C-c s l" synosaurus-mode-map)
(unbind-key "C-c s r" synosaurus-mode-map)
(add-hook 'org-mode-hook #'synosaurus-mode)
(add-hook 'LaTeX-mode-hook #'synosaurus-mode)))
(use-package powerthesaurus
;; :bind ("C-c w p" . powerthesaurus-lookup-dwim)
:config (add-to-list 'display-buffer-alist
`(,(rx bos "*Powerthesaurus - " (0+ any) "*" eos)
(display-buffer-in-side-window)
(side . right)
(slot . 0)
(window-width . 80))))
(use-package focus)
(use-package org-tidy
:disabled t
:ensure t
:hook (org-mode . org-tidy-mode)
:config
(setq org-tidy-top-property-style 'keep
org-tidy-properties-style 'fringe)
)
beacon | https://github.com/Malabarba/beacon |
(use-package holo-layer
:disabled t
:if (not is-android)
:straight (:type git :host github :repo "manateelazycat/holo-layer" :files ("*"))
:config
(setq holo-layer-enable-cursor-animation t)
(setq holo-layer-enable-place-info nil)
(setq holo-layer-cursor-animation-color-gradient-start-value 200)
(setq holo-layer-enable-indent-rainbow nil)
(setq holo-layer-enable-type-animation t)
(setq holo-layer-type-animation-style "lightning")
;; (setq holo-layer-type-animation-style "balloon")
;; (setq holo-layer-type-animation-style 'supernova)
;; (setq holo-layer-type-animation-style 'flame)
;; (setq holo-layer-sort-tab-ui t)
;; (setq holo-layer-enable-indent-rainbow t)
;; (setq holo-layer-cursor-color "Goldenrod")
(holo-layer-enable)
)
;; (use-package sort-tab :ensure t :init (sort-tab-mode 1))
(defun mk/count-today-todos ()
"Count the number of today's to-do tasks."
(interactive)
(let ((count 0)
(today (format-time-string "%Y-%m-%d")))
(org-compile-prefix-format 'todo)
(org-map-entries
(lambda ()
(when (and (string= (org-get-todo-state) "TODO")
(or (string= (org-entry-get nil "SCHEDULED") today)
(and (org-entry-get nil "DEADLINE")
(string< today (org-entry-get nil "DEADLINE")))
))
(setq count (1+ count))))
nil 'agenda)
count)
)
(use-package dirvish)
(use-package htmlize)
(setq org-tags-column 0)
(defun org-babel-C-execute/filter-args (args)
(when-let* ((params (cadr args))
(stdin (cdr (assoc :stdin params)))
(res (org-babel-ref-resolve stdin))
(stdin (org-babel-temp-file "c-stdin-")))
(with-temp-file stdin (insert res))
(let* ((cmdline (assoc :cmdline params))
(cmdline-val (or (cdr cmdline) "")))
(when cmdline (setq params (delq cmdline params)))
(setq params
(cons (cons :cmdline (concat cmdline-val " <" stdin))
params))
(setf (cadr args) params)))
args)
(with-eval-after-load 'ob-C
(advice-add 'org-babel-C-execute :filter-args
#'org-babel-C-execute/filter-args))
(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)
)
;; 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 i") (lambda () (interactive) (find-file "~/Dropbox/Dreams/Org/Inbox.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 b") '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)))))
(use-package copilot
:straight (:host github :repo "copilot-emacs/copilot.el" :files ("*.el"))
:ensure t
:config
(define-key copilot-completion-map (kbd "<tab>") 'copilot-accept-completion)
(define-key copilot-completion-map (kbd "TAB") 'copilot-accept-completion)
)
;; you can utilize :map :hook and :config to customize copilot
(setq-default
header-line-format
'("GC: " (:eval (number-to-string gcs-done)) " - " (:eval (number-to-string gc-elapsed)) "s"))
(defun mk/org-archive-to-specified-file ()
"Archive the current org entry to a user-specified file."
(interactive)
(let ((file (read-file-name "Archive to file: ")))
(let ((org-archive-location (concat file "::")))
(org-archive-subtree))
(message "Archived to %s" file)))
(use-package elysium
:straight
(:host github :repo "lanceberge/elysium" :branch "main" :files ("*.el"))
:custom
;; Below are the default values
(elysium-window-size 0.33) ; The elysium buffer will be 1/3 your screen
(elysium-window-style 'vertical)) ; Can be customized to horizontal
(use-package smerge-mode
:hook
(prog-mode . smerge-mode))
(use-package gptel
:config
(defun remove-trailing-newline (str)
"Remove the trailing newline character from STR, if it exists."
(if (string-suffix-p "\n" str)
(substring str 0 -1)
str))
(defun read-file-contents (file-path)
"Read the contents of FILE-PATH and return it as a string."
(with-temp-buffer
(insert-file-contents file-path)
(buffer-string)))
(defun gptel-api-key ()
(remove-trailing-newline (read-file-contents "~/.secrets/ipads-chatgpt.key")))
(setq gptel-use-curl nil)
(setq
;; gptel-model "gpt-4o-2024-05-13"
gptel-model "claude-3-5"
gptel-backend
(gptel-make-openai "IPADS GPT"
:host "ipads.chat.gpt:3006"
:protocol "http"
:stream t
:key #'gptel-api-key
:models '("claude-3-5"
"gpt-4o-2024-05-13"
"gpt-4o"))))
Scrolling
;; Let's disable the precision mode since it brings some troubles with the precision mode
;; (pixel-scroll-precision-mode)
(setq scroll-preserve-screen-position 'always)
(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)))
(define-key dired-mode-map "E" 'mk/dired-open-pdf)
(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)
)))
(use-package diredfl :config (diredfl-global-mode))
(use-package dired+ :config (setq diredp-hide-details-propagate-flag t))
(use-package dired-preview
:config
;; Default values for demo purposes
(setq dired-preview-delay 0.7)
(setq dired-preview-max-size (expt 2 20))
(setq dired-preview-ignored-extensions-regexp
(concat "\\."
"\\(mkv\\|webm\\|mp4\\|mp3\\|ogg\\|m4a"
"\\|gz\\|zst\\|tar\\|xz\\|rar\\|zip"
"\\|iso\\|epub\\|pdf\\)"))
)
(use-package infinite
:disabled t
:straight (:host gitlab :repo "andreyorst/infinite.el")
)
(use-package eee
:disabled t
:straight (:type git :host github :repo "eval-exec/eee.el"
:files (:defaults "*.el" "*.sh"))
:config
(setq ee-terminal-command "wezterm")
)
(use-package maple-explorer :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 ns-auto-titlebar :disabled t) ; We used a better patch.
(use-package elgantt :disabled t
:straight (:type git :host github :repo "legalnonsense/elgantt"))
(use-package paper :disabled t
:straight (:host github :repo "ymarco/paper-mode" :files("*.el" "*.so")))
(use-package gitlab-ci-mode :defer t)
(use-package dockerfile-mode :mode "Dockerfile" :defer t)
(use-package lua-mode :defer)
(use-package swift-mode :disabled t)
(use-package typescript-mode)
(use-package adoc-mode :defer t :straight (:host github :repo "sensorflo/adoc-mode"))
(use-package elm-mode)
(use-package jinja2-mode :mode "\\.jinja2\\'" :defer t)
(use-package vue-mode :mode "\\.vue\\'" :defer t)
;; 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)
;; Markdown Support
(use-package markdown-mode :defer t
:mode (("README\\.md\\'" . gfm-mode)
("\\.md\\'" . markdown-mode)
("\\.markdown\\'" . markdown-mode))
:config
;; (setq markdown-command "multimarkdown")
(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))