aboutsummaryrefslogtreecommitdiffstats
path: root/emacs
diff options
context:
space:
mode:
authorGravatar Tom Willemse2026-06-10 16:52:56 -0700
committerGravatar Tom Willemse2026-06-10 16:55:34 -0700
commitcb73a736736c8091697f93e62c31502bed9ccf80 (patch)
treea9b9c381f59517e9d747c37c1ccc416644b37a24 /emacs
parenta61c4330a203ff71b0418e6638925754b4d16d54 (diff)
downloadnew-dotfiles-cb73a736736c8091697f93e62c31502bed9ccf80.tar.gz
new-dotfiles-cb73a736736c8091697f93e62c31502bed9ccf80.zip
Update Emacs config
This is mainly used by my work machine at the moment, but that should change soon.
Diffstat (limited to 'emacs')
-rw-r--r--emacs/.config/emacs/.gitignore1
-rw-r--r--emacs/.config/emacs/init.org92
-rw-r--r--emacs/.emacs.d/init.org95
-rw-r--r--emacs/.emacs.d/oni-compilation.el53
-rw-r--r--emacs/.emacs.d/oni-corfu.el17
-rw-r--r--emacs/.emacs.d/oni-dashboard.el45
-rw-r--r--emacs/.emacs.d/oni-dumb-jump.el15
-rw-r--r--emacs/.emacs.d/oni-flycheck.el27
-rw-r--r--emacs/.emacs.d/oni-gui.el92
-rw-r--r--emacs/.emacs.d/oni-hl-todo.el8
-rw-r--r--emacs/.emacs.d/oni-php.el330
-rw-r--r--emacs/.emacs.d/oni-prescient.el11
-rw-r--r--emacs/.emacs.d/oni-smartparens.el12
-rw-r--r--emacs/.emacs.d/oni-stillness.el6
-rw-r--r--emacs/.emacs.d/oni-xterm-color.el5
-rw-r--r--emacs/.emacs.d/oni-yasnippet.el34
16 files changed, 705 insertions, 138 deletions
diff --git a/emacs/.config/emacs/.gitignore b/emacs/.config/emacs/.gitignore
deleted file mode 100644
index 509e059..0000000
--- a/emacs/.config/emacs/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-init.el \ No newline at end of file
diff --git a/emacs/.config/emacs/init.org b/emacs/.config/emacs/init.org
deleted file mode 100644
index 20ddcbb..0000000
--- a/emacs/.config/emacs/init.org
+++ /dev/null
@@ -1,92 +0,0 @@
-#+TITLE: Emacs Configuration
-
-First, lexical binding must be enabled. This is better for performance, but also makes variable binding behave more as expected, and allows the creation of closures.
-
-#+begin_src emacs-lisp :padline no
- ;; -*- lexical-binding: t; -*-
-#+end_src
-
-Store all auto-save files in =$XDG_DATA_HOME/emacs/auto-save-list= to prevent them from clogging up =$XDG_CONFIG_HOME/emacs/=. The XDG specification says that if =XDG_DATA_HOME= hasn't been specified a default of =~/.local/share= should be used.
-
-#+begin_src emacs-lisp
- (add-to-list
- 'auto-save-file-name-transforms
- `(,(rx (zero-or-more any))
- ,(concat (or (getenv "XDG_DATA_HOME")
- (expand-file-name "~/.local/share"))
- "/emacs/auto-save-list")
- t)
- t)
-#+end_src
-
-Use =hunspell= instead of the default =aspell=. Hunspell is used by LibreOffice and other programs too. So far (at least through Emacs) it doesn't recognize the =’= as an apostrophe and I have to use ='= in org-mode if I want spell checking to accept word contractions in English.
-
-#+begin_src emacs-lisp
- (eval-when-compile (require 'ispell))
- (with-eval-after-load 'ispell
- (setq ispell-program-name "hunspell"
- ispell-really-hunspell t))
-#+end_src
-
-Electric quote uses pretty quoting characters =’=, =‘=, =”=, and =“= instead of ='= and ="=, but when I'm in the middle of a word I don't want to use =’= (right single quotation mark), but ='= (apostrophe), which provides better results with spellchecking. So here is a function that checks whether the character before the previous is a word character.
-
-#+begin_src emacs-lisp
- (defun oni-in-word-p ()
- "Check whether the character just typed was part of a word."
- (save-excursion
- (backward-char)
- (looking-back (rx word) (1- (point)))))
-#+end_src
-
-Now that I can check whether or not I'm typing a word, I can tell =electric-quote-mode= not to use =’= in that case.
-
-#+begin_src emacs-lisp
- (with-eval-after-load 'electric
- (add-hook 'electric-quote-inhibit-functions #'oni-in-word-p))
-#+end_src
-
-So now that that's settled, I should be writing ='= in words like “shouldn't'' and =’= otherwise. And spellchecking should work just fine.
-
-Add MELPA to package archives, this lets me install more packages.
-
-#+begin_src emacs-lisp
- (use-package package
- :config
- (add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t))
-#+end_src
-
-* Docker
-
-I need to use Docker for some projects at work.
-
-#+begin_src emacs-lisp
- (use-package dockerfile-mode
- :ensure t)
-#+end_src
-
-* PHP
-
-I currently develop in PHP.
-
-#+begin_src emacs-lisp
- (use-package php-mode
- :ensure t)
-#+end_src
-
-* Magit
-
-GIT.
-
-#+begin_src emacs-lisp
- (use-package magit
- :ensure t)
-#+end_src
-
-* Lua mode
-
-Lua is mainly used by wezterm right now.
-
-#+begin_src emacs-lisp
- (use-package lua-mode
- :ensure t)
-#+end_src
diff --git a/emacs/.emacs.d/init.org b/emacs/.emacs.d/init.org
index 676a671..8972f65 100644
--- a/emacs/.emacs.d/init.org
+++ b/emacs/.emacs.d/init.org
@@ -66,18 +66,38 @@ So now that that's settled, I should be writing ='= in words like “shouldn't''
Add MELPA to package archives, this lets me install more packages.
#+begin_src emacs-lisp
- (use-package package
- :config
- (add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t))
+ (eval-and-compile
+ (use-package package
+ :config
+ (add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t)))
+#+end_src
+
+Make use-package default to ensuring everything. This way each =use-package= doesn't need to have its own ~:ensure t~ and when I use Guix to install these modules they don't try to download everything from everywhere else.
+
+#+begin_src emacs-lisp
+ (eval-and-compile
+ (require 'use-package-ensure)
+ (setq use-package-always-ensure t))
+#+end_src
+
+* exec-path-from-shell
+
+This is necessary to make sure that packages installed through bundle and such are available in Emacs.
+
+#+begin_src emacs-lisp
+ (use-package exec-path-from-shell
+ :init
+ (when (memq window-system '(mac ns x))
+ (exec-path-from-shell-initialize)))
#+end_src
+* Ensure system packages
+
Add the =use-package-ensure-system-package= extension for =use-package=.
#+begin_src emacs-lisp
(use-package use-package-ensure-system-package)
-
- (use-package system-packages
- :ensure t)
+ (use-package system-packages)
#+end_src
* Docker
@@ -85,8 +105,7 @@ Add the =use-package-ensure-system-package= extension for =use-package=.
I need to use Docker for some projects at work.
#+begin_src emacs-lisp
- (use-package dockerfile-mode
- :ensure t)
+ (use-package dockerfile-mode)
#+end_src
* PHP
@@ -95,7 +114,6 @@ I currently develop in PHP.
#+begin_src emacs-lisp
(use-package php-mode
- :ensure t
:ensure-system-package php)
#+end_src
@@ -105,7 +123,6 @@ GIT.
#+begin_src emacs-lisp
(use-package magit
- :ensure t
:hook
(magit-pre-display-buffer-hook . magit-save-window-configuration)
:custom
@@ -126,27 +143,13 @@ Tell magit to apply ANSI colors in the process buffer.
Lua is mainly used by wezterm right now.
#+begin_src emacs-lisp
- (use-package lua-mode
- :ensure t)
-#+end_src
-
-* exec-path-from-shell
-
-This is necessary to make sure that packages installed through bundle and such are available in Emacs.
-
-#+begin_src emacs-lisp
- (use-package exec-path-from-shell
- :ensure t
- :init
- (when (memq window-system '(mac ns x))
- (exec-path-from-shell-initialize)))
+ (use-package lua-mode)
#+end_src
* Markdown
#+begin_src emacs-lisp
- (use-package markdown-mode
- :ensure t)
+ (use-package markdown-mode)
#+end_src
* Org Mode
@@ -197,8 +200,7 @@ This is necessary to make sure that packages installed through bundle and such a
This is used to hide minor mode names.
#+begin_src emacs-lisp
- (use-package diminish
- :ensure t)
+ (use-package diminish)
#+end_src
* GCMH
@@ -207,7 +209,6 @@ This package helps improve the garbage collection settings to match modern compu
#+begin_src emacs-lisp
(use-package gcmh
- :ensure t
:diminish gcmh-mode
:init
(gcmh-mode))
@@ -216,8 +217,7 @@ This package helps improve the garbage collection settings to match modern compu
* Hydra
#+begin_src emacs-lisp
- (use-package hydra
- :ensure t)
+ (use-package hydra)
#+end_src
* Delete Trailing Whitespace
@@ -231,8 +231,7 @@ It bugs me to have whitespace left over.
* Consult
#+begin_src emacs-lisp
- (use-package consult
- :ensure t)
+ (use-package consult)
#+end_src
* Diff-hl
@@ -241,7 +240,6 @@ Highlight diffs in the fringe.
#+begin_src emacs-lisp
(use-package diff-hl
- :ensure t
:init
(global-diff-hl-mode))
#+end_src
@@ -250,24 +248,31 @@ Highlight diffs in the fringe.
#+begin_src emacs-lisp
(use-package vertico
- :ensure t)
+ :init (vertico-mode)
+ :bind (:map vertico-map
+ ("<return>" . vertico-directory-enter)
+ ("<backspace>" . vertico-directory-delete-char)
+ ("M-<backspace>" . vertico-directory-delete-word)))
(use-package vertico-prescient
- :ensure t)
+ :init (vertico-prescient-mode))
+
+ (use-package vertico-posframe
+ :init (vertico-posframe-mode)
+ :config
+ (setq vertico-posframe-poshandler 'posframe-poshandler-frame-bottom-center))
#+end_src
* Marginalia
#+begin_src emacs-lisp
- (use-package marginalia
- :ensure t)
+ (use-package marginalia)
#+end_src
* Ace Window
#+begin_src emacs-lisp
(use-package ace-window
- :ensure t
:bind (("M-o" . ace-window)
("C-x o")))
#+end_src
@@ -566,12 +571,6 @@ Highlight diffs in the fringe.
;; (with-eval-after-load 'tramp (require 'oni-tramp nil t))
;; (with-eval-after-load 'web-mode (require 'oni-web nil t))
- (with-eval-after-load 'yasnippet
- (require 'oni-yasnippet)
- (when (and (package-installed-p 'oni-yasnippet)
- (not yas-global-mode))
- (yas-global-mode)))
-
(eval-when-compile
(require 'calendar))
@@ -816,6 +815,12 @@ Highlight diffs in the fringe.
(setq switch-to-buffer-obey-display-actions t)
#+end_src
+* Rainbow Delimiters
+
+#+begin_src emacs-lisp
+ (use-package rainbow-delimiters)
+#+end_src
+
* Custom
Change the file where =customize= stores its settings.
diff --git a/emacs/.emacs.d/oni-compilation.el b/emacs/.emacs.d/oni-compilation.el
new file mode 100644
index 0000000..54e20f0
--- /dev/null
+++ b/emacs/.emacs.d/oni-compilation.el
@@ -0,0 +1,53 @@
+;; Start of oni-stillness
+
+(use-package compile
+ :config
+ (require 'subr-x)
+ (require 'xterm-color)
+
+ (defun oni-compilation--maybe-dont-show-window (buffer-or-name alist plist)
+ "Don't show BUFFER-OR-NAME unless it absolutely must.
+
+ALIST and PLIST contain extra information about the buffer."
+ (if (alist-get 'allow-no-window alist)
+ buffer-or-name
+ (funcall (plist-get plist :fallback) buffer-or-name alist
+ (plist-put (copy-sequence plist) :custom nil))))
+
+ (defun oni-compilation--maybe-display-compilation-window (buffer status)
+ "Display BUFFER if STATUS is not finished."
+ (unless (string= (string-trim status) "finished")
+ (display-buffer buffer)))
+
+ (defun oni-compilation--compilation-finish-notify-function (buffer status)
+ "Show an alert of the status of the compliation.
+
+BUFFER is the `compilation-mode' buffer and STATUS is the exit
+status of the process."
+ (when (string-match-p (rx "*compilation*" "*Chanced Tests*") (buffer-name buffer))
+ (if (string= (string-trim status) "finished")
+ (alert "Compilation finished succesfully")
+ (alert "Compilation finished with an error"))))
+
+ (defun oni-compilation--filter-xterm-colors (func proc string)
+ "Call FUNC with PROC and STRING filtered through ‘xterm-color-filter’."
+ (funcall func proc (xterm-color-filter string)))
+
+ (setq compilation-scroll-output t)
+ (setq compilation-environment '("TERM=xterm-256color"))
+
+ (add-to-list 'display-buffer-alist
+ '("\\`\\*compilation\\*\\'" display-buffer-in-side-window
+ (side . bottom)
+ (slot . 0)
+ (window-height . 0.33)))
+
+ (add-hook 'compilation-finish-functions
+ #'oni-compilation--maybe-display-compilation-window)
+
+ (add-hook 'compilation-finish-functions
+ #'oni-compilation--compilation-finish-notify-function)
+
+ (advice-add 'compilation-filter :around #'oni-compilation--filter-xterm-colors))
+
+;; End of oni-stillness
diff --git a/emacs/.emacs.d/oni-corfu.el b/emacs/.emacs.d/oni-corfu.el
new file mode 100644
index 0000000..7d6859f
--- /dev/null
+++ b/emacs/.emacs.d/oni-corfu.el
@@ -0,0 +1,17 @@
+;; Start of oni-corfu
+
+(use-package corfu
+ :config
+ (setq corfu-auto t)
+
+ (add-hook 'corfu-mode-hook 'corfu-prescient-mode)
+
+ (add-to-list 'completion-at-point-functions 'cape-abbrev)
+ (add-to-list 'completion-at-point-functions 'cape-dabbrev)
+ (add-to-list 'completion-at-point-functions 'cape-file))
+
+(use-package cape)
+
+(use-package corfu-prescient)
+
+;; End of oni-corfu
diff --git a/emacs/.emacs.d/oni-dashboard.el b/emacs/.emacs.d/oni-dashboard.el
new file mode 100644
index 0000000..c619546
--- /dev/null
+++ b/emacs/.emacs.d/oni-dashboard.el
@@ -0,0 +1,45 @@
+;; Start of oni-dashboard
+
+(use-package dashboard
+ :init
+ (dashboard-setup-startup-hook)
+ (run-with-idle-timer 300 t (lambda () (switch-to-buffer dashboard-buffer-name)))
+ (run-at-time "02:00" 86400 #'dashboard-open)
+ (setq dashboard-navigator-buttons
+ `((("💬";; ,(propertize " " 'display `(image :type svg :file ,(expand-file-name "search.svg" oni-gui-icons-dir) :ascent center :margin (5 . 0)))
+ "Conversations" "Open pull requests"
+ (lambda (&rest _)
+ (browse-url "https://github.com/pulls?q=commenter%3Atomw-punt+review%3Achanges_requested+is%3Aopen"))
+ default "[" "]")
+ ("⛙";; ,(propertize " " 'display `(image :type svg :file ,(expand-file-name "search.svg" oni-gui-icons-dir) :ascent center :margin (5 . 0)))
+ "PRs" "Open pull requests"
+ (lambda (&rest _)
+ (browse-url "https://github.com/pulls?q=is%3Aopen+is%3Apr+org%3Ajuked-social+draft%3Afalse+review%3Anone+-author%3Aapp%2Fdependabot+-base%3Adev+-base%3Amain+-base%3Achanced_dev"))
+ default "[" "]"))
+ (("⛙" ;; ,(propertize " " 'display `(image :type svg :file ,(expand-file-name "search.svg" oni-gui-icons-dir) :ascent center :margin (5 . 0)))
+ "back-end" "Unmerged into back-end"
+ (lambda (&rest _)
+ (browse-url "https://github.com/juked-social/social-api/compare/main...staging"))
+ default "[" "]")
+ ("⛙" ;; ,(propertize " " 'display `(image :type svg :file ,(expand-file-name "search.svg" oni-gui-icons-dir) :ascent center :margin (5 . 0)))
+ "chanced" "Unmerged into chanced front-end"
+ (lambda (&rest _)
+ (browse-url "https://github.com/juked-social/chanced-frontend/compare/main...staging"))
+ default "[" "]")
+ ("⛙" ;; ,(propertize " " 'display `(image :type svg :file ,(expand-file-name "search.svg" oni-gui-icons-dir) :ascent center :margin (5 . 0)))
+ "punt" "Unmerged into punt front-end"
+ (lambda (&rest _)
+ (browse-url "https://github.com/juked-social/punt-frontend/compare/main...staging"))
+ default "[" "]"))))
+ (setq dashboard-set-navigator t)
+ :config
+ (setq dashboard-startup-banner "~/code/personal/dotfiles/oni/home/services/emacs/pop-os-logo.svg")
+ (setq dashboard-set-footer nil)
+ (setq dashboard-projects-show-base t)
+ (setq dashboard-recentf-show-base t)
+
+ (add-hook 'server-after-make-frame-hook #'dashboard-open)
+ ;; (add-hook 'dashboard-mode-hook 'olivetti-mode)
+ (add-hook 'dashboard-after-initialize-hook (lambda () (setq truncate-lines t))))
+
+;; End fo oni-dashboard
diff --git a/emacs/.emacs.d/oni-dumb-jump.el b/emacs/.emacs.d/oni-dumb-jump.el
new file mode 100644
index 0000000..4b67c88
--- /dev/null
+++ b/emacs/.emacs.d/oni-dumb-jump.el
@@ -0,0 +1,15 @@
+;; Start of oni-dumb-jump
+
+(use-package dumb-jump
+ :ensure-system-package ("rg" . ripgrep)
+ :init
+ (add-hook 'xref-backend-functions 'dumb-jump-xref-activate)
+ :config
+ (setq dumb-jump-prefer-searcher 'rg)
+ (setq dumb-jump-find-rules
+ (seq-remove (lambda (rule) (and (string= "php" (map-elt rule :language))
+ (string= "type" (map-elt rule :type))
+ (string-prefix-p "\\buse" (map-elt rule :regex))))
+ dumb-jump-find-rules)))
+
+;; End of oni-dumb-jump
diff --git a/emacs/.emacs.d/oni-flycheck.el b/emacs/.emacs.d/oni-flycheck.el
new file mode 100644
index 0000000..7883cb1
--- /dev/null
+++ b/emacs/.emacs.d/oni-flycheck.el
@@ -0,0 +1,27 @@
+;; Start of oni-flycheck
+
+(use-package flycheck
+ :config
+ (require 'flycheck-posframe)
+
+ (mapc (lambda (c) (delq c flycheck-checkers))
+ '(python-pylint python-pyflakes))
+
+ (setq flycheck-highlighting-mode 'columns)
+
+ (when (not (eql system-type 'windows-nt))
+ (setq flycheck-mode-line-prefix "✓"))
+
+ (setq flycheck-emacs-args
+ (append '("--eval" "(package-initialize)")
+ flycheck-emacs-args))
+
+ (flycheck-posframe-configure-pretty-defaults)
+
+ (add-hook 'flycheck-mode-hook 'flycheck-cask-setup)
+ (add-hook 'flycheck-mode-hook 'flycheck-posframe-mode))
+
+(use-package flycheck-posframe)
+(use-package flycheck-cask)
+
+;; End of oni-flycheck
diff --git a/emacs/.emacs.d/oni-gui.el b/emacs/.emacs.d/oni-gui.el
new file mode 100644
index 0000000..e229fb9
--- /dev/null
+++ b/emacs/.emacs.d/oni-gui.el
@@ -0,0 +1,92 @@
+;; Start of oni-gui
+
+(defun oni-gui-setup-faces (frame)
+ "Setup faces for FRAME."
+ (set-face-attribute 'fixed-pitch frame :font "Fantasque Sans Mono-15")
+ (set-face-attribute 'variable-pitch frame :font "Dosis-16"))
+
+(defun oni-gui-setup-fontsets (frame)
+ "Setup fontsets for FRAME.
+If FRAME is nil, they’re set for the current frame."
+ (let ((font-awesome "Font Awesome 5 Free Solid-12"))
+ (set-fontset-font t #xf026 font-awesome frame)
+ (set-fontset-font t #xf027 font-awesome frame)
+ (set-fontset-font t #xf028 font-awesome frame)
+ (set-fontset-font t #xf240 font-awesome frame)
+ (set-fontset-font t #xf241 font-awesome frame)
+ (set-fontset-font t #xf242 font-awesome frame)
+ (set-fontset-font t #xf243 font-awesome frame)
+ (set-fontset-font t #xf244 font-awesome frame)
+ (set-fontset-font t #xf2c9 font-awesome frame)
+ (set-fontset-font t #xf6a9 font-awesome frame)
+ (set-fontset-font t #xf769 font-awesome frame)
+ (set-fontset-font t #xf76b font-awesome frame))
+ (let ((font-awesome "Font Awesome 5 Free Regular-12"))
+ (set-fontset-font t #xf0c8 font-awesome frame)
+ (set-fontset-font t #xf14a font-awesome frame))
+ (let ((dejavu-sans-mono "DejaVu Sans Mono-12"))
+ (set-fontset-font t #x25c9 dejavu-sans-mono frame)
+ (set-fontset-font t #x25cb dejavu-sans-mono frame)
+ (set-fontset-font t #x2738 dejavu-sans-mono frame)
+ (set-fontset-font t #x273f dejavu-sans-mono frame)
+ (set-fontset-font t #x2713 dejavu-sans-mono frame)))
+
+;; Thanks to the article at
+;; https://andreyorst.gitlab.io/posts/2020-07-21-programming-ligatures-in-emacs/
+(defun oni-gui-setup-ligatures (&optional _)
+ "Define ligatures supported by Fantasque Sans Mono."
+ (let ((ligatures
+ `((?= . ,(regexp-opt '("==" "===" "=/=" "=>" "==>" "=>>" "=<<")))
+ (?! . ,(regexp-opt '("!=" "!==")))
+ (?< . ,(regexp-opt '("<-<" "<<-" "<--" "<-" "<->" "<=<" "<<=" "<=="
+ "<=>" "<~>" "<~~" "<~" "<<<" "<<" "<=" "<>"
+ "<|||" "<||" "<|" "<|>" "<!--")))
+ (?- . ,(regexp-opt '("->" "-->" "->>" "-<" "-<<")))
+ (?> . ,(regexp-opt '(">->" ">=>" ">>=" ">>-" ">-" ">=" ">>" ">>>")))
+ (?~ . ,(regexp-opt '("~~" "~>" "~~>")))
+ (?| . ,(regexp-opt '("|>" "||>" "|||>" "||")))
+ (?: . ,(regexp-opt '("::")))
+ (?& . ,(regexp-opt '("&&")))
+ (?/ . ,(regexp-opt '("//" "/*")))
+ (?* . ,(regexp-opt '("*/" "**/"))))))
+ (dolist (char-regexp ligatures)
+ (set-char-table-range composition-function-table (car char-regexp)
+ `([,(cdr char-regexp) 0 font-shape-gstring])))))
+
+(use-package emacs
+ :ensure-system-package (("/opt/homebrew/Caskroom/font-fantasque-sans-mono" . font-fantasque-sans-mono)
+ ("/opt/homebrew/Caskroom/font-dosis" . font-dosis))
+ :config
+ (setf (map-elt default-frame-alist 'font) "Fantasque Sans Mono-15")
+ (setf (map-elt default-frame-alist 'internal-border-width) 15)
+ (setq-default cursor-type '(bar . 2))
+ (setq-default cursor-in-non-selected-windows 'box)
+ (setq frame-resize-pixelwise t)
+
+ (scroll-bar-mode -1)
+
+ (unless (eq system-type 'windows-nt)
+ (if (daemonp)
+ (progn
+ (add-hook 'after-make-frame-functions #'oni-gui-setup-ligatures)
+ (add-hook 'after-make-frame-functions #'oni-gui-setup-fontsets)
+ (add-hook 'after-make-frame-functions #'oni-gui-setup-faces))
+ (oni-gui-setup-fontsets nil)
+ (oni-gui-setup-faces nil)
+ (oni-gui-setup-ligatures)))
+
+ (global-unset-key (kbd "C-z"))
+ (global-set-key (kbd "C-c c") '("Frequently used commands" . oni-gui-hydra/body))
+
+ (when (fboundp 'pixel-scroll-precision-mode)
+ (pixel-scroll-precision-mode)))
+
+(use-package yoshi-theme
+ :vc (:url "https://git.sr.ht/~ryuslash/yoshi-theme"
+ :rev :newest)
+ :init
+ (load-theme 'yoshi :no-confirm)
+ :config
+ (require 'yoshi-mode-line))
+
+;; End of oni-gui
diff --git a/emacs/.emacs.d/oni-hl-todo.el b/emacs/.emacs.d/oni-hl-todo.el
new file mode 100644
index 0000000..b7ee52f
--- /dev/null
+++ b/emacs/.emacs.d/oni-hl-todo.el
@@ -0,0 +1,8 @@
+;; Start of oni-hl-todo
+
+(use-package hl-todo
+ :init (global-hl-todo-mode))
+
+(use-package consult-todo)
+
+;; End of oni-hl-todo
diff --git a/emacs/.emacs.d/oni-php.el b/emacs/.emacs.d/oni-php.el
new file mode 100644
index 0000000..3d87dca
--- /dev/null
+++ b/emacs/.emacs.d/oni-php.el
@@ -0,0 +1,330 @@
+;; Start of oni-php
+
+(use-package php-mode
+ :config
+ (require 'align)
+ (require 'hydra)
+ (require 'map)
+ (require 'project)
+ (require 'whitespace)
+
+ (defconst oni-php-root
+ (file-name-directory
+ (or load-file-name
+ (buffer-file-name)))
+ "The directory where ‘oni-php’ was loaded from.")
+
+ (defconst oni-php-snippets-dir
+ (expand-file-name "snippets" oni-php-root)
+ "The directory where ‘oni-php’ stores its snippets.")
+
+ (defconst oni-php-scripts-dir
+ (expand-file-name "scripts" oni-php-root)
+ "The directory where ‘oni-php’ stores its scripts.")
+
+ (defun oni-php--set-require-final-newline ()
+ "Set `require-final-newline' to t.
+This is necessary because the PHP mode configuration sets this to
+nil for some reason."
+ (setq require-final-newline t))
+
+ (defun oni-php--whitespace-mode ()
+ "Enable whitespace mode with only tabs showing."
+ (setq-local whitespace-style '(face tabs))
+ (whitespace-mode))
+
+ (defun oni-php--auto-fill-mode ()
+ "Enable ‘auto-fill-mode’ only for comments."
+ (setq-local comment-auto-fill-only-comments t)
+ (auto-fill-mode))
+
+ (defun oni-php-set-rainbow-identifier-faces ()
+ "Set the faces to override for ‘rainbow-identifiers-mode’."
+ (setq-local rainbow-identifiers-faces-to-override
+ '(font-lock-type-face php-property-name php-function-call-traditional
+ php-doc-variable-sigil php-method-call-traditional
+ php-variable-sigil php-variable-name)))
+
+ (defun oni-php-add-use (class)
+ "Try to add a use statement for CLASS under point."
+ (interactive (list (thing-at-point 'symbol)))
+ (let* ((default-directory (project-root (project-current)))
+ (classes (read (shell-command-to-string (concat (expand-file-name "find-php-class" oni-php-scripts-dir) " " class))))
+ (class (cond
+ ((null classes)
+ (user-error "Class ‘%s’ not found" class))
+ ((> (length classes) 1)
+ (completing-read "Use: " classes nil t))
+ (t (car classes)))))
+ (save-excursion
+ (goto-char (point-min))
+
+ (if (search-forward "use " nil t)
+ (forward-paragraph)
+ (search-forward "namespace ")
+ (forward-line)
+ (insert "\n"))
+
+ (unless (re-search-backward (rx "use " (literal class) ";") nil t)
+ (let ((start (point)))
+ (insert "use " class ";\n")
+ (pulse-momentary-highlight-region start (point)))))))
+
+ (defun oni-php--syntax-in-string-p (syntax)
+ "Does SYNTAX indicate point is inside a string?"
+ (nth 3 syntax))
+
+ (defun oni-php--syntax-in-comment-p (syntax)
+ "Does SYNTAX indicate point is inside a comment?"
+ (nth 4 syntax))
+
+ (defun oni-php--in-string-or-comment-p ()
+ "Return whether or not point is within a string or comment."
+ (let ((syntax (syntax-ppss)))
+ (or (oni-php--syntax-in-string-p syntax)
+ (oni-php--syntax-in-comment-p syntax))))
+
+ (defun oni-php-insert-dot-dwim (N)
+ "Insert either a concatenation or access operator depending on context.
+
+Do the insert N times."
+ (interactive "p")
+ (if (or (oni-php--in-string-or-comment-p)
+ (save-excursion
+ (skip-syntax-backward " ")
+ (nth 3 (syntax-ppss (1- (point)))))
+ (save-excursion
+ (skip-syntax-forward " ")
+ (nth 3 (syntax-ppss (1+ (point))))))
+ (self-insert-command N)
+ (let ((op (if (looking-back (rx (or "$" ")") (zero-or-more (any whitespace "\n" alnum "(" ")" "->")))
+ (save-excursion (backward-paragraph) (point)))
+ "->"
+ "::")))
+ (dotimes (_ N) (insert op)))))
+
+ (defun oni-php-doc-comment ()
+ "Insert a PHP documentation comment at point."
+ (interactive)
+ (let ((start (point)))
+ (insert "/**\n * ")
+ (let ((insert-marker (point-marker)))
+ (insert "\n */")
+ (indent-region start (point))
+ (goto-char insert-marker))))
+
+ (defun oni-php-doc-use-comment ()
+ "Insert a PHP documentation comment for a use statement."
+ (interactive)
+ (let ((start (point))
+ (class (save-excursion
+ (save-match-data
+ (search-forward-regexp (rx "use " (group (minimal-match (zero-or-more alnum))) ";"))
+ (match-string 1)))))
+ (insert "/**\n * @use " class)
+ (let ((insert-marker (point-marker)))
+ (insert "\n */")
+ (indent-region start (point))
+ (goto-char insert-marker))))
+
+ (defun oni-php-return-belongs-to-comment ()
+ "Insert a PHP documentation comment for a BelongsTo return type."
+ (interactive)
+ (let ((start (point)))
+ (insert "/**\n * @return BelongsTo<")
+ (save-excursion
+ (insert ", $this>\n */")
+ (indent-region start (point)))))
+
+ (defun oni-php-comment-dwim (func &rest args)
+ "See if a PHP documentation comment should be added and add it.
+Otherwise call FUNC with ARGS. This is meant as advice around
+‘comment-dwim’ to make it smarter for PHP code."
+ (cond ((looking-at (rx (minimal-match (zero-or-more (any whitespace "\n")))
+ "use "))
+ (oni-php-doc-use-comment))
+ ((looking-at (rx (minimal-match (zero-or-more (any whitespace "\n")))
+ (one-or-more nonl) ": BelongsTo" eol))
+ (oni-php-return-belongs-to-comment))
+ ((and (derived-mode-p 'php-mode)
+ (not (region-active-p))
+ (looking-back (rx (minimal-match (zero-or-more blank))) (line-beginning-position))
+ (looking-at (rx (minimal-match (zero-or-more (any whitespace "\n")))
+ (or (regexp php-beginning-of-defun-regexp)
+ (regexp php--re-classlike-pattern)))))
+ (oni-php-doc-comment))
+ (t (apply func args))))
+
+ (defun oni-php-generate-namespace ()
+ (string-join
+ (mapcar
+ (lambda (s)
+ (let ((case-fold-search nil))
+ (if (string-match-p (rx upper-case) s)
+ s
+ (capitalize s))))
+ (cdr (split-string
+ (directory-file-name
+ (file-name-directory
+ (file-relative-name
+ buffer-file-name
+ (project-root (project-current)))))
+ "/")))
+ "\\"))
+
+ (defun oni-php-set-dabbrev-settings ()
+ "Set any settings for dabbrev that make sense for PHP code."
+ (setq-local dabbrev-abbrev-skip-leading-regexp (rx "$")))
+
+ (defun oni-php-ignore-error-at-point (error-type)
+ (interactive
+ (list (let* ((error-types
+ (seq-uniq
+ (mapcar (lambda (e)
+ (let ((str (flycheck-error-message e)))
+ (string-match (rx "🪪" (one-or-more whitespace) (group (one-or-more (any alnum ".")))) str)
+ (match-string 1 str)))
+ (seq-filter (lambda (e) (not (flycheck-error-checker e)))
+ (flycheck-overlay-errors-at (point))))
+ 'string=)))
+ (if (> 1 (length error-types))
+ (completing-read "Ignore type: " error-types)
+ (car error-types)))))
+ (save-excursion
+ (goto-char (line-beginning-position))
+ (indent-for-tab-command)
+ (insert "/** @phpstan-ignore " error-type " */\n")
+ (indent-for-tab-command)))
+
+ (defhydra php-mode-hydra (:color blue)
+ ("a" align-current "Align current selection"))
+
+ (advice-add 'comment-dwim :around #'oni-php-comment-dwim)
+
+ (add-hook 'php-mode-hook #'oni-php--set-require-final-newline)
+ (add-hook 'php-mode-hook #'oni-php--whitespace-mode)
+ (add-hook 'php-mode-hook 'display-fill-column-indicator-mode)
+ (add-hook 'php-mode-hook 'electric-indent-local-mode)
+ (add-hook 'php-mode-hook 'flycheck-mode)
+ (add-hook 'php-mode-hook 'oni-php--auto-fill-mode)
+ (add-hook 'php-mode-hook 'oni-php-set-dabbrev-settings)
+ (add-hook 'php-mode-hook 'oni-php-set-rainbow-identifier-faces)
+ (add-hook 'php-mode-hook 'rainbow-delimiters-mode)
+ (add-hook 'php-mode-hook 'rainbow-identifiers-mode)
+ (add-hook 'php-mode-hook 'smartparens-mode)
+ (add-hook 'php-mode-hook 'subword-mode)
+ (add-hook 'php-mode-hook 'yas-minor-mode)
+ (add-hook 'php-mode-hook 'corfu-mode)
+
+ (define-key php-mode-map (kbd "C-c m") #'php-mode-hydra/body)
+ (define-key php-mode-map (kbd ".") #'oni-php-insert-dot-dwim)
+
+ ;; In PHP code it's nice to have any ~=>~ aligned.
+
+ ;; <?php
+ ;; array(
+ ;; 'foo' => 'bar',
+ ;; 'frob' => 'baz'
+ ;; );
+ ;; ?>
+
+ (add-to-list 'align-rules-list
+ `(php-array-arrow
+ (regexp . ,(rx any (group (zero-or-more whitespace)) "=>" any))
+ (group . (1))
+ (modes . '(php-mode web-mode php-mode))
+ (repeat . t)))
+
+ ;; The WordPress coding standards specify that multiple assignments
+ ;; should have their assignment operators aligned.
+
+ ;; <?php
+ ;; $variable = "value";
+ ;; $other_variable = "other value";
+ ;; $one_more_variable = "one more variable";
+
+ (add-to-list 'align-rules-list
+ `(php-assignment-equals
+ (regexp . ,(rx any (group (zero-or-more whitespace)) "="
+ (zero-or-more whitespace) any))
+ (group . (1))
+ (modes . '(php-mode web-mode php-ts-mode))
+ (repeat . t)))
+
+;;;###autoload
+ (add-to-list 'auto-mode-alist '("\\.inc\\'" . php-mode))
+
+;;;###autoload
+ (add-to-list 'auto-mode-alist '("\\.module\\'" . php-mode))
+
+;;;###autoload
+ (with-eval-after-load 'grep
+ (add-to-list 'grep-files-aliases '("php" . "*.php *.inc *.module")))
+
+ (with-eval-after-load 'autoinsert
+ (setf (map-elt auto-insert-alist (rx ".php" eos))
+ '(nil
+ "<?php\n"
+ "\n"
+ "declare(strict_types=1);\n"
+ "\n"
+ "namespace " (oni-php-generate-namespace) ";\n"
+ "\n"
+ "class " (file-name-sans-extension (file-name-nondirectory (buffer-file-name))) "\n"
+ "{\n"
+ > _ "\n"
+ "}\n")
+ (map-elt auto-insert-alist (rx "Test.php" eos))
+ '(nil
+ "<?php\n"
+ "\n"
+ "declare(strict_types=1);\n"
+ "\n"
+ "namespace " (oni-php-generate-namespace) ";\n"
+ "\n"
+ "use Illuminate\\Foundation\\Testing\\RefreshDatabase;\n"
+ "use Illuminate\\Foundation\\Testing\\WithFaker;\n"
+ "use Tests\\TestCase;\n"
+ "\n"
+ "class " (file-name-sans-extension (file-name-nondirectory (buffer-file-name))) " extends TestCase\n"
+ "{\n"
+ > "use RefreshDatabase;\n"
+ > "use WithFaker;\n"
+ "\n"
+ > "/** @test */\n"
+ > "public function " (replace-regexp-in-string (rx whitespace) "_" (downcase (skeleton-read "Test function name: "))) "(): void\n"
+ "{" > "\n"
+ > _ "\n"
+ "}" > "\n"
+ "}")))
+
+ (defun oni-php-in-expression-context-p ()
+ (not (oni-php-in-static-call-context-p)))
+
+ (defun oni-php-in-test-file ()
+ (string-suffix-p "Test.php" buffer-file-name))
+
+ (defun oni-php-in-static-call-context-p ()
+ (looking-back "::\\w+" (- (point) (line-beginning-position))))
+
+ (defun oni-php-grep-symbol (symbol)
+ "Use ‘rgrep’ to find SYMBOL.
+If there is an active region when this command is called interactively
+SYMBOL will be the text in the region. Otherwise it's the symbol at
+point."
+ (interactive (list
+ (if (region-active-p)
+ (buffer-substring-no-properties (region-beginning) (region-end))
+ (thing-at-point 'symbol))))
+ (rgrep (rx (literal symbol))
+ (map-elt grep-files-aliases "php")
+ (project-root (project-current))))
+
+ (define-key php-mode-map (kbd "C-c .") nil t)
+ (define-key php-mode-map (kbd "C-c . g") '("Search for symbol at point" . oni-php-grep-symbol))
+ (define-key php-mode-map (kbd "C-c . a") '("Import symbol at point" . oni-php-add-use))
+ (define-key php-mode-map (kbd "C-c . i") '("Ignore error at point" . oni-php-ignore-error-at-point)))
+
+(use-package rainbow-identifiers)
+
+;; End of oni-php
diff --git a/emacs/.emacs.d/oni-prescient.el b/emacs/.emacs.d/oni-prescient.el
new file mode 100644
index 0000000..9687b68
--- /dev/null
+++ b/emacs/.emacs.d/oni-prescient.el
@@ -0,0 +1,11 @@
+;; Start of oni-prescient
+
+(use-package prescient
+ :config
+ (setq prescient-save-file (expand-file-name "data/prescient-save.el" user-emacs-directory))
+
+ (run-with-idle-timer 10 t 'prescient--save)
+
+ (prescient-persist-mode))
+
+;; End of oni-prescient
diff --git a/emacs/.emacs.d/oni-smartparens.el b/emacs/.emacs.d/oni-smartparens.el
new file mode 100644
index 0000000..83aae3e
--- /dev/null
+++ b/emacs/.emacs.d/oni-smartparens.el
@@ -0,0 +1,12 @@
+;; Start of oni-smartparens
+
+(use-package smartparens
+ :config
+ (require 'smartparens-config)
+
+ (define-key smartparens-mode-map (kbd "C-<left>") 'sp-forward-barf-sexp)
+ (define-key smartparens-mode-map (kbd "C-<right>") 'sp-slurp-hybrid-sexp)
+ (define-key smartparens-mode-map (kbd "C-M-<right>") 'sp-backward-barf-sexp)
+ (define-key smartparens-mode-map (kbd "M-<up>") 'sp-splice-sexp-killing-backward))
+
+;; End of oni-smartparens
diff --git a/emacs/.emacs.d/oni-stillness.el b/emacs/.emacs.d/oni-stillness.el
new file mode 100644
index 0000000..b7b5567
--- /dev/null
+++ b/emacs/.emacs.d/oni-stillness.el
@@ -0,0 +1,6 @@
+;; Start of oni-stillness
+
+(use-package stillness-mode
+ :init (stillness-mode))
+
+;; End of oni-stillness
diff --git a/emacs/.emacs.d/oni-xterm-color.el b/emacs/.emacs.d/oni-xterm-color.el
new file mode 100644
index 0000000..5ab78d6
--- /dev/null
+++ b/emacs/.emacs.d/oni-xterm-color.el
@@ -0,0 +1,5 @@
+;; Start of oni-xterm-color
+
+(use-package xterm-color)
+
+;; End of oni-xterm-color
diff --git a/emacs/.emacs.d/oni-yasnippet.el b/emacs/.emacs.d/oni-yasnippet.el
new file mode 100644
index 0000000..06e6d18
--- /dev/null
+++ b/emacs/.emacs.d/oni-yasnippet.el
@@ -0,0 +1,34 @@
+;; Start of oni-yasnippet
+
+(use-package yasnippet
+ :init
+ (yas-global-mode)
+ :config
+ (require 'diminish)
+
+ (defun oni-yasnippet-remove-snippet-by-name (name mode)
+ "Remove the snippet NAME from MODE's snippet tables."
+ (and-let* ((mode-table (gethash mode yas--tables))
+ (uuidhash-table (yas--table-uuidhash mode-table))
+ (hash-table (yas--table-hash mode-table))
+ (snippet (gethash name uuidhash-table))
+ (key (yas--template-key snippet)))
+ (remhash key hash-table)
+ (remhash name uuidhash-table)))
+
+ (defun oni-yasnippet-cleanup-snippets ()
+ "Remove some snippets that I don't like."
+ (oni-yasnippet-remove-snippet-by-name "defun" 'lisp-interaction-mode))
+
+ (with-eval-after-load 'yasnippet (diminish 'yas-minor-mode))
+
+ (setq-default yas-buffer-local-condition yas-not-string-or-comment-condition)
+
+ (define-key yas-minor-mode-map (kbd "<tab>") nil)
+ (define-key yas-minor-mode-map (kbd "C-\\") 'yas-expand)
+ (define-key yas-minor-mode-map (kbd "SPC") yas-maybe-expand)
+ (define-key yas-minor-mode-map (kbd "TAB") nil)
+
+ (add-hook 'yas-after-reload-hook #'oni-yasnippet-cleanup-snippets))
+
+;; End of oni-yasnippet