I use Emacs and its literate programming features.
The content of both the Makefile and the files directory
is generated out of this org file, so do not edit these directly
but work on this document instead!
Then:
- Run
C-c C-v t - Commit all the changes
- Run
make
- Clone this repository (or pull the latest changes)
- Run
make
These are the files that will be copied over your home directory
install: $(HOME)/.gitconfig \ $(HOME)/.gitconfig-local \ $(HOME)/.gitignore \ $(HOME)/.emacs.d/init.el
brew install clojure-lsp/brew/clojure-lsp-native
My global Git configuration file will be installed in my home directory:
$(HOME)/.gitconfig: files/.gitconfig cp -f $^ $@
It will make provision for local additions that can’t be checked in for whatever reason (e.g. work stuff).
[include]
path = ~/.gitconfig-local
That file also lives in my home directory:
$(HOME)/.gitconfig-local:; touch $(HOME)/.gitconfig-local
These are the things I always want Git to ignore:
*~
.DS_Store
.\#*
.clj-kondo
.cljs_node_repl
.cpcache
.hgignore
.lsp
.nrepl-port
\#*\#
dist
node_modules
out
resources
target
These patterns live in a file in my home directory:
$(HOME)/.gitignore: files/.gitignore cp -f $^ $@
And that file is referenced in my global Git configuration file:
[core]
excludesFile = ~/.gitignore
Open Emacs maximised:
(add-to-list 'initial-frame-alist '(fullscreen . maximized))
Remember that what we usually refer to as a window is called a frame in Emacs parlance.
I don’t find both Emacs toolbar & scrollbar very useful so I disable them:
(tool-bar-mode -1) (scroll-bar-mode -1)
Disable default left and right margins:
(set-fringe-mode 0)
I always want to see line numbers so I enable that feature globally:
(global-display-line-numbers-mode t)
I need this as other I cannot type that character :)
(global-set-key (kbd "M-3") (lambda () (interactive) (insert "#")))
This seems to be frowned upon but I find using Shift and the arrow keys
really handy to navigate the windows:
(windmove-default-keybindings)This allows a "circular" navigation e.g. if you reach the last window
then Shift-<Arrow Left> get you back to the first window.
(setq windmove-wrap-around t)
(setq treesit-language-source-alist '((tsx "https://github.com/tree-sitter/tree-sitter-typescript" "master" "tsx/src") (typescript "https://github.com/tree-sitter/tree-sitter-typescript" "master" "typescript/src"))) (mapc #'treesit-install-language-grammar (mapcar #'car treesit-language-source-alist))
Indentation
(electric-indent-mode -1) (setq-default indent-tabs-mode nil) (setq-default tab-width 2) (setq-default js-indent-level 2)
I need this to avoid choking lsp-mode: https://emacs-lsp.github.io/lsp-mode/page/performance/
(setq read-process-output-max (* 1024 1024)) ;; 1mb (setq gc-cons-threshold 100000000)
Use ibuffer instead of list-buffers on C-x C-b
(global-set-key (kbd "C-x C-b") 'ibuffer)
I use straight.el as my package manager.
This is what is needed to bootstrap it:
(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)) ;; tell `use-package` to use `straight.el` as the package manager (setq straight-use-package-by-default t) (straight-use-package 'use-package)
First, make sure Fira Code is installed!
(set-frame-font "Fira Code:size=14") (use-package ligature :init ;; 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) )
(use-package vertico :ensure t :init (vertico-mode t) :custom (vertico-cycle t) ; goes back to the top when reaching the end of minibuffer )
(use-package marginalia :ensure t :init (marginalia-mode t))
Provide fuzzy search:
(use-package orderless :ensure t :config (setq completion-styles '(orderless basic)))
consult-xref is nice alternative to a plain *xref* buffer, especially
when combined with lsp-mode!
(use-package consult :init (setq xref-show-xrefs-function #'consult-xref xref-show-definitions-function #'consult-xref) :bind (("C-x b" . consult-buffer) ("C-s" . consult-line)))
(use-package which-key :init (which-key-mode t))
Install and use ef-themes from Prot.
(use-package ef-themes :init (ef-themes-select 'ef-maris-dark))
(use-package lsp-mode :commands lsp :init (setq lsp-keymap-prefix "C-c l") :hook ((typescript-ts-mode . lsp) (tsx-ts-mode . lsp) (clojure-mode . lsp)) :config (lsp-enable-which-key-integration t))
(use-package corfu :init (global-corfu-mode) :bind (:map corfu-map ("RET" . (lambda () (interactive) (corfu-quit) (newline-and-indent)))) :config (setq corfu-auto t))
Make sure Emacs can see the environment variables I have in my usual shell:
(use-package exec-path-from-shell :init (when (memq window-system '(mac ns x)) (exec-path-from-shell-initialize)))
Prevents org-mode from adding extra indentation:
(setq org-src-preserve-indentation t)
Let’s start with some basic project management stuff:
(use-package magit :init (with-eval-after-load 'project (keymap-set project-prefix-map "m" #'magit-project-status) (keymap-set project-prefix-map "g" #'consult-ripgrep) (setq project-switch-commands '((magit-project-status "Magit") (project-find-file "Find file") (consult-ripgrep "Find rg") (project-find-dir "Find dir") (project-shell "Shell")))))
(use-package embark :straight t :bind (("C-." . embark-act) ("C-h B" . embark-bindings)) :init (setq prefix-help-command #'embark-prefix-help-command)) (use-package embark-consult) (use-package wgrep)
Web development.
The major mode `typescript-ts-mode` comes with Emacs 29.1 and is what I will use for both JavaScript and TypeScript source files. React is also supported.
New entries are added at the beginning of the list and so will take precedence over any default entries from Emacs.
(dolist (pair '(("\\.js\\'" . typescript-ts-mode) ("\\.ts\\'" . typescript-ts-mode) ("\\.jsx\\'" . tsx-ts-mode) ("\\.tsx\\'" . tsx-ts-mode))) (add-to-list 'auto-mode-alist pair))
This might be occasionally useful:
(use-package add-node-modules-path :hook ((typescript-ts-mode . add-node-modules-path)))
Some projects insist on using Prettier and even go out of their way to integrate it with Git hooks.
I need to support those projects as otherwise I will have a really tough time.
(use-package prettier-js :hook ((typescript-ts-mode . prettier-js-mode) (tsx-ts-mode . prettier-js-mode)))
Things I need when I do Clojure(Script) development:
(use-package cider) (use-package rainbow-delimiters) (use-package paredit) (use-package clojure-ts-mode :hook ((clojure-ts-mode . rainbow-delimiters-mode) (clojure-ts-mode . paredit-mode) (clojure-ts-mode . cider-mode)))
Support for the Janet programming language:
You need to install Janet first:
brew install janet
(use-package janet-mode :mode (("\\.janet\\'" . janet-mode)) :hook ((janet-mode . paredit-mode) (janet-mode . rainbow-delimiters-mode)))
Check this paredit guide out!
The restclient package is a nice alternative to Postman
(use-package restclient)I use this package to execute restclient source blocks in org-mode.
Note: you can add a jq filter via a source header e.g. ==:jq .==
(use-package ob-restclient :config (org-babel-do-load-languages 'org-babel-load-languages '((restclient . t))))
This package also provides org-babel support for jq
(use-package jq-mode :config (org-babel-do-load-languages 'org-babel-load-languages '((jq . t))))
My Emacs configuration file will be put in a standard location:
$(HOME)/.emacs.d/init.el: files/init.el mkdir -p $(@D) cp -f $^ $@
See https://emacsredux.com/blog/2024/03/11/tracking-world-time-with-emacs/
(setq world-clock-list '(("Europe/London" "London") ("Europe/Brussels" "Brussels") ("Europe/Kiev" "Kiev") ("Asia/Seoul" "Seoul")))