#+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 #+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 ** Disable bell #+BEGIN_SRC emacs-lisp (setq ring-bell-function 'ignore) #+END_SRC ** Font #+BEGIN_SRC emacs-lisp (add-to-list 'default-frame-alist '(font . "DejaVuSansM Nerd Font Mono 16")) #+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 ** Handle killing of emacs/frame #+BEGIN_SRC emacs-lisp (setq confirm-kill-emacs nil) (setq confirm-kill-processes nil) (define-advice delete-frame (:around (oldfun &rest args) confirm-frame-deletion) "Confirm deleting the frame." (interactive) (when (y-or-n-p "Delete frame? ") (save-some-buffers) (apply oldfun args))) #+END_SRC ** Use ESC to quit prompts #+BEGIN_SRC emacs-lisp (global-set-key (kbd "") '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 * Keybindings Setup prefix for keybindings. #+BEGIN_SRC emacs-lisp (use-package general) (general-create-definer alex/keybindings :keymaps '(normal insert visual emacs) :prefix ",") #+END_SRC ** Quick buffer save #+BEGIN_SRC emacs-lisp (alex/keybindings "," '(save-buffer :save-buffer "save")) #+END_SRC ** Cleanup whitespace #+BEGIN_SRC emacs-lisp (alex/keybindings "w" '(whitespace-cleanup :which-key "whitespace cleanup")) #+END_SRC ** Scale text #+BEGIN_SRC emacs-lisp (use-package hydra) (defhydra hydra-text-scale (:timeout 4) "scale text" ("k" text-scale-increase "in") ("j" text-scale-decrease "out") ("r" (text-scale-adjust 0) "reset") ("esc" nil "finished" :exit t)) (alex/keybindings "t" '(:ignore t :which-key "text") "ts" '(hydra-text-scale/body :which-key "scale text")) #+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) (javascript-mode . eglot-ensure) (js-mode . eglot-ensure) (js-jsx-mode . eglot-ensure) ) ) #+END_SRC ** Eldoc-box #+BEGIN_SRC emacs-lisp (use-package eldoc-box :after eglot :bind (:map eglot-mode-map ("M-h" . eldoc-box-help-at-point))) #+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 ** YAML #+BEGIN_SRC emacs-lisp (use-package yaml-mode :mode ( ("\\.yml$" . yaml-mode) ("\\.yaml$" . yaml-mode) ) ) #+END_SRC ** Dockerfile #+BEGIN_SRC emacs-lisp (use-package dockerfile-mode :mode "Dockerfile.*") #+END_SRC ** Markdown #+BEGIN_SRC emacs-lisp (use-package markdown-mode) #+END_SRC ** Javascript #+BEGIN_SRC emacs-lisp (setq js-indent-level 2) #+END_SRC