- Emacs
- Packaging
- OS
- Org Configuration
- Look and Feel
- upcase-region
- Font size modifications
- Themes
- Highlight TODO
- Highlight Lines
- Line numbers
- Parens
- Tabs
- Title bar
- Bell
- Auto revert
- winner mode
- ansi colors setup
- Selection behaviour
- diminish
- Prettify symbols
- End of line spaces
- spaceline
- flx
- which-key
- which-key posframe
- smooth-scrolling
- disable-mouse
- Splitting of buffers
- Yes or No
- page-break-lines
- Dashboard
- Tools
- async
- Trash files
- saveplace
- monky
- ag
- magit
- command-log-mode
- Project handling
- dired-sidebar
- html
- ace-window
- all-the-icons
- shut-up
- Nov
- Vertico
- Vertico PosFrame
- Save history
- Marginalia
- Orderless
- Consult
- Consult ag
- Embark
- Embark consult
- Insert lines
- Backup directory/files
- flyspell
- Structurizr
- Plantuml
- elfeed
- vterm
- Pomm
- Replace
- Languages
My emacs configuration file. This README.org file gets “tangled” (converted) to a file called README.el, extracting the code snippets to create the final file that is loaded by init.el
This setups the basic packaging system, with the packages repositories and some additional tooling.
(require 'package)
(require 'bind-key)
(setq package-archives
(quote
(("gnu" . "https://elpa.gnu.org/packages/")
("nongnu" . "https://elpa.nongnu.org/nongnu/")
("melpa-stable" . "https://stable.melpa.org/packages/")
("melpa" . "https://melpa.org/packages/"))))
(package-initialize)
This refreshes the packages unless we have them already
(unless package-archive-contents
(package-refresh-contents))
;; By default we ensure everything
(custom-set-variables '(use-package-always-ensure t))
;; By default we defer everything
(custom-set-variables '(use-package-always-defer t))
;; t when we need to debug
(custom-set-variables '(use-package-verbose nil))
;; If the .el version is newer, compile even with .elc present
;; This is mostly to deal with no-packaged versions ... i believe
(custom-set-variables '(load-prefer-newer t))
(use-package auto-compile
:defer nil
:config (auto-compile-on-load-mode))
(use-package quelpa
:defer nil
:init
(setq quelpa-update-melpa-p nil)
:config
(quelpa
'(quelpa-use-package
:fetcher git
:url "https://github.com/quelpa/quelpa-use-package.git"))
(require 'quelpa-use-package))
(require 'quelpa)
(quelpa-use-package-activate-advice)
Configuration that depends on the Operative system
We use zsh when possible
(if (memq window-system '(mac ns))
(setenv "SHELL" "/bin/zsh"))
We check if we are in a nix system. daemonp will only happen in nix system (I think) This is to get the path variable read from the shell environment.
(if (or (memq window-system '(mac ns x))
(daemonp))
(use-package exec-path-from-shell
:defer nil
:config
(setq exec-path-from-shell-variables '("PATH"
"ZSH"
"PYENV_ROOT"
"VIRTUALENVWRAPPER_PYTHON"
"PYENV_VIRTUALENVWRAPPER_PREFER_PYVENV"
"WORKON_HOME"
"PROJECT_HOME"
"ANDROID_HOME"
"JAVA_HOME"
"SDKMAN_DIR"
"GOPATH"))
(exec-path-from-shell-initialize)))
This file configures the org mode and associated packages
(use-package org
:defer 2
:config
(setq org-startup-truncated nil)
(setq org-directory "~/org")
(setq org-agenda-files '("~/org/agendas/"))
(require 'ox-md nil t)
;; (org-startup-indented t)
;; (org-special-ctrl-a/e t)
;; (org-special-ctrl-k t)
)
This allows for a file that we want to tangle (convert into code), to have it done on save. It does require to add the `#+auto_tangle: t` at the top of the org file
(use-package org-auto-tangle
:defer t
:hook (org-mode . org-auto-tangle-mode))
This package improves the look of org-mode on Emacs. Be aware that some fonts don’t have all the necessary glyphs
(use-package org-modern
:ensure t)
(with-eval-after-load 'org (global-org-modern-mode))
Useful for org present
(use-package visual-fill-column
:config
(setq visual-fill-column-width 110
visual-fill-column-center-text t))
Setting up babel for running code in org mode
(use-package ob-go
:ensure t)
(org-babel-do-load-languages
'org-babel-load-languages
'((emacs-lisp . t)
(clojure . t)
(shell . t)
(plantuml . t)
(go . t)))
(setq org-src-preserve-indentation nil
org-src-tab-acts-natively t
org-edit-src-content-indentation 0
org-src-fontify-natively t
org-confirm-babel-evaluate nil)
Creates automatically a table of contents for you
(use-package toc-org
:defer t
:hook (org-mode . toc-org-mode))
Allows for the download of images into org buffers
(use-package org-download
:after org)
(use-package org-ref
:after org)
This is a presentation tool for org mode
Here is additional setup for when the presentation starts.
We remove things like line numbers, and highlighting of lines
(defun jgg/org-present-start ()
(org-present-big)
(org-display-inline-images)
(display-line-numbers-mode -1)
(global-hl-line-mode -1)
(org-present-read-only)
;; we center the document
(visual-fill-column-mode 1)
;; just in case, wrap
(visual-line-mode 1)
;; extra line at the top
(setq header-line-format " "))
This is the setup for when the presentation ends. Basically revert what has been done in the setup
(defun jgg/org-present-end ()
(org-present-small)
(org-remove-inline-images)
(display-line-numbers-mode 1)
(global-hl-line-mode 1)
(org-present-read-write)
;; we stop centering the document
(visual-fill-column-mode 0)
(visual-line-mode 0)
(setq header-line-format nil))
(defun jgg/org-present-slide (buffer-name heading)
;; Show only top-level headlines
(org-overview)
;; Unfold the current entry
(org-show-entry)
;; Show only direct subheadings of the slide but don't expand them
(org-show-children))
(use-package org-present
:after org
:bind (("C-c o" . org-present))
:hook
(org-present-mode . jgg/org-present-start)
(org-present-mode-quit . jgg/org-present-end)
(org-after-navigate-function . jgg/org-present-slide))
First, we acknowledge we are in version 2 of org roam. So it doesn’t show a warning
(setq org-roam-v2-ack t)
This is the main setup of org roam
(use-package org-roam
:after org
:init
(setq org-roam-v2-ack t)
:custom
(org-roam-directory (file-truename "~/org/slip-box"))
(org-roam-dailies-directory "journal/")
(org-roam-complete-everywhere t)
(org-roam-db-autosync-mode)
(org-roam-capture-templates
'(("d" "default" plain "%?"
:if-new (file+head "%<%Y%m%d%H%M%S>-${slug}.org"
"#+title: ${title}\n#+date: %<%Y-%m-%d>\n")
:unnarrowed t)
("l" "literary notes" plain
"\n* Source\n\nAuthor: %^{Author}\nTitle: $^{Title}\nYear: %^{Year}\n\n* Idea: %?"
:if-new (file+head "%<%Y%m%d%H%M%S>-${slug}.org"
"#+title: ${title}\n#+date: %<%Y-%m-%d>\n#+filetags: LiteraryNote\n")
:unnarrowed t)))
(org-roam-dailies-capture-templates
'(("d" "default" plain
"\n* %<%H:%M>\n %?\n"
:if-new (file+head "%<%Y-%m-%d>.org"
"#+title: %<%Y-%m-%d>\n\n")
:unnarrowed t)
("m" "meeting" plain
"\n* %<%H:%M>\n Reason: %^{Reason}\n Participants: %^{Participants}\n Decisions: %?\n Improvements:\n"
:if-new (file+head "%<%Y-%m-%d>.org"
"#+title: %<%Y-%m-%d>\n\n")
:unnarrowed t)
("l" "literary entry" plain
"\n* %<%H:%M>\n Author: %^{Author}\n Title: %^{Title}\n Year: %^{Year}\n Page Reference:%^{Page Reference}\n\n %?\n"
:if-new (file+head "%<%Y-%m-%d>.org"
"#+title: %<%Y-%m-%d>\n\n")
:unnarrowed t)))
:bind (("C-c z l" . org-roam-buffer-toggle)
("C-c z f" . org-roam-node-find)
("C-c z i" . org-roam-node-insert)
("C-c z r" . org-roam-node-random)
:map org-mode-map
(("C-M-i" . completion-at-point)
("C-c z t" . org-roam-tag-add)
("C-c z a" . org-roam-alias-add)
("C-c z I" . org-roam-node-insert-immediate))
:map org-roam-dailies-map
("Y" . org-roam-dailies-capture-yesterday)
("T" . org-roam-dailies-capture-tomorrow))
:bind-keymap
("C-c z d" . org-roam-dailies-map)
:config
(require 'org-roam-dailies)
(org-roam-setup))
;; Immediate creation of a node without jumping to it
(defun org-roam-node-insert-immediate (arg &rest args)
(interactive "P")
(let ((args (cons arg args))
(org-roam-capture-templates (list (append (car org-roam-capture-templates)
'(:immediate-finish t)))))
(apply #'org-roam-node-insert args)))
This allows you to see a graph on the browser of the org roam nodes
(use-package org-roam-ui)
Let’s get it out for now
(put 'upcase-region 'disabled nil)
;; font size utilities to handle different screens and dpi
(defun set-size-font (size)
(set-face-attribute 'default nil :font (concat "Iosevka Curly Extended-" (number-to-string size))))
(defun set-standard-font ()
(set-size-font 12))
(defun set-sharing-font ()
(set-size-font 16))
(defun switch-font (universal)
"Switches the font between my normal one and the one used to share screen"
(interactive "P")
(cond ((equal universal nil) (set-standard-font))
((equal universal '(4)) (set-sharing-font))
(t (set-size-font universal))))
(set-standard-font)
;; This is the theme we are using
(use-package solarized-theme
:defer nil)
(load-theme 'solarized-dark t)
(defvar current-dark t)
(defun toggle-theme ()
"Change the theme used on Emacs between a dark and a light themes."
(interactive)
(if current-dark
(load-theme 'solarized-light t)
(load-theme 'solarized-dark t))
(setq current-dark (not current-dark)))
;; Doesn't work under Cider. Need to investigate.
(global-set-key (kbd "C-c C-.") 'toggle-theme)
Solaire makes clear which buffers are not related to a file
(use-package solaire-mode
:ensure t
:hook (after-init . solaire-global-mode))
This package dims non-current buffers REVIEW is there a mismatch with solaire?
(use-package dimmer
:defer 2
:config
(dimmer-configure-which-key)
(dimmer-mode t))
Highlight certain words in documents and colorize them
(use-package hl-todo
:hook ((org-mode . hl-todo-mode)
(prog-mode . hl-todo-mode))
:config
(setq hl-todo-highlight-punctuation ":"
hl-todo-keyword-faces
`(("TODO" warning bold)
("FIXME" error bold)
("HACK" font-lock-constant-face bold)
("REVIEW" font-lock-keyword-face bold)
("NOTE" success bold)
("DEPRECATED" font-lock-doc-face bold))))
highlight current line
(global-hl-line-mode 1)
(use-package beacon)
(global-display-line-numbers-mode)
We avoid displaying numbers on eshell
(dolist (mode '(eshell-mode-hook))
(add-hook mode (lambda () (display-line-numbers-mode 0))))
by default highlight the matching paren
(show-paren-mode)
Use tabs instead of spaces
(setq-default indent-tabs-mode nil)
(setq default-tab-width 4)
full path in title bar
(setq-default frame-title-format "%b (%f)")
We don’t want a bell
(setq ring-bell-function 'ignore)
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 t)
(global-set-key [remap comment-dwim] #'comment-line)
This allows you to go to previous windows configuration.
(winner-mode 1)
(setq ansi-color-faces-vector
[default default default italic underline success warning error])
Now selecting a region behaves as in most applications you overwrite the region
(delete-selection-mode 1)
This package allows to remove modes from the modeline. Needs to be added as a keyword on use-package setup for a mode.
(use-package diminish
:defer nil)
We use the lambda character λ as a ligature.
(defun my-pretty-lambda (lambda-string)
"Make some word or string show as pretty Unicode symbols. LAMBDA-STRING is the way that the language declares lambda functions."
(setq prettify-symbols-alist
'((lambda-string . 955))))
(defun my-pretty-lambda-elixir ()
"Make some word or string show as pretty Unicode symbols."
(setq prettify-symbols-alist
'(("fn" . 955))))
(defun my-pretty-lambda-clojure ()
"Make some word or string show as pretty Unicode symbols."
(setq prettify-symbols-alist
'(("fn" . 955))))
(global-prettify-symbols-mode 1)
The end of a sentence is a single space. The double space is an old convention
(setq sentence-end-double-space nil)
This is the info line at the bottom of a buffer.
(use-package spaceline
:defer nil
:config
(spaceline-emacs-theme))
Fuzzy search TODO is it useful now with ivy at all?
(use-package flx
:defer 2)
This will show options for a prefix chord in the minibuffer
(use-package which-key
:defer nil
:diminish
:config
(which-key-mode))
This allows which-key to use posframe
(use-package which-key-posframe
:defer nil
:config
(which-key-posframe-mode))
Line by line, instead of half-screen at a time.
(use-package smooth-scrolling
:defer 2
:config
(smooth-scrolling-mode 1)
(setq smooth-scroll-margin 5))
Maybe one day we change this. It disables the mouse in emacs. Useful to force the use of the keyboard
(use-package disable-mouse
:defer 2
:diminish disable-mouse-global-mode
:config
(global-disable-mouse-mode))
Favour vertical split over horizontal split
(setq split-height-threshold nil)
(setq split-width-threshold 120)
(defun shell-horizontal ()
"This function is to display the shell on a horizontal split, whcih is usually more adequate."
(interactive)
(let ((split-width-threshold nil)
(split-height-threshold 0))
(progn
(shell)
(setq current (selected-window))
(setq window (get-buffer-window "*shell*"))
(select-window window)
(setq height (window-height window))
(shrink-window (- height 10))
(select-window current))))
All questions are y or n, for consistency
(fset 'yes-or-no-p 'y-or-n-p)
This converts form feed (^L) into horizontal lines
(use-package page-break-lines
:defer nil)
This dashboard appears whenever we open emacs.
(use-package dashboard
:ensure t
:defer nil
:hook
((dashboard-mode . page-break-lines-mode))
:config
(dashboard-setup-startup-hook)
(setq dashboard-banner-logo-title "May the Force be with you")
(setq dashboard-startup-banner 'logo)
(setq dashboard-center-content t)
(setq dashboard-icon-type 'all-the-icons)
(setq dashboard-projects-backend 'projectile)
(setq dashboard-projects-switch-function 'projectile-persp-switch-project)
(setq dashboard-items '((recents . 5)
(bookmarks . 5)
(projects . 5)
(agenda . 5))))
Allows for the use of async code within emacs
(use-package async)
We want to limit the amount and location of files created by emacs.
(setq no-littering-etc-directory
(expand-file-name "config/" user-emacs-directory))
(setq no-littering-var-directory
(expand-file-name "data/" user-emacs-directory))
(use-package no-littering
:defer nil
:config
(setq auto-save-file-name-transforms
`((".*" ,(no-littering-expand-var-file-name "auto-save/") t))))
Automatically save the last place we were on files when closing
(use-package saveplace
:defer nil
:config
(save-place-mode))
Like magit but for Mercurial
(use-package monky
:bind (("C-x M-g" . monky-status)))
(defun nothing())
Using ag, the silver searcher, from inside emacs
(use-package ag
:bind (("C-c a a" . ag)
("C-c a f" . ag-files)
("C-c a d" . ag-dired)
("C-c a r" . ag-regex)
("C-c a p" . ag-project))
:config
(setq ag-reuse-buffers 't)
(setq ag-highlight-search 't))
Porcelain for git
(use-package magit
:bind (("C-x g" . magit-status)))
This will show on a tab on the side the keybindings used TODO Doesn’t seem to work and hasn’t been updated in years
(use-package command-log-mode
:custom
(command-log-mode-key-binding-open-log "C-c C-o"))
Projectile handles project, perspective handles set of buffers. Together make it so you can have separate set of buffers for each project. And each project can work independently of each other
(use-package projectile
:diminish
:bind-keymap (("C-c p" . projectile-command-map))
:config
(projectile-mode +1)
(setq projectile-project-search-path '("~/code/"
"~/code/personal/"
"~/code/twoormore"
"~/code/externals/")))
(use-package perspective
:bind (("C-c M-p x" . persp-switch-last)
("C-x b" . persp-switch-to-buffer*)
("C-x k" . persp-kill-buffer*))
:init (persp-mode)
:custom
(persp-mode-prefix-key (kbd "C-c M-p")))
(use-package persp-projectile
:bind ("C-c M-p P" . projectile-persp-switch-project))
Directory tree browsing that uses dired
(use-package dired-sidebar
:commands (dired-sidebar-toggle-sidebar)
:bind (([f8] . dired-sidebar-toggle-sidebar)))
Adding some keybindings for the hmtl mode map
(add-hook 'mhtml-mode-hook (lambda ()
(define-key html-mode-map (kbd "M-o") nil)
(define-key html-mode-map (kbd "C-c C-p") 'facemenu-keymap)
(define-key html-mode-map (kbd "M-o") 'ace-window)))
quickly move between windows using M-o number
(use-package ace-window
:bind (("M-o" . ace-window)))
Lots of icons to work with emacs
(use-package all-the-icons
:defer 2)
(use-package all-the-icons-dired
:after (dired-sidebar all-the-icons)
:hook
(dired-mode-hook . all-the-icons-dired-mode))
;; (use-package all-the-icons-ivy
;; :hook (after-init-hook . all-the-icons-ivy-setup))
(use-package spaceline-all-the-icons
:after spaceline
:config (spaceline-all-the-icons-theme))
Reduces the amount of messages being throw my emacs and some packages
(use-package shut-up
:defer 2)
(use-package undo-tree
:defer 2)
(use-package goto-chg
:defer 2)
(use-package multiple-cursors
:defer 2)
This package allows to read epub files from inside Emacs
(use-package nov
:mode ("\\.epub\\'" . nov-mode)
:config
(setq nov-text-width 80))
Vertico shows the completion in vertical mode, rather than grid format It also updates the buffer with the possible completions as you type
Is currently pinned to melpa stable, as there was some issues with the 20241105 version
(use-package vertico
:defer nil
:pin melpa-stable
:config
(setq vertico-cycle t)
(setq vertico-resize nil)
(vertico-mode 1))
Having vertico use posframe. Instead of the minibuffer it uses posframe to show the completions where you are located
(use-package vertico-posframe
:defer nil
:config
(vertico-posframe-mode 1))
This saves history of the minibuffer. Vertico uses it to put recently selected options at the top
(savehist-mode 1)
This package adds annotations to completion candidates in the minibuffer. The information show is dependant on the candidate
(use-package marginalia
:defer nil
:config
(marginalia-mode 1))
This package adds an out-of-order algorithm for searching for completion candidates.
(use-package orderless
:defer nil
:config
(setq completion-styles '(orderless basic)))
It provides enhanced versions of some commands. It has a preview facility
(use-package consult
:defer nil
:bind (;; A recursive grep
("M-s M-g" . consult-grep)
;; Search for files names recursively
("M-s M-f" . consult-find)
;; Search through the outline (headings) of the file
("M-s M-o" . consult-outline)
;; Search the current buffer
("M-s M-l" . consult-line)
;; Switch to another buffer, or bookmarked file, or recently
;; opened file.
("M-s M-b" . consult-buffer)))
Putting together consult and ag
(use-package consult-ag
:defer nil)
Equivalent to a right-click contextual menu.
(use-package embark
:defer nil
:bind (("C-." . embark-act)
:map minibuffer-local-map
("C-c C-c" . embark-collect)
("C-c C-e" . embark-export)))
Ties together embark and consult
(use-package embark-consult
:defer nil)
This
(defun insert-line-below (universal)
"Insert an empty line below the current line.
The behaviour change if you pass the default UNIVERSAL argument. Without it, a new line below the current one will be created, but the point will not change its location. With the default UNIVERSAL argument, the point will change to the beginning of the new line created."
(interactive "P")
(if (equal universal '(4))
(progn
(end-of-line)
(open-line 1)
(forward-line))
(save-excursion
(end-of-line)
(open-line 1))))
(defun insert-line-above (universal)
"Insert an empty line above the current line.
The behaviour change if you pass the default UNIVERSAL argument. Without it, a new line above the current one will be created, but the point will not change its location. With the default UNIVERSAL argument, the point will change to the beginning of the new line created."
(interactive "P")
(if (equal universal '(4))
(progn
(end-of-line 0)
(open-line 1)
(forward-line))
(save-excursion
(end-of-line 0)
(open-line 1))))
(global-set-key (kbd "C-c C-n") 'insert-line-above)
(global-set-key (kbd "C-c n") 'insert-line-below)
We put all backup files on a single place
(setq backup-directory-alist
`(("." . ,(expand-file-name "backups" user-emacs-directory))))
We move auto-save files out into a specific directory. This is so it doesn’t cause issue with language tooling
(let ((auto-save-dir (locate-user-emacs-file "emacs-save")))
(setq auto-save-file-name-transforms
`((".*" ,(expand-file-name "\\2" auto-save-dir) t)))
(unless (file-exists-p auto-save-dir)
(make-directory auto-save-dir)))
Make sure that tramp uses it as well
(setq tramp-backup-directory-alist backup-directory-alist)
And even if the files are in version control
(setq vc-make-backup-files t)
(use-package pos-tip)
Spell checker. We want it only in text and org modes
(use-package flyspell
:diminish flyspell-mode
:hook
(prog-mode . flyspell-prog-mode)
((text-mode org-mode) . (lambda () (flyspell-mode 1)))
((change-log-mode log-edit-mode org-agenda-mode) . (lambda () (flyspell-mode -1)))
:config
(setq ;;ispell-program-name "/usr/local/bin/aspell"
ispell-local-dictionary "en_GB"
ispell-dictionary "english" ; better for aspell
ispell-extra-args '("--sug-mode=ultra" "--lang=en_GB")
ispell-list-command "--list"
ispell-local-dictionary-alist '(("en_GB" "[[:alpha:]]" "[^[:alpha:]]" "['‘’]"
t ; Many other characters
("-d" "en_GB") nil utf-8))))
(use-package column-enforce-mode
:defer 2)
This is my own mod to deal with the structurizr format. TODO This need to be converted to use ts
(if (file-directory-p "~/code/personal/structurizr-mode")
(progn
(add-to-list 'load-path "~/code/personal/structurizr-mode")
(require 'structurizr-mode)))
Mode to use plantuml withing emacs
(use-package plantuml-mode
:config
(setq plantuml-jar-path "~/bin/plantuml.jar")
(setq plantuml-default-exec-mode 'jar)
(add-to-list 'auto-mode-alist '("\\.puml\\'" . plantuml-mode))
(add-to-list 'auto-mode-alist '("\\.plantuml\\'" . plantuml-mode)))
(use-package esup
;; To use MELPA Stable use ":pin melpa-stable",
;; :pin melpa
)
(use-package elfeed
:commands elfeed
:bind (("C-x w" . elfeed))
:config
(setq elfeed-db-directory "~/Sync/elfeed/db"
elfeed-enclosure-default-dir "~/Sync/elfeed/enclosures/")
(make-directory elfeed-db-directory t))
A shell terminal
(use-package vterm
:ensure t
:bind (("C-q" . vterm-send-next-key)))
Pomodoro library to be used within Emacs
(use-package pomm
:commands (pomm pomm-third-time)
:custom
(alert-default-style 'libnotify)
(pomm-audio-enabled t))
Keybindings for this set of often used calls. Remember that projectile has “C-c p r” for replace in the project
(global-set-key (kbd "C-c M-r s") 'replace-string)
(global-set-key (kbd "C-c M-r r") 'replace-regexp)
Some additional configuration for Eglot
(add-hook 'eglot-managed-mode-hook
(lambda ()
(bind-keys :map eglot-mode-map
("C-c e a" . eglot-code-actions)
("C-c e r" . eglot-rename))))
(dolist (modes
'(("\\.tsx\\'" . tsx-ts-mode)
("\\.js\\'" . typescript-ts-mode)
("\\.mjs\\'" . typescript-ts-mode)
("\\.mts\\'" . typescript-ts-mode)
("\\.cjs\\'" . typescript-ts-mode)
("\\.ts\\'" . typescript-ts-mode)
("\\.jsx\\'" . tsx-ts-mode)
("\\.json\\'" . json-ts-mode)
("\\.Dockerfile\\'" . dockerfile-ts-mode)
("\\.go\\'" . go-ts-mode)
("/go\\.mod\\'" . go-mod-ts-mode)))
(add-to-list 'auto-mode-alist modes))
(setq treesit-language-source-alist
'((bash "https://github.com/tree-sitter/tree-sitter-bash")
(css "https://github.com/tree-sitter/tree-sitter-css")
(c-sharp "https://github.com/tree-sitter/tree-sitter-c-sharp")
(elixir "https://github.com/elixir-lang/tree-sitter-elixir")
(go "https://github.com/tree-sitter/tree-sitter-go" "v0.19.1")
(gomod "https://github.com/camdencheek/tree-sitter-go-mod")
(dockerfile "https://github.com/camdencheek/tree-sitter-dockerfile")
(html "https://github.com/tree-sitter/tree-sitter-html")
(json "https://github.com/tree-sitter/tree-sitter-json")
(make "https://github.com/alemuller/tree-sitter-make")
(markdown "https://github.com/ikatyang/tree-sitter-markdown")
(python "https://github.com/tree-sitter/tree-sitter-python")
(javascript "https://github.com/tree-sitter/tree-sitter-javascript" "v0.20.1" "src")
(tsx "https://github.com/tree-sitter/tree-sitter-typescript" "v0.20.3" "tsx/src")
(typescript "https://github.com/tree-sitter/tree-sitter-typescript" "v0.20.3" "typescript/src")
(toml "https://github.com/tree-sitter/tree-sitter-toml" "v0.5.1")
(yaml "https://github.com/ikatyang/tree-sitter-yaml" "v0.5.0")))
;; (dolist (grammar
;; '((bash ("https://github.com/tree-sitter/tree-sitter-bash"))
;; (css ("https://github.com/tree-sitter/tree-sitter-css"))
;; (c-sharp ("https://github.com/tree-sitter/tree-sitter-c-sharp"))
;; (go ("https://github.com/tree-sitter/tree-sitter-go" "v0.19.1"))
;; (gomod ("https://github.com/camdencheek/tree-sitter-go-mod"))
;; (dockerfile ("https://github.com/camdencheek/tree-sitter-dockerfile"))
;; (html ("https://github.com/tree-sitter/tree-sitter-html"))
;; (json ("https://github.com/tree-sitter/tree-sitter-json"))
;; (make ("https://github.com/alemuller/tree-sitter-make"))
;; (markdown ("https://github.com/ikatyang/tree-sitter-markdown"))
;; (python ("https://github.com/tree-sitter/tree-sitter-python"))
;; (javascript ("https://github.com/tree-sitter/tree-sitter-javascript" "v0.20.1" "src"))
;; (tsx ("https://github.com/tree-sitter/tree-sitter-typescript" "v0.20.1" "src"))
;; (typescript ("https://github.com/tree-sitter/tree-sitter-typescript" "v0.20.3" "typescript/src"))
;; (toml ("https://github.com/tree-sitter/tree-sitter-toml"))
;; (yaml ("https://github.com/ikatyang/tree-sitter-yaml"))))
;; (add-to-list 'treesit-language-source-alist grammar)
;; (unless (treesit-language-available-p (car grammar))
;; (treesit-install-language-grammar (car grammar))))
(dolist (mapping
'((python-mode . python-ts-mode)
(csharp-mode . csharp-ts-mode)
(css-mode . css-ts-mode)
(typescript-mode . typescript-ts-mode)
(js-mode . typescript-ts-mode)
(js2-mode . typescript-ts-mode)
(go-mode . go-ts-mode)
(c-mode . c-ts-mode)
(c++-mode . c++-ts-mode)
(c-or-c++-mode . c-or-c++-ts-mode)
(bash-mode . bash-ts-mode)
(css-mode . css-ts-mode)
(json-mode . json-ts-mode)
(js-json-mode . json-ts-mode)
(sh-mode . bash-ts-mode)
(sh-base-mode . bash-ts-mode)))
(add-to-list 'major-mode-remap-alist mapping))
(use-package treesit-auto
:custom
(treesit-auto-install 'prompt)
:config
(treesit-auto-add-to-auto-mode-alist 'all)
(global-treesit-auto-mode))
(use-package yasnippet
:pin melpa-stable
:diminish yas-minor-mode
;; :defines tools-map
;; :bind (:map yas-minor-mode-map
;; ("n" . yas-new-snippet)
;; ("s" . yas-insert-snippet)
;; ("v" . yas-visit-snippet-file))
:config
;; (evil-leader/set-key-for-mode 'emacs-lisp-mode "b" 'byte-compile-file)
;; (define-prefix-command 'yas-minor-mode-map)
;; (define-key tools-map (kbd "y") 'yas-minor-mode-map)
(yas-global-mode 1))
(use-package yasnippet-snippets)
(use-package auto-yasnippet
:diminish yas-minor-mode)
(use-package flycheck-pos-tip)
(use-package flycheck
:after (flycheck-pos-tip-mode)
:config
(show-paren-mode 1)
(flycheck-pos-tip-mode)
(setq-default flycheck-disabled-checkers
(append flycheck-disabled-checkers
'(javascript-jshint)))
(flycheck-add-mode 'javascript-eslint 'web-mode)
:hook
((after-init . global-flycheck-mode)))
(use-package eldoc
:diminish
:hook
(prog-mode . turn-on-eldoc-mode)
(cider-repl-mode . turn-on-eldoc-mode)
(emacs-lisp-mode . turn-on-eldoc-mode)
(lisp-interaction-mode . turn-on-eldoc-mode)
(ielm-mode . turn-on-eldoc-mode))
(use-package tagedit)
(use-package editorconfig
:diminish
:config
(editorconfig-mode 1))
It autoindents as soon as you move from a line
(use-package aggressive-indent
:hook
((emacs-lisp-mode . aggressive-indent-mode)))
Basic setup for company
(use-package company
:defer nil
:diminish
:bind (("C-S-i" . company-complete)
;; :map company-mode-map
;; ("<tab>". tab-indent-or-complete)
;; ("TAB". tab-indent-or-complete)
:map company-active-map
("C-n". company-select-next)
("C-p". company-select-previous)
("M-<". company-select-first)
("M->". company-select-last))
:hook
((after-init . global-company-mode)))
(use-package company-quickhelp
:config
(company-quickhelp-mode 1))
This is a company front-end with icons
(use-package company-box
:hook (company-mode . company-box-mode))
;; LSP setup
(setq lsp-keymap-prefix "C-c l")
(use-package lsp-mode
:defines lsp-highlight-symbol-at-point
:commands (lsp lsp-deferred)
:hook (;; (csharp-mode . lsp)
(clojure-mode . lsp)
(clojurescript-mode . lsp)
(clojurec-mode . lsp)
(elixir-ts-mode . lsp)
((tsx-ts-mode
typescript-ts-mode
js-ts-mode) . lsp-deferred)
(lsp-mode . lsp-enable-which-key-integration))
:init (setq lsp-eldoc-render-all nil
lsp-highlight-symbol-at-point nil
lsp-keymap-prefix "C-c l"
lsp-lens-enable t
lsp-signature-auto-activate nil)
:config
(add-hook 'lsp-mode-hook 'lsp-ui-mode)
(add-to-list 'lsp-disabled-clients 'omnisharp))
This add ui elements to lsp mode
(use-package lsp-ui
:commands lsp-ui-mode
:config
(setq lsp-ui-sideline-update-mode 'point)
:bind (:map lsp-ui-mode-map
([remap xref-find-definitions] . lsp-ui-peek-find-definitions)
([remap xref-find-references] . lsp-ui-peek-find-references))
:init (setq lsp-ui-doc-delay 0.5
lsp-ui-doc-position 'bottom
lsp-ui-doc-max-width 100)
:custom
(lsp-ui-peek-always-show t)
(lsp-ui-sideline-show-hover t)
(lsp-ui-sideline-enable nil)
(lsp-ui-doc-enable nil))
This links lsp with treemacs
(use-package lsp-treemacs
:commands lsp-treemacs-errors-list)
We are adding a debugger mode to lsp
(use-package dap-mode
:after lsp-mode
:bind (:map lsp-mode-map
("<f5>" . dap-debug))
:config
(dap-mode t)
(dap-ui-mode t))
Adding support for tailwind
(use-package lsp-tailwindcss
:init (setq lsp-tailwindcss-add-on-mode t)
:config
(dolist (tw-major-mode
'(css-mode
css-ts-mode
typescript-mode
typescript-ts-mode
tsx-ts-mode
js2-mode
js-ts-mode))
(add-to-list 'lsp-tailwindcss-major-modes tw-major-mode)))
(use-package go-mode)
(add-to-list 'auto-mode-alist '("\\.go\\'" . go-ts-mode))
(add-to-list 'auto-mode-alist '("/go\\.mod\\'" . go-mod-ts-mode))
(add-hook 'go-mode-hook (lambda ()
(setq tab-width 4)
(setq indent-tabs-mode 1)))
(add-hook 'go-ts-mode-hook (lambda ()
(setq tab-width 4)
(setq indent-tabs-mode 1)
(setq go-ts-mode-indent-offset 4)))
(use-package gotest
:diminish
:after go-ts-mode
:bind (:map go-ts-mode-map
("C-c t f" . go-test-current-file)
("C-c t t" . go-test-current-test)
("C-c t p" . go-test-current-project)
("C-c t b" . go-test-current-benchmark)
("C-c t c" . go-test-current-coverage)
("C-c x" . go-run)))
;; (use-package highlight-indentation ;; :defer nil ;; :hook ;; ((prog-mode . highlight-indentation-mode)))
;; (use-package highlight-sexp ;; :quelpa (abc-mode :fetcher github :repo “daimrod/highlight-sexp”) ;; :hook ;; ((clojure-mode lisp-mode emacs-lisp-mode) . highlight-sexp-mode))
(use-package mmm-mode
:config
(setq mmm-global-mode 'maybe)
;; (mmm-add-mode-ext-class 'html-mode "\\.php\\'" 'html-php)
)
(use-package buttercup)
(defun my-web-mode-hook ()
"Hooks for Web mode."
(setq web-mode-markup-indent-offset 4)
(setq web-mode-code-indent-offset 4))
(use-package web-mode
:mode ("\\.phtml\\'" "\\.tpl\\.php\\'" "\\.[agj]sp\\'" "\\.as[cp]x\\'" "\\.erb\\'" "\\.mustache\\'" "\\.djhtml\\'")
:hook
((web-mode . my-web-mode-hook)))
(use-package json-mode)
(setq major-mode-remap-alist
'((python-mode . python-ts-mode)))
This package allows to get the right environment. python-base-mode-hook works for python-mode and python-ts-mode. The -10 tells emacs to load it as soon as possible TODO can :hook do that -10?
(use-package pet
:defer nil
:config
(add-hook 'python-base-mode-hook 'pet-mode -10))
(use-package python
:hook ((python-ts-mode . eglot-ensure)))
(use-package poetry)
(use-package python-docstring)
The apheleia package formats python (black), js (prettier) and go (gofmt) by default.
We have added some configuration for prettier, so it uses the file name to infer the parser to use (to distinguish between js/ts/css)
(use-package apheleia
:diminish
:defines
apheleia-formatters
apheleia-mode-alist
:init (apheleia-global-mode +1)
:config
(setf (alist-get 'prettier-json apheleia-formatters)
'("prettier" "--stdin-filepath" filepath)))
This package allows the use of isort when saving a python file
(use-package python-isort
:hook ((python-base-mode . python-isort-on-save-mode)))
This package allows the running of pytest within emacs TODO this is not loading correctly
(use-package python-pytest
:bind (("C-c t" . python-pytest-dispatch)))
(use-package company-jedi
:hook ((python-base-mode . (lambda () (add-to-list 'company-backends 'company-jedi)))))
;; (use-package pyenv
;; :quelpa (pyenv :fetcher github :repo "aiguofer/pyenv.el"))
(use-package pyvenv
:init
(setenv "WORKON_HOME" "~/.pyenv/versions"))
(use-package dockerfile-mode
:mode "\\.Dockerfile\\'")
(use-package yaml-mode)
(use-package terraform-mode
:hook
((terraform-mode . terraform-format-on-save-mode)))
(use-package company-terraform
:config
(company-terraform-init))
(use-package elixir-ts-mode
:ensure t)
(use-package exunit
:hook
((elixir-mode . exunit-mode)))
(use-package markdown-mode
:diminish
:mode ("\\.text\\'" "\\.markdown\\'" "\\.md\\'")
:config
(custom-set-variables
'(markdown-command "/usr/bin/pandoc")))
(use-package adoc-mode
:diminish)
Kondo working with flycheck
(use-package flycheck-clj-kondo)
Cider is a project tooling for clojure.
In config we remove some of the completions from lsp-mode, to use the cider setup
(use-package cider
:pin melpa-stable
:hook
((cider-repl-mode . paredit-mode)
(cider-mode . paredit-mode)
(cider-mode . eldoc-mode)
(cider-mode . company-mode)
(cider-repl-mode . company-mode))
:bind (("C-c M-a" . cider-insert-last-sexp-in-repl))
:config
(unbind-key "C-c M-p" cider-mode-map)
(setq lsp-enable-completion-at-point nil)
(setq lsp-enable-completion nil)
(setq lsp-enable-indentation nil))
(use-package clojure-mode
:diminish
:pin melpa-stable
:config
(require 'flycheck-clj-kondo)
:hook
((clojure-mode . subword-mode)
(clojure-mode . aggressive-indent-mode)
(clojure-mode . (lambda ()
(setq inferior-lisp-program "lein repl")
(font-lock-add-keywords
nil
'(("(\\(facts?\\)"
(1 font-lock-keyword-face))
("(\\(background?\\)"
(1 font-lock-keyword-face))))
(define-clojure-indent (fact 1))
(define-clojure-indent (facts 1))))
(clojure-mode . cider-mode)
(clojure-mode . my-pretty-lambda-clojure)
(clojure-mode . column-enforce-mode)
(clojure-mode . flycheck-mode)))
This is the basic treesiter mode for clojure
(use-package clojure-ts-mode)
;; (use-package midje-mode
;; :defer t
;; :ensure t
;; :pin melpa-stable
;; :config
;; (add-hook 'clojure-mode-hook 'midje-mode))
;; (use-package clojure-jump-to-file
;; :defer t
;; :ensure t)
(defun clj-clojure-setup ()
"Functionality to be added for Clojure."
(clj-refactor-mode 1)
(yas-minor-mode 1)
(cljr-add-keybindings-with-prefix "C-c C-m"))
(use-package clj-refactor
:diminish
:pin melpa-stable
:hook
(clojure-mode . clj-clojure-setup)
:init
(setq cljr-add-ns-to-blank-clj-files nil))
(use-package clojure-mode-extra-font-locking
:pin melpa-stable)
Kaocha is a test runner for clojure
(use-package kaocha-runner
:init
(bind-keys :prefix-map ar-emacs-kaocha-prefix-map
:prefix "C-c k"
("t" . kaocha-runner-run-test-at-point)
("r" . kaocha-runner-run-tests)
("a" . kaocha-runner-run-all-tests)
("w" . kaocha-runner-show-warnings)
("h" . kaocha-runner-hide-windows)))
For mermaid you need to have downloaded the mermaid cli tool using `npm install -g @mermaid-js/mermaid-cli`
(use-package mermaid-mode
:mode ("\\.mmd\\'")
;; Uncomment when testing improvements
;; :load-path "/home/akira/code/external/mermaid-mode"
:config
(setq mermaid-mmdc-location "/home/akira/node_modules/.bin/mmdc"))
(use-package slime
:config
(setq inferior-lisp-program "/usr/bin/sbcl")
(setq slime-contribs '(slime-fancy))
(slime-setup '(slime-fancy slime-company))
(setq slime-lisp-implementations
'((sbcl ("/usr/bin/sbcl") :coding-system utf-8-unix)))
:config
(unbind-key "C-c M-p" slime-mode-indirect-map)
:bind (:map slime-mode-indirect-map
("C-c P" . slime-repl-set-package)))
(use-package slime-company
:config
(setq slime-company-major-modes (quote (lisp-mode slime-repl-mode))))
This one has to happen after all modes that use parens are loaded
(use-package paredit
:diminish
:init
(autoload 'enable-paredit-mode "paredit" "Turn on pseudo-structural editing of Lisp code." t)
:hook
((emacs-lisp-mode . enable-paredit-mode)
(eval-expression-minibuffer-setup . enable-paredit-mode)
(ielm-mode . enable-paredit-mode)
(lisp-mode . enable-paredit-mode)
(lisp-interaction-mode . enable-paredit-mode)
(scheme-mode . enable-paredit-mode)
(clojure-mode . enable-paredit-mode)
(lfe-mode . enable-paredit-mode)))
(use-package rainbow-delimiters
:diminish
:hook
((prog-mode . rainbow-delimiters-mode)))
(use-package tex
:ensure auctex
:config
(setq TeX-auto-save t)
(setq TeX-parse-self t)
:hook
((latex-mode . turn-on-reftex)
(LaTeX-mode . turn-on-reftex)))
(use-package company-auctex)
(use-package latex-preview-pane
:config
(latex-preview-pane-enable))
(use-package geiser-mit)
(use-package geiser-chez)
(use-package lua-mode)
(use-package company-lua)
(use-package luarocks)
(use-package powershell)
(use-package graphviz-dot-mode)
You will need to download opam and Merlin
(use-package tuareg
:mode (("\\.ocamlinit\\'" . tuareg-mode)))
(use-package merlin
:hook ((tuareg-mode . merlin-mode)
(caml-mode . merlin-mode))
:config
(setq merlin-command 'opam)
(setq merlin-error-after-save nil))
(use-package flycheck-ocaml
:ensure t
:config
(flycheck-ocaml-setup))
(use-package dune)
(use-package merlin-company)
(use-package merlin-eldoc
:hook ((tuareg-mode caml-mode) . merlin-eldoc-setup))
(use-package ocp-indent
:hook ((tuareg-mode . (lambda () (setq ocp-setup-indent t)))
(caml-mode . (lambda () (setq ocp-indent-caml-mode-setup t)))))
(use-package opam-switch-mode
:hook
((tuareg.mode . opam-switch-mode)))
(use-package glsl-mode)