Files
nixos-configs/hosts/pinwheel/modules/emacs/config.org
2023-09-10 21:32:56 +02:00

426 lines
11 KiB
Org Mode

#+PROPERTY: header-args :emacs-lisp :tangle yes
* Initialization
** Package handling (by Nix)
#+BEGIN_SRC emacs-lisp
(when (featurep 'nativecomp)
(setq comp-deferred-compilation nil))
#+END_SRC
*** Use package autoloads provided by Nix
#+BEGIN_SRC emacs-lisp
(defvar package-quickstart t)
#+END_SRC
*** Disable impure packages (as in not already fetched by Nix)
#+BEGIN_SRC emacs-lisp
(setq package-archives nil)
#+END_SRC
*** Initialize `use-package`
`bind-key` is required by `use-package`
#+BEGIN_SRC emacs-lisp
(use-package bind-key
:config
(add-to-list 'same-window-buffer-names "*Personal Keybindings*"))
;; (eval-when-compile
;; (require 'use-package))
;; (use-package quelpa-use-package)
#+END_SRC
** Optimization
*** Time startup
#+BEGIN_SRC emacs-lisp
(add-hook 'emacs-startup-hook
(lambda ()
(message "Started emacs in %.03fs"
(float-time (time-subtract after-init-time before-init-time)))))
#+END_SRC
*** Keep a reference to the actual file-name-handler.
#+BEGIN_SRC emacs-lisp
(defvar file-name-handler-alist-actual file-name-handler-alist)
#+END_SRC
*** Set the file-name-handler to nil (because regexing is cpu intensive)
#+BEGIN_SRC emacs-lisp
(setq file-name-handler-alist nil)
#+END_SRC
*** Increase the gc threshold significantly for faster startup
#+BEGIN_SRC emacs-lisp
(setq gc-cons-threshold most-positive-fixnum)
(add-hook 'emacs-startup-hook
(lambda ()
(setq gc-cons-threshold 16777216 ; 16mb
gc-cons-percentage 0.1)))
#+END_SRC
*** The default is very low - 4k, lsp server responses are easily much larger
#+BEGIN_SRC emacs-lisp
(setq read-process-output-max (* 1024 1024)) ;; 1mb
#+END_SRC
*** Reset file-name-handler-alist after initialization
#+BEGIN_SRC emacs-lisp
(add-hook 'after-init-hook
(lambda ()
(garbage-collect)
(setq file-name-handler-alist file-name-handler-alist-actual)) t)
#+END_SRC
*** This makes emacsclient startup faster in TUI-mode
#+BEGIN_SRC emacs-lisp
(setq-default xterm-query-timeout nil)
#+END_SRC
*** Disable startup messages
#+BEGIN_SRC emacs-lisp
(setq inhibit-startup-message t)
(setq initial-buffer-choice t)
(setq initial-scratch-message nil)
#+END_SRC
*** Don't resize gui when setting new font
... it affecs startup time
#+BEGIN_SRC emacs-lisp
(setq frame-inhibit-implied-resize t)
#+END_SRC
*** Skip loading default lib, use fundamental-mode
#+BEGIN_SRC emacs-lisp
(setq inhibit-default-init t
initial-major-mode 'fundamental-mode)
#+END_SRC
* Setup
#+BEGIN_SRC emacs-lisp
(setq confirm-kill-processes nil)
#+END_SRC
** Use wl-clipboard for interprocess copy/paste
#+BEGIN_SRC emacs-lisp
(setq wl-copy-process nil)
(defun wl-copy (text)
(setq wl-copy-process (make-process :name "wl-copy"
:buffer nil
:command '("wl-copy" "-f" "-n")
:connection-type 'pipe))
(process-send-string wl-copy-process text)
(process-send-eof wl-copy-process))
(defun wl-paste ()
(if (and wl-copy-process (process-live-p wl-copy-process))
nil ; should return nil if we're the current paste owner
(shell-command-to-string "wl-paste -n | tr -d \r")))
(when (display-graphic-p)
(setq interprogram-cut-function 'wl-copy)
(setq interprogram-paste-function 'wl-paste)
)
#+END_SRC
** Don't create backup files, don't create #autosave# files
#+BEGIN_SRC emacs-lisp
(setq temporary-file-directory "~/.emacs.d/tmp/")
(unless (file-exists-p "~/.emacs.d/tmp")
(make-directory "~/.emacs.d/tmp"))
(setq backup-inhibited t
make-backup-files nil ; don't create backup~ files
create-lockfiles nil
auto-save-default nil) ; don't create #autosave# files
#+END_SRC
** Don't store custom settings
#+BEGIN_SRC emacs-lisp
(setq custom-file null-device)
#+END_SRC
* Look and feel
** Font
#+BEGIN_SRC emacs-lisp
(set-face-attribute 'default nil :font "DejaVuSansM Nerd Font Mono" :height 160)
#+END_SRC
** Icons
#+BEGIN_SRC emacs-lisp
(use-package all-the-icons)
#+END_SRC
** Modeline
#+BEGIN_SRC emacs-lisp
(use-package doom-modeline
:init (doom-modeline-mode 1)
:custom ((doom-modeline-height 15)))
#+END_SRC
** Theme
#+BEGIN_SRC emacs-lisp
(use-package doom-themes
:init (load-theme 'doom-dracula t))
#+END_SRC
** Disable the menu bar
#+BEGIN_SRC emacs-lisp
(menu-bar-mode -1)
#+END_SRC
** Disable the tool bar
#+BEGIN_SRC emacs-lisp
(tool-bar-mode -1)
#+END_SRC
** Disable the scroll bar
#+BEGIN_SRC emacs-lisp
(scroll-bar-mode -1)
#+END_SRC
** Disable tool tips
#+BEGIN_SRC emacs-lisp
(tooltip-mode -1)
#+END_SRC
** Add margin left of buffers
#+BEGIN_SRC emacs-lisp
(set-fringe-mode 10)
#+END_SRC
** Faster "confirm kill"
#+BEGIN_SRC emacs-lisp
(setq confirm-kill-emacs 'y-or-n-p)
#+END_SRC
** Use ESC to quit prompts
#+BEGIN_SRC emacs-lisp
(global-set-key (kbd "<escape>") 'keyboard-escape-quit)
#+END_SRC
** Enable column numbers
#+BEGIN_SRC emacs-lisp
(column-number-mode)
#+END_SRC
** Enable line numbers
#+BEGIN_SRC emacs-lisp
(global-display-line-numbers-mode t)
(setq display-line-numbers-width-start t)
#+END_SRC
** Show trailing whitespace (when programming and in org-mode)
#+BEGIN_SRC emacs-lisp
(add-hook 'prog-mode-hook
(lambda ()
(setq show-trailing-whitespace t)))
(add-hook 'org-mode-hook
(lambda ()
(setq show-trailing-whitespace t)))
#+END_SRC
** Auto-insert matching parenthesis (when programming)
#+BEGIN_SRC emacs-lisp
(add-hook 'prog-mode-hook 'electric-pair-mode)
#+END_SRC
** Hilight parethesis (when programming)
#+BEGIN_SRC emacs-lisp
(defun my-show-paren-mode ()
"Enables show-paren-mode."
(setq show-paren-delay 0)
(set-face-background 'show-paren-match (face-background 'default))
(set-face-foreground 'show-paren-match "#def")
(set-face-attribute 'show-paren-match nil :weight 'extra-bold)
(show-paren-mode 1))
(add-hook 'prog-mode-hook 'my-show-paren-mode)
#+END_SRC
** Calendar
*** Show week numbers
#+BEGIN_SRC emacs-lisp
(setq calendar-intermonth-text
'(propertize
(format "%2d"
(car
(calendar-iso-from-absolute
(calendar-absolute-from-gregorian (list month day year)))))
'font-lock-face 'calendar-iso-week-face))
(setq calendar-intermonth-header
(propertize "Wk" 'font-lock-face 'font-lock-keyword-face))
#+END_SRC
*** Begin week with monday
#+BEGIN_SRC emacs-lisp
(setq calendar-week-start-day 1)
#+END_SRC
** Tabs
*** Enable tabs
#+BEGIN_SRC emacs-lisp
(tab-bar-mode 1)
#+END_SRC
*** Remove tab buttons
#+BEGIN_SRC emacs-lisp
(setq tab-bar-close-button-show nil)
(setq tab-bar-new-button-show nil)
#+END_SRC
*** Close tabs with :q
#+BEGIN_SRC emacs-lisp
(defun alex/close-tab (orig-fun &rest args)
"Close tab instead of calling ORIG-FUN if there is more than a single tab."
(if (cdr (tab-bar-tabs))
(tab-bar-close-tab)
(apply orig-fun args)))
(advice-add #'evil-quit :around #'alex/close-tab)
#+END_SRC
* Completion
** Consult
Consult provides search and navigation commands based on the Emacs completion function completing-read.
https://github.com/minad/consult
#+BEGIN_SRC emacs-lisp
(use-package consult
:bind
("C-x b" . 'consult-buffer))
#+END_SRC
** Orderless completion
Allow orderless completion, e.g. `org mode` and `mode org` return same result
https://github.com/oantolin/orderless
#+BEGIN_SRC emacs-lisp
(use-package orderless
:custom (completion-styles '(orderless)))
#+END_SRC
** Helpful
https://github.com/Wilfred/helpful
#+BEGIN_SRC emacs-lisp
(use-package helpful
:bind
([remap describe-function] . helpful-callable)
([remap describe-command] . helpful-command)
([remap describe-variable] . helpful-variable)
([remap describe-key] . helpful-key)
([remap describe-symbol] . helpful-symbol))
#+END_SRC
** Company
https://company-mode.github.io/
#+BEGIN_SRC emacs-lisp
(use-package company
:init
(setq company-idle-delay 0
company-echo-delay 0
company-minimum-prefix-length 1)
:config
(global-company-mode))
#+END_SRC
** Which key
`which-key` is a minor mode for Emacs that displays the key bindings following your currently entered incomplete command (a prefix) in a popup.
https://github.com/justbur/emacs-which-key
#+BEGIN_SRC emacs-lisp
(use-package which-key
:config
(which-key-mode)
(which-key-setup-side-window-bottom)
(setq which-key-sort-order 'which-key-key-order-alpha
which-key-side-window-max-width 0.33
which-key-idle-delay 0.05)
)
#+END_SRC
** Buffer history
`savehist` saves buffer history
#+BEGIN_SRC emacs-lisp
(use-package savehist
:init
(savehist-mode))
#+END_SRC
** Vertico
#+BEGIN_SRC emacs-lisp
(use-package vertico
:init
(vertico-mode))
#+END_SRC
** Marginalia
#+BEGIN_SRC emacs-lisp
(use-package marginalia
:after vertico
:init
(marginalia-mode))
#+END_SRC
* Evil
#+BEGIN_SRC emacs-lisp
(use-package evil
:init
(setq evil-undo-system 'undo-tree)
(setq evil-want-integration t)
(setq evil-want-keybinding nil)
(setq evil-want-C-u-scroll t)
(setq evil-want-C-i-jump nil)
:config
(evil-mode 1)
;; Use visual line motions even outside of visual-line-mode buffers
(evil-global-set-key 'motion "j" 'evil-next-visual-line)
(evil-global-set-key 'motion "k" 'evil-previous-visual-line)
(evil-set-initial-state 'messages-buffer-mode 'normal)
(evil-set-initial-state 'dashboard-mode 'normal))
(use-package evil-surround
:config (global-evil-surround-mode))
(use-package evil-collection
:after evil
:config
(evil-collection-init))
#+END_SRC
* Undo tree
#+BEGIN_SRC emacs-lisp
(use-package undo-tree
:init
(setq undo-tree-auto-save-history nil)
(global-undo-tree-mode 1))
#+END_SRC
* Org-mode
#+BEGIN_SRC emacs-lisp
(use-package org
:hook (org-mode . visual-line-mode) ;; wrap lines
:config
(setq org-ellipsis "")
(setq org-agenda-start-with-log-mode t)
(setq org-log-done 'time)
(setq org-cycle-separator-lines 1)
(setq org-startup-folded 'content)
(setq org-startup-indented t)
(setq org-agenda-files '("~/sync/org"))
#+END_SRC
** Org-habit
#+BEGIN_SRC emacs-lisp
(require 'org-habit)
(add-to-list 'org-modules 'org-habit)
(setq org-habit-graph-column 60))
#+END_SRC
* Magit
#+BEGIN_SRC emacs-lisp
(use-package magit
:custom
(magit-display-buffer-function #'magit-display-buffer-same-window-except-diff-v1))
#+END_SRC
* Diff-hl (git diff in margin)
#+BEGIN_SRC emacs-lisp
(use-package diff-hl
:config
(setq diff-hl-side 'right)
(global-diff-hl-mode t))
#+END_SRC
* LSP
** Eglot
#+BEGIN_SRC emacs-lisp
(defun alex/eglot-organize-imports () (interactive)
(call-interactively 'eglot-code-action-organize-imports))
(defun alex/eglot-on-save ()
(add-hook 'before-save-hook #'eglot-format-buffer -10 t)
(add-hook 'before-save-hook #'alex/eglot-organize-imports nil t)
)
(use-package eglot
:config
;; Ensure `nil` is in your PATH.
(add-to-list 'eglot-server-programs '(nix-mode . ("nil")))
:hook (
(eglot-managed-mode . alex/eglot-on-save)
(go-mode . eglot-ensure)
(nix-mode . eglot-ensure)
)
)
#+END_SRC
** Go
#+BEGIN_SRC emacs-lisp
(use-package go-mode
:hook (
(go-mode . eglot-ensure)
)
)
#+END_SRC
** Nix
#+BEGIN_SRC emacs-lisp
(use-package nix-mode
:mode "\\.nix$"
:hook (
(nix-mode . eglot-ensure)
)
)
#+END_SRC