Skip to content

Latest commit

 

History

History
708 lines (586 loc) · 20.1 KB

config.org

File metadata and controls

708 lines (586 loc) · 20.1 KB

Emacs Config

Notes

Catalina and Emacs don’t play well but there’s workarounds

Edit a source code block with `C-c ‘`

Sources of inspiration: https://github.com/dpsutton/tangled/blob/master/init.org

Initial Setup

Startup

Taken from Bedrock https://git.sr.ht/~ashton314/emacs-bedrock/tree/main/item/early-init.el

;; Startup speed, annoyance suppression
(setq gc-cons-threshold 10000000)
(setq byte-compile-warnings '(not obsolete))
(setq warning-suppress-log-types '((comp) (bytecomp)))
(setq native-comp-async-report-warnings-errors 'silent)

Hackarounds

hackaround for a TLS bug https://debbugs.gnu.org/cgi/bugreport.cgi?bug=34341 (allegedly fixed in 26.3)

(setq gnutls-algorithm-priority "NORMAL:-VERS-TLS1.3")

Hide custom file

Redirects custom to hidden file - the reason for this is I’ve decided to avoid using the custom feature and try and do everything via this config, but it’s impossible to do away without it completely as it gets written to automatically (when installing packages, for example)

(if (not (file-exists-p (concat user-emacs-directory ".emacs-custom.el")))
    (with-temp-buffer (write-file (concat user-emacs-directory ".emacs-custom.el"))))
(setq custom-file (concat user-emacs-directory ".emacs-custom.el"))

Setup use-package

https://github.com/jwiegley/use-package https://jwiegley.github.io/use-package/keywords/

(require 'package)

;; Setup archives and download packages
(add-to-list 'package-archives
'("melpa" . "https://melpa.org/packages/") t)
(add-to-list 'package-archives
'("org" . "https://orgmode.org/elpa/") t)
(package-initialize)

(when (not package-archive-contents)
  (message "%s" "Emacs is now refreshing its package database...")
  (package-refresh-contents))

;; Install use-package
(when (not (package-installed-p 'use-package))
  (package-install 'use-package))

;; Ensure all packages
(require 'use-package-ensure)
(setq use-package-always-ensure t)

(require 'use-package)

Fix Exec path

https://github.com/purcell/exec-path-from-shell This is to fix the issue where the GUI emacs path doesn’t match the shell path and so various commands don’t work.

(use-package exec-path-from-shell
  :config
  (when (memq window-system '(mac ns x))
    (exec-path-from-shell-initialize)))

Theming

 (use-package nord-theme
   :config
   (load-theme 'nord t))

 (defun dcf--pick-a-font-size ()
   "Tries to pick a good font size (in range 8-13) based on screen size."
   (let ((size 8))
     (dolist (l (display-monitor-attributes-list))
	(let* ((px (nth 4 (assoc 'geometry l)))
	       (mm (nth 2 (assoc 'mm-size l)))
	       (ratio (/ (float mm) px))
	       (size-cand (min 13 (floor (* 80 ratio)))))
	  (setq size (max size size-cand))))
     size))

 ;(set-frame-font (concat "Fira Code " (number-to-string (dcf--pick-a-font-size))))

 (add-to-list 'default-frame-alist `(font . ,(concat "Fira Code " (number-to-string (dcf--pick-a-font-size)))))

Ligatures

(use-package ligature
  :config
  ;; Enable the www ligature in every possible major mode
  (ligature-set-ligatures 't '("www"))

  ;; Enable ligatures in programming modes                                                           
  (ligature-set-ligatures
   'prog-mode
   '("www" "**" "***" "**/" "*>" "*/" "\\\\" "\\\\\\" "{-" "::"
     ":::" ":=" "!!" "!=" "!==" "-}" "----" "-->" "->" "->>"
     "-<" "-<<" "-~" "#{" "#[" "##" "###" "####" "#(" "#?" "#_"
     "#_(" ".-" ".=" ".." "..<" "..." "?=" "??" ";;" "/*" "/**"
     "/=" "/==" "/>" "//" "///" "&&" "||" "||=" "|=" "|>" "^=" "$>"
     "++" "+++" "+>" "=:=" "==" "===" "==>" "=>" "=>>" "<="
     "=<<" "=/=" ">-" ">=" ">=>" ">>" ">>-" ">>=" ">>>" "<*"
     "<*>" "<|" "<|>" "<$" "<$>" "<!--" "<-" "<--" "<->" "<+"
     "<+>" "<=" "<==" "<=>" "<=<" "<>" "<<" "<<-" "<<=" "<<<"
     "<~" "<~~" "</" "</>" "~@" "~-" "~>" "~~" "~~>" "%%"))

  (global-ligature-mode 't))

Defaults

Hacked together from things like prelude and bedrock etc

 (tool-bar-mode -1)
 (scroll-bar-mode -1)
 (global-visual-line-mode 1)

 ;; specify font for all unicode characters
 ;; (add-to-list 'default-frame-alist '(font . "Source Code Pro for Powerline 16"))
 (add-to-list 'default-frame-alist '(ns-transparent-titlebar . t))
 (add-to-list 'default-frame-alist '(ns-appearance . dark))
 (add-to-list 'default-frame-alist '(fullscreen . maximized))
 (add-to-list 'default-frame-alist '(background-color . "#000000"))

 (setq line-number-mode t) ;; show line number
 (setq column-number-mode t) ;; show column number
 (setq frame-title-format nil) ;; keep top bar emtpy
 (setq inhibit-startup-screen t) ;; go straight to scratch on startup
 (setq ns-pop-up-frames nil) ;; open files in same frame
 (setq initial-major-mode 'fundamental-mode)  ;; default in *scratch*

 ;; Automatically reread from disk if the underlying file changes
 (setq auto-revert-interval 1)
 (setq auto-revert-check-vc-info t)
 (global-auto-revert-mode)

 ;; Fix archaic defaults
 (setq sentence-end-double-space nil)

 ;; Make right-click do something sensible
 (when (display-graphic-p)
   (context-menu-mode))

 ;; Sensible Defaults
 (setq ring-bell-function 'ignore)
 (setq mac-right-option-modifier nil)
 (setq mac-function-modifier 'hyper)
 (fset 'yes-or-no-p 'y-or-n-p)
 (define-key global-map (kbd "RET") 'newline-and-indent)

 ;; Minibuffer
 (setq enable-recursive-minibuffers t) ;; dangerous?
 (setq completions-detailed t) ;; show annotations

 (savehist-mode)

 ;; Cursor
 (blink-cursor-mode -1)
 (let ((hl-line-hooks '(text-mode-hook prog-mode-hook)))
   (mapc (lambda (hook) (add-hook hook 'hl-line-mode)) hl-line-hooks))


 ;; Window splits
  (setq
   split-width-threshold 160
   split-height-threshold 80)

 ;; Backups and Autosaves
 (setq temporary-file-directory (concat user-emacs-directory "backups"))
 (if (not (file-exists-p temporary-file-directory))
     (make-directory temporary-file-directory t))

 (setq backup-directory-alist
	`((".*" . ,temporary-file-directory))
	auto-save-file-name-transforms
	`((".*" ,temporary-file-directory t)))
 (setq vc-make-backup-files t)

 ;; Disable lock files as they cause some tools (mostly file watchers) to crash
 ;; I only ever use one instance of emacs and I'm on a single user machine
 ;; So hopefully it won't be an issue!
 (setq create-lockfiles nil)

 ;; Seplling
 (setq ispell-program-name "aspell")

 ;; Allow use of dired 'a' to visit next dir or buffer and close current
 (put 'dired-find-alternate-file 'disabled nil)

General Tools

Editor Config

(use-package editorconfig
  :config
  (editorconfig-mode 1))

Which Key

shows a popup of available keybindings when typing a long key sequence (e.g. C-x …)

(use-package which-key
  :ensure t
  :config
  (which-key-mode))

Multiple cursors

(use-package multiple-cursors)

Vterm

https://github.com/akermu/emacs-libvterm

;; https://github.com/akermu/emacs-libvterm/issues/304#issuecomment-621617817
(defun vterm-send-C-k-with-kill-ring ()
  "Send `C-k' to libvterm."
  (interactive)
  (kill-ring-save (point) (vterm-end-of-line))
  (vterm-send-key "k" nil nil t))

(use-package vterm
  :after
  smartparens
  :config
  (define-key vterm-mode-map (kbd "C-q") #'vterm-send-next-key)
  (define-key vterm-mode-map (kbd "C-k") #'vterm-send-C-k-with-kill-ring)
  (add-to-list 'sp-ignore-modes-list 'vterm-mode))

Ag

You need to install ag and have it on your path for this to work.

(use-package ag)

Avy

https://github.com/abo-abo/avy

(use-package avy
  :after (isearch)
  :bind
  (("M-j" . avy-goto-char))
  :config
  (define-key isearch-mode-map (kbd "C-'") 'avy-isearch))

Vertico + Orderless

(use-package vertico
  :init
  (vertico-mode))

(use-package vertico-directory
  :after vertico
  :ensure nil
  ;; More convenient directory navigation commands
  :bind (:map vertico-map
		("RET" . vertico-directory-enter)
		("DEL" . vertico-directory-delete-char)
		("M-DEL" . vertico-directory-delete-word))
  ;; Tidy shadowed file names
  :hook (rfn-eshadow-update-overlay . vertico-directory-tidy))

(use-package orderless
  :custom
  (completion-styles '(orderless basic))
  (completion-category-overrides '((file (styles basic partial-completion)))))

Marginalia

(use-package marginalia
  ;; Bind `marginalia-cycle' locally in the minibuffer.  To make the binding
  ;; available in the *Completions* buffer, add it to the
  ;; `completion-list-mode-map'.
  :bind (:map minibuffer-local-map
	   ("M-A" . marginalia-cycle))

  ;; The :init section is always executed.
  :init

  ;; Marginalia must be activated in the :init section of use-package such that
  ;; the mode gets enabled right away. Note that this forces loading the
  ;; package.
  (marginalia-mode))

Consult

(use-package consult
  ;; Other good things to bind: consult-ripgrep, consult-line-multi,
  ;; consult-history, consult-outline
  :bind (("C-x b" . consult-buffer) ; orig. switch-to-buffer
	   ("M-y" . consult-yank-pop) ; orig. yank-pop
	   ("C-s" . consult-line))    ; orig. isearch
  :config
  ;; Narrowing lets you restrict results to certain groups of candidates
  (setq consult-narrow-key "<"))

Embark

 (use-package embark
   :demand t
   :after avy
   :bind (("C-." . embark-act))

   :init
   ;; Add the option to run embark when using avy
   (defun bedrock/avy-action-embark (pt)
     (unwind-protect
	  (save-excursion
	    (goto-char pt)
	    (embark-act))
	(select-window
	 (cdr (ring-ref avy-ring 0))))
     t)

   ;; After invoking avy-goto-char-timer, hit "." to run embark at the next
   ;; candidate you select
   (setf (alist-get ?. avy-dispatch-alist) 'bedrock/avy-action-embark)
   :config)

 (use-package embark-consult
   :hook
   (embark-collect-mode . consult-preview-at-point-mode))

Eglot

(use-package eglot
  ;; no :ensure t here because it's built-in

  ;; Configure hooks to automatically turn-on eglot for selected modes
					  ; :hook
					  ; (((python-mode ruby-mode elixir-mode) . eglot))

  :custom
  (eglot-send-changes-idle-time 0.1)

  :config
  (fset #'jsonrpc--log-event #'ignore)  ; massive perf boost---don't log every event  
  (setq eldoc-echo-area-prefer-doc-buffer t)
  ;; I'm just too used to how cider does it for now, leave out the docs
  (add-to-list 'eglot-stay-out-of 'eldoc)
  ;; pass extra arguments to clojure-lsp (though :hover config now irrelevant while not hooking into eldoc)
  ;; (add-to-list 'eglot-server-programs
  ;; 	       `(clojure-mode . ("clojure-lsp" :initializationOptions
  ;; 				 (:hover (:clojuredocs
  ;; 					  :json-false
  ;; 					  :hide-file-location?
  ;; 					  t
  ;; 					  :arity-on-same-line?
  ;; 					  t)))))
  )

;; Eglot can't navigate to inside jars by itself
(use-package jarchive
  :init
  (jarchive-setup))

FlyCheck

(use-package flycheck
  :hook (clojure-mode . flycheck-mode))

Dumb-Jump

Useful “mostly just works” jump to definition. It uses xref. https://github.com/jacktasia/dumb-jump

(use-package dumb-jump
  :config
  (add-hook 'xref-backend-functions #'dumb-jump-xref-activate))

M-. go-to definition M-, jump back

Projectile

Project navigation (where project often just means the git repo). I basically only use `C-c p f` to find file in project, but it can do a lot more. https://github.com/bbatsov/projectile

(use-package projectile
  :config
  (define-key projectile-mode-map (kbd "s-p") 'projectile-command-map)
  (define-key projectile-mode-map (kbd "C-c p") 'projectile-command-map)

  (projectile-mode +1)
  :bind (:map projectile-command-map
		("p" . consult-projectile)))

(use-package consult-projectile)

Magit

Magit. It’s amazing. But how is it pronounced?

(use-package magit
  :bind
  ("C-x g" . magit-status)
  :config
  (setq magit-display-buffer-function 'magit-display-buffer-same-window-except-diff-v1))

Smartparens

Using this instead of paredit - can’t remember why but it works pretty well https://github.com/Fuco1/smartparens

(use-package smartparens-config
  :ensure smartparens
  :config
  (smartparens-global-mode t)
  (show-smartparens-global-mode t)
  (setq sp-highlight-pair-overlay nil))

Smartparens Key map

(bind-keys
 :map smartparens-mode-map
 ("M-s M-a" . sp-beginning-of-sexp)
 ("M-s M-e" . sp-end-of-sexp)
 ("M-s M-f" . sp-forward-sexp)
 ("M-s M-b" . sp-backward-sexp)

 ("M-s M-d M-b" . sp-backward-down-sexp)
 ("M-s M-d M-f" . sp-down-sexp)
 ("M-s M-u M-b" . sp-backward-up-sexp)
 ("M-s M-u M-f" . sp-up-sexp)

 ("M-s M-n" . sp-next-sexp)
 ("M-s M-p" . sp-previous-sexp)

 ;; ("C-S-f" . sp-forward-symbol)
 ;; ("C-S-b" . sp-backward-symbol)

 ("C-<right>" . sp-forward-slurp-sexp)
 ("C-<left>" . sp-forward-barf-sexp)
 ("M-<left>"  . sp-backward-slurp-sexp)
 ("M-<right>"  . sp-backward-barf-sexp)

 ("C-M-t" . sp-transpose-sexp)
 ("M-k" . sp-kill-sexp)
 ("C-k"   . sp-kill-hybrid-sexp)
 ;; ("M-k"   . sp-backward-kill-sexp)
 ("C-M-w" . sp-copy-sexp)

 ("M-[" . sp-backward-unwrap-sexp)
 ("M-]" . sp-unwrap-sexp)
 ("M-p" . sp-splice-sexp))

Company

Autocompletion mode http://company-mode.github.io/ https://cider.readthedocs.io/en/latest/code_completion/ M-n / M-p to scroll C-s to search and C-o to stop C-w to see source, F1 to see documentation

(use-package company
  :config
  (global-company-mode)
  (setq company-idle-delay 1)
  (global-set-key (kbd "TAB") #'company-indent-or-complete-common))

Expand-Region

https://github.com/magnars/expand-region.el Useful for quickly selecting a logical unit (e.g a word, a paragraph, an s-expression) C-= to start, continue expand with =, contract with -

(use-package expand-region
  :bind
  ("C-=" . er/expand-region))

Ace-Window

Nicer window switching https://github.com/abo-abo/ace-window

(use-package ace-window
  :config
  (global-set-key (kbd "M-o") 'ace-window))

NeoTree

https://github.com/jaypei/emacs-neotree Bindings: n next line, p previous line。 SPC or RET or TAB Open current item if it is a file. Fold/Unfold current item if it is a directory. U Go up a directory g Refresh A Maximize/Minimize the NeoTree Window H Toggle display hidden files O Recursively open a directory C-c C-n Create a file or create a directory if filename ends with a ‘/’ C-c C-d Delete a file or a directory. C-c C-r Rename a file or a directory. C-c C-c Change the root directory. C-c C-p Copy a file or a directory.

(use-package neotree
  :config
  (setq neo-smart-open t)
  (setq neo-theme 'nerd)
  (setq neo-window-fixed-size nil)
  (global-set-key [f8] 'neotree-toggle))

Minions

Better minor mode management. Less noisy and includes them all. https://github.com/tarsius/minions

(use-package minions
  :config
  (setq minions-available-modes '())
  (setq minions-prominent-modes '(flycheck-mode))
  (setq minions-mode-line-lighter "...")
  (minions-mode 1))

Language Modes

Clojure

(use-package flycheck-clj-kondo)

(use-package clojure-mode
  :config
  (require 'flycheck-clj-kondo))
(use-package clj-refactor)

(use-package cider)

;; babashka shebang support #!/usr/bin/env bb
(add-to-list 'interpreter-mode-alist '("bb" . clojure-mode))

(defun my-clojure-mode-hook ()
  (clj-refactor-mode 1)
  (yas-minor-mode 1) ; for adding require/use/import statements
  ;; This choice of keybinding leaves cider-macroexpand-1 unbound
  (cljr-add-keybindings-with-prefix "C-c C-c"))

(add-hook 'clojure-mode-hook #'smartparens-strict-mode)
(add-hook 'clojure-mode-hook #'my-clojure-mode-hook)

Docker

(use-package dockerfile-mode)

Fennel

(use-package fennel-mode
  :config
  (put 'for-each 'fennel-indent-function 1)
  (put 'map-each 'fennel-indent-function 1)
  (put 'flatmap-each 'fennel-indent-function 1))

HTML/CSS

Web mode is designed for template but trying it for html.

We also hack our way into the css-mode constants to get auto-completion of missing properties.

(use-package web-mode
  :mode "\\.html?\\'")

(use-package css-mode
  :config
  (add-to-list 'css-property-alist '("margin-inline" margin-width))
  (add-to-list 'css-property-alist '("margin-inline-start" margin-width))
  (add-to-list 'css-property-alist '("margin-inline-end" margin-width))
  ;; This is a bit mad but it adds the added properties above to the auto-completion list
  (defconst css-property-ids
    (mapcar #'car css-property-alist)
    "Identifiers for properties."))

Javascript and Typescript

https://github.com/codesuki/add-node-modules-path This will hopefully allow for use of the project-local version of ‘prettier’ and any other relevant packages You’ll need to make sure you’ve run `yarn install` in the project and that it does indeed contain prettier

(use-package add-node-modules-path)

https://github.com/ananthakumaran/tide https://github.com/prettier/prettier-emacs/tree/

As of Emacs 27 using js-mode with js2-minor-mode I’m not sure how to use-package to install js2-mode without making it the main mode, so might have to install it manually…

(add-hook 'js-mode-hook 'js2-minor-mode)  

(use-package json-mode)
(use-package prettier-js)
(use-package tide
  :ensure t
  :config
  (setq tide-format-options '(:indentSize 2 :tabSize 2))
  (setq typescript-indent-level 2)
  :after (typescript-mode company flycheck)
  :hook ((typescript-mode . tide-setup)
	   (typescript-mode . tide-hl-identifier-mode)
	   (typescript-mode . add-node-modules-path)
	   (typescript-mode . prettier-js-mode)))

Markdown

https://jblevins.org/projects/markdown-mode/ C-c C-s for styling

(use-package markdown-mode
  :commands (markdown-mode gfm-mode)
  :mode (("README\\.md\\'" . gfm-mode)
	   ("\\.md\\'" . markdown-mode)
	   ("\\.markdown\\'" . markdown-mode))
  :init (setq markdown-command "multimarkdown"))

Python

Could also look at Jedi (currently trying out Elpy)

(use-package elpy
  :ensure t
  :init
  (elpy-enable))

Rust

(use-package rust-mode)

SQL

(use-package sql-indent)

Swift

(use-package swift-mode)
(use-package flycheck-swift
  :config
  (flycheck-swift-setup))
(setq flycheck-swift-sdk-path "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS13.0.sdk")
(setq flycheck-swift-target "arm64-apple-ios13")

Terraform

C-c C-f to toggle outline-mode folding

(use-package terraform-mode
  :config
  (defun my-terraform-mode-init ()
    ;; if you want to use outline-minor-mode
    (outline-minor-mode 1)
    )

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

YAML

(use-package yaml-mode)

Custom Functions

(defun run-love ()
  (interactive)
  (run-lisp "/Applications/love.app/Contents/MacOS/love ."))