2024-06-24 17:57:17 +02:00
2020-10-01 12:08:11 +02:00
2021-04-12 06:34:30 +02:00
2022-10-04 13:23:52 +02:00
2020-09-01 11:21:57 +02:00
2022-10-04 13:23:52 +02:00
2020-09-25 14:52:22 +02:00
2024-06-24 17:57:17 +02:00

luxicks Emacs Configuration

This is my configuration for the emacs editor.

  • Personal information (name, email) are stored in a separate personal.el file.
  • Machine specific settings are stored in a separate custom.el file.
  • Both files are loaded automatically.

Set Up use-package

Packages provided by straight.el https://github.com/radian-software/straight.el

  (defvar bootstrap-version)
  (let ((bootstrap-file
         (expand-file-name "straight/repos/straight.el/bootstrap.el" user-emacs-directory))
        (bootstrap-version 6))
    (unless (file-exists-p bootstrap-file)
      (with-current-buffer
          (url-retrieve-synchronously
           "https://raw.githubusercontent.com/radian-software/straight.el/develop/install.el"
           'silent 'inhibit-cookies)
        (goto-char (point-max))
        (eval-print-last-sexp)))
    (load bootstrap-file nil 'nomessage))

  (straight-use-package 'use-package)
  (setq straight-use-package-by-default t)

  (package-initialize)

  (straight-use-package 'bind-key)

Theming

  (use-package modus-themes
    :straight t
    :config
    ;; Add all your customizations prior to loading the themes
    (setq modus-themes-italic-constructs t
          modus-themes-bold-constructs nil)

    ;; Maybe define some palette overrides, such as by using our presets
    (setq modus-themes-common-palette-overrides
          modus-themes-preset-overrides-intense)

    ;; Load the theme of your choice.
    (load-theme 'modus-operandi t)

    (define-key global-map (kbd "<f5>") #'modus-themes-toggle))

Set up the default frame look

  (setq default-frame-alist
        (append (list '(width  . 90) '(height . 50)
                      '(vertical-scroll-bars . nil)
                      '(internal-border-width . 5))))

Fix Defaults

Hide UI elements

Remove all those UI elements. They do not look good and waste space.

  (tool-bar-mode -1)
  (menu-bar-mode -1)
  (scroll-bar-mode -1)
  (tooltip-mode -1)
  (fringe-mode -1)

Disable file backups

Emacs sure loves to clutter directories with backup files.

  (setq make-backup-files nil)
  (setq auto-save-default nil)
  (setq create-lockfiles nil)

Setup dired

Configure dired to only use one buffer.

  (setf dired-kill-when-opening-new-dired-buffer t)
  (setq dired-listing-switches "-laGh1v --group-directories-first")

  (setq dired-omit-files
        (rx (or (seq bol (? ".") "#")     ;; emacs autosave files
                (seq bol "." (not (any "."))) ;; dot-files
                (seq "~" eol)                 ;; backup-files
                (seq bol "CVS" eol)           ;; CVS dirs
                )))

  (defun my-dired-init ()
    "to be run as hook for `dired-mode'."
    (interactive)

    (define-key dired-mode-map (kbd ".") #'dired-prev-dirline)
    (define-key dired-mode-map (kbd ",") #'dired-next-dirline)

    (define-key dired-mode-map (kbd "1") #'dired-do-shell-command)
    (define-key dired-mode-map (kbd "6") #'dired-up-directory)
    (define-key dired-mode-map (kbd "9") #'dired-hide-details-mode)

    (define-key dired-mode-map (kbd "b") #'dired-do-byte-compile)

    (define-key dired-mode-map (kbd "`") #'dired-flag-backup-files)

    (define-key dired-mode-map (kbd "e") nil)
    (define-key dired-mode-map (kbd "e c") #'dired-do-copy)
    (define-key dired-mode-map (kbd "e d") #'dired-do-delete)
    (define-key dired-mode-map (kbd "e g") #'dired-mark-files-containing-regexp)
    (define-key dired-mode-map (kbd "e h") #'dired-hide-details-mode)
    (define-key dired-mode-map (kbd "e m") #'dired-mark-files-regexp)
    (define-key dired-mode-map (kbd "e n") #'dired-create-directory)
    (define-key dired-mode-map (kbd "e r") #'dired-do-rename)
    (define-key dired-mode-map (kbd "e u") #'dired-unmark-all-marks)

    (dired-hide-details-mode 1)
    (dired-omit-mode 1))

  (add-hook 'dired-mode-hook 'my-dired-init)

  (eval-after-load "dired"
    '(progn
       (define-key dired-mode-map (kbd "RET") 'dired-find-alternate-file) ; was dired-advertised-find-file
       (define-key dired-mode-map (kbd "^") (lambda () (interactive) (find-alternate-file ".."))) ; was dired-up-directory
       ))

Other Settings

  ;; The default encoding should be utf-8 everywhere
  (prefer-coding-system 'utf-8)

  ;; All "Yes or No" questions can be shortend to "y or n".
  (defalias 'yes-or-no-p 'y-or-n-p)

  ;; No more startup messages and screens
  (setq inhibit-startup-screen t)
  (setq initial-buffer-choice  nil)
  (defun display-startup-echo-area-message ()
    (message "Welcome Back!"))

  ;; Highlight matching braces
  (show-paren-mode t)

  ;; cua-mode. Like any other editor
  (cua-mode t)

  ;; Configure the cursor
  (setq-default
   cursor-type 'bar
   indent-tabs-mode nil
   cursor-in-non-selected-windows nil)
  (blink-cursor-mode 0)

  ;; Default column with
  (set-fill-column 95)

  ;; Start up in the home directory
  (setq default-directory "~/")

  ;; Make C-k always kill the whole line
  (setq kill-whole-line t)

  ;; Do not ding. Ever.
  (setq ring-bell-function 'ignore)

  ;; Dialogues always go in the modeline.
  (setq use-dialog-box nil)

  ;; Show tooltips on hover and not in the echo area.
  ;; Those are often cut of.
  (tooltip-mode)

  ;; Better line wraping
  (global-visual-line-mode 1)

Keybindings

  (bind-key "C-x k"      'kill-buffer-with-prejudice)
  (bind-key "C-x C-k"    'kill-buffer-and-window)
  (bind-key "M-p"        'switch-to-previous-buffer)
  (bind-key "M-i"        'delete-indentation)
  (bind-key "C-+"        'text-scale-increase)
  (bind-key "C--"        'text-scale-decrease)
  ;; buffer-list is not a good default
  (bind-key "C-x C-b"    'ibuffer)
  (bind-key "C-c n"      'display-line-numbers-mode)
  (global-set-key (kbd "<f12>") 'menu-bar-mode)

Unbind useless keys.

  (unbind-key "C-<tab>") ;; prevent switching to tab mode randomly
  (unbind-key "C-h n")   ;; I have never wanted to see emacs news ever
  (unbind-key "C-h C-n") ;; why on earth is it bound to two keybindings??
  (unbind-key "C-x C-d") ;; list-directory is utterly useless given the existence of dired
  (unbind-key "C-x C-r") ;; as is find-file-read-only

Useful Functions

Edit This File

A simple funtion to open this file for quick editing.

  (defun edit-config ()
    (interactive)
    (find-file "~/.emacs.d/README.org"))

Reformating

Reindet the whole buffer with F1

  (defun lux/indent-buffer ()
    "Reindents the whole buffer"
    (interactive)
    (save-excursion
      (indent-region (point-min) (point-max) nil)))
  (global-set-key [f1] 'lux/indent-buffer)

Window Splitting

These are functions for splitting windows and move the cursor over immediately.

  (defun lux/split-right-and-enter ()
    "Split the window to the right and enter it."
    (interactive)
    (split-window-right)
    (other-window 1))
  (bind-key "M-3" 'lux/split-right-and-enter)

  (defun lux/split-below-and-enter ()
    "Split the window down and enter it."
    (interactive)
    (split-window-below)
    (other-window 1))
  (bind-key "M-2" 'lux/split-below-and-enter)

Rebind the default window controls to use "M-*" keys for ease-of-use

  (bind-key "M-1" 'delete-other-windows)
  (bind-key "C-M-1" 'delete-other-windows)
  (bind-key "M-0" 'delete-window)

Quick buffer switching

  (defun switch-to-previous-buffer ()
    "Switch to previously open buffer.Repeated invocations toggle between the two most recently open buffers."
    (interactive)
    (switch-to-buffer (other-buffer (current-buffer) 1)))

Fonts

Set up the fonts to use.

  (set-face-attribute 'default nil :font "Iosevka Term-12")
  (set-face-attribute 'fixed-pitch nil :font "Iosevka Term-12")
  (set-face-attribute 'variable-pitch nil :font "Iosevka Aile")


  (let* ((variable-tuple
          (cond ((x-list-fonts "Iosevka Aile") '(:font "Iosevka Aile"))
                ((x-family-fonts "Sans Serif")        '(:family "Sans Serif"))
                (nil (warn "Cannot find a Sans Serif Font.  Install Source Sans Pro."))))
         (base-font-color     (face-foreground 'default nil 'default))
         (headline           `(:inherit default :weight bold :foreground ,base-font-color)))

    (custom-theme-set-faces
     'user
     `(org-level-8 ((t (,@headline ,@variable-tuple))))
     `(org-level-7 ((t (,@headline ,@variable-tuple))))
     `(org-level-6 ((t (,@headline ,@variable-tuple))))
     `(org-level-5 ((t (,@headline ,@variable-tuple))))
     `(org-level-4 ((t (,@headline ,@variable-tuple))))
     `(org-level-3 ((t (,@headline ,@variable-tuple))))
     `(org-level-2 ((t (,@headline ,@variable-tuple))))
     `(org-level-1 ((t (,@headline ,@variable-tuple))))
     `(org-document-title ((t (,@headline ,@variable-tuple :underline nil))))))

  (custom-theme-set-faces
   'user
   '(variable-pitch ((t (:family "Iosevka Aile" :height 120 :weight thin))))
   '(fixed-pitch ((t ( :family "Iosevka Term" :height 120)))))

Completion

Ivy

Use Ivy to make minibuf promts better. Adds the ability to sort and filter.

  (use-package ivy
    :straight t
    :diminish
    :init
    (ivy-mode 1)
    (unbind-key "S-SPC" ivy-minibuffer-map)
    (setq ivy-height 30
          ivy-use-virtual-buffers t
          ivy-use-selectable-prompt t)
    :bind (("C-x b"   . ivy-switch-buffer)
           ("C-c C-r" . ivy-resume)
           ("C-s"     . swiper)))

  ;; ivy-rich makes Ivy look a little bit more like Helm.
  (use-package ivy-rich
    :straight t
    :after counsel
    :custom
    (ivy-virtual-abbreviate 'full
                            ivy-rich-switch-buffer-align-virtual-buffer t
                            ivy-rich-path-style 'abbrev)
    :init
    (ivy-rich-mode))

  (use-package ivy-hydra
    :straight t)

Smex

Sort commands by recency in ivy windows

  (use-package smex
    :straight t)

Counsel

  (use-package counsel
    :straight t
    :after ivy
    :init (counsel-mode 1)
    :bind (("C-c ;" . counsel-M-x)
           ("C-c U" . counsel-unicode-char)
           ("C-c i" . counsel-imenu)
           ("C-c y" . counsel-yank-pop)
           ("C-c r" . counsel-recentf)
           :map ivy-minibuffer-map
           ("C-r" . counsel-minibuffer-history))
    :diminish)

Ido

  (use-package ido
    :straight t
    :config (ido-mode 1)
    :bind (("C-x f" . ido-find-file)))

Autocompletion

  (use-package auto-complete
    :straight t
    :config
    (ac-config-default))

Magit

Magit is THE go to package for using git in emacs.

  (use-package magit
    :straight t
    :bind (("C-c g" . magit-status))
    :diminish magit-auto-revert-mode
    :diminish auto-revert-mode
    :custom
    (magit-remote-set-if-missing t)
    (magit-diff-refine-hunk t)
    :config
    (magit-auto-revert-mode t)
    (advice-add 'magit-refresh :before #'maybe-unset-buffer-modified)
    (advice-add 'magit-commit  :before #'maybe-unset-buffer-modified)
    (setq magit-completing-read-function 'ivy-completing-read)
    (add-to-list 'magit-no-confirm 'stage-all-changes))

  (use-package libgit
    :straight t
    :disabled
    :after magit)

The advice-add entries are thereto stop magit from bugging us to save buffers when commiting and refreshing.

Helper Functions

  (autoload 'diff-no-select "diff")
  (defun current-buffer-matches-file-p ()
    "Return t if the current buffer is identical to its associated file."
    (when (and buffer-file-name (buffer-modified-p))
      (diff-no-select buffer-file-name (current-buffer) nil 'noasync)
      (with-current-buffer "*Diff*"
        (and (search-forward-regexp "^Diff finished \(no differences\)\." (point-max) 'noerror) t))))

Clear modified bit on all unmodified buffers

  (defun maybe-unset-buffer-modified (&optional _)
    (interactive)
    (dolist (buf (buffer-list))
      (with-current-buffer buf
        (when (and buffer-file-name (buffer-modified-p) (current-buffer-matches-file-p))
          (set-buffer-modified-p nil)))))

Don't prompt to save unmodified buffers on exit.

  (advice-add 'save-buffers-kill-emacs :before #'maybe-unset-buffer-modified)
  (defun kill-buffer-with-prejudice (&optional _)
    "Kill a buffer, eliding the save dialogue if there are no diffs."
    (interactive)
    (when (current-buffer-matches-file-p) (set-buffer-modified-p nil))
    (kill-buffer))

Org Mode

Configuration to make org-mode better as a word processor

  (use-package org-modern
    :straight t
    :hook (org-mode . org-modern-mode))

  (setq
   ;; Edit settings
   org-auto-align-tags nil
   org-tags-column 0
   org-catch-invisible-edits 'show-and-error
   org-special-ctrl-a/e t
   org-insert-heading-respect-content t

   ;; Org styling, hide markup etc.
   org-hide-emphasis-markers t
   org-pretty-entities t
   )

  ;; Ellipsis styling
  (setq org-ellipsis "…")
  (set-face-attribute 'org-ellipsis nil :inherit 'default :box nil)

  ;; Always collapse org files
  (setq org-startup-folded t)

Archive Location

When archiving items in org files, the default ist to crate a separate file named <filename>.org_archive. This clutters up my notes folder quite a bit, as I use a lot of separate files with thier respective archives. All archives should be stored in a single .archive file per directory.

  (setq org-archive-location "./.archive::* From %s")

Templates

Babel

Here we set custom templates to be used for structure expansion. These are used when we type "<" folowed by the shortcut for a template and hit "TAB". e.g. "<s TAB" expands to #+BEGIN_SRC ?\n\n#+END_SRC

Use org-tempo to quickly insert the structures

  (require 'org-tempo)

Shortcut for creating emacs-lisp code blocks. This is used extensively in this very file.

  (add-to-list 'org-structure-template-alist '("el" . "src emacs-lisp"))

Misc Packages

All The Icons

We want to have some nice looking icons

  (use-package all-the-icons
    :straight t)

Recentf

Show recent files in the buffer selection

  (use-package recentf
    :straight t
    :init (recentf-mode t)
    :config
    (add-to-list 'recentf-exclude "\\.emacs.d")
    (add-to-list 'recentf-exclude ".+tmp......\\.org"))

Rainbow Delimiters

We want to have some nicely colored delimiters when reading and writing lisp code

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

Markdown Mode

  (use-package markdown-mode
    :straight t
    :mode ("\\.md$" . gfm-mode)
    :config
    (when (executable-find "pandoc")
      (setq markdown-command "pandoc -f markdown -t html")))

Duplicate Thing

Quick bind to C-c u to duplicate the current line

  (use-package duplicate-thing
    :straight t
    :bind (("C-c u" . duplicate-thing)))

ACE Window

Small package to quickly switch tiled windows. Use M-o to quickly switch.

  (use-package ace-window
    :straight t
    :bind (("M-o" . 'ace-window))
    :config
    (custom-set-faces
     '(aw-leading-char-face
       ((t (:inherit ace-jump-face-foreground :height 3.0))))
     ))

Ag

Ag.el allows you to search using ag from inside Emacs. You can filter by file type, edit results inline, or find files.

Documentation

  (use-package ag
    :straight t)

Programming

General

  (use-package paredit
    :straight t)
  (autoload 'enable-paredit-mode "paredit" "Turn on pseudo-structural editing of Lisp code." t)
  (add-hook 'emacs-lisp-mode-hook       #'enable-paredit-mode)
  (add-hook 'eval-expression-minibuffer-setup-hook #'enable-paredit-mode)
  (add-hook 'ielm-mode-hook             #'enable-paredit-mode)
  (add-hook 'lisp-mode-hook             #'enable-paredit-mode)
  (add-hook 'lisp-interaction-mode-hook #'enable-paredit-mode)
  (add-hook 'scheme-mode-hook           #'enable-paredit-mode)

  (add-hook 'prog-mode-hook 'display-line-numbers-mode)

Copilot

  (use-package copilot
    :straight (:host github :repo "zerolfx/copilot.el" :files ("dist" "*.el"))
    :ensure t)

  (add-hook 'prog-mode-hook 'copilot-mode)
  (define-key copilot-completion-map (kbd "<tab>") 'copilot-accept-completion)
  (define-key copilot-completion-map (kbd "TAB") 'copilot-accept-completion)
  (define-key copilot-completion-map (kbd "M--") 'copilot-complete)

Elisp

Some customization for writing elisp

  (defun my-elisp-mode-hook ()
    "My elisp customizations."
    (electric-pair-local-mode 1)
    (add-hook 'before-save-hook 'check-parens nil t)
    (auto-composition-mode nil))

  (add-hook 'emacs-lisp-mode-hook 'my-elisp-mode-hook)

Common Lisp

  (setq inferior-lisp-program "sbcl")
  (use-package slime
    :straight t)
  (slime-setup '(slime-fancy slime-quicklisp slime-asdf))
  (add-hook 'slime-repl-mode-hook (lambda () (paredit-mode +1)))

Load additional files

All information about the current user should reside in the personal.el file. This file contains personal information like name, email or other identifying information. This file should contain definitions, that are the same on every device, but sould not be commited to a repository.

  (setq personal-file "~/.emacs.d/personal.el")
  (load personal-file 'noerror)

Load a custom file from the emacs home dir. This file is specific to the machine emacs runs on. It conatins customizations and file locations that are machine dependend.

  (setq custom-file "~/.emacs.d/custom.el")
  (load custom-file 'noerror)
Description
My Configuration for GNU/Emacs
Readme 1.1 MiB
Languages
Emacs Lisp 68.2%
CSS 30.5%
YASnippet 1.3%