Skip to content

Instantly share code, notes, and snippets.

@kborling
Last active November 16, 2023 18:07
Show Gist options
  • Save kborling/13f2300e60ae4878d5d96f5f4d041664 to your computer and use it in GitHub Desktop.
Save kborling/13f2300e60ae4878d5d96f5f4d041664 to your computer and use it in GitHub Desktop.
My emacs config
;;; init.el --- My personal emacs config -*- lexical-binding: t; -*-
;; Author: Kevin Borling <https://github.com/kborling>
;; Version: 1.1.0
;; Keywords: configuration
;; URL: https://gist.github.com/kborling/13f2300e60ae4878d5d96f5f4d041664
;; Homepage: https://gist.github.com/kborling/13f2300e60ae4878d5d96f5f4d041664
;; Package-Requires: ((emacs "28.1"))
;;; Commentary:
;; Copyright (C) 2022 Kevin Borling
;; My personal Emacs config
;;; Code:
;; Backups ========================================== ;;
;; Auto-revert mode
(setopt auto-revert-interval 0.5)
(setopt auto-revert-verbose t)
(add-hook 'after-init-hook #'global-auto-revert-mode)
;; Backup stored in /tmp
(setq backup-directory-alist
`((".*" . ,temporary-file-directory)))
(setq auto-save-file-name-transforms
`((".*" , temporary-file-directory t)))
(setq backup-by-copying t)
(setq version-control t)
(setq delete-old-versions t)
(setq kept-new-versions 6)
(setq kept-old-versions 2)
(setq create-lockfiles nil)
;; User ============================================= ;;
(setq user-full-name "Kevin Borling"
user-mail-address "kborling@protonmail.com")
;; Defaults ========================================= ;;
(setq frame-title-format '("%b"))
(setq use-short-answers t)
(setq ring-bell-function 'ignore)
(setq visible-bell nil)
(setq fill-column 100)
(show-paren-mode 1)
;; Treat Camelcase as words
(global-subword-mode 1)
;; Remember cursor place
(setq save-place-file (locate-user-emacs-file "saveplace"))
(setq save-place-forget-unreadable-files t)
(save-place-mode 1)
;; Remember my bookmarks
(setq bookmark-save-flag 1)
;; Enable indentation+completion using the TAB key.
(setq tab-always-indent 'complete)
(setq-default indent-tabs-mode nil
tab-stop-list ()
tab-width 2)
(setq sentence-end-double-space nil)
(setq scroll-step 1) ; keyboard scroll one line at a time
(setq scroll-preserve-screen-position t)
(setq scroll-conservatively 101)
(setq ; save-interprogram-paste-before-kill t
apropos-do-all t
mouse-yank-at-point t
require-final-newline t
load-prefer-newer t)
;; Global mark ring
(setq global-mark-ring-max 50000)
;; Delete marked region when input
(add-hook 'after-init-hook #'delete-selection-mode)
(setq icomplete-compute-delay 0)
(autoload 'zap-up-to-char "misc"
"Kill up to, but not including ARGth occurrence of CHAR." t)
(require 'uniquify)
(setq uniquify-buffer-name-style 'forward)
;; Electric Pairs ====================================== ;;
;; make electric-pair-mode work on more brackets
(setq electric-pair-inhibit-predicate 'electric-pair-conservative-inhibit)
(setq electric-pair-preserve-balance t)
(setq electric-pair-pairs
'((8216 . 8217)
(8220 . 8221)
(171 . 187)))
(setq electric-pair-skip-self 'electric-pair-default-skip-self)
(setq electric-pair-skip-whitespace nil)
(setq electric-pair-skip-whitespace-chars '(9 10 32))
(setq electric-quote-context-sensitive t)
(setq electric-quote-paragraph t)
(setq electric-quote-string nil)
(setq electric-quote-replace-double t)
(electric-pair-mode -1)
(electric-quote-mode -1)
;; I don't like auto indents in Org and related. They are okay for
;; programming.
(electric-indent-mode -1)
(add-hook 'prog-mode-hook #'electric-indent-local-mode)
;; Hooks ============================================= ;;
;; (add-hook 'emacs-startup-hook 'toggle-frame-maximized)
(add-hook 'before-save-hook #'delete-trailing-whitespace)
;; Package ========================================== ;;
;; Initialize package sources
(require 'package)
(setq package-archives
'(("elpa" . "https://elpa.gnu.org/packages/")
("org" . "https://orgmode.org/elpa/")
("nongnu" . "https://elpa.nongnu.org/nongnu/")
("melpa" . "https://melpa.org/packages/")))
;; Highest number gets priority (what is not mentioned has priority 0)
(setq package-archive-priorities
'(("elpa" . 2)
("nongnu" . 1)))
(package-initialize)
(unless package-archive-contents
(package-refresh-contents))
;; Initialize use-package on non-Linux platforms
(unless (package-installed-p 'use-package)
(package-install 'use-package))
(require 'use-package)
(setq use-package-always-ensure t)
;; Keybindings ======================================= ;;
(let ((map global-map))
;; Remove suspend
(define-key map (kbd "C-z") nil)
(define-key map (kbd "C-x C-z") nil)
(define-key map (kbd "C-;") #'comment-line)
;; (define-key map (kbd "C-t") #'other-window)
;; (define-key map (kbd "C-c C-<tab>") #'next-window)
(define-key map (kbd "C-c C-p") #'previous-buffer)
(define-key map (kbd "C-c C-n") #'next-buffer)
;; Misc
(define-key map (kbd "C-x C-b") #'ibuffer)
(define-key map (kbd "M-z") #'zap-up-to-char)
;; Isearch
(define-key map (kbd "C-s") #'isearch-forward-regexp)
(define-key map (kbd "C-r") #'isearch-backward-regexp)
(define-key map (kbd "C-M-s") #'isearch-forward)
(define-key map (kbd "C-M-r") #'isearch-backward)
;; Open applications
(define-key map (kbd "C-c o e") #'eshell)
(define-key map (kbd "C-c o d") #'dired)
(define-key map (kbd "C-c o f") #'treemacs)
)
;; Theming ================================================ ;;
(set-face-attribute 'default nil
:family "Comic Code" :weight 'regular :height 140)
(set-face-attribute 'bold nil
:family "Comic Code" :weight 'bold)
(set-face-attribute 'italic nil
:family "Comic Code" :weight 'regular :slant 'italic)
(set-face-attribute 'variable-pitch nil
:family "Cantarell" :height 130 :weight 'regular)
(set-fontset-font t 'unicode
(font-spec :name "Inconsolata Light" :size 16) nil)
;; (set-fontset-font t '(#xe000 . #xffdd)
;; (font-spec :name "LiberationMono Nerd Font" :size 12) nil)
;; Custom themes
(use-package ef-themes)
(load-theme 'ef-tritanopia-dark t)
;; Frame ============================================== ;;
;; Make frame transparency overridable
(defvar kdb-frame-transparency '(96 . 96))
;; Set frame transparency
(set-frame-parameter (selected-frame) 'alpha kdb-frame-transparency)
(add-to-list 'default-frame-alist `(alpha . ,kdb-frame-transparency))
;; (set-frame-parameter (selected-frame) 'fullscreen 'maximized)
;; (add-to-list 'default-frame-alist '(fullscreen . maximized))
;; Recent Files ======================================= ;;
(require 'recentf)
;; ;; enable recent files mode.
(setq recentf-save-file (locate-user-emacs-file "recentf"))
(setq recentf-max-saved-items 50)
(setq recentf-exclude '(".gz" ".xz" ".zip" "/elpa/" "/ssh:" "/sudo:"))
(add-hook 'after-init-hook #'recentf-mode)
;; Exec Path ====================================== ;;
(use-package exec-path-from-shell
:ensure t
:config
(when (memq window-system '(mac ns x))
(exec-path-from-shell-initialize)))
;; Diminish ======================================= ;;
(use-package diminish
:ensure t
:config
(diminish 'subword-mode)
(diminish 'eldoc-mode))
;; Which Key ========================================= ;;
(use-package which-key
:defer 0
:diminish
:config
(which-key-mode)
(setq which-key-idle-delay 1))
;; Expand Region ====================================== ;;
(use-package expand-region
:bind ("C-\\" . er/expand-region))
;; Wrap Region ======================================== ;;
(use-package wrap-region
:diminish
:config
(wrap-region-mode t))
;; Crux ============================================== ;;
(use-package crux
:bind (("C-a" . crux-move-beginning-of-line)
;; ("C-k" . crux-smart-kill-line)
("M-<return>" . crux-smart-open-line-above)
("C-x w" . crux-rename-file-and-buffer)
("C-c d" . crux-duplicate-current-line-or-region)
("C-c M-d" . crux-duplicate-and-comment-current-line-or-region)
([(shift return)] . crux-smart-open-line)))
(global-set-key [remap kill-whole-line] #'crux-kill-whole-line)
;; Highlight Todo ====================================== ;;
(use-package hl-todo
:config
(global-hl-todo-mode))
;; Magit ============================================== ;;
(use-package magit
:bind (
("C-c g g" . magit-status)
("C-c g s" . magit-status)
("C-c g i" . magit-init)
("C-c g c" . magit-clone)
("C-c g l" . magit-pull)
("C-c g p" . magit-push)
("C-c g f" . magit-fetch-all)
("C-c g b" . magit-branch)
("C-c g d" . magit-diff)
("C-c g z" . magit-stash)
("C-c g Z" . magit-apply)
))
;; Marginalia ======================================== ;;
(use-package marginalia
;; Either bind `marginalia-cycle' globally or only in the minibuffer
:bind (("M-A" . marginalia-cycle)
:map minibuffer-local-map
("M-A" . marginalia-cycle))
:init
(marginalia-mode))
;; Corfu ============================================= ;;
(use-package corfu
:init
(global-corfu-mode)
:hook ((prog-mode . corfu-mode)
(shell-mode . corfu-mode)
(eshell-mode . corfu-mode))
:custom
(corfu-cycle t) ;; Enable cycling for `corfu-next/previous'
(corfu-auto t) ;; Enable auto completion
;; (corfu-auto-delay 0)
;; (corfu-auto-prefix 1)
(corfu-separator ?\s) ;; Orderless field separator
(corfu-quit-no-match 'separator) ; Don't quit if there is `corfu-separator' inserted
;; (corfu-quit-at-boundary nil) ;; Never quit at completion boundary
;; (corfu-quit-no-match nil) ;; Never quit, even if there is no match
;; (corfu-preview-current nil) ;; Disable current candidate preview
;; (corfu-preselect-first nil) ;; Disable candidate preselection
;; (corfu-on-exact-match nil) ;; Configure handling of exact matches
(corfu-echo-documentation nil) ;; Disable documentation in the echo area
;; (corfu-scroll-margin 5) ;; Use scroll margin
;; (corfu-min-width 80)
;; (corfu-max-width corfu-min-width) ; Always have the same width
;; (corfu-count 14)
(corfu-scroll-margin 4)
:config
(define-key corfu-map (kbd "<tab>") #'corfu-complete)
(defun contrib/corfu-enable-always-in-minibuffer ()
"Enable Corfu in the minibuffer if Vertico is not active.
Useful for prompts such as `eval-expression' and `shell-command'."
(unless (bound-and-true-p vertico--input)
(corfu-mode 1)))
(add-hook 'minibuffer-setup-hook #'contrib/corfu-enable-always-in-minibuffer 1)
(defun corfu-move-to-minibuffer ()
(interactive)
(let (completion-cycle-threshold completion-cycling)
(apply #'consult-completion-in-region completion-in-region--data)))
(define-key corfu-map "\M-m" #'corfu-move-to-minibuffer))
(use-package corfu-doc
:after corfu
:config
(define-key corfu-map (kbd "M-p") #'corfu-doc-scroll-down) ;; corfu-next
(define-key corfu-map (kbd "M-n") #'corfu-doc-scroll-up) ;; corfu-previous
;; (setq corfu-doc-display-within-parent-frame nil)
(add-hook 'corfu-mode-hook #'corfu-doc-mode))
;; Add extensions
(use-package cape
;; Bind dedicated completion commands
;; Alternative prefix keys: C-c p, M-p, M-+, ...
:bind (("C-c p p" . completion-at-point) ;; capf
("C-c p t" . complete-tag) ;; etags
("C-c p d" . cape-dabbrev) ;; or dabbrev-completion
("C-c p h" . cape-history)
("C-c p f" . cape-file)
("C-c p k" . cape-keyword)
("C-c p s" . cape-symbol)
("C-c p a" . cape-abbrev)
("C-c p i" . cape-ispell)
("C-c p l" . cape-line)
("C-c p w" . cape-dict))
:init
;; Add `completion-at-point-functions', used by `completion-at-point'.
(add-to-list 'completion-at-point-functions #'cape-dabbrev)
(add-to-list 'completion-at-point-functions #'cape-file)
;;(add-to-list 'completion-at-point-functions #'cape-history)
(add-to-list 'completion-at-point-functions #'cape-keyword)
(add-to-list 'completion-at-point-functions #'cape-symbol)
;; (add-to-list 'completion-at-point-functions #'cape-line)
)
;; Templates ================================================
(use-package tempel
;; Require trigger prefix before template name when completing.
;; :custom
;; (tempel-trigger-prefix "<")
:bind (("M-+" . tempel-complete) ;; Alternative tempel-expand
("M-*" . tempel-insert))
:init
;; 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-expand
completion-at-point-functions)))
(add-hook 'prog-mode-hook 'tempel-setup-capf)
(add-hook 'text-mode-hook 'tempel-setup-capf)
;; Optionally make the Tempel templates available to Abbrev,
;; either locally or globally. `expand-abbrev' is bound to C-x '.
;; (add-hook 'prog-mode-hook #'tempel-abbrev-mode)
;; (global-tempel-abbrev-mode)
)
;; Snippets =================================================
;; (use-package yasnippet-snippets
;; :ensure t
;; :after yasnippet)
;; (yas-global-mode 1)
;; TAGS ============================================== ;;
(setq path-to-ctags "/opt/homebrew/bin/ctags")
(defun create-tags (dir-name)
"Create tags file using 'DIR-NAME'."
(interactive "DDirectory: ")
(shell-command
(format "%s -f TAGS -e -R %s" path-to-ctags (directory-file-name dir-name)))
)
;; Multiple Cursors ================================== ;;
(use-package multiple-cursors
:ensure t
:diminish
:bind (
("C->" . mc/mark-next-like-this)
("C-<" . mc/mark-previous-like-this)
("C-z" . mc/mark-next-like-this)
("M-C-z" . mc/mark-previous-like-this)
("C-c C-<" . mc/mark-all-like-this)
("C-S-c C-S-c" . mc/mark-edit-lines)
))
;; Repeat ============================================ ;;
(use-package repeat
:ensure t
:config
(setq repeat-on-final-keystroke t)
(setq set-mark-command-repeat-pop t))
;; So Long =========================================== ;;
(use-package so-long
:ensure t
:config
(global-so-long-mode 1))
;; Dabbrev =========================================== ;;
(require 'dabbrev)
(setq dabbrev-abbrev-char-regexp "\\sw\\|\\s_")
(setq dabbrev-abbrev-skip-leading-regexp "[$*/=~']")
(setq dabbrev-backward-only nil)
(setq dabbrev-case-distinction 'case-replace)
(setq dabbrev-case-fold-search nil)
(setq dabbrev-case-replace 'case-replace)
(setq dabbrev-check-other-buffers t)
(setq dabbrev-eliminate-newlines t)
(setq dabbrev-upcase-means-case-search t)
(let ((map global-map))
(define-key map (kbd "M-/") #'dabbrev-expand)
(define-key map (kbd "C-M-/") #'dabbrev-completion))
;; Orderless ========================================= ;;
(use-package orderless
:ensure t
:config
(setq orderless-component-separator " +")
(setq orderless-matching-styles
'( orderless-prefixes orderless-initialism
orderless-flex orderless-regexp))
(let ((map minibuffer-local-completion-map))
(define-key map (kbd "SPC") nil)
(define-key map (kbd "?") nil)))
;; Completion Styles ================================= ;;
;; Set completion styles
(setq completion-styles
'(basic orderless))
;; '(basic substring initials flex partial-completion orderless))
(setq completion-category-defaults nil)
(setq completion-category-overrides
'((file (styles . (basic substring partial-completion orderless)))
(project-file (styles . (basic substring partial-completion orderless)))
(imenu (styles . (basic substring orderless)))
(kill-ring (styles . (basic substring orderless)))
(consult-location (styles . (basic substring orderless)))))
(setq completion-cycle-threshold 2)
(setq completion-flex-nospace nil)
(setq completion-pcm-complete-word-inserts-delimiters nil)
(setq completion-pcm-word-delimiters "-_./:| ")
(setq completion-ignore-case t)
(setq completions-detailed t)
(setq-default case-fold-search t) ; For general regexp
;; Grouping of completions for Emacs 28
(setq completions-group t)
(setq completions-group-sort nil)
(setq completions-group-format
(concat
(propertize " " 'face 'completions-group-separator)
(propertize " %s " 'face 'completions-group-title)
(propertize " " 'face 'completions-group-separator
'display '(space :align-to right))))
(setq read-buffer-completion-ignore-case t)
(setq read-file-name-completion-ignore-case t)
(setq completion-show-inline-help nil)
(setq completions-detailed t)
;; Ibuffer ============================================== ;;
(setq ibuffer-expert t)
(setq ibuffer-display-summary nil)
(setq ibuffer-use-other-window nil)
(setq ibuffer-show-empty-filter-groups nil)
(setq ibuffer-movement-cycle nil)
(setq ibuffer-default-sorting-mode 'filename/process)
(setq ibuffer-use-header-line t)
(setq ibuffer-default-shrink-to-minimum-size nil)
(setq ibuffer-formats
'((mark modified read-only locked " "
(name 40 40 :left :elide)
" "
(size 9 -1 :right)
" "
(mode 16 16 :left :elide)
" " filename-and-process)
(mark " "
(name 16 -1)
" " filename)))
(setq ibuffer-saved-filter-groups nil)
(setq ibuffer-old-time 48)
(add-hook 'ibuffer-mode-hook #'hl-line-mode)
;; Minibuffer =========================================== ;;
(setq completion-cycle-threshold 2)
(setq completion-flex-nospace nil) ; though I don't use the built-in `flex' style...
(setq completion-pcm-complete-word-inserts-delimiters nil)
(setq completion-pcm-word-delimiters "-_./:| ")
(setq completion-ignore-case t)
(setq completions-detailed t)
(setq-default case-fold-search t) ; For general regexp
;; Grouping of completions for Emacs 28
(setq completions-group t)
(setq completions-group-sort nil)
(setq completions-group-format
(concat
(propertize " " 'face 'completions-group-separator)
(propertize " %s " 'face 'completions-group-title)
(propertize " " 'face 'completions-group-separator
'display '(space :align-to right))))
(setq read-buffer-completion-ignore-case t)
(setq read-file-name-completion-ignore-case t)
(setq enable-recursive-minibuffers t)
(setq read-answer-short t) ; also check `use-short-answers' for Emacs28
(setq resize-mini-windows t)
(setq minibuffer-eldef-shorten-default t)
(setq echo-keystrokes 0.25) ; from the C source code
(setq minibuffer-prompt-properties
'(read-only t cursor-intangible t face minibuffer-prompt))
(add-hook 'minibuffer-setup-hook #'cursor-intangible-mode)
(file-name-shadow-mode 1)
(minibuffer-depth-indicate-mode 1)
(minibuffer-electric-default-mode 1)
;; Modeline ============================================= ;;
(setq mode-line-percent-position '(-3 "%p"))
(setq mode-line-position-column-line-format '(" %l,%c")) ; Emacs 28
(setq mode-line-defining-kbd-macro
(propertize " Macro" 'face 'mode-line-emphasis))
(setq-default mode-line-modes
(seq-filter (lambda (s)
(not (and (stringp s)
(string-match-p
"^\\(%\\[\\|%\\]\\)$" s))))
mode-line-modes))
(setq mode-line-compact nil) ; Emacs 28
(setq-default mode-line-format
'("%e"
mode-line-front-space
mode-line-mule-info
mode-line-client
mode-line-modified
mode-line-remote
mode-line-frame-identification
mode-line-buffer-identification
" "
mode-line-position
mode-line-modes
" "
(vc-mode vc-mode)
" "
mode-line-misc-info
mode-line-end-spaces))
;; Winner =============================================== ;;
(add-hook 'after-init-hook #'winner-mode)
(let ((map global-map))
(define-key map (kbd "C-c <") #'winner-redo)
(define-key map (kbd "C-c >") #'winner-undo))
;; Vterm ================================================ ;;
(use-package vterm
:ensure t)
;; Vertico =========================================== ;;
(use-package vertico
:init
(vertico-mode)
;; (vertico-unobtrusive-mode)
(vertico-reverse-mode)
;; different scroll margin
;; (setq vertico-scroll-margin 0)
;; Show more candidates
;; (setq vertico-count 20)
;; Grow and shrink the Vertico minibuffer
;; (setq vertico-resize t)
;; Optionally enable cycling for `vertico-next' and `vertico-previous'.
(setq vertico-cycle t)
;; :bind
;; ("C-s" . vertico-next)
;; ("C-r" . vertico-previous)
(define-minor-mode kdb/vertico-reverse-mode
"Toggle between `vertico-reverse-mode' and 'vertico-flat-mode'."
:init-value nil
:global nil
:require 'vectico-mode
:diminish kdb/vertico-reverse-mode
(if kdb/vertico-reverse-mode
(progn
(vertico-reverse-mode)
(vertico-flat-mode -1)
)
(vertico-reverse-mode -1)
(vertico-flat-mode)
)
(message " "))
:bind ("C-=" . kdb/vertico-reverse-mode)
)
;; Dired ============================================= ;;
(setq dired-recursive-copies 'always)
(setq dired-recursive-deletes 'always)
(setq delete-by-moving-to-trash t)
(setq dired-listing-switches
"-AGFhlv --group-directories-first --time-style=long-iso")
(setq dired-dwim-target t)
(setq dired-auto-revert-buffer #'dired-directory-changed-p) ; also see `dired-do-revert-buffer'
(setq dired-make-directory-clickable t) ; Emacs 29.1
(setq dired-free-space nil) ; Emacs 29.1
(add-hook 'dired-mode-hook #'dired-hide-details-mode)
(add-hook 'dired-mode-hook #'hl-line-mode)
(setq dired-isearch-filenames 'dwim)
;; The following variables were introduced in Emacs 27.1
(setq dired-create-destination-dirs 'ask)
(setq dired-vc-rename-file t)
;; And this is for Emacs 28
(setq dired-do-revert-buffer (lambda (dir) (not (file-remote-p dir))))
(setq dired-clean-up-buffers-too t)
(setq dired-clean-confirm-killing-deleted-buffers t)
(setq dired-x-hands-off-my-keys t) ; easier to show the keys I use
(setq dired-bind-man nil)
(setq dired-bind-info nil)
(setq wdired-allow-to-change-permissions t)
(setq wdired-create-parent-directories t)
(setq image-dired-thumb-size 80)
(setq image-dired-thumb-margin 2)
(setq image-dired-thumb-relief 0)
(setq image-dired-thumbs-per-row 4)
;; Xref ============================================== ;;
(setq xref-show-definitions-function #'xref-show-definitions-completing-read) ; for M-.
(setq xref-show-xrefs-function #'xref-show-definitions-buffer) ; for grep and the like
(setq xref-file-name-display 'project-relative)
(setq xref-search-program 'ripgrep)
;; ISearch =========================================== ;;
(setq search-highlight t)
(setq search-whitespace-regexp ".*?")
(setq isearch-lax-whitespace t)
(setq isearch-regexp-lax-whitespace nil)
(setq isearch-lazy-highlight t)
;; All of the following variables were introduced in Emacs 27.1.
(setq isearch-lazy-count t)
(setq lazy-count-prefix-format nil)
(setq lazy-count-suffix-format " (%s/%s)")
(setq isearch-yank-on-move 'shift)
(setq isearch-allow-scroll 'unlimited)
;; These variables are from Emacs 28
(setq isearch-repeat-on-direction-change t)
(setq lazy-highlight-initial-delay 0.5)
(setq lazy-highlight-no-delay-length 3)
(setq isearch-wrap-pause t)
(define-key minibuffer-local-isearch-map (kbd "M-/") #'isearch-complete-edit)
(let ((map isearch-mode-map))
(define-key map (kbd "C-g") #'isearch-cancel) ; instead of `isearch-abort'
(define-key map (kbd "M-/") #'isearch-complete))
;; SaveHist ========================================== ;;
(require 'savehist)
(setq savehist-file (locate-user-emacs-file "savehist"))
(setq history-length 10000)
(setq history-delete-duplicates t)
(setq savehist-save-minibuffer-history t)
(add-hook 'after-init-hook #'savehist-mode)
;; Consult ============================================ ;;
(use-package consult
:bind (;; C-c bindings (mode-specific-map)
("C-c h" . consult-history)
("C-c m" . consult-mode-command)
("C-c k" . consult-kmacro)
("C-h t" . consult-theme)
;; C-x bindings (ctl-x-map)
("C-x M-:" . consult-complex-command) ;; orig. repeat-complex-command
("C-x b" . consult-buffer) ;; orig. switch-to-buffer
("C-x 4 b" . consult-buffer-other-window) ;; orig. switch-to-buffer-other-window
("C-x 5 b" . consult-buffer-other-frame) ;; orig. switch-to-buffer-other-frame
("C-x r b" . consult-bookmark) ;; orig. bookmark-jump
("C-x p b" . consult-project-buffer) ;; orig. project-switch-to-buffer
("C-x C-r" . consult-recent-file)
;; Custom M-# bindings for fast register access
("M-#" . consult-register-load)
("M-'" . consult-register-store) ;; orig. abbrev-prefix-mark (unrelated)
("C-M-#" . consult-register)
;; Other custom bindings
("M-y" . consult-yank-pop) ;; orig. yank-pop
("<help> a" . consult-apropos) ;; orig. apropos-command
;; M-g bindings (goto-map)
;; M-g bindings (goto-map)
("M-g e" . consult-compile-error)
("M-g f" . consult-flymake) ;; Alternative: consult-flycheck
("M-g g" . consult-goto-line) ;; orig. goto-line
("M-g M-g" . consult-goto-line) ;; orig. goto-line
("M-g o" . consult-outline) ;; Alternative: consult-org-heading
("M-g m" . consult-mark)
("M-g k" . consult-global-mark)
("M-g i" . consult-imenu)
("M-g I" . consult-imenu-multi)
;; M-s bindings (search-map)
("M-s d" . consult-find)
("M-s D" . consult-locate)
("M-s g" . consult-grep)
("M-s G" . consult-git-grep)
("M-s r" . consult-ripgrep)
("M-s l" . consult-line)
("M-s L" . consult-line-multi)
("M-s m" . consult-multi-occur)
("M-s k" . consult-keep-lines)
("M-s u" . consult-focus-lines)
;; Isearch integration
("M-s e" . consult-isearch-history)
:map isearch-mode-map
("M-e" . consult-isearch-history) ;; orig. isearch-edit-string
("M-s e" . consult-isearch-history) ;; orig. isearch-edit-string
("M-s l" . consult-line) ;; needed by consult-line to detect isearch
("M-s L" . consult-line-multi) ;; needed by consult-line to detect isearch
;; Minibuffer history
:map minibuffer-local-map
("M-s" . consult-history) ;; orig. next-matching-history-element
("M-r" . consult-history)) ;; orig. previous-matching-history-element
;; Enable automatic preview at point in the *Completions* buffer.
:hook (completion-list-mode . consult-preview-at-point-mode)
;; The :init configuration is always executed (Not lazy)
:init
(setq register-preview-delay 0
register-preview-function #'consult-register-format)
;; This adds thin lines, sorting and hides the mode line of the window.
(advice-add #'register-preview :override #'consult-register-window)
;; Optionally replace `completing-read-multiple' with an enhanced version.
;; (advice-add #'completing-read-multiple :override #'consult-completing-read-multiple)
;; Enable consult previews
(add-hook 'completion-list-mode-hook #'consult-preview-at-point-mode)
;; Use Consult to select xref locations with preview
(setq xref-show-xrefs-function #'consult-xref
xref-show-definitions-function #'consult-xref)
;; Use `consult-completion-in-region' if Vertico is enabled.
;; Otherwise use the default `completion--in-region' function.
(setq completion-in-region-function
(lambda (&rest args)
(apply (if vertico-mode
#'consult-completion-in-region
#'completion--in-region)
args)))
:config
(consult-customize
consult-theme
:preview-key '(:debounce 0.2 any)
consult-ripgrep consult-git-grep consult-grep
consult-bookmark consult-recent-file consult-xref
consult--source-bookmark consult--source-recent-file
consult--source-project-recent-file
:preview-key (kbd "M-."))
;; Optionally configure the narrowing key.
;; Both < and C-+ work reasonably well.
(setq consult-narrow-key "<") ;; (kbd "C-+")
;;;; 1. project.el (project-roots)
(setq consult-project-root-function
(lambda ()
(when-let (project (project-current))
(car (project-roots project))))))
;; Embark ============================================ ;;
(use-package embark
:ensure t
:bind
(("C-." . embark-act) ;; pick some comfortable binding
("M-." . embark-dwim) ;; good alternative: M-.
("C-h B" . embark-bindings)) ;; alternative for `describe-bindings'
:init
;; Optionally replace the key help with a completing-read interface
(setq prefix-help-command #'embark-prefix-help-command)
:config
;; (define-key embark-symbol-map "D" #'devdocs-lookup)
;; (define-key embark-function-map "D" #'devdocs-lookup)
;; Hide the mode line of the Embark live/completions buffers
(add-to-list 'display-buffer-alist
'("\\`\\*Embark Collect \\(Live\\|Completions\\)\\*"
nil
(window-parameters (mode-line-format . none)))))
;; Consult users will also want the embark-consult package.
(use-package embark-consult
:ensure t ; only need to install it, embark loads it after consult if found
:hook
(embark-collect-mode . consult-preview-at-point-mode))
;; Eldoc Box ========================================= ;;
(global-eldoc-mode 1)
(setq eldoc-echo-area-use-multiline-p t)
(use-package eldoc-box
:after eldoc
:diminish
:config
(add-hook 'eglot--managed-mode-hook #'eldoc-box-hover-mode t)
)
;; Eglot ============================================= ;;
(use-package eglot
:ensure t
:config
;; (add-to-list 'eglot-stay-out-of 'flymake)
;; Keybindings
(define-key eglot-mode-map (kbd "C-c c r") 'eglot-rename)
(define-key eglot-mode-map (kbd "C-c c f") 'eglot-format-buffer)
(define-key eglot-mode-map (kbd "C-c c o") 'eglot-code-action-organize-imports)
(define-key eglot-mode-map (kbd "C-c c a") 'eglot-code-actions)
(define-key eglot-mode-map (kbd "C-c c q") 'eglot-code-action-quickfix)
(define-key eglot-mode-map (kbd "C-c c e") 'eglot-code-action-extract)
(define-key eglot-mode-map (kbd "C-c c j") 'eglot-code-action-inline)
(define-key eglot-mode-map (kbd "C-c c k") 'eglot-code-action-rewrite)
(define-key eglot-mode-map (kbd "C-c c i") 'eglot-find-implementation)
(define-key eglot-mode-map (kbd "C-c c d") 'eglot-find-declaration)
(define-key eglot-mode-map (kbd "C-c c t") 'eglot-find-typeDefinition)
(define-key eglot-mode-map (kbd "C-c c h") 'eldoc))
;; (define-key eglot-mode-map (kbd "C-c c d") 'xref-find-definitions))
;; Language Servers
;; (add-to-list 'eglot-server-programs '(csharp-mode . ("/run/current-system/sw/bin/omnisharp" "-lsp")))
(add-to-list 'eglot-server-programs '(typescript-mode . ("typescript-language-server" "--stdio")))
;; (add-to-list 'eglot-server-programs '(web-mode . ("typescript-language-server" "--stdio")))
;; Automatically start
(add-hook 'typescript-mode-hook 'eglot-ensure)
;; (add-hook 'web-mode-hook 'eglot-ensure)
;; (add-hook 'csharp-mode-hook 'eglot-ensure)
;; (add-hook 'rust-mode-hook 'eglot-ensure)
(use-package consult-eglot)
;; Flymake ========================================= ;;
(use-package flymake
:config
(setq flymake-fringe-indicator-position 'left-fringe)
(setq flymake-suppress-zero-counters t)
(setq flymake-start-on-flymake-mode t)
(setq flymake-no-changes-timeout nil)
(setq flymake-start-on-save-buffer t)
;; (setq flymake-no-changes-timeout 0.1)
(setq flymake-proc-compilation-prevents-syntax-check t)
(setq flymake-wrap-around nil)
(setq flymake-mode-line-format
'("" flymake-mode-line-exception flymake-mode-line-counters))
(setq flymake-mode-line-counter-format
'(" " flymake-mode-line-error-counter
flymake-mode-line-warning-counter
flymake-mode-line-note-counter ""))
(define-key ctl-x-x-map "m" #'flymake-mode) ; C-x x m
(let ((map flymake-mode-map))
(define-key map (kbd "C-c f s") #'flymake-start)
(define-key map (kbd "C-c f d") #'flymake-show-buffer-diagnostics) ; Emacs28
(define-key map (kbd "C-c f D") #'flymake-show-project-diagnostics) ; Emacs28
(define-key map (kbd "C-c f n") #'flymake-goto-next-error)
(define-key map (kbd "C-c f p") #'flymake-goto-prev-error))
:init
(add-hook 'prog-mode-hook 'flymake-mode)
(add-hook 'text-mode-hook 'flymake-mode)
(add-hook 'flymake-mode-hook
(lambda ()
(setq eldoc-documentation-functions
(cons 'flymake-eldoc-function
(delq 'flymake-eldoc-function eldoc-documentation-functions))))))
;; (use-package flymake-eslint
;; :config
;; (add-hook 'typescript-mode-hook
;; (lambda ()
;; (flymake-eslint-enable))))
;; Emmet Mode ====================================== ;;
(use-package emmet-mode
:mode ("\\.html\\'" "\\.css\\'" "\\.cshtml\\'" "\\.tsx\\'")
:preface (defvar emmet-mode-keymap (make-sparse-keymap))
:bind (:map emmet-mode-keymap
("<C-tab>" . emmet-expand-line))
:hook ((css-mode web-mode html-mode vue-mode) . emmet-mode))
;; Web Mode ======================================== ;;
(use-package web-mode
:mode ("\\.html\\'" "\\.css\\'" "\\.tsx\\'" "\\.cshtml\\'"))
;; Javascript Mode ================================= ;;
(use-package js2-mode
:mode ("\\.js\\'")
;; :hook (js2-mode . lsp-deferred)
:config
;; (add-hook 'js2-mode-hook #'js2-imenu-extras-mode)
(add-hook 'js2-mode-hook #'js2-refactor-mode)
(define-key js2-mode-map (kbd "C-k") #'js2r-kill)
(define-key js2-mode-map (kbd "C-\\") #'js2r-log-this)
;; js-mode (which js2 is based on) binds "M-." which conflicts with xref, so
;; unbind it.
(define-key js-mode-map (kbd "M-.") nil)
(add-hook 'js2-mode-hook (lambda ()
(add-hook 'xref-backend-functions #'xref-js2-xref-backend nil t)))
(add-hook 'js2-mode-hook (lambda ()
(setup-tide-mode)))
)
(use-package js2-refactor)
(use-package xref-js2
:config
(js2r-add-keybindings-with-prefix "C-c C-r")
)
;; Typescript Mode ================================= ;;
(use-package typescript-mode
:mode "\\.ts\\'")
;; :hook (typescript-mode . lsp-deferred)
;; :config
;; (setq typescript-indent-level 4))
(use-package tide
:ensure t
:bind (("C-c C-." . tide-documentation-at-point))
:diminish)
(defun setup-tide-mode ()
"Setup 'tide-mode' for js/ts."
(interactive)
(tide-setup)
(tide-hl-identifier-mode 1))
;; formats the buffer before saving
(add-hook 'before-save-hook 'tide-format-before-save)
(add-hook 'typescript-mode-hook #'setup-tide-mode)
;; EditorConfig ======================================== ;;
(use-package editorconfig
:ensure t
:diminish
:config
(editorconfig-mode 1))
;; TreeSitter ========================================== ;;
(use-package tree-sitter
:ensure t
:diminish
:config
(global-tree-sitter-mode)
(add-hook 'tree-sitter-after-on-hook #'tree-sitter-hl-mode)
)
(use-package tree-sitter-langs
:ensure t
:after tree-sitter
)
(use-package tree-sitter-indent
:ensure t
:after tree-sitter
)
;; Csharp ========================================== ;;
;; (use-package csharp-mode
;; :ensure t
;; :config
;; (add-to-list 'auto-mode-alist '("\\.cs\\'" . csharp-tree-sitter-mode)))
;; Rust ========================================== ;;
(use-package rust-mode
:mode ("\\.rs\\'")
;; :hook (rust-mode . lsp-deferred)
:config
(add-hook 'rust-mode-hook
(lambda () (setq indent-tabs-mode nil)))
(setq rust-format-on-save t)
(define-key rust-mode-map (kbd "C-c C-c") 'rust-run)
)
;; Elisp ========================================= ;;
;; (add-hook 'emacs-lisp-mode-hook 'eldoc-mode)
(use-package slime
:ensure t
:config
;; (setq inferior-lisp-program "/usr/bin/sbcl")
(setq slime-contribs '(slime-fancy)))
;; YAML ========================================== ;;
(use-package yaml-mode)
;; JSON ========================================== ;;
(use-package json-mode)
;; Restclient ==================================== ;;
(use-package restclient)
(use-package ob-restclient)
;; Dev Docs ======================================= ;;
(use-package devdocs
:config
(global-set-key (kbd "C-h D") 'devdocs-lookup))
;; (use-package devdocs-browser
;; :after devdocs)
;; Dash Docs ======================================= ;;
;; (use-package dash-docs)
;; (use-package consult-dash
;; :bind (("C-h D" . consult-dash))
;; :config
;; ;; Use the symbol at point as initial search term
;; (consult-customize consult-dash :initial (thing-at-point 'symbol)))
;; Emacs Application Framework ===================== ;;
;; (use-package eaf
;; :load-path "~/.emacs.d/site-lisp/emacs-application-framework"
;; :custom
;; ; See https://github.com/emacs-eaf/emacs-application-framework/wiki/Customization
;; (eaf-browser-continue-where-left-off t)
;; (eaf-browser-enable-adblocker t)
;; :config
;; (require 'eaf-pdf-viewer)
;; (require 'eaf-browser)
;; (setq browse-url-browser-function 'eaf-open-browser)
;; (setq eaf-browse-blank-page-url "https://duckduckgo.com")
;; (defalias 'browse-web #'eaf-open-browser)
;; (eaf-bind-key scroll_up "C-n" eaf-pdf-viewer-keybinding)
;; (eaf-bind-key scroll_down "C-p" eaf-pdf-viewer-keybinding)
;; (eaf-bind-key nil "M-q" eaf-browser-keybinding)) ;; unbind, see more in the Wiki
;; Ansi-term ====================================== ;;
(setq explicit-shell-file-name "/bin/zsh")
(defadvice ansi-term (before force-bash)
"Set the default shell to bash."
(interactive (list explicit-shell-file-name)))
(ad-activate 'ansi-term)
(defun kdb-term-exec-hook ()
"Kill the terminal after exit."
(let* ((buff (current-buffer))
(proc (get-buffer-process buff)))
(set-process-sentinel
proc
`(lambda (process event)
(if (string= event "finished\n")
(kill-buffer ,buff))))))
(add-hook 'term-exec-hook 'kdb-term-exec-hook)
;; Paste into term
(eval-after-load "term"
'(define-key term-raw-map (kbd "C-c C-y") 'term-paste))
;; Ediff ======================================== ;;
(setq ediff-keep-variants nil)
(setq ediff-make-buffers-readonly-at-startup nil)
(setq ediff-merge-revisions-with-ancestor t)
(setq ediff-show-clashes-only t)
(setq ediff-split-window-function 'split-window-horizontally)
(setq ediff-window-setup-function 'ediff-setup-windows-plain)
;; Org Mode ===================================== ;;
;;; Org Mode
(defun kdb/org-mode-setup ()
"Setup org mode."
(org-indent-mode)
;; (variable-pitch-mode 1)
(visual-line-mode 1)
(electric-indent-local-mode -1)
;; (auto-fill-mode 1)
)
;; (add-hook 'org-mode-hook 'org-indent-mode)
(setq org-confirm-babel-evaluate nil)
(org-babel-do-load-languages
'org-babel-load-languages
'((emacs-lisp . t)
(shell . t)
(python . t)))
(use-package org
:pin org
:commands (org-capture org-agenda)
:hook (org-mode . kdb/org-mode-setup)
:config
(setq org-ellipsis " ▾")
(setq org-src-fontify-natively t)
(setq org-src-tab-acts-natively t)
(setq org-hide-emphasis-markers t)
(setq org-confirm-babel-evaluate nil)
(setq org-export-with-smart-quotes t)
(setq org-src-window-setup 'current-window)
(setq org-directory "~/org/")
(setq org-todo-keywords
'((sequence "TODO" "IN PROGRESS" "|" "DONE" "DELEGATED" "BLOCKED" "FIXME")))
(setq org-structure-template-alist ; CHANGED in Org 9.3, Emacs 27.1
'(("s" . "src")
("E" . "src emacs-lisp")
("e" . "example")
("q" . "quote")
("v" . "verse")
("V" . "verbatim")
("c" . "center")
("C" . "comment")))
;; (setq org-todo-keyword-faces
;; '(("TODO" . org-warning) ("IN PROGRESS" . "yellow")
;; ("BLOCKED" . (:foreground "blue" :weight bold))))
;; code blocks
(setq org-confirm-babel-evaluate nil)
(setq org-src-window-setup 'current-window)
(setq org-edit-src-persistent-message nil)
(setq org-src-fontify-natively t)
(setq org-src-preserve-indentation t)
(setq org-src-tab-acts-natively t)
(setq org-edit-src-content-indentation 0)
;; export
(setq org-export-with-toc t)
(setq org-export-headline-levels 8)
(setq org-export-dispatch-use-expert-ui nil)
(setq org-html-htmlize-output-type nil)
(setq org-html-head-include-default-style nil)
(setq org-html-head-include-scripts nil)
(require 'ox-texinfo)
(require 'ox-md)
(setq org-export-backends '(html texinfo md))
)
;; Org-Mode Snippets
(define-skeleton org-header-skeleton
"Header info for a emacs-org file."
"Title: "
"#+TITLE: " str " \n"
"#+AUTHOR: " user-full-name "\n"
"#+EMAIL: " user-mail-address "\n"
"#+DATE: " (format-time-string "%Y-%m-%d") "\n"
"-----"
)
(global-set-key [C-S-f1] 'org-header-skeleton)
;; Org Files
(defun todo-visit ()
"Load ~/.org/todo.org for editing."
(interactive)
(find-file "~/org/todo.org"))
(global-set-key (kbd "C-c e t") 'todo-visit)
;; PDF Tools ===================================== ;;
;; (use-package pdf-tools
;; :config
;; ;; initialise
;; (pdf-tools-install)
;; ;; open pdfs scaled to fit page
;; (setq-default pdf-view-display-size 'fit-page)
;; ;; automatically annotate highlights
;; (setq pdf-annot-activate-created-annotations t)
;; ;; use normal isearch
;; (define-key pdf-view-mode-map (kbd "C-s") 'isearch-forward))
;; Config ======================================= ;;
(defun config-visit ()
"Load ~/.emacs.custom/init.el for editing."
(interactive)
(find-file "~/.emacs.custom/init.el"))
(global-set-key (kbd "C-c e v") 'config-visit)
(defun config-reload ()
"Reload ~/.emacs.custom/init.el at runtime."
(interactive)
(load-file (expand-file-name "~/.emacs.custom/init.el")))
(global-set-key (kbd "C-c e r") 'config-reload)
;; Buffers ======================================== ;;
;; Hide useless buffers
;; (require 'ibuf-ext)
;; (add-to-list 'ibuffer-never-show-predicates "^\\*")
(defun kill-current-buffer ()
"Kill the current buffer."
(interactive)
(kill-buffer (current-buffer)))
(global-set-key (kbd "C-x k") 'kill-current-buffer)
(defun kill-buffer-other-window ()
"Kill buffer in the other window."
(interactive)
(other-window 1)
(kill-buffer (current-buffer))
(other-window 1))
(global-set-key (kbd "C-x M-k") 'kill-buffer-other-window)
(defun indent-current-buffer ()
"Indent the current buffer while maintaining cursor position."
(interactive)
(indent-region (point-min) (point-max)))
(global-set-key (kbd "<backtab>") 'indent-current-buffer)
(defun copy-whole-buffer ()
"Copy the current buffer while maintaining cursor position."
(interactive)
(save-excursion
(goto-char (point-min))
(push-mark (point-max) nil t)
(copy-region-as-kill 1 (buffer-size))))
(global-set-key (kbd "C-x c") 'copy-whole-buffer)
;; Window Splits ================================== ;;
;; (defun split-and-follow-horizontally ()
;; "Focus follows horizontal split."
;; (interactive)
;; (split-window-below)
;; (balance-windows)
;; (other-window 1))
;; (global-set-key (kbd "C-x 2") 'split-and-follow-horizontally)
;; (defun split-and-follow-vertically ()
;; "Focus follows vertical split."
;; (interactive)
;; (split-window-right)
;; (balance-windows)
;; (other-window 1))
;; (global-set-key (kbd "C-x 3") 'split-and-follow-vertically)
;; Screenshots ==================================== ;;
;; Take screenshot of entire screen
(defun kdb/take-screenshot ()
"Take a fullscreen screenshot of the current workspace."
(interactive)
(when window-system
(cl-loop for i downfrom 3 to 1 do
(progn
(message (concat (number-to-string i) "..."))
(sit-for 1)))
(message "Cheese!")
(sit-for 1)
(start-process "screenshot" nil "import" "-window" "root"
(concat (getenv "HOME") "/" (subseq (number-to-string (float-time)) 0 10) ".png"))
(message "Screenshot taken!")))
;; Keybindings
(global-set-key (kbd "<print>") 'kdb/take-screenshot)
;; Take screenshot of region
(defun kdb/take-screenshot-region ()
"Takes a screenshot of a region selected by the user."
(interactive)
(when window-system
(call-process "import" nil nil nil ".newScreen.png")
(call-process "convert" nil nil nil ".newScreen.png" "-shave" "1x1"
(concat (getenv "HOME") "/" (subseq (number-to-string (float-time)) 0 10) ".png"))
(call-process "rm" nil nil nil ".newScreen.png")))
;; Keybindings
(global-set-key (kbd "<Scroll_Lock>") 'kdb/take-screenshot-region)
;; Emacs ============================================= ;;
(use-package emacs
:init
;; Add prompt indicator to `completing-read-multiple'.
;; Alternatively try `consult-completing-read-multiple'.
(defun crm-indicator (args)
(cons (concat "[CRM] " (car args)) (cdr args)))
;; (advice-add #'completing-read-multiple :filter-args #'crm-indicator)
(advice-add #'consult-completing-read-multiple :filter-args #'crm-indicator)
;; Do not allow the cursor in the minibuffer prompt
(setq minibuffer-prompt-properties
'(read-only t cursor-intangible t face minibuffer-prompt))
(add-hook 'minibuffer-setup-hook #'cursor-intangible-mode)
;; Enable recursive minibuffers
(setq enable-recursive-minibuffers t)
:config
(setq window-divider-default-right-width 1)
(setq window-divider-default-bottom-width 1)
(setq window-divider-default-places t)
(window-divider-mode -1))
;; EWW =============================================== ;;
(setq
browse-url-browser-function 'eww-browse-url ; Use eww as the default browser
shr-use-fonts nil ; No special fonts
shr-use-colors nil ; No colours
shr-indentation 2 ; Left-side margin
shr-width 120 ; Fold text to 70 columns
shr-use-colors nil ; t is bad for accessibility
shr-max-image-proportion 0.6
shr-image-animate nil ; No GIFs, thank you!
shr-discard-aria-hidden t
shr-cookie-policy nil
eww-restore-desktop t
eww-desktop-remove-duplicates t
eww-header-line-format nil
eww-retrieve-command nil
eww-search-prefix "https://duckduckgo.com/html/?q="
eww-download-directory (expand-file-name "~/Downloads")
eww-suggest-uris
'(eww-links-at-point
thing-at-point-url-at-point)
eww-bookmarks-directory (locate-user-emacs-file "eww-bookmarks/")
eww-history-limit 150
eww-use-external-browser-for-content-type
"\\`\\(video/\\|audio\\)" ; On GNU/Linux check your mimeapps.list
eww-browse-url-new-window-is-tab nil
eww-form-checkbox-selected-symbol "[X]"
eww-form-checkbox-symbol "[ ]")
;; Olivetti ========================================== ;;
(use-package olivetti
:ensure
:diminish
:config
(setq olivetti-body-width 0.65)
(setq olivetti-minimum-body-width 120)
(setq olivetti-recall-visual-line-mode-entry-state t)
(define-minor-mode kdb/olivetti-mode
"Toggle buffer-local `olivetti-mode' with additional parameters.
Fringes are disabled. The modeline is hidden, except for
`prog-mode' buffers (see `kdb/hidden-mode-line-mode'). The
default typeface is set to a proportionately-spaced family,
except for programming modes (see `kdb/variable-pitch-mode').
The cursor becomes a blinking bar, per `kdb/cursor-type-mode'."
:init-value nil
:global nil
(if kdb/olivetti-mode
(progn
(olivetti-mode 1)
(set-window-fringes (selected-window) 0 0)
;; (kdb/variable-pitch-mode 1)
;; (kdb/cursor-type-mode 1)
(unless (derived-mode-p 'prog-mode)
(kdb/hidden-mode-line-mode 1))
(window-divider-mode 1))
(olivetti-mode -1)
(set-window-fringes (selected-window) nil) ; Use default width
;; (kdb/variable-pitch-mode -1)
;; (kdb/cursor-type-mode -1)
(unless (derived-mode-p 'prog-mode)
(kdb/hidden-mode-line-mode -1))
(window-divider-mode -1)))
:bind ("C-c m" . kdb/olivetti-mode))
;; Custom Files ===================================== ;;
;; (add-to-list 'load-path "~/.emacs.d/elisp")
;; ;; Custom elisp files
;; (mapc 'load (file-expand-wildcards "~/.emacs.d/elisp/*.el"))
;; (defun load-directory (dir)
;; "Load custom elisp files from specified DIR."
;; (let ((load-it (lambda (f)
;; (load-file (concat (file-name-as-directory dir) f)))
;; ))
;; (mapc load-it (directory-files dir nil "\\.el$"))))
;; Custom ========================================= ;;
(custom-set-variables
;; custom-set-variables was added by Custom.
;; If you edit it by hand, you could mess it up, so be careful.
;; Your init file should contain only one such instance.
;; If there is more than one, they won't work right.
'(package-selected-packages
'(wrap-region exec-path-from-shell desktop-environment flymake-mode eldoc-box editorconfig tempel yasnippet-snippets yas-snippet consult-dash dash-docs consult-eglot cape embark-consult embark tree-sitter-indent tree-sitter-langs tree-sitter ef-themes vterm json-mode yaml-mode orderless marginalia vertico olivetti ob-restclient restclient slime rust-mode tide typescript-mode xref-js2 js2-refactor js2-mode web-mode emmet-mode consult multiple-cursors magit hl-todo crux expand-region which-key diminish use-package)))
(custom-set-faces
;; custom-set-faces was added by Custom.
;; If you edit it by hand, you could mess it up, so be careful.
;; Your init file should contain only one such instance.
;; If there is more than one, they won't work right.
)
;; Local Variables:
;; no-byte-compile: t
;; indent-tabs-mode: nil
;; End:
;;; init.el ends here
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment