Skip to content

wang1zhen/solarion-emacs

Repository files navigation

README

Solarion Emacs

https://img.shields.io/badge/link-996.icu-red.svg

Here is my personal configuration file for Emacs. The whole README file is a symlink to solarion-emacs.org, and with org babel, this file could be tangled into separate emacs-lisp files under $HOME/.emacs.d/lisp/.

Table of Contents

Installation

Clone the repository

git clone [email protected]:wang1zhen/solarion-emacs ~/.emacs.d

Tangle the org file

emacs --batch --eval "(progn (require 'org) (let ((org-confirm-babel-evaluate nil)) (org-babel-tangle-file \"~/.emacs.d/solarion-emacs.org\")))"

Launch Emacs and have fun!

early-init.el

;;; early-init.el --- early-init.el is run before package and UI initialization happens -*- lexical-binding: t -*-

;;; Code:

;; Defer garbage collection further back in the startup process
(setq gc-cons-threshold most-positive-fixnum
      gc-cons-percentage 0.5)

;; Package initialize occurs automatically, before `user-init-file' is
;; loaded, but after `early-init-file'. We handle package
;; initialization, so we must prevent Emacs from doing it early!
(setq package-enable-at-startup nil)

;; Inhibit resizing frame
(setq frame-inhibit-implied-resize t)

