Skip to content

BaoSiZe-bot/.doom.d

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Abalonemacs

概述

“I’m rarely happier than when spending an entire day programming my computer to perform automatically a task that would otherwise take me a good ten seconds to do by hand.” - Douglas Adams

我用 Doom Emacs(以下简称Doom)作为 Emacs 基本配置。这是一个literate配置文件, 指定了Doom的所有配置并包含了文档。如果将这个文件导入到 ~/.doom.d/config.org ,Doom 会在启动或此文件变动时时自动 tangle 此文件中的代码到对应的文件中。

如果你在浏览器中打开这个文件,你可以考虑在 Emacs Org mode 中打开它以获得更好的阅读体验 :).

在更改各种package.el和init.el后,请记得运行 doom sync

这个配置仍在不断优化中,目前启动速度极慢,达 0.7s (在 WSL 中测试)。

灵感

截图

https://raw.githubusercontent.com/BaoSiZe-bot/.doom.d/screenshots/assets/screenshot1.png https://raw.githubusercontent.com/BaoSiZe-bot/.doom.d/screenshots/assets/screenshot2.png https://raw.githubusercontent.com/BaoSiZe-bot/.doom.d/screenshots/assets/screenshot3.png https://raw.githubusercontent.com/BaoSiZe-bot/.doom.d/screenshots/assets/screenshot4.png https://raw.githubusercontent.com/BaoSiZe-bot/.doom.d/screenshots/assets/screenshot5.png https://raw.githubusercontent.com/BaoSiZe-bot/.doom.d/screenshots/assets/screenshot6.png https://raw.githubusercontent.com/BaoSiZe-bot/.doom.d/screenshots/assets/screenshot7.png https://raw.githubusercontent.com/BaoSiZe-bot/.doom.d/screenshots/assets/screenshot8.png https://raw.githubusercontent.com/BaoSiZe-bot/.doom.d/screenshots/assets/screenshot9.png https://raw.githubusercontent.com/BaoSiZe-bot/.doom.d/screenshots/assets/screenshot10.png https://raw.githubusercontent.com/BaoSiZe-bot/.doom.d/screenshots/assets/screenshot11.png https://raw.githubusercontent.com/BaoSiZe-bot/.doom.d/screenshots/assets/screenshot12.png https://raw.githubusercontent.com/BaoSiZe-bot/.doom.d/screenshots/assets/screenshot13.png https://raw.githubusercontent.com/BaoSiZe-bot/.doom.d/screenshots/assets/screenshot14.png https://raw.githubusercontent.com/BaoSiZe-bot/.doom.d/screenshots/assets/screenshot15.png https://raw.githubusercontent.com/BaoSiZe-bot/.doom.d/screenshots/assets/screenshot16.png https://raw.githubusercontent.com/BaoSiZe-bot/.doom.d/screenshots/assets/screenshot17.png

目录

init.el

本部分决定了 Doom 所启用的模块和加载顺序。

这是我个人的配置,不客制化,而我已经熟练了 Doom 的快捷键,所以 Dashboard 对我来说并不重要。

在 C++ 中自动格式化不是个好想法,尤其当设置了自动保存时。

;;; init.el -*- lexical-binding: t; -*-

;; This file controls what Doom modules are enabled and what order they load
;; in. Remember to run 'doom sync' after modifying it!

;; NOTE Press 'SPC h d h' (or 'C-h d h' for non-vim users) to access Doom's
;;      documentation. There you'll find a link to Doom's Module Index where all
;;      of our modules are listed, including what flags they support.

;; NOTE Move your cursor over a module's name (or its flags) and press 'K' (or
;;      'C-c c k' for non-vim users) to view its documentation. This works on
;;      flags as well (those symbols that start with a plus).
;;
;;      Alternatively, press 'gd' (or 'C-c c d') on a module to browse its
;;      directory (for easy access to its source code).
(setq initial-frame-alist '((top . 0.5)
                            (left . 0.5)
                            (width . 0.628)
                            (height . 0.8)
                            (fullscreen)))
