diff options
-rw-r--r-- | Emacs/.config/emacs/config.org | 211 |
1 files changed, 133 insertions, 78 deletions
diff --git a/Emacs/.config/emacs/config.org b/Emacs/.config/emacs/config.org index 8eccda1..6e8cf71 100644 --- a/Emacs/.config/emacs/config.org +++ b/Emacs/.config/emacs/config.org @@ -44,38 +44,34 @@ Here's an example of some Emacs Lisp code: ;;; Code: #+end_src -This is an Emacs Lisp code block, something you will see a *LOT* of -throughout. All the Emacs Lisp code blocks in this document are -collected, concatenated then written to a file (=config.el=). This -code file is then evaluated by Emacs -[[file:init.el::+literate/load-config][at boot]]. - -This style of coding is called /literate programming/. Donald Knuth +This allows the document to act as both /source code/ and +/documentation/ at once. Pretty cool, right? This style of coding is +called /literate programming/. Donald Knuth [[https://en.wikipedia.org/wiki/Literate_programming][really liked]] the idea. I mainly utilise this to explain my decisions for configuring or using certain packages: Emacs is an opinionated piece -of software after all. +of software and I may as well express my opinions somewhere. Sections tagged =WAIT= are not compiled and are, hence, unused. -Usually I provide some reasoning as to why. Such sections can be -easily placed back into the configuration and in Emacs can be loaded -at runtime when I need them, which is why they're not deleted. A lot -of code here is essentially write and forget; nothing needs to change -unless I find a more efficient way to do things. +Usually I provide some reasoning as to why. If using Emacs, the code +in any one section may be loaded interactively (in case I need it +immediately). A lot of code here is essentially write and forget; +nothing needs to change unless I find a more efficient way to do +things. Some sections border on blog posts justifying why I think they're good applications or giving some greater reasoning about my specific -configuration of a package. That can be distracting, so tangling this -file (via ~(org-babel-tangle)~) and looking at the source code may be -more helpful. +configuration of a package. That can be distracting, so reading the +produced file may be more helpful for you. Use ~org-babel-tangle~ in +Emacs to do so, or ask me very nicely. * Basics -Let's setup a few things: +Let's setup a few absolute essentials: + My name and mail address -+ File encoding -+ Backup files (~backup-directory-alist~) -+ Refreshing buffers when a change occurs (~auto-revert-mode~) -+ Yes or no questions being less painful (~y-or-n-p~) -+ Make the kill ring work seamlessly with the clipboard ++ File encoding (no "\r" characters at the end of lines, please) ++ Where to store backup files (~backup-directory-alist~) ++ Auto refresh buffers when a change occurs (~auto-revert-mode~) ++ Yes or no questions can be less painful (~y-or-n-p~) ++ Make the "kill ring" work seamlessly with the clipboard #+begin_src emacs-lisp (use-package emacs @@ -102,8 +98,8 @@ throughout the file. An anonymous function (~lambda~) which takes no arguments is a procedure. This macro generates procedures, with the parameters of the macro being the body of the procedure. It returns it in quoted -form, as that is the most common use of this macro. - +form (as data rather than code), as that is the most common use of +this macro. #+begin_src emacs-lisp (defmacro proc (&rest BODY) "For a given list of forms BODY, return a quoted 0 argument @@ -112,13 +108,14 @@ lambda." #+end_src ** Automatically run a command on saving Define a macro which creates hooks into ~after-save-hook~. On certain -~conditions~ being met, ~to-run~ is evaluated. +~conditions~ being met, ~to-run~ is evaluated. Classic example use +case: compiling on save. #+begin_src emacs-lisp (use-package simple :defer t :config - (defmacro +oreo/create-auto-save (conditions &rest to-run) + (defmacro create-auto-save (conditions &rest to-run) "Create a hook for after saves, where on CONDITIONS being met TO-RUN is evaluated." `(add-hook 'after-save-hook @@ -126,56 +123,51 @@ TO-RUN is evaluated." (interactive) (when ,conditions ,@to-run))))) #+end_src -** Setting number of native jobs -In [[file:early-init.el][early-init.el]] I set the number of -native-workers to 4, which isn't necessarily optimal when -loading/compiling the rest of this file depending on the machine I -use: -- On my laptop (=newboy=) I'd prefer to have it use 2-3 threads so - I can actually use the rest of the laptop while waiting for - compilation -- On my desktop (=oldboy=) I'd prefer to use 4-6 threads as I can - afford more, so I can get a faster load up. - -#+begin_src emacs-lisp -(use-package comp - :init - (setq native-comp-async-jobs-number - (pcase (system-name) - ("newboy" 3) - ("oldboy" 6) - (_ 3)))) -#+end_src ** Clean buffer list -Clean all buffers except for those in ~+oreo/keep-buffers~. +Clean all buffers except for those in ~clean-buffers-keep~. #+begin_src emacs-lisp -(defconst +oreo/keep-buffers +(defconst clean-buffers-keep (list "config.org" "*scratch*" "*dashboard*" "*Messages*" "*Warnings*" "*eshell*") "List of buffer names to preserve.") -(defun +oreo/clean-buffers () - "Kill all buffers except any with names in +oreo/keep-buffers." +(defun clean-buffers () + "Kill all buffers except any with names in CLEAN-BUFFERS-KEEP." (interactive) - (let ((should-not-kill #'(lambda (buf) (member (buffer-name buf) - +oreo/keep-buffers)))) - (mapcar #'kill-buffer (cl-remove-if should-not-kill (buffer-list))))) + (let ((should-not-kill + #'(lambda (buf) + (member (buffer-name buf) + clean-buffers-keep)))) + (mapc #'kill-buffer + (cl-remove-if should-not-kill (buffer-list))))) #+end_src ** Custom window management -Emacs' default window management is horrendous, using other windows on -a whim as if your carefully crafted window setup doesn't exist! -Thankfully you can change this behaviour via the -~display-buffer-alist~ which matches regular expressions on buffer -names with a set of properties and functions that dictate how the -window for a buffer should be displayed. It's a bit verbose but once -you get the hang of it it's actually really unique. - -Here I add a use-package keyword to make ~display-buffer-alist~ -records within a single use-package call instead of doing the -~add-to-list~ yourself. I have no idea whether it's optimal AT ALL, -but it works for me. +Generally speaking, applications that have a windowing concept do not +have a lot of options for how those windows are placed. Emacs has a +window management system unlike any other piece of software I have +ever used, with some complexity but incredible capability. + +The big idea is this table (=alists= are basically just tables), +~display-buffer-alist~, which associates regular expressions with +"actions". The regular expressions are for the name of buffers, and +the actions are how the buffer should be displayed. And there are a +*lot* of ways to display buffers. + +Here's an example record: +#+begin_src lisp +'("config.org" + (display-buffer-in-side-window) + (side . bottom)) +#+end_src + +This matches any buffer named =config.org=, displaying the buffer in a +side window to the bottom. + +What I configure here is a ~use-package~ keyword, ~:display~, which +will allow me to write associations to ~display-buffer-alist~ really +easily. 2024-04-23: Found this option ~switch-to-buffer-obey-display-actions~ which makes manual buffer switches obey the same constraints via @@ -230,22 +222,32 @@ do that for me. (cl-loop for element in elements collect `(cl-pushnew ,element ,listvar)))) #+end_src +** Setting number of native jobs +Emacs has a native compilation capability to make things /even +faster/. In [[file:early-init.el][early-init.el]] I set the number of +native-workers to 4, which isn't necessarily optimal when +loading/compiling the rest of this file depending on the machine I +use. On my machines, which have 8 process throughput (4 core + +hyperthreading), 6-7 workers makes much more sense. On a machine I've +never used before, 3 seems to be a reasonable default. + +#+begin_src emacs-lisp +(use-package comp + :init + (setq native-comp-async-jobs-number + (pcase (system-name) + ((or "ravenmaiden" "oldboy") 6) + (_ 3)))) +#+end_src * Aesthetics General look and feel of Emacs (mostly disabling stuff I don't like). ** Themes -I have both a dark and light theme for differing situations. -Here I configure which one to load and how to switch between them. - -My preferred dark theme is my own "personal-solarized" theme which is -stored in the Emacs lisp folder (look at -[[file:elisp/personal-solarized-theme.el][this file]]). It's -essentially a copy of the solarized theme (from the ~solarized-themes~ -package) with a few personal changes. - -My preferred light theme is modus-operandi, mostly because I don't -care to design my own light theme and I rarely use them. They are -necessary in high light situations where a dark mode would strain the -eyes too much. +I have both a dark and light theme for differing situations. Here I +configure a timer which ensures I have a light theme during the day +and dark theme at night. I wrote my own themes by copying stuff I +like from other themes then modifying them. The dark theme is in +[[file:elisp/personal-solarized-theme.el][this file]] and the light +theme is in [[file:elisp/personal-light-theme.el][this file]]. #+begin_src emacs-lisp (use-package custom @@ -3748,6 +3750,59 @@ fun to write programs in. "sr" #'scheme-send-region "e" #'scheme-send-last-sexp)) #+end_src +** Ocaml +*** Ocaml Setup +Firstly, install ~opam~ and ~ocaml~. Then run the following script: +#+begin_src sh +opam install tuareg ocamlformat odoc utop merlin user-setup +opam user-setup install +mv ~/.emacs.d/opam-user-setup.el ~/.config/emacs/elisp +rm -rf ~/.emacs.d ~/.emacs +#+end_src +This sets up the necessary packages (particularly Emacs Lisp) and some +configuration that ensures Emacs is consistent with the user +installation. Notice the moving of =opam-user-setup.el= into +=~/.config/emacs/elisp=, which we'll use to setup the ocaml +experience. +*** Ocaml Configuration +Here I load the =opam-user-setup= package setup earlier, with some +neat tips from the default =~/.emacs= generated by ~opam user-setup +install~. +#+begin_src emacs-lisp +(use-package opam-user-setup + :defer t + :load-path "elisp/" + :mode ("\\.ml" . tuareg-mode) + :display + ("\\*utop\\*" + (display-buffer-at-bottom) + (window-height . 0.3)) + :config + (add-to-list 'compilation-error-regexp-alist-alist + `(ocaml + "[Ff]ile \\(\"\\(.*?\\)\", line \\(-?[0-9]+\\)\\(, characters \\(-?[0-9]+\\)-\\([0-9]+\\)\\)?\\)\\(:\n\\(\\(Warning .*?\\)\\|\\(Error\\)\\):\\)?" + 2 3 (5 . 6) (9 . 11) 1 (8 compilation-message-face))) + (add-to-list 'compilation-error-regexp-alist + 'ocaml) + :general + (local-leader + :keymaps 'tuareg-mode-map + "u" #'utop) + (local-leader + :keymaps 'tuareg-mode-map + :infix "e" + "r" #'utop-eval-region + "e" #'utop-eval-phrase + "b" #'utop-eval-buffer)) + +(use-package merlin-eldoc + :straight t + :after opam-user-setup + :hook + (tuareg-mode-hook . merlin-eldoc-setup) + :init + (setq merlin-eldoc-occurrences nil)) +#+end_src ** Common Lisp Common Lisp is a dialect of Lisp, the most /common/ one around. Emacs comes with builtin Lisp support, of course, and it's really good in |