同步操作将从 金色飞贼(小米)/Emacs configuration 强制同步,此操作会覆盖自 Fork 仓库以来所做的任何修改,且无法恢复!!!
确定后同步将在后台操作,完成时将刷新页面,请耐心等待。
#+title: Emacs configuration
;; -*- lexical-binding: t; -*-
(setq gc-cons-threshold (* 50 1000 1000))
(setq custom-file (expand-file-name "custom.el" user-emacs-directory))
将本文件内容写进 init.el
等文件中, 并自动保存.
(defun my/org-babel-tangle-config ()
(when (string-equal (buffer-file-name)
(expand-file-name "emacs-config.org" user-emacs-directory))
;; Dynamic scoping to the rescue
(let ((org-confirm-babel-evaluate nil))
(org-babel-tangle))))
(add-hook 'org-mode-hook
(lambda () (add-hook 'after-save-hook #'my/org-babel-tangle-config)))
;; 针对 Emacs 30 Android 端口的设置
(setq my/is-android (eq system-type 'android))
(when my/is-android
(setenv "PATH" (format "%s:%s" "/data/data/com.termux/files/usr/bin:/data/data/com.termux/files/usr/bin/texlive" (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)
(push "/data/data/com.termux/files/usr/bin/texlive" exec-path)
(setenv "TEXMFROOT" "/data/data/com.termux/files/usr/share/texlive"))
;; 在执行 init.el 前禁用 package.el
(setq package-enable-at-startup nil)
从 straight
主页上下载的 straight
初始化代码. 注意 Emacs 29 更改了 native compilation 有关的变量. 切换到 develop
分支能暂时解决这个问题
(defvar bootstrap-version)
;; 修复 Emacs 29 修改了 native-compile 相关变量导致的 bug
(unless (version<= emacs-version "28.2")
(setq straight-repository-branch "develop"))
(setq straight-check-for-modifications '(check-on-save find-when-checking))
(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
代码块其实是 straight-use-package
. 这样我们 use-package
设置在安装 straight
和未安装 straight
的机器上能够最大程序地保持一致.
(straight-use-package 'use-package) ; 安装 use-package, 版本29后内置
(setq straight-use-package-by-default t) ; 自动安装所有插件, 相当于加入 :straight t
(setq use-package-always-defer t) ; 总是延迟加载
;; 如果不使用 straight, 上面一行相当于:
;; (setq use-package-always-ensure t) ; 相当于加入 :ensure t
(use-package general
:defer 1
:config
(general-evil-setup t)
(general-create-definer
my/leader-def
:states '(normal visual insert emacs)
:prefix "SPC"
:global-prefix "<f1> SPC"
:keymap 'override)
(general-create-definer
my/insert-leader-def
:states '(insert emacs)
:global-prefix "<f1> SPC"
:keymap 'override)
(my/insert-leader-def
"SPC" '(cycle-spacing :which-key "cycle spacing")))
用 no-littering
保持文件夹整洁
(use-package no-littering
:demand t
:custom
(auto-save-file-name-transforms `((".*" ,(no-littering-expand-var-file-name "auto-save/") t)))) ; 设置自动保存文件目录
recentf
快速打开最近文件
(use-package recentf
:after no-littering
:demand t
:custom
(recentf-exclude '(no-littering-var-directory
no-littering-etc-directory)) ; 屏蔽临时文件
(recentf-max-menu-items 25)
(recentf-max-saved-items 25)
:bind ("C-x C-r" . 'recentf-open-files)
:config
(recentf-mode 1))
;; Emacs 29 启用了新变量名
(if (version<= emacs-version "28.2")
(setq native-comp-deferred-compilation-deny-list '(".*pdf.*")) ; 禁用 =pdf-tools= 有关文件的本地化编译
(setq native-comp-jit-deferred-compilation-deny-list '(".*pdf.*"))) ; 禁用 =pdf-tools= 有关文件的本地化编译
;; (setq warning-minimum-level :error) ; 不提示 warning
(setq-default major-mode 'text-mode)
这一段包含个人不同设备的设置.
(setq my/is-windows (eq system-type 'windows-nt)) ; Windows 系统
(setq my/is-linux (eq system-type 'gnu/linux)) ; Linux 系统
(setq my/is-manjaro (string-match "MANJARO" operating-system-release)) ; manjaro 系统
(setq my/is-termux (string= system-configuration "aarch64-unknown-linux-android")) ; termux
(setq my/is-userland (string= system-configuration "aarch64-unknown-linux-gnu")) ; userland
(setq my/is-WSL
(and (eq system-type 'gnu/linux)
(string-match
"icrosoft"
(shell-command-to-string "uname -a"))))
(setq my/is-HW-Mbook ; HW Matebook
(and (eq system-type 'gnu/linux)
(string-match
"Y2023"
(shell-command-to-string "uname -a"))))
;; 注意: my/is-android 已经在 early-init.el 中定义了.
;; 如果想开启这些功能可以直接把该变量设为 1. 这里默认的判断条件是随意选取的.
(setq my/is-turn-on-experimental (or (file-exists-p "~/.dotfiles/tangle-dotfiles.el")
(file-exists-p "~/termux-home/")))
(setq my/is-terminal (not window-system))
(server-start)
(use-package savehist
:defer 1
:config (savehist-mode))
(use-package saveplace
:defer 1
:config
(save-place-mode 1))
(use-package super-save
:defer 1
:custom
(super-save-auto-save-when-idle t)
:config
(super-save-mode +1))
(global-auto-revert-mode 1)
(setq global-auto-revert-non-file-buffers nil)
(prefer-coding-system 'utf-8) ; 默认编码
(setq-default buffer-file-coding-system 'utf-8-unix) ; 默认 EOL 设置
(defvar my/font-height 130)
(defvar my/latex-preview-scale 1.3)
(defvar my/mm-char-height ; 字体高度 (mm)
(if (or my/is-termux my/is-android my/is-HW-Mbook) 2.4 4.2)) ; 平板和笔记本电脑的字体小一些.
;; 计算达到上述文字大小, 相应的字体大小.
;; font-height (in 1/10 pixel) = 10 * total pixel / (totol length in mm / preset height in mm)
;; 当字体高度为 4.2 mm 时, 对应的大致字体大小为 1080p: 15.5; 2K: 18; 4K: 22
(defun my/get-font-height (&optional frame)
(let* ((attrs (frame-monitor-attributes frame))
(geometry (alist-get 'geometry attrs))
(size (alist-get 'mm-size attrs))
(pixel-width (caddr geometry)) ; 第三个参数是宽度
(mm-width ; 第一个参数是宽度
(cond (my/is-android (/ (car size) 100)) ; 平板上宽度获取有问题
(my/is-HW-Mbook 300)
(t (car size)))))
(round (* 10 (/ pixel-width (/ mm-width my/mm-char-height))))))
(defun my/set-font-size ()
;; 用 my/get-font-height 设置 my/font-height 与 my/latex-preview-scale 的值.
;; 一般是 80:1 的关系 (数学公式略大). 只有 Android 上的 Emacs 是 2:1
(interactive)
(let* ((font-size (my/get-font-height)))
(message "font size: %s" font-size)
(setq my/font-height font-size)
(setq my/latex-preview-scale
(if my/is-android (/ font-size 2.0)
(/ font-size 80.0)))))
(defun my/set-font (font-height &optional frame)
(interactive)
(unless (or my/is-terminal); 非图形界面不能使用函数 set-fontset-font
;; 设置系统默认字体
(setq my/system-default-font
(if my/is-android "Droid Sans Mono" (font-get-system-normal-font)))
;; 设置 Emacs 默认字体
(setq my/default-font "Fira Code") ; 包名: fonts-firacode (ubuntu) 或 ttf-fira-code (manjaro)
(unless (find-font (font-spec :name my/default-font))
(message (format "cannot find %s for the default font" my/default-font))
(setq my/default-font my/system-default-font))
;; 设置 LaTeX 代码默认字体
(setq my/math-font
(if my/is-android "DejaVu Math TeX Gyre" ; 平板上数学字体
"Latin Modern Math")) ; texlive 自带字体
(unless (find-font (font-spec :name my/math-font))
(message (format "cannot find %s for the math font. Use system default instead" my/math-font))
(setq my/math-font my/system-default-font))
(setq my/chinese-font
(cond (my/is-termux "Roboto")
(my/is-windows "Kaiti")
;; (my/is-linux "AR PL KaitiM GB") ; fonts-arphic-gkai00mp (apt)
(t "AR PL UKai CN"))) ; 包名: ttf-arphic-ukai (manjaro)
(unless (find-font (font-spec :name my/chinese-font))
(message (format "cannot find %s for the chinese font. Use system default instead" my/chinese-font))
(setq my/chinese-font my/system-default-font))
(setq my/variable-pitch-font
(if my/is-windows "Segoe Print"
"Iosevka Aile")) ; 包名: ttc-iosevka-aile (manjaro)
(unless (find-font (font-spec :name my/variable-pitch-font))
(message (format "cannot find %s for the variable-pitch font. Use system default instead" my/variable-pitch-font))
(setq my/variable-pitch-font my/system-default-font))
(setq my/fixed-pitch-font "JetBrains Mono") ; 包名: fonts-jetbrains-mono (ubuntu) 或 ttf-jetbrains-mono (manjaro)
(unless (find-font (font-spec :name my/fixed-pitch-font))
(message (format "cannot find %s for the fixed-pitch font. Use system default instead" my/fixed-pitch-font))
(setq my/fixed-pitch-font my/system-default-font))
(set-face-attribute 'default frame :font my/default-font :height font-height) ; 默认字体及字号.
(set-face-attribute 'variable-pitch frame :font my/variable-pitch-font :height font-height) ; 比例字体
(set-face-attribute 'fixed-pitch frame :font my/fixed-pitch-font :height font-height) ; 等宽字体
(set-fontset-font "fontset-default" 'mathematical my/math-font) ; 数学符号默认字体
(set-fontset-font "fontset-default" 'han my/chinese-font) ; 中文默认字体
(setq inhibit-compacting-font-caches t) ; 汉字及 Unicode 显示问题
(setq auto-window-vscroll nil))) ; 不根据行高做上下滚动调整
(defun my/set-font-current-frame ()
;; 根据当前显示器尺寸设置字体大小
(interactive)
(my/set-font (my/get-font-height) (selected-frame)))
(global-set-key (kbd "C-x 9") #'my/set-font-current-frame)
pyim
)pyim
自定义探针函数
(defun my/pyim-probe-latex-mode ()
"latex-mode 中的数学环境自动切换到英文输入."
(and (eq major-mode 'latex-mode)
(if (fboundp 'texmathp) (texmathp) nil)))
pyim
设置
(use-package popup) ; 选词框
(use-package pyim-wbdict
:defer 2) ; 五笔输入法
(use-package pyim
:defer 2
:after pyim-wbdict
:bind
("M-j" . 'pyim-convert-string-at-point)
:config
(setq default-input-method "pyim")
(setq pyim-default-scheme 'wubi)
;; 使用从 http://gaokuan.ysepan.com/?xzpd=1 上下载的五笔词库.
(pyim-extra-dicts-add-dict
`(:name "my-wubi-dict" :file
,(file-truename (expand-file-name "lisp/my-wubi-86-dict.pyim" user-emacs-directory))))
(require 'popup)
(setq pyim-page-tooltip '(minibuffer)) ; 需要候选框可以使用 popup, 但是会影响速度
(setq-default pyim-punctuation-translate-p '(no)); 总是输入半角标点.
(setq-default pyim-english-input-switch-functions
'(pyim-probe-auto-english
pyim-probe-isearch-mode
pyim-probe-program-mode
pyim-probe-org-structure-template
pyim-probe-org-latex-mode
my/pyim-probe-latex-mode))
(setq-default pyim-punctuation-half-width-functions
'(pyim-probe-punctuation-line-beginning
pyim-probe-punctuation-after-punctuation)))
(defun my/insert-pause ()
(interactive)
(insert "、"))
(my/insert-leader-def
"," '(my/insert-pause :which-key "insert pause"))
参考 https://www.reddit.com/r/emacs/comments/ezetx0/doomthemes_screenshots_updated_good_time_to_go/
(defun my/load-doom-theme (theme)
"Disable active themes and load a Doom theme."
(interactive (list (intern (completing-read "Theme: "
(->> (custom-available-themes)
(-map #'symbol-name)
(--select (string-prefix-p "doom-" it)))))))
(ap/switch-theme theme)
(set-face-foreground 'org-indent (face-background 'default)))
(defun my/switch-theme (theme)
"Disable active themes and load THEME."
(interactive (list (intern (completing-read "Theme: "
(->> (custom-available-themes)
(-map #'symbol-name))))))
(mapc #'disable-theme custom-enabled-themes)
(load-theme theme 'no-confirm))
(use-package doom-themes
:if (not my/is-termux) ;; disable doom-themes in termux
:demand t
:config
(setq doom-themes-enable-bold t ; if nil, bold is universally disabled
doom-themes-enable-italic t) ; if nil, italics is universally disabled
(load-theme 'doom-moonlight t) ; 当前主题
(doom-themes-visual-bell-config) ; Enable flashing mode-line on errors
(doom-themes-org-config))
(setq display-time-day-and-date t)
(display-time-mode 1)
(use-package moe-theme
:demand t
:if my/is-termux
:config
(moe-dark))
(use-package all-the-icons
:if (display-graphic-p)) ; 第一次运行时, M-x all-the-icon-install-fonts 安装字体.
(use-package minions
:hook (doom-modeline-mode . minions-mode))
(use-package doom-modeline
:hook (after-init . doom-modeline-mode)
:custom
(doom-modeline-unicode-fallback t)
:config
(setq doom-modeline-height 1) ; optional
(custom-set-faces
'(mode-line ((t (:height 0.85))))
'(mode-line-active ((t (:height 0.85)))) ; For 29+
'(mode-line-inactive ((t (:height 0.85))))))
这个要在 doom-theme
之后才能生效!
(defun my/set-line-number ()
(interactive)
(column-number-mode) ; 显示列号
(global-visual-line-mode t) ; 自动断行
(global-display-line-numbers-mode t) ; 显示行号
;; 不显示行号的模式:
(dolist (mode '(term-mode-hook
helpful-mode-hook
eshell-mode-hook
pdf-view-mode-hook
eww-mode-hook))
(add-hook mode (lambda () (display-line-numbers-mode 0))))
(setq display-line-numbers-type 'visual) ; 行号考虑自动断行
;; 行号强制用等宽字体
(unless my/is-terminal
(set-face-attribute 'line-number nil :font my/default-font :height 0.9)
(set-face-attribute 'line-number-current-line nil :font my/default-font :height 0.9)))
(setq default-frame-alist '((fullscreen . maximized))) ; 全屏
(add-to-list 'default-frame-alist '(alpha . (90 . 90) ))
(defun my/set-window ()
(interactive)
(unless my/is-termux ; 终端下以下设置不可用
(tool-bar-mode 0) ; 禁用工具栏
(scroll-bar-mode 0)) ; 禁用滚动条
(menu-bar-mode 0) ; 禁用菜单栏
)
(setq my/enable-folding (not my/is-terminal))
(setq split-height-threshold nil) ; 默认左右分屏
(setq display-buffer-base-action
'((display-buffer-reuse-window ; 针对 *eshell* 等重名 buffer
display-buffer-reuse-mode-window ; 默认使用当前窗口的模式
display-buffer-in-previous-window ; 在用过的窗口中打开
display-buffer-same-window))) ; 在当前窗口中打开
popper
)
(when my/is-turn-on-experimental
(setq my/right-popper-buffer-regexp "\\(\\*scratch\\|\\*draft\\|\\*help\\|\\*Message\\|\\*Customize\\)") ; 在右侧打开的临时窗口
(setq my/bottom-popper-buffer-regexp "\\(\^\\*shell\\|\*compilation\\|\\*Backtrace\\|\\*Warnings\\|output\\*$\\)") ; 在下方打开的临时窗口
(use-package popper
:defer 2
:after perspective ; use perspective to group
;; 修正了 popper-echo.el 中一个 bug. 若不同时使用 echo-mode 与 group-function 也可以使用原有版本(删去下一行)
:straight (:local-repo "../../lisp/popper/" :type nil)
:bind (("C-M-'" . popper-toggle-latest)
("M-'" . popper-cycle)
("C-M-;" . popper-toggle-type))
:custom
(popper-reference-buffers `(,my/bottom-popper-buffer-regexp ,my/right-popper-buffer-regexp))
(popper-group-function #'popper-group-by-perspective) ; 用 perspective 分类弹出窗口
(popper-display-control nil) ; 用 display-buffer-list 管理弹出窗口行为
:config
;; 在 termux 中不能使用 C-', 在 EXWM 窗口中不能使用 C-M. 这里定义备用快捷键
(my/leader-def
"pl" 'popper-toggle-latest
"pt" 'popper-toggle-type
"pc" 'popper-cycle)
(popper-mode +1)
(popper-echo-mode +1))
)
设置 display-buffer-alist
变量
dsiplay-buffer-alist
初始化
(setq window-side-slots '(0 0 2 2)) ; 左上右下最大临时窗口数
(setq display-buffer-alist
`((,my/bottom-popper-buffer-regexp ; 下侧打开的窗口
(display-buffer-in-previous-window display-buffer-reuse-mode-window display-buffer-in-side-window)
(window-height . 0.2)
(window-min-height . 7)
(side . bottom)
(reusable-frames . visible))
(,my/right-popper-buffer-regexp ; 右侧打开的窗口
(display-buffer-reuse-mode-window display-buffer-in-side-window)
(reusable-frames . visible)
(side . right)
(direction . rightmost)
(window-width . 0.33))))
pdf
与 tex
)
(if (not my/is-android)
(progn (add-to-list 'display-buffer-alist '(".*pdf$" ; 默认右侧打开 pdf
(display-buffer-in-direction
display-buffer-in-previous-window)
(direction . rightmost)))
(add-to-list 'display-buffer-alist '(".*tex$" (display-buffer-in-previous-window)))); 默认在原来的窗口中打开 tex 文件
(progn
(add-to-list 'display-buffer-alist '(".*pdf$" (display-buffer-in-previous-window)))))
org-roam
相关窗口管理
;; org-roam 默认在右侧打开
(add-to-list 'display-buffer-alist
'("\\*org-roam\\*"
(display-buffer-in-direction)
(direction . right)
(window-width . 0.33)
(window-height . fit-window-to-buffer)))
org-capture
相关窗口管理
;; org-roam capture 与 *Org-Select* 默认右侧打开
(add-to-list 'display-buffer-alist '("\\(^CAPTURE.*\.org$\\|\\*Org.*Select\\*$\\)"
(display-buffer-in-side-window)
(side . right)
(slot . 0)
(window-width . 60)))
(use-package ace-window
:defer 2
:bind ("M-o" . ace-window)
:custom
(aw-scope 'global)
(aw-keys '(?a ?s ?d ?f ?g ?h ?j ?k ?l))
:config
(ace-window-display-mode 1))
Winner mode
)
(use-package winner
:defer 2
:config
(winner-mode))
(defun my/minibuffer-backward-kill (arg)
"When minibuffer is completing a file name delete up to parent
folder, otherwise delete a word"
(interactive "p")
(if minibuffer-completing-file-name
;; Borrowed from https://github.com/raxod502/selectrum/issues/498#issuecomment-803283608
(if (string-match-p "/." (minibuffer-contents))
(zap-up-to-char (- arg) ?/)
(delete-minibuffer-contents))
(delete-word (- arg))))
(setq completion-ignore-case 't) ; minibuffer 补全忽略大小写
(use-package vertico
:defer 1
:custom
(verticle-cycle t)
:config
(vertico-mode)
:bind (:map minibuffer-local-map
("M-h" . my/minibuffer-backward-kill)))
(use-package marginalia
;; Either bind `marginalia-cycle' globally or only in the minibuffer
:bind (("M-A" . marginalia-cycle)
:map minibuffer-local-map
("M-A" . marginalia-cycle))
:defer 1
:config
(marginalia-mode))
(use-package orderless
:defer 1
:custom
(completion-styles '(orderless basic))
(completion-category-defaults nil)
(completion-category-overrides '((file (styles partial-completion)))))
(use-package which-key
:defer 3
:custom (which-key-idle-delay 1)
:config (which-key-mode))
(use-package helpful
:defer 3
:bind ; 这里更好的选择可能是用 [remap]
(([remap describe-function] . #'helpful-callable)
([remap describe-variable] . #'helpful-variable)
([remap describe-key] . #'helpful-key)
([remap describe-command] . #'helpful-command)
([remap describe-symbol] . #'helpful-symbol)
("C-h C-d" . #'helpful-at-point)
("C-h F" . #'helpful-function))
:config
(add-hook 'helpful-mode-hook 'visual-line-mode)) ; 侧窗显示的帮助界面需要自动换行
(use-package keycast
:demand t
:after doom-modeline
:config
(keycast-header-line-mode 1)) ; 默认在 header 显示
rainbow-delimiters
)
(use-package rainbow-delimiters
:hook (rainbow-delimiters-mode . prog-mode)) ; 在编程模式中启用
;; (setq prettify-symbols-unprettify-at-point my/enable-folding) ; 光标附近自动展开
(use-package company
:hook ((org-mode LaTeX-mode prog-mode) . company-mode) ; 加载 company 的主模式
:custom
(company-minimum-prefix-length 4)
(company-idle-delay 0.3)
(company-tootip-idle-delay 0.5)
(company-tooltip-offset-display 'line)
(company-tooltip-align-annotation t)
(company-show-quick-access t)
(company-backends
'((company-capf :with company-dabbrev-code company-keywords)
(company-dabbrev)
(company-ispell)
(company-files)))
;; dabbrev 不改变大小写
(company-dabbrev-ignore-case nil)
(company-dabbrev-downcase nil)
(company-transformers '(company-sort-by-occurrence company-sort-by-backend-importance))
(company-show-quick-access 'left)
:bind
(:map company-active-map
("M-/" . company-complete)
("<tab>" . company-indent-or-complete-common)
("C-c C-/" . company-other-backend))
:config
(set-face-attribute 'company-tooltip nil :inherit 'fixed-pitch))
(use-package avy
:demand 1
:after general
:config
(my/leader-def
"j" '(:ignore t :which-key "jump")
"jj" '(avy-goto-char :which-key "jump to char")
"jw" '(avy-goto-word-0 :which-key "jump to word")
"jl" '(avy-goto-line :which-key "jump to line")))
(use-package key-chord
:demand t
:custom
(key-chord-two-keys-delay 0.5) ; 在 evil 模式中可以用 "jk" 切换到普通模式
:config
(key-chord-mode 1)
(defun my/restart-keychord-mode ()
(interactive)
(key-chord-mode 0)
(key-chord-mode 1)))
(use-package evil
:defer 1
:after key-chord
:init
(setq evil-want-integration t)
(setq evil-want-keybinding nil) ; 使用 evil-collection 的快捷键
(setq evil-respect-visual-line-mode t) ; j/k 键考虑 visual line; 必须在 evil 加载前设置
:custom
(evil-move-cursor-back nil)
(evil-move-beyond-eol t)
(evil-want-fine-undo t)
:config
(key-chord-define evil-insert-state-map "jk" 'evil-normal-state)
(evil-mode 1))
(use-package evil-collection
:after evil
:demand t
:config
;; (setq evil-collection-mode-list nil)
;; (evil-collection-init '(company compile consult debug diff-hl diff-mode dired dired-sidebar elisp-mode embark eshell ewww helm help helpful lua-mode (magit magit-repos magit-submodule) markdown-mode org org-present org-roam (pdf pdf-view) popup python reftex sh-script (term term ansi-term multi-term) vertico whick-key yaml-mode)))
(evil-collection-init))
在 org
模式中使用 evil
(use-package evil-org
:after org
:hook (org-mode . evil-org-mode)
:config
(require 'evil-org-agenda)
(evil-org-agenda-set-keys)
(general-define-key
:states '(normal motion)
:keymaps 'org-mode-map
"zd" 'org-fold-hide-drawer-toggle)
)
ispell
词典设置
;; 个人词典
(setq my/enchant-personal-dic-en (file-truename "~/.config/enchant/en_US.dic"))
(unless (file-exists-p my/enchant-personal-dic-en)
(setq my/enchant-personal-dic-en nil))
(setq ispell-personal-dictionary my/enchant-personal-dic-en)
;; 主要用于 company-ispell 的拼写补全字典
(setq my/completion-dic-en (file-truename "~/.config/english-words.txt")) ; 主要用于 company-ispell
(if (file-exists-p my/completion-dic-en) ; 这里用 file-truename 转换成绝对路径!
(setq ispell-alternate-dictionary (file-truename my/completion-dic-en)
ispell-complete-word-dict (file-truename my/completion-dic-en)))
flyspell
需要安装 aspell
或 hunspell
. Windows
可通过 msys2
安装 libenchant
及相关字典
(use-package flyspell
:if (or my/is-windows)
:hook (LaTeX-mode org-mode))
https://github.com/minad/jinx
(unless (or my/is-windows ; windows 下 jinx 无法编译
(not my/is-turn-on-experimental))
(use-package jinx
:hook (emacs-startup . global-jinx-mode)
:bind ([remap ispell-word] . jinx-correct) ; 把拼写检查绑定到 flyspell 的 C-$ 上.
:config
(add-to-list 'jinx-exclude-regexps '(t "\\cc")) ; 拼写检查忽略中文
(add-to-list 'jinx-exclude-faces
'(latex-mode font-lock-constant-face ; 不会对 LaTeX 中 label 进行拼写检查.
font-lock-comment-face))))
(use-package hydra)
防止 Windows
用 <user name>~1
命名家目录, 修复一个 preview-latex
的 bug
(if (eq system-type 'windows-nt)
(setq temporary-file-directory "~/AppData/Local/Temp/"))
(setq safe-local-variable-values
'((code . utf-8)
(eval setq-local org-roam-db-location (file-truename "./org-roam.db")) ; 允许多个 org-roam 目录
(eval setq-local org-roam-directory (file-truename "./"))))
(defun my/set-cdlatex-command-alist ()
(setq cdlatex-command-alist
'(("eq" "insert pairs of \\[ \\]" "\\[ ? \\]" cdlatex-position-cursor nil t t)
("Big(" "insert Big ()" "\\Big( ? \\Big" cdlatex-position-cursor nil nil t)
("Big[" "insert Big[" "\\Big[ ? \\Big" cdlatex-position-cursor nil nil t)
("Big\\|" "insert Big \\|" "\\Big\\| ? \\Big\\|" cdlatex-position-cursor nil nil t)
("Big{" "insert Big{}" "\\Big\\{ ? \\Big\\" cdlatex-position-cursor nil nil t)
("Big|" "insert Big|" "\\Big| ? \\Big|" cdlatex-position-cursor nil nil t)
("aali" "insert equation" "\\left\\{\\begin{aligned}\n? \n\\end{aligned}\\right." cdlatex-position-cursor nil nil t)
("alb" "Insert beamer alert block with overlay" "\\begin{alertblock}<+->{ ? } \n\n\\end{alertblock}" cdlatex-position-cursor nil t nil)
("alb*" "Insert beamer alert block without overlay" "\\begin{alertblock}{ ? } \n\n\\end{alertblock}" cdlatex-position-cursor nil t nil)
("big(" "insert big ()" "\\big( ? \\big" cdlatex-position-cursor nil nil t)
("big[" "insert big []" "\\big[ ? \\big" cdlatex-position-cursor nil nil t)
("big\\|" "insert big \\|" "\\big\\| ? \\big\\|" cdlatex-position-cursor nil nil t)
("bigg(" "insert bigg()" "\\bigg( ? \\bigg" cdlatex-position-cursor nil nil t)
("bigg[" "insert bigg[" "\\bigg[ ? \\bigg" cdlatex-position-cursor nil nil t)
("bigg\\|" "insert bigg\\|" "\\bigg\\| ? \\bigg\\|" cdlatex-position-cursor nil nil t)
("bigg{" "insert bigg{}" "\\bigg\\{ ? \\bigg\\" cdlatex-position-cursor nil nil t)
("bigg|" "insert bigg|" "\\bigg| ? \\bigg|" cdlatex-position-cursor nil nil t)
("big{" "insert big {}" "\\big\\{ ? \\big\\" cdlatex-position-cursor nil nil t)
("big|" "insert big|" "\\big| ? \\big|" cdlatex-position-cursor nil nil t)
("blo" "Insert beamer block with overlay" "\\begin{block}<+->{ ? } \n\n\\end{block}" cdlatex-position-cursor nil t nil)
("blo*" "Insert beamer block WITHOUT overlay" "\\begin{block}{ ? } \n\n\\end{block}" cdlatex-position-cursor nil t nil)
("bn" "binomial" "\\binom{?}{}" cdlatex-position-cursor nil nil t)
("capl" "insert \\bigcap\\limits_{}^{}" "\\bigcap\\limits_{?}^{}" cdlatex-position-cursor nil nil t)
("case" "insert cases" "\\begin{cases}\n? & \\\\\n &\n\\end{cases}" cdlatex-position-cursor nil nil t)
("cd" "insert cdots" "\\cdots" nil nil t t)
("cupl" "insert \\bigcup\\limits_{}^{}" "\\bigcup\\limits_{?}^{}" cdlatex-position-cursor nil nil t)
("dd" "insert ddots" "\\ddots" nil nil t t)
("def" "insert definition env" "" cdlatex-environment ("definition") t nil)
("des" "insert description" "" cdlatex-environment ("description") t nil)
("enu*" "insert enu" "\\begin{enumerate}\n\\item ?\n\\end{enumerate}" cdlatex-position-cursor nil t nil)
("equ*" "insert unlabel equation" "" cdlatex-environment ("equation*") t nil)
("exb" "Insert beamer example block with overlay" "\\begin{exampleblock}<+->{ ? } \n\n\\end{exampleblock}" cdlatex-position-cursor nil t nil)
("exb*" "Insert beamer example block without overlay" "\\begin{exampleblock}{ ? } \n\n\\end{exampleblock}" cdlatex-position-cursor nil t nil)
("exe" "Insert exercise" "\\begin{exercise}\n? \n\\end{exercise}" cdlatex-position-cursor nil t nil)
("fra" "insert frame (for beamer)" "" cdlatex-environment ("frame") t nil)
("hhl" "insert \\ \\hline" "\\\\ \\hline" ignore nil t nil)
("hl" "insert \\hline" "\\hline" ignore nil t nil)
("ipenu" "insert in paragraph enumerate" "" cdlatex-environment ("inparaenum") t nil)
("ipite" "insert in paragraph itemize" "" cdlatex-environment ("inparaitem") t nil)
("it" "insert \\item" "\\item?" cdlatex-position-cursor nil t nil)
("ld" "insert ldots" "\\ldots" nil nil t t)
("lem" "insert lemma env" "" cdlatex-environment ("lemma") t nil)
("liml" "insert \\lim\\limits_{}" "\\lim\\limits_{?}" cdlatex-position-cursor nil nil t)
("lr<" "insert bra-ket" "\\langle ? \\rangle" cdlatex-position-cursor nil nil t)
("myenu" "insert in my enumerate for beamer" "" cdlatex-environment ("myenumerate") t nil)
("myite" "insert in my itemize for beamer" "" cdlatex-environment ("myitemize") t nil)
("ons" "" "\\onslide<?>{ }" cdlatex-position-cursor nil t t)
("pa" "insert pause" "\\pause" ignore nil t nil)
("pro" "insert proof env" "" cdlatex-environment ("proof") t nil)
("prodl" "insert \\prod\\limits_{}^{}" " \\prod\\limits_{?}^{}" cdlatex-position-cursor nil nil t)
("prop" "insert proposition" "" cdlatex-environment ("proposition") t nil)
("se" "insert \\{\\}" "\\{ ? \\}" cdlatex-position-cursor nil nil t)
("spl" "insert split" "" cdlatex-environment ("split") nil t)
("st" "stackrel" "\\stackrel{?}{}" cdlatex-position-cursor nil nil t)
("te" "insert text" "\\text{?}" cdlatex-position-cursor nil nil t)
("thm" "insert theorem env" "" cdlatex-environment ("theorem") t nil)
("vd" "insert vdots" "\\vdots" nil nil t t))))
(defun my/set-cdlatex-env-alist ()
(setq cdlatex-env-alist
'(("definition" "\\begin{definition}\n\\label{def:?}\n\n\\end{definition}" nil)
("enumerate" "\\begin{enumerate}[?]\n\\item \n\\end{enumerate}" "\\item ?")
("equation*" "\\begin{equation*}\n? \n\\end{equation*}" nil)
("exercise" "\\begin{exercise}[?]\n\n\\end{exercise}" nil)
("frame" "\\begin{frame}{ ? }\n\n\\end{frame}" nil)
("inparaenum" "\\begin{inparaenum}\n\\item ? \n\\end{inparaenum}" "\\item ?")
("inparaitem" "\\begin{inparaitem}\n\\item ?\n\\end{inparaitem}" "\\item ?")
("lemma" "\\begin{lemma}\n\\label{lem:?}\n\n\\end{lemma}" nil)
("myenumerate" "\\begin{myenumerate}\n\\item ?\n\\end{myenumerate}" "\\item ?")
("myitemize" "\\begin{myitemize}\n\\item ?\n\\end{myitemize}" "\\item ?")
("proof" "\\begin{proof}?\n\n\\end{proof}" nil)
("proposition" "\\begin{proposition}\n\n\\end{proposition}" nil)
("theorem" "\\begin{theorem}\n\\label{thm:?}\n\n\\end{theorem}" nil))))
(defun my/set-cdlatex-math-modify-alist ()
(setq cdlatex-math-modify-alist
'((?t "\\mathbb" "" t nil nil))))
(defun my/set-cdlatex-math-symbol-alist ()
(setq cdlatex-math-symbol-alist
'((?0 ("\\varnothing" "\\emptyset"))
(?1 ("\\ONE" "\\one"))
(?. ("\\cdot" "\\circ"))
(?v ("\\vee" "\\bigvee"))
(?& ("\\wedge" "\\bigwedge"))
(?9 ("\\cap" "\\bigcap" "\\bigoplus"))
(?+ ("\\cup" "\\bigcup" "\\oplus"))
(?- ("\\rightharpoonup" "\\hookrightarrow" "\\circlearrowleft"))
(?= ("\\equiv" "\\Leftrightarrow" "\\Longleftrightarrow"))
(?~ ("\\sim" "\\approx" "\\propto"))
(?L ("\\Lambda" "\\limits"))
(?* ("\\times" "\\otimes" "\\bigotimes"))
(?e ("\\eps" "\\epsilon" "\\exp\\Big( ? \\Big)"))
(?> ("\\mapsto" "\\longrightarrow" "\\rightrightarrows"))
(?< ("\\preceq" "\\leftarrow" "\\longleftarrow"))
(?| ("\\parallel" "\\mid" "\\perp"))
(?S ("\\Sigma" "\\sum_{?}^{}"))
(?{ ("\\subset" "\\prec" "\\subseteq"))
(?} ("\\supset" "\\succ" "\\supseteq")))))
(use-package cdlatex
:straight (:host github :repo "cdominik/cdlatex" )
:defer 10
:after tex ; cdlatex 需要 auctex 中的 texmathp.el
:config
;; 导入 cdlatex 自定义设置
(setq cdlatex-paired-parens "$[{(")
(my/set-cdlatex-math-symbol-alist)
(my/set-cdlatex-math-modify-alist)
(my/set-cdlatex-env-alist)
(my/set-cdlatex-command-alist))
主要使用 AucTeX 及配套插件
(defun my/TeX-fold-config ()
(setq TeX-fold-type-list '(env macro comment)
TeX-fold-env-spec-list '(("[comment]" ("comment")) ("[proof]" ("proof")))
LaTeX-fold-env-spec-list '(("frame" ("frame")))
TeX-fold-macro-spec-list
'(("[f]" ("footnote" "marginpar"))
("[c]" ("cite"))
("[l]" ("label"))
("[r]" ("ref" "pageref" "eqref"))
("[i]" ("index" "glossary"))
("[1]:||*" ("item"))
("..." ("dots"))
("(C)" ("copyright"))
("(R)" ("textregistered"))
("TM" ("texttrademark"))
(1 ("emph" "textit" "textsl" "textmd" "textrm" "textsf" "texttt" "textbf" "textsc" "textup")))))
用 C-x C-e <key>
改变选中文字的字体.
(defun my/TeX-fonts-config ()
(setq LaTeX-font-list
'((?m "\\textmc{" "}" "\\mathmc{" "}")
(?g "\\textgt{" "}" "\\mathgt{" "}")
(?e "\\en{" "}")
(?c "\\cn{" "}")
(?4 "$" "$")
(1 "" "" "\\mathcal{" "}")
(2 "\\textbf{" "}" "\\mathbf{" "}")
(3 "\\textsc{" "}")
(5 "\\emph{" "}")
(6 "\\textsf{" "}" "\\mathsf{" "}")
(9 "\\textit{" "}" "\\mathit{" "}")
(12 "\\textulc{" "}")
(13 "\\textmd{" "}")
(14 "\\textnormal{" "}" "\\mathnormal{" "}")
(18 "\\textrm{" "}" "\\mathrm{" "}")
(19 "\\textsl{" "}" "\\mathbb{" "}")
(20 "\\texttt{" "}" "\\mathtt{" "}")
(21 "\\textup{" "}")
(23 "\\textsw{" "}")
(4 "" "" t))))
(defun my/preview-latex-config ()
(setq preview-default-option-list
'("displaymath" "floats" "graphics" "textmath" "footnotes") ; 执行预览的环境
preview-preserve-counters t ; 保留数学公式编号
preview-pdf-color-adjust-method 'compatible)) ; 预览图片使用Emacs主题背景色
(defun my/reftex-config ()
(setq reftex-label-alist ; 交叉引用的自定义类型
'((nil ?e nil "\\cref{%s}" nil nil) ; 与 cref 配合使用.
("theorem" ?t "thm:" nil t ("Theorem" "定理"))
("proposition" ?p "prop:" nil t ("Proposition" "命题"))
("definition" ?d "def:" nil t ("Definition" ))
("lemma" ?a "lem:" nil t ("Lemma" "引理")))
reftex-insert-label-flags '("s" "sftpd")
reftex-ref-macro-prompt nil ; ~cte<tab>~ 后不提示类型
reftex-ref-style-default-list '("Cleveref"))) ; 默认引用风格 Used to "Default"
查找Unicode编码: https://en.wikipedia.org/wiki/Mathematical_operators_and_symbols_in_Unicode
(defun my/more-prettified-symbols ()
(require 'tex-mode) ; 载入 tex--prettify-symbols-alist 变量
(mapc (lambda (pair) (delete pair tex--prettify-symbols-alist))
'(("\\supset" . 8835)))
(mapc (lambda (pair) (cl-pushnew pair tex--prettify-symbols-alist))
'(("\\big(" . #x2987) ; Notation left image bracket
("\\big)" . #x2988)
("\\Big(" . #x2985) ; left white parenthesis
("\\Big)" . #x2986)
("\\bigg(" . #xFF5F) ; full width left white parenthesis
("\\bigg)" . #xFF60)
("\\big[" . #x3010) ; full width left square bracket
("\\big]" . #x3011)
("\\Big[" . #x27E6) ; math left white square bracket
("\\Big]" . #x27E7)
("\\bigg[" . #x301A) ; left white square bracket
("\\bigg]" . #x301B)
("\\{" . #xFF5B) ; full width curly bracket
("\\}" . #xFF5D)
("\\big\\{" . #xFF5B) ;
("\\big\\}" . #xFF5D)
("\\Big\\{" . #xFF5B) ; white bracket
("\\Big\\}" . #xFF5D)
("\\bigg\\{" . #xFF5B) ; white bracket
("\\bigg\\}" . #xFF5D)
("\\Z" . 8484)
("\\Q" . 8474)
("\\N" . 8469)
("\\R" . 8477)
("\\eps" . 949)
("\\inf" . #x22C0)
("\\sup". #x22C1)
("\\ONE" . #x1D7D9)
("\\mathbb{S}" . #x1D54A)
("\\PP" . #x2119)
("\\Ps" . #x1D5AF )
("\\Pp" . #x1D40F)
("\\E" . #x1D5A4)
("\\Ee" . #x1D404)
("\\EE" . #x1D53C )
("\\Fc" . #x2131)
("\\Nc" . #x1D4A9))))
(use-package outline
:init
(if my/is-windows
(setq outline-minor-mode-prefix (kbd "C-o"))
(setq outline-minor-mode-prefix (kbd "C-'")))
:bind
(:map outline-minor-mode-map
("C-' t" . outline-hide-body)
("C-' e" . outline-show-entry)
("C-' p" . outline-previous-visible-heading)
("C-' n" . outline-next-visible-heading)
("C-' a" . outline-show-all)))
(defun my/latex-hook ()
(turn-on-cdlatex)
(turn-on-reftex)
(outline-minor-mode) ; 大纲预览
(outline-hide-body) ; 启动时折叠文件
(when my/enable-folding
(prettify-symbols-mode t))) ; prettify 数学符号
(defun pdf-util-frame-scale-factor () 2)
(use-package pdf-tools
:mode ("\\.pdf\\'" . pdf-view-mode) ; pdf 文件默认打开方式
:bind
(:map pdf-view-mode-map
("d" . pdf-view-next-page-command)
("a" . pdf-view-previous-page-command)
("s" . pdf-view-scroll-up-or-next-page)
("w" . pdf-view-scroll-down-or-previous-page)
:map pdf-history-minor-mode-map
("b" . pdf-history-backward)
:map pdf-annot-minor-mode-map
("C-a a" . pdf-annot-add-highlight-markup-annotation)
("C-a s" . pdf-annot-add-squiggly-markup-annotation)
("C-a u" . pdf-annot-add-underline-markup-annotation)
("C-a d" . pdf-annot-delete))
:config
(pdf-tools-install)
(require 'pdf-annot) ; 设置 pdf-annot-mimor-mode-map 必须
(require 'pdf-history) ; 设置 pdf-history-minor-mode-map 必须
(add-hook 'pdf-view-mode-hook 'pdf-view-fit-width-to-window) ; 默认适应页宽
)
(defun my/set-latex-font ()
(interactive)
(require 'font-latex)
(unless my/is-terminal
(set-face-attribute 'font-latex-math-face nil :foreground "#f78c6c" :font my/math-font :height 1.15)) ; 数学符号
(set-face-attribute 'font-latex-script-char-face nil :foreground "#c792ea") ; 上下标字符^与_
(set-face-attribute 'font-latex-sedate-face nil :foreground "#ffcb6b")) ; 关键字
(use-package tex
:defer 10
:straight auctex
:custom
(TeX-parse-self t) ; 自动解析 tex 文件found
(TeX-PDF-mode t)
(TeX-DVI-via-PDFTeX t)
;; (TeX-PDF-from-DVI "Dvips") ; for preview latex, see https://www.reddit.com/r/emacs/comments/bsoko7/comment/eor96mj/
;; 正向与反向搜索设置
(TeX-source-correlate-mode t)
(TeX-source-correlate-method 'synctex)
(TeX-view-program-selection '((output-pdf "PDF Tools"))) ; 使用 pdf-tools 预览 pdf
(TeX-source-correlate-start-server t)
:config
;; 设置 LaTeX 语法高亮颜色及字体大小
(setq-default TeX-master t) ; 默认询问主文件
(add-hook 'LaTeX-mode-hook 'my/latex-hook) ; 加载LaTeX模式设置
(add-hook 'TeX-after-compilation-finished-functions
#'TeX-revert-document-buffer) ; 编译后更新 pdf 文件
(my/TeX-fold-config)
(my/TeX-fonts-config)
(my/preview-latex-config)
(my/reftex-config)
(my/more-prettified-symbols))
(use-package auctex-latexmk
:straight (auctex-latexmk :fetcher github :repo "emacsmirror/auctex-latexmk") ; fix a incompatibility bug by non-author.
:defer 5
:after tex
:init
(auctex-latexmk-setup)
:config
(setq auctex-latexmk-inherit-TeX-PDF-mode t)
(add-to-list 'TeX-command-list
'("myLatexMK" "latexmk %(-PDF)%S%(mode) %(file-line-error) -pvc %(extraopts) %t" TeX-run-latexmk nil (plain-tex-mode latex-mode doctex-mode) :help "Run LatexMK with -pvc")))
(use-package org-modern-indent
:straight (:host github :repo "jdtsmith/org-modern-indent")
:config
(add-hook 'org-mode-hook #'org-modern-indent-mode 90))
(use-package org-modern ;; 安卓下 Droid Sans Mono 字体不能显示 bullet. 最好安装 Iosevka Aile 字体.
:custom
(org-modern-hide-stars nil) ; adds extra indentation
(org-modern-table nil)
(org-modern-list
'((?- . "•")
(?* . "•")
(?+ . "•")))
:init
(global-org-modern-mode))
org-appear
)
(use-package org-appear
:after org
:hook (org-mode . org-appear-mode))
org-face
相关)
(defun my/set-org-font ()
(interactive)
;; org 字体美化
(require 'org-faces)
;; 标题字体大小优化
(set-face-attribute 'org-document-title nil :weight 'bold :height 1.2)
(dolist (face '((org-level-1 . 1.05)
(org-level-2 . 1.0)
(org-level-3 . 1.0)
(org-level-4 . 1.0)
(org-level-5 . 1.0)
(org-level-6 . 1.0)
(org-level-7 . 1.0)
(org-level-8 . 1.0)))
(set-face-attribute (car face) nil :weight 'medium :height (cdr face)))
(set-face-attribute 'org-block nil :foreground 'unspecified' :inherit 'fixed-pitch)
(set-face-attribute 'org-block-begin-line nil :foreground 'unspecified' :inherit '(font-lock-comment-face fixed-pitch))
(set-face-attribute 'org-block-end-line nil :foreground 'unspecified' :inherit '(font-lock-comment-face fixed-pitch))
(set-face-attribute 'org-property-value nil :inherit '(font-lock-comment-face fixed-pitch))
(set-face-attribute 'org-code nil :inherit '(shadow fixed-pitch))
(set-face-attribute 'org-verbatim nil :inherit '(shadow fixed-pitch))
(set-face-attribute 'org-special-keyword nil :inherit '(font-lock-comment-face fixed-pitch))
(set-face-attribute 'org-meta-line nil :inherit '(font-lock-comment-face fixed-pitch))
(set-face-attribute 'org-checkbox nil :inherit 'fixed-pitch)
(set-face-attribute 'org-drawer nil :inherit '(font-lock-comment-face fixed-pitch))
(set-face-attribute 'org-document-info-keyword nil :inherit '(font-lock-comment-face fixed-pitch))
(set-face-attribute 'org-table nil :inherit 'fixed-pitch)
(setq org-fontify-quote-and-verse-blocks t) ; 启用 org-qoute 变量为 quote 设置不同的字体
(set-face-attribute 'org-quote nil :inherit 'fixed-pitch)
(require 'org-indent) ;; 开启 org-indent 并设设置缩进字体
(set-face-attribute 'org-indent nil :inherit '(org-hide fixed-pitch)))
visual-fill-column
)
(defun my/org-mode-visual-fill ()
(interactive)
(setq visual-fill-column-width 150
visual-fill-column-center-text t)
(visual-fill-column-mode 1))
(use-package visual-fill-column
:hook (org-mode . my/org-mode-visual-fill))
LaTeX
语法高亮相关
(defun my/org-view-latex ()
(interactive)
(setq org-format-latex-options
`(:foreground default :background default :scale ,my/latex-preview-scale :html-foreground "Black" :html-background "Transparent" :html-scale ,my/latex-preview-scale :matchers ("begin" "$1" "$" "$$" "\\(" "\\[")) ; 公式预览设置
;; 以下为 LaTeX 语法高亮设置
org-highlight-latex-and-related '(native latex entities)
org-pretty-entities my/enable-folding
org-pretty-entities-include-sub-superscripts nil))
org-preview
)
(use-package org-fragtog
:hook (org-mode . org-fragtog-mode))
;; 快速编译数学公式, 测试版
(use-package org-preview
:straight (:host github :repo "karthink/org-preview")
:hook (org-mode . org-preview-mode))
;; 在 ~/texmf/tex/latex/ 下的 .sty 文件
(setq org-latex-packages-alist '(("" "mypreamble" t)
("" "mysymbol" t)))
org-tempo
模板设置
(defun my/org-tempo-setting ()
(interactive)
(require 'org-tempo) ; 保证 org-structure-template-alist 可用
(setq org-structure-template-alist ; 用 org-tempo 快速插入代码块
'(("el" . "src elisp")
("la" . "src latex")
("sh" . "src shell")
("a" . "export ascii")
("c" . "center")
("C" . "comment")
("e" . "example")
("E" . "export")
("h" . "export html")
("l" . "export latex")
("q" . "quote")
("s" . "src")
("v" . "verse"))))
org
中截图 (org-download
)
(unless my/is-android
;; 用文件名作为文件夹
(defun my/org-download-method (link)
(let ((filename
(file-name-nondirectory
(car (url-path-and-query
(url-generic-parse-url link)))))
(dirname (concat "./img/" (file-name-sans-extension (file-name-nondirectory (buffer-file-name))))))
(setq org-download-image-dir dirname)
(make-directory dirname t)
(expand-file-name (funcall org-download-file-format-function filename) dirname)))
;; 在 Windows 系统下修复过时的convert.exe; 注意: 用户名文件夹不能含有空格!
(defun my/org-download-clipboard-windows ()
(interactive)
(let ((filename (expand-file-name "screenshot.png" temporary-file-directory)))
(shell-command-to-string (format "magick clipboard: %s" filename))
(when (file-exists-p filename)
(org-download-image filename)
(delete-file filename))))
;; 在 WSL 中复制 Windows 剪贴板图片
(defun my/org-download-clipboard-WSL ()
(interactive)
(let ((filename (expand-file-name "screenshot.png" "/tmp/")))
(shell-command-to-string (format "/mnt/c/msys64/mingw64/bin/magick.exe clipboard: %s" filename)) ; 这是我的 magick.exe 安装位置
(when (file-exists-p filename)
(org-download-image filename)
(delete-file filename))))
(defun my/org-download-clipboard ()
(interactive)
(cond (my/is-windows (my/org-download-clipboard-windows))
(my/is-WSL (my/org-download-clipboard-WSL))
(t (org-download-clipboard)))) ; for Linux system
(use-package org-download
:custom
(org-download-heading-lvl 1) ; 以一级标题作为图片文件夹
(org-download-method #'my/org-download-method)
:after org
:bind (:map org-mode-map
("C-c i y" . org-download-yank)
("C-c i d" . org-download-delete)
("C-c i e" . org-download-edit)
("C-M-y" . my/org-download-clipboard))))
org-table
中文对齐 (valign
)
(use-package valign
:if (display-graphic-p)
:after org
:hook (org-mode . valign-mode))
(defun my/follow-link-at-current-window ()
(interactive)
(let ((org-link-frame-setup (quote ((vm . vm-visit-folder-other-frame)
(vm-imap . vm-visit-imap-folder-other-frame)
(gnus . gnus)
(file . find-file)
(wl . wl-other-frame)))))
(org-open-at-point)))
(defun my/follow-link-at-current-window-mouse (event)
(interactive (list last-command-event))
(posn-set-point (event-end event))
(let ((org-link-frame-setup (quote ((vm . vm-visit-folder-other-frame)
(vm-imap . vm-visit-imap-folder-other-frame)
(gnus . gnus)
(file . find-file)
(wl . wl-other-frame)))))
(org-open-at-point)))
$
及括号
(defun my/insert-inline-OCDL ()
(interactive)
(insert "\\(")
(save-excursion (insert "\\)" )))
(defun my/insert-dollar-OCDL ()
(interactive)
(insert "$")
(save-excursion (insert "$" )))
(defun my/insert-bra-OCDL ()
(interactive)
(insert "(")
(save-excursion (insert ")" )))
(defun my/insert-sq-bra-OCDL ()
(interactive)
(insert "[")
(save-excursion (insert "]" )))
(defun my/insert-curly-bra-OCDL ()
(interactive)
(insert "{")
(save-excursion (insert "}" )))
(defun my/insert-backquote ()
(interactive)
(insert "`"))
(defun my/set-org-cdlatex-extra-kbd ()
(interactive)
(my/insert-leader-def
:keymaps 'org-cdlatex-mode-map
"$" '(my/insert-inline-OCDL :which-key "insert \\\( \\\)")
"`" '(my/insert-backquote :which-key "insert `"))
(general-define-key
:states '(insert emacs)
:keymaps 'org-cdlatex-mode-map
"$" 'my/insert-inline-OCDL
"(" 'my/insert-bra-OCDL
"[" 'my/insert-sq-bra-OCDL
"{" 'my/insert-curly-bra-OCDL))
org-mode-hook
(defun my-org-hook ()
(org-indent-mode) ; 自动缩进
(unless (or (< (display-pixel-height) 999) my/is-terminal)
(variable-pitch-mode 1)) ; 比例字体
(org-cdlatex-mode) ; LaTeX 公式
(visual-line-mode 1))
(use-package org
:defer 10
:custom
(org-M-RET-may-split-line t)
(org-priority-lowest ?E) ; org-agenda 的优先级设为A-E
(org-priority-default ?D) ; org-agenda 的默认优先级设为D
;; (org-startup-with-latex-preview t) ; 设为 t 则创建新笔记时会出错.
:bind
(:map org-mode-map
("C-c p" . nil) ; 用于 popper 快捷键
("C-c n" . nil) ; 用于 org-roam 快捷键
("C-c o" . my/follow-link-at-current-window) ; 在当前窗口打开 org 文件
("C-<down-mouse-1>" . my/follow-link-at-current-window-mouse) ; Ctrl+鼠标点击时, 在当前窗口打开 org 文件
("C-<drag-mouse-1>" . my/follow-link-at-current-window-mouse))
:config
(unless my/is-android
(require 'org-download)
(setq org-ellipsis " ▾")); 用小箭头代替...表示折叠
(if t ; my/enable-folding
(setq org-startup-folded 'content) ; 开启时折叠大纲
(setq org-startup-folded 'showeverything))
(unless my/is-terminal
(my/set-org-font))
(my/org-view-latex)
(my/org-tempo-setting)
(my/set-org-cdlatex-extra-kbd)
(add-hook 'org-mode-hook 'my-org-hook)
(add-to-list 'org-babel-load-languages '(shell . t)))
org-present
)
(use-package org-present
:config
(defun my/org-present-prepare-slide (buffer-name heading)
(org-overview) ; 仅显示顶层标题Show only top-level headlines
(org-show-entry); 展开当前标题Unfold the current entry
(org-show-children)) ; 显示当前子标题
(defun my/org-present-start () ; 开始幻灯片的设置
(turn-off-evil-mode)
(setq visual-fill-column-width 110
visual-fill-column-center-text t) ; 调整显示界面
;; 调整字体大小
(setq-local face-remapping-alist '((default (:height 1.5) variable-pitch)
(header-line (:height 4.0) variable-pitch)
(org-document-title (:height 1.75) org-document-title)
(org-code (:height 1.55) org-code)
(org-verbatim (:height 1.55) org-verbatim)
(org-block (:height 1.25) org-block)
(org-block-begin-line (:height 0.7) org-block)))
(setq header-line-format " ") ; 在标题前加入空行
(display-line-numbers-mode 0)
(org-display-inline-images) ; 显示图片
(read-only-mode 1)) ; 只读模式
(defun my/org-present-end () ; 重置上述设置
(setq-local face-remapping-alist
'((default variable-pitch default)))
(setq header-line-format nil)
(org-remove-inline-images)
(org-present-small)
(read-only-mode 0)
(display-line-numbers-mode 1)
(turn-on-evil-mode))
(add-hook 'org-present-mode-hook 'my/org-present-start)
(add-hook 'org-present-mode-quit-hook 'my/org-present-end)
(add-hook 'org-present-after-navigate-functions 'my/org-present-prepare-slide))
(use-package org-ref
:bind (:map org-mode-map
("C-c (". org-ref-insert-label-link)
("C-c )". org-ref-insert-ref-link)))
(use-package org-transclusion
:straight (:host github
:repo "nobiot/org-transclusion")
:after org)
org-roam
)许多设置参考了 https://www.youtube.com/watch?v=CUkuyW6hr18 及相关教程
(setq zot_bib "~/Nutstore/1/Nutstore/Zotero-Library/Main.bib"; Zotero .bib 文件
zot_pdf "~/Nutstore/1/Nutstore/Zotero-Library" ; Zotero 同步文件夹
org_notes "~/repos/notes/ref/") ; org-roam 文献笔记目录
(unless (file-exists-p zot_bib) (setq zot_bib nil))
(unless (file-exists-p zot_pdf) (setq zot_pdf nil))
(unless (file-exists-p org_notes) (setq org_ntoes nil)) ; 防止文件不存在而报错
(setq my/daily-note-filename "%<%Y-%m-%d>.org" ; 日记默认文件名
my/daily-note-header "#+title: %<%Y-%m-%d %a>\n#+SETUPFILE: ~/repos/notes/latex-preamble.org\n\n[[roam:%<%Y-%B>]]\n\n") ; 日记文件头
(use-package org-roam
:defer 15
:custom
(org-roam-directory "~/repos/notes/") ; 默认笔记目录
(org-roam-completion-everywhere t)
(org-roam-node-display-template ; 搜索节点信息显示
(concat "${title:*} " (propertize "${tags:10}" 'face 'org-tag)))
(org-roam-db-gc-threshold most-positive-fixnum)
(org-roam-dailies-directory "daily/") ; 默认日记目录
(org-roam-dailies-capture-templates ; 日记默认模板
`(("d" "default" entry "* %?" ; 普通条目
:target (file+head ,my/daily-note-filename
,my/daily-note-header))
("t" "task" entry "* TODO %?\n %U\n %a\n %i" ; 待办
:if-new (file+head+olp ,my/daily-note-filename
,my/daily-note-header
("Tasks"))
:empty-lines 1)
("j" "journal" entry "* %<%I:%M %p> - Journal :journal:\n\n%?\n\n" ; 研究日志
:if-new (file+head+olp ,my/daily-note-filename
,my/daily-note-header
("Log")))
("m" "meeting" entry "* %<%I:%M %p> - Meeting with %^{whom} :meetings:\n\n%?\n\n"
:if-new (file+head+olp ,my/daily-note-filename
,my/daily-note-header
("Meeting")))))
:bind (("C-c n l" . org-roam-buffer-toggle)
("C-c n f" . org-roam-node-find)
("C-c n c" . org-roam-capture)
("C-c n i" . org-roam-node-insert)
("C-c n I" . org-roam-node-insert-immediate)
("C-c n t" . my/org-roam-capture-task)
("C-c n k" . orb-insert-link)
("C-c n a" . orb-note-actions)
("C-c n d" . my/org-roam-jump-menu/body)
("C-c n P" . my/org-roam-insert-new-project)
("C-c n p" . my/org-roam-find-project)
("C-c n u" . org-roam-ui-mode)
("C-c n j" . org-roam-dailies-capture-today)
:map org-mode-map
("C-M-i" . completion-at-point))
:config
(define-key org-roam-mode-map [mouse-1] (kbd "C-u <return>")) ; org-roam-buffer 界面左键相当于C-u <return>
(setq org-roam-capture-templates ; org-roam 笔记模板
'(("d" "default" plain "- tag :: \n %?" ; 普及模板
:target
(file+head "%<%Y%m%d%H%M%S>-${slug}.org" "#+title: ${title} \n#+SETUPFILE: ./latex-preamble.org")
:unnarrowed t)
("r" "bibliography reference in pdfs" plain ; 文献模板
"#+FILETAGS: reading research \n - tags :: %^{keywords} \n* %^{title}
:PROPERTIES:\n:Custom_ID: %^{citekey}\n:URL: %^{url}\n:AUTHOR: %^{author-or-editor}\n:NOTER_DOCUMENT: ~/Nutstore/1/Nutstore/Zotero-Library/%^{citekey}.pdf\n:NOTER_PAGE:\n:END:"
:target
(file+head "ref/${citekey}.org" "#+title: ${title}\n#+SETUPFILE: ../latex-preamble.org\n"))
("a" "article/post/blog/discussion" plain ; 其它阅读模板
"#+FILETAGS: reading \n- tags :: \n- sources ::\n"
:target
(file+head "article/%<%Y%m%d%H%M%S>-reading-${slug}.org" "#+title: ${title}\n#+SETUPFILE: ../latex-preamble.org\n"))
("s" "Seminar notes" plain "#+FILETAGS: seminar draft\n- title:\n- speaker:\n- event:\n- ref :: \n- tags ::" ; 学术报告模板
:target
(file+head "seminar/%<%Y%m%d>-seminar-${slug}.org" "#+title: ${title}\n#+SETUPFILE: ../latex-preamble.org"))))
(require 'org-roam-dailies)
(org-roam-db-autosync-mode) ; 自动同步数据库
(my/org-roam-refresh-agenda-list) ; 自动收集 project 文件中的待办事项
(add-to-list 'org-after-todo-state-change-hook ; 将完成的待办事项备份至日记
(lambda ()
(when (equal org-state "DONE")
(my/org-roam-copy-todo-to-today)))))
org-roam-ui
自定义 LaTeX 宏命令
(defun my/set-ORUI-latex-macros ()
(setq org-roam-ui-latex-macros
'(("\\C" . "\\mathbb{C}")
("\\Fc" . "\\mathcal{F}")
("\\Nc" . "\\mathcal{N}")
("\\Ps" . "\\mathsf{P}")
("\\Pp" . "\\mathbf{P}")
("\\PP" . "\\mathbb{P}")
("\\E" . "\\mathsf{E}")
("\\Ee" . "\\mathbf{E}")
("\\EE" . "\\mathbb{E}")
("\\ONE" . "\\mathbf{1}")
("\\R" . "\\mathbb{R}")
("\\Z" . "\\mathbb{Z}")
("\\Q" . "\\mathbb{Q}")
("\\N" . "\\mathbb{N}")
("\\eps" . "\\varepsilon")
("\\det" . "\\mathop{det}"))))
org-roam-ui 可以显示节点连接图
(use-package org-roam-ui
:straight
(:host github :repo "org-roam/org-roam-ui" :branch "main" :files ("*.el" "out"))
:after org-roam
:custom
(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)
:config
(my/set-ORUI-latex-macros))
(use-package org-noter
:straight (:host github
:repo "org-noter/org-noter"
:files ("*.el" "modules/*.el"))
:bind
(("C-c n n" . org-noter)
:map org-noter-doc-mode-map
("M-e" . org-noter-insert-precise-note)
("e" . org-noter-insert-note)) ; This is incompatible with evil mode!
:custom
(org-noter-highlight-selected-text t)
(org-noter-notes-search-path '("~/repos/notes/ref/"))
(org-noter-auto-save-last-location t))
导入 Zotero 文献库, 并将文献笔记作为笔记节点
(use-package helm-bibtex
:custom
(bibtex-completion-notes-path org_notes)
(bibtex-completion-bibliography zot_bib)
(bibtex-completion-library-path zot_pdf))
(use-package org-roam-bibtex
:after org-roam
:hook (org-roam-mode . org-roam-bibtex-mode)
:custom
(orb-insert-interface 'helm-bibtex)
(orb-insert-link-description 'citekey)
(orb-preformat-keywords
'("citekey" "title" "url" "author-or-editor" "keywords" "file"))
(orb-process-file-keyword t)
(orb-attached-file-extensions '("pdf")))
(add-hook 'org-roam-mode-hook 'visual-line-mode) ; 自动换行
实现功能:
(defvar my/org-roam-project-template ; 项目笔记模板
'("p" "project" plain "** TODO %?"
:if-new (file+head+olp "%<%Y%m%d%H>-${slug}.org"
"#+title: ${title}\n#+category: ${title}\n#+filetags: Project\n"
("Tasks"))))
(defun my/org-roam-filter-by-tag (tag-name) ; 按 tag 搜索笔记; 需要 lexical binding
(lambda (node)
(member tag-name (org-roam-node-tags node))))
(defun my/org-roam-list-notes-by-tag (tag-name) ; 按 tag 显示笔记
(mapcar #'org-roam-node-file
(seq-filter
(my/org-roam-filter-by-tag tag-name)
(org-roam-node-list))))
(defun my/org-roam-project-finalize-hook ()
"Adds the captured project file to `org-agenda-files' if the
capture was not aborted."
;; Remove the hook since it was added temporarily
(remove-hook 'org-capture-after-finalize-hook #'my/org-roam-project-finalize-hook)
;; Add project file to the agenda list if the capture was confirmed
(unless org-note-abort
(with-current-buffer (org-capture-get :buffer)
(add-to-list 'org-agenda-files (buffer-file-name)))))
(defun my/org-roam-insert-new-project ()
(interactive)
;; Add the project file to the agenda after capture is finished
(add-hook 'org-capture-after-finalize-hook #'my/org-roam-project-finalize-hook)
;; Select a project file to open, creating it if necessary
(org-roam-capture- :node (org-roam-node-read
nil
(my/org-roam-filter-by-tag "Project"))
:templates (list my/org-roam-project-template)))
(defun my/org-roam-find-project ()
(interactive)
;; Add the project file to the agenda after capture is finished
(add-hook 'org-capture-after-finalize-hook #'my/org-roam-project-finalize-hook)
;; Select a project file to open, creating it if necessary
(org-roam-node-find
nil
nil
(my/org-roam-filter-by-tag "Project")))
把项目笔记加入 org-agenda 文件中
(defun my/org-roam-refresh-agenda-list ()
(interactive)
(setq org-agenda-files (my/org-roam-list-notes-by-tag "Project")))
(defun my/org-roam-capture-task ()
(interactive)
;; 新增项目后, 更新 org-agende 文件列表
(add-hook 'org-capture-after-finalize-hook #'my/org-roam-project-finalize-hook)
;; 新增待办
(org-roam-capture- :node (org-roam-node-read
nil
(my/org-roam-filter-by-tag "Project"))
:templates (list my/org-roam-project-template)))
月结/年终总结模板
(defun my/org-roam-goto-month ()
(interactive)
(org-roam-capture- :goto (when (org-roam-node-from-title-or-alias (format-time-string "%Y-%B")) '(4))
:node (org-roam-node-create)
:templates '(("m" "month" plain "\n* Goals\n\n%?* Summary\n\n"
:if-new (file+head "%<%Y-%B>.org"
"#+title: %<%Y-%B>\n#+filetags: Project\n")
:unnarrowed t))))
(defun my/org-roam-goto-year ()
(interactive)
(org-roam-capture- :goto (when (org-roam-node-from-title-or-alias (format-time-string "%Y")) '(4))
:node (org-roam-node-create)
:templates '(("y" "year" plain "\n* Goals\n\n%?* Summary\n\n"
:if-new (file+head "%<%Y>.org"
"#+title: %<%Y>\n#+filetags: Project\n")
:unnarrowed t))))
Hydra 定义的日记界面
(defhydra my/org-roam-jump-menu (:hint nil)
"
^Dailies^ ^Capture^ ^Jump^
^^^^^^^^-------------------------------------------------
_t_: today _T_: today _m_: current month
_r_: tomorrow _R_: tomorrow _e_: current year
_y_: yesterday _Y_: yesterday ^ ^
_d_: date ^ ^ ^ ^
"
("t" org-roam-dailies-goto-today)
("r" org-roam-dailies-goto-tomorrow)
("y" org-roam-dailies-goto-yesterday)
("d" org-roam-dailies-goto-date)
("T" org-roam-dailies-capture-today)
("R" org-roam-dailies-capture-tomorrow)
("Y" org-roam-dailies-capture-yesterday)
("m" my/org-roam-goto-month)
("e" my/org-roam-goto-year)
("c" nil "cancel"))
(defun my/org-roam-copy-todo-to-today ()
(interactive)
(unless (string= (buffer-name) "*habitica*") ; do nothing in habitica buffer
(let ((org-refile-keep t) ; Set this to nil to delete the original!
(org-roam-dailies-capture-templates
'(("t" "tasks" entry "%?"
:if-new (file+head+olp "%<%Y-%m-%d>.org" "#+title: %<%Y-%m-%d>\n" ("Tasks")))))
(org-after-refile-insert-hook #'save-buffer)
today-file
pos)
(save-window-excursion
(org-roam-dailies--capture (current-time) t)
(setq today-file (buffer-file-name))
(setq pos (point)))
;; Only refile if the target file is different than the current file
(unless (equal (file-truename today-file)
(file-truename (buffer-file-name)))
(org-refile nil nil (list "Tasks" today-file nil pos))))))
(defun org-roam-node-insert-immediate (arg &rest args)
(interactive "P")
(let ((args (push arg args))
(org-roam-capture-templates (list (append (car org-roam-capture-templates)
'(:immediate-finish t)))))
(apply #'org-roam-node-insert args)))
(use-package magit
:commands magit-status
:autoload magit-get-current-branch
:custom
(magit-display-buffer-function #'magit-display-buffer-same-window-except-diff-v1))
(use-package perspective
:defer 2
:bind (("C-x C-b" . persp-list-buffers)
("C-x b" . persp-switch-to-buffer*)
("C-M-k" . persp-switch)
("C-M-n" . persp-next)
("C-x k" . persp-kill-buffer*))
:custom
(persp-mode-prefix-key (kbd "C-x x"))
(persp-interactive-completion-function 'ido-completing-read)
(persp-show-modestring 'header)
:config
(setq persp-sort 'created)
(unless (equal persp-mode t) ; to avoid conflict with persp-mode
(persp-mode))
(setq persp-state-default-file (expand-file-name ".persp-save" user-emacs-directory)))
(use-package shell)
More colorful terminal
(use-package eterm-256color
:if (not my/is-termux)
:hook (term-mode . eterm-256color-mode))
(use-package subed
:straight
(:host github :repo "sachac/subed" :files ("subed/*.el"))
:config
;; Remember cursor position between sessions
(add-hook 'subed-mode-hook 'save-place-local-mode)
;; Break lines automatically while typing
(add-hook 'subed-mode-hook 'turn-on-auto-fill)
;; Break lines at 40 characters
(add-hook 'subed-mode-hook (lambda () (setq-local fill-column 100)))
;; Some reasonable defaults
(add-hook 'subed-mode-hook 'subed-enable-pause-while-typing)
;; As the player moves, update the point to show the current subtitle
(add-hook 'subed-mode-hook 'subed-enable-sync-point-to-player)
;; As your point moves in Emacs, update the player to start at the current subtitle
(add-hook 'subed-mode-hook 'subed-enable-sync-player-to-point)
;; Replay subtitles as you adjust their start or stop time with M-[, M-], M-{, or M-}
(add-hook 'subed-mode-hook 'subed-enable-replay-adjusted-subtitle)
;; Loop over subtitles
(add-hook 'subed-mode-hook 'subed-enable-loop-over-current-subtitle)
;; Show characters per second
(add-hook 'subed-mode-hook 'subed-enable-show-cps))
(use-package python-mode)
(use-package cython-mode
:mode "\\.pyx\\'"
:config
(add-hook 'cython-mode-hook #'flycheck-mode))
follow suggestion from https://emacs.stackexchange.com/questions/10065/how-can-i-defer-loading-elpy-using-use-package to defer elpy mode
(use-package elpy
:config
(advice-add 'python-mode :before 'elpy-enable)
(setq elpy-modules
'(elpy-module-company elpy-module-eldoc elpy-module-flymake elpy-module-pyvenv elpy-module-highlight-indentation elpy-module-yasnippet elpy-module-django elpy-module-sane-defaults)))
(use-package yaml-mode
:mode "\\.yml\\'")
(use-package info+
:defer 10)
(use-package auth-source-pass
:config
(auth-source-pass-enable))
(use-package pass)
(use-package esup
:config
(setq esup-depth 0))
(defun efs/display-startup-time ()
(message "Emacs loaded in %s with %d garbage collections."
(format "%.2f seconds"
(float-time
(time-subtract after-init-time before-init-time)))
gcs-done))
(add-hook 'emacs-startup-hook #'efs/display-startup-time)
(use-package shrface
:after eww
:config
(shrface-basic)
(shrface-trial)
(shrface-default-keybindings) ; setup default keybindings
(setq shrface-href-versatile t))
(use-package shr-tag-pre-highlight
:after shr
:config
(add-to-list 'shr-external-rendering-functions
'(pre . shr-tag-pre-highlight)))
(use-package eww
:custom
(eww-retrieve-command nil)
(eww-search-prefix "https://google.com/search?q=")
(shr-use-fonts nil)
:init
(add-hook 'eww-after-render-hook #'shrface-mode)
:config
(add-hook 'eww-mode-hook 'visual-line-mode)
(require 'shrface))
因为 mu4e 设置比较复杂, 这里直接用机器名称判断
(if my/is-termux
(setq my/mu4e-dir "/data/data/com.termux/files/usr/share/emacs/site-lisp/mu4e/")
(setq my/mu4e-dir "/usr/local/share/emacs/site-lisp/mu4e/"))
(setq my/mu4e-setting-file (expand-file-name "lisp/mu4e-setting-file.el" user-emacs-directory))
(setq my/mu4e-enabled (and (file-exists-p my/mu4e-dir)
(file-exists-p my/mu4e-setting-file)))
(when my/mu4e-enabled
;; fix for mu 1.10
(defun mu4e--main-action-str (str &optional func-or-shortcut))
(defun evil-collection-mu4e-update-main-view@override())
(advice-add 'evil-collection-mu4e-update-main-view :override #'evil-collection-mu4e-update-main-view@override)
(use-package mu4e
:straight `(:local-repo ,my/mu4e-dir
:type nil :pre-build ())
:defer 20 ; Wait until 20 seconds after startup
:after (evil-collection auth-source-pass)
:config
;; This is set to 't' to avoid mail syncing issues when using mbsync
(setq mu4e-change-filenames-when-moving t)
;; Refresh mail using isync every 5 minutes
(setq mu4e-update-interval (* 5 60))
(setq mu4e-get-mail-command "mbsync -a")
(setq mu4e-maildir "~/Mail")
;; header view customization
(setq mu4e-view-fields '(:from-or-to :cc :subject :flags :date :maildir :mailing-list :tags :attachments :signature :decryption))
;; 设置 mu4e-context, bookmark, shortcut.
(load-file my/mu4e-setting-file)))
auth-source-pass
Add password-store
to auth-source
(use-package auth-source-pass
:defer 2
:config
(auth-source-pass-enable))
(use-package ox-hugo
:demand t
:after ox
:config
(setq org-hugo-use-code-for-kbd t))
(defun my/set-client-appearance-and-folding ()
(interactive)
(setq my/is-terminal (not window-system))
(setq my/enable-folding window-system)
(my/set-font-size)
(my/set-font (my/get-font-height))
(my/set-window)
(my/set-line-number)
(my/set-latex-font)
(my/org-view-latex)
(my/set-org-font)
(setq org-hide-emphasis-markers nil))
(if (daemonp)
(add-hook 'server-after-make-frame-hook #'my/set-client-appearance-and-folding)
(my/set-client-appearance-and-folding))
(Taken from https://hungyi.net/posts/browse-emacs-urls-wsl/)
(when my/is-WSL
(setq
browse-url-generic-program "/mnt/c/Windows/System32/cmd.exe"
browse-url-generic-args '("/c" "start")
browse-url-browser-function #'browse-url-generic))
popper
)
(when (and my/is-turn-on-experimental
(not my/is-android))
(use-package habitica
:defer 5
:init
(if (file-exists-p (setq my/habitica-credential-file (expand-file-name "habitica-credential.el" user-emacs-directory)))
(load-file my/habitica-credential-file))
:config
;; some partial evil keybindings for habitica
(general-define-key
:states 'normal
:keymaps 'habitica-mode-map
"gr" '(habitica-tasks :which-key "refresh habitica buffer"))
(my/leader-def
:keymaps 'org-mode-map
"h" '(:ignore t :which-key "habitica command")
"hh" '(my/create-habitica-todo-using-headline :which-key "current headline to hab task")
"hf" '(my/habitica-finish-todo-in-org :which-key "finish a habitica todo")
"hg" '(habitica-tasks :which-key "fetch habitica data")
"hn" '(habitica-new-task :which-key "create a new task")
"hu" '(habitica-up-task :which-key "up a habit/finish a task")
"ht" '(my/habitica-finish-todo :which-key "finish a todo (fixed a bug)")
"hx" '(habitica-delete-task :which-key "delete task")
"hi" '(habitica-set-difficulty :which-key "set task difficulty")))
)
完成任务
(defun my/habitica-finish-todo ()
"Try to fix the login bug. Mark the current task as done or todo depending on its current state."
(interactive)
(if (not (habitica-buffer-p))
(message "You must be inside the habitica buffer")
(if (equal (format "%s" (org-element-property :todo-type (org-element-at-point))) "todo")
(org-todo "DONE"))))
在 org-mode
中把当前标题发送至 habitica
(defun my/create-habitica-todo-using-headline (level)
"Create a new todo based on current headline in a common org-file."
(interactive "nEnter the difficulty level, 1 (easy) 2 (medium) 3 (hard): ")
(let* ((headlines (nth 4 (org-heading-components)))
(difficulty (format "%s" (car (nth (- level 1) habitica-difficulty))))
(dif-string (format "%s" (cdr (nth (- level 1) habitica-difficulty)))))
(message "habitica-task-name:%s" headlines)
(habitica--update-properties (habitica-api-create-task "todo" headlines))
(save-excursion
(org-back-to-heading)
(setq id (org-element-property :HABITICA_ID (org-element-at-point)))
(habitica-api-set-difficulty id difficulty)
(setq tags-str (org-make-tag-string (org-get-tags nil t)))
(org-set-tags (format "%shab:%s:" tags-str dif-string))
(org-todo "TODO"))))
在 org-mode
中完成当前 habitica
任务
(defun my/habitica-finish-todo-in-org ()
(interactive)
(if (equal (format "%s" (org-element-property :todo-type (org-element-at-point))) "todo")
(progn (habitica-up-task)
(if habitica-show-streak
(habitica--update-streak 1))
(org-todo "DONE"))
(message "This is not a habitica todo")))
(setq gc-cons-threshold (* 2 1000 1000))
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。