Files
.emacs.d/README.org
2023-07-05 10:33:01 +02:00

586 lines
17 KiB
Org Mode

#+TITLE: luxicks Emacs Configuration
#+PROPERTY: header-args :results silent
This is my configuration for the emacs editor.
Points of intrest:
- 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
#+BEGIN_SRC emacs-lisp
(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)
#+end_src
* Theming
Add the nano package from Github
#+begin_src emacs-lisp
(straight-use-package
'(nano-emacs :type git :host github :repo "rougier/nano-emacs"))
(setq nano-font-size 12)
#+end_src
Configure all nano modules
#+begin_src emacs-lisp
;; Default layout (optional)
(require 'nano-layout)
;; Theming Command line options (this will cancel warning messages)
(add-to-list 'command-switch-alist '("-dark" . (lambda (args))))
(add-to-list 'command-switch-alist '("-light" . (lambda (args))))
(add-to-list 'command-switch-alist '("-default" . (lambda (args))))
(add-to-list 'command-switch-alist '("-no-splash" . (lambda (args))))
(add-to-list 'command-switch-alist '("-no-help" . (lambda (args))))
(add-to-list 'command-switch-alist '("-compact" . (lambda (args))))
(cond
((member "-default" command-line-args) t)
((member "-dark" command-line-args) (require 'nano-theme-dark))
(t (require 'nano-theme-light)))
;; Customize support for 'emacs -q' (Optional)
;; You can enable customizations by creating the nano-custom.el file
;; with e.g. `touch nano-custom.el` in the folder containing this file.
(let* ((this-file (or load-file-name (buffer-file-name)))
(this-dir (file-name-directory this-file))
(custom-path (concat this-dir "nano-custom.el")))
(when (and (eq nil user-init-file)
(eq nil custom-file)
(file-exists-p custom-path))
(setq user-init-file this-file)
(setq custom-file custom-path)
(load custom-file)))
;; Theme
(require 'nano-faces)
(nano-faces)
(require 'nano-theme)
(nano-theme)
;; Nano session saving (optional)
(require 'nano-session)
;; Nano header & mode lines (optional)
(require 'nano-modeline)
;; Nano key bindings modification (optional)
(require 'nano-bindings)
;; Compact layout (need to be loaded after nano-modeline)
(when (member "-compact" command-line-args)
(require 'nano-compact))
;; Nano counsel configuration (optional)
;; Needs "counsel" package to be installed (M-x: package-install)
;; (require 'nano-counsel)
;; Welcome message (optional)
(let ((inhibit-message t))
(message "Welcome to GNU Emacs / N Λ N O edition")
(message (format "Initialization time: %s" (emacs-init-time))))
;; Splash (optional)
(unless (member "-no-splash" command-line-args)
(require 'nano-splash))
;; Help (optional)
(unless (member "-no-help" command-line-args)
(require 'nano-help))
#+end_src
*Set up the default frame look*
#+begin_src emacs-lisp
(setq default-frame-alist
(append (list '(width . 90) '(height . 60)
'(vertical-scroll-bars . nil)
'(internal-border-width . 5))))
#+end_src
* Fix Defaults
** Hide UI elements
Remove all those UI elements. They do not look good and waste space.
#+BEGIN_SRC emacs-lisp
(tool-bar-mode -1)
(menu-bar-mode -1)
(scroll-bar-mode -1)
(tooltip-mode -1)
(fringe-mode -1)
#+END_SRC
** Disable file backups
Emacs sure loves to clutter directories with backup files.
#+BEGIN_SRC emacs-lisp
(setq make-backup-files nil)
(setq auto-save-default nil)
(setq create-lockfiles nil)
#+END_SRC
** Setup dired
Configure dired to only use one buffer.
#+BEGIN_SRC emacs-lisp
(eval-after-load "dired"
'(progn
(defadvice dired-advertised-find-file (around dired-subst-directory activate)
"Replace current buffer if file is a directory."
(interactive)
(let* ((orig (current-buffer))
;; (filename (dired-get-filename))
(filename (dired-get-filename t t))
(bye-p (file-directory-p filename)))
ad-do-it
(when (and bye-p (not (string-match "[/\\\\]\\.$" filename)))
(kill-buffer orig))))))
(eval-after-load "dired"
;; don't remove `other-window', the caller expects it to be there
'(defun dired-up-directory (&optional other-window)
"Run Dired on parent directory of current directory."
(interactive "P")
(let* ((dir (dired-current-directory))
(orig (current-buffer))
(up (file-name-directory (directory-file-name dir))))
(or (dired-goto-file (directory-file-name dir))
;; Only try dired-goto-subdir if buffer has more than one dir.
(and (cdr dired-subdir-alist)
(dired-goto-subdir up))
(progn
(kill-buffer orig)
(dired up)
(dired-goto-file dir))))))
#+END_SRC
** Other Settings
#+begin_src emacs-lisp
;; 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)
#+end_src
** Keybindings
#+BEGIN_SRC emacs-lisp
(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)
#+END_SRC
Unbind useless keys.
#+BEGIN_SRC emacs-lisp
(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
#+END_SRC
* Useful Functions
** Edit This File
A simple funtion to open this file for quick editing.
#+BEGIN_SRC emacs-lisp
(defun edit-config ()
(interactive)
(find-file "~/.emacs.d/README.org"))
#+END_SRC
** Reformating
Reindet the whole buffer with ~F1~
#+BEGIN_SRC emacs-lisp
(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)
#+END_SRC
** Window Splitting
These are functions for splitting windows and move the cursor over immediately.
#+BEGIN_SRC emacs-lisp
(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)
#+END_SRC
Rebind the default window controls to use "M-*" keys for ease-of-use
#+begin_src emacs-lisp
(bind-key "M-1" 'delete-other-windows)
(bind-key "M-0" 'delete-window)
#+end_src
** Quick buffer switching
#+BEGIN_SRC emacs-lisp
(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)))
#+END_SRC
* Fonts
Set up the fonts to use. I like the [[https://typeof.net/Iosevka/][Iosevka]] font family.
#+begin_src emacs-lisp
(set-face-attribute 'default nil :font "Fantasque Sans Mono-12")
(set-face-attribute 'fixed-pitch nil :font "Fantasque Sans Mono-12")
(set-face-attribute 'variable-pitch nil :font "Fantasque Sans Mono-12")
#+end_src
* Completion
** Ivy
Use Ivy to make minibuf promts better. Adds the ability to sort and filter.
#+BEGIN_SRC emacs-lisp
(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)
#+END_SRC
** Smex
Sort commands by recency in ivy windows
#+BEGIN_SRC emacs-lisp
(use-package smex
:straight t)
#+END_SRC
** Counsel
#+BEGIN_SRC emacs-lisp
(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)
#+END_SRC
** Ido
#+begin_src emacs-lisp
(use-package ido
:straight t
:config (ido-mode 1)
:bind (("C-x f" . ido-find-file)))
#+end_src
** Autocompletion
#+BEGIN_SRC emacs-lisp
(use-package auto-complete
:straight t
:config
(ac-config-default))
#+END_SRC
* Magit
Magit is THE go to package for using git in emacs.
#+BEGIN_SRC emacs-lisp
(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)
#+END_SRC
The ~advice-add~ entries are thereto stop magit from bugging us to save buffers when commiting and refreshing.
** Helper Functions
#+BEGIN_SRC emacs-lisp
(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))))
#+END_SRC
Clear modified bit on all unmodified buffers
#+BEGIN_SRC emacs-lisp
(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)))))
#+END_SRC
Don't prompt to save unmodified buffers on exit.
#+BEGIN_SRC emacs-lisp
(advice-add 'save-buffers-kill-emacs :before #'maybe-unset-buffer-modified)
#+END_SRC
#+BEGIN_SRC emacs-lisp
(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))
#+END_SRC
* Org Mode
This is the main configuration for the infamous org-mode.
The most important parts are configuring key bindings to quickly access the files we have defined above.
#+BEGIN_SRC emacs-lisp
;; (use-package org
;; :straight t
;; ;; Always get this from the GNU archive.
;; :bind (:map org-mode-map
;; ("M-s-<return>" . org-insert-todo-heading)
;; ("M-<return>" . org-insert-heading-respect-content)
;; ("C-c a s" . org-emphasize)
;; ("C-c -" . org-edit-special))
;; :hook ((org-mode . visual-line-mode)
;; (org-mode . org-indent-mode))
;; :config
;; (setq org-pretty-entities t
;; org-indent-mode t
;; org-hide-leading-stars nil
;; org-link-file-path-type 'relative
;; org-hide-emphasis-markers t
;; )
#+END_SRC
** 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.
#+BEGIN_SRC emacs-lisp
(setq org-archive-location "./.archive::* From %s")
#+END_SRC
** 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
#+begin_src emacs-lisp
(require 'org-tempo)
#+end_src
Shortcut for creating ~emacs-lisp~ code blocks. This is used extensively in this very file.
#+BEGIN_SRC emacs-lisp
(add-to-list 'org-structure-template-alist '("el" . "src emacs-lisp"))
#+END_SRC
* Misc Packages
** All The Icons
We want to have some nice looking icons
#+BEGIN_SRC emacs-lisp
(use-package all-the-icons
:straight t)
#+END_SRC
** Recentf
Show recent files in the buffer selection
#+BEGIN_SRC emacs-lisp
(use-package recentf
:straight t
:init (recentf-mode t)
:config
(add-to-list 'recentf-exclude "\\.emacs.d")
(add-to-list 'recentf-exclude ".+tmp......\\.org"))
#+END_SRC
** Rainbow Delimiters
We want to have some nicely colored delimiters when reading and writing lisp code
#+BEGIN_SRC emacs-lisp
(use-package rainbow-delimiters
:straight t
:hook (prog-mode . rainbow-delimiters-mode))
#+END_SRC
** Markdown Mode
#+BEGIN_SRC emacs-lisp
(use-package markdown-mode
:straight t
:mode ("\\.md$" . gfm-mode)
:config
(when (executable-find "pandoc")
(setq markdown-command "pandoc -f markdown -t html")))
#+END_SRC
** Duplicate Thing
Quick bind to ~C-c u~ to duplicate the current line
#+BEGIN_SRC emacs-lisp
(use-package duplicate-thing
:straight t
:bind (("C-c u" . duplicate-thing)))
#+END_SRC
** ACE Window
Small package to quickly switch tiled windows.
Use ~M-o~ to quickly switch.
#+BEGIN_SRC emacs-lisp
(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))))
))
#+END_SRC
** Ag
Ag.el allows you to search using ~ag~ from inside Emacs. You can filter by file type, edit results inline, or find files.
[[https://agel.readthedocs.io/en/latest/index.html][Documentation]]
#+BEGIN_SRC emacs-lisp
(use-package ag
:straight t)
#+END_SRC
* Programming
** Elisp
Some customization for writing elisp
#+BEGIN_SRC emacs-lisp
(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)
#+END_SRC
* 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.
#+BEGIN_SRC emacs-lisp
(setq personal-file "~/.emacs.d/personal.el")
(load personal-file 'noerror)
#+END_SRC
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.
#+BEGIN_SRC emacs-lisp
(setq custom-file "~/.emacs.d/custom.el")
(load custom-file 'noerror)
#+END_SRC