(doom! :input
       ;;bidi              ; (tfel ot) thgir etirw uoy gnipleh
       ;;chinese
       ;;japanese
       ;;layout            ; auie,ctsrnm is the superior home row

       :completion
       ;;(company +childframe)          ; the ultimate code completion backend
       (corfu +icons +orderless +dabbrev)    ; complete with cap(f), cape and a flying feather!
       ;;helm              ; the *other* search engine for love and life
       ;;ido               ; the other *other* search engine...
       ;;ivy               ; a search engine for love and life
       (vertico +icons +childframe)    ; the search engine of the future

       :ui
       ;;deft              ; notational velocity for Emacs
       doom                ; what makes DOOM look the way it does
       ;;doom-dashboard    ; a nifty splash screen for Emacs
       ;;doom-quit         ; DOOM quit-message prompts when you quit Emacs
       ;;(emoji +ascii +github)    ; 🙂
       hl-todo             ; highlight TODO/FIXME/NOTE/DEPRECATED/HACK/REVIEW
       indent-guides       ; highlighted indent columns
       ;; ligatures        ; ligatures and symbols to make your code pretty again
       ;; minimap          ; show a map of the code on the side
       modeline            ; snazzy, Atom-inspired modeline, plus API
       nav-flash           ; blink cursor line after big motions
       ;;neotree           ; a project drawer, like NERDTree for vim
       ophints             ; highlight the region an operation acts on
       (popup +defaults)    ; tame sudden yet inevitable temporary windows
       ;;tabs              ; a tab bar for Emacs
       treemacs            ; a project drawer, like neotree but cooler
       unicode             ; extended unicode support for various languages
       (vc-gutter +pretty) ; vcs diff in the fringe
       ;;vi-tilde-fringe   ; fringe tildes to mark beyond EOB
       ;; window-select    ; visually switch windows
       workspaces          ; tab emulation, persistence & separate workspaces
       zen                 ; distraction-free coding or writing

       :editor
       meow                ; come to the dark side, we have cookies
       file-templates      ; auto-snippets for empty files
       fold                ; (nigh) universal code folding
       format              ; automated prettiness
       ;;god               ; run Emacs commands without modifier keys
       ;;lispy             ; vim for lisp, for people who don't like vim
       multiple-cursors    ; editing in many places at once
       ;;objed             ; text object editing for the innocent
       ;;parinfer          ; turn lisp into python, sort of
       ;;rotate-text       ; cycle region at point between text candidates
       snippets            ; my elves. They type so I don't have to
       ;;word-wrap         ; soft wrapping with language-aware indent

       :emacs
       (dired +icons)      ; making dired pretty [functional]
       ;;electric          ; smarter, keyword-based electric-indent
       ;;eww               ; the internet is gross
       (ibuffer +icons)    ; interactive buffer management
       undo                ; persistent, smarter undo for your inevitable mistakes
       vc                  ; version-control and Emacs, sitting in a tree

       :term
       eshell            ; the elisp shell that works everywhere
       ;;shell             ; simple shell REPL for Emacs
       ;;term              ; basic terminal emulator for Emacs
       vterm               ; the best terminal emulation in Emacs

       :checkers
       (syntax +childframe +flymake)             ; tasing you for every semicolon you forget
       ;;(spell +flyspell) ; tasing you for misspelling mispelling
       ;;grammar           ; tasing grammar mistake every you make

       :tools
       ;;ansible
       ;;biblio            ; Writes a PhD for you (citation needed)
       ;;collab            ; buffers with friends
       debugger            ; FIXME stepping through code, to help you add bugs
       ;;direnv
       ;;docker
       editorconfig        ; let someone else argue about tabs vs spaces
       ;;ein               ; tame Jupyter notebooks with emacs
       eval                ; run code, run (also, repls)
       lookup              ; navigate your code and its documentation
       (lsp +eglot)        ; M-x vscode
       magit               ; a git porcelain for Emacs
       ;;make              ; run make tasks from Emacs
       ;;pass              ; password manager for nerds
       ;;pdf               ; pdf enhancements
       ;;prodigy           ; FIXME managing external services & code builders
       ;;terraform         ; infrastructure as code
       ;;tmux              ; an API for interacting with tmux
       ;;tree-sitter       ; syntax and parsing, sitting in a tree...
       ;;upload            ; map local to remote projects via ssh/ftp

       :os
       (:if (featurep :system 'macos) macos)  ; improve compatibility with macOS
       ;; (tty +osc)          ; improve the terminal Emacs experience

       :lang
       ;;agda              ; types of types of types of types...
       ;;beancount         ; mind the GAAP
       ;;(cc +lsp)         ; C > C++ == 1
       ;;clojure           ; java with a lisp
       ;;common-lisp       ; if you've seen one lisp, you've seen them all
       ;;coq               ; proofs-as-programs
       ;;crystal           ; ruby at the speed of c
       ;;csharp            ; unity, .NET, and mono shenanigans
       ;;data              ; config/data formats
       ;;(dart +flutter)   ; paint ui and not much else
       ;;dhall
       ;;elixir            ; erlang done right
       ;;elm               ; care for a cup of TEA?
       emacs-lisp          ; drown in parentheses
       ;;erlang            ; an elegant language for a more civilized age
       ;;ess               ; emacs speaks statistics
       ;;factor
       ;;faust             ; dsp, but you get to keep your soul
       ;;fortran           ; in FORTRAN, GOD is REAL (unless declared INTEGER)
       ;;fsharp            ; ML stands for Microsoft's Language
       ;;fstar             ; (dependent) types and (monadic) effects and Z3
       ;;gdscript          ; the language you waited for
       ;;(go +lsp)         ; the hipster dialect
       ;;(graphql +lsp)    ; Give queries a REST
       ;;(haskell +lsp)    ; a language that's lazier than I am
       ;;hy                ; readability of scheme w/ speed of python
       ;;idris             ; a language you can depend on
       ;;json              ; At least it ain't XML
       ;;(java +lsp)       ; the poster child for carpal tunnel syndrome
       ;;javascript        ; all(hope(abandon(ye(who(enter(here))))))
       ;;julia             ; a better, faster MATLAB
       ;;kotlin            ; a better, slicker Java(Script)
       latex               ; writing papers in Emacs has never been so fun
       ;;lean              ; for folks with too much to prove
       ;;ledger            ; be audit you can be
       ;;lua               ; one-based indices? one-based indices
       (markdown +grip)    ; writing docs for people to ignore
       ;;nim               ; python + lisp at the speed of c
       ;;nix               ; I hereby declare "nix geht mehr!"
       ;;ocaml             ; an objective camel
       (org +pretty)       ; organize your plain life in plain text
       ;;php               ; perl's insecure younger brother
       ;;plantuml          ; diagrams for confusing people more
       ;;graphviz          ; diagrams for confusing yourself even more
       ;;purescript        ; javascript, but functional
       ;;python            ; beautiful is better than ugly
       ;;qt                ; the 'cutest' gui framework ever
       ;;racket            ; a DSL for DSLs
       ;;raku              ; the artist formerly known as perl6
       ;;rest              ; Emacs as a REST client
       ;;rst               ; ReST in peace
       ;;(ruby +rails)     ; 1.step {|i| p "Ruby is #{i.even? ? 'love' : 'life'}"}
       ;;(rust +lsp)       ; Fe2O3.unwrap().unwrap().unwrap().unwrap()
       ;;scala             ; java, but good
       ;;(scheme +guile)   ; a fully conniving family of lisps
       ;;sh                ; she sells {ba,z,fi}sh shells on the C xor
       ;;sml
       ;;solidity          ; do you need a blockchain? No.
       ;;swift             ; who asked for emoji variables?
       ;;terra             ; Earth and Moon in alignment for performance.
       ;;web               ; the tubes
       ;;yaml              ; JSON, but readable
       ;;zig               ; C, but simpler

       :app
       calendar
       ;;emms
       ;;everywhere        ; *leave* Emacs!? You must be joking
       ;;irc               ; how neckbeards socialize
       ;;(rss +org)        ; emacs as an RSS reader

       :email
       ;;(mu4e +org +gmail)
       ;;notmuch
       ;;(wanderlust +gmail)

       :config
       literate
       ;;use-package
       (default +bindings)

       :baosize
       chinese
       ;;awesome-tray
       holo-layer
       eaf
       popweb
       ;;blink-search
       sort-tab
       corfu-english-helper
       color-rg
       ;;nyan
       treesit-context
       symbol-overlay
       winum                          
       super-save
       ;; keyfreq
       ;; emacs-lsp-booster
       colorful-mode
       ;; avy-thing-edit
       super-eglot
       vterm-run
       dape)

config.el

;;; config.el -*- lexical-binding: t; -*-

85%真透明(只透明背景,不透明文字)

(add-to-list 'default-frame-alist '(alpha-background . 85))

nord 主题

(setq doom-theme 'doom-nord-light)

VictorMono & 霞鹜文楷,emoji设置特殊字体

(setq doom-font (font-spec :family "VictorMono Nerd Font" :size 14 :weight 'Regular)
      doom-symbol-font (font-spec :family "LXGW WenKai Mono GB" :size 14 :weight 'Regular)
      doom-variable-pitch-font (font-spec :family "LXGW WenKai Mono GB" :size 14 :weight 'Regular)
      doom-big-font (font-spec :family "VictorMono Nerd Font" :size 16 :weight 'Regular)
      nerd-icons-font-family "VictorMono Nerd Font")
(defun +font-set-emoji (&rest _)
  (set-fontset-font t 'emoji "Noto Color Emoji" nil 'prepend))
(add-hook 'after-setting-font-hook #'+font-set-emoji)

平滑滚动

(when (display-graphic-p)
  (setq mouse-wheel-scroll-amount '(1 ((shift) . hscroll))
        mouse-wheel-scroll-amount-horizontal 1
        mouse-wheel-progressive-speed nil))
(setq scroll-step 1
      scroll-margin 0
      scroll-conservatively 100000
      auto-window-vscroll nil
      scroll-preserve-screen-position t)
(if (fboundp 'pixel-scroll-precision-mode)
    (pixel-scroll-precision-mode t)
  (unless sys/macp
    (use-package good-scroll
      :diminish
      :hook (after-init . good-scroll-mode)
      :bind (([remap next] . good-scroll-up-full-screen)
             ([remap prior] . good-scroll-down-full-screen)))))

Centaur Emacs 中的一些基础设置

(use-package simple
  :hook ((after-init . size-indication-mode)
         (text-mode . visual-line-mode)
         ((prog-mode markdown-mode conf-mode) . enable-trailing-whitespace))
  :init
  (setq column-number-mode t
        line-number-mode t
        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)))

Treesitter 默认的高亮太素了,但是定义多了影响速度,设置一下jit-lock-defer-time

(setq treesit-font-lock-level 4
      major-mode-remap-alist
      '((yaml-mode . yaml-ts-mode)
        (sh-mode . bash-ts-mode)
        (js-mode . js-ts-mode)
        (css-mode . css-ts-mode)
        (c-mode . c-ts-mode)
        (c++-mode . c++-ts-mode)
        (c-or-c++-mode . c-or-c++-ts-mode)
        (python-mode . python-ts-mode)))
(defun my-fontify-variable (node override start end &rest _)
  (let ((parent (treesit-node-parent node)) tyn)
    (catch 'break
      (while parent
        (setq tyn (treesit-node-type parent))
        (cond ((or (equal tyn "call_expression") (equal tyn "template_function"))
               (progn
                 (treesit-fontify-with-override (treesit-node-start node) (treesit-node-end node) 'font-lock-function-call-face override start end)
                 (throw 'break nil))))
        (cond ((or (equal tyn "argument_list") (equal tyn "field_expression")) (progn (setq parent nil) (throw 'break nil))))
        (cond (t (setq parent (treesit-node-parent parent))))))
    (when (not parent) (treesit-fontify-with-override (treesit-node-start node) (treesit-node-end node) 'font-lock-variable-use-face override start end))))
(advice-add 'c-ts-mode--fontify-variable :around (lambda (fn &rest args) (eval `(my-fontify-variable ,@args))))
(defun my-c-font-lock-settings (fn mode)
  (if (eq mode 'cpp)
      `(
        ,@(treesit-font-lock-rules
           :language 'cpp
           :feature 'function
           '((destructor_name (identifier) @font-lock-function-name-face))
           ;; :language mode
           ;; :feature 'property
           ;; '((template_method (field_identifier) @font-lock-function-call-face))
           )
        ,@(funcall fn mode))
    (funcall fn mode)))
(advice-add 'c-ts-mode--font-lock-settings :around 'my-c-font-lock-settings)
;; (add-hook 'meow-insert-mode-hook (lambda () (setq jit-lock-defer-time 0.25)))
;; (add-hook 'meow-normal-mode-hook (lambda () (setq jit-lock-defer-time 0)))

C++ 缩进和调试

(add-hook 'c++-ts-mode-hook (lambda ()
(setq c-basic-offset 4)
(rainbow-delimiters-mode-enable)
(lsp!)
(treesit-context)
(bind-key "C-c d c" #'cpp-gdb 'c++-ts-mode-map)
 (defun cpp-gdb ()
   "open compile and C++ debug"
   (interactive)
   (if buffer-file-name
       (let ((filename (file-name-sans-extension (file-name-nondirectory buffer-file-name))))
         (when (eq 0 (shell-command (concat "g++ -g3 -std=c++17 " buffer-file-name " -o /tmp/cpp-" filename)))
           (gdb (concat "gdb -i=mi /tmp/cpp-" filename))))
     (message "buffer-file-name is nil")))))

键绑定

(bind-keys ("C-c f o" . consult-org-agenda)
           ("C-s" . consult-line))

由于本人使用fish作为默认shell所以要做一点操作才行

(setq shell-file-name (executable-find "bash"))
(setq-default vterm-shell (executable-find "fish"))
(setq-default explicit-shell-file-name (executable-find "fish"))

显示时间

(use-package time
  :init (setq display-time-default-load-average nil
              display-time-format "%H:%M"))
(display-time-mode)

让符号更漂亮

(setq-default prettify-symbols-alist
  '(("[ ]"            . ?)
    ("[-]"            . ?)
    ("[X]"            . ?)
    (":PROPERTIES:"   . ?)
    (":ID:"           . ?🪪)
    (":END:"          . ?🔚)
    ("#+ARCHIVE:"     . ?📦)
    ("#+AUTHOR:"      . ?👤)
    ("#+CREATOR:"     . ?💁)
    ("#+DATE:"        . ?📆)
    ("#+DESCRIPTION:" . ?⸙)
    ("#+EMAIL:"       . ?📧)
    ("#+HEADERS"      . ?☰)
    ("#+OPTIONS:"     . ?⚙)
    ("#+SETUPFILE:"   . ?⚒)
    ("#+TAGS:"        . ?🏷)
    ("#+TITLE:"       . ?📓)
    ("#+BEGIN_SRC"    . ?✎)
    ("#+END_SRC"      . ?□)
    ("#+BEGIN_QUOTE"  . )
    ("#+END_QUOTE"    . )
    ("#+RESULTS:"     . ?💻)
    ("lambda" . )
    ("<-"     . ?←)
    ("->"     . ?→)
    ("->>"    . ?↠)
    ("=>"     . ?⇒)
    ("map"    . ?↦)
    ("/="     . ?≠)
    ("!="     . ?≠)
    ("=="     . ?≡)
    ("<="     . ?≤)
    (">="     . ?≥)
    ("=<<"    . (?= (Br . Bl) ?≪))
    (">>="    . (?≫ (Br . Bl) ?=))
    ("<=<"    . ?↢)
    (">=>"    . ?↣)
    ("&&"     . ?∧)
    ("||"     . ?∨)
    ("not"    . )))
(setq prettify-symbols-unprettify-at-point 'right-edge)
(global-prettify-symbols-mode 1)
(add-hook 'prog-mode-hook #'prettify-symbols-mode)
(add-hook 'org-mode-hook #'+org-pretty-mode)

彩色缩进

(use-package indent-bars
  :custom
  (indent-bars-color '(highlight :face-bg t :blend 0.225))
  (indent-bars-treesit-support t)
  (indent-bars-pattern ".")
  (indent-bars-no-descend-string t)
  (indent-bars-color-by-depth '(:regexp "outline-\\([0-9]+\\)" :blend 1))
  (indent-bars-highlight-current-depth t)
  (indent-bars-pattern "|")  
  (indent-bars-display-on-blank-lines nil)
  (indent-bars-treesit-ignore-blank-lines-types '("module"))
  (indent-bars-prefer-character t)
  (indent-bars-treesit-scope '((python function_definition class_definition for_statement
				                       if_statement with_statement while_statement)))
  :hook ((prog-mode yaml-mode) . indent-bars-mode)
  :config (require 'indent-bars-ts))

支持 FooBar 类 subword 移动

(global-subword-mode)

设置括号匹配,用绿色高亮

(use-package paren
  :custom-face
  (show-paren-match ((((class color) (background light))
                      (:box (:line-width (-1 . -1) :color "gray70")))
                     (((class color) (background dark))
                      (:box (:line-width (-1 . -1) :color "gray50")))))
  :hook (after-init . show-paren-mode)
  :init (setq show-paren-when-point-inside-paren t
              show-paren-when-point-in-periphery t)
  :config
  (setq blink-matching-paren-highlight-offscreen t
        show-paren-context-when-offscreen 'child-frame))

设置 doom-modeline

(setq doom-modeline-major-mode-icon t
      doom-modeline-major-mode-color-icon t)

打开面包屑导航

(when (modulep! :tools lsp +lsp)
  (add-hook 'lsp-mode-hook #'lsp-headerline-breadcrumb-mode))

悬浮窗口

corfu 貌似不应该出现在这里,但是不放这里就没法工作

(standard-display-unicode-special-glyphs) ; 终端中的弹窗不设置会使用ASCII边框
(use-package posframe
    :init
    (defface posframe-border
      `((t (:inherit region)))
      "Face used by the `posframe' border."
      :group 'posframe)
    (defvar posframe-border-width 2
      "Default posframe border width.")
    :config
    (with-no-warnings
      (defun my-posframe--prettify-frame (&rest _)
        (set-face-background 'fringe nil posframe--frame))
      (advice-add #'posframe--create-posframe :after #'my-posframe--prettify-frame)

      (defun posframe-poshandler-frame-center-near-bottom (info)
        (cons (/ (- (plist-get info :parent-frame-width)
                    (plist-get info :posframe-width))
                 2)
              (/ (+ (plist-get info :parent-frame-height)
                    (* 2 (plist-get info :font-height)))
                 2)))))
(use-package! org-modern
  :after org
  :config
  (add-hook 'org-mode-hook #'org-modern-mode))
(use-package transient-posframe
    :defer 2    
    :defines posframe-border-width
    :custom-face
    (transient-posframe ((t (:inherit tooltip))))
    (transient-posframe-border ((t (:inherit posframe-border :background unspecified))))
    :init
    (setq transient-posframe-border-width posframe-border-width
          transient-posframe-min-width 80
          transient-posframe-min-height nil
          transient-posframe-poshandler 'posframe-poshandler-point-frame-center
          transient-posframe-parameters '((left-fringe . 8)
                                          (right-fringe . 8)))
    :config
    (with-no-warnings
      ;; FIXME:https://github.com/yanghaoxie/transient-posframe/issues/5#issuecomment-1974871665
      (defun my-transient-posframe--show-buffer (buffer _alist)
        "Show BUFFER in posframe and we do not use _ALIST at this period."
        (when (posframe-workable-p)
          (let* ((posframe
                      (posframe-show buffer
        		                     :font transient-posframe-font
        		                     :position (point)
        		                     :poshandler transient-posframe-poshandler
        		                     :background-color (face-attribute 'transient-posframe :background nil t)
        		                     :foreground-color (face-attribute 'transient-posframe :foreground nil t)
                                             :initialize #'transient-posframe--initialize
        		                     :min-width transient-posframe-min-width
        		                     :min-height transient-posframe-min-height
        		                     :internal-border-width transient-posframe-border-width
        		                     :internal-border-color (face-attribute 'transient-posframe-border :background nil t)
        		                     :override-parameters transient-posframe-parameters)))
            (frame-selected-window posframe))))
      (advice-add #'transient-posframe--show-buffer :override #'my-transient-posframe--show-buffer)

      (setq transient-mode-line-format nil) ; without line

      (defun transient-posframe--initialize ()
        "Initialize transient posframe."
        (setq window-resize-pixelwise t)
        (setq window-size-fixed nil))

      (defun transient-posframe--resize (window)
        "Resize transient posframe."
        (fit-frame-to-buffer-1 (window-frame window)
                               nil transient-posframe-min-height
                               nil transient-posframe-min-width))
      (advice-add 'transient--fit-window-to-buffer :override #'transient-posframe--resize)

      (defun my-transient-posframe--hide ()
        "Hide transient posframe."
        (posframe-hide transient--buffer-name))
      (advice-add #'transient-posframe--delete :override #'my-transient-posframe--hide))
    (transient-posframe-mode 1))
(setq vertico-posframe-poshandler #'posframe-poshandler-point-window-center
      vertico-posframe-parameters '((left-fringe  . 8)(right-fringe . 8)))
(with-eval-after-load 'xref
    (setq xref-show-xrefs-function #'consult-xref
          xref-show-definitions-function #'consult-xref))
(with-eval-after-load 'corfu
  (global-corfu-mode)
  (bind-keys :map corfu-map
   ("C-SPC"    . corfu-insert-separator)
   ("C-n"      . corfu-next)
   ("C-p"      . corfu-previous)
   ("M-p"      . corfu-popupinfo-scroll-up)
   ("M-n"      . corfu-popupinfo-scroll-down)
   ("M-d"      . corfu-popupinfo-toggle)
   ("RET"      . corfu-insert)
   ("C-x C-k"  . cape-dict)
   ("C-x C-f"  . cape-file)))

简化提示,用 y/n 代替 yes/no ,别再提醒我 “Really kill emacs?” 了。

从 manateelazycat 大佬的配置上抄的,但我并不知道新语法 advice-add 怎么用。

(fset 'yes-or-no-p 'y-or-n-p)
;; (advice-add 'save-buffer-kill-emacs :around (lambda (fn &rest)
;;   (require 'noflet)
;;   (setq confirm-kill-emacs nil)
;;   (noflet (process-list) ad-do-it)))
(defadvice save-buffers-kill-emacs (around no-query-kill-emacs activate)
  "Prevent annoying \"Active processes exist\" query when you quit Emacs."
  (require 'noflet)
  (setq confirm-kill-emacs nil)
  (noflet (process-list) ad-do-it))

自定义Variables和Faces

我不知道这是干嘛用的,但它既然在这里……

(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.
 )
(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.

packages.el

Emacs 核心所需的插件

;; -*- no-byte-compile: t; -*-
;;; packages.el
(unpin! t)
;;(package! vc-msg)
;;(package! power-mode)
;;(package! imenu-list)
(package! org-modern)
(package! noflet)
(package! transient-posframe)
;;(package! cal-china-x)
;;(package! railgun :recipe(:host github :repo "gynamics/railgun.el"))

个人模块

meow

Evil实在是太重了,但我又无法适应Emacs原生按键,就使用轻量级的Meow了

M-x meow-tutor 以学习Meow按键(类似于vim-tutor)

;; -*- no-byte-compile: t; -*-
;;; modules/editor/meow/packages.el

(package! meow)
;;; modules/editor/meow/config.el -*- lexical-binding: t; -*-
(defun meow/setup ()
  (setq meow-use-cursor-position-hack t
        meow-use-clipboard t
        meow-use-enhanced-selection-effect t)
  (bind-keys :map meow-normal-state-keymap
             ("0" . meow-expand-0)
             ("1" . meow-expand-1)
             ("2" . meow-expand-2)
             ("3" . meow-expand-3)
             ("4" . meow-expand-4)
             ("5" . meow-expand-5)
             ("6" . meow-expand-6)
             ("7" . meow-expand-7)
             ("8" . meow-expand-8)
             ("9" . meow-expand-9)
             ("-" . negative-argument)
             (";" . meow-reverse)
             ("," . meow-inner-of-thing)
             ("." . meow-bounds-of-thing)
             ("'" . repeat)))
(defun meow-append-this-line ()
  (interactive)
  (move-end-of-line 1)
  (meow-insert))
(defun meow-insert-this-line ()
  (interactive)
  (move-beginning-of-line 1)
  (meow-insert))
(defun meow/setup-qwerty ()
  (setq meow-cheatsheet-layout meow-cheatsheet-layout-qwerty)
  (meow/setup)
  (bind-keys :map meow-normal-state-keymap
   ("[" . meow-beginning-of-thing)
   ("]" . meow-end-of-thing)
   ("a" . meow-append)
   ("o" . meow-open-below)
   ("A" . meow-append-this-line)
   ("b" . meow-back-word)
   ("B" . meow-back-symbol)
   ("c" . meow-change)
   ("e" . meow-next-word)
   ("E" . meow-next-symbol)
   ("f" . meow-find)
   ("g" . meow-cancel-selection)
   ("G" . meow-grab)
   ("h" . meow-left)
   ("H" . meow-left-expand)
   ("i" . meow-insert)
   ("I" . meow-insert-this-line)
   ("O" . meow-open-above)
   ("j" . meow-next)
   ("J" . meow-next-expand)
   ("k" . meow-prev)
   ("K" . meow-prev-expand)
   ("l" . meow-right)
   ("L" . meow-right-expand)
   ("v" . meow-visit)
   ("m" . meow-join)
   ("n" . meow-search)
   ("%" . meow-block)
   ("p" . meow-yank)
   ("q" . meow-quit)
   ("Q" . meow-goto-line)
   ("r" . meow-replace)
   ("R" . meow-swap-grab)
   ("d" . meow-kill)
   ("t" . meow-till)
   ("u" . meow-undo)
   ("U" . meow-undo-in-selection)
   ("/" . meow-comment)
   ("w" . meow-mark-word)
   ("W" . meow-mark-symbol)
   ("x" . meow-line)
   ("X" . meow-goto-line)
   ("y" . meow-save)
   ("Y" . meow-sync-grab)
   ("z" . meow-pop-selection)))

(use-package meow
  :hook (doom-after-modules-config . meow-global-mode)
  :demand t
  :config
  (meow/setup-qwerty)
  (bind-keys :map meow-keymap ([remap describe-key] . helpful-key))
  (meow-define-keys
   'normal
   '("s" . avy-goto-char)
   '("F" . avy-goto-char-2)))

baosize

awesome-tray

懒猫的底部状态栏,代替 modeline ,与 sort-tab 一样以最小窗口空间占用为理念。

config.el

给默认模块加图标。
;;; modules/baosize/awesome-tray/config.el -*- lexical-binding: t; -*-

显示 lsp-bridge 状态和诊断数目

(defun awesome-tray-lsp-module () (if (not (equal lsp-bridge-mode nil))
  (if (not (equal lsp-bridge-diagnostic-count nil))
      (concat "" (int-to-string lsp-bridge-diagnostic-count))
      "")
  ""))
(defface awesome-tray-module-lsp-face
  '((((background light)) :inherit awesome-tray-orange-face)
    (t :inherit awesome-tray-orange-face))
  "Lsp-bridge face."
  :group 'awesome-tray)

显示当前光标所在函数

(defun awesome-tray-mybelong-module ()
    (let ((origin (if (modulep 'treesit)
      (let ((current-seconds (awesome-tray-current-seconds)))
        (if (or (not (eq (current-buffer) awesome-tray-belong-last-buffer))
                (> (- current-seconds awesome-tray-belong-last-time) awesome-tray-belong-update-duration))
            (progn
              (setq awesome-tray-belong-last-time current-seconds)
              (setq awesome-tray-belong-last-buffer (current-buffer))
              (awesome-tray-update-belong-cache))
          awesome-tray-belong-cache))"")))
        (if (equal origin "") "" (concat "󰡱 " origin))))

显示 meow 状态

(defun awesome-tray-mymeow-module ()
  (let ((origin (with-demoted-errors
      ""
    (if (and (modulep 'meow) awesome-tray-meow-show-mode)
        meow--indicator
      ""))))
    (concat "󰄛" origin)))

显示 Git 状态

(defun awesome-tray-mygit-module ()
  (let ((origin (if (executable-find "git")
      (progn
        (if (not (string= (buffer-file-name) awesome-tray-git-buffer-filename))
            (awesome-tray-git-command-update-cache))
        awesome-tray-git-command-cache)
    "")))
    (if (equal origin "") "" (concat "" origin))))

添加上述模块到 awesome-tray 核心并挂上启动时的钩子

(use-package 'awesome-tray
:defer t
:hook (doom-after-init . awesome-tray-mode)
:custom
(awesome-tray-buffer-read-only-style "󰌾 ")
(awesome-tray-mode-line-active-color "#4ea9e6")
(awesome-tray-belong-update-duration 1)
(awesome-tray-active-modules '("winum"
                               "lsp"
                               "input-method"
                               "mybelong"
                               "mymeow"
                               "file-path"
                               "buffer-read-only"
                               "mygit"
                               "󰥔"
                               "date"
                               "clock"))
(awesome-tray-input-method-local-style "")
:config
(add-to-list 'awesome-tray-module-alist
       '("winum" . (awesome-tray-winum-module awesome-tray-winum-module-face)))
(add-to-list 'awesome-tray-module-alist
       '("mybelong" . (awesome-tray-mybelong-module awesome-tray-module-belong-face)))
(add-to-list 'awesome-tray-module-alist
       '("mymeow" . (awesome-tray-mymeow-module awesome-tray-module-meow-face)))
(add-to-list 'awesome-tray-module-alist
       '("mygit" . (awesome-tray-mygit-module awesome-tray-module-git-face)))
(add-to-list 'awesome-tray-module-alist
       '("lsp" . (awesome-tray-lsp-module awesome-tray-module-lsp-face))))

packages.el

;; -*- no-byte-compile: t; -*-
;;; modules/baosize/awesome-tray/packages.el
(package! awesome-tray
  :recipe (:host github :repo "manateelazycat/awesome-tray"))

blink-search

懒猫的多源搜索,据说很快就可以取代 vertico+consult 全家桶了。

config.el

声明
;;; modules/baosize/blink-search/config.el -*- lexical-binding: t; -*-
(use-package blink-search

由于某种原因, blink-search 不能正常加载,需要指定 load-path

注意如果把 Doom 安装在 ~/.config/emacs 需要更改位置。

:load-path "~/.config/doomemacs/.local/straight/repos/blink-search/"

绑定键位就使用默认的 C-M-g 吧。

:bind (("C-M-g" . blink-search))

进入 blink-search 时肯定得是 meow-insert-mode

:config (add-hook 'blink-search-mode-hook #'meow-insert))

packages.el

;; -*- no-byte-compile: t; -*-
;;; modules/baosize/blink-search/packages.el
(package! blink-search
  :recipe (:host github :repo "manateelazycat/blink-search"))

color-rg

懒猫的搜索插件,类似于 el-search ,但是更易用,更快

config.el

;;; modules/baosize/color-rg/config.el -*- lexical-binding: t; -*-
(use-package color-rg
  :bind
  (("C-c r i" . color-rg-search-input)
   ("C-c r s" . color-rg-search-symbol)
   ("C-c r I" . color-rg-search-input-in-project)
   ("C-c r S" . color-rg-search-symbol-in-project)
   ("C-c r b" . color-rg-search-input-in-current-file)
   ("C-c r j" . color-rg-search-symbol-in-current-file)
   ("C-c r t" . color-rg-search-project-with-type)
   ("C-c r x" . color-rg-search-symbol-with-type)))

packages.el

;; -*- no-byte-compile: t; -*-
;;; modules/baosize/color-rg/packages.el
(package! color-rg
  :recipe (:host github :repo "manateelazycat/color-rg"))

EAF

Emacs Application Frames ,由懒猫开发的使 “Live in Emacs” 成为现实的超级应用框架,也是本配置的核心之一。

config.el

;;; modules/baosize/eaf/config.el -*- lexical-binding: t; -*-

判断是否是终端,是则不加载 EAF 以节省启动时间

(when (and (display-graphic-p) (not (daemonp)))

启动 EAF 框架

(use-package eaf
  :after-call doom-after-init-hook
  :hook
  (eaf-mode . doom-modeline-mode)
  :init
  (bind-keys ("C-c ee" . eaf-open-this-buffer)
             ("C-c ef" . eaf-open)
             ("C-c em" . eaf-open-bookmark)))

启动浏览器(这么大一个包,肯定得懒加载)

(use-package eaf-browser

自定义外观

:custom
;;eaf-browser-dark-mode t
(eaf-browser-default-search-engine "bing")
(eaf-webengine-font-family "VictorMono Nerd Font")
(eaf-webengine-fixed-font-family "VictorMono Nerd Font")
(eaf-webengine-serif-font-family "VictorMono Nerd Font")
(eaf-webengine-font-size 16)
(eaf-webengine-fixed-font-size 16)

自定义搜索引擎

(eaf-browser-search-engines '(("bing" . "https://bing.com/search?q=%s"))
                             ("baidu" . "https://www.baidu.com/search?ie=utf-8&q=%s")
                             ("google" . "http://www.google.com/search?ie=utf-8&q=%s")
                             ("duckduckgo" . "https://duckduckgo.com/?q=%s"))

设置为默认浏览器

(browse-url-browser-function #'eaf-open-browser)

ESC 退出焦点

:config
(eaf-bind-key clear_focus "<escape>" eaf-browser-keybinding)

洛谷小插件😅

(defun luogu-open-problem (pid)
  "打开题目"
  (interactive "M[Luogu] ProblemID: ")
  (eaf-open-browser (concat "https://www.luogu.com.cn/problem/" pid)))
(defun luogu-open-discuss (did)
  "打开讨论"
  (interactive "M[Luogu] DiscussID: ")
  (eaf-open-browser (concat "https://www.luogu.com.cn/discuss/" did)))
(defun luogu-open-training (tid)
  "打开题单"
  (interactive "M[Luogu] TrainingID: ")
  (eaf-open-browser (concat "https://www.luogu.com.cn/training/" tid)))
(defun luogu-open-user-home (uid)
  "打开用户主页"
  (interactive "M[Luogu] UserID: ")
  (eaf-open-browser (concat "https://www.luogu.com.cn/user/" uid)))
(defun luogu-open-contest (cid)
  "打开比赛"
  (interactive "M[Luogu] ContestID: ")
  (eaf-open-browser (concat "https://www.luogu.com.cn/contest/" cid)))
(defun luogu-open-team (teamid)
  "打开团队"
  (interactive "M[Luogu] TeamID: ")
  (eaf-open-browser (concat "https://www.luogu.com.cn/team/" teamid)))

浏览器键绑定

:bind (("C-c e b" . eaf-open-browser)
       ("C-c e h" . eaf-open-browser-with-history)
       ("C-c e B" . eaf-open-browser-other-window)
       ("C-c e s" . eaf-open-browser-same-window)
       ("C-c elc" . luogu-open-contest)
       ("C-c eld" . luogu-open-discuss)
       ("C-c ele" . luogu-open-team)
       ("C-c elp" . luogu-open-problem)
       ("C-c elt" . luogu-open-training)
       ("C-c elu" . luogu-open-user-home)))

启动终端

(use-package eaf-pyqterminal

设置外观

:custom
(eaf-pyqterminal-font-size 16)
(eaf-pyqterminal-font-family "VictorMono Nerd Font")

终端键绑定

:bind (("C-c e t" . eaf-open-pyqterminal)
       ("C-c e i" . eaf-open-ipython)))

文件管理器键绑定

(use-package eaf-file-manager
 :bind (("C-c e /" . eaf-open-in-file-manager)))

启动预览

(use-package eaf-org-previewer
  :after-call org-mode)
(use-package eaf-markdown-previewer
  :after-call (markdown-mode gfm-mode))

目前存在没修好的 bug 的一些包

(with-eval-after-load 'eaf
  (use-package eaf-pdf-viewer))
;; (use-package eaf-git :bind (("C-c e g" . eaf-open-git)))
)

packages.el

;; -*- no-byte-compile: t; -*-
;;; modules/baosize/eaf/packages.el

eaf 需要编译相关依赖

(defun +eaf-install-deps-for-app(app-dir)
  "Install deps from dependencies.json."
  (let* ((deps-dict (with-temp-buffer
                      (insert-file-contents
                       (expand-file-name "dependencies.json" app-dir))
                      (json-parse-string (buffer-string))))
         (pip-deps (gethash (if IS-LINUX "linux" "darwin")
                            (or (gethash "pip" deps-dict)
                                (make-hash-table))))
         (vue-install (gethash "vue_install" deps-dict))
         (npm-install (gethash "npm_install" deps-dict))
         (npm-rebuild (gethash "npm_rebuild" deps-dict)))
    (when pip-deps
      (dolist (pkg (append pip-deps nil))
        (message "%s" (shell-command-to-string (format "pip install %s" pkg)))))
    (when vue-install
      (let ((default-directory app-dir))
        (message "%s" (shell-command-to-string "npm install"))
        (message "%s" (shell-command-to-string "npm run build"))))
    (when npm-install
      (let ((default-directory app-dir))
        (message "%s" (shell-command-to-string "npm install"))))
    (when npm-rebuild
      (let ((default-directory app-dir))
        (message "%s" (shell-command-to-string "npm rebuild"))))))

安装 eaf 核心

(package! eaf
  :recipe (:host github :repo "emacs-eaf/emacs-application-framework"
           :files ("*")
           :post-build
           (shell-command "python install-eaf.py --install-core-deps")))

安装浏览器

(package! eaf-browser
  :recipe (:host github :repo "emacs-eaf/eaf-browser"
           :files ("*")
           :post-build
           (+eaf-install-deps-for-app
            (concat straight-base-dir "/straight/" straight-build-dir "/eaf-browser"))))

安装终端

(package! eaf-pyqterminal
  :recipe (:host github :repo "mumu-lhl/eaf-pyqterminal"
           :files ("*")
           :post-build
           (+eaf-install-deps-for-app
            (concat straight-base-dir "/straight/" straight-build-dir "/eaf-pyqterminal"))))

安装文件管理器

(package! eaf-file-manager
  :recipe (:host github :repo "emacs-eaf/eaf-file-manager"
           :files ("*")
           :post-build
           (+eaf-install-deps-for-app
            (concat straight-base-dir "/straight/" straight-build-dir "/eaf-file-manager"))))

安装预览插件

(package! eaf-org-previewer
 :recipe (:host github :repo "emacs-eaf/eaf-org-previewer"
          :files ("*")
          :post-build
          (+eaf-install-deps-for-app
           (concat straight-base-dir "/straight/" straight-build-dir "/eaf-org-previewer"))))
(package! eaf-markdown-previewer
 :recipe (:host github :repo "emacs-eaf/eaf-markdown-previewer"
          :files ("*")
          :post-build
          (+eaf-install-deps-for-app
           (concat straight-base-dir "/straight/" straight-build-dir "/eaf-markdown-previewer"))))

一些有 bug 的包

(package! eaf-pdf-viewer
 :recipe (:host github :repo "emacs-eaf/eaf-pdf-viewer"
          :files ("*")
          :post-build
          (+eaf-install-deps-for-app
           (concat straight-base-dir "/straight/" straight-build-dir "/eaf-pdf-viewer"))))
;;(package! eaf-git
;;  :recipe (:host github :repo "emacs-eaf/eaf-git"
;;           :files ("*")
;;           :post-build
;;           (+eaf-install-deps-for-app
;;            (concat straight-base-dir "/straight/" straight-build-dir "/eaf-git"))))

holo-layer

懒猫开发的各种特效,没有准 Linux 环境所以目前唯一成功的环境是 wslg+sway

这个模块会破坏 blink-search 的窗口,不建议启用。

config.el

;;; modules/baosize/holo-layer/config.el -*- lexical-binding: t; -*-
(when (and (display-graphic-p) (not (daemonp)))

解决找不到函数的 bug

(add-to-list 'load-path "~/.config/doomemacs/.local/straight/repos/blink-search/backend/")

启动 holo-layer

(use-package holo-layer
  :custom
  (holo-layer-enable-cursor-animation t)
  (holo-layer-enable-type-animation t)
  (holo-layer-cursor-animation-interval 3)
  (holo-layer-cursor-animation-duration 50)
  (holo-layer-enable-window-border t)
  ;; (holo-layer-enable-place-info t)
  (holo-layer-enable-window-number-background t)
  ;; (holo-layer-hide-mode-line t)
  ;; (holo-layer-enable-indent-rainbow t)
  (holo-layer-cursor-color nil)
  (holo-layer-cursor-alpha 255)
  (holo-layer-type-animation-style "supernova")
  (holo-layer-sort-tab-ui t)
  :config
  (holo-layer-enable)))

packages.el

;; -*- no-byte-compile: t; -*-
;;; modules/baosize/holo-layer/packages.el
(package! holo-layer
  :recipe (:host github :repo "manateelazycat/holo-layer"
    :files ("*")
    :build (:not compile)))

sort-tab

懒猫的标签栏,启用 holo-layer 即可显示图标

config.el

;;; modules/baosize/sort-tab/config.el -*- lexical-binding: t; -*-
(use-package sort-tab
  :defer t
  :hook
  (doom-after-init . sort-tab-mode)
  :init
  (bind-keys ("C-c b]" . sort-tab-select-next-tab)
        ("C-c bn" . sort-tab-select-next-tab)
        ("C-<tab>" . sort-tab-select-next-tab)
        ("C-<iso-lefttab>" . sort-tab-select-prev-tab)
        ("C-c b[" . sort-tab-select-prev-tab)
        ("C-c bp" . sort-tab-select-prev-tab)
        ("C-c bl" . sort-tab-select-last-tab)
        ("C-c bK" . sort-tab-close-all-tabs)
        ("C-c bO" . sort-tab-close-other-tabs)
        ("C-c bd" . sort-tab-close-current-tab)
        ("C-c bk" . sort-tab-close-current-tab)))

packages.el

;; -*- no-byte-compile: t; -*-
;;; modules/baosize/sort-tab/packages.el
(package! sort-tab
  :recipe (:host github :repo "manateelazycat/sort-tab"))

popweb

懒猫开发的多媒体弹窗,目前支持预览 LaTeX ,弹出各种翻译。

config.el

指定 load-path
;;; modules/baosize/popweb/config.el -*- lexical-binding: t; -*-
(when (and (display-graphic-p) (not (daemonp)))
;;(add-to-list 'load-path "~/.config/doomemacs/.local/straight/repos/popweb/extension/org-roam")
(add-to-list 'load-path "~/.config/doomemacs/.local/straight/repos/popweb/extension/latex")
(add-to-list 'load-path "~/.config/doomemacs/.local/straight/repos/popweb/extension/dict")
;;(add-to-list 'load-path "~/.config/doomemacs/.local/straight/repos/popweb/extension/color-picker")
;;(add-to-list 'load-path "~/.config/doomemacs/.local/straight/repos/popweb/extension/anki-review")
(add-to-list 'load-path "~/.config/doomemacs/.local/straight/repos/popweb/extension/url-preview")

加载对应应用

(use-package popweb
  :defer t
  :bind
  ("C-c py" . popweb-dict-youdao-input)
  ("C-c pd" . popweb-dict-dictcn-input)
  ("C-c pb" . popweb-dict-bing-input)
  ("C-c pu" . popweb-url-input)
  :config
  (use-package popweb-url)
;;(use-package color-picker)
  (use-package popweb-dict))
(add-hook 'latex-mode-hook #'(lambda () (require 'popweb) (require 'popweb-latex) (popweb-latex-mode))))

packages.el

;; -*- no-byte-compile: t; -*-
;;; modules/baosize/popweb/packages.el
(package! popweb
  :recipe (:host github
           :repo "manateelazycat/popweb"
           :files ("*")))

chinese

设置 emacs-rime 输入法, Rime 在 ~/.local/share/emacs-rime 文件夹中设置。

config.el

;;; modules/baosize/chinese/config.el -*- lexical-binding: t; -*-

使用 ace-pinyin 以支持 avy 跳转到中文

使用 pinyin-lib 以支持 consult 搜索中文

(use-package ace-pinyin
  :after avy
  :init (setq ace-pinyin-use-avy t)
  :config (ace-pinyin-global-mode t))
(use-package pinyinlib
  :commands (pinyinlib-build-regexp-string)
  :init
  (defun orderless-regexp-pinyin (str)
    (setf (car str) (pinyinlib-build-regexp-string (car str)))
    str)
  (advice-add 'orderless-regexp :filter-args #'orderless-regexp-pinyin))

禁用系统输入法 Fcitx5 什么的在 Emacs 上的体验很不好。

; disable gtk im modules for emacs-pgtk, add "Emacs*UseXIM: false" to ~/.Xresources to disable xim
(when (boundp 'pgtk-use-im-context-on-new-connection)
  (setq pgtk-use-im-context-on-new-connection nil))

use-package 声明

(use-package rime

键绑定

:bind
(:map rime-mode-map ("C-`" . #'rime-send-keybinding))

自动切换输入法

:custom
(rime-disable-predicates
    '(rime-predicate-evil-mode-p
         meow-normal-mode-p
         meow-keypad-mode-p
         meow-motion-mode-p
         rime-predicate-hydra-p
         rime-predicate-prog-in-code-p
         rime-predicate-space-after-cc-p
         ;; rime-predicate-org-in-src-block-p
         rime-predicate-org-latex-mode-p
         rime-predicate-punctuation-after-space-cc-p
         rime-predicate-punctuation-after-ascii-p
         rime-predicate-punctuation-line-begin-p
         ;; rime-predicate-space-after-ascii-p
         ;; rime-predicate-space-after-cc-p
         rime-predicate-after-ascii-char-p))

Rime 本身相关设置

;; (rime-share-data-dir
;;  (cl-some (lambda (dir)
;;             (let ((abs-dir (expand-file-name dir)))
;;               (when (file-directory-p abs-dir)
;;                 abs-dir)))
;;           '("/usr/share/rime-data"
;;             "/usr/share/local"
;;             "/usr/share")))
(rime-user-data-dir (expand-file-name "~/.local/share/emacs-rime"))
(rime-show-candidate 'posframe)
(rime-posframe-style 'vertical)

设置默认输入法

(default-input-method "rime")

Org-mode 自启动

:config
(add-hook 'org-mode-hook (lambda () (activate-input-method default-input-method)))

防止堵塞、冻结 Emacs

(add-hook 'kill-emacs-hook (lambda () (ignore-errors (rime-lib-finalize)))))

packages.el

;; -*- no-byte-compile: t; -*-
;;; modules/baosize/chinese/packages.el


(package! rime)
(package! ace-pinyin)
(package! pinyinlib)
(when (modulep! :editor evil) (package! evil-pinyin))

corfu-english-helper

用 corfu 输入英文单词

config.el

;;; modules/baosize/corfu-english-helper/config.el -*- lexical-binding: t; -*-
(use-package corfu-english-helper
  :defer t
  :hook (text-mode . toggle-corfu-english-helper))

packages.el

;; -*- no-byte-compile: t; -*-
;;; modules/baosize/corfu-english-helper/packages.el
(package! corfu-english-helper :recipe(:host github :repo "manateelazycat/corfu-english-helper" :files ("*")))

treesit-context

类似于 Nvim Treesitter Context 的显示代码层级的插件,代码高度借鉴Emacs China

试着整理一下,当学习 Emacs Lisp 了。

定义基本变量,以及文件头

;;; modules/baosize/treesit-context/autoload.el -*- lexical-binding: t; -*-
;;;###autoload
(defgroup treesit-context nil
  "Show the context of the currently visible buffer contents."
  :group 'treesit)
(defvar treesit-context--buffer (generate-new-buffer "*treesit-context-posframe-buffer*")
  "Buffer used to display the context.")
(defvar treesit-context--list nil
  "List used to store the context needs showing.")
(defvar treesit-context--timer nil
  "Timer for updating the context.")

声明显示函数( Emacs Lisp 加载的时候会先读取所有源码,然后在源码中查找定义,也就是说无需计较声明顺序,不像某些 C 语言)

;;;###autoload
(defun treesit-context ()
  "Show code context."
  (interactive)
  (unless (not (treesit-available-p))
    (local-unset-key (kbd "C-g"))
    (local-set-key (kbd "C-g") 'treesit-context-abort)
    ;; (add-hook 'post-command-hook #'treesit-context--update nil 'local)
    (setq treesit-context--timer (run-with-idle-timer 0.1 t 'treesit-context--update))
    (treesit-context--update)))

声明删除窗口的函数(不知道该怎么称呼这东西了)

;;;###autoload
(defun treesit-context-abort ()
  "Abort showing code context."
  (interactive)
  (posframe-hide treesit-context--buffer)
  (local-set-key (kbd "C-g") 'keyboard-quit)
  ;; (kill-buffer treesit-context--buffer)
  ;; (remove-hook 'post-command-hook #'treesit-context--update 'local)
  (when treesit-context--timer
    (cancel-timer treesit-context--timer)))

我们可以显示像 loop,fucntion,condition,class 之类的各种 tree-sitter node ,这个时候我们就要维护一个变量记录我们要显示什么东西了。

;;;###autoload
(defun treesit-context--add-to-list (node)
  "Add the text of the node into `treesit-context--list'."
  (if (or (string= (treesit-node-type node) "struct_specifier")
	      (string= (treesit-node-type node) "function_definition"))
      (progn
	(let* ((text (treesit-node-text node))
	       (buf (generate-new-buffer "*treesit-context-temp-buffer*"))
	       (text-showed nil))
	  (with-current-buffer buf
	    (goto-char (point-min))	    (insert text)
	    (goto-char (point-min))
	    (setq text-showed (buffer-substring
			       (point-min) (line-end-position))))
	  (push text-showed treesit-context--list)
	  (kill-buffer buf)))))

我们需要从 tree-sitter 中查询上下文以显示代码层级。

;;;###autoload
(defun treesit-context--get-context-from-list ()
  "Get the context of `treesit-context--list'"
  (let ((context ""))
    (dolist (text treesit-context--list)
      (setq context (concat context text "\n")))
    context))

光标是会动的,层级是会变化的,窗口是要更新的。

;;;###autoload
(defun treesit-context--update ()
  "Update `treesit-context--ov'."
  (unless (or (minibufferp) (not (buffer-live-p treesit-context--buffer)))
    (setq treesit-context--list nil)
    (ignore-errors
      (let* ((node (treesit-node-at (point))))
	(cl-loop while node
		 do (treesit-context--add-to-list node)
		 do (setq node (treesit-node-parent node)))))
    (if treesit-context--list
	(progn
	  (with-current-buffer treesit-context--buffer
	    (erase-buffer)
	    (insert (treesit-context--get-context-from-list)))
	  (when (posframe-workable-p)
	    (posframe-show treesit-context--buffer
			   :poshandler #'posframe-poshandler-window-top-right-corner
			   :background-color "#cde0ed"
			   :border-width 5
			   :border-color "#cde0ed")))
      (posframe-hide treesit-context--buffer))))

vterm-run

autoload.el

判断是否开启了 vterm 模块
;;; modules/baosize/vterm-run/autoload.el -*- lexical-binding: t; -*-
;;;###if (modulep! :term vterm)

将内容发送给 vterm

;;;###autoload
(defun run-in-vterm (command)
  "Execute string COMMAND in a new vterm.
   Interactively, prompt for COMMAND with the current buffer's file
   name supplied. When called from Dired, supply the name of the
   file at point.
   Like `async-shell-command`, but run in a vterm for full terminal features.
   The new vterm buffer is named in the form `*foo bar.baz*`, the
   command and its arguments in earmuffs.
   When the command terminates, the shell remains open, but when the
   shell exits, the buffer is killed."
  (interactive
   (list
    (let* ((f (cond (buffer-file-name)
                    ((eq major-mode 'dired-mode)
                     (dired-get-filename nil t))))
           (filename (if f
                         (concat " " (shell-quote-argument f))
                       "")))
      (read-shell-command "Terminal command: "
                          (cons filename 0)
                          (cons 'shell-command-history 1)
                          (list filename)))))
  (+vterm/toggle nil)
  (vterm-send-string command)
  (vterm-send-return))

运行代码

;;;###autoload
(defun run-code ()
  "运行代码"
  (interactive)
  (if buffer-file-name
    (let ((file-name (shell-quote-argument
                      (file-name-sans-extension
                       (file-name-nondirectory buffer-file-name))))
          (file-path (shell-quote-argument buffer-file-name))
          (dir (shell-quote-argument
                (if (doom-project-root) (doom-project-root)
                  (file-name-directory buffer-file-name)))))
      (pcase major-mode
        ('c-ts-mode (run-in-vterm (concat "cd " dir " && "
                                        "gcc -O2 -std=c11 -g3 "
                                        file-path
                                        " -o /tmp/c-" file-name
                                        " && /tmp/c-" file-name)))
        ('c++-ts-mode (run-in-vterm (concat "cd " dir " && "
                                          "g++ -O2 -std=gnu++17 -g3 "
                                          file-path
                                          " -o /tmp/cpp-" file-name
                                          " && /tmp/cpp-" file-name)))
        ('python-ts-mode (run-in-vterm (concat "cd " dir " && "
                                             "python " file-path)))
        (_ (message "not supported"))))
  (message "buffer-file-name is nil")))

进行代码错误检查

;;;###autoload
(defun run-cpp-fsanitize ()
  "检查未定义行为"
  (interactive)
  (if buffer-file-name
      (let ((filename (file-name-sans-extension (file-name-nondirectory buffer-file-name)))
            (dir (if (doom-project-root) (doom-project-root) (file-name-directory buffer-file-name))))
        (run-in-vterm (concat "cd " dir " && " "clang++ -O2 -std=c++17 -fsanitize=undefined " buffer-file-name " -o /tmp/cpp-" filename " && /tmp/cpp-" filename)))
    (message "buffer-file-name is nil")))

config.el

绑定一些快捷键

;;; modules/baosize/vterm-run/config.el -*- lexical-binding: t; -*-
(when (modulep! :term vterm)
  (bind-keys ("C-c o TAB" . run-in-vterm)
        ("C-c oo" . run-code)
        ("C-c ot" . +vterm/toggle)
        ("C-c oF" . run-cpp-fsanitize)))

winum

切换窗口时更高效的选择( Alt + 数字键)

config.el
;;; modules/baosize/winum/config.el -*- lexical-binding: t; -*-
(use-package ace-window
  :custom-face
  (aw-leading-char-face ((t (:inherit font-lock-keyword-face :foreground unspecified :bold t :height 3.0))))
  (aw-minibuffer-leading-char-face ((t (:inherit font-lock-keyword-face :bold t :height 1.0))))
  (aw-mode-line-face ((t (:inherit mode-line-emphasis :bold t))))
  :bind (([remap other-window] . ace-window))
  :hook (emacs-startup . ace-window-display-mode)
  :config
  (defun toggle-window-split ()
    (interactive)
    (if (= (count-windows) 2)
        (let* ((this-win-buffer (window-buffer))
               (next-win-buffer (window-buffer (next-window)))
               (this-win-edges (window-edges (selected-window)))
               (next-win-edges (window-edges (next-window)))
               (this-win-2nd (not (and (<= (car this-win-edges)
                                           (car next-win-edges))
                                       (<= (cadr this-win-edges)
                                           (cadr next-win-edges)))))
               (splitter
                (if (= (car this-win-edges)
                       (car (window-edges (next-window))))
                    'split-window-horizontally
                  'split-window-vertically)))
          (delete-other-windows)
          (let ((first-win (selected-window)))
            (funcall splitter)
            (if this-win-2nd (other-window 1))
            (set-window-buffer (selected-window) this-win-buffer)
            (set-window-buffer (next-window) next-win-buffer)
            (select-window first-win)
            (if this-win-2nd (other-window 1))))
      (user-error "`toggle-window-split' only supports two windows")))
  ;; Select widnow via `M-1'...`M-9'
  (defun aw--select-window (number)
    "Slecet the specified window."
    (when (numberp number)
      (let ((found nil))
        (dolist (win (aw-window-list))
          (when (and (window-live-p win)
                     (eq number
                         (string-to-number
                          (window-parameter win 'ace-window-path))))
            (setq found t)
            (aw-switch-to-window win)))
        (unless found
          (message "No specified window: %d" number)))))
  (dotimes (n 9)
    (bind-key (format "M-%d" (1+ n))
              (lambda ()
                (interactive)
                (aw--select-window (1+ n))))))
packages.el
;; -*- no-byte-compile: t; -*-
;;; modules/baosize/winum/packages.el
;; (package! winum)

symbol-overlay

Emacs 杀器之一,高亮多个匹配单词并提供重命名、跳转等多种功能

config.el

;;; modules/baosize/symbol-overlay/config.el -*- lexical-binding: t; -*-
(use-package symbol-overlay
    :defer t
    :hook
    (prog-mode . symbol-overlay-mode)
    (text-mode . symbol-overlay-mode)
    :bind
    (("M-i" . symbol-overlay-put)
    ("M-n" . symbol-overlay-switch-forward)
    ("M-p" . symbol-overlay-switch-backward)
    ("<f7>" . symbol-overlay-mode)
    ("<f8>" . symbol-overlay-remove-all)))

packages.el

;; -*- no-byte-compile: t; -*-
;;; modules/baosize/symbol-overlay/packages.el
(package! symbol-overlay)

super-save

自动保存

config.el

;;; modules/baosize/super-save/config.el -*- lexical-binding: t; -*-
(use-package super-save
  :defer 0.5
  :config
  (add-to-list 'super-save-triggers 'switch-window)
  (setq super-save-exclude '(".gpg"))
  (setq super-save-idle-duration 1)
  (setq super-save-all-buffers 1)
  (setq super-save-auto-save-when-idle t)
  (setq super-save-silent t)
  (super-save-mode 1))

packages.el

;; -*- no-byte-compile: t; -*-
;;; modules/baosize/super-save/packages.el
(package! super-save)

keyfreq

记录按键频率,方便优化

config.el

;;; modules/baosize/keyfreq/config.el -*- lexical-binding: t; -*-
(use-package keyfreq
  :defer t
  :hook (doom-first-input . keyfreq-mode)
        (doom-first-input . keyfreq-autosave-mode))

packages.el

;; -*- no-byte-compile: t; -*-
;;; modules/baosize/keyfreq/packages.el
(package! keyfreq
  :recipe (:host github :repo "dacap/keyfreq"))

colorful-mode

在文件中将颜色标上对应高亮(比如”SpringGreen3”在 el 文件中会变绿)

config.el

;;; modules/baosize/colorful-mode/config.el -*- lexical-binding: t; -*-
(use-package colorful-mode
  :defer t
  :hook (prog-mode text-mode))

packages.el

;; -*- no-byte-compile: t; -*-
;;; modules/baosize/super-save/packages.el
(package! colorful-mode)

emacs-lsp-booster

为 lsp-mode 和 eglot 进行加速(将 json 转换为 elisp 形式,加速解析)

在 emacs 30 之后, emacs 对 json 的解析速度已经超越了对于 emacs-lisp array 的解析速度:)到那时 emacs-lsp-booster 如果再 parse json 造成的将是负优化。

config.el

没啥好说的,都是从项目主页抄的。

  ;;; modules/baosize/emacs-lsp-booster/config.el
(if (modulep! :tools lsp +eglot)
  (when (<= emacs-major-version 29)
    (use-package eglot-booster
      :after eglot
      :config (eglot-booster-mode)))
(progn (defun lsp-booster--advice-json-parse (old-fn &rest args)
  "Try to parse bytecode instead of json."
  (or
    (when (equal (following-char) ?#)
       (let ((bytecode (read (current-buffer))))
         (when (byte-code-function-p bytecode)
           (funcall bytecode))))
     (apply old-fn args)))
    (advice-add (if (progn (require 'json)
                           (fboundp 'json-parse-buffer))
                    'json-parse-buffer
                  'json-read)
                :around
                #'lsp-booster--advice-json-parse)
    (defun lsp-booster--advice-final-command (old-fn cmd &optional test?)
      "Prepend emacs-lsp-booster command to lsp CMD."
      (let ((orig-result (funcall old-fn cmd test?)))
        (if (and (not test?)                             ;; for check lsp-server-present?
                 (not (file-remote-p default-directory)) ;; see lsp-resolve-final-command, it would add extra shell wrapper
                 lsp-use-plists
                 (not (functionp 'json-rpc-connection))  ;; native json-rpc
                 (executable-find "emacs-lsp-booster"))
            (progn
              (when-let ((command-from-exec-path (executable-find (car orig-result))))  ;; resolve command from exec-path (in case not found in $PATH)
                (setcar orig-result command-from-exec-path))
              (message "Using emacs-lsp-booster for %s!" orig-result)
              (cons "emacs-lsp-booster" orig-result))
          orig-result)))
    (advice-add 'lsp-resolve-final-command :around #'lsp-booster--advice-final-command)))

packages.el

;; -*- no-byte-compile: t; -*-
;;; modules/baosize/emacs-lsp-booster/packages.el
(when (and (modulep! :tools lsp +eglot) (<= emacs-major-version 29))
  (package! eglot-booster
    :recipe(:host github
            :repo "jdtsmith/eglot-booster")))

doctor.el

要是没有 emacs-lsp-booster 可执行文件的话……

;;; modules/baosize/emacs-lsp-booster/doctor.el
(unless (or (executable-find "emacs-lsp-booster") (>= emacs-major-version 30))
  (warn! "LSP will crash when emacs-lsp-booster can't found in PATH!"))

nyan

在 modeline 上的彩虹猫

config.el

;;; modules/baosize/nyan/config.el -*- lexical-binding: t; -*-
(use-package nyan-mode
  :hook (doom-modeline-mode)
  :custom
  ;; (nyan-animate-nyancat t)
  (nyan-wavy-trail t))

packages.el

;; -*- no-byte-compile: t -*-
;;; modules/baosize/nyan/packages.el
(package! nyan-mode
  :recipe (:host github
           :repo "zakudriver/nyan-mode"
           :files ("*")))

avy-thing-edit

类似于 neovim 中 flash.nvim 的远程跳转编辑( Operator-PENDING mode 下的 r 键)

config.el

;;; modules/baosize/avy-thing-edit/config.el -*- lexical-binding: t; -*-
(use-package thing-edit
  :defer t
  :config
  (use-package avy-thing-edit
    :defer t
    :custom
    (avy-thing-edit-jump-command 'avy-goto-word-0)))

packages.el

;; -*- no-byte-compile: t -*-
;;; modules/baosize/avy-thing-edit/packages.el
(package! avy-thing-edit
  :recipe (:host github
           :repo "lyjdwh/avy-thing-edit"))
(package! thing-edit
  :recipe (:host github
           :repo "manateelazycat/thing-edit"))

super-eglot

我尝试用这个模块以将 eglot 打造得和 vscode 一样优秀( lsp-mode 提供了一个基于 lsp 的高亮,这对于 eglot 来说是极为困难的)

它目前包含了 breadcrumb 和 eldoc-box 。

config.el

;;; modules/baosize/super-eglot/config.el -*- lexical-binding: t; -*-

面包屑导航

(use-package breadcrumb
  :defer t
  :hook (prog-mode . breadcrumb-local-mode))

弹出文档和提示

(use-package eldoc-box
  :custom
  (eldoc-box-lighter nil)
  (eldoc-box-only-multi-line t)
  (eldoc-box-clear-with-C-g t)
  :custom-face
  (eldoc-box-border ((t (:inherit posframe-border :background unspecified))))
  (eldoc-box-body ((t (:inherit tooltip))))
  :hook (eglot-managed-mode . eldoc-box-hover-at-point-mode)
  :config
  ;; Prettify `eldoc-box' frame
  (setf (alist-get 'left-fringe eldoc-box-frame-parameters) 8
  (alist-get 'right-fringe eldoc-box-frame-parameters) 8))

code-action 提示

(use-package sideline
  :defer t
  :hook (eglot-managed-mode . sideline-mode)
  :init
  (setq sideline-backends-left-skip-current-line t   ; don't display on current line (left)
        sideline-backends-right-skip-current-line t  ; don't display on current line (right)
        sideline-order-left 'down                    ; or 'up
        sideline-order-right 'up                     ; or 'down
        sideline-format-left "%s   "                 ; format for left aligment
        sideline-format-right "   %s"                ; format for right aligment
        sideline-priority 100                        ; overlays' priority
        sideline-display-backend-name t))            ; display the backend name
(use-package sideline-eglot
  :defer 1
  :init
  (setq sideline-backends-right '(sideline-eglot)))

packages.el

;; -*- no-byte-compile: t -*-
;;; modules/baosize/super-eglot/packages.el
(package! breadcrumb)
(package! eldoc-box)
(package! sideline)
(package! sideline-eglot
  :recipe (:host github
           :repo "emacs-sideline/sideline-eglot"))

dape

不依赖于 lsp-mode 的 DAP 服务

config.el

;;; modules/baosize/dape/config.el -*- lexical-binding:t; -*-
(use-package dape
    :bind (("<f5>" . dape))
    :custom (dape-buffer-window-arrangment 'right)
    :config
    ;; Save buffers on startup, useful for interpreted languages
    (add-hook 'dape-on-start-hooks
              (defun dape--save-on-start ()
                (save-some-buffers t t))))

packages.el

;; -*- no-byte-compile: t -*-
;;; modules/baosize/dape/packages.el
(package! dape)

Releases

No releases published

Packages

No packages published