mirror of
https://gitlab.com/dwt1/dotfiles.git
synced 2026-04-23 03:20:26 +10:00
Moving to Doom Emacs!
This commit is contained in:
561
.emacs.d/core/core-editor.el
Normal file
561
.emacs.d/core/core-editor.el
Normal file
@@ -0,0 +1,561 @@
|
||||
;;; core-editor.el -*- lexical-binding: t; -*-
|
||||
|
||||
(defvar doom-detect-indentation-excluded-modes '(fundamental-mode so-long-mode)
|
||||
"A list of major modes in which indentation should be automatically
|
||||
detected.")
|
||||
|
||||
(defvar-local doom-inhibit-indent-detection nil
|
||||
"A buffer-local flag that indicates whether `dtrt-indent' should try to detect
|
||||
indentation settings or not. This should be set by editorconfig if it
|
||||
successfully sets indent_style/indent_size.")
|
||||
|
||||
(defvar-local doom-large-file-p nil)
|
||||
(put 'doom-large-file-p 'permanent-local t)
|
||||
|
||||
(defvar doom-large-file-size-alist '((t . 1.0))
|
||||
"An alist mapping major mode to filesize thresholds.
|
||||
|
||||
If a file is opened and discovered to be larger than the threshold, Doom
|
||||
performs emergency optimizations to prevent Emacs from hanging, crashing or
|
||||
becoming unusably slow.
|
||||
|
||||
These thresholds are in MB, and is used by `doom--optimize-for-large-files-a'.")
|
||||
|
||||
(defvar doom-large-file-excluded-modes
|
||||
'(so-long-mode special-mode archive-mode tar-mode jka-compr
|
||||
git-commit-mode image-mode doc-view-mode doc-view-mode-maybe
|
||||
ebrowse-tree-mode pdf-view-mode tags-table-mode)
|
||||
"Major modes that `doom-check-large-file-h' will ignore.")
|
||||
|
||||
|
||||
;;
|
||||
;;; File handling
|
||||
|
||||
(defadvice! doom--optimize-for-large-files-a (orig-fn &rest args)
|
||||
"Set `doom-large-file-p' if the file is too large.
|
||||
|
||||
Uses `doom-large-file-size-alist' to determine when a file is too large. When
|
||||
`doom-large-file-p' is set, other plugins can detect this and reduce their
|
||||
runtime costs (or disable themselves) to ensure the buffer is as fast as
|
||||
possible."
|
||||
:around #'after-find-file
|
||||
(if (setq doom-large-file-p
|
||||
(and buffer-file-name
|
||||
(not doom-large-file-p)
|
||||
(file-readable-p buffer-file-name)
|
||||
(> (nth 7 (file-attributes buffer-file-name))
|
||||
(* 1024 1024
|
||||
(cdr (or (assq major-mode doom-large-file-size-alist)
|
||||
(assq 't doom-large-file-size-alist)))))))
|
||||
(prog1 (apply orig-fn args)
|
||||
(if (memq major-mode doom-large-file-excluded-modes)
|
||||
(setq doom-large-file-p nil)
|
||||
(so-long-minor-mode +1)
|
||||
(message "Large file detected! Cutting a few corners to improve performance...")))
|
||||
(apply orig-fn args)))
|
||||
|
||||
;; Resolve symlinks when opening files, so that any operations are conducted
|
||||
;; from the file's true directory (like `find-file').
|
||||
(setq find-file-visit-truename t
|
||||
vc-follow-symlinks t)
|
||||
|
||||
;; Disable the warning "X and Y are the same file". It's fine to ignore this
|
||||
;; warning as it will redirect you to the existing buffer anyway.
|
||||
(setq find-file-suppress-same-file-warnings t)
|
||||
|
||||
;; Create missing directories when we open a file that doesn't exist under a
|
||||
;; directory tree that may not exist.
|
||||
(add-hook! 'find-file-not-found-functions
|
||||
(defun doom-create-missing-directories-h ()
|
||||
"Automatically create missing directories when creating new files."
|
||||
(unless (file-remote-p buffer-file-name)
|
||||
(let ((parent-directory (file-name-directory buffer-file-name)))
|
||||
(and (not (file-directory-p parent-directory))
|
||||
(y-or-n-p (format "Directory `%s' does not exist! Create it?"
|
||||
parent-directory))
|
||||
(progn (make-directory parent-directory 'parents)
|
||||
t))))))
|
||||
|
||||
;; Don't autosave files or create lock/history/backup files. We don't want
|
||||
;; copies of potentially sensitive material floating around, and we'll rely on
|
||||
;; git and our own good fortune instead. Fingers crossed!
|
||||
(setq auto-save-default nil
|
||||
create-lockfiles nil
|
||||
make-backup-files nil
|
||||
;; But have a place to store them in case we do use them...
|
||||
auto-save-list-file-name (concat doom-cache-dir "autosave")
|
||||
backup-directory-alist `(("." . ,(concat doom-cache-dir "backup/"))))
|
||||
|
||||
(add-hook! 'after-save-hook
|
||||
(defun doom-guess-mode-h ()
|
||||
"Guess mode when saving a file in `fundamental-mode'."
|
||||
(and (eq major-mode 'fundamental-mode)
|
||||
(buffer-file-name (buffer-base-buffer))
|
||||
(eq (current-buffer) (window-buffer (selected-window))) ; only visible buffers
|
||||
(set-auto-mode))))
|
||||
|
||||
|
||||
;;
|
||||
;;; Formatting
|
||||
|
||||
;; Indentation
|
||||
(setq-default tab-width 4
|
||||
tab-always-indent t
|
||||
indent-tabs-mode nil
|
||||
fill-column 80)
|
||||
|
||||
;; Word wrapping
|
||||
(setq-default word-wrap t
|
||||
truncate-lines t
|
||||
truncate-partial-width-windows nil)
|
||||
|
||||
(setq sentence-end-double-space nil
|
||||
delete-trailing-lines nil
|
||||
require-final-newline t
|
||||
tabify-regexp "^\t* [ \t]+") ; for :retab
|
||||
|
||||
;; Favor hard-wrapping in text modes
|
||||
(add-hook 'text-mode-hook #'auto-fill-mode)
|
||||
|
||||
|
||||
;;
|
||||
;;; Clipboard / kill-ring
|
||||
|
||||
;; Eliminate duplicates in the kill ring. That is, if you kill the same thing
|
||||
;; twice, you won't have to use M-y twice to get past it to older entries in the
|
||||
;; kill ring.
|
||||
(setq kill-do-not-save-duplicates t)
|
||||
|
||||
;;
|
||||
(setq x-select-request-type '(UTF8_STRING COMPOUND_TEXT TEXT STRING))
|
||||
|
||||
;; Save clipboard contents into kill-ring before replacing them
|
||||
(setq save-interprogram-paste-before-kill t)
|
||||
|
||||
;; Fixes the clipboard in tty Emacs by piping clipboard I/O through xclip, xsel,
|
||||
;; pb{copy,paste}, wl-copy, termux-clipboard-get, or getclip (cygwin).
|
||||
(add-hook! 'tty-setup-hook
|
||||
(defun doom-init-clipboard-in-tty-emacs-h ()
|
||||
(and (not (getenv "SSH_CONNECTION"))
|
||||
(require 'xclip nil t)
|
||||
(xclip-mode +1))))
|
||||
|
||||
|
||||
;;
|
||||
;;; Extra file extensions to support
|
||||
|
||||
(push '("/LICENSE\\'" . text-mode) auto-mode-alist)
|
||||
(push '("\\.log\\'" . text-mode) auto-mode-alist)
|
||||
|
||||
|
||||
;;
|
||||
;;; Built-in plugins
|
||||
|
||||
(use-package! autorevert
|
||||
;; revert buffers when their files/state have changed
|
||||
:hook (focus-in . doom-auto-revert-buffers-h)
|
||||
:hook (after-save . doom-auto-revert-buffers-h)
|
||||
:hook (doom-switch-buffer . doom-auto-revert-buffer-h)
|
||||
:hook (doom-switch-window . doom-auto-revert-buffer-h)
|
||||
:config
|
||||
(setq auto-revert-verbose t ; let us know when it happens
|
||||
auto-revert-use-notify nil
|
||||
auto-revert-stop-on-user-input nil
|
||||
;; Only prompts for confirmation when buffer is unsaved.
|
||||
revert-without-query (list "."))
|
||||
|
||||
;; Instead of using `auto-revert-mode' or `global-auto-revert-mode', we employ
|
||||
;; lazy auto reverting on `focus-in-hook' and `doom-switch-buffer-hook'.
|
||||
;;
|
||||
;; This is because autorevert abuses the heck out of inotify handles which can
|
||||
;; grind Emacs to a halt if you do expensive IO (outside of Emacs) on the
|
||||
;; files you have open (like compression). We only really need to revert
|
||||
;; changes when we switch to a buffer or when we focus the Emacs frame.
|
||||
(defun doom-auto-revert-buffer-h ()
|
||||
"Auto revert current buffer, if necessary."
|
||||
(unless (or auto-revert-mode (active-minibuffer-window))
|
||||
(auto-revert-handler)))
|
||||
|
||||
(defun doom-auto-revert-buffers-h ()
|
||||
"Auto revert stale buffers in visible windows, if necessary."
|
||||
(dolist (buf (doom-visible-buffers))
|
||||
(with-current-buffer buf
|
||||
(doom-auto-revert-buffer-h)))))
|
||||
|
||||
|
||||
(use-package! recentf
|
||||
;; Keep track of recently opened files
|
||||
:defer-incrementally easymenu tree-widget timer
|
||||
:after-call after-find-file
|
||||
:commands recentf-open-files
|
||||
:config
|
||||
(defun doom--recent-file-truename (file)
|
||||
(if (or (file-remote-p file nil t)
|
||||
(not (file-remote-p file)))
|
||||
(file-truename file)
|
||||
file))
|
||||
(setq recentf-filename-handlers '(doom--recent-file-truename abbreviate-file-name))
|
||||
|
||||
(setq recentf-save-file (concat doom-cache-dir "recentf")
|
||||
recentf-auto-cleanup 'never
|
||||
recentf-max-menu-items 0
|
||||
recentf-max-saved-items 200)
|
||||
|
||||
(add-hook! '(doom-switch-window-hook write-file-functions)
|
||||
(defun doom--recentf-touch-buffer-h ()
|
||||
"Bump file in recent file list when it is switched or written to."
|
||||
(when buffer-file-name
|
||||
(recentf-add-file buffer-file-name))
|
||||
;; Return nil for `write-file-functions'
|
||||
nil))
|
||||
|
||||
(add-hook! 'dired-mode-hook
|
||||
(defun doom--recentf-add-dired-directory-h ()
|
||||
"Add dired directory to recentf file list."
|
||||
(recentf-add-file default-directory)))
|
||||
|
||||
(when doom-interactive-mode
|
||||
(add-hook 'kill-emacs-hook #'recentf-cleanup)
|
||||
(quiet! (recentf-mode +1))))
|
||||
|
||||
|
||||
(use-package! savehist
|
||||
;; persist variables across sessions
|
||||
:defer-incrementally custom
|
||||
:after-call post-command-hook
|
||||
:config
|
||||
(setq savehist-file (concat doom-cache-dir "savehist")
|
||||
savehist-save-minibuffer-history t
|
||||
savehist-autosave-interval nil ; save on kill only
|
||||
savehist-additional-variables '(kill-ring search-ring regexp-search-ring))
|
||||
(savehist-mode +1)
|
||||
|
||||
(add-hook! 'kill-emacs-hook
|
||||
(defun doom-unpropertize-kill-ring-h ()
|
||||
"Remove text properties from `kill-ring' for a smaller savehist file."
|
||||
(setq kill-ring (cl-loop for item in kill-ring
|
||||
if (stringp item)
|
||||
collect (substring-no-properties item)
|
||||
else if item collect it)))))
|
||||
|
||||
|
||||
(use-package! saveplace
|
||||
;; persistent point location in buffers
|
||||
:after-call after-find-file dired-initial-position-hook
|
||||
:config
|
||||
(setq save-place-file (concat doom-cache-dir "saveplace")
|
||||
save-place-limit 100)
|
||||
|
||||
(defadvice! doom--recenter-on-load-saveplace-a (&rest _)
|
||||
"Recenter on cursor when loading a saved place."
|
||||
:after-while #'save-place-find-file-hook
|
||||
(if buffer-file-name (ignore-errors (recenter))))
|
||||
|
||||
(defadvice! doom--dont-prettify-saveplace-cache-a (orig-fn)
|
||||
"`save-place-alist-to-file' uses `pp' to prettify the contents of its cache.
|
||||
`pp' can be expensive for longer lists, and there's no reason to prettify cache
|
||||
files, so we replace calls to `pp' with the much faster `prin1'."
|
||||
:around #'save-place-alist-to-file
|
||||
(cl-letf (((symbol-function #'pp)
|
||||
(symbol-function #'prin1)))
|
||||
(funcall orig-fn)))
|
||||
|
||||
(save-place-mode +1))
|
||||
|
||||
|
||||
(use-package! server
|
||||
:when (display-graphic-p)
|
||||
:after-call pre-command-hook after-find-file focus-out-hook
|
||||
:init
|
||||
(when-let (name (getenv "EMACS_SERVER_NAME"))
|
||||
(setq server-name name))
|
||||
:config
|
||||
(unless (server-running-p)
|
||||
(server-start)))
|
||||
|
||||
|
||||
;;
|
||||
;;; Packages
|
||||
|
||||
(use-package! better-jumper
|
||||
:after-call pre-command-hook
|
||||
:preface
|
||||
;; REVIEW Suppress byte-compiler warning spawning a *Compile-Log* buffer at
|
||||
;; startup. This can be removed once gilbertw1/better-jumper#2 is merged.
|
||||
(defvar better-jumper-local-mode nil)
|
||||
:init
|
||||
(global-set-key [remap evil-jump-forward] #'better-jumper-jump-forward)
|
||||
(global-set-key [remap evil-jump-backward] #'better-jumper-jump-backward)
|
||||
(global-set-key [remap xref-pop-marker-stack] #'better-jumper-jump-backward)
|
||||
:config
|
||||
(better-jumper-mode +1)
|
||||
(add-hook 'better-jumper-post-jump-hook #'recenter)
|
||||
|
||||
(defadvice! doom-set-jump-a (orig-fn &rest args)
|
||||
"Set a jump point and ensure ORIG-FN doesn't set any new jump points."
|
||||
(better-jumper-set-jump (if (markerp (car args)) (car args)))
|
||||
(let ((evil--jumps-jumping t)
|
||||
(better-jumper--jumping t))
|
||||
(apply orig-fn args)))
|
||||
|
||||
(defadvice! doom-set-jump-maybe-a (orig-fn &rest args)
|
||||
"Set a jump point if ORIG-FN returns non-nil."
|
||||
(let ((origin (point-marker))
|
||||
(result
|
||||
(let* ((evil--jumps-jumping t)
|
||||
(better-jumper--jumping t))
|
||||
(apply orig-fn args))))
|
||||
(unless result
|
||||
(with-current-buffer (marker-buffer origin)
|
||||
(better-jumper-set-jump
|
||||
(if (markerp (car args))
|
||||
(car args)
|
||||
origin))))
|
||||
result))
|
||||
|
||||
(defun doom-set-jump-h ()
|
||||
"Run `better-jumper-set-jump' but return nil, for short-circuiting hooks."
|
||||
(better-jumper-set-jump)
|
||||
nil)
|
||||
|
||||
;; Creates a jump point before killing a buffer. This allows you to undo
|
||||
;; killing a buffer easily (only works with file buffers though; it's not
|
||||
;; possible to resurrect special buffers).
|
||||
(advice-add #'kill-current-buffer :around #'doom-set-jump-a)
|
||||
|
||||
;; Create a jump point before jumping with imenu.
|
||||
(advice-add #'imenu :around #'doom-set-jump-a))
|
||||
|
||||
|
||||
(use-package! dtrt-indent
|
||||
;; Automatic detection of indent settings
|
||||
:when doom-interactive-mode
|
||||
:defer t
|
||||
:init
|
||||
(add-hook! '(change-major-mode-after-body-hook read-only-mode-hook)
|
||||
(defun doom-detect-indentation-h ()
|
||||
(unless (or (not after-init-time)
|
||||
doom-inhibit-indent-detection
|
||||
doom-large-file-p
|
||||
(memq major-mode doom-detect-indentation-excluded-modes)
|
||||
(member (substring (buffer-name) 0 1) '(" " "*")))
|
||||
;; Don't display messages in the echo area, but still log them
|
||||
(let ((inhibit-message (not doom-debug-mode)))
|
||||
(dtrt-indent-mode +1)))))
|
||||
:config
|
||||
;; Enable dtrt-indent even in smie modes so that it can update `tab-width',
|
||||
;; `standard-indent' and `evil-shift-width' there as well.
|
||||
(setq dtrt-indent-run-after-smie t)
|
||||
;; Reduced from the default of 5000 for slightly faster analysis
|
||||
(setq dtrt-indent-max-lines 2000)
|
||||
|
||||
;; always keep tab-width up-to-date
|
||||
(push '(t tab-width) dtrt-indent-hook-generic-mapping-list)
|
||||
|
||||
(defvar dtrt-indent-run-after-smie)
|
||||
(defadvice! doom--fix-broken-smie-modes-a (orig-fn arg)
|
||||
"Some smie modes throw errors when trying to guess their indentation, like
|
||||
`nim-mode'. This prevents them from leaving Emacs in a broken state."
|
||||
:around #'dtrt-indent-mode
|
||||
(let ((dtrt-indent-run-after-smie dtrt-indent-run-after-smie))
|
||||
(cl-letf* ((old-smie-config-guess (symbol-function 'smie-config-guess))
|
||||
(old-smie-config--guess (symbol-function 'symbol-config--guess))
|
||||
((symbol-function 'symbol-config--guess)
|
||||
(lambda (beg end)
|
||||
(funcall old-smie-config--guess beg (min end 10000))))
|
||||
((symbol-function 'smie-config-guess)
|
||||
(lambda ()
|
||||
(condition-case e (funcall old-smie-config-guess)
|
||||
(error (setq dtrt-indent-run-after-smie t)
|
||||
(message "[WARNING] Indent detection: %s"
|
||||
(error-message-string e))
|
||||
(message "")))))) ; warn silently
|
||||
(funcall orig-fn arg)))))
|
||||
|
||||
|
||||
(use-package! helpful
|
||||
;; a better *help* buffer
|
||||
:commands helpful--read-symbol
|
||||
:init
|
||||
(define-key!
|
||||
[remap describe-function] #'helpful-callable
|
||||
[remap describe-command] #'helpful-command
|
||||
[remap describe-variable] #'helpful-variable
|
||||
[remap describe-key] #'helpful-key
|
||||
[remap describe-symbol] #'doom/describe-symbol)
|
||||
|
||||
(defun doom-use-helpful-a (orig-fn &rest args)
|
||||
"Force ORIG-FN to use helpful instead of the old describe-* commands."
|
||||
(cl-letf (((symbol-function #'describe-function) #'helpful-function)
|
||||
((symbol-function #'describe-variable) #'helpful-variable))
|
||||
(apply orig-fn args)))
|
||||
|
||||
(after! apropos
|
||||
;; patch apropos buttons to call helpful instead of help
|
||||
(dolist (fun-bt '(apropos-function apropos-macro apropos-command))
|
||||
(button-type-put
|
||||
fun-bt 'action
|
||||
(lambda (button)
|
||||
(helpful-callable (button-get button 'apropos-symbol)))))
|
||||
(dolist (var-bt '(apropos-variable apropos-user-option))
|
||||
(button-type-put
|
||||
var-bt 'action
|
||||
(lambda (button)
|
||||
(helpful-variable (button-get button 'apropos-symbol)))))))
|
||||
|
||||
|
||||
;;;###package imenu
|
||||
(add-hook 'imenu-after-jump-hook #'recenter)
|
||||
|
||||
|
||||
(use-package! smartparens
|
||||
;; Auto-close delimiters and blocks as you type. It's more powerful than that,
|
||||
;; but that is all Doom uses it for.
|
||||
:after-call doom-switch-buffer-hook after-find-file
|
||||
:commands sp-pair sp-local-pair sp-with-modes sp-point-in-comment sp-point-in-string
|
||||
:config
|
||||
;; Load default smartparens rules for various languages
|
||||
(require 'smartparens-config)
|
||||
|
||||
;; Overlays are too distracting and not terribly helpful. show-parens does
|
||||
;; this for us already, so...
|
||||
(setq sp-highlight-pair-overlay nil
|
||||
sp-highlight-wrap-overlay nil
|
||||
sp-highlight-wrap-tag-overlay nil)
|
||||
;; But if someone does want overlays enabled, evil users will be stricken with
|
||||
;; an off-by-one issue where smartparens assumes you're outside the pair when
|
||||
;; you're really at the last character in insert mode. We must correct this
|
||||
;; vile injustice.
|
||||
(setq sp-show-pair-from-inside t)
|
||||
;; ...and stay highlighted until we've truly escaped the pair!
|
||||
(setq sp-cancel-autoskip-on-backward-movement nil)
|
||||
;; The default is 100, because smartparen's scans are relatively expensive
|
||||
;; (especially with large pair lists for somoe modes), we halve it, as a
|
||||
;; better compromise between performance and accuracy.
|
||||
(setq sp-max-prefix-length 50)
|
||||
;; This speeds up smartparens. No pair has any business being longer than 4
|
||||
;; characters; if they must, the modes that need it set it buffer-locally.
|
||||
(setq sp-max-pair-length 4)
|
||||
;; This isn't always smart enough to determine when we're in a string or not.
|
||||
;; See https://github.com/Fuco1/smartparens/issues/783.
|
||||
(setq sp-escape-quotes-after-insert nil)
|
||||
|
||||
;; Silence some harmless but annoying echo-area spam
|
||||
(dolist (key '(:unmatched-expression :no-matching-tag))
|
||||
(setf (cdr (assq key sp-message-alist)) nil))
|
||||
|
||||
(add-hook! 'minibuffer-setup-hook
|
||||
(defun doom-init-smartparens-in-minibuffer-maybe-h ()
|
||||
"Enable `smartparens-mode' in the minibuffer, during `eval-expression' or
|
||||
`evil-ex'."
|
||||
(when (memq this-command '(eval-expression evil-ex))
|
||||
(smartparens-mode))))
|
||||
|
||||
;; You're likely writing lisp in the minibuffer, therefore, disable these
|
||||
;; quote pairs, which lisps doesn't use for strings:
|
||||
(sp-local-pair 'minibuffer-inactive-mode "'" nil :actions nil)
|
||||
(sp-local-pair 'minibuffer-inactive-mode "`" nil :actions nil)
|
||||
|
||||
;; Smartparens breaks evil-mode's replace state
|
||||
(defvar doom-buffer-smartparens-mode nil)
|
||||
(add-hook! 'evil-replace-state-exit-hook
|
||||
(defun doom-enable-smartparens-mode-maybe-h ()
|
||||
(when doom-buffer-smartparens-mode
|
||||
(turn-on-smartparens-mode)
|
||||
(kill-local-variable 'doom-buffer-smartparens-mode))))
|
||||
(add-hook! 'evil-replace-state-entry-hook
|
||||
(defun doom-disable-smartparens-mode-maybe-h ()
|
||||
(when smartparens-mode
|
||||
(setq-local doom-buffer-smartparens-mode t)
|
||||
(turn-off-smartparens-mode))))
|
||||
|
||||
(smartparens-global-mode +1))
|
||||
|
||||
|
||||
(use-package! so-long
|
||||
:after-call after-find-file
|
||||
:config
|
||||
(when doom-interactive-mode
|
||||
(global-so-long-mode +1))
|
||||
;; Don't disable syntax highlighting and line numbers, or make the buffer
|
||||
;; read-only, in `so-long-minor-mode', so we can have a basic editing
|
||||
;; experience in them, at least. It will remain off in `so-long-mode',
|
||||
;; however, because long files have a far bigger impact on Emacs performance.
|
||||
(delq! 'font-lock-mode so-long-minor-modes)
|
||||
(delq! 'display-line-numbers-mode so-long-minor-modes)
|
||||
(delq! 'buffer-read-only so-long-variable-overrides 'assq)
|
||||
;; ...but at least reduce the level of syntax highlighting
|
||||
(add-to-list 'so-long-variable-overrides '(font-lock-maximum-decoration . 1))
|
||||
;; Text files could possibly be too long too
|
||||
(add-to-list 'so-long-target-modes 'text-mode)
|
||||
;; But disable everything else that may be unnecessary/expensive for large
|
||||
;; or wide buffers.
|
||||
(appendq! so-long-minor-modes
|
||||
'(flycheck-mode
|
||||
flyspell-mode
|
||||
eldoc-mode
|
||||
smartparens-mode
|
||||
highlight-numbers-mode
|
||||
better-jumper-local-mode
|
||||
ws-butler-mode
|
||||
auto-composition-mode
|
||||
undo-tree-mode
|
||||
highlight-indent-guides-mode
|
||||
hl-fill-column-mode))
|
||||
;; HACK Fix #2183: `so-long-detected-long-line-p' tries to parse comment
|
||||
;; syntax, but in some buffers comment state isn't initialized, leading
|
||||
;; to a wrong-type-argument: stringp error.
|
||||
(defun doom-buffer-has-long-lines-p ()
|
||||
(when (bound-and-true-p comment-use-syntax)
|
||||
(so-long-detected-long-line-p)))
|
||||
(setq so-long-predicate #'doom-buffer-has-long-lines-p))
|
||||
|
||||
|
||||
(use-package! undo-tree
|
||||
;; Branching & persistent undo
|
||||
:after-call doom-switch-buffer-hook after-find-file
|
||||
:config
|
||||
(setq undo-tree-auto-save-history t
|
||||
;; Increase undo-limits by a factor of ten to avoid emacs prematurely
|
||||
;; truncating the undo history and corrupting the tree. See
|
||||
;; https://github.com/syl20bnr/spacemacs/issues/12110
|
||||
undo-limit 800000
|
||||
undo-strong-limit 12000000
|
||||
undo-outer-limit 120000000
|
||||
undo-tree-history-directory-alist
|
||||
`(("." . ,(concat doom-cache-dir "undo-tree-hist/"))))
|
||||
|
||||
;; Compress undo-tree history files with zstd, if available. File size isn't
|
||||
;; the (only) concern here: the file IO barrier is slow for Emacs to cross;
|
||||
;; reading a tiny file and piping it in-memory through zstd is *slightly*
|
||||
;; faster than Emacs reading the entire undo-tree file from the get go (on
|
||||
;; SSDs). Whether or not that's true in practice, we still enjoy zstd's ~80%
|
||||
;; file savings (these files add up over time and zstd is so incredibly fast).
|
||||
(when (executable-find "zstd")
|
||||
(defadvice! doom--undo-tree-make-history-save-file-name-a (file)
|
||||
:filter-return #'undo-tree-make-history-save-file-name
|
||||
(concat file ".zst")))
|
||||
|
||||
;; Strip text properties from undo-tree data to stave off bloat. File size
|
||||
;; isn't the concern here; undo cache files bloat easily, which can cause
|
||||
;; freezing, crashes, GC-induced stuttering or delays when opening files.
|
||||
(defadvice! doom--undo-tree-strip-text-properties-a (&rest _)
|
||||
:before #'undo-list-transfer-to-tree
|
||||
(dolist (item buffer-undo-list)
|
||||
(and (consp item)
|
||||
(stringp (car item))
|
||||
(setcar item (substring-no-properties (car item))))))
|
||||
|
||||
(global-undo-tree-mode +1))
|
||||
|
||||
|
||||
(use-package! ws-butler
|
||||
;; a less intrusive `delete-trailing-whitespaces' on save
|
||||
:after-call after-find-file
|
||||
:config
|
||||
(appendq! ws-butler-global-exempt-modes
|
||||
'(special-mode comint-mode term-mode eshell-mode))
|
||||
(ws-butler-global-mode))
|
||||
|
||||
(provide 'core-editor)
|
||||
;;; core-editor.el ends here
|
||||
Reference in New Issue
Block a user