This is my emacs, there are many like it, but this one is mine…
The very first thing you need to have installed is a recent version of
Emacs. I believe the minimum supported version is Emacs 24 otherwise
you’ll have to install package.el
and you’re on your own.
I strongly suggest you remap your cap locks key to control to help
reduce the onset of Emacs pinky. I even go further and have a new key
binding for M-x
, so you are hitting Ctrl
instead of Alt
.
You will need the following already installed for this configuration to run correctly.
Install the Fira Code Retina font because it’s beautiful and makes for a wonderful font. You will need ispell installed in order to user Flymake mode. Clojure mode requires leiningen.
I use melpa and melpa stable for my packages.
(require 'package)
(add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t)
(add-to-list 'package-archives '("melpa-stable" . "https://stable.melpa.org/packages/") t)
I don’t like my cider to be bleeding edge since it’s caused compatability problems in the past so pin it to melpa-stable.
(add-to-list 'package-pinned-packages '(cider . "melpa-stable") t)
Install my packages if they aren’t installed.
(package-initialize)
(when (not package-archive-contents)
(package-refresh-contents))
(defvar my-packages '(ag
bnf-mode
cider
clj-refactor
clojure-mode
csv-mode
company
dockerfile-mode
eclim
eglot
flycheck-plantuml
gradle-mode
htmlize
just-mode
lsp-mode
lsp-ui
magit
markdown-mode
nix-mode
nixpkgs-fmt
ox-gfm
paredit
plantuml-mode
projectile
protobuf-mode
rainbow-delimiters
rustic
string-inflection
terraform-mode
timu-spacegrey-theme
tuareg
yaml-mode)
"A list of packages to ensure are installed at launch.")
(dolist (p my-packages)
(when (not (package-installed-p p))
(package-install p)))
I like to have my Emacs clean, chrisp and minimal. Removing the menu bar, tool bar, and scroll bar frees some space and it helps remove dependency on the mouse. Protip: Learn the Emacs navigation key strokes until they are second nature. You can thank me later.
(setq inhibit-startup-message t)
;; (load-theme 'dracula t)
(load-theme 'timu-spacegrey t)
(dolist (mode '(menu-bar-mode tool-bar-mode scroll-bar-mode))
(when (fboundp mode) (funcall mode -1)))
(when window-system
;; (add-to-list 'default-frame-alist '(alpha . (95 . 50)))
;; (set-frame-parameter (selected-frame) 'alpha '(95 . 50))
(set-frame-font "Fira Code Retina 18" nil t))
Dats me.
(setq user-full-name "Trevor Bernard"
user-mail-address "trevor@bernard.gg")
Ignore minimize functionality when you’re in a GUI because it’s very annoying to accidently minimize your window.
(when window-system
(global-set-key "\C-z" 'ignore)
(global-set-key "\C-x\C-z" 'ignore))
M-x is one of the most wildly used key combinations in Emacs but it’s also the most annoying. You have to scrunch your left thumb and fore finger in the most uncomfortable RSI inducing way.
I choose to rebind M-x to C-x C-m because of an article Steve Yegge wrote called: Effective Emacs. This allows you to keep your fingers on the home row if you have caps lock mapped to control. With some practice, it will become intuitive.
(global-set-key "\C-x\C-m" 'execute-extended-command)
(global-set-key "\C-c\C-m" 'execute-extended-command)
(add-to-list 'load-path "~/.emacs.d/lisp/")
(set-fringe-mode 10) ; breathing room
(setq make-backup-files nil) ; stop creating backup~ files
(setq auto-save-default nil) ; stop creating #autosave# files
(setq interprogram-paste-function 'x-selection-value) ;
(global-auto-revert-mode t) ; Auto revert buffers
(ido-mode 1)
(column-number-mode 1) ; Show column number
(delete-selection-mode 1) ; Allow delete of selection
(fset 'yes-or-no-p 'y-or-n-p) ; Shorten confirmation message
(global-font-lock-mode 1) ; Syntax Highlighting
(show-paren-mode 1) ; Highlight parenthesis
;; Highlight selected Regions
(transient-mark-mode 1)
;; Make pgup/dn remember current line
(setq scroll-preserve-screen-position t)
(add-hook 'prog-mode-hook 'display-line-numbers-mode)
Use spaces in favour of tabs because they are evil. But when there are tabs show them as 8 spaces.
(setq-default indent-tabs-mode nil)
(setq-default c-basic-offset 4)
(setq-default tab-width 8)
Limit the default fill mode to 80 characters
(setq-default set-fill-column 80)
(setq-default truncate-lines nil)
Ignore the stupid ring bell feature.
(setq ring-bell-function 'ignore)
Allow functions without issuing warnings
(put 'downcase-region 'disabled nil)
(put 'narrow-to-region 'disabled nil)
(put 'upcase-region 'disabled nil)
(defun set-exec-path-from-shell-PATH ()
(let ((path-from-shell (shell-command-to-string "$SHELL -i -c 'echo $PATH'")))
(setenv "PATH" path-from-shell)
(setq exec-path (split-string path-from-shell path-separator))))
(defun my-mac-config ()
;; Mac's ls doesn't support --dired
(setq dired-use-ls-dired nil)
;; setup the correct shell path
(set-exec-path-from-shell-PATH)
;; Move to trash when deleting stuff
(setq delete-by-moving-to-trash t
trash-directory "~/.Trash/emacs")
;; Don't open files from the workspace in a new frame
(setq ns-pop-up-frames nil)
;; Use aspell for spell checking: brew install aspell --lang=en
(setq ispell-program-name "/opt/homebrew/bin/aspell")
;; Open up links in Google Chrome
(setq browse-url-browser-function 'browse-url-default-macosx-browser))
(when (equal system-type 'darwin)
(my-mac-config))
Bind projectile to C-c p
and enable by default.
(setq projectile-project-search-path '("~/p/"))
(setq projectile-keymap-prefix (kbd "C-c p"))
(projectile-mode +1)
C-c
is reserved for the user. Add a more friendly binding for
magit-file-dispatch
(global-set-key (kbd "C-c g") 'magit-file-dispatch)
(require 'cider)
(require 'clojure-mode)
(require 'company)
(setq nrepl-log-messages t)
(setq cider-repl-use-clojure-font-lock t)
(setq cider-repl-display-help-banner nil)
(defun my-cider-repl-mode-hook ()
(company-mode 1)
(paredit-mode 1)
(rainbow-delimiters-mode 1))
(defun my-cider-mode-hook ()
(company-mode 1)
(eldoc-mode 1))
(defun my-clojure-mode-hook ()
(setq show-trailing-whitespace 1)
(setq clojure-align-forms-automatically t)
(clj-refactor-mode 1)
(rainbow-delimiters-mode 1)
(linum-mode t)
(paredit-mode 1)
(subword-mode t)
(eldoc-add-command 'paredit-backward-delete 'paredit-close-round))
(add-hook 'cider-repl-mode-hook 'my-cider-repl-mode-hook)
(add-hook 'cider-mode-hook 'my-cider-mode-hook)
(add-hook 'clojure-mode-hook 'my-clojure-mode-hook)
I have long since used this key binding to jack into a repl. My fingers are programmed this way.
(global-set-key (kbd "C-c C-j") 'cider-jack-in)
When you hit f3
at the end of the sexp in Clojure, it will copy and
evaluate the function into the current repl. I no longer use this
function but it might be useful to someone eventually.
(defun my-last-expression ()
"Return the last sexp."
(buffer-substring-no-properties
(save-excursion (backward-sexp) (point))
(point)))
(defun cider-execute-in-current-repl (expr)
(if (not (get-buffer (cider-current-connection)))
(message "No active nREPL connection.")
(progn
(set-buffer (cider-current-repl))
(goto-char (point-max))
(insert expr)
(cider-repl-return))))
(defun cider-eval-expression-at-point-in-repl ()
(interactive)
(let ((form (my-last-expression)))
;; Eat white
(while (string-match "\\`\s+\\|\n+\\'" form)
(setq form (replace-match "" t t form)))
(cider-execute-in-current-repl form)))
(eval-after-load 'cider-repl-mode-hook
'(local-set-key '[f3] 'cider-eval-expression-at-point-in-repl))
This is required for re-frame cider intergration.
(setq cider-cljs-lein-repl
"(do (require 'figwheel-sidecar.repl-api)
(figwheel-sidecar.repl-api/start-figwheel!)
(figwheel-sidecar.repl-api/cljs-repl))")
(defun my-emacs-lisp-mode-hook ()
(paredit-mode 1)
(eldoc-mode 1))
(add-hook 'emacs-lisp-mode-hook 'my-emacs-lisp-mode-hook)
Some handy dandy paredit shortcuts
On mac ^-left and ^-right are bought to Misson Control. Go to System Preferences > Keyboard > Shortcuts > Mission Control and change the settings for “Move left a space” and “Move right a space” or disable them completely.
(eval-after-load 'paredit
'(progn
(define-key paredit-mode-map (kbd "C-<right>") 'paredit-forward-slurp-sexp)
(define-key paredit-mode-map (kbd "C-<left>") 'paredit-forward-barf-sexp)
(define-key paredit-mode-map (kbd "C-<backspace>") 'paredit-backward-kill-word)))
I almost exclusively use C-j
in place of hitting the enter key. The
problem is that it’s bound to org-return-indent
function. This is
very annoying in when you are in org-mode
. So instead of trying to
remap my brain, I’ll remap it to newline
.
(global-set-key (kbd "C-c l") #'org-store-link)
(global-set-key (kbd "C-c a") #'org-agenda)
(global-set-key (kbd "C-c c") #'org-capture)
(defun my-org-mode-hook ()
(turn-on-auto-fill)
(define-key org-mode-map (kbd "C-j") 'org-return)
(org-babel-do-load-languages
'org-babel-load-languages '((clojure . t)
(plantuml . t)
(rust . t)
(shell . t))))
(add-hook 'org-mode-hook 'my-org-mode-hook)
In order to export to PDF, I choose to use basictex and install packages only when they are missing.
brew reinstall --cask basictex
sudo tlmgr update --self
sudo tlmgr install wrapfig
sudo tlmgr install capt-of
(defun my-js-mode-hook ()
(setq js-indent-level 2))
(add-hook 'js-mode-hook 'my-js-mode-hook)
(autoload 'css-mode "css-mode" nil t)
(defun my-css-mode-hook ()
(setq css-indent-level 2)
(setq css-indent-offset 2))
(add-hook 'css-mode-hook 'my-css-mode-hook)
(autoload 'markdown-mode "markdown-mode" "Major mode for editing Markdown files" t)
;; Double click on mac mouse trackpad
(eval-after-load "flyspell"
'(progn
(define-key flyspell-mouse-map [down-mouse-3] #'flyspell-correct-word)
(define-key flyspell-mouse-map [mouse-3] #'undefined)))
(add-to-list 'auto-mode-alist '("\\.text\\'" . markdown-mode))
(add-to-list 'auto-mode-alist '("\\.markdown\\'" . markdown-mode))
(add-to-list 'auto-mode-alist '("\\.md\\'" . markdown-mode))
(defun my-markdown-hook ()
(auto-fill-mode t)
(flyspell-mode t))
(add-hook 'markdown-mode-hook 'my-markdown-hook)
Use diff-mode when editing a git commit message
(add-to-list 'auto-mode-alist '("COMMIT_EDITMSG$" . diff-mode))
Calling M-x ansi-term
will prompt you for which shell you want to
spawn. TODO. Find a keybinding
(defun my/term ()
(interactive)
(term "/bin/zsh"))
(require 'eglot)
(defun my-rust-mode-hook ()
(setq rustic-cargo-build-arguments "--release")
(setq rustic-default-clippy-arguments "--all-targets --all-features -- -D warnings")
(yas-minor-mode))
(add-hook 'rust-mode-hook 'my-rust-mode-hook)
(add-hook 'rust-mode-hook 'eglot-ensure)
(setq rustic-compile-command "cargo b --release")
(defun my-ielm-mode-hook ()
(paredit-mode 1)
(rainbow-delimiters-mode 1)
(define-key ielm-map (kbd "C-m") 'ielm-return)
(define-key ielm-map (kbd "<return>") 'ielm-return))
(add-hook 'ielm-mode-hook 'my-ielm-mode-hook)
(defun my-ocaml-mode-hook ())
(add-hook 'tuareg-mode-hook 'my-ocaml-mode-hook)
(defun my-nix-mode-hook ()
(nixpkgs-fmt-on-save-mode)
(define-key 'nix-mode-map (kbd "C-c C-f") 'nixpkgs-fmt))
(add-hook 'nix-mode-hook 'my-nix-mode-hook)