Files
.emacs.d/lisp/init-package.el
trogloxene c7352d0460 feat: add dashboard and enhance completion
- Add startup dashboard with recent files and bookmarks
- Enhance corfu with icons and minibuffer transfer
- Add avy-zap, markdown-mode, consult-dir
- Optimize GC settings and editor config
2026-04-02 14:56:29 +08:00

447 lines
14 KiB
EmacsLisp
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
;;; init-package.el --- major packages -*- lexical-binding: t -*-
;;; Commentary:
;;; Code:
(setopt use-package-enable-imenu-support t)
;; 安装gcmh用于管理内存回收
(use-package gcmh
:demand t
:init
(setq gcmh-idle-delay 'auto
gcmh-auto-idle-delay-factor 10
gcmh-high-cons-threshold #x4000000)
:config
(gcmh-mode 1))
(use-package emacs
:hook (((prog-mode markdown-mode conf-mode) . enable-trailing-whitespace))
:init
(setq kill-whole-line t ; Kill line including '\n'
line-move-visual nil
track-eol t ; Keep cursor at end of lines. Require line-move-visual is nil.
set-mark-command-repeat-pop t) ; Repeating C-SPC after popping mark pops it again
;; Visualize TAB, (HARD) SPACE, NEWLINE
(setq-default show-trailing-whitespace nil) ; Don't show trailing whitespace by default
(defun enable-trailing-whitespace ()
"Show trailing spaces and delete on saving."
(setq show-trailing-whitespace t)
(add-hook 'before-save-hook #'delete-trailing-whitespace nil t))
;; Prettify the process list
(with-no-warnings
(defun my/list-processes--prettify ()
"Prettify process list."
(when-let* ((entries tabulated-list-entries))
(setq tabulated-list-entries nil)
(dolist (p (process-list))
(when-let* ((val (cadr (assoc p entries)))
(name (aref val 0))
(pid (aref val 1))
(status (aref val 2))
(status (list status
'face
(if (memq status '(stop exit closed failed))
'error
'success)))
(buf-label (aref val 3))
(tty (list (aref val 4) 'face 'font-lock-doc-face))
(thread (list (aref val 5) 'face 'font-lock-doc-face))
(cmd (list (aref val 6) 'face 'completions-annotations)))
(push (list p (vector name pid status buf-label tty thread cmd))
tabulated-list-entries)))))
(advice-add #'list-processes--refresh :after #'my/list-processes--prettify)))
(use-package restart-emacs)
;; 安装multiple-cursors
(use-package multiple-cursors)
;; 安装crux增强快捷键快捷键配置在init-kbd.el中
(use-package crux)
;; 安装hungry-delete
(use-package hungry-delete)
;; 安装drag-stuff拖动字符
(use-package drag-stuff)
;; 安装which-key快捷键提示
(use-package which-key
:defer 0
:config
(which-key-mode))
;; 安装vertico
(use-package vertico
:init (vertico-mode t))
;; 安装orderless用于模糊搜索
(use-package orderless
:custom (completion-styles '(orderless basic)))
;; 安装marginalia用于命令注释
(use-package marginalia
:init (marginalia-mode))
;; 安装consult增强搜索和其他菜单
(use-package consult
:config
(defun consult-fd-global ()
"Search for all files use fd"
(interactive)
(let ((consult-fd-args "fd -H -I -i -c never --full-path")
(default-directory "~/"))
(consult-fd)))
(if *is-windows*
(progn
(setq consult-locate-args (encode-coding-string "es.exe -i -p -r" 'gbk))
(add-to-list 'process-coding-system-alist '("es" gbk . gbk))))
(when *is-mac*
(setopt consult-locate-args "mdfind -name")))
(use-package consult-dir
:bind (("C-x C-d" . consult-dir)
:map minibuffer-local-completion-map
("C-x C-d" . consult-dir)
("C-x C-j" . consult-dir-jump-file)))
;; embark
(use-package embark
:config (setq prefix-help-command 'embark-prefix-help-command)
:init
(defun my/embark-preview ()
"Previews candidate in vertico buffer, unless it's a consult command."
(interactive)
(unless (bound-and-true-p consult--preview-function)
(save-selected-window
(let ((embark-quit-after-action nil))
(embark-dwim)))))
;; 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))))
(with-no-warnings
(with-eval-after-load 'which-key
(defun embark-which-key-indicator ()
"An embark indicator that displays keymaps using which-key.
The which-key help message will show the type and value of the
current target followed by an ellipsis if there are further
targets."
(lambda (&optional keymap targets prefix)
(if (null keymap)
(which-key--hide-popup-ignore-command)
(which-key--show-keymap
(if (eq (plist-get (car targets) :type) 'embark-become)
"Become"
(format "Act on %s '%s'%s"
(plist-get (car targets) :type)
(embark--truncate-target (plist-get (car targets) :target))
(if (cdr targets) "" "")))
(if prefix
(pcase (lookup-key keymap prefix 'accept-default)
((and (pred keymapp) km) km)
(_ (key-binding prefix 'accept-default)))
keymap)
nil nil t (lambda (binding)
(not (string-suffix-p "-argument" (cdr binding))))))))
(setq embark-indicators
'(embark-which-key-indicator
embark-highlight-indicator
embark-isearch-highlight-indicator))
(defun embark-hide-which-key-indicator (fn &rest args)
"Hide the which-key indicator immediately when using the completing-read prompter."
(which-key--hide-popup-ignore-command)
(let ((embark-indicators
(remq #'embark-which-key-indicator embark-indicators)))
(apply fn args)))
(advice-add #'embark-completing-read-prompter
:around #'embark-hide-which-key-indicator))))
;; 安装embark-consult和wgrep
(use-package embark-consult)
(use-package wgrep)
(with-eval-after-load
'consult
'(with-eval-after-load
'embark
'(progn
(require 'embark-consult)
(add-hook
'embark-collect-mode-hook
#'consult-preview-at-point-mode))))
;; nerd-icon
(use-package nerd-icons)
;; 启用savehist保存命令顺序
(use-package savehist
:hook (after-init . savehist-mode)
:init (setq enable-recursive-minibuffers t
history-length 50
savehist-additional-variables '(mark-ring
global-mark-ring
search-ring
regexp-search-ring
extended-command-history)
savehist-autosave-interval 300))
;; saveplace保存光标位置
(use-package saveplace
:hook (after-init . save-place-mode))
;; undo增强
(use-package undo-fu)
(use-package undo-fu-session
:init (undo-fu-session-global-mode))
;; vundop撤回树
(use-package vundo
:init (setq undo-limit 800000
undo-strong-limit 1200000
undo-outer-limit 12000000))
;; expand-region快速展开选中
(use-package expand-region)
;; ibuffer-projectile
(use-package ibuffer-projectile
:config (add-hook 'ibuffer-hook
(lambda ()
(ibuffer-projectile-set-filter-groups)
(unless (eq ibuffer-sorting-mode 'alphabetic)
(ibuffer-do-sort-by-alphabetic))))
(when (centaur-treesit-available-p)
(defun treesit-mark-bigger-node ()
"Use tree-sitter to mark regions."
(let* ((root (treesit-buffer-root-node))
(node (treesit-node-descendant-for-range root (region-beginning) (region-end)))
(node-start (treesit-node-start node))
(node-end (treesit-node-end node)))
;; Node fits the region exactly. Try its parent node instead.
(when (and (= (region-beginning) node-start) (= (region-end) node-end))
(when-let* ((node (treesit-node-parent node)))
(setq node-start (treesit-node-start node)
node-end (treesit-node-end node))))
(set-mark node-end)
(goto-char node-start)))
(add-to-list 'er/try-expand-list 'treesit-mark-bigger-node)))
;; avy中文支持
(use-package ace-pinyin
:init (ace-pinyin-global-mode +1))
;; avy-zap
(use-package avy-zap
:bind (("M-z" . avy-zap-to-char-dwim)
("M-Z" . avy-zap-up-to-char-dwim)))
;; jinx拼写检查
(unless *is-windows*
(use-package jinx
:hook (org-mode-hook . jinx-mode)
:bind ([remap ispell-word] . jinx-correct)
:config (setq jinx-languages "en_US")
(add-to-list 'jinx-exclude-regexps '(t "\\cc"))
(with-eval-after-load 'jinx
(dolist (range '((#x4E00 . #x9FFF)
(#x3400 . #x4DBF)
(#x3000 . #x303F)
(#xFF00 . #xFFEF)
(#x20000 . #x2A6DF)))
(let ((start (car range))
(end (cdr range)))
(dotimes (i (- end start))
(modify-syntax-entry (+ start i) "_" jinx--syntax-table)))))
(require 'init-jinx)))
;; flycheck
(use-package flycheck
:init
(add-hook 'after-init-hook #'global-flycheck-mode))
;; consult-flycheck
(use-package consult-flycheck)
;; markdown
(use-package markdown-mode
:mode ("README\\.md\\'" . gfm-mode)
:init (setq markdown-command "multimarkdown")
:bind (:map markdown-mode-map
("C-c C-e" . markdown-do)))
;; 安装emms
(use-package emms
:init
;; 设置音乐文件默认目录
(when *is-windows*
(setq emms-source-file-default-directory "F:/luping26-1-11/"))
:config
;; --- 基础设置 ---
(require 'emms-setup)
(emms-all) ; 加载所有稳定功能
;; 使用简单模式的 mpv 播放器
;; 移除默认的 emms-player-mpv
(require 'emms-player-simple)
;; 定义简单的 mpv 播放器
(define-emms-simple-player mpv-simple '(file url streamlist playlist)
(concat "\\.\\("
(mapconcat 'identity
'("mp3" "mp4" "avi" "mkv" "flv" "mov" "wmv" "webm"
"ogg" "ogv" "oga" "ogx"
"flac" "wav" "aac" "m4a" "wma"
"mpg" "mpeg" "mpe" "mpv"
"3gp" "3g2"
"m3u" "pls")
"\\|")
"\\)\\'\\|http[s]?://")
"mpv"
"--force-window=immediate"
"--keep-open=yes"
"--fs=no"
"--quiet")
;; 设置播放器列表
(setq emms-player-list '(emms-player-mpv-simple
emms-player-vlc
emms-player-mplayer))
(setq emms-playlist-default-playlist-name "*EMMS Playlist*")
(setq emms-playlist-buffer-name "*EMMS Playlist*")
;; 使用更快的文件查找方法(windows上需要使用internal)
;; (setq emms-source-file-directory-tree-function 'emms-source-file-directory-tree-find)
(setq emms-source-file-directory-tree-function 'emms-source-file-directory-tree-internal)
;; 使用原生 Elisp 元数据读取器
(setq emms-info-functions '(emms-info-native))
;; 异步读取元数据
(setq emms-info-asynchronously t)
;; 使用更详细的曲目描述
(setq emms-track-description-function #'emms-info-track-description)
;; 模式行设置
(require 'emms-mode-line)
(emms-mode-line-mode 1)
(emms-mode-line-blank) ; 初始为空
;; 自定义模式行格式
(setq emms-mode-line-format " [%s] ")
(setq emms-mode-line-length-limit 60)
;; 播放时间显示
(require 'emms-playing-time)
(emms-playing-time-mode 1)
;; 歌词设置
(require 'emms-lyrics)
(setq emms-lyrics-display-on-modeline t) ; 在模式行显示歌词
(setq emms-lyrics-display-on-minibuffer nil) ; 不在 minibuffer 显示
(setq emms-lyrics-display-buffer nil) ; 不使用专用缓冲区
(setq emms-lyrics-scroll-p t) ; 启用歌词滚动
(setq emms-lyrics-scroll-timer-interval 0.4) ; 滚动间隔
(setq emms-lyrics-dir "~/Music/lyrics") ; 歌词文件目录
(setq emms-lyrics-display-format " %s ") ; 歌词显示格式
(emms-lyrics 1) ; 启用歌词显示
;; 浏览器设置
(require 'emms-browser)
(setq emms-browser-default-browse-type 'artist)
(setq emms-browser-covers nil) ; 禁用封面
;; 浏览器显示格式
(setq emms-browser-info-title-format "%i%n")
(setq emms-browser-playlist-info-title-format "%i%n")
;; 添加浏览器快捷键
(define-key emms-browser-mode-map (kbd "SPC") 'emms-browser-add-tracks-and-play)
;; 缓存设置
(require 'emms-cache)
(emms-cache 1) ; 启用缓存
;; 历史记录
(require 'emms-history)
(add-hook 'emms-player-started-hook #'emms-last-played-update-current)
;; 音量控制
(require 'emms-volume)
;; 在播放列表中使用 +/- 控制音量
(define-key emms-playlist-mode-map (kbd "+") #'emms-volume-raise)
(define-key emms-playlist-mode-map (kbd "-") #'emms-volume-lower)
;; 添加(playlist中的)快捷键
(define-key emms-playlist-mode-map (kbd "SPC") 'emms-pause)
(define-key emms-playlist-mode-map (kbd "N") 'emms-next)
(define-key emms-playlist-mode-map (kbd "P") 'emms-previous)
(define-key emms-playlist-mode-map (kbd "R") 'emms-random)
(define-key emms-playlist-mode-map (kbd "/") 'emms-playlist-limit)
;; 启用标记功能
(require 'emms-mark)
;; 启用播放列表排序
(require 'emms-playlist-sort)
(define-key emms-playlist-mode-map (kbd "S s") 'emms-playlist-sort-map)
;; 启用播放列表限制/过滤
(require 'emms-playlist-limit)
;; 启用标签编辑器
(require 'emms-tag-editor)
;; 启用评分系统
(require 'emms-score)
(emms-score 1)
;; 启动后自动恢复播放列表
;; (add-hook 'after-init-hook 'emms-history-load)
;; 显示加载完成消息
(message "EMMS loaded")
;; 关闭自动连播
(add-hook 'emms-playlist-mode-hook
(lambda ()
(setq emms-single-track t))))
;; 提供 EMMS 快捷启动函数
(defun my-emms-start-browser ()
"Open emms browser."
(interactive)
(emms-browser)
(message "EMMS browser loaded"))
(defun my-emms-play-directory (dir)
"Play all files in directory.."
(interactive "Dchoose a directory: ")
(emms-play-directory-tree dir)
(message "playing: %s" dir))
;; vterm
(unless *is-windows*
(use-package vterm))
(provide 'init-package)
;;; init-package.el ends here