;; Faster to disable these here (before they've been initialized)
(push '(menu-bar-lines . 0) default-frame-alist)
(push '(tool-bar-lines . 0) default-frame-alist)
(push '(vertical-scroll-bars) default-frame-alist)

;; Suppress the 'Package cl is deprecated' warning
(setq byte-compile-warnings '(not obsolete))

init.el

;;; init.el --- Load the full configuration -*- lexical-binding: t -*-

;;; Code:

(add-to-list 'load-path (expand-file-name "lisp" user-emacs-directory))

;; Custom file
(setq custom-file (make-temp-file "emacs-custom-"))

;; Adjust garbage collection thresholds during startup, and thereafter
(let ((normal-gc-cons-threshold (* 20 1024 1024))
      (init-gc-cons-threshold (* 128 1024 1024)))
  (setq gc-cons-threshold init-gc-cons-threshold)
  (add-hook 'emacs-startup-hook
            (lambda () (setq gc-cons-threshold normal-gc-cons-threshold))))

;; Always load newest byte code
(setq load-prefer-newer t)

;; Packages
(require 'init-straight)

;; Useful functions defined
(require 'init-func)

;; Preferences
(require 'init-basic)
(require 'init-general)

(require 'init-ui)
(require 'init-themes)
(require 'init-scroll)
(require 'init-fonts)
(require 'init-edit)

;; Keybindings
(require 'init-hydra)
(require 'init-map)

(require 'init-vertico)
(require 'init-corfu)
(require 'init-tempel)

(require 'init-magit)
(require 'init-ibuffer)
(require 'init-midnight)

(require 'init-tramp)

(require 'init-org)
(require 'init-latex)

(require 'init-dired)
(require 'init-projectile)

(require 'init-dashboard)
(require 'init-vterm)
(require 'init-persp)

(require 'init-dict)
(require 'init-im)

;; WSL specific setting
(when (and (eq system-type 'gnu/linux) (getenv "WSLENV"))
  (require 'init-wsl))

init-straight.el

;;; init-straight.el --- Initialize package configurations -*- lexical-binding: t -*-

;;; Code:

(defvar bootstrap-version)
(let ((bootstrap-file
       (expand-file-name "straight/repos/straight.el/bootstrap.el" user-emacs-directory))
      (bootstrap-version 5))
  (unless (file-exists-p bootstrap-file)
    (with-current-buffer
        (url-retrieve-synchronously
         "https://raw.githubusercontent.com/raxod502/straight.el/develop/install.el"
         'silent 'inhibit-cookies)
      (goto-char (point-max))
      (eval-print-last-sexp)))
  (setq straight-use-package-by-default t)
  (setq straight-vc-git-default-protocol 'https)
  (setq straight-vc-git-default-clone-depth 3)
  (load bootstrap-file nil 'nomessage))

;; Install use-package with straight
(straight-use-package 'use-package)

;; Should set before loading `use-package'
(setq use-package-expand-minimally t)
(setq use-package-enable-imenu-support t)
(require 'use-package)

;; Native compile
;; Log warnings but not pop up the *Warnings* buffer
(setq native-comp-async-report-warnings-errors 'silent)

;; Required by `use-package'
(use-package diminish)
(use-package bind-key)

(provide 'init-straight)

init-func.el

;;; init-func.el --- Useful functions are defined here -*- lexical-binding: t -*-

;;; Code:

(defun indent-buffer ()
  (interactive)
  (save-excursion
    (indent-region (point-min) (point-max) nil)))

;; Font
(defun font-installed-p (font-name)
  "Check if font with FONT-NAME is available."
  (find-font (font-spec :name font-name)))

;; Auto tangle babel file
(defun org-babel-auto-tangle ()
  (when (and (eq major-mode 'org-mode)
             (string-equal (buffer-name) "solarion-emacs.org"))
    (org-babel-tangle)))

;; Define split-window-below-and-focus and split-window-right-and-focus
(defun split-window-below-and-focus ()
  "Split the window vertically and focus the new window."
  (interactive)
  (split-window-below)
  (windmove-down))

(defun split-window-right-and-focus ()
  "Split the window horizontally and focus the new window."
  (interactive)
  (split-window-right)
  (windmove-right))

(defun solarion/org-mode-setup ()
  (auto-fill-mode 0)
  (visual-line-mode 1)
  (adaptive-wrap-prefix-mode 1)
  ;; (electric-pair-local-mode -1)
  )

;; Ask for the filename before pasting an image
;; filename should end with ".png/.jpg/.svg"
(defun solarion/org-download-paste-clipboard-wsl ()
  "to simplify the logic, use c:/Users/Public as temporary directory, and move it into current directory"
  (interactive)
  (let* ((powershell (executable-find "powershell.exe"))
         (file-base-name (format-time-string "image-%Y%m%d_%H%M%S.png"))
         (file-name (read-string (format "Filename [%s]: " file-base-name) nil nil file-base-name))
         (file-path-wsl (concat "./image/" file-name)))
    (shell-command (concat powershell " -command \"(Get-Clipboard -Format Image).Save(\\\"C:/Users/Public/" file-name "\\\")\""))
    (make-directory "./image" t)
    (rename-file (concat "/mnt/c/Users/Public/" file-name) file-path-wsl)
    (insert (concat "#+ATTR_LATEX: :width \\linewidth\n"))
    (org-indent-line)
    (insert (concat "[[file:" file-path-wsl "]]"))
    (org-display-inline-images)))

;; dashboard
(defun solarion-homepage (&rest _)
  (interactive)
  (browse-url "https://github.com/wang1zhen/solarion-emacs"))
(defun solarion-edit-config (&rest _)
  (interactive)
  (find-file (concat user-emacs-directory "solarion-emacs.org")))

;; buffer
(defun solarion-new-buffer nil
  (interactive)
  (let ((buffer (generate-new-buffer "*new*")))
    (set-window-buffer nil buffer)
    (with-current-buffer buffer
      (funcall (default-value 'major-mode)))))

;; Delete file and buffer
(defun delete-file-and-buffer ()
  "Kill the current buffer and deletes the file it is visiting."
  (interactive)
  (let ((filename (buffer-file-name)))
    (if filename
        (if (y-or-n-p (concat "Do you really want to delete file " filename " ?"))
            (progn
              (delete-file filename)
              (message "Deleted file %s." filename)
              (kill-buffer)))
      (message "Not a file visiting buffer!"))))

(defun flash-mode-line ()
  (invert-face 'mode-line)
  (run-with-timer 0.1 nil #'invert-face 'mode-line))

(defun copy-line (arg)
  "Copy lines (as many as prefix argument) in the kill ring.
      Ease of use features:
      - Move to start of next line.
      - Appends the copy on sequential calls.
      - Use newline as last char even on the last line of the buffer.
      - If region is active, copy its lines."
  (interactive "p")
  (let ((beg (line-beginning-position))
        (end (line-end-position arg)))
    (when mark-active
      (if (> (point) (mark))
          (setq beg (save-excursion (goto-char (mark)) (line-beginning-position)))
        (setq end (save-excursion (goto-char (mark)) (line-end-position)))))
    (if (eq last-command 'copy-line)
        (kill-append (buffer-substring beg end) (< end beg))
      (kill-ring-save beg end)))
  (kill-append "\n" nil)
  (beginning-of-line (or (and arg (1+ arg)) 2))
  (if (and arg (not (= 1 arg))) (message "%d lines copied" arg)))

(defun solarion/git-add-commit-push ()
  "Simple commit current git project and push to its upstream."
  (interactive)
  (when (and buffer-file-name
             (buffer-modified-p))
    (save-buffer))                   ;; save it first if modified.
  (magit-diff-unstaged)
  (when (yes-or-no-p "Do you really want to commit everything?")
    (magit-stage-modified t)         ;; stage modified and untracked
    (magit-diff-staged)
    (let ((msg (read-string "Commit Message: ")))
      (when (= 0 (length msg))
        (setq msg (format-time-string "commit by magit in emacs@%Y-%m-%d %H:%M:%S"
                                      (current-time))))
      (magit-call-git "commit" "-m" msg)
      (magit-push-current-to-upstream nil)
      (message "now do async push to %s" (magit-get "remote" "origin" "url"))))
  (magit-mode-bury-buffer))

(defun solarion/indent-buffer-and-format ()
  "Indent buffer and format code"
  (interactive)
  (indent-buffer)
  (when (format-all--language-id-buffer)
    (format-all-buffer t)))

(provide 'init-func)

init-basic.el

;;; init-basic.el --- Default configurations -*- lexical-binding: t -*-

;;; Code:

(setq user-full-name "wang1zhen"
      user-mail-address "[email protected]")

;; Increase how much is read from processes in a single chunk (default is 4kb)
(setq read-process-output-max #x10000)  ; 64kb

;; Garbage Collector Magic Hack
(use-package gcmh
  :diminish
  :init
  (setq gcmh-idle-delay 5
        gcmh-high-cons-threshold #x1000000) ; 16MB
  :hook (after-init . gcmh-mode))

;; Encoding
;; UTF-8 as the default coding system
(when (fboundp 'set-charset-priority)
  (set-charset-priority 'unicode))

;; Explicitly set the prefered coding systems to avoid annoying prompt
;; from emacs (especially on Microsoft Windows)
(prefer-coding-system 'utf-8)
(setq locale-coding-system 'utf-8)

(set-language-environment 'utf-8)
(set-default-coding-systems 'utf-8)
(set-buffer-file-coding-system 'utf-8)
(set-clipboard-coding-system 'utf-8)
(set-file-name-coding-system 'utf-8)
(set-keyboard-coding-system 'utf-8)
(set-terminal-coding-system 'utf-8)
(set-selection-coding-system 'utf-8)
(modify-coding-system-alist 'process "*" 'utf-8)

;; Ensure environment variables inside Emacs look the same as in the user's shell
(use-package exec-path-from-shell
  :init
  (setq exec-path-from-shell-variables '("PATH" "MANPATH")
        exec-path-from-shell-arguments '("-l"))
  :config
  (exec-path-from-shell-initialize))

;; Start server
(use-package server
  :straight nil
  :hook (after-init . server-mode))

;; Go to the last place when previously visited the file
(use-package saveplace
  :straight nil
  :hook (after-init . save-place-mode))

(use-package recentf
  :straight nil
  :hook (after-init . recentf-mode)
  :init
  (setq recentf-max-saved-items 500
        recentf-max-menu-items 15
        recentf-exclude
        '("\\.?cache" ".cask" "url" "COMMIT_EDITMSG\\'" "bookmarks"
          "\\.\\(?:gz\\|gif\\|svg\\|png\\|jpe?g\\|bmp\\|xpm\\)$"
          "\\.?ido\\.last$" "\\.revive$" "/G?TAGS$" "/.elfeed/"
          "^/tmp/" "^/var/folders/.+$" "^/ssh:" "/persp-confs/"
          (lambda (file) (file-in-directory-p file package-user-dir))))
  :config
  (push (expand-file-name recentf-save-file) recentf-exclude)
  (add-to-list 'recentf-filename-handlers #'abbreviate-file-name))

(use-package savehist
  :straight nil
  :hook (after-init . savehist-mode)
  :init
  (setq enable-recursive-minibuffers t ; Allow commands in minibuffers
        history-length 1000
        savehist-additional-variables '(mark-ring
                                        global-mark-ring
                                        search-ring
                                        regexp-search-ring
                                        extended-command-history)
        savehist-autosave-interval 300))

(use-package simple
  :straight nil
  :hook ((after-init . size-indication-mode)
         (text-mode . visual-line-mode)
         (helpful-mode . visual-line-mode)
         ((prog-mode org-mode markdown-mode conf-mode latex-mode) . (lambda () (setq show-trailing-whitespace t))))
  :init
  (setq column-number-mode t
        line-number-mode t
        ;; kill-whole-line t               ; Kill line including '\n'
        line-move-visual t
        ;; 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
  )

(use-package time
  :straight nil
  :init (setq display-time-24hr-format t
              display-time-day-and-date t))

(use-package so-long
  :straight nil
  :hook (after-init . global-so-long-mode)
  :config (setq so-long-threshold 400))

(use-package adaptive-wrap
  :commands adaptive-wrap-prefix-mode)

(use-package keyfreq
  :init
  (setq keyfreq-file "~/.emacs.d/.keyfreq")
  (setq keyfreq-file-lock "~/.emacs.d/.keyfreq.lock")
  (keyfreq-mode 1)
  (keyfreq-autosave-mode 1)
  :config
  (setq keyfreq-excluded-commands
        '(self-insert-command
          org-self-insert-command
          forward-char
          backward-char
          previous-line
          next-line))
  (setq keyfreq-excluded-regexp
        '("\\`vertico-.*\\'"
          "\\`iscroll-.*\\'"
          "\\`vterm-.*\\'")))

;; Misc
(fset 'yes-or-no-p 'y-or-n-p)
(setq-default major-mode 'emacs-lisp-mode
              tab-width 8
              indent-tabs-mode nil)     ; Permanently indent with spaces, never with TABs

;; flash the modeline for visual bell
(setq visible-bell nil
      ring-bell-function 'flash-mode-line)
(setq inhibit-compacting-font-caches t  ; Don’t compact font caches during GC.
      delete-by-moving-to-trash t       ; Deleting files go to OS's trash folder
      make-backup-files nil             ; Forbide to make backup files
      create-lockfiles nil              ; Forbide to make lockfiles
      auto-save-default nil             ; Disable auto save

      uniquify-buffer-name-style 'post-forward-angle-brackets ; Show path if names are same
      adaptive-fill-regexp "[ t]+|[ t]*([0-9]+.|*+)[ t]*"
      adaptive-fill-first-line-regexp "^* *$"
      sentence-end-double-space nil)

;; Use the system clipboard
(setq select-enable-clipboard t)

;; Always focus the help window
(setq help-window-select t)

;; Enable mouse in terminal mode
(xterm-mouse-mode)

;; Auto tangle this file after save (without prompt)
(add-hook 'after-save-hook #'org-babel-auto-tangle)

;; Disable scratch buffer text
(setq initial-scratch-message nil)

(provide 'init-basic)

init-general.el

Only prepare the packages here, specific keybindings goes to init-map.el.

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

;;; Code:

(use-package key-chord
  :diminish
  :init
  (key-chord-mode))

(use-package general)

(provide 'init-general)

init-ui.el

;;; init-ui.el --- Better lookings and appearances. -*- lexical-binding: t -*-

;;; Code:

(defconst solarion-font-size
  260
  "Font size for default font and modeline")

;; Title
(setq frame-title-format '((:eval (if (buffer-file-name)
                                      (abbreviate-file-name (buffer-file-name))
                                    "%b"))
                           "    "
                           user-login-name
                           "@"
                           system-name)
      icon-title-format frame-title-format)

;; Optimization
(setq idle-update-delay 1.0)

(setq-default cursor-in-non-selected-windows nil)
(setq highlight-nonselected-windows nil)

(tooltip-mode -1) ;; Disable tooltips
(set-fringe-mode 10) ;; 左右边框 仅对GUI生效
(global-hl-line-mode t)

;; always split vertically
(setq split-height-threshold nil
      split-width-threshold 80)

;; Mode-line
(use-package doom-modeline
  :diminish doom-modeline-mode
  :init
  (setq doom-modeline-modal-icon nil)
  ;; Must use mono font here
  (set-face-attribute 'mode-line nil :font "CaskaydiaCove Nerd Font Mono" :height solarion-font-size)
  (set-face-attribute 'mode-line-inactive nil :font "CaskaydiaCove Nerd Font Mono" :height solarion-font-size)
  (unless (version< emacs-version "29")
    (set-face-attribute 'mode-line-active nil :font "CaskaydiaCove Nerd Font Mono" :height solarion-font-size)) ;; For Emacs 29+
  (doom-modeline-mode t))

;; Icons
;; NOTE: Must run `M-x all-the-icons-install-fonts', and install fonts manually on Windows
(use-package all-the-icons)

(use-package display-line-numbers
  :straight nil
  :init
  (setq display-line-numbers-width-start t)
  (setq display-line-numbers-current-absolute t)
  :config
  (dolist (mode '(c-mode-common-hook
                  c-mode-hook
                  emacs-lisp-mode-hook
                  lisp-interaction-mode-hook
                  lisp-mode-hook
                  sh-mode-hook
                  python-mode-hook
                  html-mode-hook
                  rust-mode-hook
                  conf-mode-hook))
    (add-hook mode (lambda () (setq display-line-numbers t)))))

;; Suppress GUI features
(setq use-file-dialog nil
      use-dialog-box nil
      inhibit-startup-screen t
      inhibit-startup-echo-area-message t)

;; Display dividers between windows
(setq window-divider-default-places t
      window-divider-default-bottom-width 1
      window-divider-default-right-width 1)
(add-hook 'window-setup-hook #'window-divider-mode)

(add-to-list 'default-frame-alist '(fullscreen . maximized))

(use-package rainbow-delimiters
  :hook
  (prog-mode . rainbow-delimiters-mode)
  (LaTeX-mode . rainbow-delimiters-mode))

(use-package which-key
  :diminish which-key-mode
  :hook (after-init . which-key-mode)
  :init
  (setq which-key-idle-delay 0.2)
  (setq which-key-sort-order 'which-key-key-order-alpha)
  (setq which-key-prefix-prefix "")
  :config
  (set-face-attribute 'which-key-group-description-face nil :weight 'bold))

;; (use-package which-key-posframe
;;   :init
;;   (which-key-posframe-mode)
;;   :config
;;   (setq which-key-posframe-parameters
;;         '((left-fringe . 8)
;;           (right-fringe . 8))))

(use-package command-log-mode
  :commands command-log-mode)

;; (use-package keycast
;;   :after doom-modeline
;;   :config
;;   (setq keycast-mode-line-insert-after '(:eval (doom-modeline-format--main)))
;;   (add-to-list 'global-mode-string '("" keycast-mode-line))
;;   (keycast-mode-line-mode))

(use-package helpful
  :bind
  ([remap describe-function] . helpful-callable)
  ([remap describe-variable] . helpful-variable)
  ([remap describe-key] . helpful-key))

(use-package winum
  :hook (after-init . winum-mode))

(use-package posframe)

(use-package shackle
  :hook (after-init . shackle-mode)
  :init
  (setq shackle-select-reused-windows nil) ; default nil
  (setq shackle-default-alignment 'right) ; default below
  (setq shackle-select-reused-windows t)
  (setq shackle-rules
        '(("*vterm*" :size 0.3 :align below :popup t)
          ;; (compilation-mode :ignore t)
          ;; ("\\*Async Shell.*\\*" :regexp t :ignore t)
          ;; ("\\*corfu.*\\*" :regexp t :ignore t)
          ;; ("*eshell*" :select t :size 0.4 :align t :popup t)
          (helpful-mode :size 0.4 :align t :popup t)
          (help-mode :size 0.4 :align t :popup t)
          ;; ("*Messages*" :select t :size 0.4 :align t :popup t)
          (magit-status-mode :inhibit-window-quit t :other t)
          (magit-log-mode :inhibit-window-quit t :other t)
          ("\\*Org Src.*\\*" :regexp t :inhibit-window-quit t :other t))))

(provide 'init-ui)

init-themes.el

;;; init-themes.el --- Theme related configs goes here. -*- lexical-binding: t -*-

;;; Code:

;; (use-package modus-themes
;;   :init
;;   (setq modus-themes-italic-constructs t)
;;   (setq modus-themes-bold-constructs t)
;;   (setq modus-themes-syntax '(alt-syntax green-strings yellow-comments))
;;   (setq modus-themes-links '(neutral-underline background))
;;   (setq modus-themes-hl-line '(intense))
;;   (setq modus-themes-markup '(italic bold intense background))
;;   (setq modus-themes-paren-match '(intense))
;;   (setq modus-themes-org-blocks nil)
;;   (setq modus-themes-completions '((selection . (intense))))
;;   :config
;;   (modus-themes-load-operandi))

(use-package ef-themes
  :straight '(ef-themes :type git :host github :repo "protesilaos/ef-themes")
  :init
  (setq ef-themes-headings nil)
  (setq ef-themes-mixed-fonts nil)
  (setq ef-themes-variable-pitch-ui nil)
  (ef-themes-select 'ef-cyprus))

(provide 'init-themes)

init-scroll.el

Use iscroll for image scrolling and pixel-scroll-precision-mode for smooth scrolling (available since emacs 29)

;;; init-scroll.el --- Better scrolling effects. -*- lexical-binding: t -*-

;;; Code:

(setq scroll-preserve-screen-position 'always)
(setq next-screen-context-lines 5)

(use-package iscroll
  :init
  ;; (setq iscroll-preserve-screen-position t)
  :hook (org-mode . iscroll-mode))


(when (fboundp 'pixel-scroll-precision-mode)
  (pixel-scroll-precision-mode))

(provide 'init-scroll)

init-fonts.el

The font settings are mainly for GUI Emacs, this would not affect TUI Emacs. font check Chinese: 言 Symbols: ♪ Kana: 夜に駆ける

;;; init-fonts.el --- Fonts configurations (for GUI) -*- lexical-bindings: t -*-

;;; Code:

(defun solarion-config-fonts ()
  (when (display-graphic-p)
    ;; Set default font
    (set-face-attribute 'default
                        nil
                        :font "CaskaydiaCove Nerd Font Mono"
                        :height solarion-font-size)

    ;; Fixed-pitch (monospaced) fonts 等宽字体
    (set-face-attribute 'fixed-pitch
                        nil
                        :font "CaskaydiaCove Nerd Font Mono"
                        :height solarion-font-size)

    ;; CJK fonts
    (set-fontset-font t 'han (font-spec :family "Noto Serif CJK SC" :weight 'semi-bold :slant 'normal))
    (set-fontset-font t 'cjk-misc (font-spec :family "Noto Serif CJK SC" :weight 'semi-bold :slant 'normal))
    (set-fontset-font t 'kana (font-spec :family "Noto Serif CJK JP" :weight 'semi-bold :slant 'normal))
    ;; Emoji
    (set-fontset-font t 'symbol (font-spec :family "Noto Color Emoji") nil 'prepend)))

(solarion-config-fonts)
(add-hook 'window-setup-hook #'solarion-config-fonts)
(add-hook 'server-after-make-frame-hook #'solarion-config-fonts)

;; https://github.com/mickeynp/ligature.el
(use-package ligature
  :straight '(ligature :type git :host github :repo "mickeynp/ligature.el")
  :config
  ;; Enable the "www" ligature in every possible major mode
  (ligature-set-ligatures 't '("www"))
  ;; Enable traditional ligature support in eww-mode, if the
  ;; `variable-pitch' face supports it
  (ligature-set-ligatures 'eww-mode '("ff" "fi" "ffi"))
  ;; Enable all Cascadia Code ligatures in programming modes
  (ligature-set-ligatures 'prog-mode '("|||>" "<|||" "<==>" "<!--" "####" "~~>" "***" "||=" "||>"
                                       ":::" "::=" "=:=" "===" "==>" "=!=" "=>>" "=<<" "=/=" "!=="
                                       "!!." ">=>" ">>=" ">>>" ">>-" ">->" "->>" "-->" "---" "-<<"
                                       "<~~" "<~>" "<*>" "<||" "<|>" "<$>" "<==" "<=>" "<=<" "<->"
                                       "<--" "<-<" "<<=" "<<-" "<<<" "<+>" "</>" "###" "#_(" "..<"
                                       "..." "+++" "/==" "///" "_|_" "www" "&&" "^=" "~~" "~@" "~="
                                       "~>" "~-" "**" "*>" "*/" "||" "|}" "|]" "|=" "|>" "|-" "{|"
                                       "[|" "]#" "::" ":=" ":>" ":<" "$>" "==" "=>" "!=" "!!" ">:"
                                       ">=" ">>" ">-" "-~" "-|" "->" "--" "-<" "<~" "<*" "<|" "<:"
                                       "<$" "<=" "<>" "<-" "<<" "<+" "</" "#{" "#[" "#:" "#=" "#!"
                                       "##" "#(" "#?" "#_" "%%" ".=" ".-" ".." ".?" "+>" "++" "?:"
                                       "?=" "?." "??" ";;" "/*" "/=" "/>" "//" "__" "~~" "(*" "*)"
                                       "\\\\" "://"))
  ;; Enables ligature checks globally in all buffers. You can also do it
  ;; per mode with `ligature-mode'.
  (global-ligature-mode t))

(provide 'init-fonts)

init-edit.el

;;; init-edit.el --- Initialize editing configurations -*- lexical-binding: t -*-

;;; Code:

;; Automatically reload files was modified by external program
(use-package autorevert
  :straight nil
  :diminish
  :init
  (setq global-auto-revert-non-file-buffers t
        auto-revert-interval 1)
  (global-auto-revert-mode))

(use-package auto-save
  :straight '(auto-save :type git :host github :repo "manateelazycat/auto-save")
  :config
  (auto-save-enable)
  (setq auto-save-silent t)   ; quietly save
  (setq auto-save-delete-trailing-whitespace t)  ; automatically delete spaces at the end of the line when saving
  )

(use-package format-all
  :commands (format-all-buffer format-all--language-id-buffer))

;; Jump to things in Emacs tree-style
(use-package avy
  :hook (after-init . avy-setup-default)
  :config (setq avy-all-windows t
                avy-background t
                avy-style 'at-full
                avy-timeout-seconds 0.5))

(use-package beginend
  :diminish beginend-global-mode
  :hook (after-init . beginend-global-mode))

;; A comprehensive visual interface to diff & patch
(use-package ediff
  :straight nil
  :hook (;; show org ediffs unfolded
         (ediff-prepare-buffer . outline-show-all)
         ;; restore window layout when done
         ;; (ediff-quit . winner-undo)
         )
  :config
  (setq ediff-window-setup-function 'ediff-setup-windows-plain
        ediff-split-window-function 'split-window-vertically
        ediff-merge-split-window-function 'split-window-vertically))

;; Increase selected region by semantic units
(use-package expand-region
  :commands er/expand-region)

;; Hungry deletion
(use-package hungry-delete
  :diminish
  :hook (after-init . global-hungry-delete-mode)
  :init (setq hungry-delete-except-modes '(help-mode minibuffer-mode minibuffer-inactive-mode calc-mode)
              hungry-delete-chars-to-skip " 	
\f"))

;; Move to the beginning/end of line or code
(use-package mwim
  :config
  (general-def "C-a" #'mwim-beginning-of-code-or-line)
  (general-def "C-e" #'mwim-end-of-code-or-line))

(general-def "C-/" #'undo-only)
(general-def "C-r" #'undo-redo)

;; vundo
(use-package vundo
  :config
  (general-def "C-x u" #'vundo)
  (general-def "C-x r" #'vundo)
  (general-def vundo-mode-map "C-n" #'vundo-next)
  (general-def vundo-mode-map "C-p" #'vundo-previous)
  (general-def vundo-mode-map "C-f" #'vundo-forward)
  (general-def vundo-mode-map "C-b" #'vundo-backward)
  (setq vundo-glyph-alist vundo-unicode-symbols))

;; Handling capitalized subwords in a nomenclature
(use-package subword
  :straight nil
  :diminish
  :hook ((prog-mode . subword-mode)
         (minibuffer-setup . subword-mode)))

(use-package sudo-edit
  :commands (sudo-edit-find-file sudo-edit-current-file))

;; On-the-fly spell checker
(use-package flyspell
  :straight nil
  :diminish
  :if (executable-find "aspell")
  :hook
  (((text-mode outline-mode) . flyspell-mode)
   (prog-mode . flyspell-prog-mode)
   (LaTeX-mode . flyspell-mode)
   (flyspell-mode . (lambda ()
                      (dolist (key '("C-;" "C-," "C-."))
                        (unbind-key key flyspell-mode-map)))))
  :init
  (setq flyspell-issue-message-flag nil
        ispell-program-name "aspell"
        ispell-extra-args '("--sug-mode=ultra" "--lang=en_US" "--run-together")))

;; Framework for mode-specific buffer indexes
(use-package imenu
  :straight nil
  :init
  (setq imenu-auto-rescan t))

;; 中英文间自动加入空格
(use-package pangu-spacing
  :diminish global-pangu-spacing-mode
  :init
  (global-pangu-spacing-mode 1)
  (setq pangu-spacing-real-insert-separtor t))

;; occur
(add-hook 'occur-hook (lambda () (switch-to-buffer-other-window "*Occur*")))

;; smartparens
(use-package smartparens
  :diminish
  :config
  (require 'smartparens-config)
  (add-hook 'org-mode-hook #'smartparens-mode)
  (add-hook 'LaTeX-mode-hook #'smartparens-mode)
  (add-hook 'emacs-lisp-mode-hook #'smartparens-mode)
  ;; custom pairs
  (with-eval-after-load 'org
    (sp-local-pair 'org-mode "\\[" "\\]")
    (sp-local-pair 'org-mode "=" nil :actions :rem)
    (sp-local-pair 'org-mode "/" nil :actions :rem)))

(use-package lorem-ipsum)

;; (treesit-auto-install-all)
(use-package treesit-auto
  :config
  (global-treesit-auto-mode)
  (setq treesit-font-lock-level 4))

(provide 'init-edit)

init-hydra.el

;;; init-hydra.el --- Hydra configurations -*- lexical-binding: t -*-

;;; Code:

(use-package hydra
  :config
  (defhydra hydra-window-resize (:timeout 4)
    "Resize window"
    ("j" enlarge-window "Increase height")
    ("k" shrink-window "Decrease height")
    ("h" shrink-window-horizontally "Decrease width")
    ("l" enlarge-window-horizontally "Increase width")
    ("SPC" balance-windows "Balance windows")
    ("q" nil "quit" :exit t)))

(provide 'init-hydra)

init-map.el

Define the majority of keybindings here.

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

;;; Code:
;; misc
(general-def [f10] #'solarion/indent-buffer-and-format) ;; f12 reserved for yakuake
(general-def [f5] #'revert-buffer)
(general-def ";" (general-key-dispatch 'self-insert-command
                   :timeout 0.25
                   "'" #'comment-line))
(general-def "j" (general-key-dispatch 'self-insert-command
                   :timeout 0.25
                   "k" (general-key "C-g")))
(general-def "k" (general-key-dispatch 'self-insert-command
                   :timeout 0.25
                   "j" #'avy-goto-char-timer))
(general-def :keymaps 'override "C-c k" #'copy-line)

(general-unbind "M-`")	;; reserved for tmux

(general-create-definer global-leader-def
  :keymaps 'override
  :prefix "C-c")

(general-create-definer local-leader-def
  :keymaps 'override
  :prefix "C-c m")

;; Global leader
(global-leader-def

  ;; maps
  "h" #'(help-command :which-key "Help")
  "p" #'(projectile-command-map :which-key "Projectile")

  ;; keys
  "C-." #'consult-imenu  ;; "C-c ." for org-time-stamp
  "=" #'er/expand-region
  "C-s" #'consult-ripgrep
  "C-SPC" #'consult-mark

  ;; window
  "w" '(:ignore t :which-key "Window")
  "ws" #'split-window-below-and-focus
  "wv" #'split-window-right-and-focus
  "wd" #'(delete-window :which-key "Delete window")
  "wq" #'(kill-buffer-and-window :which-key "Kill buffer and window")
  "wr" #'(hydra-window-resize/body :which-key "Window Resize")
  "w=" #'(balance-windows :which-key "Balance Windows")
  "1" #'(winum-select-window-1 :which-key "Switch to window 1")
  "2" #'(winum-select-window-2 :which-key "Switch to window 2")
  "3" #'(winum-select-window-3 :which-key "Switch to window 3")
  "4" #'(winum-select-window-4 :which-key "Switch to window 4")
  "5" #'(winum-select-window-5 :which-key "Switch to window 5")

  ;; buffer & bookmark
  "b" '(:ignore t :which-key "Buffer/Bookmark")
  "bp" #'(previous-buffer :which-key "Previous Buffer")
  "bn" #'(next-buffer :which-key "Next Buffer")
  "bb" #'(consult-buffer :which-key "Switch Buffer")
  "bc" #'(clone-indirect-buffer :which-key "Clone Buffer")
  "bd" #'(kill-current-buffer :which-key "Kill Buffer")
  "bi" #'ibuffer
  "bm" #'(bookmark-set :which-key "Set Bookmark")
  "bM" #'(bookmark-delete :which-key "Delete Bookmark")
  "bj" #'(consult-bookmark :which-key "Jump to Bookmark")
  "bl" #'(list-bookmarks :which-key "Bookmarks List")
  "bN" #'(solarion-new-buffer :which-key "New Empty Buffer")
  "br" #'(revert-buffer :which-key "Revert Buffer")

  ;; file
  "f" '(:ignore t :which-key "File")
  "fd" #'(dired-jump :which-key "Dired Jump")
  "fD" #'(delete-file-and-buffer :which-key "Delete File")
  "ff" #'(find-file :which-key "Find File")
  "fs" #'(save-buffer :which-key "Save File")
  "fS" #'(write-file :which-key "Save File As")
  "fr" #'(consult-recent-file :which-key "Recent Files")
  "fp" #'(solarion-edit-config :which-key "Edit Config")

  ;; quit
  "q" '(:ignore t :which-key "Quit")
  "qf" #'(delete-frame :which-key "Delete Frame")
  "qq" #'(save-buffers-kill-terminal :which-key "Quit Emacs")

  ;; roam
  "r" '(:ignore t :which-key "Roam")
  "ra" #'org-roam-node-random
  "rr" #'org-roam-buffer-toggle
  "rf" #'org-roam-node-find
  "rg" #'org-roam-graph
  "ri" #'org-roam-node-insert
  "rc" #'org-roam-capture
  "rs" #'solarion/org-roam-rg-search
  "rS" #'org-roam-db-sync
  "ro" '(:ignore t :which-key "Node Properties")
  "roa" #'org-roam-alias-add
  "roA" #'org-roam-alias-remove
  "ror" #'org-roam-ref-add
  "roR" #'org-roam-ref-remove
  "rot" #'org-roam-tag-add
  "roT" #'org-roam-tag-remove

  ;; git
  "g" '(:ignore t :which-key "Git")
  "gR" #'vc-revert
  "g/" #'magit-dispatch
  "g." #'magit-file-dispatch
  ;; "g'" #'forge-dispatch
  "gb" #'magit-branch-checkout
  "gg" #'magit-status
  "gG" #'solarion/git-add-commit-push
  "gD" #'magit-file-delete
  "gB" #'magit-blame
  "gC" #'magit-clone
  "gF" #'magit-fetch
  "gL" #'magit-log-buffer-file
  "gS" #'magit-stage-file
  "gU" #'magit-unstage-file
  "gf" '(:ignore t :which-key "find")
  "gff" #'magit-find-file
  "gfg" #'magit-find-git-config-file
  "gfc" #'magit-show-commit
  ;; "gfi" #'forge-visit-issue
  ;; "gfp" #'forge-visit-pullreq
  "gl" '(:ignore t :which-key "list")
  "glr" #'magit-list-repositories
  "gls" #'magit-list-submodules
  ;; "gli" #'forge-list-issues
  ;; "glp" #'forge-list-pullreqs
  ;; "gln" #'forge-list-notifications
  "gc" '(:ignore t :which-key "create")
  "gcr" #'magit-init
  "gcR" #'magit-clone
  "gcc" #'magit-commit-create
  "gcf" #'magit-commit-fixup
  "gcb" #'magit-branch-and-checkout
  ;; "gci" #'forge-create-issue
  ;; "gcp" #'forge-create-pullreq

  ;; custom
  "o" '(:ignore t :which-key "Custom Entry")
  "oT" #'(consult-theme :which-key "Choose Theme")
  "ot" #'(ef-themes-load-random :which-key "Random Theme")
  "oo" #'occur
  "of" #'(fanyi-dwim :which-key "Dict")
  "oy" #'yadm
  ;; "ok" #'(keycast-mode-line-mode :which-key "Keycast")
  )

;; Local leader
;; org-mode
(local-leader-def org-mode-map
  "," #'org-switchb
  "." #'consult-org-heading
  "b" #'org-mark-ring-goto
  "a" '(:ignore t :which-key "Attach")
  "aa" #'org-attach
  "ap" #'solarion/org-download-paste-clipboard-wsl
  "e" #'(org-export-dispatch :which-key "Export")
  "d" '(:ignore t :which-key "Date")
  "dd" #'org-deadline
  "ds" #'org-schedule
  "dt" #'org-time-stamp
  "dT" #'org-time-stamp-inactive
  "f" #'org-footnote-action
  "h" #'org-toggle-heading
  "i" #'org-toggle-item
  "r" '(:ignore t :which-key "Roam")
  "ra" #'org-roam-node-random
  "rr" #'org-roam-buffer-toggle
  "rf" #'org-roam-node-find
  "rg" #'org-roam-graph
  "ri" #'org-roam-node-insert
  "rc" #'org-roam-capture
  "rs" #'solarion/org-roam-rg-search
  "rS" #'org-roam-db-sync
  "ro" '(:ignore t :which-key "Node Properties")
  "roa" #'org-roam-alias-add
  "roA" #'org-roam-alias-remove
  "ror" #'org-roam-ref-add
  "roR" #'org-roam-ref-remove
  "rot" #'org-roam-tag-add
  "roT" #'org-roam-tag-remove
  "p" '(:ignore t :which-key "Priority")
  "pd" #'org-priority-down
  "pp" #'org-priority
  "pu" #'org-priority-up
  "R" #'org-refile
  "t" #'org-todo
  "x" #'org-toggle-checkbox)

(general-def help-map
  ;; new keybinds
  "'"    #'describe-char

  ;; Unbind `help-for-help'. Conflicts with which-key's help command for the
  ;; <leader> h prefix. It's already on ? and F1 anyway.
  "C-h"  nil

  ;; replacement keybinds
  ;; replaces `info-emacs-manual' b/c it's on C-m now
  "r"    nil

  "b"   #'describe-bindings
  "B"   #'general-describe-keybindings

  ;; replaces `apropos-command'
  "a"    #'apropos
  "A"    #'apropos-documentation
  ;; replaces `describe-copying' b/c not useful
  "C-c"  #'describe-coding-system
  ;; replaces `Info-got-emacs-command-node' b/c redundant w/ `Info-goto-node'
  "F"    #'describe-face
  ;; replaces `view-hello-file' b/c annoying
  "h"    nil
  ;; replaces `help-with-tutorial', b/c it's less useful than `load-theme'
  "t"    #'consult-theme
  ;; replaces `finder-by-keyword' b/c not useful
  "p"    nil)

(provide 'init-map)

init-vertico.el

The bundle of vertico, consult, orderless, marginalia and embark

;;; init-vertico.el --- Initialize the vertico bundle -*- lexical-binding: t -*-

;;; Code:

(use-package vertico
  :straight (vertico :files (:defaults "extensions/*"))
  :init
  (vertico-mode)

  (setq vertico-scroll-margin 2)

  ;; Show 10 candidates
  (setq vertico-count 10)

  ;; Optionally enable cycling for `vertico-next' and `vertico-previous'.
  (setq vertico-cycle t))

;; (use-package vertico-posframe
;;   :after vertico
;;   :init
;;   (vertico-posframe-mode 1)
;;   (setq vertico-posframe-parameters
;;         '((left-fringe . 8)
;;           (right-fringe . 8))))

(use-package vertico-directory
  :after vertico
  :straight nil
  ;; More convenient directory navigation commands
  :bind (:map vertico-map
              ("RET" . vertico-directory-enter)
              ("DEL" . vertico-directory-delete-char)
              ("C-DEL" . vertico-directory-delete-word))
  ;; Tidy shadowed file names
  :hook (rfn-eshadow-update-overlay . vertico-directory-tidy))

(use-package all-the-icons-completion
  :after (marginalia all-the-icons)
  :hook (marginalia-mode . all-the-icons-completion-marginalia-setup)
  :init
  (all-the-icons-completion-mode))

(use-package pinyinlib
  :after orderless
  :config
  (defun completion--regex-pinyin (str)
    (orderless-regexp (pinyinlib-build-regexp-string str)))
  (add-to-list 'orderless-matching-styles 'completion--regex-pinyin))

(use-package orderless
  :init
  ;; Configure a custom style dispatcher (see the Consult wiki)
  ;; (setq orderless-style-dispatchers '(+orderless-dispatch)
  ;;       orderless-component-separator #'orderless-escapable-split-on-space)
  (setq completion-styles '(basic orderless)
        completion-category-defaults nil
        completion-category-overrides '((file (styles basic partial-completion)))))

;; Enable richer annotations using the Marginalia package
(use-package marginalia
  ;; Either bind `marginalia-cycle` globally or only in the minibuffer
  ;; The :init configuration is always executed (Not lazy!)
  :init
  ;; Must be in the :init section of use-package such that the mode gets
  ;; enabled right away. Note that this forces loading the package.
  (marginalia-mode))

(use-package consult
  :bind
  ("C-s" . consult-line)
  ([remap switch-to-buffer] . consult-buffer)
  ([remap yank-pop] . consult-yank-pop)
  :config
  (setq consult-fontify-preserve nil))

(use-package embark
  :bind
  ("C-." . embark-act)
  ("M-." . embark-dwim)
  ;; Optionally replace the key help with a completing-read interface
  :init
  (setq prefix-help-command #'embark-prefix-help-command))

(use-package embark-consult
  :after (embark consult)
  :demand t
  ;; only necessary if you have the hook below
  ;; if you want to have consult previews as you move around an
  ;; auto-updating embark collect buffer
  :hook
  (embark-collect-mode . consult-preview-at-point-mode))

(use-package wgrep)

(provide 'init-vertico)

init-corfu.el

Corfu enhances completion at point with a small completion popup. The current candidates are shown in a popup below or above the point. Corfu is the minimalistic completion-in-region counterpart of the Vertico minibuffer UI.

;;; init-corfu.el --- Completion Overlay Region FUnction -*- lexical-binding: t -*-

;;; Code:

(use-package corfu
  :straight (corfu :files (:defaults "extensions/*"))
  :init
  ;; built-in configurations
  (setq completion-cycle-threshold 5)
  ;; Enable indentation+completion using the TAB key.
  (setq tab-always-indent 'complete)
  ;; Emacs 28: Hide commands in M-x which do not apply to the current mode.
  ;; Corfu commands are hidden, since they are not supposed to be used via M-x.
  (setq read-extended-command-predicate #'command-completion-default-include-p)

  ;; corfu settings
  (setq corfu-cycle t)
  (setq corfu-auto t)
  (setq corfu-auto-prefix 2)
  (setq corfu-auto-delay 0)
  (setq corfu-count 7)
  (setq corfu-preselect-first nil) ;; tab for complete common
  (global-corfu-mode)

  ;; corfu quick
  (setq corfu-quick1 "asdf")
  (setq corfu-quick2 "jkl")
  (general-def corfu-map "`" #'corfu-quick-complete)
  )

(use-package cape
  :init
  ;; Add `completion-at-point-functions', used by `completion-at-point'.
  (setq cape-dabbrev-check-other-buffers nil) ;; only check current buffer for completion
  (add-to-list 'completion-at-point-functions #'cape-dabbrev)
  (add-to-list 'completion-at-point-functions #'cape-file))

(provide 'init-corfu)

init-tempel.el

Tempel is a tiny template package for Emacs, which uses the syntax of the Emacs Tempo library. A substitute for yasnippet.

;;; init-tempel.el --- Simple templates for Emacs -*- lexical-binding: t -*-

;;; Code:

;; Configure Tempel
(use-package tempel
  :bind
  (:map tempel-map
        ("TAB" . tempel-next))
  :init
  (setq tempel-path (concat user-emacs-directory "tempel-templates/*.eld"))
  (setq tempel-trigger-prefix "<")
  ;; Setup completion at point
  (defun tempel-setup-capf ()
    ;; Add the Tempel Capf to `completion-at-point-functions'.
    ;; `tempel-expand' only triggers on exact matches. Alternatively use
    ;; `tempel-complete' if you want to see all matches, but then you
    ;; should also configure `tempel-trigger-prefix', such that Tempel
    ;; does not trigger too often when you don't expect it. NOTE: We add
    ;; `tempel-expand' *before* the main programming mode Capf, such
    ;; that it will be tried first.
    (setq-local completion-at-point-functions
                (cons #'tempel-complete
                      completion-at-point-functions)))

  (add-hook 'prog-mode-hook 'tempel-setup-capf)
  (add-hook 'text-mode-hook 'tempel-setup-capf))

(provide 'init-tempel)

init-magit.el

;;; init-magit.el --- Configuration related to git -*- lexical-binding: t -*-

;;; Code:

(use-package magit
  :bind
  (:map magit-mode-map
        ("p" . magit-push))
  :init
  (setq magit-display-buffer-function #'magit-display-buffer-traditional
        git-commit-major-mode 'org-mode))

(use-package diff-hl
  :diminish
  :init
  (global-diff-hl-mode)
  (add-hook 'magit-pre-refresh-hook 'diff-hl-magit-pre-refresh)
  (add-hook 'magit-post-refresh-hook 'diff-hl-magit-post-refresh))

(provide 'init-magit)

init-ibuffer.el

;;; init-ibuffer.el --- Initialize ibuffer configurations -*- lexical-binding: t -*-

;;; Code:

(use-package ibuffer
  :straight nil
  :hook (ibuffer-mode . (lambda () (ibuffer-auto-mode 1) (ibuffer-switch-to-saved-filter-groups "custom")))
  :custom
  (ibuffer-show-empty-filter-groups nil)
  (ibuffer-saved-filter-groups
   '(("custom"
      ("Dired" (mode . dired-mode))
      ("Org" (mode . org-mode))
      ("Emacs" (or
                (name . "^\\*scratch\\*$")
                (name . "^\\*Backtrace\\*$")
                (name . "^\\*Messages\\*$")))
      ("Help" (or
               (name . "Help")
               (name . "^helpful")))
      ("Magit" (name . "^magit"))
      ))))

(provide 'init-ibuffer)

init-midnight.el

Clean inactive buffers.

;;; init-midnight.el --- Configurations for midnight -*- lexical-binding: t -*-

;;; Code:

;; use `clean-buffer-list' from `midngiht.el'
(use-package midnight
  :after (dashboard vterm minimap)
  :config
  ;;kill buffers if they were last disabled more than this seconds ago
  (setq clean-buffer-list-delay-special (* 3 60 60))

  (defvar clean-buffer-list-timer nil
    "Stores clean-buffer-list timer if there is one. You can disable clean-buffer-list by (cancel-timer clean-buffer-list-timer).")

  ;; run clean-buffer-list every 30 minites
  (setq clean-buffer-list-timer (run-at-time t 1800 'clean-buffer-list))

  ;; kill everything, clean-buffer-list is very intelligent at not killing
  ;; unsaved buffer.
  ;; 满足条件且超过`clean-buffer-list-delay-special'的buffer才会被清除
  (setq clean-buffer-list-kill-regexps '("^.*$"))

  (defvar solarion-clean-buffer-list-kill-never-buffer-names
    `("*httpd*" "*Messages" "*Backtrace*" "*scratch*" "*Ibuffer*" ,dashboard-buffer-name ,vterm-buffer-name ,minimap-buffer-name)
    "buffer names not to kill")
  (dolist (buf solarion-clean-buffer-list-kill-never-buffer-names)
    (add-to-list 'clean-buffer-list-kill-never-buffer-names buf))

  (defvar solarion-clean-buffer-list-kill-never-regexps
    nil
    "regexps not to kill")
  (dolist (buf solarion-clean-buffer-list-kill-never-regexps)
    (add-to-list 'clean-buffer-list-kill-never-regexps buf)))

(provide 'init-midnight)

init-tramp.el

;;; init-tramp.el --- Tramp settings -*- lexical-binding: t -*-

;;; Code:

(use-package tramp
  :straight (:type built-in)
  :config
  (add-to-list 'tramp-methods
               '("yadm"
                 (tramp-login-program "yadm")
                 (tramp-login-args (("enter")))
                 (tramp-login-env (("SHELL") ("/bin/sh")))
                 (tramp-remote-shell "/bin/sh")
                 (tramp-remote-shell-args ("-c"))))
  (defun yadm ()
    (interactive)
    (magit-status "/yadm::")))

(provide 'init-tramp)

init-org.el

;;; init-org.el --- Org-mode -*- lexical-binding: t -*-

;;; Code:

(use-package org
  :straight (:type built-in)
  :hook
  (org-mode . solarion/org-mode-setup)
  :config
  (org-babel-do-load-languages
   'org-babel-load-languages
   '((emacs-lisp . t)
     (shell . t)
     (latex . t)
     (python . t)
     (matlab . t)
     (gnuplot . t)))
  (setq org-startup-with-inline-images nil)
  (setq org-startup-with-latex-preview nil)
  (setq org-startup-numerated t);; Start org-mode numbered
  (setq org-adapt-indentation t);; add indentation for newlines
  (setq org-highlight-latex-and-related '(native script entities))
  (setq org-directory "~/org")
  (setq org-ellipsis "\t[+]")
  (setq org-tags-column -80)
  (setq org-log-done 'time)
  (setq org-hide-emphasis-markers nil) ;; Show bold and italic verbosely
  (setq org-link-descriptive t) ;; Show links verbosely
  (setq org-hide-leading-stars t)
  ;; export settings
  (setq org-export-with-tags nil)
  (setq org-export-with-sub-superscripts '{})
  ;; latex settings
  (setq org-latex-compiler "xelatex")
  (setq org-latex-hyperref-template "\\hypersetup{\n pdfauthor={%a},\n pdftitle={%t},\n pdfkeywords={%k},\n pdfsubject={%d},\n colorlinks=true,\n linkcolor=black\n}\n")
  ;; set table of contents level
  (setq org-export-with-toc 3)
  (setq org-latex-toc-command "\\pagestyle{empty}\n\\tableofcontents\n\\clearpage\n\n\\setcounter{page}{1}\n\\pagestyle{plain}\n\n")
  ;; maketitle command
  (setq org-latex-title-command "\\maketitle\n\\thispagestyle{empty}")
  ;; size of the preview latex fragments
  (plist-put org-format-latex-options :scale 2)
  (general-def org-src-mode-map "C-c C-c" #'org-edit-src-exit)
  (general-def org-mode-map "C-RET" #'org-meta-return)
  (general-def org-mode-map "C-<return>" #'org-meta-return)
  ;; org latex packages
  (setq org-latex-packages-alist
        '(("" "siunitx")
          ("" "mathrsfs")
          ("scheme=plain" "ctex")
          ;; mlmodern is thicker
          ;; ("" "mlmodern")
          ("" "lmodern")
          ("T1" "fontenc")))
  (setq org-image-actual-width t)
  (setq org-preview-latex-image-directory (concat user-emacs-directory ".local/ltximg/"))
  (general-def [remap org-return] #'(lambda () (interactive) (org-return electric-indent-mode)))
  )

(use-package ox-gfm
  :config (add-to-list 'org-export-backends 'md))

(use-package org-superstar
  :diminish org-superstar-mode
  :hook (org-mode . (lambda () (org-superstar-mode)))
  :init
  (setq
   org-superstar-headline-bullets-list '("" "" "" "")
   org-superstar-cycle-headline-bullets nil
   org-superstar-prettify-item-bullets nil))

(use-package org-download
  :defer t
  :config
  (org-download-enable)
  (setq
   org-download-method 'directory
   org-download-image-dir "images"
   org-download-heading-lvl nil
   org-download-timestamp "%Y%m%d-%H%M%S_")

  ;; to change image width seperately (also hide the annotate #+DOWNLOADED)
  (setq org-download-annotate-function (lambda (_link) "#+ATTR_LATEX: :width \\linewidth\n")))

(use-package org-roam
  :diminish
  :init
  (setq
   org-roam-v2-ack t
   org-roam-directory (file-truename "~/org-roam/")
   org-id-locations-file (file-truename "~/org-roam/.orgids"))
  (add-to-list 'display-buffer-alist
               '("\\*org-roam\\*"
                 (display-buffer-in-direction)
                 (direction . right)
                 (window-width . 0.33)
                 (window-height . fit-window-to-buffer)))
  :config
  (unless (file-exists-p org-roam-directory)
    (make-directory org-roam-directory))
  (setq org-roam-capture-templates
        '(("d" "Default" plain
           "%?"
           :target (file+head "%<%Y%m%d%H%M%S>-${slug}.org" "#+title: ${title}\n#+date: %u\n")
           :unnarrowed t)
          ("r" "Research Note" plain
           (file "~/org-roam/Templates/ResearchNoteTemplate.org")
           :target (file+head "%<%Y%m%d%H%M%S>-${slug}.org" "#+title: ${title}\n#+date: %u\n")
           :unnarrowed t)))
  (defun solarion/org-roam-rg-search ()
    "Search org-roam directory using consult-ripgrep. With live-preview."
    (interactive)
    (let ((consult-ripgrep-command "rg --null --ignore-case --type org --line-buffered --color=always --max-columns=500 --no-heading --line-number . -e ARG OPTS"))
      (consult-ripgrep org-roam-directory)))
  (setq org-roam-node-display-template (concat "${title:*} " (propertize "${tags:10}" 'face 'org-tag)))
  (org-roam-db-autosync-mode))

;; Automatically insert table of contents after the heading with :TOC: tag
(use-package toc-org
  :hook (org-mode . toc-org-mode))

;; Auto-toggle Org LaTeX fragments
(use-package org-fragtog)

;; matlab mode, currently only for org mode, could be separated
;; the package name is matlab, yet it provides `matlab'
(use-package matlab
  :straight matlab-mode
  :diminish
  :config
  (add-to-list 'auto-mode-alist '("\\.m\\'" . matlab-mode))
  (setq matlab-indent-function t)
  (setq matlab-shell-command "matlab"))

;; gnuplot mode, currently only for org mode, could be separated
(use-package gnuplot
  :diminish
  :config
  (add-to-list 'auto-mode-alist '("\\.gp$" . gnuplot-mode)))

(use-package org-roam-ui
  :config
  (setq org-roam-ui-sync-theme t
        org-roam-ui-follow t
        org-roam-ui-update-on-save t
        org-roam-ui-open-on-start nil))

(use-package ox-hugo
  :after ox)

(provide 'init-org)

init-latex.el

;;; init-latex.el --- Initialize LaTeX settings -*- lexical-binding: t -*-

;; GhostScript is needed for previewing latex fragments

;;; Code:

;; Note that it *must* be 'use-package latex', if 'auctex' is used instead,
;; 'auctex.el' is never called later, and the :config section is not set.
;; Many (most?) people use 'use-package tex', which is fine and probably
;; more "correct", but then care would have to be taken with variables which
;; are not defined in 'tex.el' (starting with "TeX-"), but in 'latex.el'
;; (starting with "LaTeX-"). As 'latex.el' requires 'tex.el', simply setting
;; 'use-package latex' catches all in one go.
(use-package latex
  :straight auctex
  :config
  (setq
   LaTeX-electric-left-right-brace t
   TeX-parse-self t ;; parse onload
   TeX-auto-save t ;; parse on save
   ;; use hidden dirs for auctex files
   TeX-auto-local ".auctex-auto"
   TeX-style-local ".auctex-style"

   TeX-source-correlate-method 'synctex
   ;; don't start the emacs server when correlating sources
   TeX-source-correlate-start-server nil
   ;; just save, dont ask me before each compilation
   TeX-save-query nil)

  (setq-default TeX-engine 'xetex)

  (setq preview-default-option-list '("displaymath" "floats" "graphics" "textmath" "footnotes"))

  ;; (setq preview-scale-function 1.5)

  (add-to-list 'auto-mode-alist '("\\.tex\\'" . LaTeX-mode))
  (TeX-source-correlate-mode))

(use-package auctex-latexmk
  :straight '(auctex-latexmk :type git :host github :fork "wang1zhen/auctex-latexmk")
  :hook (LaTeX-mode . (lambda ()
                        (setq TeX-command-default "LatexMk")))
  :config
  (setq auctex-latexmk-inherit-TeX-PDF-mode t)
  (auctex-latexmk-setup))

(provide 'init-latex)

init-dired.el

;;; init-dired.el --- Emacs built in file manager -*- lexical-binding: t -*-

;;; Code:

(use-package dired
  :straight nil
  :commands (dired dired-jump)
  :config
  (general-def dired-mode-map "C-c C-p" #'wdired-change-to-wdired-mode)
  (setq dired-listing-switches "-alh --group-directories-first"
        dired-dwim-target t
        dired-recursive-deletes 'always
        dired-recursive-copies 'always))

(use-package dired-rsync
  :after dired
  :config
  (general-def dired-mode-map "C-c C-r" #'dired-rsync))

;; Colourful dired
(use-package diredfl
  :after dired
  :config (diredfl-global-mode 1))

(use-package dired-single
  :after dired
  :bind
  (:map dired-mode-map
        ([remap dired-find-file] . dired-single-buffer)
        ([remap dired-mouse-find-file-other-window] . dired-single-buffer-mouse)
        ([remap dired-up-directory] . dired-single-up-directory)))

(use-package dired-hide-dotfiles
  :after dired
  :hook (dired-mode . dired-hide-dotfiles-mode)
  :config
  (general-def dired-mode-map "H" 'dired-hide-dotfiles-mode))

(provide 'init-dired)

init-projectile.el

;;; init-projectile.el --- Projectile configurations -*- lexical-binding: t -*-

;;; Code:

(use-package projectile
  :diminish
  :hook (after-init . projectile-mode)
  :init
  (setq solarion-projectile-dir "~/solarion-emacs")
  (when (file-directory-p solarion-projectile-dir)
    (setq projectile-project-search-path `(,(file-truename solarion-projectile-dir))))
  (setq projectile-switch-project-action #'projectile-dired)
  :config
  (setq projectile-mode-line-prefix nil
        projectile-sort-order 'recentf
        projectile-use-git-grep t))

(provide 'init-projectile)

init-dashboard.el

;;; init-dashboard.el --- Setup for the splash screen (dashboard) -*- lexical-binding: t -*-

;;; Code:

(use-package dashboard
  :diminish
  :init
  (defun solarion-init-time ()
    "Showing Emacs initializing time, packages loaded and GC"
    (format "Loaded %d packages in %.2f ms."
            (- (length load-path) (length (get 'load-path 'initial-value)))
            (* 1e3 (float-time (time-subtract after-init-time before-init-time)))))
  (setq dashboard-init-info (solarion-init-time))
  (setq dashboard-banner-logo-title (concat "Emacs " emacs-version)
        dashboard-startup-banner "~/.emacs.d/logo.png"
        dashboard-image-banner-max-height 400
        dashboard-page-separator "\n\n"
        dashboard-center-content t
        dashboard-show-shortcuts t
        dashboard-items '((recents . 5)
                          (bookmarks . 5)
                          (projects . 3))
        dashboard-startupify-list '(dashboard-insert-banner
                                    dashboard-insert-newline
                                    dashboard-insert-banner-title
                                    dashboard-insert-newline
                                    dashboard-insert-navigator
                                    dashboard-insert-newline
                                    dashboard-insert-init-info
                                    dashboard-insert-items)
        dashboard-navigator-buttons `(((nil "Homepage (H)" "Browse homepage" solarion-homepage)
                                       (nil "Restore (R)" "Restore previous session" (lambda (&rest _) (restore-previous-session)))
                                       (nil "Config (C)" "Open custom file" solarion-edit-config)
                                       (nil "Update (U)" "Update Packages" (lambda (&rest _) (straight-pull-all))))))
  (when (< (length command-line-args) 2)
    (setq initial-buffer-choice 'dashboard-open))
  :config
  (dashboard-setup-startup-hook)
  (general-def dashboard-mode-map
    "H" #'solarion-homepage
    "R" #'restore-previous-session
    "C" #'solarion-edit-config
    "U" #'straight-pull-all))

(provide 'init-dashboard)

init-vterm.el

;;; init-vterm.el --- Emacs libvterm integration -*- lexical-binding: t -*-

;;; Code:

(when (and module-file-suffix           ;; dynamic module
           (executable-find "cmake")
           (executable-find "libtool")  ;; install libtool-bin
           (executable-find "make"))
  (use-package vterm
    :init
    (setq vterm-always-compile-module t)
    :bind (:map vterm-mode-map
                ("C-\\" . toggle-input-method)
                ("C-q" . vterm-send-next-key)))

  (use-package vterm-toggle
    :bind
    ([f2] . vterm-toggle)
    ([C-f2] . vterm-toggle-cd)
    (:map vterm-mode-map
          ("C-<return>" . vterm-toggle-insert-cd)
          ([f2] . vterm-toggle))))

(provide 'init-vterm)

init-persp.el

Restore previous session.

;;; init-persp.el --- Configurations for persp-mode -*- lexical-binding: t -*-

;;; Code:

(use-package persp-mode
  :diminish
  :hook
  ((after-init . persp-mode)
   (persp-mode . persp-load-frame)
   (kill-emacs . persp-save-frame))
  :init
  (setq persp-keymap-prefix nil
        persp-nil-name "default"
        persp-set-last-persp-for-new-frames nil
        persp-kill-foreign-buffer-behaviour 'kill
        persp-auto-resume-time 0)
  :config
  ;; Save and load frame parameters (size & position)
  (defvar persp-frame-file (expand-file-name "persp-frame" persp-save-dir)
    "File of saving frame parameters.")

  (defun persp-save-frame ()
    "Save the current frame parameters to file."
    (interactive)
    (when (and (display-graphic-p) persp-mode)
      (condition-case error
          (with-temp-buffer
            (erase-buffer)
            (insert
             ";;; -*- mode: emacs-lisp; coding: utf-8-unix -*-\n"
             ";;; This is the previous frame parameters.\n"
             ";;; Last generated " (current-time-string) ".\n"
             "(setq initial-frame-alist\n"
             (format "      '((top . %d)\n" (eval (frame-parameter nil 'top)))
             (format "        (left . %d)\n" (eval (frame-parameter nil 'left)))
             (format "        (width . %d)\n" (eval (frame-parameter nil 'width)))
             (format "        (height . %d)\n" (eval (frame-parameter nil 'height)))
             (format "        (fullscreen . %s)))\n" (frame-parameter nil 'fullscreen)))
            (write-file persp-frame-file))
        (error
         (warn "persp frame: %s" (error-message-string error))))))

  (defun persp-load-frame ()
    "Load frame with the previous frame's geometry."
    (interactive)
    (when (and (display-graphic-p) persp-mode)
      (condition-case error
          (progn
            (load persp-frame-file)

            ;; Handle multiple monitors gracefully
            (when (or (>= (eval (frame-parameter nil 'left)) (display-pixel-width))
                      (>= (eval (frame-parameter nil 'top)) (display-pixel-height)))
              (set-frame-parameter nil 'left 0)
              (set-frame-parameter nil 'top 0)))
        (error
         (warn "persp frame: %s" (error-message-string error))))))

  (defun restore-previous-session ()
    "Restore the previous session."
    (interactive)
    (when (bound-and-true-p persp-mode)
      (restore-session persp-auto-save-fname)))

  (defun restore-session (fname)
    "Restore the specified session."
    (interactive (list (read-file-name "Load perspectives from a file: "
                                       persp-save-dir)))
    (when (bound-and-true-p persp-mode)
      (message "Restoring session...")
      (quit-window t)
      (condition-case-unless-debug err
          (persp-load-state-from-file fname)
        (error "Error: Unable to restore session -- %s" err))
      (message "Restoring session...done")))
  ;; Don't save dead or temporary buffers
  (add-hook 'persp-filter-save-buffers-functions
            (lambda (b)
              "Ignore dead and unneeded buffers."
              (or (not (buffer-live-p b))
                  (string-prefix-p " *" (buffer-name b)))))
  (add-hook 'persp-filter-save-buffers-functions
            (lambda (b)
              "Ignore temporary buffers."
              (let ((bname (file-name-nondirectory (buffer-name b))))
                (or (string-prefix-p ".newsrc" bname)
                    (string-prefix-p "magit" bname)
                    (string-prefix-p "COMMIT_EDITMSG" bname)
                    (string-prefix-p "Pfuture-Callback" bname)
                    (string-prefix-p "treemacs-persist" bname)
                    (string-match-p "\\.elc\\|\\.tar\\|\\.gz\\|\\.zip\\'" bname)
                    (string-match-p "\\.bin\\|\\.so\\|\\.dll\\|\\.exe\\'" bname)))))

  ;; Don't save persp configs in `recentf'
  (with-eval-after-load 'recentf
    (push persp-save-dir recentf-exclude)))

(provide 'init-persp)

init-dict.el

;;; init-dict.el --- Youdao dictionary -*- lexical-binding: t -*-

;;; Code:

(use-package fanyi
  :commands fanyi-dwim
  :custom
  (fanyi-providers '(;; Longman
                     fanyi-longman-provider
                     ;; 海词
                     fanyi-haici-provider
                     ;; 有道同义词词典
                     ;; fanyi-youdao-thesaurus-provider
                     ;; Etymonline
                     ;; fanyi-etymon-provider
                     )))

(provide 'init-dict)

init-im.el

;;; init-im.el --- 输入法相关 -*- lexical-binding: t -*-

;;; Code:

;; requires librime-dev on Debian
(use-package rime
  :init
  (setq default-input-method "rime"
        rime-show-candidate 'posframe
        rime-popup-style 'vertical
        rime-posframe-style 'vertical
        rime-user-data-dir (concat user-emacs-directory "rime/")
        rime-posframe-properties '(:internal-border-width 2))
  :config
  (general-def rime-mode-map "C-`" #'rime-send-keybinding)
  (general-def rime-active-mode-map "S-<delete>" #'rime-send-keybinding))

;; requires emacs-mozc on Debian
(use-package mozc
  :init
  (setq mozc-candidate-style 'echo-area))

(defun solarion/toggle-input-method ()
  "Toggle between nil, rime and japanese-mozc input methods."
  (interactive)
  (cond
   ((equal current-input-method nil)
    (set-input-method 'rime))
   ((equal current-input-method "rime")
    (set-input-method 'japanese-mozc))
   ((equal current-input-method "japanese-mozc")
    (set-input-method 'rime))))

(general-def :keymaps 'override "C-c SPC" #'solarion/toggle-input-method)

(provide 'init-im)

init-wsl.el

;;; init-wsl.el --- wsl-specific setup -*- lexical-binding: t -*-

;;; Code:

;; teach Emacs how to open links with your default browser
(let ((cmd-exe "/mnt/c/Windows/System32/cmd.exe")
      (cmd-args '("/c" "start")))
  (when (file-exists-p cmd-exe)
    (setq browse-url-generic-program  cmd-exe
          browse-url-generic-args     cmd-args
          browse-url-browser-function 'browse-url-generic
          search-web-default-browser 'browse-url-generic)))

;; Fix wayland Copy from wsl to Windows
(setq select-active-regions nil)

(defun wl-copy (text)
  (let ((process-connection-type nil))
    (let ((proc (start-process "wl-copy" "*Messages*" "wl-copy" "-f" "-n")))
      (process-send-string proc text)
      (process-send-eof proc))))

(defun wl-paste ()
  (shell-command-to-string "wl-paste -n"))

;; (setq interprogram-cut-function 'wl-copy)
;; (setq interprogram-paste-function 'wl-paste)

(provide 'init-wsl)

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published