刚毕业的时跟着第一任 leader 学了 Emacs,一直用到现在。也许 Vi/Vim 可能是更实用一些(服务器上随处可见,同事们也大多用它),但我的肌肉记忆已经长在 Emacs 键位上,我尝试熟悉 Vim 这些快捷键, 但是实在无法适应。平时主要还是使用 CLion(我买过最贵的软件, 同时也是最值得),但是远程开发或者简单修改测试, 还是切换成 Emacs, CLion 的 remote 体验非常差。CLion 有默认的 Emacs keymap,可以无缝随意切换。
这份配置奉行”够用就好”:启动快、界面干净、键位比默认的更顺手。尽量使用内置功能解, 只使用了两个插件——neotree 做文件树,undo-tree 支持撤销重做。Spacemacs 这种巨大的配置项目,但对我来说太重了;我更喜欢使用自己能完全看懂的东西。

source: https://github.com/duanfuxiang0/emacs
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Emacs 配置文件 - fuxiang
;; 最后更新: 2022
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 界面外观配置
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 主题设置 - 使用内置的深色主题护眼
(load-theme 'wombat t)
;; 隐藏滚动条
(when (fboundp 'scroll-bar-mode)
(scroll-bar-mode -1))
;; 隐藏菜单栏
(when (fboundp 'menu-bar-mode)
(menu-bar-mode -1))
;; 隐藏工具栏
(when (fboundp 'tool-bar-mode)
(tool-bar-mode -1))
;; 显示行号
(global-display-line-numbers-mode t)
;; 隐藏欢迎界面
(setq inhibit-splash-screen t)
;; 禁用系统蜂鸣声,改用视觉提示
(setq visible-bell t)
;; 设置字体和大小
(set-frame-font "Monaco 20" nil t)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 编辑器行为配置
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 默认使用 ido mode
(ido-mode 1)
;; 让 Ido 接管所有地方
(ido-everywhere 1)
;; 使用 y/n 替代 yes/no
(defalias 'yes-or-no-p 'y-or-n-p)
;; 与系统剪贴板集成 (macOS)
(setq select-enable-clipboard t)
(setq select-enable-primary t)
(setq save-interprogram-paste-before-kill t)
;; macOS 强制使用 pbcopy/pbpaste
(defun copy-to-osx-clipboard (text &optional push)
"Copy TEXT to macOS clipboard using pbcopy."
(let ((process-connection-type nil))
(let ((proc (start-process "pbcopy" "*Messages*" "pbcopy")))
(process-send-string proc text)
(process-send-eof proc))))
(defun paste-from-osx-clipboard ()
"Paste from macOS clipboard using pbpaste."
(shell-command-to-string "pbpaste"))
(setq interprogram-cut-function 'copy-to-osx-clipboard)
(setq interprogram-paste-function 'paste-from-osx-clipboard)
;; 使用空格替代制表符
(setq-default indent-tabs-mode nil)
;; 设置制表符宽度为 2 个空格
(setq tab-width 2)
;; 退出 Emacs 时不需要确认
(setq confirm-kill-emacs nil)
;; 关闭包含进程的 buffer 时不需要确认
(setq kill-buffer-query-functions
(remq 'process-kill-buffer-query-function
kill-buffer-query-functions))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 自动保存和备份配置
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 启用自动保存功能(类似 VSCode 行为)
(setq auto-save-default t)
(setq auto-save-interval 100) ;; 每 100 次按键后自动保存
(setq auto-save-timeout 10) ;; 闲置 10 秒后自动保存
(setq auto-save-file-name-transforms
`((".*" "~/.emacs.d/auto-save-list/" t)))
;; 备份文件配置 - 保存到专用目录
(setq make-backup-files t)
(setq backup-directory-alist '((".*" . "~/.emacs.d/backups/")))
(setq version-control t) ;; 使用版本号管理备份
(setq kept-new-versions 10) ;; 保留最新的 10 个版本
(setq kept-old-versions 0) ;; 不保留旧版本
(setq delete-old-versions t) ;; 自动删除多余的备份
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 鼠标支持配置
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; GUI 模式下的鼠标滚轮支持
(when (fboundp 'mouse-wheel-mode)
(mouse-wheel-mode t))
(setq mouse-wheel-scroll-amount '(1 ((shift) . 1)))
(setq mouse-wheel-progressive-speed nil)
(setq mouse-wheel-follow-mouse t)
;; 终端模式下的鼠标支持
(unless window-system
(require 'mouse)
(xterm-mouse-mode t)
(global-set-key [mouse-4] (lambda ()
(interactive)
(scroll-down 1)))
(global-set-key [mouse-5] (lambda ()
(interactive)
(scroll-up 1)))
(defun track-mouse (e))
(setq mouse-sel-mode t))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 快捷键配置
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 跳转到指定行: Ctrl+c Ctrl+g
(define-key global-map "\C-c\C-g" 'goto-line)
;; Undo/Redo 快捷键
(global-set-key (kbd "C-/") 'undo-tree-undo) ;; Ctrl+/ 撤销
(global-set-key (kbd "C-_") 'undo-tree-undo) ;; Ctrl+Shift+- 撤销(备用)
(global-set-key (kbd "C-?") 'undo-tree-redo) ;; Ctrl+Shift+/ 重做
(global-set-key (kbd "M-z") 'undo-tree-redo) ;; Alt+z 重做(更方便)
;; 上下移动当前行: Meta+上/下方向键
(global-set-key (kbd "M-<up>") 'move-line-up)
(global-set-key (kbd "M-<down>") 'move-line-down)
;; NeoTree 文件树: F8 键切换显示
(global-set-key [f8] 'neotree-toggle)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 自定义功能函数
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 上下移动行的功能实现(支持单行和多行)
;; 参考 move-text.el 实现
(defun move-text-region (start end n)
"向上或向下移动选中区域 N 行."
(let ((line-text (delete-and-extract-region start end)))
(forward-line n)
(let ((start-pos (point)))
(insert line-text)
(setq deactivate-mark nil)
(set-mark start-pos))))
(defun move-text-line-up ()
"向上移动当前行."
(let ((col (current-column)))
(transpose-lines 1)
(forward-line -2)
(move-to-column col)))
(defun move-text-line-down ()
"向下移动当前行."
(let ((col (current-column)))
(forward-line 1)
(transpose-lines 1)
(forward-line -1)
(move-to-column col)))
(defun move-line-up ()
"向上移动当前行或选中的多行."
(interactive)
(if (region-active-p)
(move-text-region (region-beginning) (region-end) -1)
(move-text-line-up)))
(defun move-line-down ()
"向下移动当前行或选中的多行."
(interactive)
(if (region-active-p)
(move-text-region (region-beginning) (region-end) 1)
(move-text-line-down)))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; 外部插件和模式配置
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Org Mode 配置
(setq org-startup-indented t)
;; NeoTree 文件树插件
(add-to-list 'load-path "~/.emacs.d/neotree")
(require 'neotree)
(setq neo-theme (if (display-graphic-p) 'icons 'arrow))
;; Rust 语言
(add-to-list 'load-path "~/.emacs.d/rust-mode")
(autoload 'rust-mode "rust-mode" nil t)
(add-to-list 'auto-mode-alist '("\\.rs\\'" . rust-mode))
;; undo-tree - 提供类似 VSCode 的 undo/redo 功能
(add-to-list 'load-path "~/.emacs.d/undo-tree")
(require 'undo-tree)
(global-undo-tree-mode)
;; undo-tree 配置
(setq undo-tree-auto-save-history t) ;; 自动保存 undo 历史
(setq undo-tree-history-directory-alist '((".*" . "~/.emacs.d/undo-tree-history/")))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Custom 自动生成配置(请勿手动编辑)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(custom-set-variables
;; custom-set-variables was added by Custom.
;; If you edit it by hand, you could mess it up, so be careful.
;; Your init file should contain only one such instance.
;; If there is more than one, they won't work right.
'(word-wrap nil))
(custom-set-faces
;; custom-set-faces was added by Custom.
;; If you edit it by hand, you could mess it up, so be careful.
;; Your init file should contain only one such instance.
;; If there is more than one, they won't work right.
)