From 3c10944651bc941149ae987ee8a4ea0c88378322 Mon Sep 17 00:00:00 2001 From: noa@gaiwan.org Date: Wed, 19 Jun 2024 07:44:22 +0000 Subject: Initial commit --- bootstrap | 15 - config.org | 1611 +++++++++++++++++++++++++++++++++ emacs/early-init.el | 41 - emacs/init.el | 1007 --------------------- emacs/site-lisp/fixed-pitch.el | 53 -- emacs/site-lisp/tubthumping-theme.el | 262 ------ firefox/README | 3 - firefox/chrome/userChrome.css | 44 - firefox/user.js | 208 ----- fish/config.fish | 49 - fish/fish_variables | 7 - fish/functions/fish_prompt.fish | 6 - fish/functions/fish_right_prompt.fish | 2 - fish/functions/grep.fish | 5 - fish/functions/ls.fish | 10 - git/config | 5 - jwmrc | 140 --- mbsyncrc | 23 - msmtp/config | 13 - mutt/mailcap | 1 - mutt/muttrc | 71 -- picom/picom.conf | 18 - rofi/config.rasi | 157 ---- rofi/spotlight.rasi | 78 -- setup.sh | 106 --- user-dirs.dirs | 8 - xdm/README | 1 - xdm/Xresources | 23 - xdm/Xsession | 131 --- xdm/Xsetup | 6 - xmodmap | 14 - xsession | 26 - 32 files changed, 1611 insertions(+), 2533 deletions(-) delete mode 100644 bootstrap create mode 100644 config.org delete mode 100644 emacs/early-init.el delete mode 100644 emacs/init.el delete mode 100644 emacs/site-lisp/fixed-pitch.el delete mode 100644 emacs/site-lisp/tubthumping-theme.el delete mode 100644 firefox/README delete mode 100644 firefox/chrome/userChrome.css delete mode 100644 firefox/user.js delete mode 100644 fish/config.fish delete mode 100644 fish/fish_variables delete mode 100644 fish/functions/fish_prompt.fish delete mode 100644 fish/functions/fish_right_prompt.fish delete mode 100644 fish/functions/grep.fish delete mode 100644 fish/functions/ls.fish delete mode 100644 git/config delete mode 100644 jwmrc delete mode 100644 mbsyncrc delete mode 100644 msmtp/config delete mode 100644 mutt/mailcap delete mode 100644 mutt/muttrc delete mode 100644 picom/picom.conf delete mode 100644 rofi/config.rasi delete mode 100644 rofi/spotlight.rasi delete mode 100755 setup.sh delete mode 100644 user-dirs.dirs delete mode 100644 xdm/README delete mode 100644 xdm/Xresources delete mode 100755 xdm/Xsession delete mode 100755 xdm/Xsetup delete mode 100644 xmodmap delete mode 100755 xsession diff --git a/bootstrap b/bootstrap deleted file mode 100644 index e6f1d87..0000000 --- a/bootstrap +++ /dev/null @@ -1,15 +0,0 @@ -#!/usr/bin/env sh - -set -e - -mkdir -p $HOME/.config -cd $HOME/.config -git init -git remote add origin "http://cgit.tilde.town/~noa/dots/" -git fetch origin -git checkout -b main --track origin/main -git remote set-url origin noa@tilde.town:public_git/dots - -echo -echo "Configuration files installed." -echo "You probably want to run ~/.config/setup.sh now." diff --git a/config.org b/config.org new file mode 100644 index 0000000..9c27254 --- /dev/null +++ b/config.org @@ -0,0 +1,1611 @@ +#+TITLE: My configurations +#+SUBTITLE: Version 0.1 +#+DATE: 2024-06-18 +#+PROPERTY: header-args :tangle yes + +* Introduction +This is an experiment in using literate programming to generate my computer configurations. I want to try it out because my emacs configuration already has a large number of comments, and it seems more fitting to make them first class citizens. Furthermore, i want to reorder some parts of the configurations to put relevant information close together, rather than having to arbitrarily split configuration from different programs into different files. + +The system should be generated using this command: + +#+begin_src sh :tangle no +emacs config.org --batch -f org-babel-tangle +#+end_src + +* Inspiration +I have consulted [[https://raw.githubusercontent.com/rasendubi/dotfiles/master/README.org][Oleksii's configuration]] heavily to get used to how to work with literate programming. Lots of literate configuration attempts are disappointing in that they feature almost no commentary and are strictly linear. In my eyes, these are the two biggest advantages of the literate programming model to begin with. Oleksii's configuration is nice in that it has both lots of commentary, and is non-linear. It also features configuration for more than one program, mixed together with the parts that matter. + +For this initial test, my configuration fails on both counts. All i've done is put every section of elisp into a code block and turned the comments into normal org text. Over time, i hope to expand it into something which ticks both of those boxes. + +* Configuration + +#+begin_src elisp +;;; init.el --- my emacs configuration -*- lexical-binding: t; -*- +#+end_src + +#+begin_src elisp +(add-to-list 'load-path (expand-file-name (concat user-emacs-directory "site-lisp"))) +#+end_src + +I like to see garbage collection messages. I keep meaning to set up something like the [[https://akrl.sdf.org/#orgc9536b4][garbage collector magic hack]] so that emacs hangs less when i'm running a macro or opening a big web page or whatever. But for now, the default values are adequate. + +#+begin_src elisp + (setq garbage-collection-messages t) + #+end_src + +We set the ~gc-cons-threshold~ and ~gc-cons-percentage~ to be really high in the ~early-init.el~ file. This makes loading emacs a little bit faster. But obviously i don't want that in general usage, so once emacs has finished starting up, i make sure to lower the values again. + +#+begin_src elisp + (add-hook 'emacs-startup-hook + #'(lambda () + (message (format "Initialised in %s seconds with %s garbage collections." (emacs-init-time) gcs-done)) + ;;; reset garbage collector + (setq + gc-cons-threshold 800000 + gc-cons-percentage 0.2))) +#+end_src + +#+begin_src elisp + (setopt user-full-name "noa") + (setopt user-mail-address "noa@gaiwan.org") +#+end_src + +Properly distinguish these chords from their ascii legacy + +#+begin_src elisp +(define-key input-decode-map [?\C-m] [C-m]) +#+end_src + +** Colour theme +This is my emacs theme. It's a monochrome theme which, unlike most monochrome themes, really does have only two colours. I define a few faces, and set every other face as one of them. There are a few things i want to do with it before i make it properly public: make the colours configurable and able to update on the fly, and in general iron out some of the janky parts. A few things defined it are quite specific to this configuration, like the way i define the borders for the tab and header bars, and there is no mode line configuration because i don't use it. + +#+begin_src elisp + (require 'tubthumping-theme) + (load-theme 'tubthumping t) +#+end_src + +** Executing commands +I make my caps lock a menu key, so i can open the command palette with it: + +#+begin_src elisp + (define-key context-menu-mode-map (kbd "") nil) + (global-set-key (kbd "") 'execute-extended-command) +#+end_src + +I also unbind ~M-x~ so i can use it as another keybinding. + +#+begin_src elisp + (global-unset-key (kbd "M-x")) +#+end_src + +It is often useful to be able to run a command while i am already in the process of running a command in the minibuffer. This is rarely two extended commands; usually it is completion. + +#+begin_src elisp +(setopt minibuffer-depth-indicate-mode t) +#+end_src + +** Minibuffer candidate completion +Vertico is a package for a nice minibuffer completion experience. It displays a vertical list of candidates. It integrates well with the emacs ecosystem and lets me use other packages that also play nicely. + +#+begin_src elisp + (use-package vertico :ensure t) + (setopt vertico-mode t) +#+end_src + +We want vertico to take up a maximum of 12 lines on the display. My screen is quite small, so that's fine, but if i had a bigger screen, i might want to look into setting a percentage or increasing this. + +#+begin_src elisp + (setopt vertico-count 12) +#+end_src + +By default, vertico uses a font-face trick to put a horizontal line across group titles. It looks quite nice, but doesn't really conform to my design sensibilities, so here i redefine the group format to not have this. Because we no longer have the line, we also align the group name to the left edge. + +#+begin_src elisp +(setopt vertico-group-format #("%s " 0 3 (face vertico-group-title))) +#+end_src + +We also want to be able to jump to the bottom of the list by moving up from the top of the list, and the opposite. I've rarely made use of this functionality and i don't know if it's actually a best practice from an interaction perspective, but i'm going to keep it on until it causes an issue for me. + +#+begin_src elisp +(setopt vertico-cycle t) +#+end_src + +Multiform mode will allow us to set different layouts for different completion categories. For example, after pressing a prefix key, i can press C-h to view a list of all possible following keys. For this, i want vertico to display a grid of choices, rather than one completion per line. + +#+begin_src elisp +(setopt vertico-multiform-mode t) +#+end_src + +And of course, i want to be able to interact with vertico with the mouse. + +#+begin_src elisp +(setopt vertico-mouse-mode t) +#+end_src + +When completing a filename, i want to be able to easily delete directories in one fell swoop, instead of character by character or word by word. Usually C- would be fine, but if directories have a hyphen or space in their name, i have to press multiple times, which is almost never desirable. + +#+begin_src elisp +(bind-key (kbd "RET") #'vertico-directory-enter 'vertico-map) +(bind-key (kbd "") #'vertico-directory-delete-char 'vertico-map) +(bind-key (kbd "") #'vertico-directory-delete-word 'vertico-map) +#+end_src + +If i type ~/ etc in a find-file prompt, get rid of the preceding directory names for a cleaner look. + +#+begin_src elisp +(add-hook 'rfn-eshadow-update-overlay-hook #'vertico-directory-tidy) +#+end_src + +#+begin_src elisp +(setopt read-buffer-completion-ignore-case t) +(setopt read-file-name-completion-ignore-case t) +(setopt completion-ignore-case t) +#+end_src + +#+begin_src elisp +(use-package orderless :ensure t) +(setopt completion-styles '(orderless basic)) +(setopt completion-category-defaults nil) +(setopt completion-category-overrides '((file (styles partial-completion)))) +#+end_src + +#+begin_src elisp +(setopt confirm-nonexistent-file-or-buffer 'after-completion) +#+end_src + +** Replace the mode line with a header line +First, we set the mode line to nil. On my graphical display, this collapses it so all i get is a thin black line separating the buffer from the echo area. + +#+begin_src elisp +(setq-default mode-line-format nil) +#+end_src + +But the mode line still holds some useful information that i want to see. I would rather that be in the header line, because to me it makes sense for this kind of metadata to be /above/ the buffer it is describing. + +First, in white on black text, i want the information about the state of the file. This will show three hyphens in the top left corner of the header line. The first two hyphens mean that the file is both writable and unchanged. If the buffer has been changed, they will change to two asterisks. If the buffer is read only, they will change two percentage symbols. And if the buffer is read only and has been changed, the first will change to a percentage symbol, and the second will change to an asterisk. The final hyphen represents that the file is local, specifically that the default-directory variable is local. If it is remote, an at symbol will be displayed instead. + +Next, we want to display the buffer name. For buffers which belong to files, this will usually be the file name, but it is likely to be something more informative for special buffers. + +Below that, show a line and column coördinate. There are special minor modes that will enable or disable this for the default mode line, but i ignore that and put the formatting code here directly. The docstring for the mode-line-format variable suggests that the column might not be displayed correctly in some situations without enabling the minor mode, but i haven't noticed that yet so i don't bother. This column number is zero-indexed; a capital c would make it one-indexed. For now i stick with zero-indexed as that's the emacs default and i'm not sure which is better. I guess it makes a bit more sense that the first character on a line is labeled "1". + +I don't know exactly what the final variable covers, so i keep it here so that if something shows up i know that it gets put here. Because i have a global mode line in my tab bar, some of the things that would otherwise be here (like the time, battery percentage, and notifications for chat buffers) don't show up. + +Before we define this, we will copy the code from mode-line-format-right-align so that i can use it. This is an emacs 30 feature, which i don't run yet. In the future, i'll be able to remove this. Note that because this isn't emacs 30, this doesn't work perfectly, and the right-aligned content is often cut off. + +#+begin_src elisp +(defcustom mode-line-right-align-edge 'window + "Where function `mode-line-format-right-align' should align to. +Internally, that function uses `:align-to' in a display property, +so aligns to the left edge of the given area. See info node +`(elisp)Pixel Specification'. + +Must be set to a symbol. Acceptable values are: +- `window': align to extreme right of window, regardless of margins + or fringes +- `right-fringe': align to right-fringe +- `right-margin': align to right-margin" + :type '(choice (const right-margin) + (const right-fringe) + (const window)) + :group 'mode-line + :version "30.1") +(defun mode--line-format-right-align () + "Right-align all following mode-line constructs. + +When the symbol `mode-line-format-right-align' appears in +`mode-line-format', return a string of one space, with a display +property to make it appear long enough to align anything after +that symbol to the right of the rendered mode line. Exactly how +far to the right is controlled by `mode-line-right-align-edge'. + +It is important that the symbol `mode-line-format-right-align' be +included in `mode-line-format' (and not another similar construct +such as `(:eval (mode-line-format-right-align)'). This is because +the symbol `mode-line-format-right-align' is processed by +`format-mode-line' as a variable." + (let* ((rest (cdr (memq 'mode-line-format-right-align + mode-line-format))) + (rest-str (format-mode-line `("" ,@rest))) + (rest-width (string-pixel-width rest-str))) + (propertize " " 'display + ;; The `right' spec doesn't work on TTY frames + ;; when windows are split horizontally (bug#59620) + (if (and (display-graphic-p) + (not (eq mode-line-right-align-edge 'window))) + `(space :align-to (- ,mode-line-right-align-edge + (,rest-width))) + `(space :align-to (,(- (window-pixel-width) + (window-scroll-bar-width) + (window-right-divider-width) + (* (or (cdr (window-margins)) 1) + (frame-char-width)) + ;; Manually account for value of + ;; `mode-line-right-align-edge' even + ;; when display is non-graphical + (pcase mode-line-right-align-edge + ('right-margin + (or (cdr (window-margins)) 0)) + ('right-fringe + ;; what here? + (or (cadr (window-fringes)) 0)) + (_ 0)) + rest-width))))))) + +(defvar mode-line-format-right-align '(:eval (mode--line-format-right-align)) + "Mode line construct to right align all following constructs.") +(put 'mode-line-format-right-align 'risky-local-variable t) +#+end_src + +#+begin_src elisp +(setq-default header-line-format + '("%b:%l,%c " + mode-line-format-right-align + "%1*%1+%1@")) +#+end_src + +** Flash the current line +This function was taken from a karthinks blog post. Previously i was using an external package, [[https://github.com/Malabarba/beacon][beacon]], and i still think that works better. But this is adequate enough that i'm happy. + +I'd like to change the face, but ~pulse-highlight-face~ has *DO NOT CUSTOMIZE* in the docstring so what am i meant to do!? + +#+begin_src elisp +(defun pulse-line (&rest _) + "Pulse the current line." + (pulse-momentary-highlight-one-line (point))) +(dolist (command '(scroll-up-command scroll-down-command recenter-top-bottom other-window)) + (advice-add command :after #'pulse-line)) +#+end_src + +** Xmpp +Jabber.el is an xmpp client in emacs. I don't actually use xmpp as xmpp that much. But i do use it to connect to irc, and this package lets me do that. Unfortunately, it's not a particularly well-behaved package; by default it clobbers some keybindings and floods the echo area with unhelpful messages. + +#+begin_src elisp + (use-package jabber :ensure t) + (setopt jabber-account-list '(("noa@hmm.st"))) +#+end_src + +So now what we're going to do is get it to stop showing a bunch of channels in the mode line, because there will always be new activity and i want to drop in when i feel like it, and not always have a reminder of that fact. The defun below is copied from jabber-activity-show-p-default but with an extra condition plopped in. + +#+begin_src elisp + (defcustom noa/jabber-activity-dont-show + '("#tildetown%town@irc.hmm.st" + "#meta%tilde.chat@irc.hmm.st" + "hmm@conference.hmm.st") + "List of JIDs not to show in the modeline." + :group 'jabber-activity)(defun noa/jabber-activity-show-p (jid) + "Return non-nil if JID should be hidden. + A JID should be hidden when there is an invisible buffer for JID, + when JID is not in `noa/jabber-activity-dont-show', + and when JID is not in `jabber-activity-banned'." + (let ((buffer (jabber-activity-find-buffer-name jid))) + (and (buffer-live-p buffer) + (not (get-buffer-window buffer 'visible)) + (not (cl-dolist (entry jabber-activity-banned) + (when (string-match entry jid) + (cl-return t)))) + (not (cl-dolist (entry noa/jabber-activity-dont-show) + (when (string-match entry jid) + (cl-return t)))))))(setopt jabber-activity-show-p #'noa/jabber-activity-show-p) +#+end_src + +I'm on a laptop, so whenever i shut it i get disconnected. Jabber can query auth-source for my password, so automatically reconnecting is useful and doesn't need me to do anything. + +#+begin_src elisp +(setopt jabber-auto-reconnect t) +#+end_src + +Because my xmpp server supports message history, i don't need to worry about exiting without seeing all messages, as they'll be there when i get back. + +#+begin_src elisp +(setopt jabber-activity-query-unread nil) +#+end_src + +The default buffer names are a bit ugly to look at, so i change them to a similar format as eww. Which is still pretty ugly, welcome to emacs + +#+begin_src elisp +(setopt jabber-chat-buffer-format "*%n | jabber*" + jabber-groupchat-buffer-format "*%n | jabber*") +#+end_src + +As alluded to above, jabber.el also has a terrible terrible habit of sending a message to the echo area for every change in online state of my contacts, and every single message in any channel. Obviously this gets very annoying, especially if i'm using the minibuffer at that time. Thank you to acdw for pointing me towards these helpful hooks to remove. + +#+begin_src elisp +(remove-hook 'jabber-alert-muc-hooks #'jabber-muc-echo) +(remove-hook 'jabber-alert-presence-hooks #'jabber-presence-echo) +#+end_src + +Also stop jabber from clobbering the dired-jump binding and instead use something on C-c like a good child. + +#+begin_src elisp +(with-eval-after-load 'jabber + (keymap-global-set "C-x C-j" #'dired-jump)) +#+end_src + +Finally, have a binding to jump to a buffer in which there's been some new activity. Better than always using switch-to-buffer to get there. + +#+begin_src elisp +(keymap-global-set "C-c C-j" #'jabber-activity-switch-to) +#+end_src + +** Nov.el +#+begin_src elisp +(use-package nov :ensure t) +(add-to-list 'auto-mode-alist '("\\.epub\\'" . nov-mode)) +#+end_src + +** Spellcheck +Jinx is a package for spellchecking. Previously i used [[https://www.gnu.org/software/emacs/manual/html_node/emacs/Spelling.html][flyspell]], which is built in, and [[https://codeberg.org/ideasman42/emacs-spell-fu][spell-fu]]. Flyspell is not ideal because it only checks the word under the point. Furthermore, the correction interface is not pleasant to look at with a proportional font as it uses spaces to align the candidates. Spell-fu checks all the words that are visible, thereby behaving much more like a traditional spell checker. Jinx improves on spell-fu by interacting with the spellcheck process in a more efficient way, and has a nicer interface to corrections. + +#+begin_src elisp +(use-package jinx :ensure t) +(setopt global-jinx-mode t) +#+end_src + +Replace the default spellcheck binding with jinx + +#+begin_src elisp +(keymap-global-set "M-$" #'jinx-correct) +(keymap-global-set "C-M-$" #'jinx-languages) +#+end_src + +*** Improve the corrections grid + +Show the corrections in a grid, so i can see more of them at once. + +#+begin_src elisp +(add-to-list 'vertico-multiform-categories + '(jinx grid (vertico-grid-annotate . 20))) + #+end_src + +*** Add corrected words to abbrev + +This is a cool function i took from the jinx wiki. It automatically creates an abbrev for words i correct, so if i make the same error again, it gets fixed without me having to do anything! + +#+begin_src elisp +(defun jinx--add-to-abbrev (overlay word) + "Add abbreviation to `global-abbrev-table'. +The misspelled word is taken from OVERLAY. WORD is the corrected word." + (let ((abbrev (buffer-substring-no-properties + (overlay-start overlay) + (overlay-end overlay)))) + (message "Abbrev: %s -> %s" abbrev word) + (define-abbrev global-abbrev-table abbrev word))) +(advice-add 'jinx--correct-replace :before #'jinx--add-to-abbrev) +#+end_src + +*** Consistent face on hover +Almost everywhere else, the ~highlight~ face is used for interactive text on mouse over. However, jinx reuses its own ~jinx-highlight~ face, which i don't really like. This face clashes with the face i use for the active region, which means selecting text across a misspelled word can be a bit confusing. If i change the ~jinx-highlight~ face, it looks wrong when i've activated jinx to correct the word. + +#+begin_src elisp + (put 'jinx-overlay 'mouse-face '(jinx-misspelled highlight)) +#+end_src + +** Completing-read everywhere with consult +Consult is a package to provide navigation commands that take advantage of completing-read. I set up a nice completing-read environment earlier with vertico. There are a lot of commands built in to consult, and it's possible to define more. But i use it very simply. + +#+begin_src elisp +(use-package consult :ensure t) +#+end_src + +Consult buffer can be used instead of the default buffer menu. It lists recently used files and bookmarks as well as open buffers. + +#+begin_src elisp +(global-set-key [remap switch-to-buffer] #'consult-buffer) +#+end_src + +These are some other almost default functions but with extra interactivity. + +#+begin_src elisp +(global-set-key [remap yank-pop] #'consult-yank-pop) +(global-set-key [remap goto-line] #'consult-goto-line) +(global-set-key [remap imenu] #'consult-imenu) +(bind-key [remap imenu] #'consult-org-heading #'org-mode-map) +(global-set-key [remap info] #'consult-info) +#+end_src + +** Embark: sort of like right click, but better +I've only recently started making use of embark and i definitely need to experiment with it more. Essentially it lets you execute actions based on what kind of thing is selected, either at the point in the buffer, or in an already open completion buffer. + +#+begin_src elisp +(use-package embark :ensure t) +#+end_src + +#+begin_src elisp +(global-set-key (kbd "C-") #'embark-act) +(global-set-key (kbd "C-") #'embark-export) +(global-set-key (kbd "M-.") #'embark-dwim) +#+end_src + +Embark indicators give us visual indication of what embark will do. The minimal indicator puts a message in the echo area. The highlight indicator highlights the region in the buffer that is being acted on. The isearch indicator does the same for when there are multiple regions to be acted on. If we want to see how we can act on the region, we can press C-h. + +#+begin_src elisp +(setopt embark-indicators '(embark-minimal-indicator + embark-highlight-indicator + embark-isearch-highlight-indicator)) +#+end_src + +As mentioned in the vertico configuration above, we can set vertico to use a different layout when completing different things. In this case, we set embark to take control of showing bindings help and of the prefix help, which is pressing C-h after pressing a prefix. Then we ensure we get a grid layout, so that we can see more commands on screen at a time. + +#+begin_src elisp +(global-set-key [remap describe-bindings] #'embark-bindings) +(setopt prefix-help-command #'embark-prefix-help-command) +(add-to-list 'vertico-multiform-categories '(embark-keybinding grid)) +#+end_src + +Because i use consult, it's recommended to have this package installed. + +#+begin_src elisp +(use-package embark-consult :ensure t) +(add-hook 'embark-collect-mode-hook #'consult-preview-at-point-mode) +#+end_src + +** Annotations for completing-read +Marginalia provides us with annotations for candidates in completing read functions. This is things like docstrings for functions, file permissions in find-file, and so on. It's a small quality of life improvement. + +#+begin_src elisp +(use-package marginalia :ensure t) +(setopt marginalia-mode t) +#+end_src + +We want to always show the relative age of a file. By default, files which haven't been modified for more than two weeks will display an absolute date. + +#+begin_src elisp +(setopt marginalia-max-relative-age most-positive-fixnum) +#+end_src + +My keyboard has a tab key and an i key. For legacy reasons, by default emacs converts C-i to mean the same thing as the tab key, but i don't really want that. The tab key is called and it gets translated to TAB. C-i is TAB, but i'd rather it by C-i. That's what this decode line does. + +#+begin_src elisp +(define-key input-decode-map [?\C-i] [C-i]) +#+end_src + +Now that tab and C-i are properly distinguished, i can bind C-i to completion at point. + +#+begin_src elisp +(global-set-key (kbd "") 'completion-at-point) +#+end_src + +I also want to make the completion at point function a bit more friendly than the default, so i ask consult to provide the completion functionality. + +#+begin_src elisp +(setopt completion-in-region-function 'consult-completion-in-region) +#+end_src + +Select the help window so that i can easily close it again with q + +#+begin_src elisp +(setopt help-window-select t) +#+end_src + +#+begin_src elisp +(setopt switch-to-buffer-obey-display-actions t) +#+end_src + +** Org mode + +I thought it would be a good idea to have the ability to set headings in my notes as things i wanted to recall later, as i store most of the things i think about in an org file. I still do think that, but the package isn't in melpa right now and i'm lazy and i'm not in education, so i haven't got around to it yet. + +#+begin_src elisp :tangle no + (use-package org-fc + :disabled + :ensure t + :custom + (org-fc-directories (expand-file-name "~/data/notes/"))) +#+end_src + +If we enable this, emphasis markers will be hidden for a more word processor feel. This has the downside of meaning you have to delete a hidden character to get rid of bold or italic text. I don't have much of a problem with seeing the emphasis markers so i'm willing to put up with any aesthetic shortcomings for a better user experience. The package org-appear solves this by hiding them, but showing them when the point is over them, but i don't think having a whole package just for that is worth it. + +#+begin_src elisp +(setopt org-hide-emphasis-markers nil) +#+end_src + +#+begin_src elisp +(setopt org-startup-with-inline-images t) +(setopt org-image-actual-width '(300)) +(setopt org-auto-align-tags nil) +(setopt org-tags-column 0) +(setopt org-catch-invisible-edits 'show-and-error) +(setopt org-special-ctrl-a/e t) +(setopt org-insert-heading-respect-content t) +(setopt org-ellipsis "…") +(setopt org-display-custom-times t) +(setopt org-time-stamp-custom-formats '("%Y-%m-%d" . "%Y-%m-%d %H:%M")) +(setopt org-extend-today-until 4) +(setopt org-adapt-indentation nil) +(setopt org-log-done 'time) +(setopt org-return-follows-link t) +(setopt org-agenda-files '("~/data/notes/notes.org")) +(setopt org-capture-bookmark nil) +(setopt org-capture-templates '(("j" "Journal" entry (file+olp+datetree "~/data/notes/notes.org") "* %?\n" :empty-lines 1) + ("w" "Website" entry (file+olp+datetree "~/data/notes/notes.org") "* %a\n%?\n" :empty-lines 1) + ("c" "Contact" entry (file+olp+datetree "~/data/notes/notes.org") + "* %^{Name} +:PROPERTIES: +:ADDRESS: %^{Address} +:BIRTHDAY: %^{yyyy-mm-dd} +:EMAIL: %^{EMAIL}p +:NOTE: %^{NOTE} +:END:" + :empty-lines 1) + )) +#+end_src + +#+begin_src elisp + (setopt org-agenda-block-separator nil) + (setopt org-agenda-include-deadlines t) + ;; Always start the weekly agenda for a week from today + (setopt org-agenda-start-on-weekday nil) + ;; Show week of agenda by default + (setopt org-agenda-span 'week) + (setopt org-agenda-prefix-format '((agenda . " %i %?-12t% s") + (todo . " %i ") + (tags . " %i ") + (search . " %i "))) +#+end_src + +The default agenda time grid has thick lines which i don't think add anything to the output. Similarly, the arrow pointing to the current time has a long line which helps me to find it more easily, but by getting rid of the excess of colour and making it bold, i never struggle to find it anyway. + +#+begin_src elisp + (setopt org-agenda-time-grid '((daily today require-timed) + (800 1000 1200 1400 1600 1800 2000) + " " " ")) + (setopt org-agenda-current-time-string "◀ you are here") + (setopt org-support-shift-select 'always) +#+end_src + +#+begin_src elisp + ;; Make org html export more pleasant by default + (setopt org-export-with-smart-quotes t) + (setopt org-export-with-entities nil) + (setopt org-export-headline-levels 5) + (setopt org-export-with-toc nil) + (setopt org-export-section-numbers nil) + (setopt org-html-doctype "html5") + (setopt org-html-html5-fancy t) + (setopt org-html-container-element "section") + (setopt org-html-divs '((preamble "header" "preamble") + (content "main" "content") + (postamble "footer" "postamble"))) + (setopt org-export-with-sub-superscripts t) + (setopt org-html-head-include-default-style nil + org-html-head-include-scripts nil + org-html-validation-link "") +#+end_src + +This doesn't work with code blocks at the moment. + +#+begin_src elisp + (setopt org-html-indent nil) + #+end_src + +#+begin_src elisp +(global-set-key (kbd "C-c c") #'org-capture) +(global-set-key (kbd "C-c a") #'org-agenda) +(global-set-key (kbd "C-c l") #'org-store-link) +#+end_src + +#+begin_src elisp +(use-package helm-org-ql :ensure t) +(use-package org-super-links) +(setopt org-super-links-search-function #'helm-org-ql) +#+end_src + +#+begin_src +(use-package org-modern :ensure t) +(add-hook 'org-mode-hook #'org-modern-mode) +;; (add-hook 'org-agenda-finalize-hook #'org-modern-agenda) +#+end_src + +There are three ways to make bullet lists in org mode, which seems a bit excessive to me. I almost always only use the hyphen, but i like my bullet points to look like bullets, so here i overwrite the hyphen display to show a bullet point. While i'm at it, i overwrite the others too, because they are functionally identical so should probably look the same too. + +#+begin_src elisp +(setopt org-modern-list '((?+ . " • ") + (?- . " • ") + (?* . " • "))) + #+end_src + +This doesn't respect my timestamp custom format configured above. + +#+begin_src elisp +(setopt org-modern-timestamp nil) +#+end_src + +#+begin_src elisp +(setopt org-modern-star nil) +(setopt org-modern-keyword nil) +(setopt org-modern-checkbox '((88 . "☑") + (45 . #("□–" 0 2 + (composition + ((2))))) + (32 . "□"))) +(setopt org-modern-table nil) +#+end_src + +#+begin_src elisp +(setopt org-id-link-to-org-use-id 'create-if-interactive-and-no-custom-id) +#+end_src + +** Website generation + +#+begin_src elisp +(defun read-file-as-string (filename) + "Read file contents from FILENAME." + (with-temp-buffer + (insert-file-contents filename) + (buffer-string))) +#+end_src + +#+begin_src elisp +(setq noa/website-header (read-file-as-string "/home/noa/projects/org-website/templates/header.html")) +(setq noa/website-footer (read-file-as-string "/home/noa/projects/org-website/templates/footer.html")) +#+end_src + +The index page generation functions were taken from Dennis Ogbe. Thank you! + +#+begin_src elisp +(defun my-blog-parse-sitemap-list (l) + "Convert the sitemap list in to a list of filenames." + ;; LIST looks like: + ;; (unordered ("[[file:uses.org][Things i use]]") ("[[file:media.org][Media Diary]]") ("[[file:tanklobsters.org][Tank lobsters]]")) + (mapcar #'(lambda (i) + (let ((link (with-temp-buffer + (let ((org-inhibit-startup nil)) + (insert (car i)) + (org-mode) + (goto-char (point-min)) + (org-element-link-parser))))) + (when link + (plist-get (cadr link) :path)))) + (cdr l))) +#+end_src + +#+begin_src elisp +(defun my-blog-sort-article-list (l p) + "sort the article list anti-chronologically." + (sort l #'(lambda (a b) + (let ((date-a (org-publish-find-date a p)) + (date-b (org-publish-find-date b p))) + (not (time-less-p date-a date-b)))))) +#+end_src + +#+begin_src elisp +(defun noa/naive-org-first-paragraph (file) + "Naively returns the first paragraph of FILE. + + The way that the first paragraph is determined is to assume that there will be an org metadata block beforehand, so look for the first two consecutive newlines and mark the following paragraph." + (with-temp-buffer + (insert-file-contents file) + (goto-char (point-min)) + (re-search-forward "\n\n") + (mark-paragraph) + (let ((beg (mark)) + (end (point))) + (buffer-substring beg end)))) +#+end_src + +#+begin_src elisp +(defun noa/website-sitemap (title list) + "Generate the index page for my website." + ;; LIST looks like: + ;; (unordered ("[[file:uses.org][Things i use]]") ("[[file:media.org][Media Diary]]") ("[[file:tanklobsters.org][Tank lobsters]]")) + (with-temp-buffer + ;; mangle the parsed list given to us into a plain lisp list of files + (let* ((filenames (my-blog-parse-sitemap-list list)) + (project-plist (assoc "website-pages" org-publish-project-alist)) + (articles (my-blog-sort-article-list filenames project-plist))) + (message (concat "PLIST: " (plist-get project-plist :base-directory))) + + (insert "Several parts of this website are broken as i wrangle with the monstrosity that is programming in emacs lisp. The content should still be fine, but for further cosmetics please hold <3\n\n") + (dolist (file filenames) + (let* ((abspath (file-name-concat "/home/noa/data/share" file)) + ;; (abspath (file-name-concat (plist-get project-plist :base-directory) file)) + (relpath (file-relative-name abspath "/home/noa/data/share")) + (title (org-publish-find-title file project-plist)) + (date (format-time-string (car org-time-stamp-formats) (org-publish-find-date file project-plist))) + (preview (noa/naive-org-first-paragraph abspath))) + (insert (concat "* [[file:" relpath "][" title "]]\n")) + (insert (concat + "*" date ":*" + preview)) + (insert "\n"))) + ;; insert a title and save + (insert "#+TITLE: noa.pub\n") + (buffer-string)))) + #+end_src + +#+begin_src elisp +(setq org-publish-project-alist + `(("website" + :components ("website-pages" "website-assets")) + ("website-pages" + :publishing-function org-html-publish-to-html + :base-directory "/home/noa/data/share" + :publishing-directory "/home/noa/projects/org-website" + :base-extension "org" + :with-drawers t + :html-link-home "/" + :html-head-include-default-style nil + :html-head-include-scripts nil + :html-doctype "html5" + ;; :html-validation-link nil + :html-preamble "" + :html-postamble ,noa/website-footer + :html-home/up-format "" + :html-link-up "" + :html-html5-fancy t + :html-indent nil + :html-head "𰻝\">\n +" + :auto-sitemap t + :sitemap-filename "/home/noa/projects/org-website/index.org" + :sitemap-title "noa.pub" + :sitemap-style list + ;; :sitemap-format-entry + :sitemap-function noa/website-sitemap + :sitemap-sort-folders ignore + :sitemap-sort-files anti-chronologically + :sitemap-ignore-case t) + ("website-assets" + :publishing-function org-publish-attachment + :base-directory "/home/noa/data/share" + :publishing-directory "/home/noa/projects/org-website" + :base-extension "css\\|js\\|png|\\jpg" + :recursive t))) +#+end_src + +** Make wide windows narrow with visual-fill-column +Reading prose with long lines is a chore. Luckily there are several packages in emacs to make the windows squeeze text into a more legible sliver. Previously i used olivetti, which is a really nice package, but it's quite heavyweight and broke on me with no explanation more frequently than i appreciated. I've switched to visual-fill-column and been quite satisfied. + +#+begin_src elisp + (use-package visual-fill-column :ensure t) + (setopt visual-fill-column-enable-sensible-window-split t) + (setopt visual-fill-column-center-text t) + (advice-add 'text-scale-adjust :after #'visual-fill-column-adjust) + + (add-hook 'text-mode-hook #'visual-line-fill-column-mode) + (add-hook 'eww-after-render-hook #'visual-line-fill-column-mode) + (add-hook 'nov-post-html-render-hook #'visual-line-fill-column-mode) + (add-hook 'mu4e-view-mode-hook #'visual-line-fill-column-mode) +#+end_src + +The fringes of a window can show useful icons relating to the text in the buffer. For example, when using org modern, blocks get a line in the left fringe to show their content more clearly, Because of this, i prefer for them to be right next to the buffer text. + +#+begin_src elisp + (setopt visual-fill-column-fringes-outside-margins nil) +#+end_src + +Adaptive wrap will indent visually wrapped text to match the indent at the start of the line, for example in lists. This works... fine. However it's adapting the prefix, it doesn't indent nicely with proportional fonts, but you can't win them all. + + ,#+begin_src elisp + (use-package adaptive-wrap :ensure t) + (add-hook 'visual-fill-column-mode-hook #'adaptive-wrap-prefix-mode) +#+end_src + +** Find file at point +#+begin_src elisp +(setopt ffap-file-name-with-spaces t) +(global-set-key [remap find-file] #'find-file-at-point) +(global-set-key [remap dired] #'dired-at-point) +#+end_src + +** Web browsing in emacs +I hear it's now possible to run a full fat browser inside emacs. But this is surely quite heavyweight, and doesn't get to take advantage of things like ublock origin. When it comes to alternative browsers, it's always the same story; i like the concept, but most websites are a horrific experience without a good ad blocker. + +Instead, i use eww, a browser more closely aligned with browsers for the terminal. Despite the name, eww is a delight to use for text-heavy websites. If a website doesn't render well in it, because it uses fancy layout tricks or lots of javascript, we can press ~&~ to open the url in firefox. + +#+begin_src elisp + (setopt browse-url-browser-function 'eww-browse-url + browse-url-secondary-browser-function 'browse-url-default-browser) +#+end_src + +For the kind of sites i use eww to visit, i've not had a use for cookies. We can tell emacs that we don't trust cookies from any sites, we don't trust cookies from all sites, and frankly, we don't want to use cookies. + +#+begin_src elisp + (setopt url-cookie-trusted-urls '() + url-cookie-untrusted-urls '(".*") + shr-cookie-policy nil) +#+end_src + +Eww has rudimentary support for colours. But i don't want web pages to be able to specify their own colours, because i like the colours i already have set. + +#+begin_src elisp + (setopt shr-use-colors nil) + (setopt shr-max-width nil) +#+end_src + +We can set what the maximum size of an image in a window should be. This is a fraction of the total window width or height, and if the image would be bigger than this, it'll be resized to fit. It's useful to have it smaller because emacs still sort of chokes on scrolling when there are large images in a buffer. This is the default value of this option. + +#+begin_src elisp + (setopt shr-max-image-proportion 0.9 + shr-discard-aria-hidden t) + #+end_src + +The default name for the eww buffer is *eww*. This is unhelpful because it makes having more than one eww buffer open a bit of a chore to navigate. We can set it to 'url, 'title, or a function. I set it to 'title because marginalia already shows me the url. However, this means that i can't search for a url name when switching buffers. See the help for this variable for an example of a function which gives the page title and the url. + +#+begin_src elisp +(setopt eww-auto-rename-buffer 'title) +#+end_src + +Goto address mode makes urls and email address in a buffer clickable. I want these clickable links to look like links, because that's what they are. The two mouse face variables are what face is used on hover, which at the moment i ignore. It might also be worth setting them to 'highlight. + +#+begin_src elisp +(setopt global-goto-address-mode t) +(setopt goto-address-mail-face 'link) +(setopt goto-address-mail-mouse-face 'highlight) +(setopt goto-address-url-face 'link) +(setopt goto-address-url-mouse-face 'highlight) +#+end_src + +Abbrev mode expands one string into another string. I use it as a simple autocorrect mode. If i misspell a word, i run C-x a i g which will prompt me for what to expand the previous word into. I type the correct spelling, and whenever i make that mistake again, it will automatically be corrected. It's important to be careful not to set something that could be a typo for two words though, because otherwise it gets even more annoying. Luckily it's easy to update the abbrevs which are stored in ~/.config/emacs/abbrev_defs. M-x list-abbrevs is also a nice command which shows all the saved abbrevs and how many times they've been expanded. + +#+begin_src elisp +(add-hook 'text-mode-hook #'abbrev-mode) +#+end_src + +#+begin_src elisp +(setopt global-eldoc-mode t) +#+end_src + +Use a bar cursor and blink it and don't stop blinking it. i don't know how i feel about this yet to be honest, but it helps me know which window is active so for now i'm keeping it + +#+begin_src elisp +(setopt + cursor-type 'bar + blink-cursor-mode -1 + blink-cursor-interval 0.7) +#+end_src + +** Dired +Dired is a really nice package which, as with a lot of emacs, has some dodgy defaults. Here we round off some of the sharp edges to make it more enjoyable to use. + +By default, dired permanently deletes files. But i have quite a bit of storage and also make bad decisions regularly, so it seems fitting to make use of the wonderful invention that is the trash. People who have used systems from the last forty years or so will likely be familiar with this innovation. + +#+begin_src elisp +(setopt delete-by-moving-to-trash t) +#+end_src + +It's not fun to be asked every time whether we want to delete a directory recursively. It's an understandable default for safety reasons, but because we are not deleting permanently but rather just moving to the trash, it's not such a concern. + +#+begin_src elisp +(setopt dired-recursive-deletes 'always) +#+end_src + +Recursive copying isn't even destructive, so i definitely don't want to be asked about that. + +#+begin_src elisp +(setopt dired-recursive-copies 'always) +#+end_src + +After we delete some files or directories, it makes sense to get rid of any buffers which are looking at those files or directories. + +#+begin_src elisp +(setopt dired-clean-up-buffers-too nil) +#+end_src + +With this set, if we have two dired buffers open next to one another, a rename operation in one will default to the directory shown in the other. In this way, we can pretend we are using some kind of norton commander like file browser instead of slumming it in emacs. + +#+begin_src elisp +(setopt dired-dwim-target t) +#+end_src + +These are some useful ls switches. We have to keep -l. To show dotfiles as well, we use -a. To sort numbers by number order instead of lumping together ones, twos, and so on, we use -v. Because we don't have colour, it's nice to have a clear indicator of what is a file and what is a directory, as well as other different things like symlinks which i never remember. By using -F, a forward slash is appended to every directory. And to get more easily understandable file sizes, we use -h, which will tell us the file size in kilobytes or megabytes rather than a huge number that means nothing to me. I won't explain the meaning of the long flag. + +#+begin_src elisp +(setopt dired-listing-switches "-alvFh --group-directories-first") +#+end_src + +By default, don't show dired details + +#+begin_src elisp +(add-hook 'dired-mode-hook #'dired-hide-details-mode) +#+end_src + +I find it useful to see the recursive sizes of directories. This can be a little slow, so setting it as always on might not be the best idea, but the longest i've had to wait is about a second, and that's only if i run it on my home directory, so i think it's worth it at the moment. + +#+begin_src elisp +(use-package dired-du :ensure t) +(setopt dired-du-size-format t) +(add-hook 'dired-mode-hook #'dired-du-mode) +#+end_src + +** Indentation: tabs and whitespace settings + +In general, my rules for inserting tabs are that the tab key should insert tabs. I personally prefer tabs to spaces, because tabs work reasonably well whatever font or tab width one chooses to set, whereas spaces are the same width for everyone, except when someone uses a proportional font in which case they are narrower than expected. Furthermore, people tend to use spaces for alignment, which looks bad when you can't rely on every character being the same width. + +However, i'm in the minority, and fighting with the very complicated emacs indentation systems is simply not fun. That said, i refuse to use a monospaced font. Luckily the minority is more than one and someone has already done the hard work for me of writing a mode to make spaces for indentation work reasonably well with a proportional font. That mode is elastic-indent-mode, and it very simply makes leading whitespace characters the same width as the characters on the line above. It's a simple solution but most of the time it does what i want. + +#+begin_src elisp +(require 'elastic-indent) +(add-hook 'prog-mode-hook #'elastic-indent-mode) +#+end_src + +Previously i used a function to naïvely copy the whitespace from the line above. This is the way that vi, nano, and acme all implement auto-indentation. However, for now i'm experimenting with using the built-in indentation functions again. I'm leaving this defun here for posterity. + +#+begin_src elisp :tangle no +(defun noa/naive-return-and-indent () + "Insert a newline and copy the indentation of the previous line, vi/nano style." + (interactive) + (open-line 1) + (let* ((start (progn (beginning-of-line) (point))) + (indent (progn (back-to-indentation) (point))) + (end (progn (end-of-line) (point))) + (whitespace (buffer-substring start indent))) + (delete-trailing-whitespace start end) + (beginning-of-line 2) + (insert whitespace))) +#+end_src + +We will only be trying to indent at the start of a line, and sometimes we will want to insert a standard tab character. We can also set this option to 'complete, which will run completion at point if the region is already indented. + +#+begin_src elisp +(setopt tab-always-indent nil) +#+end_src + +Usually, we want indentation to be done with tabs. Some modes make more sense to use spaces to indent. Lisp is a particular example, and emacs's default behaviour of converting tabs into spaces is frankly horrific. I've taken the below code from acdw to use spaces in these modes. + +#+begin_src elisp +(defvar space-indent-modes '(emacs-lisp-mode + lisp-interaction-mode + lisp-mode + scheme-mode + python-mode) + "Modes to indent with spaces, not tabs.") +(add-hook 'prog-mode-hook + (defun indent-tabs-mode-maybe () + (setq indent-tabs-mode + (if (apply #'derived-mode-p space-indent-modes) nil t)))) +#+end_src + +I want to ensure that indentation is always correct. The builtin electric indent mode works /sometimes/, but the aggressive indent mode package is more reliable. + +#+begin_src elisp +(use-package aggressive-indent :ensure t) +(setopt global-aggressive-indent-mode t) +#+end_src + +** Interface +I want to make sure that various bits of the interface are hidden. but this isn't an "all gui chrome is useless" rampage. I personally think the scrollbar is useful, i like the visual indication it gives of how far i am through a file. + +At the moment, explicitly disabling the menu bar and tool bar does nothing, because i already set there to be no lines displayed for the tool and menu bars in my early-init.el file. + +#+begin_src elisp :tangle no + (setopt menu-bar-mode nil + tool-bar-mode nil) +#+end_src + +Tooltips are little popups next to the mouse cursor. I think this information is helpful, but i like it to appear in a more consistent position, because i find it frustrating when popups cover parts of the ui that i wanted to see. By disabling tooltip-mode, the contents that would be in a popup is instead shown in the echo area. + +#+begin_src elisp +(setopt tooltip-mode nil) +#+end_src + +I see no reason not to immediately show which chords in a key sequence i have already pressed. Emacs does, however, and instead of letting me set the value of echo-keystrokes to zero to wait zero seconds to show that information, it repurposes zero as a method of disabling the functionality altogether, and provides no special functionality for setting it to nil that would explain why that's not an acceptable method of disabling a feature. Instead, i have to deal with setting it to nearly zero, and luckily i can't tell the difference. + +#+begin_src elisp +(setopt echo-keystrokes 0.1) +#+end_src + +A useful feature when programming is to show matching parentheses. Show-paren-mode is a global mode. By default it runs in all buffers except those inheriting from special mode. + +#+begin_src elisp +(setopt show-paren-mode t) +#+end_src + +This variable means that if there is no non-whitespace character in between the point and the paren, it will be highlighted. It's useful to highlight parentheses if the point is at the start of the line and the paren is indented. + +#+begin_src elisp +(setopt show-paren-when-point-in-periphery t) +#+end_src + +By default, the point has to be after a paren for it to be highlighted. But often the point will be just inside, in which case it's also helpful for the pair to be highlighted. + +#+begin_src elisp +(setopt show-paren-when-point-inside-paren t) +#+end_src + +#+begin_src elisp +(setopt tab-bar-mode t) +(setopt tab-bar-format '(tab-bar-format-menu-bar + tab-bar-format-align-right + tab-bar-format-global)) +#+end_src + +#+begin_src elisp +(setopt global-font-lock-mode t) +(setopt font-lock-maximum-decoration nil) +#+end_src + +#+begin_src elisp + (setopt inhibit-startup-screen t + mouse-drag-and-drop-region nil + mouse-yank-at-point t + ;; deleting should be an explicit action + delete-selection-mode nil) +#+end_src + +#+begin_src elisp +(global-set-key (kbd "C-t") 'tab-new) +#+end_src + +Shift click to select region with the mouse. This annoyingly rings the bell for an error. It also interferes with my input method switcher, which doesn't notice the mouse click and thinks i've pressed shift with no other keys. + +#+begin_src elisp +(global-unset-key (kbd "S-")) +(global-set-key (kbd "S-") 'mouse-save-then-kill) +#+end_src + +** packages +#+begin_src elisp +(setopt package-archives + '(("gnu" . "https://elpa.gnu.org/packages/") + ("nongnu" . "https://elpa.nongnu.org/nongnu/") + ("melpa-stable" . "https://stable.melpa.org/packages/") + ("melpa" . "https://melpa.org/packages/"))) +#+end_src + +** saving +Backups are pointless in long emacs sessions imo, but autosaves are useful. + +#+begin_src elisp +(setopt remote-file-name-inhibit-auto-save t) +(setopt remote-file-name-inhibit-auto-save-visited t) +(setopt make-backup-files nil + backup-by-copying t + create-lockfiles nil + auto-save-mode 1 + auto-save-interval 6 ;; every six keystrokes + auto-save-timeout 5 ;; every 5 seconds + auto-save-default t + auto-save-no-message t + save-silently t + version-control t + ;; this will auto save to the current file + auto-save-visited-mode t) +(add-hook 'focus-out-hook (lambda () (interactive) (save-some-buffers t))) +(add-hook 'mouse-leave-buffer-hook (lambda () (interactive) (save-some-buffers t))) +#+end_src + +** Keyfreq +Previously i had keyfreq enabled, because i think it's a nice feature to be able to see what commands i'm using most frequently. But i ran into an issue where it would permanently hang my emacs trying to save, so i've disabled it. + +#+begin_src elisp :tangle no +(use-package keyfreq :ensure t) +(setopt keyfreq-mode t) +(setopt keyfreq-autosave-mode t) +(setopt keyfreq-excluded-regexp (rx (or "pixel-scroll-precision"))) +#+end_src + +C-l goes in order +#+begin_src elisp +(setopt recenter-positions '(top middle bottom)) +#+end_src + +Emacs uses choppy scrolling by default. If i scoll with my trackpad, it's nice to have it move tiny amounts at the same time as my fingers, which pixel-scroll-precision-mode allows for. This also has the benefit of making scrolling over images a little bit of a nicer experience. + +#+begin_src elisp +(setopt pixel-scroll-precision-mode t + pixel-scroll-precision-use-momentum t) +#+end_src + +** Smart scan +This is a nice package to easily jump between identical things at point, like the * operator in vim. I disabled it because i'm trying out using the same keybindings to jump between compile mode errors. + +#+begin_src elisp :tangle no + (use-package smartscan) + (global-set-key (kbd "M-n") #'smartscan-symbol-go-forward) + (global-set-key (kbd "M-p") #'smartscan-symbol-go-backward) + (global-set-key (kbd "M-n") #'next-error) + (global-set-key (kbd "M-p") #'previous-error) +#+end_src + +** Sentences +I prefer to double space sentences. But it seems that most other people do not, and the sentence navigation commands still work for my sentences with this set to nil, but don't work for other people's with it set to t. There are of course some little errors with this, like ending a title with a full stop, but for the most part it's fine. + +#+begin_src elisp +(setopt sentence-end-double-space nil) +#+end_src + +If i write a script, i will always run chmod +x after saving it. This command means i don't have to do that. + +#+begin_src elisp +(add-hook 'after-save-hook #'executable-make-buffer-file-executable-if-script-p) +#+end_src + +We are on a unix system, so it makes sense to end files in the unix system way. I'm surprised this isn't the default. + +#+begin_src elisp +(setopt require-final-newline t) +#+end_src + +#+begin_src elisp +(setopt window-min-height 1 + window-combination-resize t + window-resize-pixelwise t + frame-resize-pixelwise t) +#+end_src elisp + +** history +#+begin_src elisp +(setopt history-length 250 + kill-ring-max 25) +#+end_src + +#+begin_src elisp +(setopt savehist-file "~/.config/emacs/savehist") +(setopt savehist-additional-variables + '(kill-ring + command-history + set-variable-value-history + custom-variable-history + query-replace-history + read-expression-history + minibuffer-history + read-char-history + face-name-history + bookmark-history + file-name-history)) +(setopt savehist-mode t) +#+end_src + +#+begin_src elisp +(setopt window-divider-mode t) +(setopt window-divider-default-right-width 1) +(setopt window-divider-default-bottom-width 1) +(setopt window-divider-default-places t) +#+end_src + +Taken from configuration for the vertico stack: +Add prompt indicator to `completing-read-multiple'. +We display [CRM], e.g., [CRM,] if the separator is a comma. +#+begin_src elisp +(defun crm-indicator (args) + (cons (format "[CRM%s] %s" + (replace-regexp-in-string + "\\`\\[.*?]\\*\\|\\[.*?]\\*\\'" "" + crm-separator) + (car args)) + (cdr args))) +(advice-add #'completing-read-multiple :filter-args #'crm-indicator) +#+end_src + +Do not allow the cursor in the minibuffer prompt + +#+begin_src elisp +(setopt minibuffer-prompt-properties + '(read-only t cursor-intangible t face minibuffer-prompt)) +(add-hook 'minibuffer-setup-hook #'cursor-intangible-mode) +(setopt display-battery-mode t) +(setopt display-time-default-load-average nil) +(setopt display-time-24hr-format t) +(setopt display-time-mode t) +#+end_src + +Support opening new minibuffers from inside existing minibuffers. + +#+begin_src elisp +(setopt enable-recursive-minibuffers t) +(setopt debug-on-error t) +#+end_src + +Hide commands in M-x which do not work in the current mode. + +#+begin_src elisp +(setopt read-extended-command-predicate 'command-completion-default-include-p) +#+end_src + +#+begin_src elisp +(setopt recentf-max-menu-items 25 + recentf-save-file "~/.config/emacs/recentf" + recentf-mode 1 + bookmark-default-file "~/.config/emacs/bookmarks") +#+end_src + +** Miscellaneous + +#+begin_src elisp +(setopt save-place-mode 1) +#+end_src + +#+begin_src elisp +(setenv "PAGER" "cat") +(setenv "TERM" "dumb") +(setenv "NO_COLOR") +(setenv "GPG_AGENT_INFO" nil) +#+end_src + +The former means that when given a list of choices, we can use single character abbreviations to answer. The latter is a fancy way of defaliasing yes-or-no-p to y-or-n-p. + +#+begin_src elisp +(setopt read-answer-short t) +(setopt use-short-answers t) +#+end_src + +#+begin_src elisp +(setq disabled-command-function nil) +(setopt custom-file (make-temp-file "custom")) +(setq inhibit-startup-echo-area-message "noa") ;; #userfreedom +#+end_src + +#+begin_src elisp +(setopt + uniquify-after-kill-buffer-p t + uniquify-buffer-name-style 'forward + uniquify-ignore-buffers-re "^\\*" + uniquify-separator "/") +#+end_src + +#+begin_src elisp +(setopt + save-interprogram-paste-before-kill t + mouse-yank-at-point t + require-final-newline t + visible-bell t + load-prefer-newer t + ediff-window-setup-function 'ediff-setup-windows-plain) +#+end_src + +#+begin_src elisp :tangle no +(unless (server-running-p) (server-start))) +#+end_src + +#+begin_src elisp +(setopt help-at-pt-display-when-idle t) +#+end_src + +** Search in buffer +Isearch is good, but it has some rough edges. The easiest way forward was just to use ctrlf, which fixes most of them. But i still had some gripes with ctrlf, like that it doesn't play well with a lot of other commands and packages and the general ecosystem built around isearch. So i've tried to fix as many of the issues as i can while keeping real isearch. + +It makes more sense to go to the start of the match, because i start searching where i want to be. + +#+begin_src elisp +(defun isearch-exit-at-front () + "always exit isearch, at the front of search match." + (interactive) + (isearch-exit) + (when isearch-forward + (goto-char isearch-other-end))) +(defun isearch-exit-at-end () + "Always exit isearch, at the end of search match." + (interactive) + (isearch-exit) + (when (not isearch-forward) + (goto-char isearch-other-end))) +#+end_src + +This seemed necessary to use with isearch-mb, but in fact i think i'd just broken something else. + +#+begin_src elisp +;; (setopt search-nonincremental-instead nil) +#+end_src + +My preferred behaviour is for the point to be at the start of the match. Because the search is incremental, usually i won't finish typing something useful before exiting the search, but i always start searching at a place i can reason about. However, i can't figure out how to get this to work along with isearch-mb + +#+begin_src elisp +;; (define-key isearch-mb-minibuffer-map (kbd "") #'isearch-exit-at-front) +;; (define-key isearch-mb-minibuffer-map (kbd "C-") #'isearch-exit-at-end) +;; Make isearch always quit on C-g +(define-key isearch-mode-map (kbd "C-g") #'isearch-cancel) +(define-key isearch-mode-map (kbd "C-o") #'isearch-occur) +(setopt search-whitespace-regexp ".*?") +(setopt isearch-lax-whitespace t) +(setopt isearch-lazy-count t) +(setopt isearch-allow-motion t) +(setopt isearch-repeat-on-direction-change t) +(setopt isearch-wrap-pause 'no) +#+end_src + +Okay, i lied about being vanilla. I want isearch to use the minibuffer like a good normal part of emacs + +#+begin_src elisp +(use-package isearch-mb :ensure t) +(setopt isearch-mb-mode t) +#+end_src + +#+begin_src elisp +(global-set-key (kbd "M-o") 'other-window) +(global-set-key (kbd "C-x k") 'kill-this-buffer) +#+end_src + + +Undo is on C-/ and redo is on C-S-/. It's not standard, but these bindings are easier to remember. And with this setting, it behaves for the most part like undo in other programs, which isn't as good as i'd really want, but is something i can reason about much more easily than the default undo. + +#+begin_src elisp +(setopt undo-no-redo t) +#+end_src + +** Email: mu4e +#+begin_src elisp +(setopt mu4e-headers-skip-duplicates t) +(setopt mu4e-view-show-images t) +(setopt mu4e-view-show-addresses t) +#+end_src + +In theory i like format flowed, but what i like even more is just not hard wrapping messages and dealing with hacks to get around that to begin with. If software supported soft wrapping at an arbitrary column, the world would be a better place. + +#+begin_src elisp +(setopt mu4e-compose-format-flowed nil) +(setopt mu4e-change-filenames-when-moving t) +(setopt mu4e-use-fancy-chars nil) +(setopt mu4e-confirm-quit nil) +(setopt mu4e-headers-leave-behavior 'apply) +(setopt mu4e-headers-precise-alignment t) +(setopt mu4e-headers-fields '((:flags . 6) + (:from . 32) + (:subject))) +(setopt mu4e-search-threads nil) +(setopt mu4e-hide-index-messages t) +(setopt mu4e-get-mail-command "mbsync -c ~/.config/mbsyncrc fastmail") +(setopt mu4e-maildir "~/mail") +(setopt mu4e-drafts-folder "/Drafts") +(setopt mu4e-sent-folder "/Sent") +(setopt mu4e-refile-folder "/Archive") +(setopt mu4e-trash-folder "/Trash") +(setopt mu4e-bookmarks '((:name "Inbox" :query "maildir:/Inbox" :key ?i) + (:name "Feeds" :query "maildir:/Feeds" :key ?f) + (:name "Paper trail" :query "\"maildir:/Paper trail\"" :key ?p))) +#+end_src + +function to move mails to trash + +#+begin_src elisp +(with-eval-after-load 'mu4e + (bind-key (kbd "d") #'noa/move-to-trash 'mu4e-headers-mode-map) + (bind-key (kbd "d") #'noa/move-to-trash 'mu4e-view-mode-map) + (fset 'noa/move-to-trash "mTrash")) +#+end_src + +The first string is for when fancy characters are disabled, and the second is for when they are enabled. But i set them all manually because some of the other characters are ugly in fancy mode, but i like my unicode thread icons. + +#+begin_src elisp +(setq mu4e-headers-thread-connection-prefix '("│ " . "│ ") + mu4e-headers-thread-last-child-prefix '("└ " . "└ ") + mu4e-headers-thread-blank-prefix '(" " . " ") + mu4e-headers-thread-root-prefix '("□ " . "□ ") + mu4e-headers-thread-child-prefix '("│ " . "│ ") + mu4e-headers-thread-orphan-prefix '("♢ " . "♢ ") + mu4e-headers-thread-duplicate-prefix '("≡ " . "≡ ") + mu4e-headers-thread-first-child-prefix '("⚬ " . "⚬ ") + mu4e-headers-thread-single-orphan-prefix '("♢ " . "♢ ")) +#+end_src + +Setting this to nil stops auto-fill from being automatically enabled in message buffers. + +#+begin_src elisp +(setopt message-fill-column nil) +#+end_src + +I set an email signature. I could put this outside of the configuration in a file referenced by message-signature-file, but for now i just keep it inline. + +#+begin_src elisp +(setopt message-signature "~noa (https://noa.pub) + • I try to reply to formal emails in three sentences or fewer; excuse my brevity. + • I queue replies and batch send them at intervals; excuse my untimeliness.") +#+end_src + +** More miscellaneous + +#+begin_src elisp +(global-set-key (kbd "M-z") 'zap-up-to-char) +#+end_src + +#+begin_src elisp +(use-package markdown-mode + :ensure t + :mode ("\\.md\\'" . markdown-mode)) +#+end_src + +#+begin_src elisp +(use-package valign + :ensure t + :hook (markdown-mode . valign-mode) + :hook (org-mode . valign-mode) + :custom + (valign-fancy-bar t) + (valign-max-table-size 0)) +#+end_src + +This is my own version of fixed-pitch, which has some changes to it. No hooks are added by default. Updating the whitelist automatically applies the hooks. And there is no functionality for changing the cursor type. + +#+begin_src elisp +(use-package fixed-pitch) +(setopt fixed-pitch-whitelist-hooks '(calendar-mode-hook + dired-mode-hook + ibuffer-mode-hook + magit-mode-hook + profiler-report-mode-hook + jabber-roster-mode-hook + mu4e-headers-mode-hook)) + #+end_src + +While we're at it, ensure that transients look nice with a variable pitch font. + +#+begin_src elisp +(setopt transient-align-variable-pitch t) +#+end_src + +** Fonts +My current favourite font is sn pro, which feels like comic sans for grown ups. It's friendly but consistent and well thought out. However, it's also a proportional font, which obviously is the right way to do things, but emacs is very old and comes from a time before the innovation of legibility. As a result, there are some things that require a monospaced font, so i set one here. I chose go mono for two reasons: the first is because i think it looks really nice; the second is because it has serifs and is very visually distinct from sn pro, so i can notice and shame those buffers which require a fixed width font to operate properly. + +#+begin_src elisp +(custom-set-faces + '(fixed-pitch ((t (:family "Go Mono" :height 110)))) + '(variable-pitch ((t (:family "SN Pro" :height 110))))) +#+end_src + +For some frustrating reason, emacs does not respect fontconfig font settings. What this means in practice is that emacs by default draws cjk characters with the korean variant. Luckily emacs has its own obscure and poorly documented way of doing things, so i can iterate over the relevant charsets and set the font specifically for those characters. + +#+begin_src elisp +(dolist (charset '(han cjk-misc)) + (set-fontset-font t charset (font-spec :family "Noto Sans CJK SC"))) +#+end_src + +Similar to the above, we have to manually set the font we want to be used for emoji. I like the cute style of the emoji in fsd emoji, but it doesn't have very good coverage, so we also set noto emoji as the backup. Note that noto emoji is not the same as noto color emoji, which uses coloured emoji. That's clearly against the vibe of this emacs! + +#+begin_src elisp +(set-fontset-font t 'emoji (font-spec :family "FSD Emoji") nil 'prepend) +(set-fontset-font t 'emoji (font-spec :family "Noto Emoji") nil 'append) +#+end_src + +While we're here, let's set up emoji input. + +#+begin_src elisp +(use-package cape :ensure t) +(add-to-list 'vertico-multiform-categories + '(cape-emoji grid indexed (vertico-grid-annotate . 6))) +(global-set-key (kbd "C-.") #'cape-emoji) +#+end_src + +Describe a key based on a string like "C-SPC" + +#+begin_src elisp +(defun describe-key-shortcut (shortcut) + (interactive "MShortcut: ") + (describe-key (kbd shortcut))) +#+end_src + +Update the calendar. We want weeks to start on a monday, the first day of the week. Holidays should be highlighted, and the date format should put the year first. + +#+begin_src elisp +(setopt calendar-week-start-day 1 + calendar-mark-holidays-flag t + calendar-date-style 'iso) +#+end_src + +Multiple cursors are a nice feature because they are very interactive. However, i've always found the emacs implementation a bit too janky. Iedit implements one case where multiple cursors are used, which is to put a cursor at every same symbol in the buffer and edit them all, sort of like a real-time query-replace. + +#+begin_src elisp +(use-package iedit :ensure t) +#+end_src + +** Replace +Anzu provides real-time updates to the replacement string when running query-replace. + +#+begin_src elisp +(use-package anzu :ensure t) +(global-set-key [remap query-replace] 'anzu-query-replace) +(global-set-key [remap query-replace-regexp] 'anzu-query-replace-regexp) +#+end_src + +My computer has a small screen, so i find that it's more beneficial for me to split the frame into columns, so i get more context. However, splitting in this way only gives me a (window-width) of 61, so emacs will always split into vertically stacked windows. By setting this to 80, the first split should always be vertical. + +#+begin_src elisp +(setopt split-width-threshold 80) +#+end_src + +Define a handy function that allows me to do a full text search of every file in my home directory. For the most part, this works well; ripgrep avoids binary files. However, in some files with embedded images, it can add a lot of junk to the output. + +#+begin_src elisp +(defun noa/consult-rg-home () + (interactive) + (consult-ripgrep "~/")) +(global-set-key (kbd "") #'noa/consult-rg-home) +#+end_src + +#+begin_src elisp +(setopt shell-file-name "/bin/sh") +#+end_src + +#+begin_src elisp +(defun snarf-song (url) + (interactive "sYoutube url:") + (async-shell-command + (concat "yt-dlp -x --audio-format=mp3 -o " + (shell-quote-argument "~/media/music/%(title)s [%(id)s].%(ext)s") + " " + (shell-quote-argument url)))) +#+end_src + +Put a quote in the scratch buffer + +#+begin_src elisp +(setopt cookie-file "~/data/quotes") +(setopt initial-scratch-message + (concat (with-temp-buffer + (emacs-lisp-mode) + (insert (cookie cookie-file)) + (mark-whole-buffer) + (comment-region (mark) (point)) + (buffer-substring (mark) (point))) + "\n\n")) +#+end_src + +** Eshell +Eshell is a command shell written in elisp. It integrates with emacs in a more consistent manner than the other shells available, although it still has its own quirks. + +In general, i try and avoid using a shell if possible, because i think that bespoke emacs interfaces to different commands tend to have more pleasant interaction methods. But there are still lots of things which are simply easier to do with a shell. + +*** Set the eshell banner +This is equivalent to the message of the day present in some shells. I wanted it to print a new quote every time eshell opened, but when i tried that eshell refused to load. Probably some mistake on my end. + +#+begin_src elisp +(defun noa/eshell-banner-message () + (concat (cookie cookie-file) + "\n\n")) +(setopt eshell-banner-message (noa/eshell-banner-message)) +#+end_src + +** i-ching +I don't know why but it seems cool + +#+begin_src elisp +(use-package i-ching :ensure t) +#+end_src + +** Unfill commands + +#+begin_src elisp +(defun unfill-paragraph () + "Takes a multi-line paragraph and makes it into a single line of text." + (interactive) + (let ((fill-column (point-max))) + (fill-paragraph nil))) +(global-set-key (kbd "M-Q") #'unfill-paragraph) +#+end_src + +The following functions were written by acdw for use with buffers like dict and help, where it's often ugly to read them with their hard wrapping + +#+begin_src elisp +;; unfill/refill a buffer + +;; unfill makes all paragraphs 1 line +(defun unfill-region (beg end) + (let ((fill-column most-positive-fixnum)) + (fill-region beg end))) + +;; this command is what you'd run in a hook +;; visual-line-mode makes it so it doesn't look shit +(defun unfill-buffer-force () + (interactive) + (let ((buffer-read-only nil)) + (unfill-region (point-min) (point-max)) + (visual-line-mode))) + +;; refill makes the width equal to the window-width minus 2 +;; (you could change it ofc) +(defun refill-region (beg end) + (let ((fill-column (- (window-width) 2))) + (fill-region beg end))) + +;; this command is what you'd run in a hook or w/e +(defun refill-buffer-force () + (interactive) + (let ((buffer-read-only nil)) + (refill-region (point-min) (point-max)))) +#+end_src + +** Pass(1) +The auth-source library allows packages to request password information. It has a password store backend, which is nicer to work with than netrc files. + +#+begin_src elisp +(require 'auth-source-pass) +(add-to-list 'auth-sources 'password-store) +(auth-source-forget-all-cached) +#+end_src + +#+begin_src elisp +(setopt confirm-kill-emacs 'y-or-n-p) +#+end_src + +#+begin_src elisp +(global-set-key (kbd "C-=") #'calc) +#+end_src diff --git a/emacs/early-init.el b/emacs/early-init.el deleted file mode 100644 index 5ba6898..0000000 --- a/emacs/early-init.el +++ /dev/null @@ -1,41 +0,0 @@ -;;; early-init.el -*- lexical-binding: t; -*- - -;; Emacs 27+ introduces early-init.el, which is run before init.el, -;; before package and UI initialization happens. - -;; Defer garbage collection further back in the startup process -(setq - gc-cons-threshold most-positive-fixnum - gc-cons-percentage 0.6 - - ;; In noninteractive sessions, prioritize non-byte-compiled source files to prevent the use of stale byte-code. Otherwise, it saves us a little IO time to skip the mtime checks on every *.elc file. - load-prefer-newer 'noninteractive - native-comp-jit-compilation nil - - ;; is this a bad idea? - site-run-file nil - inhibit-default-init t - - ;; In Emacs 27+, package initialization occurs before `user-init-file' is loaded, but after `early-init-file'. - ;; package-enable-at-startup nil - - ;; `use-package' is builtin since 29. It must be set before loading `use-package'. - use-package-enable-imenu-support t - - ;; Disable built-in mode-line because we have own config - ;; mode-line-format nil - - ;; Gui changes are expensive - frame-inhibit-implied-resize t - default-frame-alist '( - (fullscreen . maximized) - (font . "SN Pro-13") - (menu-bar-lines . 0) - (tool-bar-lines . 0) - ;; (vertical-scroll-bars . nil) - ) - - ) - -;; Ignore X resources; its settings would be redundant with the other settings in this file and can conflict with later config (particularly where the cursor color is concerned). -(advice-add #'x-apply-session-resources :override #'ignore) diff --git a/emacs/init.el b/emacs/init.el deleted file mode 100644 index 523c947..0000000 --- a/emacs/init.el +++ /dev/null @@ -1,1007 +0,0 @@ -;;; init.el --- my emacs configuration -*- lexical-binding: t; -*- - -(add-to-list 'load-path (expand-file-name (concat user-emacs-directory "site-lisp"))) - -(setq garbage-collection-messages t) -(add-hook 'emacs-startup-hook - #'(lambda () - (message (format "Initialised in %s seconds with %s garbage collections." (emacs-init-time) gcs-done)) - ;;; reset garbage collector - (setq - gc-cons-threshold 800000 - gc-cons-percentage 0.2))) - -(setopt user-mail-address "noa@gaiwan.org") - -;; properly distinguish these chords from their ascii legacy -(define-key input-decode-map [?\C-m] [C-m]) - -(require 'tubthumping-theme) -(load-theme 'tubthumping t) - -;; I make my caps lock a menu key, so i can open the command palette with it -(define-key context-menu-mode-map (kbd "") nil) -(global-unset-key (kbd "M-x")) -(global-set-key (kbd "") 'execute-extended-command) - -(setopt minibuffer-depth-indicate-mode t) - -;;; Minibuffer candidate completion - -;; Vertico is a package for a nice minibuffer completion experience. It displays a vertical list of candidates. It integrates well with the emacs ecosystem and lets me use other packages that also play nicely. -(use-package vertico :ensure t) -(setopt vertico-mode t) - -;; We want vertico to take up a maximum of 12 lines on the display. My screen is quite small, so that's fine, but if i had a bigger screen, i might want to look into setting a percentage or increasing this. -(setopt vertico-count 12) - -(setopt vertico-group-format #("%s " 0 3 (face vertico-group-title))) - - -;; We also want to be able to jump to the bottom of the list by moving up from the top of the list, and the opposite. I've rarely made use of this functionality and i don't know if it's actually a best practice from an interaction perspective, but i'm going to keep it on until it causes an issue for me. -(setopt vertico-cycle t) - -;; Multiform mode will allow us to set different layouts for different completion categories. For example, after pressing a prefix key, i can press C-h to view a list of all possible following keys. For this, i want vertico to display a grid of choices, rather than one completion per line. -(setopt vertico-multiform-mode t) - -;; And of course, i want to be able to interact with vertico with the mouse. -(setopt vertico-mouse-mode t) - -;; When completing a filename, i want to be able to easily delete directories in one fell swoop, instead of character by character or word by word. Usually C- would be fine, but if directories have a hyphen or space in their name, i have to press multiple times, which is almost never desirable. -(bind-key (kbd "RET") #'vertico-directory-enter 'vertico-map) -(bind-key (kbd "") #'vertico-directory-delete-char 'vertico-map) -(bind-key (kbd "") #'vertico-directory-delete-word 'vertico-map) - -;; If i type ~/ etc in a find-file prompt, get rid of the preceding directory names for a cleaner look. -(add-hook 'rfn-eshadow-update-overlay-hook #'vertico-directory-tidy) - -(setopt read-buffer-completion-ignore-case t) -(setopt read-file-name-completion-ignore-case t) -(setopt completion-ignore-case t) - -(use-package orderless :ensure t) -(setopt completion-styles '(orderless basic)) -(setopt completion-category-defaults nil) -(setopt completion-category-overrides '((file (styles partial-completion)))) - -(setopt confirm-nonexistent-file-or-buffer 'after-completion) - -;;; Replace the mode line with a header line - -;; First, we set the mode line to nil. On my graphical display, this collapses it so all i get is a thin black line separating the buffer from the echo area. -(setq-default mode-line-format nil) - -;; But the mode line still holds some useful information that i want to see. I would rather that be in the header line, because to me it makes sense for this kind of metadata to be /above/ the buffer it is describing. - -;; First, in white on black text, i want the information about the state of the file. This will show three hyphens in the top left corner of the header line. The first two hyphens mean that the file is both writable and unchanged. If the buffer has been changed, they will change to two asterisks. If the buffer is read only, they will change two percentage symbols. And if the buffer is read only and has been changed, the first will change to a percentage symbol, and the second will change to an asterisk. The final hyphen represents that the file is local, specifically that the default-directory variable is local. If it is remote, an at symbol will be displayed instead. - -;; Next, we want to display the buffer name. For buffers which belong to files, this will usually be the file name, but it is likely to be something more informative for special buffers. - -;; Below that, show a line and column coördinate. There are special minor modes that will enable or disable this for the default mode line, but i ignore that and put the formatting code here directly. The docstring for the mode-line-format variable suggests that the column might not be displayed correctly in some situations without enabling the minor mode, but i haven't noticed that yet so i don't bother. This column number is zero-indexed; a capital c would make it one-indexed. For now i stick with zero-indexed as that's the emacs default and i'm not sure which is better. I guess it makes a bit more sense that the first character on a line is labeled "1". - -;; I don't know exactly what the final variable covers, so i keep it here so that if something shows up i know that it gets put here. Because i have a global mode line in my tab bar, some of the things that would otherwise be here (like the time, battery percentage, and notifications for chat buffers) don't show up. - -;; Copy the code from mode-line-format-right-align so that i can use it. This is an emacs 30 feature, which i don't run yet. In the future, i'll be able to remove this. -(defcustom mode-line-right-align-edge 'window - "Where function `mode-line-format-right-align' should align to. -Internally, that function uses `:align-to' in a display property, -so aligns to the left edge of the given area. See info node -`(elisp)Pixel Specification'. - -Must be set to a symbol. Acceptable values are: -- `window': align to extreme right of window, regardless of margins - or fringes -- `right-fringe': align to right-fringe -- `right-margin': align to right-margin" - :type '(choice (const right-margin) - (const right-fringe) - (const window)) - :group 'mode-line - :version "30.1") -(defun mode--line-format-right-align () - "Right-align all following mode-line constructs. - -When the symbol `mode-line-format-right-align' appears in -`mode-line-format', return a string of one space, with a display -property to make it appear long enough to align anything after -that symbol to the right of the rendered mode line. Exactly how -far to the right is controlled by `mode-line-right-align-edge'. - -It is important that the symbol `mode-line-format-right-align' be -included in `mode-line-format' (and not another similar construct -such as `(:eval (mode-line-format-right-align)'). This is because -the symbol `mode-line-format-right-align' is processed by -`format-mode-line' as a variable." - (let* ((rest (cdr (memq 'mode-line-format-right-align - mode-line-format))) - (rest-str (format-mode-line `("" ,@rest))) - (rest-width (string-pixel-width rest-str))) - (propertize " " 'display - ;; The `right' spec doesn't work on TTY frames - ;; when windows are split horizontally (bug#59620) - (if (and (display-graphic-p) - (not (eq mode-line-right-align-edge 'window))) - `(space :align-to (- ,mode-line-right-align-edge - (,rest-width))) - `(space :align-to (,(- (window-pixel-width) - (window-scroll-bar-width) - (window-right-divider-width) - (* (or (cdr (window-margins)) 1) - (frame-char-width)) - ;; Manually account for value of - ;; `mode-line-right-align-edge' even - ;; when display is non-graphical - (pcase mode-line-right-align-edge - ('right-margin - (or (cdr (window-margins)) 0)) - ('right-fringe - ;; what here? - (or (cadr (window-fringes)) 0)) - (_ 0)) - rest-width))))))) - -(defvar mode-line-format-right-align '(:eval (mode--line-format-right-align)) - "Mode line construct to right align all following constructs.") -(put 'mode-line-format-right-align 'risky-local-variable t) - -(setq-default header-line-format - '("%b:%l,%c " - mode-line-format-right-align - "%1*%1+%1@")) - -(defun pulse-line (&rest _) - "Pulse the current line." - (pulse-momentary-highlight-one-line (point))) -(dolist (command '(scroll-up-command scroll-down-command recenter-top-bottom other-window)) - (advice-add command :after #'pulse-line)) - -;;; Jabber - -(use-package jabber :ensure t) - -;; I don't actually use xmpp as xmpp that much. But i do use it to connect to irc, and this package lets me do that. Unfortunately, it's not a particularly well-behaved package; by default it clobbers some keybindings and floods the echo area with unhelpful messages. -(setopt jabber-account-list '(("noa@hmm.st"))) - -;; So now what we're going to do is get it to stop showing a bunch of channels in the mode line, because there will always be new activity and i want to drop in when i feel like it, and not always have a reminder of that fact. The defun below is copied from jabber-activity-show-p-default but with an extra condition plopped in. -(defcustom noa/jabber-activity-dont-show - '("#tildetown%town@irc.hmm.st" - "#meta%tilde.chat@irc.hmm.st" - "hmm@conference.hmm.st") - "List of JIDs not to show in the modeline." - :group 'jabber-activity)(defun noa/jabber-activity-show-p (jid) - "Return non-nil if JID should be hidden. -A JID should be hidden when there is an invisible buffer for JID, -when JID is not in `noa/jabber-activity-dont-show', -and when JID is not in `jabber-activity-banned'." - (let ((buffer (jabber-activity-find-buffer-name jid))) - (and (buffer-live-p buffer) - (not (get-buffer-window buffer 'visible)) - (not (cl-dolist (entry jabber-activity-banned) - (when (string-match entry jid) - (cl-return t)))) - (not (cl-dolist (entry noa/jabber-activity-dont-show) - (when (string-match entry jid) - (cl-return t)))))))(setopt jabber-activity-show-p #'noa/jabber-activity-show-p) - -;; I'm on a laptop, so whenever i shut it i get disconnected. Jabber can query auth-source for my password, so automatically reconnecting is useful and doesn't need me to do anything. -(setopt jabber-auto-reconnect t) - -;; Because my xmpp server supports message history, i don't need to worry about exiting without seeing all messages, as they'll be there when i get back. -(setopt jabber-activity-query-unread nil) - -;; The default buffer names are a bit ugly to look at, so i change them to a similar format as eww. Which is still pretty ugly, welcome to emacs -(setopt jabber-chat-buffer-format "*%n | jabber*" - jabber-groupchat-buffer-format "*%n | jabber*") - -;; As alluded to above, jabber.el also has a terrible terrible habit of sending a message to the echo area for every change in online state of my contacts, and every single message in any channel. Obviously this gets very annoying, especially if i'm using the minibuffer at that time. Thank you to acdw for pointing me towards these helpful hooks to remove. -(remove-hook 'jabber-alert-muc-hooks #'jabber-muc-echo) -(remove-hook 'jabber-alert-presence-hooks #'jabber-presence-echo) - -;; Also stop jabber from clobbering the dired-jump binding and instead use something on C-c like a good child. -(with-eval-after-load 'jabber - (keymap-global-set "C-x C-j" #'dired-jump)) - -;; Finally, have a binding to jump to a buffer in which there's been some new activity. Better than always using switch-to-buffer to get there. -(keymap-global-set "C-c C-j" #'jabber-activity-switch-to) - -(use-package nov :ensure t) -(add-to-list 'auto-mode-alist '("\\.epub\\'" . nov-mode)) - -;;; Spellcheck -(use-package jinx :ensure t) -(setopt global-jinx-mode t) -(keymap-global-set "M-$" #'jinx-correct) -(keymap-global-set "C-M-$" #'jinx-languages) -(add-to-list 'vertico-multiform-categories - '(jinx grid (vertico-grid-annotate . 20))) -(defun jinx--add-to-abbrev (overlay word) - "Add abbreviation to `global-abbrev-table'. -The misspelled word is taken from OVERLAY. WORD is the corrected word." - (let ((abbrev (buffer-substring-no-properties - (overlay-start overlay) - (overlay-end overlay)))) - (message "Abbrev: %s -> %s" abbrev word) - (define-abbrev global-abbrev-table abbrev word))) -(advice-add 'jinx--correct-replace :before #'jinx--add-to-abbrev) - -;;; Completing-read everywhere with consult - -;; Consult is a package to provide navigation commands that take advantage of completing-read. I set up a nice completing-read environment earlier with vertico. There are a lot of commands built in to consult, and it's possible to define more. But i use it very simply. -(use-package consult :ensure t) - -;; Consult buffer can be used instead of the default buffer menu. It lists recently used files and bookmarks as well as open buffers. -(global-set-key [remap switch-to-buffer] #'consult-buffer) ;; also contains file history, etc - -(global-set-key [remap yank-pop] #'consult-yank-pop) ;; like normal yank-pop but with live preview -(global-set-key [remap goto-line] #'consult-goto-line) -(global-set-key [remap imenu] #'consult-imenu) -(bind-key [remap imenu] #'consult-org-heading #'org-mode-map) -(global-set-key [remap info] #'consult-info) - -;;; Embark: sort of like right click, but better - -;; I've only recently started making use of embark and i definitely need to experiment with it more. Essentially it lets you execute actions based on what kind of thing is selected, either at the point in the buffer, or in an already open completion buffer. -(use-package embark :ensure t) - -(global-set-key (kbd "C-") #'embark-act) -(global-set-key (kbd "C-") #'embark-export) -(global-set-key (kbd "M-.") #'embark-dwim) - -;; Embark indicators give us visual indication of what embark will do. The minimal indicator puts a message in the echo area. The highlight indicator highlights the region in the buffer that is being acted on. The isearch indicator does the same for when there are multiple regions to be acted on. If we want to see how we can act on the region, we can press C-h. -(setopt embark-indicators '(embark-minimal-indicator - embark-highlight-indicator - embark-isearch-highlight-indicator)) - -;; As mentioned in the vertico configuration above, we can set vertico to use a different layout when completing different things. In this case, we set embark to take control of showing bindings help and of the prefix help, which is pressing C-h after pressing a prefix. Then we ensure we get a grid layout, so that we can see more commands on screen at a time. -(global-set-key [remap describe-bindings] #'embark-bindings) -(setopt prefix-help-command #'embark-prefix-help-command) -(add-to-list 'vertico-multiform-categories '(embark-keybinding grid)) - -;; Because i use consult, it's recommended to have this package installed. -(use-package embark-consult :ensure t) -(add-hook 'embark-collect-mode-hook #'consult-preview-at-point-mode) - -;;; Annotations for completing-read - -;; Marginalia provides us with annotations for candidates in completing read functions. This is things like docstrings for functions, file permissions in find-file, and so on. It's a small quality of life improvement. -(use-package marginalia :ensure t) -(setopt marginalia-mode t) - -;; We want to always show the relative age of a file. By default, files which haven't been modified for more than two weeks will display an absolute date. -(setopt marginalia-max-relative-age most-positive-fixnum) - -;; My keyboard has a tab key and an i key. For legacy reasons, by default emacs converts C-i to mean the same thing as the tab key, but i don't really want that. The tab key is called and it gets translated to TAB. C-i is TAB, but i'd rather it by C-i. That's what this decode line does. -(define-key input-decode-map [?\C-i] [C-i]) -;; Now that tab and C-i are properly distinguished, i can bind C-i to completion at point. -(global-set-key (kbd "") 'completion-at-point) -;; I also want to make the completion at point function a bit more friendly than the default, so i ask consult to provide the completion functionality. -(setopt completion-in-region-function 'consult-completion-in-region) - -;; select the help window so that i can easily close it again with q -(setopt help-window-select t) - -(setopt switch-to-buffer-obey-display-actions t) - -;; (use-package org-fc -;; :disabled -;; :ensure t -;; :custom -;; (org-fc-directories (expand-file-name "~/data/notes/"))) - -;; If we enable this, emphasis markers will be hidden for a more word processor feel. This has the downside of meaning you have to delete a hidden character to get rid of bold or italic text. I don't have much of a problem with seeing the emphasis markers so i'm willing to put up with any aesthetic shortcomings for a better user experience. The package org-appear solves this by hiding them, but showing them when the point is over them, but i don't think having a whole package just for that is worth it. -(setopt org-hide-emphasis-markers nil) -(setopt org-startup-with-inline-images t) -(setopt org-image-actual-width '(300)) -(setopt org-auto-align-tags nil) -(setopt org-tags-column 0) -(setopt org-catch-invisible-edits 'show-and-error) -(setopt org-special-ctrl-a/e t) -(setopt org-insert-heading-respect-content t) -(setopt org-ellipsis "…") -(setopt org-display-custom-times t) -(setopt org-time-stamp-custom-formats '("%Y-%m-%d" . "%Y-%m-%d %H:%M")) -(setopt org-extend-today-until 4) -(setopt org-adapt-indentation nil) -(setopt org-log-done 'time) -(setopt org-return-follows-link t) -(setopt org-agenda-files '("~/data/notes/notes.org")) -(setopt org-capture-bookmark nil) -(setopt org-capture-templates '(("j" "Journal" entry (file+olp+datetree "~/data/notes/notes.org") "* %?\n" :empty-lines 1) - ("w" "Website" entry (file+olp+datetree "~/data/notes/notes.org") "* %a\n%?\n" :empty-lines 1) - ("c" "Contact" entry (file+olp+datetree "~/data/notes/notes.org") - "* %^{Name} -:PROPERTIES: -:ADDRESS: %^{Address} -:BIRTHDAY: %^{yyyy-mm-dd} -:EMAIL: %^{EMAIL}p -:NOTE: %^{NOTE} -:END:" - :empty-lines 1) - )) - -(setopt org-agenda-block-separator nil) -(setopt org-agenda-include-deadlines t) -;; Always start the weekly agenda for a week from today -(setopt org-agenda-start-on-weekday nil) -;; Show week of agenda by default -(setopt org-agenda-span 'week) -(setopt org-agenda-prefix-format '((agenda . " %i %?-12t% s") - (todo . " %i ") - (tags . " %i ") - (search . " %i "))) -(setopt org-agenda-time-grid '((daily today require-timed) - (800 1000 1200 1400 1600 1800 2000) - " " " ")) -(setopt org-agenda-current-time-string - "◀ you are here") -(setopt org-support-shift-select 'always) - -;; Make org html export more pleasant by default -(setopt org-export-with-smart-quotes t) -(setopt org-export-with-entities nil) -(setopt org-export-headline-levels 5) -(setopt org-export-with-toc nil) -(setopt org-export-section-numbers nil) -(setopt org-html-doctype "html5") -(setopt org-html-html5-fancy t) -(setopt org-html-container-element "section") -(setopt org-html-divs '((preamble "header" "preamble") - (content "main" "content") - (postamble "footer" "postamble"))) -(setopt org-export-with-sub-superscripts t) -(setopt org-html-head-include-default-style nil - org-html-head-include-scripts nil - org-html-validation-link "" - org-html-indent t) - - -(global-set-key (kbd "C-c c") #'org-capture) -(global-set-key (kbd "C-c a") #'org-agenda) - -(use-package org-modern :ensure t) -(add-hook 'org-mode-hook #'org-modern-mode) -;; (add-hook 'org-agenda-finalize-hook #'org-modern-agenda) - -;; There are three ways to make bullet lists in org mode, which seems a bit excessive to me. I almost always only use the hyphen, but i like my bullet points to look like bullets, so here i overwrite the hyphen display to show a bullet point. While i'm at it, i overwrite the others too, because they are functionally identical so should probably look the same too. -(setopt org-modern-list '((?+ . " • ") - (?- . " • ") - (?* . " • "))) -(setopt org-modern-timestamp nil) -(setopt org-modern-star nil) -(setopt org-modern-keyword nil) -(setopt org-modern-checkbox '((88 . "☑") - (45 . #("□–" 0 2 - (composition - ((2))))) - (32 . "□"))) -(setopt org-modern-table nil) - -(defun read-file-as-string (filename) - "Read file contents from FILENAME." - (with-temp-buffer - (insert-file-contents filename) - (buffer-string))) - -(setq noa/website-header (read-file-as-string "/home/noa/projects/org-website/templates/header.html")) -(setq noa/website-footer (read-file-as-string "/home/noa/projects/org-website/templates/footer.html")) - - -;; The index page generation functions were taken from Dennis Ogbe. Thank you! -(defun my-blog-parse-sitemap-list (l) - "Convert the sitemap list in to a list of filenames." - ;; LIST looks like: - ;; (unordered ("[[file:uses.org][Things i use]]") ("[[file:media.org][Media Diary]]") ("[[file:tanklobsters.org][Tank lobsters]]")) - (mapcar #'(lambda (i) - (let ((link (with-temp-buffer - (let ((org-inhibit-startup nil)) - (insert (car i)) - (org-mode) - (goto-char (point-min)) - (org-element-link-parser))))) - (when link - (plist-get (cadr link) :path)))) - (cdr l))) - -(defun my-blog-sort-article-list (l p) - "sort the article list anti-chronologically." - (sort l #'(lambda (a b) - (let ((date-a (org-publish-find-date a p)) - (date-b (org-publish-find-date b p))) - (not (time-less-p date-a date-b)))))) - -(defun noa/naive-org-first-paragraph (file) - "Naively returns the first paragraph of FILE. - - The way that the first paragraph is determined is to assume that there will be an org metadata block beforehand, so look for the first two consecutive newlines and mark the following paragraph." - (with-temp-buffer - (insert-file-contents file) - (goto-char (point-min)) - (re-search-forward "\n\n") - (mark-paragraph) - (let ((beg (mark)) - (end (point))) - (buffer-substring beg end)))) - -(defun noa/website-sitemap (title list) - "Generate the index page for my website." - ;; LIST looks like: - ;; (unordered ("[[file:uses.org][Things i use]]") ("[[file:media.org][Media Diary]]") ("[[file:tanklobsters.org][Tank lobsters]]")) - (with-temp-buffer - ;; mangle the parsed list given to us into a plain lisp list of files - (let* ((filenames (my-blog-parse-sitemap-list list)) - (project-plist (assoc "website-pages" org-publish-project-alist)) - (articles (my-blog-sort-article-list filenames project-plist))) - (message (concat "PLIST: " (plist-get project-plist :base-directory))) - - (insert "Several parts of this website are broken as i wrangle with the monstrosity that is programming in emacs lisp. The content should still be fine, but for further cosmetics please hold <3\n\n") - (dolist (file filenames) - (let* ((abspath (file-name-concat "/home/noa/data/share" file)) - ;; (abspath (file-name-concat (plist-get project-plist :base-directory) file)) - (relpath (file-relative-name abspath "/home/noa/data/share")) - (title (org-publish-find-title file project-plist)) - (date (format-time-string (car org-time-stamp-formats) (org-publish-find-date file project-plist))) - (preview (noa/naive-org-first-paragraph abspath))) - (insert (concat "* [[file:" relpath "][" title "]]\n")) - (insert (concat - "*" date ":*" - preview)) - (insert "\n"))) - ;; insert a title and save - (insert "#+TITLE: noa.pub\n") - (buffer-string)))) - -(setq org-publish-project-alist - `(("website" - :components ("website-pages" "website-assets")) - ("website-pages" - :publishing-function org-html-publish-to-html - :base-directory "/home/noa/data/share" - :publishing-directory "/home/noa/projects/org-website" - :base-extension "org" - :with-drawers t - :html-link-home "/" - :html-head "𰻝\">" - :html-head-include-default-style nil - :html-head-include-scripts nil - :html-doctype "html5" - ;; :html-validation-link nil - :html-preamble "" - :html-postamble ,noa/website-footer - :html-home/up-format "" - :html-link-up "" - :html-html5-fancy t - :html-indent t - :html-head " -" - :auto-sitemap t - :sitemap-filename "/home/noa/projects/org-website/index.org" - :sitemap-title "noa.pub" - :sitemap-style list - ;; :sitemap-format-entry - :sitemap-function noa/website-sitemap - :sitemap-sort-folders ignore - :sitemap-sort-files anti-chronologically - :sitemap-ignore-case t) - ("website-assets" - :publishing-function org-publish-attachment - :base-directory "/home/noa/data/share" - :publishing-directory "/home/noa/projects/org-website" - :base-extension "css\\|js\\|png|\\jpg" - :recursive t))) - -;;; Make wide windows narrow with visual-fill-column -(use-package visual-fill-column :ensure t) -(setopt visual-fill-column-enable-sensible-window-split t) -(setopt visual-fill-column-center-text t) -(advice-add 'text-scale-adjust :after #'visual-fill-column-adjust) - -(add-hook 'text-mode-hook #'visual-line-fill-column-mode) -(add-hook 'eww-after-render-hook #'visual-line-fill-column-mode) -(add-hook 'nov-post-html-render-hook #'visual-line-fill-column-mode) -(add-hook 'mu4e-view-mode-hook #'visual-line-fill-column-mode) - -;; This works... fine. However it's adapting the prefix, it doesn't indent nicely with proportional fonts, but you can't win them all. -(use-package adaptive-wrap :ensure t) -(add-hook 'visual-fill-column-mode-hook #'adaptive-wrap-prefix-mode) - -(setopt ffap-file-name-with-spaces t) -(global-set-key [remap find-file] #'find-file-at-point) -(global-set-key [remap dired] #'dired-at-point) - -(setopt browse-url-browser-function 'eww-browse-url - browse-url-secondary-browser-function 'browse-url-default-browser - url-cookie-trusted-urls '() - url-cookie-untrusted-urls '(".*") - shr-cookie-policy nil) - -;; I don't want web pages to be able to specify their own colours, because i like the colours i already have set. -(setopt shr-use-colors nil) -(setopt shr-max-width nil) - -;; We can set what the maximum size of an image in a window should be. This is a fraction of the total window width or height, and if the image would be bigger than this, it'll be resized to fit. It's useful to have it smaller because emacs still sort of chokes on scrolling when there are large images in a buffer. This is the default value of this option. -(setopt shr-max-image-proportion 0.9 - shr-discard-aria-hidden t - ;; The default name for the eww buffer is *eww*. This is unhelpful because it makes having more than one eww buffer open a bit of a chore to navigate. We can set it to 'url, 'title, or a function. I set it to 'title because marginalia already shows me the url. However, this means that i can't search for a url name when switching buffers. See the help for this variable for an example of a function which gives the page title and the url. - eww-auto-rename-buffer 'title) - -;; Goto address mode makes urls and email address in a buffer clickable. I want these clickable links to look like links, because that's what they are. The two mouse face variables are what face is used on hover, which at the moment i ignore. It might also be worth setting them to 'highlight. -(setopt global-goto-address-mode t) -(setopt goto-address-mail-face 'link) -(setopt goto-address-mail-mouse-face 'highlight) -(setopt goto-address-url-face 'link) -(setopt goto-address-url-mouse-face 'highlight) - -;; Abbrev mode expands one string into another string. I use it as a simple autocorrect mode. If i misspell a word, i run C-x a i g which will prompt me for what to expand the previous word into. I type the correct spelling, and whenever i make that mistake again, it will automatically be corrected. It's important to be careful not to set something that could be a typo for two words though, because otherwise it gets even more annoying. Luckily it's easy to update the abbrevs which are stored in ~/.config/emacs/abbrev_defs. M-x list-abbrevs is also a nice command which shows all the saved abbrevs and how many times they've been expanded. -(add-hook 'text-mode-hook #'abbrev-mode) - -(setopt global-eldoc-mode t) - -;; use a bar cursor and blink it and don't stop blinking it. i don't know how i feel about this yet to be honest, but it helps me know which window is active so for now i'm keeping it -(setopt - cursor-type 'bar - blink-cursor-mode -1 - blink-cursor-interval 0.7) - -;; Dired is a really nice package which, as with a lot of emacs, has some dodgy defaults. Here we round off some of the sharp edges to make it more enjoyable to use. -;; By default, dired permanently deletes files. But i have quite a bit of storage and also make bad decisions regularly, so it seems fitting to make use of the wonderful invention that is the trash. People who have used systems from the last forty years or so will likely be familiar with this innovation. -(setopt delete-by-moving-to-trash t) -;; It's not fun to be asked every time whether we want to delete a directory recursively. It's an understandable default for safety reasons, but because we are not deleting permanently but rather just moving to the trash, it's not such a concern. -(setopt dired-recursive-deletes 'always) -;; Recursive copying isn't even destructive, so i definitely don't want to be asked about that. -(setopt dired-recursive-copies 'always) -;; After we delete some files or directories, it makes sense to get rid of any buffers which are looking at those files or directories. -(setopt dired-clean-up-buffers-too nil) -;; With this set, if we have two dired buffers open next to one another, a rename operation in one will default to the directory shown in the other. In this way, we can pretend we are using some kind of norton commander like file browser instead of slumming it in emacs. -(setopt dired-dwim-target t) -;; These are some useful ls switches. We have to keep -l. To show dotfiles as well, we use -a. To sort numbers by number order instead of lumping together ones, twos, and so on, we use -v. Because we don't have colour, it's nice to have a clear indicator of what is a file and what is a directory, as well as other different things like symlinks which i never remember. By using -F, a forward slash is appended to every directory. And to get more easily understandable file sizes, we use -h, which will tell us the file size in kilobytes or megabytes rather than a huge number that means nothing to me. I won't explain the meaning of the long flag. -(setopt dired-listing-switches "-alvFh --group-directories-first") - -;; By default, don't show dired details -(add-hook 'dired-mode-hook #'dired-hide-details-mode) - -(use-package dired-du :ensure t) -(setopt dired-du-size-format t) -;; This can be a little slow -(add-hook 'dired-mode-hook #'dired-du-mode) - -;;; Indentation: tabs and whitespace settings - -;; In general, my rules for inserting tabs are that the tab key should insert tabs. I personally prefer tabs to spaces, because tabs work reasonably well whatever font or tab width one chooses to set, whereas spaces are the same width for everyone, except when someone uses a proportional font in which case they are narrower than expected. Furthermore, people tend to use spaces for alignment, which looks bad when you can't rely on every character being the same width. - -;; However, i'm in the minority, and fighting with the very complicated emacs indentation systems is simply not fun. That said, i refuse to use a monospaced font. Luckily the minority is more than one and someone has already done the hard work for me of writing a mode to make spaces for indentation work reasonably well with a proportional font. That mode is elastic-indent-mode, and it very simply makes leading whitespace characters the same width as the characters on the line above. It's a simple solution but most of the time it does what i want. -(require 'elastic-indent) -(add-hook 'prog-mode-hook #'elastic-indent-mode) - -;; Previously i used a function to naïvely copy the whitespace from the line above. This is the way that vi, nano, and acme all implement auto-indentation. However, for now i'm experimenting with using the built-in indentation functions again. I'm leaving this defun here for posterity. -(defun noa/naive-return-and-indent () - "Insert a newline and copy the indentation of the previous line, vi/nano style." - (interactive) - (open-line 1) - (let* ((start (progn (beginning-of-line) (point))) - (indent (progn (back-to-indentation) (point))) - (end (progn (end-of-line) (point))) - (whitespace (buffer-substring start indent))) - (delete-trailing-whitespace start end) - (beginning-of-line 2) - (insert whitespace))) - -;; We will only be trying to indent at the start of a line, and sometimes we will want to insert a standard tab character. We can also set this option to 'complete, which will run completion at point if the region is already indented. -(setopt tab-always-indent nil) - -;; Usually, we want indentation to be done with tabs. Some modes make more sense to use spaces to indent. Lisp is a particular example, and emacs's default behaviour of converting tabs into spaces is frankly horrific. I've taken the below code from acdw to use spaces in these modes. -(defvar space-indent-modes '(emacs-lisp-mode - lisp-interaction-mode - lisp-mode - scheme-mode - python-mode) - "Modes to indent with spaces, not tabs.") -(add-hook 'prog-mode-hook - (defun indent-tabs-mode-maybe () - (setq indent-tabs-mode - (if (apply #'derived-mode-p space-indent-modes) nil t)))) - -;; I want to ensure that indentation is always correct. The builtin electric indent mode works /sometimes/, but the aggressive indent mode package is more reliable. -(use-package aggressive-indent :ensure t) -(setopt global-aggressive-indent-mode t) - -;;; Interface - -;; I want to make sure that various bits of the interface are hidden. but this isn't an "all gui chrome is useless" rampage. I personally think the scrollbar is useful, i like the visual indication it gives of how far i am through a file. - -;; At the moment, explicitly disabling the menu bar and tool bar does nothing, because i already set there to be no lines displayed for the tool and menu bars in my early-init.el file. -;; (setopt -;; menu-bar-mode nil -;; tool-bar-mode nil -;; ) - -;; Tooltips are little popups next to the mouse cursor. I think this information is helpful, but i like it to appear in a more consistent position, because i find it frustrating when popups cover parts of the ui that i wanted to see. By disabling tooltip-mode, the contents that would be in a popup is instead shown in the echo area. -(setopt tooltip-mode nil) - -;; I see no reason not to immediately show which chords in a key sequence i have already pressed. Emacs does, however, and instead of letting me set the value of echo-keystrokes to zero to wait zero seconds to show that information, it repurposes zero as a method of disabling the functionality altogether, and provides no special functionality for setting it to nil that would explain why that's not an acceptable method of disabling a feature. Instead, i have to deal with setting it to nearly zero, and luckily i can't tell the difference. -(setopt echo-keystrokes 0.1) - -;; A useful feature when programming is to show matching parentheses. Show-paren-mode is a global mode. By default it runs in all buffers except those inheriting from special mode. -(setopt show-paren-mode t) - -;; This variable means that if there is no non-whitespace character in between the point and the paren, it will be highlighted. It's useful to highlight parentheses if the point is at the start of the line and the paren is indented. -(setopt show-paren-when-point-in-periphery t) - -;; By default, the point has to be after a paren for it to be highlighted. But often the point will be just inside, in which case it's also helpful for the pair to be highlighted. -(setopt show-paren-when-point-inside-paren t) - -(setopt tab-bar-mode t) -(setopt tab-bar-format '(tab-bar-format-menu-bar - tab-bar-format-align-right - tab-bar-format-global)) - -(setopt global-font-lock-mode t) -(setopt font-lock-maximum-decoration nil) - -(setopt inhibit-startup-screen t - mouse-drag-and-drop-region nil - mouse-yank-at-point t - ;; deleting should be an explicit action - delete-selection-mode nil) - -(global-set-key (kbd "C-t") 'tab-new) - -;; shift click to select region with the mouse. This annoyingly rings the bell for an error -(global-unset-key (kbd "S-")) -(global-set-key (kbd "S-") 'mouse-save-then-kill) - -;;; packages -(setopt package-archives - '(("gnu" . "https://elpa.gnu.org/packages/") - ("nongnu" . "https://elpa.nongnu.org/nongnu/") - ("melpa-stable" . "https://stable.melpa.org/packages/") - ("melpa" . "https://melpa.org/packages/"))) - -;;; saving - -;; backups are pointless in long emacs sessions imo, but autosaves are useful -(setopt remote-file-name-inhibit-auto-save t) -(setopt remote-file-name-inhibit-auto-save-visited t) -(setopt make-backup-files nil - backup-by-copying t - create-lockfiles nil - auto-save-mode 1 - auto-save-interval 6 ;; every six keystrokes - auto-save-timeout 5 ;; every 5 seconds - auto-save-default t - auto-save-no-message t - save-silently t - version-control t - ;; this will auto save to the current file - auto-save-visited-mode t) -(add-hook 'focus-out-hook (lambda () (interactive) (save-some-buffers t))) -(add-hook 'mouse-leave-buffer-hook (lambda () (interactive) (save-some-buffers t))) - -;; (use-package keyfreq :ensure t) -;; (setopt keyfreq-mode t) -;; (setopt keyfreq-autosave-mode t) -;; (setopt keyfreq-excluded-regexp (rx (or "pixel-scroll-precision"))) - -;; C-l goes in order -(setopt recenter-positions '(top middle bottom)) - -;; Emacs uses choppy scrolling by default. If i scoll with my trackpad, it's nice to have it move tiny amounts at the same time as my fingers, which pixel-scroll-precision-mode allows for. This also has the benefit of making scrolling over images a little bit of a nicer experience. -(setopt pixel-scroll-precision-mode t - pixel-scroll-precision-use-momentum t) - -;; (use-package smartscan) -;; (global-set-key (kbd "M-n") #'smartscan-symbol-go-forward) -;; (global-set-key (kbd "M-p") #'smartscan-symbol-go-backward) -(global-set-key (kbd "M-n") #'next-error) -(global-set-key (kbd "M-p") #'previous-error) - -;;; sentences -(setopt sentence-end-double-space nil) - -;; If i write a script, i will always run chmod +x after saving it. This command means i don't have to do that. -(add-hook 'after-save-hook #'executable-make-buffer-file-executable-if-script-p) - -;; We are on a unix system, so it makes sense to end files in the unix system way. I'm surprised this isn't the default. -(setopt require-final-newline t) - -(setopt window-min-height 1 - window-combination-resize t - window-resize-pixelwise t - frame-resize-pixelwise t) - -;;; history -(setopt history-length 250 - kill-ring-max 25) - -(setopt savehist-file "~/.config/emacs/savehist") -(setopt savehist-additional-variables - '(kill-ring - command-history - set-variable-value-history - custom-variable-history - query-replace-history - read-expression-history - minibuffer-history - read-char-history - face-name-history - bookmark-history - file-name-history)) -(setopt savehist-mode t) - -(setopt window-divider-mode t) -(setopt window-divider-default-right-width 1) -(setopt window-divider-default-bottom-width 1) -(setopt window-divider-default-places t) - -;; Add prompt indicator to `completing-read-multiple'. -;; We display [CRM], e.g., [CRM,] if the separator is a comma. -(defun crm-indicator (args) - (cons (format "[CRM%s] %s" - (replace-regexp-in-string - "\\`\\[.*?]\\*\\|\\[.*?]\\*\\'" "" - crm-separator) - (car args)) - (cdr args))) -(advice-add #'completing-read-multiple :filter-args #'crm-indicator) - -;; Do not allow the cursor in the minibuffer prompt -(setopt minibuffer-prompt-properties - '(read-only t cursor-intangible t face minibuffer-prompt)) -(add-hook 'minibuffer-setup-hook #'cursor-intangible-mode) -(setopt display-battery-mode t) -(setopt display-time-default-load-average nil) -(setopt display-time-24hr-format t) -(setopt display-time-mode t) - -;; Support opening new minibuffers from inside existing minibuffers. -(setopt enable-recursive-minibuffers t) -(setopt debug-on-error t) - -;; Hide commands in M-x which do not work in the current mode. -(setopt read-extended-command-predicate 'command-completion-default-include-p) - -(setopt recentf-max-menu-items 25 - recentf-save-file "~/.config/emacs/recentf" - recentf-mode 1 - bookmark-default-file "~/.config/emacs/bookmarks") - -;;; miscellaneous -(setopt save-place-mode 1) - -(setenv "PAGER" "cat") -(setenv "TERM" "dumb") -(setenv "NO_COLOR") -(setenv "GPG_AGENT_INFO" nil) - -;; The former means that when given a list of choices, we can use single character abbreviations to answer. The latter is a fancy way of defaliasing yes-or-no-p to y-or-n-p. -(setopt read-answer-short t) -(setopt use-short-answers t) - -(setq disabled-command-function nil) -(setopt custom-file (make-temp-file "custom")) -(setq inhibit-startup-echo-area-message "noa") ;; #userfreedom - -(setopt - uniquify-after-kill-buffer-p t - uniquify-buffer-name-style 'forward - uniquify-ignore-buffers-re "^\\*" - uniquify-separator "/") - -(setopt - save-interprogram-paste-before-kill t - mouse-yank-at-point t - require-final-newline t - visible-bell t - load-prefer-newer t - ediff-window-setup-function 'ediff-setup-windows-plain) - -;; (unless (server-running-p) (server-start))) - -(setopt help-at-pt-display-when-idle t) - -;;; Search in buffer - -;; Isearch is good, but it has some rough edges. The easiest way forward was just to use ctrlf, which fixes most of them. -;; (use-package ctrlf :ensure t) -;; (global-set-key [remap isearch-forward] #'ctrlf-forward-default) -;; n(global-set-key [remap isearch-backward] #'ctrlf-backward-default) -;; (global-set-key [remap isearch-forward-regexp] #'ctrlf-forward-alternate) -;; (global-set-key [remap isearch-backward-regexp] #'ctrlf-backward-alternate) - -;; (use-package casual-isearch :ensure t) -;; (define-key isearch-mode-map (kbd "") #'casual-isearch-tmenu) -(define-key isearch-mode-map (kbd "") #'cc-isearch-menu-transient) - -;; It makes more sense to go to the start of the match, because i start searching where i want to be. -(defun isearch-exit-at-front () - "always exit isearch, at the front of search match." - (interactive) - (isearch-exit) - (when isearch-forward - (goto-char isearch-other-end))) -(defun isearch-exit-at-end () - "Always exit isearch, at the end of search match." - (interactive) - (isearch-exit) - (when (not isearch-forward) - (goto-char isearch-other-end))) - -(define-key isearch-mode-map (kbd "") #'isearch-exit-at-front) -(define-key isearch-mode-map (kbd "C-") #'isearch-exit-at-end) -;; Make isearch always quit on C-g -(define-key isearch-mode-map (kbd "C-g") #'isearch-cancel) -(define-key isearch-mode-map (kbd "C-o") #'isearch-occur) -(setopt search-whitespace-regexp ".*?") -(setopt isearch-lax-whitespace t) -(setopt isearch-lazy-count t) -(setopt isearch-allow-motion t) -(setopt isearch-repeat-on-direction-change t) -(setopt isearch-wrap-pause 'no) - -;; Make isearch use the minibuffer like a good normal program -(use-package isearch-mb :ensure t) -(setopt isearch-mb-mode t) - -;; (add-hook 'occur-mode-hook #'hl-line-mode) - -(global-set-key (kbd "M-o") 'other-window) -(global-set-key (kbd "C-x k") 'kill-this-buffer) - -;; undo C-/ -;; redo C-S-/ -(setopt undo-no-redo t) - -;;; Email: mu4e -(setopt mu4e-headers-skip-duplicates t) -(setopt mu4e-view-show-images t) -(setopt mu4e-view-show-addresses t) - -;; In theory i like format flowed, but what i like even more is just not hard wrapping messages and dealing with hacks to get around that to begin with. If software supported soft wrapping at an arbitrary column, the world would be a better place. -(setopt mu4e-compose-format-flowed nil) -(setopt mu4e-change-filenames-when-moving t) -(setopt mu4e-use-fancy-chars nil) -(setopt mu4e-confirm-quit nil) -(setopt mu4e-headers-leave-behavior 'apply) -(setopt mu4e-headers-precise-alignment t) -(setopt mu4e-headers-fields '((:flags . 6) - (:from . 32) - (:subject))) -(setopt mu4e-search-threads nil) -(setopt mu4e-hide-index-messages t) -(setopt mu4e-get-mail-command "mbsync -c ~/.config/mbsyncrc fastmail") -(setopt mu4e-maildir "~/mail") -(setopt mu4e-drafts-folder "/Drafts") -(setopt mu4e-sent-folder "/Sent") -(setopt mu4e-refile-folder "/Archive") -(setopt mu4e-trash-folder "/Trash") -(setopt mu4e-bookmarks '((:name "Inbox" :query "maildir:/Inbox" :key ?i) - (:name "Feeds" :query "maildir:/Feeds" :key ?f) - (:name "Paper trail" :query "\"maildir:/Paper trail\"" :key ?p))) - -;; function to move mails to trash -(with-eval-after-load 'mu4e - (bind-key (kbd "d") #'noa/move-to-trash 'mu4e-headers-mode-map) - (bind-key (kbd "d") #'noa/move-to-trash 'mu4e-view-mode-map) - (fset 'noa/move-to-trash "mTrash")) - -;; The first string is for when fancy characters are disabled, and the second is for when they are enabled. But i set them all manually because some of the other characters are ugly in fancy mode, but i like my unicode thread icons. -(setq mu4e-headers-thread-connection-prefix '("│ " . "│ ") - mu4e-headers-thread-last-child-prefix '("└ " . "└ ") - mu4e-headers-thread-blank-prefix '(" " . " ") - mu4e-headers-thread-root-prefix '("□ " . "□ ") - mu4e-headers-thread-child-prefix '("│ " . "│ ") - mu4e-headers-thread-orphan-prefix '("♢ " . "♢ ") - mu4e-headers-thread-duplicate-prefix '("≡ " . "≡ ") - mu4e-headers-thread-first-child-prefix '("⚬ " . "⚬ ") - mu4e-headers-thread-single-orphan-prefix '("♢ " . "♢ ")) - -;; Setting this to nil stops auto-fill from being automatically enabled in message buffers. -(setopt message-fill-column nil) - -;; (message-signature-file) -(setopt message-signature "~noa (https://noa.pub) - • I try to reply to formal emails in three sentences or fewer; excuse my brevity. - • I queue replies and batch send them at intervals; excuse my untimeliness.") - -(global-set-key (kbd "M-z") 'zap-up-to-char) - -(use-package markdown-mode - :ensure t - :mode ("\\.md\\'" . markdown-mode)) - -(use-package valign - :ensure t - :hook (markdown-mode . valign-mode) - :hook (org-mode . valign-mode) - :custom - (valign-fancy-bar t) - (valign-max-table-size 0)) - -;; This is my own version of fixed-pitch, which has some changes to it. No hooks are added by default. Updating the whitelist automatically applies the hooks. And there is no functionality for changing the cursor type. -(use-package fixed-pitch) -(setopt fixed-pitch-whitelist-hooks '(calendar-mode-hook - dired-mode-hook - ibuffer-mode-hook - magit-mode-hook - profiler-report-mode-hook - jabber-roster-mode-hook - mu4e-headers-mode-hook)) -(setopt transient-align-variable-pitch t) - -;; My current favourite font is sn pro, which feels like comic sans for grown ups. It's friendly but consistent and well thought out. However, it's also a proportional font, which obviously is the right way to do things, but emacs is very old and comes from a time before the innovation of legibility. As a result, there are some things that require a monospaced font, so i set one here. I chose go mono for two reasons: the first is because i think it looks really nice; the second is because it has serifs and is very visually distinct from sn pro, so i can notice and shame those buffers which require a fixed width font to operate properly. -(custom-set-faces - '(fixed-pitch ((t (:family "Go Mono" :height 110)))) - '(variable-pitch ((t (:family "SN Pro" :height 110))))) - -;; For some frustrating reason, emacs does not respect fontconfig font settings. What this means in practice is that emacs by default draws cjk characters with the korean variant. Luckily emacs has its own obscure and poorly documented way of doing things, so i can iterate over the relevant charsets and set the font specifically for those characters. -(dolist (charset '(han cjk-misc)) - (set-fontset-font t charset (font-spec :family "Noto Sans CJK SC"))) -;; Similar to the above, we have to manually set the font we want to be used for emoji. I like the cute style of the emoji in fsd emoji, but it doesn't have very good coverage, so we also set noto emoji as the backup. Note that noto emoji is not the same as noto color emoji, which uses coloured emoji. That's clearly against the vibe of this emacs! -(set-fontset-font - t 'emoji (font-spec :family "FSD Emoji") nil 'prepend) -(set-fontset-font - t 'emoji (font-spec :family "Noto Emoji") nil 'append) - -;; While we're here, let's set up emoji input. -(use-package cape :ensure t) -(add-to-list 'vertico-multiform-categories - '(cape-emoji grid indexed (vertico-grid-annotate . 6))) -(global-set-key (kbd "C-.") #'cape-emoji) - -;; Describe a key based on a string like "C-SPC" -(defun describe-key-shortcut (shortcut) - (interactive "MShortcut: ") - (describe-key (kbd shortcut))) - -;; Update the calendar. We want weeks to start on a monday, the first day of the week. Holidays should be highlighted, and the date format should put the year first. -(setopt calendar-week-start-day 1 - calendar-mark-holidays-flag t - calendar-date-style 'iso) - -;; Multiple cursors are a nice feature because they are very interactive. However, i've always found the emacs implementation a bit too janky. Iedit implements one case where multiple cursors are used, which is to put a cursor at every same symbol in the buffer and edit them all, sort of like a real-time query-replace. -(use-package iedit :ensure t) - -;;; Replace -;; Anzu provides real-time updates to the replacement string when running query-replace. -(use-package anzu :ensure t) -(global-set-key [remap query-replace] 'anzu-query-replace) -(global-set-key [remap query-replace-regexp] 'anzu-query-replace-regexp) - -;; My computer has a small screen, so i find that it's more beneficial for me to split the frame into columns, so i get more context. However, splitting in this way only gives me a (window-width) of 61, so emacs will always split into vertically stacked windows. By setting this to 80, the first split should always be vertical. -(setopt split-width-threshold 80) - -;; Define a handy function that allows me to do a full text search of every file in my home directory. For the most part, this works well; ripgrep avoids binary files. However, in some files with embedded images, it can add a lot of junk to the output. -(defun noa/consult-rg-home () - (interactive) - (consult-ripgrep "~/")) -(global-set-key (kbd "") #'noa/consult-rg-home) - -(setopt shell-file-name "/bin/sh") - -(defun snarf-song (url) - (interactive "sYoutube url:") - (async-shell-command - (concat "yt-dlp -x --audio-format=mp3 -o " - (shell-quote-argument "~/media/music/%(title)s [%(id)s].%(ext)s") - " " - (shell-quote-argument url)))) - -;; Put a quote in the scratch buffer - -(setopt cookie-file "~/data/quotes") - -(setopt initial-scratch-message - (concat (with-temp-buffer - (emacs-lisp-mode) - (insert (cookie cookie-file)) - (mark-whole-buffer) - (comment-region (mark) (point)) - (buffer-substring (mark) (point))) - "\n\n")) - -(use-package i-ching :ensure t) - -;; Use pass from auth-source -(require 'auth-source-pass) -(add-to-list 'auth-sources 'password-store) -(auth-source-forget-all-cached) - diff --git a/emacs/site-lisp/fixed-pitch.el b/emacs/site-lisp/fixed-pitch.el deleted file mode 100644 index 411a547..0000000 --- a/emacs/site-lisp/fixed-pitch.el +++ /dev/null @@ -1,53 +0,0 @@ -;;; fixed-pitch.el --- Use fixed-pitch only in sensible buffers -*- lexical-binding: t; -*- - -;; Copyright (C) 2020, Carl Steib -;; Author: Carl Steib -;; URL: https://github.com/cstby/fixed-pitch -;; Version: 0.0.0 -;; Package-Requires: ((emacs "27.1")) - -;; This program is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation, either version 3 of the License, or -;; (at your option) any later version. - -;; This program is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with this program. If not, see . - -;; This file is not part of Emacs. - -;;; Commentary: - -;; Provides a minor mode for using the fixed-pitch face. Allows users to use a -;; variable-pitch font as the default while still using fixed-pitch for code. - -;;; Code: - -(defun fixed-pitch-update-hooks (list) - "Adds `fixed-pitch-mode' to every hook in LIST." - (dolist (hook list) - (add-hook hook 'fixed-pitch-mode))) - -(defcustom fixed-pitch-whitelist-hooks '() - "List of hooks that should activate `fixed-pitch-mode'." - :type '(repeat symbol) - :group 'fixed-pitch - :set (lambda (var val) - (set-default var val) - (fixed-pitch-update-hooks val))) - -;;;###autoload -(define-minor-mode fixed-pitch-mode - "Use monospace typeface in the appropriate context." - :lighter " fxd" - (if fixed-pitch-mode - (progn (buffer-face-set 'fixed-pitch)) - (buffer-face-set))) - -(provide 'fixed-pitch) -;;; fixed-pitch.el ends here diff --git a/emacs/site-lisp/tubthumping-theme.el b/emacs/site-lisp/tubthumping-theme.el deleted file mode 100644 index a1ebc75..0000000 --- a/emacs/site-lisp/tubthumping-theme.el +++ /dev/null @@ -1,262 +0,0 @@ -;;; tubthumping-theme.el --- Monochrome theme -*- lexical-binding: t; -*- - -;; By noa, -;; -;; Version: 1.0.0 -;; Author: noa, -;; URL: https://noa.pub/404 - -;; This file is not part of Emacs. - -;;; Commentary: - -;; This is a monochrome theme for emacs. I've only themed packages i've used as i've come across colours in them. - -;; The name is an homage to the classic song, as well as to the monochrome emacs tao theme. - -;;; Code: - -(deftheme tubthumping) - -;; Original function by acdw -(defvar tubthumping/inherit - '((t ())) - "Specification to clear a given face.") - -(defgroup tubthumping-theme nil - "Customization options for the tubthumping theme family." - :group 'tubthumping - :group 'faces) - -(defcustom tubthumping-background-colour "#ffffff" - "The background colour for the tubthumping theme." - :type 'color - :group 'tubthumping-theme) - -(defcustom tubthumping-foreground-colour "#000000" - "The foreground colour for the tubthumping theme." - :type 'color - :group 'tubthumping-theme) - -(custom-theme-set-faces 'tubthumping - `(default ((t (:background ,tubthumping-background-colour :foreground ,tubthumping-foreground-colour)))) - - ;; default font lock. make comments and strings italic and everything else look the same - `(font-lock-bracket-face ,tubthumping/inherit) - `(font-lock-builtin-face ,tubthumping/inherit) - `(font-lock-constant-face ,tubthumping/inherit) - `(font-lock-delimiter-face ,tubthumping/inherit) - `(font-lock-doc-markup-face ,tubthumping/inherit) - `(font-lock-escape-face ,tubthumping/inherit) - `(font-lock-function-call-face ,tubthumping/inherit) - `(font-lock-function-name-face ,tubthumping/inherit) - `(font-lock-keyword-face ,tubthumping/inherit) - `(font-lock-misc-punctuation-face ,tubthumping/inherit) - `(font-lock-negation-char-face ,tubthumping/inherit) - `(font-lock-number-face ,tubthumping/inherit) - `(font-lock-operator-face ,tubthumping/inherit) - `(font-lock-preprocessor-face ,tubthumping/inherit) - `(font-lock-property-name-face ,tubthumping/inherit) - `(font-lock-property-use-face ,tubthumping/inherit) - `(font-lock-punctuation-face ,tubthumping/inherit) - `(font-lock-regexp-face ,tubthumping/inherit) - `(font-lock-regexp-grouping-backslash ,tubthumping/inherit) - `(font-lock-regexp-grouping-construct ,tubthumping/inherit) - `(font-lock-type-face ,tubthumping/inherit) - `(font-lock-variable-name-face ,tubthumping/inherit) - `(font-lock-variable-use-face ,tubthumping/inherit) - `(font-lock-warning-face ,tubthumping/inherit) - - ;; make strings and comments bold - `(font-lock-comment-delimiter-face ((t (:bold t)))) - `(font-lock-comment-face ((t (:bold t)))) - `(font-lock-string-face ((t (:bold t)))) - - `(region ((t ( :inverse-video t)))) - - `(highlight ((t ( :inverse-video t)))) - - `(fringe ,tubthumping/inherit) - `(cursor ((t (:background ,tubthumping-foreground-colour)))) - `(show-paren-match ((t (:inherit highlight)))) - - `(isearch ((t ( :box t)))) - - ;; replace - `(match ((t (:box t)))) - - ;; faces - `(shadow ,tubthumping/inherit) - - ;; mode line - `(mode-line ((t ( :box t)))) - `(mode-line-active ((t ( :box t)))) - `(mode-line-inactive ((t ( :box t)))) - ;; `(mode-line-buffer-id ,flear) - ;; `(mode-line-highlight ((t ( :box nil :weight normal)))) - ;; `(mode-line-emphasis ((t ( :weight bold)))) - - ;; vertical border in tuis - `(vertical-border ,tubthumping/inherit) - `(default-italic ((t (:italic t)))) - - ;; minibuffer - `(minibuffer-prompt ((t (:normal t )))) - `(minibuffer-depth-indicator ((t (:normal t )))) - - ;; link - `(link ((t (:underline t)))) - - `(header-line ((t ( :box t)))) - - ;; vertico - `(vertico-current ((t (:inherit highlight)))) - - ;; vertico-current - ;; vertico-multiline - ;; vertico-group-title - ;; vertico-group-separator - - ;; marginalia - - ;; Custom - `(custom-group-tag ((t (:weight bold :height 1.2)))) - `(custom-variable-tag ((t (:weight bold)))) - `(custom-state ,tubthumping/inherit) - `(custom-visibility ((t (:underline t)))) - `(custom-button ((t (:inherit link)))) - - ;; spell-fu - `(spell-fu-incorrect-face ((t (:underline (:style wave))))) - - ;; widgets - `(widget-field ((t ( :box t)))) - - ;; completions - `(completions-common-part ((t ( :weight bold)))) - `(completions-annotations ((t ( :slant italic)))) - - ;; orderless - `(orderless-match-face-0 ((t ( :box t)))) - `(orderless-match-face-1 ((t ( :box t)))) - `(orderless-match-face-2 ((t ( :box t)))) - `(orderless-match-face-3 ((t ( :box t)))) - - ;; org mode - `(org-document-title ((t ( :weight bold :height 1.6)))) - `(org-drawer ,tubthumping/inherit) - `(org-code ((t ( :box t)))) - ;; this one needs to be the background - `(org-hide ((t (:foreground ,tubthumping-background-colour)))) - ;; bigger fonts for headings - `(org-level-1 ((t ( :weight bold :height 1.4)))) - `(org-level-2 ((t ( :weight bold :height 1.3)))) - `(org-level-3 ((t ( :weight bold :height 1.2)))) - `(org-level-4 ((t ( :weight bold :height 1.1)))) - `(org-date ((t (:underline t)))) - `(org-table ,tubthumping/inherit) - `(org-footnote ((t (:underline t )))) - `(org-link ((t (:underline t )))) - `(org-special-keyword ,tubthumping/inherit) - `(org-block ,tubthumping/inherit) - `(org-quote ((t (:inherit org-block :slant italic)))) - `(org-verse ((t (:inherit org-block :slant italic)))) - `(org-todo ((t (:box (:line-width 1 :color ,tubthumping-foreground-colour) :bold t)))) - `(org-done ((t (:box (:line-width 1 :color ,tubthumping-background-colour) :bold t :foreground ,tubthumping-background-colour)))) - `(org-warning ((t (:inherit highlight)))) - `(org-agenda-structure ((t (:weight bold :box (:color ,tubthumping-foreground-colour) :background ,tubthumping-background-colour)))) - `(org-agenda-date ((t ( :height 1.1 )))) - `(org-agenda-date-weekend ((t (:weight bold )))) - `(org-agenda-date-today ((t (:weight bold :height 1.4)))) - `(org-agenda-done ((t (:foreground ,tubthumping-background-colour)))) - `(org-scheduled ,tubthumping/inherit) - `(org-scheduled-today ((t ( :weight bold :height 1.2)))) - `(org-ellipsis ((t ( :box nil)))) - `(org-verbatim ,tubthumping/inherit) - `(org-document-info-keyword ,tubthumping/inherit) - `(org-sexp-date ,tubthumping/inherit) - - ;; tab bar - `(tab-bar ((t (:inherit highlight)))) - - ;; variable pitch - `(variable-pitch ,tubthumping/inherit) - `(variable-pitch-text ,tubthumping/inherit) - - ;; nano modeline - `(nano-modeline-status ((t (:inherit highlight)))) - `(nano-modeline-active ((t ( :box t)))) - - ;; window divider - `(window-divider ,tubthumping/inherit) - - `(font-latex-bold-face ((t (:bold t)))) - `(font-latex-italic-face ((t ( :italic t)))) - `(font-latex-string-face ((t (:bold t)))) - `(font-latex-match-reference-keywords ,tubthumping/inherit) - `(font-latex-match-variable-keywords ,tubthumping/inherit) - - ;; Eww - `(eww-valid-certificate ((t (:bold t)))) - `(eww-invalid-certificate ((t (:inherit highlight :bold t)))) - - ;; Jabber - `(jabber-activity-face ,tubthumping/inherit) - `(jabber-chat-prompt-local ((t (:bold t)))) - `(jabber-chat-prompt-foreign ((t (:bold t)))) - `(jabber-chat-prompt-system ((t (:bold t)))) - `(jabber-rare-time-face ((t (:bold t)))) - - ;; mu4e - `(mu4e-highlight-face ((t (:inherit highlight)))) - `(mu4e-header-title-face ((t (:inherit mu4e-header-face)))) - `(mu4e-header-highlight-face ((t (:inherit highlight)))) - `(mu4e-title-face ((t (:inherit mu4e-header-face)))) - `(mu4e-replied-face ((t (:inherit mu4e-header-face :foreground unspecified)))) - `(mu4e-header-key-face ((t (:inherit mu4e-header-face)))) - `(mu4e-header-marks-face ,tubthumping/inherit) - - ;; message - `(message-header-name ,tubthumping/inherit) - `(message-header-to ,tubthumping/inherit) - `(message-header-cc ,tubthumping/inherit) - `(message-header-other ,tubthumping/inherit) - `(message-header-subject ,tubthumping/inherit) - `(message-separator ,tubthumping/inherit) - - ;; gnus - `(gnus-header-name ((t (:weight bold)))) - `(gnus-header-content ,tubthumping/inherit) - `(gnus-header-from ,tubthumping/inherit) - `(gnus-header-subject ,tubthumping/inherit) - - ;; `(ffap ((t (:foreground ,tubthumping-foreground-colour)))) - - `(warning ((t (:inherit highlight)))) - - `(ac-completion-face ((t (:underline t )))) - `(info-quoted-name ,tubthumping/inherit) - `(info-string ((t (:bold t)))) - `(icompletep-determined ,tubthumping/inherit) - `(slime-repl-inputed-output-face ,tubthumping/inherit) - `(trailing-whitespace ((t (:inherit highlight)))) - - `(lazy-highlight ((t (:box t)))) - - ;; compile - `(compilation-line-number ((t (:underline t)))) - `(compilation-column-number ((t (:underline t)))) - `(compilation-info ((t (:underline t)))) - - ;; dired - `(dired-flagged ((t (:strike-through t :bold t)))) -) - -;;;###autoload -(when load-file-name - (add-to-list 'custom-theme-load-path - (file-name-as-directory (file-name-directory load-file-name)))) - -(provide-theme 'tubthumping) -(provide 'tubthumping-theme) -;;; tubthumping-theme.el ends here diff --git a/firefox/README b/firefox/README deleted file mode 100644 index eb8063f..0000000 --- a/firefox/README +++ /dev/null @@ -1,3 +0,0 @@ -Run this firefox profile with the following command: - -firefox --profile ~/.config/firefox diff --git a/firefox/chrome/userChrome.css b/firefox/chrome/userChrome.css deleted file mode 100644 index 8674958..0000000 --- a/firefox/chrome/userChrome.css +++ /dev/null @@ -1,44 +0,0 @@ -#TabsToolbar { - visibility: collapse !important; -} - -/* ffffe8 */ - -/*#navigator-toolbox-background {*/ -/* -#nav-bar { - background: #e5e5d0 !important; -} -#nav-bar:-moz-window-inactive { - background: #ffffe8 !important; -} -#urlbar-background { - background: inherit !important; -} -*/ - -/* - * Replace navigation icons with text - */ -#back-button image, -#forward-button image, -#stop-reload-button image { - display:none !important; -} -#context-navigation .menu-iconic-left{ - -moz-margin-start:15px !important; /*adjust this for your OS/theme*/ -} -#back-button:after, -#forward-button:after, -#stop-button:after, -#reload-button:after { - content: attr(label) !important; - text-decoration: underline !important; - color: inherit !important; -} -#context-navigation{ - -moz-box-orient: vertical !important; -} -#context-navigation > .menuitem-iconic{ - -moz-box-pack: start !important; -} diff --git a/firefox/user.js b/firefox/user.js deleted file mode 100644 index 850d732..0000000 --- a/firefox/user.js +++ /dev/null @@ -1,208 +0,0 @@ -// settings to make firefox a little more comfy for me -// many tips taken from https://www.reddit.com/r/firefox/comments/17hlkhp/what_are_your_must_have_changes_in_aboutconfig/ - -// -// -// better ui - -// use system titlebar -user_pref("browser.tabs.inTitlebar", 0); - -// big square scrollbar that doesn't disappear, in lieu of native them -user_pref("widget.non-native-theme.scrollbar.style", 4); -user_pref("widget.non-native-theme.scrollbar.size.orverride", 24); -user_pref("widget.gtk.overlay-scrollbars.enabled", false); - -// make the buttons smaller -user_pref("browser.uidensity", 1); - -// make websites use the colours i choose -user_pref("browser.display.document_color_use", 2); -user_pref("browser.display.use_system_colors", true); -user_pref("browser.display.background_color", "#ffffe8"); - -// don't let websites set their own fonts -user_pref("browser.display.use_document_fonts", 0); - -// always enable cursor key navigation -// user_pref("accessibility.browsewithcaret", true); - -// nicer settings in view source -user_pref("view_source.wrap_long_lines", true); -user_pref("view_source.syntax_highlight", false); -user_pref("view_source.tab_size", 8); -//user_pref("view_source.editor.external", true); -//user_pref("view_source.editor.path", "emacs"); -//user_pref("view_source.tab", false); // open source view in new window - -// disable user interface elements -user_pref("browser.toolbars.bookmarks.visibility", "never"); - -// clean new tab page -user_pref("browser.newtabpage.activity-stream.feeds.section.topstories", false); -user_pref("browser.newtabpage.activity-stream.feeds.section.topsites", false); -user_pref("browser.newtabpage.activity-stream.showSearch", false); -user_pref("browser.newtabpage.activity-stream.showSponsoredTopSites", false); -user_pref("browser.newtabpage.enabled", false); -// TODO: still shows top sites. Unsure how to get rid. - -// boring url bar: show protocol, don't grey bits out, don't "pop it out" -user_pref("browser.urlbar.formatting.enabled", false); -user_pref("browser.urlbar.trimURLs", false); -user_pref("browser.urlbar.openViewOnFocus", false); - -// disable url bar suggestions -// user_pref("browser.urlbar.maxRichResults", -1); - -// use text in the toolbar, not icons -//user_pref("browser.chrome.toolbar_style", 1); - -// don't pop up menu on alt -user_pref("ui.key.menuAccessKeyFocuses", false); - -// default to empty headers when printing -user_pref("print.print_footerleft", ""); -user_pref("print.print_footerright", ""); -user_pref("print.print_headerleft", ""); -user_pref("print.print_headerright", ""); - -// don't show a disclaimer for about:config -user_pref("browser.aboutConfig.showWarning", false); - -// backspace to go back -user_pref("browser.backspace_action", 0); - -// -// -// Disable unused features - -// disable firefox view -user_pref("browser.tabs.firefox-view", false); - -// disable pocket -user_pref("extensions.pocket.enabled", false); -user_pref("extensions.pocket.showHome", false); -user_pref("browser.newtabpage.activity-stream.section.highlights.includePocket", false); -user_pref("browser.newtabpage.activity-stream.discoverystream.sendToPocket.enabled", false); -user_pref("browser.newtabpage.activity-stream.discoverystream.saveToPocketCard.enabled", false); - -// disable reader view -user_pref("reader.parse-on-load.enabled", false); - -// disable telemetry -user_pref("app.shield.optoutstudies.enabled", false); -user_pref("datareporting.healthreport.service.enabled", false); -user_pref("datareporting.healthreport.uploadEnabled", false); -user_pref("datareporting.policy.dataSubmissionPolicyAcceptedVersion", 2); -user_pref("datareporting.policy.dataSubmissionPolicyNotifiedTime", "1450604664862"); -user_pref("datareporting.policy.firstRunTime", "1450604654097"); - -// disable https only. -user_pref("dom.security.https_only_mode_ever_enabled", false); -user_pref("dom.security.https_only_mode", false); - -// disable experiments -user_pref("experiments.enabled", false); -user_pref("experiments.supported", false); - -// don't save passwords -user_pref("signon.rememberSignons", false); - -// disable firefox accounts -user_pref("identity.fxaccounts.enabled", false); - -// disable picture-in-picture video -user_pref("media.videocontrols.picture-in-picture.video-toggle.enabled", false); - -// disable safe browsing -user_pref("browser.safebrowsing.downloads.remote.enabled", false); -user_pref("browser.safebrowsing.enabled", false); -user_pref("browser.safebrowsing.malware.enabled", false); -user_pref("browser.safebrowsing.phishing.enabled", false); - -// -// -// Enable used features - -// enable userchrome -user_pref("toolkit.legacyUserProfileCustomizations.stylesheets", true); - -// always prompt me for download location -user_pref("browser.download.useDownloadDir", false); - -// -// -// Window oriented behaviour - -// Middle clock opens in a new window -user_pref("browser.tabs.opentabfor.middleclick", false); -user_pref("middlemouse.openNewWindow", true); - -// open links in the current tab (1), even if the website says otherwise (0) -user_pref("browser.link.open_newwindow", 1); -user_pref("browser.link.open_newwindow.restriction", 0); - -// Closing the last tab closes the browser -// user_pref("browser.tabs.closeWindowWithLastTab", false); - -// -// -// speed related things -user_pref("nglayout.initialpaint.delay", 0); - -// -// -// Settings to increase caches etc, which ostensibly speed firefox up but that many people recommend against - -// dont save browsing session to disk so often -user_pref("browser.cache.disk.enable", false); -user_pref("browser.cache.memory.enable", true); - -// Lower cache size as we are now storing it in memory not on disk -user_pref("media.cache_size", 102400); -user_pref("media.memory_caches_combined_limit_kb", 102400); -user_pref("image.mem.surfacecache.max_size_kb", 102400); - -// Only save the session once per day -user_pref("browser.sessionstore.interval", 86400000); -// Don't store recently parsed recent pages in memory -user_pref("browser.sessionhistory.max_total_viewers", 0); - -// Increase the defaults for a bunch of settings related to http requests. -user_pref("network.buffer.cache.size", 524288); -user_pref("network.buffer.cache.count", 128); -user_pref("network.http.max-connections", 1800); -user_pref("network.http.max-persistent-connections-per-server", 12); -user_pref("network.http.max-urgent-start-excessive-connections-per-host", 10); user_pref("network.http.pacing.requests.burst", 32); -user_pref("network.http.pacing.requests.min-parallelism", 10); -user_pref("network.websocket.max-connections", 400); -user_pref("network.ssl_tokens_cache_capacity", 32768); -// also see "security.pki.crlite_mode" and "browser.cache.memory.capacity" - - - -/* misc stuff */ -//user_pref("browser.fixup.dns_first_for_single_words", true); -//user_pref("browser.reader.detectedFirstArticle", true); -//user_pref("browser.search.suggest.enabled", false); -//user_pref("browser.search.update", false); -//user_pref("browser.sessionstore.restore_on_demand", false); -//user_pref("browser.sessionstore.resume_from_crash", false); - -//user_pref("browser.tabs.animate", false); -// -//user_pref("browser.tabs.warnOnClose", false); -//user_pref("browser.warnOnQuit", false); -//user_pref("browser.warnOnQuitShortcut", false); -// - -// - -//user_pref("general.smoothScroll", false); -//user_pref("keyword.enabled", false); -//user_pref("layout.spellcheckDefault", 0); -//user_pref("mousewheel.system_scroll_override.enabled", false); -//user_pref("network.allow-experiments", false); -//user_pref("network.captive-portal-service.enabled", false); -//user_pref("pdfjs.disabled", true); -//user_pref("security.webauth.u2f", true); diff --git a/fish/config.fish b/fish/config.fish deleted file mode 100644 index 046e1ff..0000000 --- a/fish/config.fish +++ /dev/null @@ -1,49 +0,0 @@ -if status is-interactive - # Commands to run in interactive sessions can go here -end - -set fish_greeting - -fish_add_path $HOME/Scripts - -set -Ux NO_COLOR - -# unset most of the colours -set fish_color_normal normal -set fish_color_command -set fish_color_quote -set fish_color_redirection -set fish_color_end -set fish_color_error -set fish_color_param -set fish_color_comment -set fish_color_match -set fish_color_selection --reverse -set fish_color_search_match --reverse -set fish_color_history_current -set fish_color_operator -set fish_color_escape -set fish_color_cwd # normal -set fish_color_cwd_root # normal -set fish_color_valid_path -set fish_color_autosuggestion --underline -set fish_color_user # normal -set fish_color_host # normal -set fish_color_cancel --reverse -set fish_pager_color_prefix --underline -set fish_pager_color_progress red -set fish_pager_color_completion # normal -set fish_pager_color_description -set fish_pager_color_selected_background --reverse -set fish_color_host_remote -set fish_pager_color_selected_description -set fish_pager_color_selected_prefix -set fish_color_option -set fish_pager_color_secondary_background -set fish_color_keyword -set fish_pager_color_background -set fish_pager_color_secondary_description -set fish_pager_color_secondary_prefix -set fish_pager_color_selected_completion -set fish_pager_color_secondary_completion -set fish_color_status diff --git a/fish/fish_variables b/fish/fish_variables deleted file mode 100644 index fc92707..0000000 --- a/fish/fish_variables +++ /dev/null @@ -1,7 +0,0 @@ -# This file contains fish universal variable definitions. -# VERSION: 3.0 -SETUVAR --export MOZ_ENABLE_WAYLAND:1 -SETUVAR --export NO_COLOR:\x1d -SETUVAR __fish_initialized:3400 -SETUVAR fish_key_bindings:fish_default_key_bindings -SETUVAR fish_user_paths:/usr/local/go/bin\x1e/home/noa/\x2econfig/Scripts\x1e/home/noa/binaries\x1e/home/noa/\x2elocal/bin diff --git a/fish/functions/fish_prompt.fish b/fish/functions/fish_prompt.fish deleted file mode 100644 index eeec7d8..0000000 --- a/fish/functions/fish_prompt.fish +++ /dev/null @@ -1,6 +0,0 @@ -function fish_prompt - #set_color $fish_color_cwd - echo -n (basename $PWD) - #set_color normal - echo -n ' ) ' -end diff --git a/fish/functions/fish_right_prompt.fish b/fish/functions/fish_right_prompt.fish deleted file mode 100644 index c1b019e..0000000 --- a/fish/functions/fish_right_prompt.fish +++ /dev/null @@ -1,2 +0,0 @@ -function fish_right_prompt -end diff --git a/fish/functions/grep.fish b/fish/functions/grep.fish deleted file mode 100644 index bf66e8e..0000000 --- a/fish/functions/grep.fish +++ /dev/null @@ -1,5 +0,0 @@ -# grep without colour - -function grep - command grep --color=never $argv -end diff --git a/fish/functions/ls.fish b/fish/functions/ls.fish deleted file mode 100644 index 94fa076..0000000 --- a/fish/functions/ls.fish +++ /dev/null @@ -1,10 +0,0 @@ -# ls but do it without colour - -function ls --description "List contents of directory" - # make ls show */=>@| indicators - isatty stdout - and set -a opt -F - - # command $__fish_ls_command $__fish_ls_color_opt $opt $argv - command ls $opt $argv -end diff --git a/git/config b/git/config deleted file mode 100644 index 66d1acb..0000000 --- a/git/config +++ /dev/null @@ -1,5 +0,0 @@ -[init] - defaultBranch = main -[user] - email = noa@gaiwan.org - name = noa diff --git a/jwmrc b/jwmrc deleted file mode 100644 index e59390c..0000000 --- a/jwmrc +++ /dev/null @@ -1,140 +0,0 @@ - - - - - - - - - - - - - - exec:~/Scripts/launch - - - - - - root:1 - - - - - Noto Sans CJK SC-16 - 4 - - 0 - - #000000 - #ffffff - #000000 - 1.0 - - - #000000 - #ffffff - #000000 - - - - - #ffffff - #000000 - - - - Noto Sans CJK SC-16 - #ffffff - #000000 - #000000 - 1 - - - - Sans-9 - - #000000 - #ffffff - - #000000 - #ffffff - - - - Sans-9 - #000000 - #ffffff - - - - - /usr/share/icons/wm-icons/32x32-aquafusion - - - /usr/local/share/jwm - - - - - - /home/noa/Pictures/Wallpapers/horse-mono.png - - - - 400 - - - 2 - - - sloppy - - - border - - - opaque - - - opaque - - - up - down - right - left - left - down - up - right - select - escape - - exec:~/Scripts/launch - exec:rofi -show calc -modi calc -no-show-match -no-sort - exec:~/Scripts/enqueue - - exec:brightnessctl -d intel_backlight set 5%- - exec:brightnessctl -d intel_backlight set 5%+ - exec:amixer -D pulse sset Master 5%+ - exec:amixer -D pulse sset Master 5%- - exec:amixer -D pulse sset Master toggle - - restart - - nextstacked - close - desktop# - window - maximize - rdesktop - ldesktop - udesktop - ddesktop - - diff --git a/mbsyncrc b/mbsyncrc deleted file mode 100644 index 3239039..0000000 --- a/mbsyncrc +++ /dev/null @@ -1,23 +0,0 @@ -IMAPAccount fastmail -Host imap.fastmail.com -User noa@gaiwan.org -#Pass 2y995b3s9j9m7c28 -PassCmd "cat ~/.config/mbsync-pass" -SSLType IMAPS - -IMAPStore fastmail-remote -Account fastmail - -MaildirStore fastmail-local -SubFolders Verbatim -Path "~/mail/" -Inbox "~/mail/Inbox" - -Channel fastmail -Far :fastmail-remote: -Near :fastmail-local: -Patterns * -Create Near -Expunge Near -SyncState * -CopyArrivalDate yes diff --git a/msmtp/config b/msmtp/config deleted file mode 100644 index f6d9dca..0000000 --- a/msmtp/config +++ /dev/null @@ -1,13 +0,0 @@ -defaults -auth on -tls on - -account fastmail -host smtp.fastmail.com -port 465 -tls_starttls off -from noa@gaiwan.org -user noa@gaiwan.org -password !!REDACTED!! - -account default: fastmail diff --git a/mutt/mailcap b/mutt/mailcap deleted file mode 100644 index c9f551b..0000000 --- a/mutt/mailcap +++ /dev/null @@ -1 +0,0 @@ -text/html; w3m -I %{charset} -T text/html; copiousoutput diff --git a/mutt/muttrc b/mutt/muttrc deleted file mode 100644 index a959277..0000000 --- a/mutt/muttrc +++ /dev/null @@ -1,71 +0,0 @@ -set mbox_type = Maildir -set folder = "~/Documents/Mail/" -set spoolfile = "+Inbox" -set postponed = "+Drafts" -set record = "+Sent" -unset move - -set signature = ~/.config/mutt/signature - -alternates .*@gaiwan.org - -set wait_key = no -# set delete -# unset confirmappend -# set quit -unset mark_old - -set status_on_top = yes -set status_format = "%r%m messages%?n? (%n new)?%?d? (%d to delete)?%?t? (%t tagged)? %>-%?p?( %p postponed ) " -set help = no - -ignore * -unignore from: to: cc: date: subject: -unhdr_order * -hdr_order from: to: cc: date: subject: - -set markers = no -unset user_agent -set sort = threads -set sort_aux = reverse-last-date-received -set date_format = "%m/%d" -set index_format="[%Z] %D %-16.16F %s" - -# Mailcap -alternative_order text/plain text text/html -set mailcap_path = ~/.config/mutt/mailcap -auto_view text/html - -# macro pager \Cu "|urlscan -cd" "call urlscan to open links - -macro index,pager,attach,compose \Cb "\ - set my_pipe_decode=\$pipe_decode pipe_decode\ - urlview\ - set pipe_decode=\$my_pipe_decode; unset my_pipe_decode" \ -"call urlview to extract URLs out of a message" - -# Colours -color normal default default -color attachment bold default default -color hdrdefault cyan default -color indicator default red -color quoted default yellow -color signature cyan default -color status reverse default default -color tilde blue default -color tree default default - -color index red default ~P -color index red default ~D -color index default yellow ~T - -color header brightdefault default ^From: -color header brightdefault default ^To: -color header brightdefault default ^Date: -color header brightdefault default ^Cc: -color header brightdefault default ^Subject: - -# emails and urls -color body brightdefault default [\-\.+_a-zA-Z0-9]+@[\-\ea-zA-Z0-9]+ -color body brightdefault default (https?|ftp)://[\-\.,/%~_:?&=\#a-zA-Z0-9]+ - diff --git a/picom/picom.conf b/picom/picom.conf deleted file mode 100644 index 0820d7e..0000000 --- a/picom/picom.conf +++ /dev/null @@ -1,18 +0,0 @@ -# picom -cfF -o 0.38 -O 200 -I 200 -t 0 -l 0 -r 3 -D2 -m 0.88 -shadow = true; -# opacity = 0.38; -fade-out-step = 200; -fade-in-step = 200; -shadow-offset-y = 6; -shadow-offset-x = 6; -shadow-radius = 0; -# fade-delta = 2; - -wintypes: -{ - # menu = { shadow = false; }; - dropdown_menu = { shadow = false; }; - popup_menu = { shadow = false; }; - utility = { shadow = false; }; -} -# TODO: make tooltips have a smaller shadow (3x3) diff --git a/rofi/config.rasi b/rofi/config.rasi deleted file mode 100644 index 3a27d77..0000000 --- a/rofi/config.rasi +++ /dev/null @@ -1,157 +0,0 @@ -configuration { - modi: "window,run,ssh,drun,combi,calc"; - font: "mono 12"; - location: 0; - yoffset: 0; - xoffset: 0; - fixed-num-lines: true; - show-icons: false; - terminal: "rofi-sensible-terminal"; - ssh-client: "ssh"; - ssh-command: "{terminal} -e {ssh-client} {host} [-p {port}]"; - run-command: "{cmd}"; - run-list-command: ""; - run-shell-command: "{terminal} -e {cmd}"; - window-command: "wmctrl -i -R {window}"; - window-match-fields: "all"; -/* icon-theme: ; */ - drun-match-fields: "name,generic,exec,categories,keywords"; -/* drun-categories: ; */ - drun-show-actions: false; - drun-display-format: "{name} [({generic})]"; - drun-url-launcher: "xdg-open"; - disable-history: false; - ignored-prefixes: ""; - sort: false; - sorting-method: "normal"; - case-sensitive: false; - cycle: true; - sidebar-mode: false; - hover-select: false; - eh: 1; - auto-select: false; - parse-hosts: false; - parse-known-hosts: true; - combi-modi: "window,run"; - matching: "normal"; - tokenize: true; - m: "-5"; -/* filter: ; */ - dpi: -1; - threads: 0; - scroll-method: 0; - window-format: "{w} {c} {t}"; - click-to-exit: true; - max-history-size: 25; - combi-hide-mode-prefix: false; - combi-display-format: "{mode} {text}"; - matching-negate-char: '-' /* unsupported */; -/* cache-dir: ; */ - window-thumbnail: false; - drun-use-desktop-cache: false; - drun-reload-desktop-cache: false; - normalize-match: false; - steal-focus: false; -/* application-fallback-icon: ; */ - pid: "/run/user/1000/rofi.pid"; -/* display-window: ; */ -/* display-windowcd: ; */ -/* display-run: ; */ -/* display-ssh: ; */ -/* display-drun: ; */ -/* display-combi: ; */ -/* display-keys: ; */ -/* display-filebrowser: ; */ - kb-primary-paste: "Control+V,Shift+Insert"; - kb-secondary-paste: "Control+v,Insert"; - kb-clear-line: "Control+w"; - kb-move-front: "Control+a"; - kb-move-end: "Control+e"; - kb-move-word-back: "Alt+b,Control+Left"; - kb-move-word-forward: "Alt+f,Control+Right"; - kb-move-char-back: "Left,Control+b"; - kb-move-char-forward: "Right,Control+f"; - kb-remove-word-back: "Control+Alt+h,Control+BackSpace"; - kb-remove-word-forward: "Control+Alt+d"; - kb-remove-char-forward: "Delete,Control+d"; - kb-remove-char-back: "BackSpace,Shift+BackSpace,Control+h"; - kb-remove-to-eol: "Control+k"; - kb-remove-to-sol: "Control+u"; - kb-accept-entry: "Control+j,Control+m,Return,KP_Enter"; - kb-accept-custom: "Control+Return"; - kb-accept-custom-alt: "Control+Shift+Return"; - kb-accept-alt: "Shift+Return"; - kb-delete-entry: "Shift+Delete"; - kb-mode-next: "Shift+Right,Control+Tab"; - kb-mode-previous: "Shift+Left,Control+ISO_Left_Tab"; - kb-mode-complete: "Control+l"; - kb-row-left: "Control+Page_Up"; - kb-row-right: "Control+Page_Down"; - kb-row-up: "Up,Control+p,ISO_Left_Tab"; - kb-row-down: "Down,Control+n"; - kb-row-tab: "Tab"; - kb-page-prev: "Page_Up"; - kb-page-next: "Page_Down"; - kb-row-first: "Home,KP_Home"; - kb-row-last: "End,KP_End"; - kb-row-select: "Control+space"; - kb-screenshot: "Alt+S"; - kb-ellipsize: "Alt+period"; - kb-toggle-case-sensitivity: "grave,dead_grave"; - kb-toggle-sort: "Alt+grave"; - kb-cancel: "Escape,Control+g,Control+bracketleft"; - kb-custom-1: "Alt+1"; - kb-custom-2: "Alt+2"; - kb-custom-3: "Alt+3"; - kb-custom-4: "Alt+4"; - kb-custom-5: "Alt+5"; - kb-custom-6: "Alt+6"; - kb-custom-7: "Alt+7"; - kb-custom-8: "Alt+8"; - kb-custom-9: "Alt+9"; - kb-custom-10: "Alt+0"; - kb-custom-11: "Alt+exclam"; - kb-custom-12: "Alt+at"; - kb-custom-13: "Alt+numbersign"; - kb-custom-14: "Alt+dollar"; - kb-custom-15: "Alt+percent"; - kb-custom-16: "Alt+dead_circumflex"; - kb-custom-17: "Alt+ampersand"; - kb-custom-18: "Alt+asterisk"; - kb-custom-19: "Alt+parenleft"; - kb-select-1: "Super+1"; - kb-select-2: "Super+2"; - kb-select-3: "Super+3"; - kb-select-4: "Super+4"; - kb-select-5: "Super+5"; - kb-select-6: "Super+6"; - kb-select-7: "Super+7"; - kb-select-8: "Super+8"; - kb-select-9: "Super+9"; - kb-select-10: "Super+0"; - ml-row-left: "ScrollLeft"; - ml-row-right: "ScrollRight"; - ml-row-up: "ScrollUp"; - ml-row-down: "ScrollDown"; - me-select-entry: "MousePrimary"; - me-accept-entry: "MouseDPrimary"; - me-accept-custom: "Control+MouseDPrimary"; - timeout { - action: "kb-cancel"; - delay: 0; - } - filebrowser { - directories-first: true; - sorting-method: "name"; - } -} - -/* -window { - anchor: north; - location: north; - width: 100%; - padding: 4px; -} -*/ -@theme "spotlight" diff --git a/rofi/spotlight.rasi b/rofi/spotlight.rasi deleted file mode 100644 index d93b50c..0000000 --- a/rofi/spotlight.rasi +++ /dev/null @@ -1,78 +0,0 @@ -/******************************************************************************* - * MACOS SPOTLIGHT LIKE THEME FOR ROFI - * User : LR-Tech - * Theme Repo : https://github.com/lr-tech/rofi-themes-collection - *******************************************************************************/ - -* { - font: "Noto Serif CJK SC 14"; - bg: #ffffe8; - fg: black; - - background-color: @bg; - text-color: @fg; -} - -window { - background-color: @fg; - - location: center; - anchor: center; - width: 50%; - height: 60%; - - border: 1px; - border-color: @fg; - border-radius: 0; - -} - -inputbar { - font: @font; - padding: 12px; - children: [ entry ]; -} - -entry { - font: inherit; - - /* placeholder : ""; */ - /* placeholder-color : @fg; */ -} - -message { - border: 2px 0 0; - border-color: @bg; - background-color: red; -} - -textbox { - padding: 12px; - background-color: @bg; -} - -listview { - columns: 1; - fixed-height: false; - border: 1px 0 0; - padding: 12px; - border-color: @fg; -} - -element { - padding: 6px; - background-color: @bg; -} - -element normal active { - border: 1px; - border-color: @fg; -} - -element selected normal, -element selected active { - background-color: @bg; - text-color: @fg; - border: 2px; - border-color: @fg; -} diff --git a/setup.sh b/setup.sh deleted file mode 100755 index 14caacf..0000000 --- a/setup.sh +++ /dev/null @@ -1,106 +0,0 @@ -#!/usr/bin/env sh - -set -e - -echo "Hi noa. Let's get things set up~" -echo "This script assumes a kde neon install." -read -p "Press RET when you are ready to start." - -echo -echo "=== SYSTEM UPDATE ===" -pkcon refresh -pkcon update - -echo -echo "=== DISABLE SNAP AND APPARMOR ===" -sudo apt remove -y plasma-discover-backend-snap -sudo systemctl stop apparmor -sudo systemctl disable apparmor -sudo apt remove apparmor - -echo -echo "=== CONFIGURE PLASMA ===" - -## Put control at left of space bar -## Better touchpad settings -## Night light -## Faster animations - -## Open krunner instead of application launcher -kwriteconfig5 --file ~/.config/kwinrc --group ModifierOnlyShortcuts --key Meta "org.kde.krunner,/App,,display" - -## Nicer application launcher -## Nicer task bar - -#echo -#echo "=== INSTALL FONTS ===" -#sudo apt install fonts-noto-core - -echo "=== SET UP CHINESE INPUT ===" -sudo apt install -y --install-recommends --install-suggests fcitx5 -sudo apt remove -y im-config - -echo -echo "=== INSTALL DESKTOP PROGRAMS FROM APT ===" -sudo apt install rclone keepassxc - -echo -echo "=== INSTALL DESKTOP PROGRAMS FROM FLATHUB ===" -flatpak install flathub net.ankiweb.Anki - -echo -echo "=== CONFIGURE FIREFOX ===" -# copy user.js to right location -# copy userchrome to right location - -echo -echo "=== INSTALL FIREFOX ADDONS ===" -# - https://addons.mozilla.org/en-US/firefox/addon/keepassxc-browser/ -# - https://addons.mozilla.org/en-US/firefox/addon/ublock-origin/ -# - https://addons.mozilla.org/en-US/firefox/addon/plasma-integration/ -# - https://addons.mozilla.org/en-US/firefox/addon/zhongwen/ -# - single tab? - -echo -echo "=== FETCH FILES ===" -while [ ! -f ~/.config/Passwords.kdbx ]; do - read -p "It looks like ~/.config/Passwords.kdbx doesn't exist. Make sure it exists and press RET when you're ready." -done - -read -rp "Fastmail username: " fastmailusername -echo "Now go to https://app.fastmail.com/settings/security/integrations/devicekeys/new?u=0b814011 and create a new app password with access to webdav." -read -rsp "Fastmail app password: " fastmailpassword -echo # Read with -s appears not to properly newline - -rclone config create fastmail webdav \ - url "https://webdav.fastmail.com/" \ - vendor "fastmail" \ - user "$fastmailusername" \ - pass "$fastmailpassword" \ - --obscure - -echo -rclone copy "fastmail:noa.gaiwan.org/files/10-19 Personal" "$HOME/10-19 Personal" -P -rclone copy "fastmail:noa.gaiwan.org/files/20-29 Study" "$HOME/20-29 Study" -P -rclone copy "fastmail:noa.gaiwan.org/files/30-39 Media" "$HOME/30-39 Media" -P -rclone copy "fastmail:noa.gaiwan.org/files/40-49 Words" "$HOME/40-49 Words" -P -rclone copy "fastmail:noa.gaiwan.org/files/50-59 Code" "$HOME/50-59 Code" -P - -echo -echo "=== CONFIGURE MAIL ===" -echo "Now go to https://app.fastmail.com/settings/security/integrations/devicekeys/new?u=0b814011 and create a new app password with access to imap and smtp." -read -rp "Fastmail app password: " fastmailpassword -echo # Read with -s appears not to properly newline -sed -i "s/!!REDACTED!!/$fastmailpassword/" ~/.config/mbsyncrc -sed -i "s/!!REDACTED!!/$fastmailpassword/" ~/.config/msmtp/config - -# mu init --maildir=~/mail '--my-address=/.*@gaiwan\.org/' -# mu index - -#echo -#echo "=== DOWNLOAD WIKIPEDIA MIRROR ===" -#echo "Go to https://ftp.halifax.rwth-aachen.de/aarddict/zhwiki/ and download the latest slob file to ~/Documents/Dictionaries." - -echo -echo "Thanks~" - diff --git a/user-dirs.dirs b/user-dirs.dirs deleted file mode 100644 index f0f271b..0000000 --- a/user-dirs.dirs +++ /dev/null @@ -1,8 +0,0 @@ -XDG_DESKTOP_DIR="$HOME" -XDG_DOCUMENTS_DIR="$HOME/data" -XDG_DOWNLOAD_DIR="/tmp" -XDG_MUSIC_DIR="$HOME/media/music" -XDG_PICTURES_DIR="$HOME/media/images" -XDG_PUBLICSHARE_DIR="/tmp" -XDG_TEMPLATES_DIR="/tmp" -XDG_VIDEOS_DIR="$HOME/media/videos" diff --git a/xdm/README b/xdm/README deleted file mode 100644 index 3f5b24b..0000000 --- a/xdm/README +++ /dev/null @@ -1 +0,0 @@ -The files in this directory should be copied to /etc/X11/xdm/ diff --git a/xdm/Xresources b/xdm/Xresources deleted file mode 100644 index 4d7126d..0000000 --- a/xdm/Xresources +++ /dev/null @@ -1,23 +0,0 @@ -Xcursor.theme: whiteglass - -xlogin.Login.greeting: -xlogin.Login.fail: Incorrect -xlogin.Login.namePrompt: Username: -xlogin.Login.passwdPrompt: Password: -xlogin.Login.echoPasswd: true - -xlogin.Login.face: Noto sans cjk sc-18 -xlogin.Login.greetFace: Noto sans cjk sc-18 -xlogin.Login.greetColor: black -xlogin.Login.promptFace: Noto sans cjk sc-18 -xlogin.Login.failFace: Noto sans cjk sc-18 -xlogin.Login.failColor: black - -! user input colours -xlogin.Login.background: #ffffe8 -xlogin.Login.foreground: #000000 - -xlogin.Login.borderWidth: 1 -xlogin.Login.frameWidth: 0 -xlogin.Login.innerFramesWidth: 0 -xlogin.Login.sepWidth: 0 diff --git a/xdm/Xsession b/xdm/Xsession deleted file mode 100755 index a564fb0..0000000 --- a/xdm/Xsession +++ /dev/null @@ -1,131 +0,0 @@ -#!/bin/sh -# -# /etc/X11/Xsession -# -# global Xsession file -- used by display managers and xinit (startx) - -# $Id: Xsession 967 2005-12-27 07:20:55Z dnusinow $ - -set -e - -PROGNAME=Xsession - -message () { - # pretty-print messages of arbitrary length; use xmessage if it - # is available and $DISPLAY is set - MESSAGE="$PROGNAME: $*" - echo "$MESSAGE" | fold -s -w ${COLUMNS:-80} >&2 - if [ -n "$DISPLAY" ] && command -v xmessage > /dev/null 2>&1; then - echo "$MESSAGE" | fold -s -w ${COLUMNS:-80} | xmessage -center -file - - fi -} - -message_nonl () { - # pretty-print messages of arbitrary length (no trailing newline); use - # xmessage if it is available and $DISPLAY is set - MESSAGE="$PROGNAME: $*" - echo -n "$MESSAGE" | fold -s -w ${COLUMNS:-80} >&2; - if [ -n "$DISPLAY" ] && command -v xmessage > /dev/null 2>&1; then - echo -n "$MESSAGE" | fold -s -w ${COLUMNS:-80} | xmessage -center -file - - fi -} - -errormsg () { - # exit script with error - message "$*" - exit 1 -} - -internal_errormsg () { - # exit script with error; essentially a "THIS SHOULD NEVER HAPPEN" message - # One big call to message() for the sake of xmessage; if we had two then - # the user would have dismissed the error we want reported before seeing the - # request to report it. - errormsg "$*" \ - "Please report the installed version of the \"x11-common\"" \ - "package and the complete text of this error message to" \ - "." -} - -# initialize variables for use by all session scripts - -OPTIONFILE=/etc/X11/Xsession.options - -SYSRESOURCES=/etc/X11/Xresources -USRRESOURCES=$HOME/.Xresources - -SYSSESSIONDIR=/etc/X11/Xsession.d -USERXSESSION=$HOME/.config/xsession -USERXSESSIONRC=$HOME/.xsessionrc -ALTUSERXSESSION=$HOME/.Xsession -ERRFILE=$HOME/.local/share/xsession-errors - -OPTIONS="$( - if [ -r "$OPTIONFILE" ]; then - cat "$OPTIONFILE" - fi - if [ -d /etc/X11/Xsession.options.d ]; then - run-parts --list --regex '\.conf$' /etc/X11/Xsession.options.d | xargs -d '\n' cat - fi -)" - -has_option() { - # Ensure that a later no-foo overrides an earlier foo - if [ "$(echo "$OPTIONS" | grep -Eo "^(no-)?$1\>" | tail -n 1)" = "$1" ]; then - return 0 - else - return 1 - fi -} - -# attempt to create an error file; abort if we cannot -if (umask 077 && touch "$ERRFILE") 2> /dev/null && [ -w "$ERRFILE" ] && - [ ! -L "$ERRFILE" ]; then - chmod 600 "$ERRFILE" -elif ERRFILE=$(mktemp 2> /dev/null); then - if ! ln -sf "$ERRFILE" "${TMPDIR:=/tmp}/xsession-$USER"; then - message "warning: unable to symlink \"$TMPDIR/xsession-$USER\" to" \ - "\"$ERRFILE\"; look for session log/errors in" \ - "\"$TMPDIR/xsession-$USER\"." - fi -else - errormsg "unable to create X session log/error file; aborting." -fi - -exec >>"$ERRFILE" 2>&1 - -echo "$PROGNAME: X session started for $LOGNAME at $(date)" - -# sanity check; is our session script directory present? -if [ ! -d "$SYSSESSIONDIR" ]; then - errormsg "no \"$SYSSESSIONDIR\" directory found; aborting." -fi - -# Attempt to create a file of non-zero length in /tmp; a full filesystem can -# cause mysterious X session failures. We do not use touch, :, or test -w -# because they won't actually create a file with contents. We also let standard -# error from mktemp and echo go to the error file to aid the user in -# determining what went wrong. -WRITE_TEST=$(mktemp) -if ! echo "*" >>"$WRITE_TEST"; then - message "warning: unable to write to ${WRITE_TEST%/*}; X session may exit" \ - "with an error" -fi -rm -f "$WRITE_TEST" - -# use run-parts to source every file in the session directory; we source -# instead of executing so that the variables and functions defined above -# are available to the scripts, and so that they can pass variables to each -# other -SESSIONFILES=$(run-parts --list $SYSSESSIONDIR) -if [ -n "$SESSIONFILES" ]; then - set +e - for SESSIONFILE in $SESSIONFILES; do - . $SESSIONFILE - done - set -e -fi - -exit 0 - -# vim:set ai et sts=2 sw=2 tw=80: diff --git a/xdm/Xsetup b/xdm/Xsetup deleted file mode 100755 index 6db7807..0000000 --- a/xdm/Xsetup +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/sh -# -# This script is run as root before showing login widget. - -xsetroot -solid "#ffffe8" -# picom -b --config /home/noa/.config/picom/picom.conf diff --git a/xmodmap b/xmodmap deleted file mode 100644 index b4ab7b2..0000000 --- a/xmodmap +++ /dev/null @@ -1,14 +0,0 @@ -clear lock -clear mod1 -clear control - -! Set key left of spacebar to control -keycode 64 = Control_L -add control = Control_L - -! Set key right of spacebar to alt -keycode 108 = Alt_L -add mod1 = Alt_L - -! Set caps lock to search -keycode 66 = XF86Search diff --git a/xsession b/xsession deleted file mode 100755 index c300841..0000000 --- a/xsession +++ /dev/null @@ -1,26 +0,0 @@ -brightnessctl -d intel_backlight set 25% - -# compositor -picom -b - -# dock apps -cbatticon & -pnmixer & -nm-tray & -qlipper & - -# password manager -keepassxc & - -# ime -GTK_IM_MODULE=fcitx -QT_IM_MODULE=fcitx -XMODIFIERS=@im=fcitx -fcitx5 -d - -# put ctrl left of spacebar and caps to search key. -# this has to come after fcitx -xmodmap ~/.config/xmodmap - -# exec startfluxbox -exec jwm -f ~/.config/jwmrc -- cgit 1.4.1-2-gfad0