├── .conform.yaml ├── .dir-locals.el ├── .envrc ├── .github ├── renovate.json5 └── workflows │ └── ci.yml ├── .gitignore ├── LICENSE ├── README.org ├── dev ├── flake-module.nix ├── flake.lock ├── flake.nix ├── nix.conf ├── screenshots.el └── test-home-configuration.nix ├── flake.lock ├── flake.nix ├── init.org ├── lisp ├── ff-test-test.el ├── ff-test.el ├── pairable.el ├── readable-mono-theme.el ├── readable-typo-theme.el └── readable.el ├── lock ├── archive.lock ├── flake.lock └── flake.nix ├── media ├── emacs-lisp-mode-dark.png ├── emacs-lisp-mode-light.png ├── markdown-mode-dark.png ├── markdown-mode-light.png ├── org-mode-dark.png ├── org-mode-light.png ├── rst-mode-dark.png ├── rst-mode-light.png └── samples │ ├── example-image.jpg │ ├── sample.md │ ├── sample.org │ └── sample.rst ├── nix ├── home-manager.nix └── packages │ ├── emacs-config │ ├── build-config.nix │ └── default.nix │ └── emacs-env │ ├── default.nix │ ├── inputOverrides.nix │ ├── packageOverrides.nix │ └── registries.nix ├── recipes ├── adaptive-wrap ├── cobol-mode ├── compat ├── dired-git-info ├── epithet ├── explain-pause-mode ├── ghelp ├── gptel-aibo ├── gptel-quick ├── indent-bars ├── minuet ├── nov ├── org-contrib ├── org-limit-image-size ├── pairable ├── plz ├── queue ├── readable ├── readable-mono-theme ├── readable-typo-theme ├── spinner ├── ultra-scroll ├── valign ├── vundo └── ws-butler ├── shell.nix └── templates /.conform.yaml: -------------------------------------------------------------------------------- 1 | policies: 2 | - type: commit 3 | spec: 4 | header: 5 | length: 89 6 | imperative: true 7 | case: lower 8 | invalidLastCharacters: . 9 | gpg: 10 | required: true 11 | spellcheck: 12 | locale: US 13 | conventional: 14 | types: 15 | - feat 16 | - fix 17 | - build 18 | - chore 19 | - ci 20 | - docs 21 | - pref 22 | - refactor 23 | - style 24 | - test 25 | scopes: 26 | - flake 27 | - github 28 | - lock 29 | - theme 30 | descriptionLength: 72 31 | -------------------------------------------------------------------------------- /.dir-locals.el: -------------------------------------------------------------------------------- 1 | ((nil . ((apheleia-formatter . treefmt))) 2 | (auto-mode-alist . (("recipes/.*\\'" . lisp-data-mode) 3 | ("templates\\'" . lisp-data-mode)))) 4 | -------------------------------------------------------------------------------- /.envrc: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | export NIX_USER_CONF_FILES="$PWD/dev/nix.conf" 3 | 4 | if command -v nix >/dev/null; then 5 | if nix print-dev-env --help >/dev/null 2>&1; then 6 | use flake 7 | else 8 | use nix 9 | watch_file ./flake.nix 10 | watch_file ./dev/flake-parts.nix 11 | fi 12 | else 13 | echo 'The development environment is using Nix to provide all the tools, please install Nix:' >&2 14 | echo 'https://nixos.org/download.html' >&2 15 | fi 16 | 17 | unset IN_NIX_SHELL 18 | -------------------------------------------------------------------------------- /.github/renovate.json5: -------------------------------------------------------------------------------- 1 | { 2 | $schema: "https://docs.renovatebot.com/renovate-schema.json", 3 | extends: [ 4 | "config:recommended", 5 | "helpers:pinGitHubActionDigests", 6 | ":semanticCommits", 7 | ], 8 | labels: [ 9 | "automated", 10 | "dependencies", 11 | "chore", 12 | ], 13 | vulnerabilityAlerts: { 14 | enabled: true, 15 | }, 16 | packageRules: [ 17 | { 18 | groupName: "all dependencies", 19 | groupSlug: "all", 20 | matchPackageNames: ["*"], 21 | separateMajorMinor: false, 22 | extends: ["schedule:weekly"], 23 | }, 24 | ], 25 | lockFileMaintenance: { 26 | enabled: true, 27 | extends: ["schedule:weekly"], 28 | }, 29 | nix: { 30 | enabled: true, 31 | }, 32 | } 33 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: CI 3 | 4 | on: 5 | push: 6 | branches: 7 | - main 8 | pull_request: 9 | branches: 10 | - main 11 | 12 | env: 13 | # renovate: datasource=github-releases depName=nixos/nix 14 | NIX_VERSION: 2.18.2 15 | 16 | jobs: 17 | prepare: 18 | name: Prepare 19 | runs-on: ubuntu-latest 20 | outputs: 21 | checks: ${{ steps.checks.outputs.checks }} 22 | steps: 23 | - name: Checkout 24 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 25 | 26 | - name: Install Nix 27 | uses: DeterminateSystems/nix-installer-action@e50d5f73bfe71c2dd0aa4218de8f4afa59f8f81d # v16 28 | with: 29 | nix-package-url: https://releases.nixos.org/nix/nix-${{ env.NIX_VERSION }}/nix-${{ env.NIX_VERSION }}-x86_64-linux.tar.xz 30 | extra-conf: | 31 | http-connections = 50 32 | max-jobs = auto 33 | diagnostic-endpoint: '' 34 | 35 | - name: Find checks 36 | id: checks 37 | run: | 38 | nix eval --json --apply builtins.attrNames .#checks.x86_64-linux | sed 's|^|checks=|' >>$GITHUB_OUTPUT 39 | echo $GITHUB_OUTPUT 40 | 41 | check: 42 | name: Check 43 | needs: 44 | - prepare 45 | strategy: 46 | fail-fast: false 47 | matrix: 48 | check: ${{ fromJSON(needs.prepare.outputs.checks) }} 49 | runs-on: ubuntu-latest 50 | steps: 51 | - name: Checkout 52 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 53 | 54 | - name: Install Nix 55 | uses: DeterminateSystems/nix-installer-action@e50d5f73bfe71c2dd0aa4218de8f4afa59f8f81d # v16 56 | with: 57 | nix-package-url: https://releases.nixos.org/nix/nix-${{ env.NIX_VERSION }}/nix-${{ env.NIX_VERSION }}-x86_64-linux.tar.xz 58 | extra-conf: | 59 | http-connections = 50 60 | max-jobs = auto 61 | diagnostic-endpoint: '' 62 | 63 | - name: Nix cache (cachix) 64 | uses: cachix/cachix-action@ad2ddac53f961de1989924296a1f236fcfbaa4fc # v15 65 | with: 66 | useDaemon: true 67 | name: terlar 68 | authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}' 69 | extraPullNames: nix-community 70 | 71 | - name: Run check 72 | run: nix build .#checks.x86_64-linux.${{ matrix.check }} 73 | 74 | build: 75 | name: Build 76 | strategy: 77 | matrix: 78 | os: [ubuntu-latest] 79 | runs-on: ${{ matrix.os }} 80 | steps: 81 | - name: Checkout 82 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 83 | 84 | - name: Install Nix 85 | uses: DeterminateSystems/nix-installer-action@e50d5f73bfe71c2dd0aa4218de8f4afa59f8f81d # v16 86 | with: 87 | nix-package-url: https://releases.nixos.org/nix/nix-${{ env.NIX_VERSION }}/nix-${{ env.NIX_VERSION }}-x86_64-linux.tar.xz 88 | extra-conf: | 89 | http-connections = 50 90 | max-jobs = auto 91 | diagnostic-endpoint: '' 92 | 93 | - name: Nix cache (cachix) 94 | uses: cachix/cachix-action@ad2ddac53f961de1989924296a1f236fcfbaa4fc # v15 95 | with: 96 | useDaemon: true 97 | name: terlar 98 | authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}' 99 | extraPullNames: nix-community 100 | 101 | - name: Build default package 102 | run: nix build --print-build-logs 103 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Nix 2 | .direnv 3 | .pre-commit-config.yaml 4 | result 5 | result-* 6 | 7 | # Compiled 8 | *.elc 9 | 10 | # Generated 11 | init.el 12 | 13 | # Backup files 14 | *~ 15 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Terje Larsen 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.org: -------------------------------------------------------------------------------- 1 | init.org -------------------------------------------------------------------------------- /dev/flake-module.nix: -------------------------------------------------------------------------------- 1 | { inputs, ... }: 2 | 3 | { 4 | imports = [ 5 | inputs.dev-flake.flakeModule 6 | ./test-home-configuration.nix 7 | ]; 8 | 9 | dev.name = "terlar/emacs-config"; 10 | 11 | perSystem = 12 | { 13 | config, 14 | pkgs, 15 | ... 16 | }: 17 | { 18 | pre-commit.settings.hooks = { 19 | conform.enable = true; 20 | statix.settings.ignore = [ "lock" ]; 21 | }; 22 | 23 | treefmt = { 24 | programs.nixfmt = { 25 | enable = true; 26 | package = pkgs.nixfmt-rfc-style; 27 | }; 28 | settings.formatter.nixfmt.excludes = [ "lock/**/*.nix" ]; 29 | }; 30 | 31 | devshells.default = { 32 | commands = [ 33 | { package = pkgs.gdb; } 34 | { 35 | name = "test-emacs-config"; 36 | help = "launch bundled Emacs with configuration from source"; 37 | category = "emacs"; 38 | command = '' 39 | exec nix run $PRJ_ROOT 40 | ''; 41 | } 42 | { 43 | package = config.packages.reloadEmacsConfig; 44 | help = "reload and launch Emacs service"; 45 | category = "emacs"; 46 | } 47 | { 48 | package = config.packages.updateCaches; 49 | help = "update Nix caches"; 50 | category = "nix"; 51 | } 52 | { 53 | name = "update-screenshots"; 54 | help = "generate new screenshots"; 55 | category = "emacs"; 56 | command = '' 57 | exec nix run $PRJ_ROOT#updateScreenshots 58 | ''; 59 | } 60 | ]; 61 | }; 62 | 63 | packages = { 64 | default = pkgs.writeShellApplication { 65 | name = "test-emacs-config"; 66 | runtimeInputs = [ 67 | config.packages.emacs-env 68 | pkgs.xorg.lndir 69 | ]; 70 | text = '' 71 | XDG_DATA_DIRS="$XDG_DATA_DIRS:${ 72 | builtins.concatStringsSep ":" (map (x: "${x}/share") config.packages.emacs-config.runtimeInputs) 73 | }" 74 | EMACS_DIR="$(mktemp -td emacs.XXXXXXXXXX)" 75 | lndir -silent ${config.packages.emacs-config} "$EMACS_DIR" 76 | emacs --init-directory "$EMACS_DIR" "$@" 77 | ''; 78 | }; 79 | 80 | reloadEmacsConfig = pkgs.writeShellApplication { 81 | name = "reload-emacs-config"; 82 | text = '' 83 | systemctl --user restart emacs.service 84 | while ! emacsclient -a false -e t 2>/dev/null 85 | do sleep 1; done 86 | emacsclient -nc 87 | ''; 88 | }; 89 | 90 | updateCaches = pkgs.writeShellApplication { 91 | name = "update-caches"; 92 | runtimeInputs = [ pkgs.cachix ]; 93 | text = '' 94 | cachix use -O . nix-community 95 | cachix use -O . terlar 96 | ''; 97 | }; 98 | 99 | updateScreenshots = pkgs.writeShellApplication { 100 | name = "update-screenshots"; 101 | runtimeInputs = [ 102 | pkgs.xorg.lndir 103 | config.packages.emacs-env 104 | ]; 105 | text = '' 106 | EMACS_DIR="$(mktemp -td emacs.XXXXXXXXXX)" 107 | lndir -silent ${config.packages.emacs-config} "$EMACS_DIR" 108 | emacs --fullscreen --init-directory "$EMACS_DIR" --load ${./screenshots.el} --eval '(kill-emacs)' 109 | ''; 110 | }; 111 | }; 112 | 113 | checks = { 114 | build-config = config.packages.emacs-config; 115 | build-env = config.packages.emacs-env; 116 | build-config-pgtk = config.packages.emacs-config-pgtk; 117 | build-env-pgtk = config.packages.emacs-env-pgtk; 118 | }; 119 | }; 120 | } 121 | -------------------------------------------------------------------------------- /dev/flake.lock: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "dev-flake": { 4 | "inputs": { 5 | "devshell": "devshell", 6 | "flake-parts": "flake-parts", 7 | "git-hooks": "git-hooks", 8 | "nixpkgs": [ 9 | "nixpkgs" 10 | ], 11 | "treefmt": "treefmt" 12 | }, 13 | "locked": { 14 | "lastModified": 1748247580, 15 | "narHash": "sha256-PBCmjpL5b25Ehf+UP+DxhK5IUJrZ+YZucXoB1Ts4+mo=", 16 | "owner": "terlar", 17 | "repo": "dev-flake", 18 | "rev": "49c60d679c5cdf6b3ff9bfd19393fe11ea3728c7", 19 | "type": "github" 20 | }, 21 | "original": { 22 | "owner": "terlar", 23 | "repo": "dev-flake", 24 | "type": "github" 25 | } 26 | }, 27 | "devshell": { 28 | "inputs": { 29 | "nixpkgs": [ 30 | "dev-flake", 31 | "nixpkgs" 32 | ] 33 | }, 34 | "locked": { 35 | "lastModified": 1741473158, 36 | "narHash": "sha256-kWNaq6wQUbUMlPgw8Y+9/9wP0F8SHkjy24/mN3UAppg=", 37 | "owner": "numtide", 38 | "repo": "devshell", 39 | "rev": "7c9e793ebe66bcba8292989a68c0419b737a22a0", 40 | "type": "github" 41 | }, 42 | "original": { 43 | "owner": "numtide", 44 | "repo": "devshell", 45 | "type": "github" 46 | } 47 | }, 48 | "flake-compat": { 49 | "flake": false, 50 | "locked": { 51 | "lastModified": 1696426674, 52 | "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", 53 | "owner": "edolstra", 54 | "repo": "flake-compat", 55 | "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", 56 | "type": "github" 57 | }, 58 | "original": { 59 | "owner": "edolstra", 60 | "repo": "flake-compat", 61 | "type": "github" 62 | } 63 | }, 64 | "flake-compat_2": { 65 | "flake": false, 66 | "locked": { 67 | "lastModified": 1747046372, 68 | "narHash": "sha256-CIVLLkVgvHYbgI2UpXvIIBJ12HWgX+fjA8Xf8PUmqCY=", 69 | "owner": "edolstra", 70 | "repo": "flake-compat", 71 | "rev": "9100a0f413b0c601e0533d1d94ffd501ce2e7885", 72 | "type": "github" 73 | }, 74 | "original": { 75 | "owner": "edolstra", 76 | "repo": "flake-compat", 77 | "type": "github" 78 | } 79 | }, 80 | "flake-parts": { 81 | "inputs": { 82 | "nixpkgs-lib": "nixpkgs-lib" 83 | }, 84 | "locked": { 85 | "lastModified": 1743550720, 86 | "narHash": "sha256-hIshGgKZCgWh6AYJpJmRgFdR3WUbkY04o82X05xqQiY=", 87 | "owner": "hercules-ci", 88 | "repo": "flake-parts", 89 | "rev": "c621e8422220273271f52058f618c94e405bb0f5", 90 | "type": "github" 91 | }, 92 | "original": { 93 | "owner": "hercules-ci", 94 | "repo": "flake-parts", 95 | "type": "github" 96 | } 97 | }, 98 | "git-hooks": { 99 | "inputs": { 100 | "flake-compat": "flake-compat", 101 | "gitignore": "gitignore", 102 | "nixpkgs": [ 103 | "dev-flake", 104 | "nixpkgs" 105 | ] 106 | }, 107 | "locked": { 108 | "lastModified": 1747372754, 109 | "narHash": "sha256-2Y53NGIX2vxfie1rOW0Qb86vjRZ7ngizoo+bnXU9D9k=", 110 | "owner": "cachix", 111 | "repo": "git-hooks.nix", 112 | "rev": "80479b6ec16fefd9c1db3ea13aeb038c60530f46", 113 | "type": "github" 114 | }, 115 | "original": { 116 | "owner": "cachix", 117 | "repo": "git-hooks.nix", 118 | "type": "github" 119 | } 120 | }, 121 | "gitignore": { 122 | "inputs": { 123 | "nixpkgs": [ 124 | "dev-flake", 125 | "git-hooks", 126 | "nixpkgs" 127 | ] 128 | }, 129 | "locked": { 130 | "lastModified": 1709087332, 131 | "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=", 132 | "owner": "hercules-ci", 133 | "repo": "gitignore.nix", 134 | "rev": "637db329424fd7e46cf4185293b9cc8c88c95394", 135 | "type": "github" 136 | }, 137 | "original": { 138 | "owner": "hercules-ci", 139 | "repo": "gitignore.nix", 140 | "type": "github" 141 | } 142 | }, 143 | "home-manager": { 144 | "inputs": { 145 | "nixpkgs": [ 146 | "nixpkgs" 147 | ] 148 | }, 149 | "locked": { 150 | "lastModified": 1748830238, 151 | "narHash": "sha256-EB+LzYHK0D5aqxZiYoPeoZoOzSAs8eqBDxm3R+6wMKU=", 152 | "owner": "nix-community", 153 | "repo": "home-manager", 154 | "rev": "c7fdb7e90bff1a51b79c1eed458fb39e6649a82a", 155 | "type": "github" 156 | }, 157 | "original": { 158 | "owner": "nix-community", 159 | "repo": "home-manager", 160 | "type": "github" 161 | } 162 | }, 163 | "nixpkgs": { 164 | "locked": { 165 | "lastModified": 1748693115, 166 | "narHash": "sha256-StSrWhklmDuXT93yc3GrTlb0cKSS0agTAxMGjLKAsY8=", 167 | "owner": "nixos", 168 | "repo": "nixpkgs", 169 | "rev": "910796cabe436259a29a72e8d3f5e180fc6dfacc", 170 | "type": "github" 171 | }, 172 | "original": { 173 | "owner": "nixos", 174 | "ref": "nixos-unstable", 175 | "repo": "nixpkgs", 176 | "type": "github" 177 | } 178 | }, 179 | "nixpkgs-lib": { 180 | "locked": { 181 | "lastModified": 1743296961, 182 | "narHash": "sha256-b1EdN3cULCqtorQ4QeWgLMrd5ZGOjLSLemfa00heasc=", 183 | "owner": "nix-community", 184 | "repo": "nixpkgs.lib", 185 | "rev": "e4822aea2a6d1cdd36653c134cacfd64c97ff4fa", 186 | "type": "github" 187 | }, 188 | "original": { 189 | "owner": "nix-community", 190 | "repo": "nixpkgs.lib", 191 | "type": "github" 192 | } 193 | }, 194 | "root": { 195 | "inputs": { 196 | "dev-flake": "dev-flake", 197 | "flake-compat": "flake-compat_2", 198 | "home-manager": "home-manager", 199 | "nixpkgs": "nixpkgs" 200 | } 201 | }, 202 | "treefmt": { 203 | "inputs": { 204 | "nixpkgs": [ 205 | "dev-flake", 206 | "nixpkgs" 207 | ] 208 | }, 209 | "locked": { 210 | "lastModified": 1747912973, 211 | "narHash": "sha256-XgxghfND8TDypxsMTPU2GQdtBEsHTEc3qWE6RVEk8O0=", 212 | "owner": "numtide", 213 | "repo": "treefmt-nix", 214 | "rev": "020cb423808365fa3f10ff4cb8c0a25df35065a3", 215 | "type": "github" 216 | }, 217 | "original": { 218 | "owner": "numtide", 219 | "repo": "treefmt-nix", 220 | "type": "github" 221 | } 222 | } 223 | }, 224 | "root": "root", 225 | "version": 7 226 | } 227 | -------------------------------------------------------------------------------- /dev/flake.nix: -------------------------------------------------------------------------------- 1 | { 2 | description = "Dependencies for development purposes"; 3 | 4 | inputs = { 5 | nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; 6 | 7 | dev-flake = { 8 | url = "github:terlar/dev-flake"; 9 | inputs.nixpkgs.follows = "nixpkgs"; 10 | }; 11 | home-manager = { 12 | url = "github:nix-community/home-manager"; 13 | inputs.nixpkgs.follows = "nixpkgs"; 14 | }; 15 | flake-compat = { 16 | url = "github:edolstra/flake-compat"; 17 | flake = false; 18 | }; 19 | }; 20 | 21 | outputs = _: { }; 22 | } 23 | -------------------------------------------------------------------------------- /dev/nix.conf: -------------------------------------------------------------------------------- 1 | experimental-features = nix-command flakes 2 | extra-substituters = https://terlar.cachix.org 3 | extra-trusted-public-keys = terlar.cachix.org-1:M8CXTOaJib7CP/jEfpNJAyrgW4qECnOUI02q7cnmh8U= 4 | max-jobs = auto 5 | -------------------------------------------------------------------------------- /dev/screenshots.el: -------------------------------------------------------------------------------- 1 | ;;; screenshots.el --- Configuration screenshots -*- coding: utf-8; lexical-binding: t -*- 2 | 3 | ;; Copyright (C) 2022 Terje Larsen 4 | ;; All rights reserved. 5 | 6 | ;; This file is NOT part of GNU Emacs. 7 | 8 | ;; screenshots is free software: you can redistribute it and/or modify it under the 9 | ;; terms of the GNU General Public License as published by the Free Software Foundation, 10 | ;; either version 3 of the License, or (at your option) any later version. 11 | 12 | ;; screenshots is distributed in the hope that it will be useful, but WITHOUT ANY 13 | ;; WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 14 | ;; PARTICULAR PURPOSE. See the GNU General Public License for more details. 15 | 16 | ;; You should have received a copy of the GNU General Public License 17 | ;; along with GNU Emacs. If not, see . 18 | 19 | ;;; Commentary: 20 | ;; Script to take screenshots to demo configuration. 21 | 22 | ;;; Code: 23 | (let* ((media-dir (expand-file-name "media")) 24 | (captures 25 | `((org-mode 26 | . ((find-file (expand-file-name "samples/sample.org" ,media-dir)) 27 | (goto-char 49) 28 | (follow-mode 1) 29 | (split-window-right) 30 | (follow-redraw))) 31 | (markdown-mode 32 | . ((find-file (expand-file-name "samples/sample.md" ,media-dir)) 33 | (goto-char 51) 34 | (follow-mode 1) 35 | (split-window-right) 36 | (follow-redraw))) 37 | (rst-mode 38 | . ((find-file (expand-file-name "samples/sample.rst" ,media-dir)) 39 | (goto-char 239) 40 | (follow-mode 1) 41 | (split-window-right) 42 | (follow-redraw))) 43 | (emacs-lisp-mode 44 | . ((find-file (expand-file-name "../lisp/readable-mono-theme.el" ,media-dir)) 45 | (goto-char 1223) 46 | (follow-mode 1) 47 | (split-window-right) 48 | (follow-redraw)))))) 49 | (global-hide-fringes-mode 1) 50 | (blink-cursor-mode 0) 51 | 52 | (dolist (capture captures) 53 | (let ((name (symbol-name (car capture))) 54 | (actions (cdr capture))) 55 | (delete-other-windows) 56 | 57 | (dolist (action actions) (eval action)) 58 | 59 | (font-lock-update) 60 | 61 | (dolist (background-mode '(light dark)) 62 | (customize-set-variable 'frame-background-mode background-mode) 63 | (customize-set-variable 'custom-enabled-themes custom-enabled-themes) 64 | (message nil) 65 | (with-temp-file (expand-file-name 66 | (concat name 67 | "-" 68 | (symbol-name background-mode) 69 | ".png") 70 | media-dir) 71 | (insert (x-export-frames nil 'png))))))) 72 | 73 | (provide 'screenshots) 74 | ;;; screenshots.el ends here 75 | -------------------------------------------------------------------------------- /dev/test-home-configuration.nix: -------------------------------------------------------------------------------- 1 | { inputs, config, ... }: 2 | let 3 | rootConfig = config; 4 | in 5 | { 6 | transposition.homeConfigurations.adHoc = true; 7 | 8 | perSystem = 9 | { config, pkgs, ... }: 10 | { 11 | homeConfigurations = inputs.home-manager.lib.homeManagerConfiguration { 12 | inherit pkgs; 13 | 14 | modules = [ 15 | rootConfig.flake.homeManagerModules.emacsConfig 16 | { 17 | home = { 18 | stateVersion = "22.05"; 19 | username = "test"; 20 | homeDirectory = "/home/test"; 21 | }; 22 | 23 | custom.emacsConfig = { 24 | enable = true; 25 | package = config.packages.emacs-env; 26 | configPackage = config.packages.emacs-config; 27 | erc = pkgs.writeText "ercrc.el" '' 28 | ;; Testing testing 29 | ''; 30 | }; 31 | } 32 | ]; 33 | }; 34 | 35 | checks.build-home-configuration = config.homeConfigurations.activationPackage; 36 | }; 37 | } 38 | -------------------------------------------------------------------------------- /flake.lock: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "elisp-helpers": { 4 | "inputs": { 5 | "fromElisp": "fromElisp" 6 | }, 7 | "locked": { 8 | "lastModified": 1741687420, 9 | "narHash": "sha256-tWPUfH3hCpB6g7a+0AK3lLYnhKgCxry5+pxNKZ2rQoY=", 10 | "owner": "emacs-twist", 11 | "repo": "elisp-helpers", 12 | "rev": "dd91691d642188f857e3fc3fec3e16719810e6d2", 13 | "type": "github" 14 | }, 15 | "original": { 16 | "owner": "emacs-twist", 17 | "repo": "elisp-helpers", 18 | "type": "github" 19 | } 20 | }, 21 | "emacs-overlay": { 22 | "inputs": { 23 | "nixpkgs": [ 24 | "nixpkgs" 25 | ], 26 | "nixpkgs-stable": [ 27 | "nixpkgs" 28 | ] 29 | }, 30 | "locked": { 31 | "lastModified": 1748830325, 32 | "narHash": "sha256-VfYtLnOm4wj69Wk4UrJ2mV64aqigYhY+C2c8v1G8QZ0=", 33 | "owner": "nix-community", 34 | "repo": "emacs-overlay", 35 | "rev": "27826d97ee15ea9db4fb8147aa09b25e74af20fd", 36 | "type": "github" 37 | }, 38 | "original": { 39 | "owner": "nix-community", 40 | "repo": "emacs-overlay", 41 | "type": "github" 42 | } 43 | }, 44 | "flake-parts": { 45 | "inputs": { 46 | "nixpkgs-lib": "nixpkgs-lib" 47 | }, 48 | "locked": { 49 | "lastModified": 1748821116, 50 | "narHash": "sha256-F82+gS044J1APL0n4hH50GYdPRv/5JWm34oCJYmVKdE=", 51 | "owner": "hercules-ci", 52 | "repo": "flake-parts", 53 | "rev": "49f0870db23e8c1ca0b5259734a02cd9e1e371a1", 54 | "type": "github" 55 | }, 56 | "original": { 57 | "owner": "hercules-ci", 58 | "repo": "flake-parts", 59 | "type": "github" 60 | } 61 | }, 62 | "fromElisp": { 63 | "flake": false, 64 | "locked": { 65 | "lastModified": 1723987997, 66 | "narHash": "sha256-OhaVgTG6zjLByzl+uPTvtCld3p2uqgbCXmOl/s3LVRo=", 67 | "owner": "talyz", 68 | "repo": "fromElisp", 69 | "rev": "f071a0e262c02c0895b575c4e322b7fd90713543", 70 | "type": "github" 71 | }, 72 | "original": { 73 | "owner": "talyz", 74 | "repo": "fromElisp", 75 | "type": "github" 76 | } 77 | }, 78 | "melpa": { 79 | "flake": false, 80 | "locked": { 81 | "lastModified": 1748794819, 82 | "narHash": "sha256-MNM2u9nG/SNFkWrlY0w/0/7ZVGzlq++HBs7iUhbda74=", 83 | "owner": "melpa", 84 | "repo": "melpa", 85 | "rev": "2e4449e68cb58f4638a52f1222c2a2ad50516545", 86 | "type": "github" 87 | }, 88 | "original": { 89 | "owner": "melpa", 90 | "repo": "melpa", 91 | "type": "github" 92 | } 93 | }, 94 | "nixpkgs": { 95 | "locked": { 96 | "lastModified": 1748762463, 97 | "narHash": "sha256-rb8vudY2u0SgdWh83SAhM5QZT91ZOnvjOLGTO4pdGTc=", 98 | "owner": "NixOS", 99 | "repo": "nixpkgs", 100 | "rev": "0d0bc640d371e9e8c9914c42951b3d6522bc5dda", 101 | "type": "github" 102 | }, 103 | "original": { 104 | "owner": "NixOS", 105 | "ref": "nixos-unstable-small", 106 | "repo": "nixpkgs", 107 | "type": "github" 108 | } 109 | }, 110 | "nixpkgs-lib": { 111 | "locked": { 112 | "lastModified": 1748740939, 113 | "narHash": "sha256-rQaysilft1aVMwF14xIdGS3sj1yHlI6oKQNBRTF40cc=", 114 | "owner": "nix-community", 115 | "repo": "nixpkgs.lib", 116 | "rev": "656a64127e9d791a334452c6b6606d17539476e2", 117 | "type": "github" 118 | }, 119 | "original": { 120 | "owner": "nix-community", 121 | "repo": "nixpkgs.lib", 122 | "type": "github" 123 | } 124 | }, 125 | "org-babel": { 126 | "locked": { 127 | "lastModified": 1731256202, 128 | "narHash": "sha256-xtV0vIUhl3ZUzaUIHSaiWpybxyCgQ9Yp/MUGo3f5zvM=", 129 | "owner": "emacs-twist", 130 | "repo": "org-babel", 131 | "rev": "a5d16c54aca35c07af59d216cda598163512db42", 132 | "type": "github" 133 | }, 134 | "original": { 135 | "owner": "emacs-twist", 136 | "repo": "org-babel", 137 | "type": "github" 138 | } 139 | }, 140 | "root": { 141 | "inputs": { 142 | "emacs-overlay": "emacs-overlay", 143 | "flake-parts": "flake-parts", 144 | "melpa": "melpa", 145 | "nixpkgs": "nixpkgs", 146 | "org-babel": "org-babel", 147 | "twist": "twist" 148 | } 149 | }, 150 | "twist": { 151 | "inputs": { 152 | "elisp-helpers": "elisp-helpers" 153 | }, 154 | "locked": { 155 | "lastModified": 1741687500, 156 | "narHash": "sha256-3XFSz42KAz53k9dzY5C2QbL5R4uiPwwqZ86RPiOYcNg=", 157 | "owner": "emacs-twist", 158 | "repo": "twist.nix", 159 | "rev": "cb0299ed2d7936357288b77d1f22ddbd9e35808d", 160 | "type": "github" 161 | }, 162 | "original": { 163 | "owner": "emacs-twist", 164 | "repo": "twist.nix", 165 | "type": "github" 166 | } 167 | } 168 | }, 169 | "root": "root", 170 | "version": 7 171 | } 172 | -------------------------------------------------------------------------------- /flake.nix: -------------------------------------------------------------------------------- 1 | { 2 | description = "Emacs config of Terje"; 3 | 4 | nixConfig = { 5 | extra-substituters = "https://terlar.cachix.org"; 6 | extra-trusted-public-keys = "terlar.cachix.org-1:M8CXTOaJib7CP/jEfpNJAyrgW4qECnOUI02q7cnmh8U="; 7 | }; 8 | 9 | inputs = { 10 | nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable-small"; 11 | 12 | flake-parts.url = "github:hercules-ci/flake-parts"; 13 | 14 | emacs-overlay = { 15 | url = "github:nix-community/emacs-overlay"; 16 | inputs = { 17 | nixpkgs.follows = "nixpkgs"; 18 | nixpkgs-stable.follows = "nixpkgs"; 19 | }; 20 | }; 21 | 22 | twist.url = "github:emacs-twist/twist.nix"; 23 | org-babel.url = "github:emacs-twist/org-babel"; 24 | 25 | melpa = { 26 | url = "github:melpa/melpa"; 27 | flake = false; 28 | }; 29 | }; 30 | 31 | outputs = 32 | inputs: 33 | inputs.flake-parts.lib.mkFlake { inherit inputs; } { 34 | systems = [ "x86_64-linux" ]; 35 | 36 | imports = [ 37 | inputs.flake-parts.flakeModules.partitions 38 | ]; 39 | 40 | partitionedAttrs = { 41 | checks = "dev"; 42 | devShells = "dev"; 43 | packages = "dev"; 44 | }; 45 | 46 | partitions.dev = { 47 | extraInputsFlake = ./dev; 48 | module.imports = [ ./dev/flake-module.nix ]; 49 | }; 50 | 51 | flake = { 52 | homeManagerModules.emacsConfig = import ./nix/home-manager.nix; 53 | }; 54 | 55 | perSystem = 56 | { 57 | config, 58 | pkgs, 59 | inputs', 60 | ... 61 | }: 62 | { 63 | packages = { 64 | emacs = inputs'.emacs-overlay.packages.emacs-git.overrideAttrs (old: { 65 | src = pkgs.fetchFromGitHub { 66 | owner = "emacs-mirror"; 67 | repo = "emacs"; 68 | inherit (old.src) rev; 69 | sha256 = old.src.outputHash; 70 | }; 71 | }); 72 | 73 | emacs-pgtk = inputs'.emacs-overlay.packages.emacs-git-pgtk.overrideAttrs (old: { 74 | src = pkgs.fetchFromGitHub { 75 | owner = "emacs-mirror"; 76 | repo = "emacs"; 77 | inherit (old.src) rev; 78 | sha256 = old.src.outputHash; 79 | }; 80 | }); 81 | 82 | emacs-env = pkgs.callPackage ./nix/packages/emacs-env { 83 | org-babel-lib = inputs.org-babel.lib; 84 | twist-lib = inputs.twist.lib; 85 | rootPath = ./.; 86 | melpaSrc = inputs.melpa.outPath; 87 | inherit (config.packages) emacs; 88 | }; 89 | 90 | emacs-env-pgtk = config.packages.emacs-env.override { 91 | emacs = config.packages.emacs-pgtk; 92 | }; 93 | 94 | emacs-config = pkgs.callPackage ./nix/packages/emacs-config { 95 | twist-lib = inputs.twist.lib; 96 | rootPath = ./.; 97 | inherit (config.packages) emacs emacs-env; 98 | }; 99 | 100 | emacs-config-pgtk = config.packages.emacs-config.override { 101 | emacs = config.packages.emacs-pgtk; 102 | emacs-env = config.packages.emacs-env-pgtk; 103 | }; 104 | }; 105 | 106 | apps = config.packages.emacs-env.makeApps { lockDirName = "lock"; }; 107 | }; 108 | }; 109 | } 110 | -------------------------------------------------------------------------------- /lisp/ff-test-test.el: -------------------------------------------------------------------------------- 1 | ;;; ff-test-test.el --- Tests for ff-test -*- coding: utf-8; -*- 2 | 3 | ;;; Code: 4 | 5 | (load-file "ff-test.el") 6 | 7 | (ert-deftest implementation-file-given () 8 | (let ((ff-test-suffixes '("-test" "_test"))) 9 | (should (equal (ff-test-converter "/tmp/p/src/file.el") 10 | '("file-test.el" "file_test.el"))))) 11 | 12 | (ert-deftest test-file-given () 13 | (let ((ff-test-suffixes '("-test"))) 14 | (should (equal (ff-test-converter "/tmp/p/src/file-test.el") 15 | '("file.el"))))) 16 | 17 | (ert-deftest implementation-file-given-using-search-directories () 18 | (let ((ff-test-suffixes '("-test" "_test")) 19 | (ff-test-expanded-search-implementation-project-directories '("/tmp/p/src")) 20 | (ff-test-expanded-search-test-project-directories '("/tmp/p/test"))) 21 | (should (equal (ff-test-converter "/tmp/p/src/path/file.el") 22 | '("file-test.el" "file_test.el" "path/file-test.el" "path/file_test.el"))))) 23 | 24 | (ert-deftest test-file-with-test-extension-given-using-search-directories () 25 | (let ((ff-test-suffixes '("-test" "_test")) 26 | (ff-test-expanded-search-implementation-project-directories '("/tmp/p/src")) 27 | (ff-test-expanded-search-test-project-directories '("/tmp/p/test"))) 28 | (should (equal (ff-test-converter "/tmp/p/test/path/file-test.el") 29 | '("file.el" "path/file.el"))))) 30 | 31 | (ert-deftest test-file-with-test-extension-given-using-search-in-subdirectories () 32 | (let ((ff-test-suffixes '("-test" "_test")) 33 | (ff-test-expanded-search-implementation-project-directories '("/tmp/p/src")) 34 | (ff-test-expanded-search-test-project-directories '("/tmp/p/test/unit" "/tmp/p/test/integration"))) 35 | (should (equal (ff-test-converter "/tmp/p/test/unit/path/file-test.el") 36 | '("file.el" "path/file.el"))))) 37 | 38 | (provide 'ff-test-file-test) 39 | ;;; ff-test-file-test.el ends here 40 | -------------------------------------------------------------------------------- /lisp/ff-test.el: -------------------------------------------------------------------------------- 1 | ;;; ff-test.el --- Find a test/implementation file related to current file -*- coding: utf-8; lexical-binding: t; -*- 2 | 3 | ;; Copyright (C) 2022 Terje Larsen 4 | ;; All rights reserved. 5 | 6 | ;; Author: Terje Larsen 7 | ;; Keywords: files 8 | ;; URL: https://github.com/terlar/emacs-config/blob/main/lisp/ff-test.el 9 | ;; Package-Requires: ((emacs "28.1")) 10 | ;; Version: 0.1 11 | 12 | ;; This file is NOT part of GNU Emacs. 13 | 14 | ;; ff-test is free software: you can redistribute it and/or modify 15 | ;; it under the terms of the GNU General Public License as published by 16 | ;; the Free Software Foundation, either version 3 of the License, or 17 | ;; (at your option) any later version. 18 | 19 | ;; ff-test is distributed in the hope that it will be useful, 20 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 21 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 | ;; GNU General Public License for more details. 23 | 24 | ;; You should have received a copy of the GNU General Public License 25 | ;; along with GNU Emacs. If not, see . 26 | 27 | ;;; Commentary: 28 | 29 | ;; Find related test file from implementation and vice-versa. 30 | 31 | ;;; Code: 32 | 33 | ;; TODO Use `ff-file-created-hook', if several search folders, ask where to create (e.g. unit/integration/acceptance) 34 | 35 | (require 'find-file) 36 | (require 'seq) 37 | 38 | (defgroup ff-test nil 39 | "Find a test/implementation file related to current file." 40 | :group 'find-file) 41 | 42 | (defcustom ff-test-suffixes '("_test" "_spec" 43 | "-test" "-spec" 44 | ".test" ".spec") 45 | "List of test suffixes to look associate with implementation file." 46 | :type '(repeat string) 47 | :group 'ff-test 48 | :safe (lambda (x) (seq-every-p #'stringp x))) 49 | 50 | (defcustom ff-test-search-implementation-directories '(".") 51 | "List of directories to look for implementation files." 52 | :type '(repeat directory) 53 | :group 'ff-test 54 | :safe (lambda (x) (seq-every-p #'file-directory-p x))) 55 | 56 | (defcustom ff-test-search-implementation-project-directories '("src") 57 | "List of project relative directories to look for related implementation files." 58 | :type '(repeat string) 59 | :group 'ff-test 60 | :safe (lambda (x) (seq-every-p #'stringp x))) 61 | 62 | (defcustom ff-test-search-test-directories '(".") 63 | "List of directories to look for test files." 64 | :type '(repeat directory) 65 | :group 'ff-test 66 | :safe (lambda (x) (seq-every-p #'file-directory-p x))) 67 | 68 | (defcustom ff-test-search-test-project-directories '("test" "spec") 69 | "List of project relative directories to look for associated test files." 70 | :type '(repeat string) 71 | :group 'ff-test 72 | :safe (lambda (x) (seq-every-p #'stringp x))) 73 | 74 | (defcustom ff-test-project-root-function #'ff-test-project-root-from-current-project 75 | "Function used to get project roots." 76 | :type 'function 77 | :group 'ff-test) 78 | 79 | (make-variable-buffer-local 'ff-test-search-implementation-directories) 80 | (make-variable-buffer-local 'ff-test-search-implementation-project-directories) 81 | (make-variable-buffer-local 'ff-test-search-test-directories) 82 | (make-variable-buffer-local 'ff-test-search-test-project-directories) 83 | (make-variable-buffer-local 'ff-test-suffixes) 84 | 85 | (defvar-local ff-test-expanded-search-implementation-project-directories nil 86 | "List of expanded `ff-test-search-implementation-project-directories'. 87 | Using `ff-test-project-root-function'.") 88 | (defvar-local ff-test-expanded-search-test-project-directories nil 89 | "List of expanded `ff-test-search-test-project-directories'. 90 | Using `ff-test-project-root-function'.") 91 | 92 | ;; Optional dependencies to set project local directories. 93 | (autoload 'project-root "project") 94 | (autoload 'project-current "project") 95 | 96 | (defun ff-test-project-root-from-current-project () 97 | "Use `project' to resolve project roots." 98 | (project-root (project-current t))) 99 | 100 | (defun ff-test-file-regexp (extension) 101 | "Return regular expression for EXTENSION matching `ff-test-suffixes'." 102 | (concat "\\(" (mapconcat #'regexp-quote ff-test-suffixes "\\|") "\\)" "." extension "$")) 103 | 104 | (defun ff-test-test-file-p (file-name) 105 | "Return t if FILE-NAME is a test file." 106 | (string-match-p (ff-test-file-regexp (file-name-extension file-name)) 107 | file-name)) 108 | 109 | ;;;###autoload 110 | (defun ff-test-project-dirs (dirs) 111 | "Return DIRS as a list of expanded project directories." 112 | (let ((root (expand-file-name (funcall ff-test-project-root-function)))) 113 | (mapcar (lambda (dir) (concat root dir)) 114 | dirs))) 115 | 116 | ;;;###autoload 117 | (defun ff-test-converter (file-name) 118 | "Possible related test/implementation files for FILE-NAME." 119 | (let* ((file-ext (file-name-extension file-name)) 120 | (file-dir (file-name-directory file-name)) 121 | (test-regexp (ff-test-file-regexp file-ext)) 122 | (test-file-p (ff-test-test-file-p file-name)) 123 | file-targets 124 | search-directories) 125 | (cond 126 | (test-file-p 127 | (setq file-targets 128 | (list (replace-regexp-in-string test-regexp 129 | (concat "." file-ext) 130 | (file-name-nondirectory file-name))) 131 | search-directories ff-test-expanded-search-test-project-directories)) 132 | (t 133 | (setq file-targets (mapcar (lambda (suffix) 134 | (concat (file-name-base file-name) suffix "." file-ext)) 135 | ff-test-suffixes) 136 | search-directories ff-test-expanded-search-implementation-project-directories))) 137 | 138 | (apply 'append 139 | file-targets 140 | (mapcar (lambda (dir) (let ((relative-dir 141 | (replace-regexp-in-string 142 | (replace-regexp-in-string "\\\\\\*" "[^/]+" (regexp-quote (concat dir "/"))) 143 | "" 144 | file-dir))) 145 | (unless (string= relative-dir file-dir) 146 | (mapcar (lambda (target) (concat relative-dir target)) 147 | file-targets)))) 148 | search-directories)))) 149 | 150 | ;;;###autoload 151 | (defun ff-test-other-file-name () 152 | "Return the name of the corresponding test/implementation file." 153 | (let* ((file-name (ff-buffer-file-name)) 154 | (file-ext (file-name-extension file-name)) 155 | (test-regexp (ff-test-file-regexp file-ext)) 156 | (implementation-regxp (concat "\\." file-ext "$")) 157 | (test-file-p (ff-test-test-file-p file-name)) 158 | (ff-test-expanded-search-implementation-project-directories 159 | (ff-test-project-dirs ff-test-search-implementation-project-directories)) 160 | (ff-test-expanded-search-test-project-directories 161 | (ff-test-project-dirs ff-test-search-test-project-directories)) 162 | (ff-search-directories 163 | (cond 164 | (test-file-p 165 | (append ff-test-search-implementation-directories 166 | ff-test-expanded-search-implementation-project-directories)) 167 | (t 168 | (append ff-test-search-test-directories 169 | ff-test-expanded-search-test-project-directories)))) 170 | (ff-other-file-alist 171 | `((,test-regexp ,'ff-test-converter) 172 | (,implementation-regxp ,'ff-test-converter)))) 173 | (ff-find-the-other-file))) 174 | 175 | ;;;###autoload 176 | (defun ff-test-find-other-file (&optional in-other-window) 177 | "Find the test or implementation file corresponding to this file. 178 | 179 | If optional IN-OTHER-WINDOW is non-nil, find the file in the other window. 180 | 181 | Variables of interest include: 182 | 183 | - `ff-test-search-implementation-directories' 184 | List of directories searched through for implementation files. 185 | 186 | - `ff-test-search-test-directories' List of directories searched 187 | through for test files, using each suffix specified in 188 | `ff-test-suffixes'." 189 | (interactive "P") 190 | (let* ((file-name (ff-buffer-file-name)) 191 | (file-ext (file-name-extension file-name)) 192 | (test-regexp (ff-test-file-regexp file-ext)) 193 | (implementation-regxp (concat "\\." file-ext "$")) 194 | (test-file-p (ff-test-test-file-p file-name)) 195 | (ff-test-expanded-search-implementation-project-directories 196 | (ff-test-project-dirs ff-test-search-implementation-project-directories)) 197 | (ff-test-expanded-search-test-project-directories 198 | (ff-test-project-dirs ff-test-search-test-project-directories)) 199 | (ff-search-directories 200 | (cond 201 | (test-file-p 202 | (append ff-test-search-implementation-directories 203 | ff-test-expanded-search-implementation-project-directories)) 204 | (t 205 | (append ff-test-search-test-directories 206 | ff-test-expanded-search-test-project-directories)))) 207 | (ff-other-file-alist 208 | `((,test-regexp ,'ff-test-converter) 209 | (,implementation-regxp ,'ff-test-converter)))) 210 | (ff-find-other-file in-other-window t))) 211 | 212 | (provide 'ff-test) 213 | ;;; ff-test.el ends here 214 | -------------------------------------------------------------------------------- /lisp/pairable.el: -------------------------------------------------------------------------------- 1 | ;;; pairable.el --- Optimize for pair-programming -*- coding: utf-8; lexical-binding: t; -*- 2 | 3 | ;; Copyright (C) 2022 Terje Larsen 4 | ;; All rights reserved. 5 | 6 | ;; Author: Terje Larsen 7 | ;; Keywords: faces 8 | ;; URL: https://github.com/terlar/emacs-config/blob/main/lisp/pariable.el 9 | ;; Package-Requires: ((emacs "29.1")) 10 | ;; Version: 0.1 11 | 12 | ;; This file is NOT part of GNU Emacs. 13 | 14 | ;; pariable is free software: you can redistribute it and/or modify 15 | ;; it under the terms of the GNU General Public License as published by 16 | ;; the Free Software Foundation, either version 3 of the License, or 17 | ;; (at your option) any later version. 18 | 19 | ;; pairable is distributed in the hope that it will be useful, 20 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 21 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 | ;; GNU General Public License for more details. 23 | 24 | ;; You should have received a copy of the GNU General Public License 25 | ;; along with GNU Emacs. If not, see . 26 | 27 | ;;; Commentary: 28 | 29 | ;; `pairable' is a small minor mode that optimizes for pair-programming, this is 30 | ;; achieved by Increase font-sizes, enable line-numbering, e.t.c. 31 | 32 | ;;; Code: 33 | 34 | (require 'face-remap) 35 | 36 | (defgroup pairable nil 37 | "Settings for pair-programming." 38 | :group 'faces) 39 | 40 | ;;;###autoload 41 | (defcustom pairable-text-scale 2 42 | "Scaling increment for text. 43 | Will be multiplied with `global-text-scale-adjust--increment-factor'" 44 | :type 'number 45 | :group 'pairable) 46 | 47 | ;;;###autoload 48 | (defcustom pairable-display-line-numbers t 49 | "Enable line-numbers or not." 50 | :type 'boolean 51 | :group 'pairable) 52 | 53 | ;;;###autoload 54 | (defcustom pairable-hl-line t 55 | "Enable highlighting of the current line or not." 56 | :type 'boolean 57 | :group 'pairable) 58 | 59 | ;;;###autoload 60 | (defcustom pairable-lighter " Pairable" 61 | "Mode-line indicator for `pairable-mode'." 62 | :type '(choice (const :tag "No lighter" "") string) 63 | :group 'pairable) 64 | 65 | ;;;###autoload 66 | (define-minor-mode pairable-mode 67 | "Toggle Pariable mode. 68 | 69 | In Pariable mode, the text scale is increased, line numbers enabled and various 70 | other improvements to optimize for pair-programming." 71 | :lighter pairable-lighter 72 | :global t 73 | :group 'pairable 74 | (if pairable-mode 75 | (progn 76 | (when pairable-display-line-numbers 77 | (global-display-line-numbers-mode 1)) 78 | (when pairable-hl-line 79 | (global-hl-line-mode 1)) 80 | (when (> pairable-text-scale 0) 81 | (let ((inc (* global-text-scale-adjust--increment-factor pairable-text-scale))) 82 | (setq global-text-scale-adjust--default-height (face-attribute 'default :height)) 83 | (set-face-attribute 'default nil :height (+ global-text-scale-adjust--default-height inc)) 84 | (redisplay 'force)))) 85 | (progn 86 | (when pairable-display-line-numbers 87 | (global-display-line-numbers-mode 0)) 88 | (when pairable-hl-line 89 | (global-hl-line-mode 0)) 90 | (when (> pairable-text-scale 0) 91 | (set-face-attribute 'default nil :height global-text-scale-adjust--default-height) 92 | (redisplay 'force))))) 93 | 94 | (defun pairable-mode-enable () 95 | "Enable `pairable-mode' in the current buffer." 96 | (unless (minibufferp) 97 | (pairable-mode 1))) 98 | 99 | ;;;###autoload 100 | (define-global-minor-mode global-pairable-mode 101 | pairable-mode pairable-mode-enable 102 | :require 'pairable 103 | :group 'pairable) 104 | 105 | (provide 'pairable) 106 | ;;; pairable.el ends here 107 | -------------------------------------------------------------------------------- /lisp/readable-mono-theme.el: -------------------------------------------------------------------------------- 1 | ;;; readable-mono-theme.el --- Readable mostly monochromatic theme -*- coding: utf-8; lexical-binding: t -*- 2 | 3 | ;; Copyright (C) 2022 Terje Larsen 4 | ;; All rights reserved. 5 | 6 | ;; Author: Terje Larsen 7 | ;; URL: https://github.com/terlar/emacs-config 8 | ;; Keywords: faces 9 | ;; Version: 0.1 10 | ;; Package-Requires: ((emacs "26.1")) 11 | 12 | ;; This file is NOT part of GNU Emacs. 13 | 14 | ;; readable-mono-theme is free software: you can redistribute it and/or modify it under the 15 | ;; terms of the GNU General Public License as published by the Free Software Foundation, 16 | ;; either version 3 of the License, or (at your option) any later version. 17 | 18 | ;; readable-mono-theme is distributed in the hope that it will be useful, but WITHOUT ANY 19 | ;; WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 20 | ;; PARTICULAR PURPOSE. See the GNU General Public License for more details. 21 | 22 | ;; You should have received a copy of the GNU General Public License 23 | ;; along with GNU Emacs. If not, see . 24 | 25 | ;;; Commentary: 26 | ;; Minimal and mostly monochromatic theme. 27 | 28 | ;;; Code: 29 | (deftheme readable-mono "Minimal and monochromatic theme.") 30 | 31 | (defgroup readable-mono-theme nil 32 | "Minimal and monochromatic theme customization options." 33 | :group 'faces) 34 | 35 | ;;;; Light theme 36 | (defgroup readable-mono-theme-light nil 37 | "Minimal and monochromatic light theme customization options." 38 | :group 'readable-mono-theme) 39 | 40 | (defcustom readable-mono-theme-light-background "#fbf7ef" 41 | "Default background color for light theme." 42 | :type 'string 43 | :group 'readable-mono-theme-light) 44 | 45 | (defcustom readable-mono-theme-light-secondary-background "#f1ede5" 46 | "Secondary background color for light theme." 47 | :type 'string 48 | :group 'readable-mono-theme-light) 49 | 50 | (defcustom readable-mono-theme-light-highlight-background "#f1e9d2" 51 | "Highlight background color for light theme." 52 | :type 'string 53 | :group 'readable-mono-theme-light) 54 | 55 | (defcustom readable-mono-theme-light-foreground "#000011" 56 | "Default foreground color for light theme." 57 | :type 'string 58 | :group 'readable-mono-theme-light) 59 | 60 | (defcustom readable-mono-theme-light-secondary-foreground "#474747" 61 | "Secondary foreground color for light theme." 62 | :type 'string 63 | :group 'readable-mono-theme-light) 64 | 65 | (defcustom readable-mono-theme-light-attention "#d6000c" 66 | "Attention color for light theme." 67 | :type 'string 68 | :group 'readable-mono-theme-light) 69 | 70 | ;;;; Dark theme 71 | (defgroup readable-mono-theme-dark nil 72 | "Minimal and monochromatic dark theme customization options." 73 | :group 'readable-mono-theme) 74 | 75 | (defcustom readable-mono-theme-dark-background "#000011" 76 | "Default background color for dark theme." 77 | :type 'string 78 | :group 'readable-mono-theme-dark) 79 | 80 | (defcustom readable-mono-theme-dark-secondary-background "#252525" 81 | "Secondary background color for dark theme." 82 | :type 'string 83 | :group 'readable-mono-theme-dark) 84 | 85 | (defcustom readable-mono-theme-dark-highlight-background "#3b3b3b" 86 | "Highlight background color for dark theme." 87 | :type 'string 88 | :group 'readable-mono-theme-dark) 89 | 90 | (defcustom readable-mono-theme-dark-foreground "#ffffee" 91 | "Default foreground color for dark theme." 92 | :type 'string 93 | :group 'readable-mono-theme-dark) 94 | 95 | (defcustom readable-mono-theme-dark-secondary-foreground "#8d9fa1" 96 | "Secondary foreground color for dark theme." 97 | :type 'string 98 | :group 'readable-mono-theme-dark) 99 | 100 | (defcustom readable-mono-theme-dark-attention "#ec423a" 101 | "Attention color for dark theme." 102 | :type 'string 103 | :group 'readable-mono-theme-dark) 104 | 105 | ;;;; Faces 106 | (defface readable-mono-theme-secondary 107 | `((((background light)) (:background ,readable-mono-theme-light-secondary-background)) 108 | (((background dark)) (:background ,readable-mono-theme-dark-secondary-background))) 109 | "Face used to distinguish from default but not stand out." 110 | :group 'readable-mono-theme) 111 | 112 | (let ((l-bg readable-mono-theme-light-background) 113 | (l-bg-s readable-mono-theme-light-secondary-background) 114 | (l-bg-hl readable-mono-theme-light-highlight-background) 115 | (l-fg readable-mono-theme-light-foreground) 116 | (l-fg-s readable-mono-theme-light-secondary-foreground) 117 | (l-attention readable-mono-theme-light-attention) 118 | 119 | (d-bg readable-mono-theme-dark-background) 120 | (d-bg-s readable-mono-theme-dark-secondary-background) 121 | (d-bg-hl readable-mono-theme-dark-highlight-background) 122 | (d-fg readable-mono-theme-dark-foreground) 123 | (d-fg-s readable-mono-theme-dark-secondary-foreground) 124 | (d-attention readable-mono-theme-dark-attention)) 125 | 126 | ;;;; Theme faces 127 | (custom-theme-set-faces 128 | 'readable-mono 129 | 130 | ;;;;; Basic 131 | `(default 132 | ((((type graphic) (background light)) (:background ,l-bg :foreground ,l-fg)) 133 | (((type graphic) (background dark)) (:background ,d-bg :foreground ,d-fg)) 134 | (((type tty) (background light)) (:background unspecified :foreground ,l-fg)) 135 | (((type tty) (background dark)) (:background unspecified :foreground ,d-fg)))) 136 | 137 | `(shadow 138 | ((((background light)) (:foreground ,l-fg-s)) 139 | (((background dark)) (:foreground ,d-fg-s)))) 140 | 141 | `(highlight 142 | ((((background light)) (:background ,l-bg-hl)) 143 | (((background dark)) (:background ,d-bg-hl)))) 144 | `(region 145 | ((((background light)) (:background ,l-bg :foreground ,l-fg :inverse-video t)) 146 | (((background dark)) (:background ,d-bg :foreground ,l-bg :inverse-video t)))) 147 | '(secondary-selection ((t (:inherit highlight)))) 148 | 149 | `(help-key-binding 150 | ((((background light)) (:background ,l-bg-hl :foreground ,l-fg-s)) 151 | (((background dark)) (:background ,d-bg-hl :foreground ,d-fg-s)))) 152 | 153 | `(error 154 | ((((background light)) (:background ,l-attention :foreground "#ffffff")) 155 | (((background dark)) (:background ,d-attention :foreground "#ffffff")))) 156 | '(warning ((t (:inherit bold)))) 157 | '(success ((t (:foreground unspecified)))) 158 | 159 | ;;;;; Visual aid 160 | `(cursor 161 | ((((background light)) (:background ,l-attention)) 162 | (((background dark)) (:background ,d-attention)))) 163 | `(line-number-current-line 164 | ((((background light)) (:inherit bold :foreground ,l-attention)) 165 | (((background dark)) (:inherit bold :foreground ,d-attention)))) 166 | '(hl-line ((t (:inherit highlight)))) 167 | '(show-paren-match ((t (:inherit bold :underline t)))) 168 | '(show-paren-mismatch ((t (:inherit error)))) 169 | '(trailing-whitespace ((t (:inherit error)))) 170 | '(whitespace-line ((t (:inherit error)))) 171 | '(whitespace-trailing ((t (:inherit error)))) 172 | 173 | ;;;;; Search 174 | '(completions-annotations ((t (:inherit italic)))) 175 | '(completions-common-part ((t (:inherit region)))) 176 | '(completion-preview-exact ((t (:inherit underline)))) 177 | '(isearch ((t (:inherit region)))) 178 | '(isearch-fail ((t (:inherit error)))) 179 | '(lazy-highlight ((t (:inherit highlight)))) 180 | '(match ((t (:inherit highlight)))) 181 | 182 | ;;;;; Interface 183 | `(mode-line-active 184 | ((((background light)) (:background ,l-bg-s :box (:line-width 6 :color ,l-bg-s))) 185 | (((background dark)) (:background ,d-bg-s :box (:line-width 6 :color ,d-bg-s))))) 186 | `(mode-line-inactive 187 | ((((type graphic) (background light)) (:background ,l-bg :box (:line-width 6 :color ,l-bg))) 188 | (((type graphic) (background dark)) (:background ,d-bg :box (:line-width 6 :color ,d-bg))) 189 | (((type tty) (background light)) (:background unspecified :foreground ,l-fg-s)) 190 | (((type tty) (background dark)) (:background unspecified :foreground ,d-fg-s)))) 191 | '(mode-line-emphasis ((t :bold nil))) 192 | '(mode-line-buffer-id ((t :inherit bold))) 193 | 194 | `(header-line 195 | ((((background light)) (:foreground ,l-bg :background ,l-fg :box (:line-width 6 :color ,l-fg))) 196 | (((background dark)) (:foreground ,d-bg :background ,d-fg :box (:line-width 6 :color ,d-fg))))) 197 | 198 | '(minibuffer-prompt ((t (:inherit bold)))) 199 | 200 | '(fringe ((t (:inherit shadow)))) 201 | 202 | '(button ((t (:inherit underline)))) 203 | '(widget-button ((t (:inherit button)))) 204 | `(widget-field 205 | ((((background light)) (:inherit readable-mono-theme-secondary :box (:line-width 1 :color ,l-bg))) 206 | (((background dark)) (:inherit readable-mono-theme-secondary :box (:line-width 1 :color ,d-bg))))) 207 | 208 | '(menu ((t (:inherit readable-mono-theme-secondary)))) 209 | '(tool-bar ((t (:inherit readable-mono-theme-secondary)))) 210 | '(tooltip ((t (:inherit readable-mono-theme-secondary)))) 211 | 212 | `(vertical-border 213 | ((((background light)) (:foreground ,l-bg-s)) 214 | (((background dark)) (:foreground ,d-bg-s)))) 215 | '(window-divider ((t (:inherit vertical-border)))) 216 | '(window-divider-first-pixel ((t (:inherit window-divider)))) 217 | '(window-divider-last-pixel ((t (:inherit window-divider)))) 218 | 219 | ;;;;; Headlines 220 | '(custom-group-tag ((t (:inherit bold)))) 221 | '(custom-state ((t (:inherit bold)))) 222 | '(custom-variable-tag ((t (:inherit bold)))) 223 | 224 | ;;;;; font-lock 225 | '(font-lock-function-name-face ((t (:foreground unspecified)))) 226 | '(font-lock-variable-name-face ((t (:foreground unspecified)))) 227 | '(font-lock-constant-face ((t (:foreground unspecified)))) 228 | '(font-lock-doc-string-face ((t (:foreground unspecified)))) 229 | '(font-lock-doc-face ((t (:foreground unspecified)))) 230 | '(font-lock-preprocessor-face ((t (:foreground unspecified)))) 231 | '(font-lock-reference-face ((t (:foreground unspecified)))) 232 | '(font-lock-string-face ((t (:foreground unspecified)))) 233 | '(font-lock-warning-face ((t (:inherit warning)))) 234 | 235 | ;;;;; Diff 236 | '(diff-header ((t (:inherit readable-mono-theme-secondary)))) 237 | '(diff-file-header ((t (:inherit header-line)))) 238 | '(diff-hunk-header ((t (:inherit shadow)))) 239 | `(diff-indicator-removed 240 | ((((background light)) (:background ,l-attention :foreground ,l-attention)) 241 | (((background dark)) (:background ,d-attention :foreground ,d-attention)))) 242 | `(diff-removed ((t (:inherit shadow :strike-through t)))) 243 | `(diff-refine-removed ((t (:inherit diff-removed)))) 244 | `(diff-indicator-added 245 | ((((background light)) (:background ,l-fg :foreground ,l-fg)) 246 | (((background dark)) (:background ,d-fg :foreground ,d-fg)))) 247 | `(diff-added ((t (:inherit highlight)))) 248 | `(diff-refine-added ((t (:inherit diff-added)))) 249 | `(diff-indicator-changed 250 | ((((background light)) (:background ,l-fg-s :foreground ,l-fg-s)) 251 | (((background dark)) (:background ,d-fg-s :foreground ,d-fg-s)))) 252 | '(diff-refine-changed ((t (:inverse-video t)))) 253 | '(diff-error ((t (:inherit error)))) 254 | 255 | '(ediff-current-diff-A ((t (:inherit highlight)))) 256 | '(ediff-fine-diff-A ((t (:inherit region)))) 257 | '(ediff-current-diff-B ((t (:inherit highlight)))) 258 | '(ediff-fine-diff-B ((t (:inherit region)))) 259 | `(ediff-current-diff-C ((t (:inherit highlight)))) 260 | `(ediff-fine-diff-C ((t (:inherit region)))) 261 | '(ediff-current-diff-Ancestor ((t (:inherit readable-mono-theme-secondary)))) 262 | '(ediff-fine-diff-Ancestor ((t (:inherit highlight)))) 263 | 264 | '(smerge-base ((t (:inherit readable-mono-theme-secondary)))) 265 | '(smerge-lower ((t (:background unspecified)))) 266 | '(smerge-upper ((t (:background unspecified)))) 267 | '(smerge-refined-added ((t (:inherit diff-refine-added)))) 268 | '(smerge-refined-changed ((t (:inherit diff-refine-changed)))) 269 | '(smerge-refined-removed ((t (:inherit diff-refine-removed)))) 270 | 271 | '(diff-hl-insert ((t (:inherit diff-indicator-added)))) 272 | `(diff-hl-change 273 | ((((background light)) (:background ,l-bg-s :foreground ,l-bg-s)) 274 | (((background dark)) (:background ,d-bg-s :foreground ,d-bg-s)))) 275 | '(diff-hl-delete ((t (:inherit diff-indicator-removed)))) 276 | `(diff-hl-unknown 277 | ((((background light)) (:background ,l-bg-s :foreground ,l-bg-s)) 278 | (((background dark)) (:background ,d-bg-s :foreground ,d-bg-s)))) 279 | 280 | ;;;;; ansi-color 281 | `(ansi-color-black 282 | ((((background light)) (:foreground ,l-fg)) 283 | (((background dark)) (:foreground ,d-fg)))) 284 | `(ansi-color-bright-black 285 | ((((background light)) (:foreground ,l-fg-s)) 286 | (((background dark)) (:foreground ,d-fg-s)))) 287 | `(ansi-color-red 288 | ((((background light)) (:foreground ,l-attention)) 289 | (((background dark)) (:foreground ,d-attention)))) 290 | '(ansi-color-bright-red ((t (:inherit ansi-color-red)))) 291 | '(ansi-color-green ((t (:inherit success)))) 292 | '(ansi-color-bright-green ((t (:inherit ansi-color-green)))) 293 | '(ansi-color-yellow ((t (:inherit shadow)))) 294 | '(ansi-color-bright-yellow ((t (:inherit ansi-color-yellow)))) 295 | '(ansi-color-blue ((t (:inherit ansi-color-black)))) 296 | '(ansi-color-bright-blue ((t (:inherit ansi-color-blue)))) 297 | '(ansi-color-magenta ((t (:inherit ansi-color-black)))) 298 | '(ansi-color-bright-magenta ((t (:inherit ansi-color-magenta)))) 299 | '(ansi-color-cyan ((t (:inherit ansi-color-black)))) 300 | '(ansi-color-bright-cyan ((t (:inherit ansi-color-cyan)))) 301 | '(ansi-color-white ((t (:inherit shadow)))) 302 | '(ansi-color-bright-white ((t (:inherit ansi-color-white)))) 303 | 304 | ;;;;; cider 305 | '(cider-test-failure-face ((t (:inherit error)))) 306 | '(cider-result-overlay-face ((t (:inherit highlight)))) 307 | 308 | ;;;;; company 309 | '(company-echo-common ((t (:inherit completions-common-part)))) 310 | '(company-preview ((t (:inherit shadow)))) 311 | '(company-preview-common ((t (:inherit completions-common-part)))) 312 | '(company-preview-search ((t (:inverse-video t)))) 313 | '(company-scrollbar-bg ((t (:inherit region)))) 314 | '(company-scrollbar-fg ((t (:inherit cursor)))) 315 | '(company-tooltip ((t (:inherit tooltip)))) 316 | '(company-tooltip-annotation ((t (:inherit shadow)))) 317 | '(company-tooltip-common ((t (:inherit completions-common-part)))) 318 | '(company-tooltip-selection ((t (:inherit highlight)))) 319 | 320 | ;;;;; compilation 321 | '(compilation-mode-line-fail ((t (:inherit compilation-error)))) 322 | 323 | ;;;;; corfu 324 | '(corfu-default ((t (:inherit readable-mono-theme-secondary)))) 325 | '(corfu-bar ((t (:inherit nil :inverse-video t)))) 326 | '(corfu-current ((t (:inherit highlight)))) 327 | 328 | ;;;;; cov 329 | `(cov-none-face 330 | ((((background light)) (:foreground ,l-attention)) 331 | (((background dark)) (:foreground ,d-attention)))) 332 | `(cov-light-face 333 | ((((background light)) (:foreground ,l-fg-s)) 334 | (((background dark)) (:foreground ,d-fg-s)))) 335 | `(cov-med-face 336 | ((((background light)) (:foreground ,l-fg-s)) 337 | (((background dark)) (:foreground ,d-fg-s)))) 338 | `(cov-heavy-face 339 | ((((background light)) (:foreground ,l-fg)) 340 | (((background dark)) (:foreground ,d-fg)))) 341 | 342 | `(cov-coverage-not-run-face 343 | ((((background light)) (:foreground ,l-attention)) 344 | (((background dark)) (:foreground ,d-attention)))) 345 | `(cov-coverage-run-face 346 | ((((background light)) (:foreground ,l-fg)) 347 | (((background dark)) (:foreground ,d-fg)))) 348 | 349 | ;;;;; dired 350 | '(all-the-icons-dired-dir-face ((t (:foreground unspecified)))) 351 | '(dired-directory ((t (:inherit bold)))) 352 | '(dired-broken-symlink ((t (:inherit error)))) 353 | '(dired-flagged ((t (:inherit bold)))) 354 | 355 | ;;;;; erc 356 | '(erc-current-nick-face ((t (:inherit bold)))) 357 | '(erc-input-face ((t (:inherit readable-mono-theme-secondary :extend t)))) 358 | '(erc-my-nick-face ((t (:inherit bold)))) 359 | '(erc-nick-default-face ((t (:inherit bold)))) 360 | '(erc-notice-face ((t (:inherit nil)))) 361 | '(erc-prompt-face ((t (:inherit bold)))) 362 | '(erc-timestamp-face ((t (:inherit shadow)))) 363 | 364 | ;;;;; eros 365 | '(eros-result-overlay-face ((t (:inherit highlight)))) 366 | 367 | ;;;;; eshell 368 | '(eshell-prompt ((t (:inherit bold)))) 369 | '(eshell-ls-archive ((t (:inherit bold)))) 370 | '(eshell-ls-backup ((t (:inherit font-lock-comment-face)))) 371 | '(eshell-ls-clutter ((t (:inherit font-lock-comment-face)))) 372 | '(eshell-ls-directory ((t (:inherit bold)))) 373 | '(eshell-ls-executable ((t (:inherit bold)))) 374 | '(eshell-ls-unreadable ((t (:inherit nil)))) 375 | '(eshell-ls-missing ((t (:inherit font-lock-warning-face)))) 376 | '(eshell-ls-product ((t (:inherit font-lock-doc-face)))) 377 | '(eshell-ls-special ((t (:inherit bold)))) 378 | '(eshell-ls-symlink ((t (:inherit bold)))) 379 | 380 | ;;;;; flymake 381 | `(flymake-error 382 | ((((background light)) (:underline (:style wave :color ,l-attention))) 383 | (((background dark)) (:underline (:style wave :color ,d-attention))))) 384 | 385 | ;;;;; flyspell 386 | `(flyspell-duplicate 387 | ((((background light)) (:underline (:style wave :color ,l-fg-s))) 388 | (((background dark)) (:underline (:style wave :color ,d-fg-s))))) 389 | `(flyspell-incorrect 390 | ((((background light)) (:underline (:style wave :color ,l-fg))) 391 | (((background dark)) (:underline (:style wave :color ,d-fg))))) 392 | 393 | ;;;;; ghelp 394 | '(ghelp-header-button ((t (:inherit info-header-node :box nil)))) 395 | 396 | ;;;;; gotest 397 | '(go-test--standard-face ((t (:foreground unspecified)))) 398 | '(go-test--ok-face ((t (:foreground unspecified)))) 399 | '(go-test--error-face ((t (:inherit error)))) 400 | '(go-test--pointer-face ((t (:foreground unspecified)))) 401 | '(go-test--warning-face ((t (:inherit warning)))) 402 | 403 | ;;;;; haskell 404 | '(haskell-interactive-face-prompt ((t (:inherit bold)))) 405 | 406 | ;;;;; idle-highlight 407 | '(idle-highlight ((t (:inherit underline)))) 408 | 409 | ;;;;; imenu-list 410 | '(imenu-list-entry-face-0 ((t (:foreground unspecified)))) 411 | '(imenu-list-entry-face-1 ((t (:foreground unspecified)))) 412 | '(imenu-list-entry-face-2 ((t (:foreground unspecified)))) 413 | '(imenu-list-entry-face-3 ((t (:foreground unspecified)))) 414 | 415 | ;;;;; indent-guide 416 | '(indent-guide-face ((t (:inherit fringe)))) 417 | 418 | ;;;;; Info 419 | '(info-header-node ((t (:inherit bold)))) 420 | '(info-header-xref ((t (:inherit bold :box nil)))) 421 | 422 | ;;;;; magit 423 | '(magit-section-heading-selection ((t (:inherit region)))) 424 | '(magit-section-highlight ((t (:inherit readable-mono-theme-secondary)))) 425 | '(magit-diff-file-heading-selection ((t (:inherit region)))) 426 | '(magit-diff-context ((t (:background unspecified)))) 427 | '(magit-diff-context-highlight ((t (:inherit readable-mono-theme-secondary)))) 428 | '(magit-diff-removed ((t (:inherit diff-refine-removed)))) 429 | '(magit-diff-removed-highlight ((t (:inherit (diff-removed readable-mono-theme-secondary))))) 430 | '(magit-diff-added ((t (:inherit diff-refine-added)))) 431 | '(magit-diff-added-highlight ((t (:inherit diff-added)))) 432 | '(magit-diff-hunk-heading ((t (:inherit nil)))) 433 | '(magit-diff-hunk-heading-highlight ((t (:inherit readable-mono-theme-secondary)))) 434 | '(magit-diff-hunk-heading-selection ((t (:inherit region)))) 435 | '(magit-diff-lines-boundary ((t (:inherit region)))) 436 | '(magit-diff-lines-heading ((t (:inherit region)))) 437 | '(magit-process-ok ((t (:inherit success)))) 438 | '(magit-process-ng ((t (:inherit error)))) 439 | 440 | '(magit-branch-current ((t (:inherit bold :box (:line-width 1))))) 441 | '(magit-branch-local ((t (:inherit bold)))) 442 | '(magit-branch-remote ((t (:inherit bold)))) 443 | '(magit-head ((t (:inherit bold)))) 444 | '(magit-tag ((t (:inherit italic)))) 445 | 446 | ;;;;; marginalia 447 | '(marginalia-file-priv-no ((t (:inherit nil)))) 448 | 449 | ;;;;; markdown 450 | '(markdown-code-face ((t (:inherit readable-mono-theme-secondary :extend t)))) 451 | `(markdown-inline-code-face 452 | ((((background light)) (:inherit readable-mono-theme-secondary :box (:line-width 1 :color ,l-bg))) 453 | (((background dark)) (:inherit readable-mono-theme-secondary :box (:line-width 1 :color ,d-bg))))) 454 | 455 | ;;;;; message 456 | '(message-cited-text-1 ((t (:foreground unspecified)))) 457 | '(message-cited-text-2 ((t (:foreground unspecified)))) 458 | '(message-cited-text-3 ((t (:foreground unspecified)))) 459 | '(message-cited-text-4 ((t (:foreground unspecified)))) 460 | '(message-header-cc ((t (:foreground unspecified)))) 461 | '(message-header-name ((t (:foreground unspecified)))) 462 | '(message-header-newsgroups ((t (:inherit bold)))) 463 | '(message-header-other ((t (:foreground unspecified)))) 464 | '(message-header-subject ((t (:inherit bold)))) 465 | '(message-header-to ((t (:inherit bold)))) 466 | '(message-header-xheader ((t (:foreground unspecified)))) 467 | '(message-mml ((t (:foreground unspecified)))) 468 | '(message-separator ((t (:inherit shadow)))) 469 | 470 | ;;;;; orderless 471 | '(orderless-match-face-0 ((t (:inherit completions-common-part)))) 472 | '(orderless-match-face-1 ((t (:inherit completions-common-part)))) 473 | '(orderless-match-face-2 ((t (:inherit completions-common-part)))) 474 | '(orderless-match-face-3 ((t (:inherit completions-common-part)))) 475 | 476 | ;;;;; org 477 | '(org-meta-line ((t (:inherit (shadow font-lock-comment-face))))) 478 | '(org-ellipsis ((t (:inherit shadow)))) 479 | '(org-done ((t (:foreground unspecified)))) 480 | '(org-todo ((t (:inherit bold)))) 481 | '(org-headline-done ((t (:foreground unspecified)))) 482 | '(org-headline-todo ((t (:foreground unspecified)))) 483 | '(org-block ((t (:inherit readable-mono-theme-secondary :extend t)))) 484 | `(org-code 485 | ((((background light)) (:inherit readable-mono-theme-secondary :box (:line-width 1 :color ,l-bg))) 486 | (((background dark)) (:inherit readable-mono-theme-secondary :box (:line-width 1 :color ,d-bg))))) 487 | '(org-date ((t (:foreground unspecified :underline nil)))) 488 | '(org-document-info ((t (:foreground unspecified)))) 489 | '(org-drawer ((t (:inherit shadow)))) 490 | `(org-hide 491 | ((((background light)) (:foreground ,l-bg)) 492 | (((background dark)) (:foreground ,d-bg)))) 493 | '(org-table ((t (:foreground unspecified)))) 494 | '(org-quote ((t (:foreground unspecified)))) 495 | 496 | '(org-agenda-structure ((t (:foreground unspecified)))) 497 | '(org-agenda-date ((t (:foreground unspecified)))) 498 | '(org-agenda-date-today ((t (:inherit (bold highlight))))) 499 | '(org-agenda-date-weekend ((t (:inherit bold)))) 500 | '(org-scheduled ((t (:foreground unspecified)))) 501 | '(org-scheduled-today ((t (:inherit underline)))) 502 | '(org-scheduled-previously ((t (:inherit bold)))) 503 | 504 | ;;;;; org-tree-slide 505 | '(org-tree-slide-header-overlay-face ((t (:inherit header-line)))) 506 | 507 | ;;;;; outline 508 | '(outline-minor-0 ((t (:background unspecified)))) 509 | 510 | ;;;;; popup 511 | '(popup-face ((t (:inherit (readable-mono-theme-secondary default))))) 512 | '(popup-isearch-match ((t (:inherit bold)))) 513 | '(popup-menu-mouse-face ((t (:underline t)))) 514 | '(popup-menu-selection-face ((t (:inherit (highlight default))))) 515 | '(popup-scroll-bar-background-face ((t (:inherit region)))) 516 | '(popup-scroll-bar-foreground-face ((t (:inherit cursor)))) 517 | '(popup-summary-face ((t (:inherit (popup-face shadow))))) 518 | `(popup-tip-face 519 | ((((background light)) (:inherit default :background ,l-bg-s :box (:line-width 6 :color ,l-bg-s))) 520 | (((background dark)) (:inherit default :background ,d-bg-s :box (:line-width 6 :color ,d-bg-s))))) 521 | 522 | ;;;;; quick-peek 523 | '(quick-peek-background-face ((t :inherit readable-mono-theme-secondary))) 524 | 525 | ;;;;; rainbow-delimiters 526 | '(rainbow-delimiters-unmatched-face ((t (:inherit error)))) 527 | 528 | ;;;;; rst 529 | '(rst-directive ((t (:inherit font-lock-comment-face)))) 530 | '(rst-external ((t (:inherit font-lock-comment-face)))) 531 | '(rst-literal ((t (:inherit readable-mono-theme-secondary :extend t)))) 532 | 533 | ;;;;; sh-script 534 | '(sh-quoted-exec ((t (:inherit readable-mono-theme-secondary)))) 535 | '(sh-heredoc ((t (:foreground unspecified)))) 536 | 537 | ;;;;; spray 538 | `(spray-accent-face 539 | ((((background light)) (:foreground ,l-attention :underline (:color ,(face-foreground 'default)) :overline ,(face-foreground 'default))) 540 | (((background dark)) (:foreground ,d-attention :underline (:color ,(face-foreground 'default)) :overline ,(face-foreground 'default))))) 541 | 542 | ;;;;; stripe-buffer 543 | `(stripe-highlight 544 | ((((background light)) (:background ,l-bg-s :foreground ,l-fg :extend t)) 545 | (((background dark)) (:background ,d-bg-s :foreground ,d-fg :extend t)))) 546 | 547 | ;;;;; term 548 | `(term-color-black 549 | ((((background light)) (:foreground ,l-fg :background ,l-fg-s)) 550 | (((background dark)) (:foreground ,d-fg :foreground ,d-fg-s)))) 551 | `(term-color-red 552 | ((((background light)) (:foreground ,l-attention :background ,l-attention)) 553 | (((background dark)) (:foreground ,d-attention :foreground ,d-attention)))) 554 | '(term-color-green ((t (:inherit term-color-black)))) 555 | '(term-color-yellow ((t (:inherit shadow)))) 556 | '(term-color-blue ((t (:inherit term-color-black)))) 557 | '(term-color-magenta ((t (:inherit term-color-black)))) 558 | '(term-color-cyan ((t (:inherit term-color-black)))) 559 | '(term-color-white ((t (:inherit shadow)))) 560 | 561 | ;;;;; terraform 562 | '(terraform-resource-name-face ((t (:foreground unspecified)))) 563 | '(terraform-resource-type-face ((t (:foreground unspecified)))) 564 | 565 | ;;;;; visual-replace 566 | '(visual-replace-region ((t (:inherit highlight)))) 567 | '(visual-replace-delete-match ((t (:inverse-video t :strike-through t)))) 568 | 569 | ;;;;; web 570 | '(web-mode-current-element-highlight-face ((t (:inherit show-paren-match)))) 571 | 572 | ;;;;; wgrep 573 | '(wgrep-face ((t (:inverse-video t)))) 574 | '(wgrep-delete-face ((t (:inverse-video t :strike-through t)))) 575 | '(wgrep-file-face ((t (:inverse-video t)))) 576 | '(wgrep-reject-face ((t (:inherit shadow)))) 577 | '(wgrep-done-face ((t (:inherit readable-mono-theme-secondary))))) 578 | 579 | ;;;; Theme variables 580 | (custom-theme-set-variables 581 | 'readable-mono 582 | 583 | ;;;;; hl-todo 584 | '(hl-todo-keyword-faces 585 | '(("TODO" . (:inherit bold :box (:line-width 1))) 586 | ("FIXME" . (:inherit error :box (:line-width 1))) 587 | ("NOTE" . (:box (:line-width 1))))) 588 | 589 | ;;;;; indent-bars 590 | '(indent-bars-color '(shadow :blend 0.4)) 591 | 592 | ;;;;; rainbow-identifiers 593 | '(rainbow-identifiers-cie-l*a*b*-saturation 65) 594 | '(rainbow-identifiers-cie-l*a*b*-lightness 45) 595 | 596 | ;;;;; zoom-window 597 | `(zoom-window-mode-line-color ,(pcase (frame-parameter nil 'background-mode) 598 | ('light l-bg-s) 599 | ('dark d-bg-s))))) 600 | 601 | ;;;###autoload 602 | (and load-file-name 603 | (boundp 'custom-theme-load-path) 604 | (add-to-list 'custom-theme-load-path 605 | (file-name-as-directory (file-name-directory load-file-name)))) 606 | 607 | (provide-theme 'readable-mono) 608 | (provide 'readable-mono-theme) 609 | ;;; readable-mono-theme.el ends here 610 | -------------------------------------------------------------------------------- /lisp/readable-typo-theme.el: -------------------------------------------------------------------------------- 1 | ;;; readable-typo-theme.el --- Readable typographic theme -*- coding: utf-8; lexical-binding: t -*- 2 | 3 | ;; Copyright (C) 2022 Terje Larsen 4 | ;; All rights reserved. 5 | 6 | ;; Author: Terje Larsen 7 | ;; URL: https://github.com/terlar/emacs-config 8 | ;; Keywords: faces 9 | ;; Version: 0.1 10 | ;; Package-Requires: ((emacs "24.3")) 11 | 12 | ;; This file is NOT part of GNU Emacs. 13 | 14 | ;; readable-typo-theme is free software: you can redistribute it and/or modify it under 15 | ;; the terms of the GNU General Public License as published by the Free Software 16 | ;; Foundation, either version 3 of the License, or (at your option) any later version. 17 | 18 | ;; readable-typo-theme is distributed in the hope that it will be useful, but WITHOUT ANY 19 | ;; WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 20 | ;; PARTICULAR PURPOSE. See the GNU General Public License for more details. 21 | 22 | ;; You should have received a copy of the GNU General Public License 23 | ;; along with GNU Emacs. If not, see . 24 | 25 | ;;; Commentary: 26 | ;; Typographic theme to achieve a more readable and pleasant experience. 27 | 28 | ;;; Code: 29 | (deftheme readable-typo "Readable typographic theme.") 30 | 31 | (defgroup readable-typo-theme nil 32 | "Readable typographic theme customization options." 33 | :group 'faces) 34 | 35 | ;;;; Customization options 36 | (defcustom readable-typo-theme-default-font-height 120 37 | "Default font height." 38 | :type 'string 39 | :group 'readable-typo-theme) 40 | 41 | (defcustom readable-typo-theme-font-scaling t 42 | "Scale font sizes." 43 | :type 'boolean 44 | :group 'readable-typo-theme) 45 | 46 | (defcustom readable-typo-theme-font-height-small 0.8 47 | "Small font height." 48 | :type 'string 49 | :group 'readable-typo-theme) 50 | 51 | (defcustom readable-typo-theme-font-height-title 1.8 52 | "Title font height." 53 | :type 'string 54 | :group 'readable-typo-theme) 55 | 56 | (defcustom readable-typo-theme-font-height-level-1 1.6 57 | "Level 1 font height." 58 | :type 'string 59 | :group 'readable-typo-theme) 60 | 61 | (defcustom readable-typo-theme-font-height-level-2 1.4 62 | "Level 2 font height." 63 | :type 'string 64 | :group 'readable-typo-theme) 65 | 66 | (defcustom readable-typo-theme-font-height-level-3 1.2 67 | "Level 3 font height." 68 | :type 'string 69 | :group 'readable-typo-theme) 70 | 71 | (defcustom readable-typo-theme-font-height-level-4 1.1 72 | "Level 4 font height." 73 | :type 'string 74 | :group 'readable-typo-theme) 75 | 76 | (defcustom readable-typo-theme-font-height-level-5 1.1 77 | "Level 5 font height." 78 | :type 'string 79 | :group 'readable-typo-theme) 80 | 81 | (defcustom readable-typo-theme-font-height-level-6 1.1 82 | "Level 6 font height." 83 | :type 'string 84 | :group 'readable-typo-theme) 85 | 86 | (defcustom readable-typo-theme-font-height-level-7 1.1 87 | "Level 7 font height." 88 | :type 'string 89 | :group 'readable-typo-theme) 90 | 91 | (defcustom readable-typo-theme-font-height-level-8 1.1 92 | "Level 8 font height." 93 | :type 'string 94 | :group 'readable-typo-theme) 95 | 96 | (defcustom readable-typo-theme-default-font-weight 'light 97 | "Default font weight." 98 | :type 'string 99 | :group 'readable-typo-theme) 100 | 101 | (defcustom readable-typo-theme-bold-font-weight 'medium 102 | "Bold font weight." 103 | :type 'string 104 | :group 'readable-typo-theme) 105 | 106 | (defcustom readable-typo-theme-line-spacing 0.25 107 | "Spacing between lines." 108 | :type 'number 109 | :group 'readable-typo-theme) 110 | 111 | (defcustom readable-typo-theme-fixed-pitch-font "Monospace" 112 | "Font used for fixed-pitch." 113 | :type 'string 114 | :group 'readable-typo-theme) 115 | 116 | (defcustom readable-typo-theme-fixed-pitch-serif-font "Monospace" 117 | "Font used for fixed-pitch serif." 118 | :type 'string 119 | :group 'readable-typo-theme) 120 | 121 | (defcustom readable-typo-theme-variable-pitch-font "sans-serif" 122 | "Font used for variable-pitch." 123 | :type 'string 124 | :group 'readable-typo-theme) 125 | 126 | (defcustom readable-typo-theme-serif-font "serif" 127 | "Font used for serif." 128 | :type 'string 129 | :group 'readable-typo-theme) 130 | 131 | ;;;; Faces 132 | (defface readable-typo-theme-echo-area 133 | nil 134 | "Face used for echo area." 135 | :group 'readable-mono-theme) 136 | 137 | (let ((default-height readable-typo-theme-default-font-height) 138 | (default-weight readable-typo-theme-default-font-weight) 139 | (bold-weight readable-typo-theme-bold-font-weight) 140 | (fixed-pitch readable-typo-theme-fixed-pitch-font) 141 | (fixed-pitch-serif readable-typo-theme-fixed-pitch-serif-font) 142 | (variable-pitch readable-typo-theme-variable-pitch-font) 143 | (serif readable-typo-theme-serif-font) 144 | (small-height (if readable-typo-theme-font-scaling readable-typo-theme-font-height-small nil)) 145 | (title-height (if readable-typo-theme-font-scaling readable-typo-theme-font-height-title nil)) 146 | (level-1-height (if readable-typo-theme-font-scaling readable-typo-theme-font-height-level-1 nil)) 147 | (level-2-height (if readable-typo-theme-font-scaling readable-typo-theme-font-height-level-2 nil)) 148 | (level-3-height (if readable-typo-theme-font-scaling readable-typo-theme-font-height-level-3 nil)) 149 | (level-4-height (if readable-typo-theme-font-scaling readable-typo-theme-font-height-level-4 nil)) 150 | (level-5-height (if readable-typo-theme-font-scaling readable-typo-theme-font-height-level-5 nil)) 151 | (level-6-height (if readable-typo-theme-font-scaling readable-typo-theme-font-height-level-6 nil)) 152 | (level-7-height (if readable-typo-theme-font-scaling readable-typo-theme-font-height-level-7 nil)) 153 | (level-8-height (if readable-typo-theme-font-scaling readable-typo-theme-font-height-level-8 nil))) 154 | 155 | ;;;; Theme faces 156 | (custom-theme-set-faces 157 | 'readable-typo 158 | 159 | `(default ((t (:height ,default-height :family ,fixed-pitch :weight ,default-weight)))) 160 | 161 | `(bold ((t (:weight ,bold-weight)))) 162 | '(bold-italic ((t (:inherit bold)))) 163 | 164 | `(fixed-pitch ((t (:family ,fixed-pitch :weight ,default-weight)))) 165 | `(fixed-pitch-serif ((t (:family ,fixed-pitch-serif :weight ,default-weight)))) 166 | `(variable-pitch ((t (:family ,variable-pitch :weight ,default-weight)))) 167 | `(variable-pitch-text ((t (:height 1.1 :family ,serif)))) 168 | 169 | '(link ((t (:inherit underline)))) 170 | 171 | `(readable-typo-theme-echo-area ((t (:family ,variable-pitch :weight ,default-weight)))) 172 | 173 | ;;;;; Interface 174 | `(mode-line-active ((t (:family ,variable-pitch :height ,small-height)))) 175 | `(mode-line-inactive ((t (:family ,variable-pitch :height ,small-height)))) 176 | `(header-line ((t (:family ,variable-pitch :height ,small-height)))) 177 | `(line-number ((t (:family ,fixed-pitch)))) 178 | `(whitespace-space ((t (:family ,fixed-pitch)))) 179 | `(help-key-binding ((t (:inherit fixed-pitch)))) 180 | 181 | ;;;;; font-lock 182 | '(font-lock-comment-face ((t (:inherit italic)))) 183 | '(font-lock-type-face ((t (:inherit bold)))) 184 | '(font-lock-builtin-face ((t (:inherit bold)))) 185 | '(font-lock-keyword-face ((t (:inherit bold)))) 186 | 187 | ;;;;; corfu 188 | `(corfu-default ((t (:family ,fixed-pitch)))) 189 | 190 | ;;;;; Info 191 | `(info-title-1 ((t (:height ,level-1-height)))) 192 | `(info-title-2 ((t (:height ,level-2-height)))) 193 | `(info-title-3 ((t (:height ,level-3-height)))) 194 | `(info-title-4 ((t (:height ,level-4-height :slant italic)))) 195 | 196 | ;;;;; magit 197 | `(magit-section-heading ((t (:family ,variable-pitch :height ,level-2-height)))) 198 | 199 | ;;;;; markdown 200 | `(markdown-header-face-1 ((t (:height ,level-1-height :weight ,bold-weight)))) 201 | `(markdown-header-face-2 ((t (:height ,level-2-height :weight ,bold-weight)))) 202 | `(markdown-header-face-3 ((t (:height ,level-3-height :weight ,bold-weight)))) 203 | `(markdown-header-face-4 ((t (:height ,level-4-height :weight ,bold-weight :slant italic)))) 204 | `(markdown-header-face-5 ((t (:height ,level-5-height :weight ,bold-weight :slant italic)))) 205 | `(markdown-header-face-6 ((t (:height ,level-6-height :weight ,bold-weight :slant italic)))) 206 | `(markdown-code-face ((t (:family ,fixed-pitch)))) 207 | `(markdown-gfm-checkbox-face ((t (:family ,fixed-pitch)))) 208 | `(markdown-inline-code-face ((t (:family ,fixed-pitch)))) 209 | `(markdown-markup-face ((t (:family ,fixed-pitch)))) 210 | `(markdown-pre-face ((t (:family ,fixed-pitch)))) 211 | `(markdown-table-face ((t (:family ,fixed-pitch)))) 212 | 213 | ;;;;; org 214 | `(org-document-title ((t (:height ,title-height :weight ,bold-weight)))) 215 | `(org-level-1 ((t (:height ,level-1-height :weight ,bold-weight)))) 216 | `(org-level-2 ((t (:height ,level-2-height :weight ,bold-weight)))) 217 | `(org-level-3 ((t (:height ,level-3-height :weight ,bold-weight)))) 218 | `(org-level-4 ((t (:height ,level-4-height :weight ,bold-weight :slant italic)))) 219 | `(org-level-5 ((t (:height ,level-5-height :weight ,bold-weight :slant italic)))) 220 | `(org-level-6 ((t (:height ,level-6-height :weight ,bold-weight :slant italic)))) 221 | `(org-level-7 ((t (:height ,level-7-height :weight ,bold-weight :slant italic)))) 222 | `(org-level-8 ((t (:height ,level-8-height :weight ,bold-weight :slant italic)))) 223 | `(org-list-dt ((t (:weight ,bold-weight)))) 224 | `(org-block ((t (:family ,fixed-pitch)))) 225 | `(org-checkbox ((t (:family ,fixed-pitch)))) 226 | `(org-code ((t (:family ,fixed-pitch)))) 227 | `(org-meta-line ((t (:family ,fixed-pitch)))) 228 | `(org-table ((t (:family ,fixed-pitch)))) 229 | `(org-verbatim ((t (:family ,fixed-pitch)))) 230 | 231 | `(org-agenda-structure ((t (:family ,variable-pitch :height ,level-1-height)))) 232 | 233 | ;;;;; outline 234 | `(outline-1 ((t (:height ,level-1-height :weight ,bold-weight)))) 235 | `(outline-2 ((t (:height ,level-2-height :weight ,bold-weight)))) 236 | `(outline-3 ((t (:height ,level-3-height :weight ,bold-weight)))) 237 | `(outline-4 ((t (:height ,level-4-height :weight ,bold-weight :slant italic)))) 238 | `(outline-5 ((t (:height ,level-5-height :weight ,bold-weight :slant italic)))) 239 | `(outline-6 ((t (:height ,level-6-height :weight ,bold-weight :slant italic)))) 240 | `(outline-7 ((t (:height ,level-7-height :weight ,bold-weight :slant italic)))) 241 | `(outline-8 ((t (:height ,level-8-height :weight ,bold-weight :slant italic)))) 242 | `(outline-minor-0 ((t (:family ,serif)))) 243 | 244 | ;;;;; rst 245 | `(rst-level-1 ((t (:height ,level-1-height :weight ,bold-weight)))) 246 | `(rst-level-2 ((t (:height ,level-2-height :weight ,bold-weight)))) 247 | `(rst-level-3 ((t (:height ,level-3-height :weight ,bold-weight)))) 248 | `(rst-level-4 ((t (:height ,level-4-height :weight ,bold-weight :slant italic)))) 249 | `(rst-level-5 ((t (:height ,level-5-height :weight ,bold-weight :slant italic)))) 250 | `(rst-level-6 ((t (:height ,level-6-height :weight ,bold-weight :slant italic)))) 251 | `(rst-literal ((t (:family ,fixed-pitch)))) 252 | 253 | ;;;;; spray 254 | `(spray-base-face ((t (:inherit default :family ,serif :weight ,bold-weight))))) 255 | 256 | ;;;; Theme variables 257 | (custom-theme-set-variables 258 | 'readable-typo 259 | `(line-spacing ,readable-typo-theme-line-spacing) 260 | `(x-underline-at-descent-line t))) 261 | 262 | ;;;###autoload 263 | (and load-file-name 264 | (boundp 'custom-theme-load-path) 265 | (add-to-list 'custom-theme-load-path 266 | (file-name-as-directory (file-name-directory load-file-name)))) 267 | 268 | (provide-theme 'readable-typo) 269 | (provide 'readable-typo-theme) 270 | ;;; readable-typo-theme.el ends here 271 | -------------------------------------------------------------------------------- /lisp/readable.el: -------------------------------------------------------------------------------- 1 | ;;; readable.el --- A minor-mode to make text more readable -*- coding: utf-8; lexical-binding: t -*- 2 | 3 | ;; Copyright (C) 2022 Terje Larsen 4 | ;; All rights reserved. 5 | 6 | ;; Author: Terje Larsen 7 | ;; URL: https://github.com/terlar/readable.el 8 | ;; Keywords: faces 9 | ;; Version: 0.1 10 | ;; Package-Requires: ((emacs "24.3")) 11 | 12 | ;; This file is NOT part of GNU Emacs. 13 | 14 | ;; readable is free software: you can redistribute it and/or modify 15 | ;; it under the terms of the GNU General Public License as published by 16 | ;; the Free Software Foundation, either version 3 of the License, or 17 | ;; (at your option) any later version. 18 | 19 | ;; readable is distributed in the hope that it will be useful, 20 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 21 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 | ;; GNU General Public License for more details. 23 | 24 | ;; You should have received a copy of the GNU General Public License 25 | ;; along with GNU Emacs. If not, see . 26 | 27 | ;;; Commentary: 28 | 29 | ;; `readable' is a small Emacs minor mode that improves readability by changing 30 | ;; the type face, size, line spacing e.t.c. 31 | 32 | ;;; Code: 33 | 34 | (defgroup readable nil 35 | "Make text more readable." 36 | :group 'faces) 37 | 38 | ;;;###autoload 39 | (defface readable-fixed-pitch 40 | '((t (:inherit fixed-pitch-serif))) 41 | "Face used to increase readability for `fixed-pitch' face." 42 | :group 'readable) 43 | 44 | ;;;###autoload 45 | (defface readable-variable-pitch 46 | '((t (:inherit variable-pitch-text))) 47 | "Face used to increase readability for `variable-pitch' face." 48 | :group 'readable) 49 | 50 | ;;;###autoload 51 | (defcustom readable-line-spacing 0.4 52 | "Line spacing used when command `readable-mode' is active." 53 | :type 'number 54 | :group 'readable) 55 | 56 | ;;;###autoload 57 | (defcustom readable-lighter " Readable" 58 | "Mode-line indicator for command `readable-mode'." 59 | :type '(choice (const :tag "No lighter" "") string) 60 | :group 'readable) 61 | 62 | (defvar-local readable-mode-saved-state-plist nil 63 | "Properties containing the state before `readable-mode' was enabled. 64 | Contains following state: 65 | 66 | :line-spacing NUMBER 67 | :variable-pitch BOOLEAN") 68 | 69 | (defvar-local readable-mode-fixed-pitch-remapping nil 70 | "Readable `face-remap' cookie for `fixed-pitch' face.") 71 | 72 | (defvar-local readable-mode-variable-pitch-remapping nil 73 | "Readable `face-remap' cookie for `variable-pitch' face.") 74 | 75 | (autoload 'face-remap-add-relative "face-remap") 76 | (autoload 'face-remap-remove-relative "face-remap") 77 | 78 | ;;;###autoload 79 | (define-minor-mode readable-mode 80 | "Toggle Readable mode. 81 | 82 | In Readable mode, the type face is changed, line spacing increased and various 83 | other improvements to increase readability. 84 | 85 | The face used is `readable' and `line-spacing' is configured by 86 | `readable-line-spacing'." 87 | :lighter readable-lighter 88 | :group 'readable 89 | (when readable-mode-fixed-pitch-remapping 90 | (face-remap-remove-relative readable-mode-fixed-pitch-remapping) 91 | (setq readable-mode-fixed-pitch-remapping nil)) 92 | 93 | (when readable-mode-variable-pitch-remapping 94 | (face-remap-remove-relative readable-mode-variable-pitch-remapping) 95 | (setq readable-mode-variable-pitch-remapping nil)) 96 | 97 | (if readable-mode 98 | (progn 99 | ;; Save state 100 | (setq readable-mode-saved-state-plist 101 | (list :line-spacing line-spacing 102 | :variable-pitch (bound-and-true-p buffer-face-mode))) 103 | 104 | ;; Configure readability 105 | (variable-pitch-mode 1) 106 | (setq line-spacing readable-line-spacing 107 | readable-mode-fixed-pitch-remapping 108 | (face-remap-add-relative 'fixed-pitch 'readable-fixed-pitch) 109 | readable-mode-variable-pitch-remapping 110 | (face-remap-add-relative 'variable-pitch 'readable-variable-pitch))) 111 | (progn 112 | (variable-pitch-mode (plist-get readable-mode-saved-state-plist :variable-pitch)) 113 | (setq line-spacing (plist-get readable-mode-saved-state-plist :line-spacing) 114 | readable-mode-saved-state-plist nil)))) 115 | 116 | (provide 'readable) 117 | ;;; readable.el ends here 118 | -------------------------------------------------------------------------------- /lock/archive.lock: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /lock/flake.nix: -------------------------------------------------------------------------------- 1 | { 2 | description = "THIS IS AN AUTO-GENERATED FILE. PLEASE DON'T EDIT IT MANUALLY."; 3 | inputs = { 4 | adaptive-wrap = { 5 | flake = false; 6 | owner = "emacsmirror"; 7 | repo = "adaptive-wrap"; 8 | type = "github"; 9 | }; 10 | aio = { 11 | flake = false; 12 | owner = "skeeto"; 13 | repo = "emacs-aio"; 14 | type = "github"; 15 | }; 16 | alert = { 17 | flake = false; 18 | owner = "jwiegley"; 19 | repo = "alert"; 20 | type = "github"; 21 | }; 22 | all-the-icons = { 23 | flake = false; 24 | owner = "domtronn"; 25 | repo = "all-the-icons.el"; 26 | type = "github"; 27 | }; 28 | all-the-icons-completion = { 29 | flake = false; 30 | owner = "iyefrat"; 31 | repo = "all-the-icons-completion"; 32 | type = "github"; 33 | }; 34 | all-the-icons-dired = { 35 | flake = false; 36 | owner = "wyuenho"; 37 | repo = "all-the-icons-dired"; 38 | type = "github"; 39 | }; 40 | annotate = { 41 | flake = false; 42 | owner = "bastibe"; 43 | repo = "annotate.el"; 44 | type = "github"; 45 | }; 46 | apheleia = { 47 | flake = false; 48 | owner = "radian-software"; 49 | repo = "apheleia"; 50 | type = "github"; 51 | }; 52 | avy = { 53 | flake = false; 54 | owner = "abo-abo"; 55 | repo = "avy"; 56 | type = "github"; 57 | }; 58 | browse-at-remote = { 59 | flake = false; 60 | owner = "rmuslimov"; 61 | repo = "browse-at-remote"; 62 | type = "github"; 63 | }; 64 | caml = { 65 | flake = false; 66 | owner = "ocaml"; 67 | repo = "caml-mode"; 68 | type = "github"; 69 | }; 70 | cape = { 71 | flake = false; 72 | owner = "minad"; 73 | repo = "cape"; 74 | type = "github"; 75 | }; 76 | cider = { 77 | flake = false; 78 | owner = "clojure-emacs"; 79 | repo = "cider"; 80 | type = "github"; 81 | }; 82 | clojure-mode = { 83 | flake = false; 84 | owner = "clojure-emacs"; 85 | repo = "clojure-mode"; 86 | type = "github"; 87 | }; 88 | cobol-mode = { 89 | flake = false; 90 | owner = "~hjelmtech"; 91 | repo = "cobol-mode"; 92 | type = "sourcehut"; 93 | }; 94 | compat = { 95 | flake = false; 96 | owner = "emacs-compat"; 97 | repo = "compat"; 98 | type = "github"; 99 | }; 100 | consult = { 101 | flake = false; 102 | owner = "minad"; 103 | repo = "consult"; 104 | type = "github"; 105 | }; 106 | consult-git-log-grep = { 107 | flake = false; 108 | owner = "ghosty141"; 109 | repo = "consult-git-log-grep"; 110 | type = "github"; 111 | }; 112 | copilot = { 113 | flake = false; 114 | owner = "copilot-emacs"; 115 | repo = "copilot.el"; 116 | type = "github"; 117 | }; 118 | copilot-chat = { 119 | flake = false; 120 | owner = "chep"; 121 | repo = "copilot-chat.el"; 122 | type = "github"; 123 | }; 124 | corfu = { 125 | flake = false; 126 | owner = "minad"; 127 | repo = "corfu"; 128 | type = "github"; 129 | }; 130 | cov = { 131 | flake = false; 132 | owner = "AdamNiederer"; 133 | repo = "cov"; 134 | type = "github"; 135 | }; 136 | crystal-mode = { 137 | flake = false; 138 | owner = "crystal-lang-tools"; 139 | repo = "emacs-crystal-mode"; 140 | type = "github"; 141 | }; 142 | d2-mode = { 143 | flake = false; 144 | owner = "andorsk"; 145 | repo = "d2-mode"; 146 | type = "github"; 147 | }; 148 | dash = { 149 | flake = false; 150 | owner = "magnars"; 151 | repo = "dash.el"; 152 | type = "github"; 153 | }; 154 | deadgrep = { 155 | flake = false; 156 | owner = "Wilfred"; 157 | repo = "deadgrep"; 158 | type = "github"; 159 | }; 160 | devdocs = { 161 | flake = false; 162 | owner = "astoff"; 163 | repo = "devdocs.el"; 164 | type = "github"; 165 | }; 166 | diff-hl = { 167 | flake = false; 168 | owner = "dgutov"; 169 | repo = "diff-hl"; 170 | type = "github"; 171 | }; 172 | dired-git-info = { 173 | flake = false; 174 | owner = "clemera"; 175 | repo = "dired-git-info"; 176 | type = "github"; 177 | }; 178 | dired-hacks-utils = { 179 | flake = false; 180 | owner = "Fuco1"; 181 | repo = "dired-hacks"; 182 | type = "github"; 183 | }; 184 | dired-sidebar = { 185 | flake = false; 186 | owner = "jojojames"; 187 | repo = "dired-sidebar"; 188 | type = "github"; 189 | }; 190 | dired-subtree = { 191 | flake = false; 192 | owner = "Fuco1"; 193 | repo = "dired-hacks"; 194 | type = "github"; 195 | }; 196 | docker = { 197 | flake = false; 198 | owner = "Silex"; 199 | repo = "docker.el"; 200 | type = "github"; 201 | }; 202 | dslide = { 203 | flake = false; 204 | owner = "positron-solutions"; 205 | repo = "dslide"; 206 | type = "github"; 207 | }; 208 | dtrt-indent = { 209 | flake = false; 210 | owner = "jscheid"; 211 | repo = "dtrt-indent"; 212 | type = "github"; 213 | }; 214 | dumb-jump = { 215 | flake = false; 216 | owner = "jacktasia"; 217 | repo = "dumb-jump"; 218 | type = "github"; 219 | }; 220 | easy-escape = { 221 | flake = false; 222 | owner = "cpitclaudel"; 223 | repo = "easy-escape"; 224 | type = "github"; 225 | }; 226 | edit-indirect = { 227 | flake = false; 228 | owner = "Fanael"; 229 | repo = "edit-indirect"; 230 | type = "github"; 231 | }; 232 | editorconfig = { 233 | flake = false; 234 | owner = "editorconfig"; 235 | repo = "editorconfig-emacs"; 236 | type = "github"; 237 | }; 238 | elisp-refs = { 239 | flake = false; 240 | owner = "Wilfred"; 241 | repo = "elisp-refs"; 242 | type = "github"; 243 | }; 244 | elquery = { 245 | flake = false; 246 | owner = "AdamNiederer"; 247 | repo = "elquery"; 248 | type = "github"; 249 | }; 250 | elysium = { 251 | flake = false; 252 | owner = "lanceberge"; 253 | repo = "elysium"; 254 | type = "github"; 255 | }; 256 | embark = { 257 | flake = false; 258 | owner = "oantolin"; 259 | repo = "embark"; 260 | type = "github"; 261 | }; 262 | embark-consult = { 263 | flake = false; 264 | owner = "oantolin"; 265 | repo = "embark"; 266 | type = "github"; 267 | }; 268 | envrc = { 269 | flake = false; 270 | owner = "purcell"; 271 | repo = "envrc"; 272 | type = "github"; 273 | }; 274 | epithet = { 275 | flake = false; 276 | owner = "oantolin"; 277 | repo = "epithet"; 278 | type = "github"; 279 | }; 280 | erlang = { 281 | flake = false; 282 | owner = "erlang"; 283 | repo = "otp"; 284 | type = "github"; 285 | }; 286 | esxml = { 287 | flake = false; 288 | owner = "tali713"; 289 | repo = "esxml"; 290 | type = "github"; 291 | }; 292 | "f" = { 293 | flake = false; 294 | owner = "rejeep"; 295 | repo = "f.el"; 296 | type = "github"; 297 | }; 298 | fish-mode = { 299 | flake = false; 300 | owner = "wwwjfy"; 301 | repo = "emacs-fish"; 302 | type = "github"; 303 | }; 304 | flymake-racket = { 305 | flake = false; 306 | owner = "jojojames"; 307 | repo = "flymake-racket"; 308 | type = "github"; 309 | }; 310 | focus = { 311 | flake = false; 312 | owner = "larstvei"; 313 | repo = "Focus"; 314 | type = "github"; 315 | }; 316 | fullframe = { 317 | flake = false; 318 | owner = "~tomterl"; 319 | repo = "fullframe"; 320 | type = "sourcehut"; 321 | }; 322 | gcmh = { 323 | flake = false; 324 | owner = "koral"; 325 | repo = "gcmh"; 326 | type = "gitlab"; 327 | }; 328 | ghelp = { 329 | flake = false; 330 | owner = "casouri"; 331 | repo = "ghelp"; 332 | type = "github"; 333 | }; 334 | git-modes = { 335 | flake = false; 336 | owner = "magit"; 337 | repo = "git-modes"; 338 | type = "github"; 339 | }; 340 | gntp = { 341 | flake = false; 342 | owner = "tekai"; 343 | repo = "gntp.el"; 344 | type = "github"; 345 | }; 346 | gotest = { 347 | flake = false; 348 | owner = "nlamirault"; 349 | repo = "gotest.el"; 350 | type = "github"; 351 | }; 352 | goto-chg = { 353 | flake = false; 354 | owner = "emacs-evil"; 355 | repo = "goto-chg"; 356 | type = "github"; 357 | }; 358 | gptel = { 359 | flake = false; 360 | owner = "karthink"; 361 | repo = "gptel"; 362 | type = "github"; 363 | }; 364 | gptel-aibo = { 365 | flake = false; 366 | owner = "dolmens"; 367 | repo = "gptel-aibo"; 368 | type = "github"; 369 | }; 370 | gptel-quick = { 371 | flake = false; 372 | owner = "karthink"; 373 | repo = "gptel-quick"; 374 | type = "github"; 375 | }; 376 | gradle-mode = { 377 | flake = false; 378 | owner = "scubacabra"; 379 | repo = "emacs-gradle-mode"; 380 | type = "github"; 381 | }; 382 | groovy-mode = { 383 | flake = false; 384 | owner = "Groovy-Emacs-Modes"; 385 | repo = "groovy-emacs-modes"; 386 | type = "github"; 387 | }; 388 | grugru = { 389 | flake = false; 390 | owner = "ROCKTAKEY"; 391 | repo = "grugru"; 392 | type = "github"; 393 | }; 394 | haskell-mode = { 395 | flake = false; 396 | owner = "haskell"; 397 | repo = "haskell-mode"; 398 | type = "github"; 399 | }; 400 | hcl-mode = { 401 | flake = false; 402 | owner = "hcl-emacs"; 403 | repo = "hcl-mode"; 404 | type = "github"; 405 | }; 406 | helpful = { 407 | flake = false; 408 | owner = "Wilfred"; 409 | repo = "helpful"; 410 | type = "github"; 411 | }; 412 | hide-mode-line = { 413 | flake = false; 414 | owner = "hlissner"; 415 | repo = "emacs-hide-mode-line"; 416 | type = "github"; 417 | }; 418 | hl-todo = { 419 | flake = false; 420 | owner = "tarsius"; 421 | repo = "hl-todo"; 422 | type = "github"; 423 | }; 424 | idle-highlight-mode = { 425 | flake = false; 426 | type = "git"; 427 | url = "https://codeberg.org/ideasman42/emacs-idle-highlight-mode.git"; 428 | }; 429 | imenu-anywhere = { 430 | flake = false; 431 | owner = "vspinu"; 432 | repo = "imenu-anywhere"; 433 | type = "github"; 434 | }; 435 | imenu-extra = { 436 | flake = false; 437 | owner = "redguardtoo"; 438 | repo = "imenu-extra"; 439 | type = "github"; 440 | }; 441 | imenu-list = { 442 | flake = false; 443 | owner = "bmag"; 444 | repo = "imenu-list"; 445 | type = "github"; 446 | }; 447 | indent-bars = { 448 | flake = false; 449 | owner = "jdtsmith"; 450 | repo = "indent-bars"; 451 | type = "github"; 452 | }; 453 | indent-info = { 454 | flake = false; 455 | owner = "terlar"; 456 | repo = "indent-info.el"; 457 | type = "github"; 458 | }; 459 | inf-crystal = { 460 | flake = false; 461 | owner = "brantou"; 462 | repo = "inf-crystal.el"; 463 | type = "github"; 464 | }; 465 | inf-ruby = { 466 | flake = false; 467 | owner = "nonsequitur"; 468 | repo = "inf-ruby"; 469 | type = "github"; 470 | }; 471 | inheritenv = { 472 | flake = false; 473 | owner = "purcell"; 474 | repo = "inheritenv"; 475 | type = "github"; 476 | }; 477 | jinx = { 478 | flake = false; 479 | owner = "minad"; 480 | repo = "jinx"; 481 | type = "github"; 482 | }; 483 | json-navigator = { 484 | flake = false; 485 | owner = "DamienCassou"; 486 | repo = "json-navigator"; 487 | type = "github"; 488 | }; 489 | kotlin-mode = { 490 | flake = false; 491 | owner = "Emacs-Kotlin-Mode-Maintainers"; 492 | repo = "kotlin-mode"; 493 | type = "github"; 494 | }; 495 | kubernetes = { 496 | flake = false; 497 | owner = "kubernetes-el"; 498 | repo = "kubernetes-el"; 499 | type = "github"; 500 | }; 501 | ligature = { 502 | flake = false; 503 | owner = "mickeynp"; 504 | repo = "ligature.el"; 505 | type = "github"; 506 | }; 507 | link-hint = { 508 | flake = false; 509 | owner = "noctuid"; 510 | repo = "link-hint.el"; 511 | type = "github"; 512 | }; 513 | llama = { 514 | flake = false; 515 | owner = "tarsius"; 516 | repo = "llama"; 517 | type = "github"; 518 | }; 519 | log4e = { 520 | flake = false; 521 | owner = "aki2o"; 522 | repo = "log4e"; 523 | type = "github"; 524 | }; 525 | lte = { 526 | flake = false; 527 | owner = "fredericgiquel"; 528 | repo = "lte.el"; 529 | type = "github"; 530 | }; 531 | magit = { 532 | flake = false; 533 | owner = "magit"; 534 | repo = "magit"; 535 | type = "github"; 536 | }; 537 | magit-popup = { 538 | flake = false; 539 | owner = "magit"; 540 | repo = "magit-popup"; 541 | type = "github"; 542 | }; 543 | magit-section = { 544 | flake = false; 545 | owner = "magit"; 546 | repo = "magit"; 547 | type = "github"; 548 | }; 549 | marginalia = { 550 | flake = false; 551 | owner = "minad"; 552 | repo = "marginalia"; 553 | type = "github"; 554 | }; 555 | markdown-mode = { 556 | flake = false; 557 | owner = "jrblevin"; 558 | repo = "markdown-mode"; 559 | type = "github"; 560 | }; 561 | markdown-toc = { 562 | flake = false; 563 | owner = "ardumont"; 564 | repo = "markdown-toc"; 565 | type = "github"; 566 | }; 567 | miniedit = { 568 | flake = false; 569 | owner = "emacsorphanage"; 570 | repo = "miniedit"; 571 | type = "github"; 572 | }; 573 | minitest = { 574 | flake = false; 575 | owner = "arthurnn"; 576 | repo = "minitest-emacs"; 577 | type = "github"; 578 | }; 579 | nix-mode = { 580 | flake = false; 581 | owner = "NixOS"; 582 | repo = "nix-mode"; 583 | type = "github"; 584 | }; 585 | nix-ts-mode = { 586 | flake = false; 587 | owner = "nix-community"; 588 | repo = "nix-ts-mode"; 589 | type = "github"; 590 | }; 591 | no-littering = { 592 | flake = false; 593 | owner = "emacscollective"; 594 | repo = "no-littering"; 595 | type = "github"; 596 | }; 597 | noccur = { 598 | flake = false; 599 | owner = "NicolasPetton"; 600 | repo = "noccur.el"; 601 | type = "github"; 602 | }; 603 | nov = { 604 | flake = false; 605 | owner = "emacsmirror"; 606 | repo = "nov"; 607 | type = "github"; 608 | }; 609 | nushell-ts-mode = { 610 | flake = false; 611 | owner = "herbertjones"; 612 | repo = "nushell-ts-mode"; 613 | type = "github"; 614 | }; 615 | ob-http = { 616 | flake = false; 617 | owner = "zweifisch"; 618 | repo = "ob-http"; 619 | type = "github"; 620 | }; 621 | orderless = { 622 | flake = false; 623 | owner = "oantolin"; 624 | repo = "orderless"; 625 | type = "github"; 626 | }; 627 | org-appear = { 628 | flake = false; 629 | owner = "awth13"; 630 | repo = "org-appear"; 631 | type = "github"; 632 | }; 633 | org-cliplink = { 634 | flake = false; 635 | owner = "rexim"; 636 | repo = "org-cliplink"; 637 | type = "github"; 638 | }; 639 | org-contrib = { 640 | flake = false; 641 | owner = "~bzg"; 642 | repo = "org-contrib"; 643 | type = "sourcehut"; 644 | }; 645 | org-limit-image-size = { 646 | flake = false; 647 | owner = "misohena"; 648 | repo = "org-inline-image-fix"; 649 | type = "github"; 650 | }; 651 | org-modern = { 652 | flake = false; 653 | owner = "minad"; 654 | repo = "org-modern"; 655 | type = "github"; 656 | }; 657 | org-noter = { 658 | flake = false; 659 | owner = "org-noter"; 660 | repo = "org-noter"; 661 | type = "github"; 662 | }; 663 | outline-minor-faces = { 664 | flake = false; 665 | owner = "tarsius"; 666 | repo = "outline-minor-faces"; 667 | type = "github"; 668 | }; 669 | ox-epub = { 670 | flake = false; 671 | owner = "ofosos"; 672 | repo = "ox-epub"; 673 | type = "github"; 674 | }; 675 | package-lint = { 676 | flake = false; 677 | owner = "purcell"; 678 | repo = "package-lint"; 679 | type = "github"; 680 | }; 681 | package-lint-flymake = { 682 | flake = false; 683 | owner = "purcell"; 684 | repo = "package-lint"; 685 | type = "github"; 686 | }; 687 | page-break-lines = { 688 | flake = false; 689 | owner = "purcell"; 690 | repo = "page-break-lines"; 691 | type = "github"; 692 | }; 693 | parseclj = { 694 | flake = false; 695 | owner = "clojure-emacs"; 696 | repo = "parseclj"; 697 | type = "github"; 698 | }; 699 | parseedn = { 700 | flake = false; 701 | owner = "clojure-emacs"; 702 | repo = "parseedn"; 703 | type = "github"; 704 | }; 705 | pdf-tools = { 706 | flake = false; 707 | owner = "vedang"; 708 | repo = "pdf-tools"; 709 | type = "github"; 710 | }; 711 | polymode = { 712 | flake = false; 713 | owner = "polymode"; 714 | repo = "polymode"; 715 | type = "github"; 716 | }; 717 | pomm = { 718 | flake = false; 719 | owner = "SqrtMinusOne"; 720 | repo = "pomm.el"; 721 | type = "github"; 722 | }; 723 | popper = { 724 | flake = false; 725 | owner = "karthink"; 726 | repo = "popper"; 727 | type = "github"; 728 | }; 729 | popup = { 730 | flake = false; 731 | owner = "auto-complete"; 732 | repo = "popup-el"; 733 | type = "github"; 734 | }; 735 | puni = { 736 | flake = false; 737 | owner = "AmaiKinono"; 738 | repo = "puni"; 739 | type = "github"; 740 | }; 741 | python-test = { 742 | flake = false; 743 | owner = "emacs-pe"; 744 | repo = "python-test.el"; 745 | type = "github"; 746 | }; 747 | queue = { 748 | flake = false; 749 | owner = "emacsmirror"; 750 | repo = "queue"; 751 | type = "github"; 752 | }; 753 | racket-mode = { 754 | flake = false; 755 | owner = "greghendershott"; 756 | repo = "racket-mode"; 757 | type = "github"; 758 | }; 759 | repl-toggle = { 760 | flake = false; 761 | owner = "~tomterl"; 762 | repo = "repl-toggle"; 763 | type = "sourcehut"; 764 | }; 765 | request = { 766 | flake = false; 767 | owner = "tkf"; 768 | repo = "emacs-request"; 769 | type = "github"; 770 | }; 771 | "s" = { 772 | flake = false; 773 | owner = "magnars"; 774 | repo = "s.el"; 775 | type = "github"; 776 | }; 777 | scala-mode = { 778 | flake = false; 779 | owner = "hvesalai"; 780 | repo = "emacs-scala-mode"; 781 | type = "github"; 782 | }; 783 | separedit = { 784 | flake = false; 785 | owner = "twlz0ne"; 786 | repo = "separedit.el"; 787 | type = "github"; 788 | }; 789 | sesman = { 790 | flake = false; 791 | owner = "vspinu"; 792 | repo = "sesman"; 793 | type = "github"; 794 | }; 795 | shell-maker = { 796 | flake = false; 797 | owner = "xenodium"; 798 | repo = "shell-maker"; 799 | type = "github"; 800 | }; 801 | sly = { 802 | flake = false; 803 | owner = "joaotavora"; 804 | repo = "sly"; 805 | type = "github"; 806 | }; 807 | sly-quicklisp = { 808 | flake = false; 809 | owner = "joaotavora"; 810 | repo = "sly-quicklisp"; 811 | type = "github"; 812 | }; 813 | spinner = { 814 | flake = false; 815 | owner = "Malabarba"; 816 | repo = "spinner.el"; 817 | type = "github"; 818 | }; 819 | spray = { 820 | flake = false; 821 | owner = "~iank"; 822 | repo = "spray"; 823 | type = "sourcehut"; 824 | }; 825 | string-inflection = { 826 | flake = false; 827 | owner = "akicho8"; 828 | repo = "string-inflection"; 829 | type = "github"; 830 | }; 831 | stripe-buffer = { 832 | flake = false; 833 | owner = "sabof"; 834 | repo = "stripe-buffer"; 835 | type = "github"; 836 | }; 837 | tablist = { 838 | flake = false; 839 | owner = "emacsorphanage"; 840 | repo = "tablist"; 841 | type = "github"; 842 | }; 843 | tempel = { 844 | flake = false; 845 | owner = "minad"; 846 | repo = "tempel"; 847 | type = "github"; 848 | }; 849 | terraform-mode = { 850 | flake = false; 851 | owner = "hcl-emacs"; 852 | repo = "terraform-mode"; 853 | type = "github"; 854 | }; 855 | transient = { 856 | flake = false; 857 | owner = "magit"; 858 | repo = "transient"; 859 | type = "github"; 860 | }; 861 | transpose-frame = { 862 | flake = false; 863 | owner = "emacsorphanage"; 864 | repo = "transpose-frame"; 865 | type = "github"; 866 | }; 867 | tuareg = { 868 | flake = false; 869 | owner = "ocaml"; 870 | repo = "tuareg"; 871 | type = "github"; 872 | }; 873 | ultra-scroll = { 874 | flake = false; 875 | owner = "jdtsmith"; 876 | repo = "ultra-scroll"; 877 | type = "github"; 878 | }; 879 | valign = { 880 | flake = false; 881 | owner = "casouri"; 882 | repo = "valign"; 883 | type = "github"; 884 | }; 885 | vertico = { 886 | flake = false; 887 | owner = "minad"; 888 | repo = "vertico"; 889 | type = "github"; 890 | }; 891 | virtual-auto-fill = { 892 | flake = false; 893 | owner = "luisgerhorst"; 894 | repo = "virtual-auto-fill"; 895 | type = "github"; 896 | }; 897 | visual-fill-column = { 898 | flake = false; 899 | type = "git"; 900 | url = "https://codeberg.org/joostkremers/visual-fill-column.git"; 901 | }; 902 | visual-replace = { 903 | flake = false; 904 | owner = "szermatt"; 905 | repo = "visual-replace"; 906 | type = "github"; 907 | }; 908 | vterm = { 909 | flake = false; 910 | owner = "akermu"; 911 | repo = "emacs-libvterm"; 912 | type = "github"; 913 | }; 914 | vterm-toggle = { 915 | flake = false; 916 | owner = "jixiuf"; 917 | repo = "vterm-toggle"; 918 | type = "github"; 919 | }; 920 | vundo = { 921 | flake = false; 922 | owner = "casouri"; 923 | repo = "vundo"; 924 | type = "github"; 925 | }; 926 | with-editor = { 927 | flake = false; 928 | owner = "magit"; 929 | repo = "with-editor"; 930 | type = "github"; 931 | }; 932 | ws-butler = { 933 | flake = false; 934 | owner = "emacsmirror"; 935 | ref = "elpa/ws-butler"; 936 | repo = "nongnu_elpa"; 937 | type = "github"; 938 | }; 939 | }; 940 | outputs = { ... }: { }; 941 | } 942 | -------------------------------------------------------------------------------- /media/emacs-lisp-mode-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terlar/emacs-config/ce8528a9feb55243b0f94756db24d94d1b4951aa/media/emacs-lisp-mode-dark.png -------------------------------------------------------------------------------- /media/emacs-lisp-mode-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terlar/emacs-config/ce8528a9feb55243b0f94756db24d94d1b4951aa/media/emacs-lisp-mode-light.png -------------------------------------------------------------------------------- /media/markdown-mode-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terlar/emacs-config/ce8528a9feb55243b0f94756db24d94d1b4951aa/media/markdown-mode-dark.png -------------------------------------------------------------------------------- /media/markdown-mode-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terlar/emacs-config/ce8528a9feb55243b0f94756db24d94d1b4951aa/media/markdown-mode-light.png -------------------------------------------------------------------------------- /media/org-mode-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terlar/emacs-config/ce8528a9feb55243b0f94756db24d94d1b4951aa/media/org-mode-dark.png -------------------------------------------------------------------------------- /media/org-mode-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terlar/emacs-config/ce8528a9feb55243b0f94756db24d94d1b4951aa/media/org-mode-light.png -------------------------------------------------------------------------------- /media/rst-mode-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terlar/emacs-config/ce8528a9feb55243b0f94756db24d94d1b4951aa/media/rst-mode-dark.png -------------------------------------------------------------------------------- /media/rst-mode-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terlar/emacs-config/ce8528a9feb55243b0f94756db24d94d1b4951aa/media/rst-mode-light.png -------------------------------------------------------------------------------- /media/samples/example-image.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terlar/emacs-config/ce8528a9feb55243b0f94756db24d94d1b4951aa/media/samples/example-image.jpg -------------------------------------------------------------------------------- /media/samples/sample.md: -------------------------------------------------------------------------------- 1 | An h1 header 2 | ============ 3 | Paragraphs are separated by a blank line. 4 | 5 | 2nd paragraph. *Italic*, **bold**, and `monospace`. Itemized lists look like: 6 | 7 | * this one 8 | * [x] that one 9 | * [ ] the other one 10 | 11 | Note that --- not considering the asterisk --- the actual text content starts at 4-columns in. 12 | 13 | > Block quotes are 14 | > written like so. 15 | > 16 | > They can span multiple paragraphs, 17 | > if you like. 18 | 19 | Use 3 dashes for an em-dash. Use 2 dashes for ranges (ex., "it's all in chapters 12--14"). Three dots ... will be converted to an ellipsis. Unicode is supported. ☺ 20 | 21 | An h2 header 22 | ------------ 23 | Here's a numbered list: 24 | 25 | 1. first item 26 | 2. second item 27 | 3. third item 28 | 29 | Note again how the actual text starts at 4 columns in (4 characters from the left side). Here's a code sample: 30 | 31 | # Let me re-iterate ... 32 | for i in 1 .. 10 { do-something(i) } 33 | 34 | As you probably guessed, indented 4 spaces. By the way, instead of indenting the block, you can use delimited blocks, if you like: 35 | 36 | ~~~ 37 | define foobar() { 38 | print "Welcome to flavor country!"; 39 | } 40 | ~~~ 41 | 42 | (which makes copying & pasting easier). You can optionally mark the delimited block for Pandoc to syntax highlight it: 43 | 44 | ~~~python 45 | import time 46 | # Quick, count to ten! 47 | for i in range(10): 48 | # (but not *too* quick) 49 | time.sleep(0.5) 50 | print i 51 | ~~~ 52 | 53 | ### An h3 header ### 54 | 55 | Now a nested list: 56 | 1. First, get these ingredients: 57 | * carrots 58 | * celery 59 | * lentils 60 | 2. Boil some water. 61 | 3. Dump everything in the pot and follow this algorithm: 62 | 63 | find wooden spoon 64 | uncover pot 65 | stir 66 | cover pot 67 | balance wooden spoon precariously on pot handle 68 | wait 10 minutes 69 | goto first step (or shut off burner when done) 70 | 71 | Do not bump wooden spoon or it will fall. 72 | 73 | Notice again how text always lines up on 4-space indents (including that last line which continues item 3 above). 74 | 75 | Here's a link to [a website](http://foo.bar), to a [local doc](local-doc.html), and to a [section heading in the current doc](#an-h2-header). Here's a footnote [^1]. 76 | 77 | [^1]: Footnote text goes here. 78 | 79 | Tables can look like this: 80 | 81 | | size | material | color | 82 | |------|-------------|-------------| 83 | | 9 | rubber | yellow | 84 | | 10 | hemp canvas | natural | 85 | | 11 | glass | transparent | 86 | 87 | Table: Shoes, their sizes, and what they're made of 88 | 89 | A horizontal rule follows. 90 | 91 | *** 92 | 93 | Here's a definition list: 94 | 95 | apples 96 | : Good for making applesauce. 97 | oranges 98 | : Citrus! 99 | tomatoes 100 | : There's no "e" in tomatoe. 101 | 102 | Again, text is indented 4 spaces. (Put a blank line between each term/definition pair to spread things out more.) 103 | 104 | Here's a "line block": 105 | 106 | | Line one 107 | | Line too 108 | | Line tree 109 | 110 | and images can be specified like so: 111 | 112 | ![example image](example-image.jpg "An exemplary image") 113 | 114 | Inline math equations go in like so: $\omega = d\phi / dt$. Display math should get its own line and be put in in double-dollarsigns: 115 | 116 | $$I = \int \rho R^{2} dV$$ 117 | 118 | And note that you can backslash-escape any punctuation characters which you wish to be displayed literally, ex.: \`foo\`, \*bar\*, etc. 119 | 120 | > **Note:** 121 | > This is a note... 122 | -------------------------------------------------------------------------------- /media/samples/sample.org: -------------------------------------------------------------------------------- 1 | #+TITLE: Sample 2 | 3 | * Header 4 | This is is a paragraph with enough text to make it wrap at 80 characters, so to reach that it has to contain at least a few more words, there, that hit the spot and some more. 5 | 6 | ** Subheading 7 | This is a paragraph of a subheading. 8 | 9 | ** Formatting 10 | Text can be formatted in different ways, for example: *bold*, /italic/, _underlined_ and =monospaced=. 11 | 12 | ** Quotation 13 | #+BEGIN_QUOTE 14 | This is a quote 15 | #+END_QUOTE 16 | 17 | ** Lists 18 | *** Bullet lists 19 | - This an item in a list 20 | - A list can have multiple items 21 | - A list can also contain other lists 22 | - Long lines of text in a list will make the text wrap, now one may ask: What does that look like? It looks like this. 23 | 24 | *** Numbered lists 25 | 1) This is an item in a numbered list 26 | 2) This is another item in a numbered list 27 | 28 | *** Checklists [2/8] 29 | - [ ] This is an item in a checklist 30 | - [X] This is a checked item in a checklist 31 | - [-] A checklist can also contain sub-checklists 32 | - [ ] This is an item in a sub-checklist 33 | - [X] This is a checked item in a sub-checklist 34 | 35 | *** Definition lists 36 | - Definition lists :: lists that define things 37 | - Definition list item :: a member of the definition list 38 | 39 | ** Table 40 | | Header for column A | Header for column B | 41 | |---------------------------+---------------------------| 42 | | An entry in column A | An entry in column B | 43 | | Another entry in column A | Another entry in column B | 44 | 45 | ** Code 46 | Code can be described ~inline~ or as a source block: 47 | #+BEGIN_SRC python 48 | def hello: 49 | print "hello" 50 | 51 | hello() 52 | #+END_SRC 53 | 54 | #+RESULTS: 55 | -------------------------------------------------------------------------------- /media/samples/sample.rst: -------------------------------------------------------------------------------- 1 | ========================================= 2 | ReStructuredText (rst): plain text markup 3 | ========================================= 4 | 5 | .. sectnum:: 6 | 7 | .. contents:: The tiny table of contents 8 | 9 | What is reStructuredText? 10 | ~~~~~~~~~~~~~~~~~~~~~~~~~ 11 | 12 | An easy-to-read, what-you-see-is-what-you-get plaintext markup syntax 13 | and parser system, abbreviated *rst*. In other words, using a simple 14 | text editor, documents can be created which 15 | 16 | - are easy to read in text editor and 17 | - can be *automatically* converted to 18 | 19 | - html and 20 | - latex (and therefore pdf) 21 | 22 | What is it good for? 23 | ~~~~~~~~~~~~~~~~~~~~ 24 | 25 | reStructuredText can be used, for example, to 26 | 27 | - write technical documentation (so that it can easily be offered as a 28 | pdf file or a web page) 29 | - create html webpages without knowing html 30 | - to document source code 31 | - [x] checked checkbox 32 | - [ ] unchecked checkbox 33 | 34 | Show me some formatting examples 35 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 36 | 37 | You can highlight text in *italics* or, to provide even more emphasis 38 | in **bold**. Often, when describing computer code, we like to use a 39 | ``fixed space font`` to quote code snippets. 40 | 41 | We can also include footnotes [1]_. We could include source code files 42 | (by specifying their name) which is useful when documenting code. We 43 | can also copy source code verbatim (i.e. include it in the rst 44 | document) like this:: 45 | 46 | int main ( int argc, char *argv[] ) { 47 | printf("Hello World\n"); 48 | return 0; 49 | } 50 | 51 | We have already seen at itemised list in section `What is it good 52 | for?`_. Enumerated list and descriptive lists are supported as 53 | well. It provides very good support for including html-links in a 54 | variety of ways. Any section and subsections defined can be linked to, 55 | as well. 56 | 57 | 58 | Where can I learn more? 59 | ~~~~~~~~~~~~~~~~~~~~~~~ 60 | 61 | reStructuredText is described at 62 | http://docutils.sourceforge.net/rst.html. We provide some geeky small 63 | print in this footnote [2]_. 64 | 65 | 66 | Show me some more stuff, please 67 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 68 | 69 | We can also include figures: 70 | 71 | .. figure:: image.png 72 | :width: 300pt 73 | 74 | 75 | The magnetisation in a small ferromagnetic disk. The diametre is of the order of 120 nanometers and the material is Ni20Fe80. Png is a file format that is both acceptable for html pages as well as for (pdf)latex. 76 | 77 | --------------------------------------------------------------------------- 78 | 79 | .. [1] although there isn't much point of using a footnote here. 80 | 81 | .. [2] Random facts: 82 | 83 | - Emacs provides an rst mode 84 | - when converting rst to html, a style sheet can be provided (there is a similar feature for latex) 85 | - rst can also be converted into XML 86 | - the recommended file extension for rst is ``.txt`` 87 | 88 | -------------------------------------------------------------------------------- /nix/home-manager.nix: -------------------------------------------------------------------------------- 1 | { 2 | config, 3 | lib, 4 | pkgs, 5 | ... 6 | }: 7 | 8 | let 9 | inherit (lib) types; 10 | cfg = config.custom.emacsConfig; 11 | 12 | emacsEdit = if cfg.enableServer then "emacsclient" else "emacs"; 13 | emacsDesktop = if cfg.enableServer then "emacsclient.desktop" else "emacs.desktop"; 14 | emacsMailDesktop = if cfg.enableServer then "emacsclient-mail.desktop" else "emacs-mail.desktop"; 15 | in 16 | { 17 | options.custom.emacsConfig = { 18 | enable = lib.mkEnableOption "custom emacs configuration"; 19 | 20 | package = lib.mkOption { 21 | type = types.package; 22 | description = "The default Emacs derivation to use."; 23 | }; 24 | 25 | configPackage = lib.mkOption { 26 | type = types.package; 27 | description = "The default Emacs config derivation to use."; 28 | }; 29 | 30 | enableUserDirectory = lib.mkOption { 31 | default = true; 32 | type = types.bool; 33 | description = "Whether to enable user Emacs directory files."; 34 | }; 35 | 36 | enableGitDiff = lib.mkOption { 37 | default = true; 38 | type = types.bool; 39 | description = "Whether to enable ediff as default git diff tool."; 40 | }; 41 | 42 | enableServer = lib.mkOption { 43 | default = pkgs.stdenv.isLinux; 44 | type = types.bool; 45 | description = "Whether to enable user Emacs server."; 46 | }; 47 | 48 | defaultEditor = lib.mkOption { 49 | default = true; 50 | type = types.bool; 51 | description = "Whether to use Emacs as default editor."; 52 | }; 53 | 54 | defaultEmailApplication = lib.mkOption { 55 | default = false; 56 | type = types.bool; 57 | description = "Whether to use Emacs as default e-mail application."; 58 | }; 59 | 60 | defaultPdfApplication = lib.mkOption { 61 | default = false; 62 | type = types.bool; 63 | description = "Whether to use Emacs as default PDF application."; 64 | }; 65 | 66 | gnus = lib.mkOption { 67 | type = types.nullOr types.path; 68 | default = null; 69 | description = "Gnus config file."; 70 | }; 71 | 72 | erc = lib.mkOption { 73 | type = types.nullOr types.path; 74 | default = null; 75 | description = "ERC config file."; 76 | }; 77 | 78 | private = lib.mkOption { 79 | type = types.nullOr types.path; 80 | default = null; 81 | description = "Private config file."; 82 | }; 83 | }; 84 | 85 | config = lib.mkIf cfg.enable ( 86 | lib.mkMerge [ 87 | { 88 | services.emacs = { 89 | inherit (cfg) package; 90 | enable = lib.mkDefault cfg.enableServer; 91 | client.enable = lib.mkDefault true; 92 | socketActivation.enable = lib.mkDefault true; 93 | extraOptions = [ "--no-desktop" ]; 94 | }; 95 | 96 | programs.git.extraConfig = { 97 | difftool.ediff.cmd = '' 98 | ${emacsEdit} --eval '(ediff-files "'$LOCAL'" "'$REMOTE'")' 99 | ''; 100 | 101 | mergetool.ediff.cmd = '' 102 | ${emacsEdit} --eval '(ediff-merge-files-with-ancestor "'$LOCAL'" "'$REMOTE'" "'$BASE'" nil "'$MERGED'")' 103 | ''; 104 | }; 105 | 106 | home.packages = [ 107 | cfg.package 108 | ] ++ lib.optionals cfg.enableUserDirectory cfg.configPackage.runtimeInputs; 109 | } 110 | (lib.mkIf cfg.enableUserDirectory { 111 | xdg.configFile.emacs = { 112 | source = cfg.configPackage; 113 | recursive = true; 114 | }; 115 | }) 116 | (lib.mkIf cfg.defaultEditor { 117 | home.sessionVariables.EDITOR = emacsEdit; 118 | programs.qutebrowser.settings.editor.command = [ 119 | emacsEdit 120 | "{}" 121 | ]; 122 | }) 123 | (lib.mkIf cfg.enableGitDiff { programs.git.extraConfig.diff.tool = "ediff"; }) 124 | (lib.mkIf cfg.defaultEmailApplication { 125 | xdg.mimeApps.defaultApplications."x-scheme-handler/mailto" = emacsMailDesktop; 126 | }) 127 | (lib.mkIf cfg.defaultPdfApplication { 128 | xdg.mimeApps.defaultApplications."application/pdf" = emacsDesktop; 129 | }) 130 | (lib.mkIf (cfg.gnus != null) { home.file.".gnus.el".source = cfg.gnus; }) 131 | (lib.mkIf (cfg.erc != null) { xdg.configFile."emacs/.ercrc.el".source = cfg.erc; }) 132 | (lib.mkIf (cfg.private != null) { xdg.configFile."emacs/private/private.el".source = cfg.private; }) 133 | ] 134 | ); 135 | } 136 | -------------------------------------------------------------------------------- /nix/packages/emacs-config/build-config.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | stdenv, 4 | buildElispPackage, 5 | elispInputs, 6 | emacs-all-the-icons-fonts, 7 | treesit-grammars, 8 | xorg, 9 | rootPath, 10 | }: 11 | let 12 | init = buildElispPackage { 13 | ename = "config-init"; 14 | 15 | src = lib.sourceByRegex rootPath [ "init.org" ]; 16 | files = [ "init.org" ]; 17 | lispFiles = [ 18 | "early-init.el" 19 | "init.el" 20 | ]; 21 | 22 | inherit elispInputs; 23 | nativeCompileAhead = true; 24 | wantExtraOutputs = false; 25 | errorOnWarn = true; 26 | doTangle = false; 27 | 28 | preBuild = '' 29 | export HOME="$NIX_BUILD_TOP/.home" 30 | mkdir -p "$HOME/.config/emacs" 31 | 32 | emacs --batch --quick \ 33 | --load org \ 34 | *.org \ 35 | --funcall org-babel-tangle 36 | rm *.org 37 | 38 | ln -s ${treesit-grammars}/lib "$HOME/.config/emacs/tree-sitter" 39 | ''; 40 | 41 | meta = { }; 42 | }; 43 | in 44 | stdenv.mkDerivation { 45 | name = "emacs-config"; 46 | 47 | src = lib.sourceByRegex rootPath [ "templates" ]; 48 | dontUnpack = true; 49 | 50 | passthru = { 51 | components = { 52 | inherit init; 53 | }; 54 | 55 | runtimeInputs = [ 56 | emacs-all-the-icons-fonts 57 | ]; 58 | }; 59 | 60 | installPhase = '' 61 | mkdir -p $out 62 | ${xorg.lndir}/bin/lndir -silent ${init}/share/emacs/site-lisp $out 63 | 64 | if [ -d "${init}/share/emacs/native-lisp" ]; then 65 | mkdir -p $out/eln-cache 66 | ${xorg.lndir}/bin/lndir -silent ${init}/share/emacs/native-lisp $out/eln-cache 67 | fi 68 | 69 | install -D -t $out $src/templates 70 | 71 | ln -s ${treesit-grammars}/lib $out/tree-sitter 72 | ''; 73 | } 74 | -------------------------------------------------------------------------------- /nix/packages/emacs-config/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | twist-lib, 4 | pkgs, 5 | emacs, 6 | emacs-env, 7 | emacsPackages, 8 | rootPath, 9 | }: 10 | 11 | pkgs.callPackage ./build-config.nix { 12 | inherit rootPath; 13 | 14 | buildElispPackage = (twist-lib.buildElispPackage pkgs).override { 15 | inherit emacs; 16 | }; 17 | 18 | elispInputs = lib.pipe emacs-env.elispPackages [ 19 | builtins.attrValues 20 | (builtins.filter lib.isDerivation) 21 | ]; 22 | 23 | treesit-grammars = emacsPackages.treesit-grammars.with-grammars (ps: [ 24 | ps.tree-sitter-dockerfile 25 | ps.tree-sitter-elixir 26 | ps.tree-sitter-go 27 | ps.tree-sitter-gomod 28 | ps.tree-sitter-heex 29 | ps.tree-sitter-java 30 | ps.tree-sitter-javascript 31 | ps.tree-sitter-jsdoc 32 | ps.tree-sitter-json 33 | ps.tree-sitter-json5 34 | ps.tree-sitter-lua 35 | ps.tree-sitter-nix 36 | ps.tree-sitter-nu 37 | ps.tree-sitter-python 38 | ps.tree-sitter-ruby 39 | ps.tree-sitter-rust 40 | ps.tree-sitter-typescript 41 | ps.tree-sitter-yaml 42 | ]); 43 | } 44 | -------------------------------------------------------------------------------- /nix/packages/emacs-env/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | org-babel-lib, 4 | twist-lib, 5 | rootPath, 6 | melpaSrc, 7 | pkgs, 8 | emacs, 9 | }: 10 | 11 | let 12 | initEl = lib.pipe (rootPath + "/init.org") [ 13 | builtins.readFile 14 | (org-babel-lib.tangleOrgBabel { }) 15 | (builtins.toFile "init.el") 16 | ]; 17 | 18 | packageOverrides = _: prev: { 19 | elispPackages = prev.elispPackages.overrideScope ( 20 | pkgs.callPackage ./packageOverrides.nix { inherit (prev) emacs; } 21 | ); 22 | }; 23 | in 24 | (twist-lib.makeEnv { 25 | inherit pkgs; 26 | emacsPackage = emacs; 27 | 28 | initFiles = [ initEl ]; 29 | lockDir = rootPath + "/lock"; 30 | 31 | registries = import ./registries.nix { inherit rootPath melpaSrc; }; 32 | 33 | inputOverrides = import ./inputOverrides.nix { inherit rootPath lib; }; 34 | 35 | initialLibraries = [ 36 | "cl-lib" 37 | "jsonrpc" 38 | "let-alist" 39 | "map" 40 | "org" 41 | "seq" 42 | ]; 43 | 44 | localPackages = [ 45 | "pairable" 46 | "readable" 47 | "readable-mono-theme" 48 | "readable-typo-theme" 49 | ]; 50 | }).overrideScope 51 | packageOverrides 52 | -------------------------------------------------------------------------------- /nix/packages/emacs-env/inputOverrides.nix: -------------------------------------------------------------------------------- 1 | { rootPath, lib }: 2 | 3 | { 4 | devdocs = _: prev: { 5 | packageRequires = builtins.removeAttrs prev.packageRequires [ 6 | # Unused integrations. 7 | "mathjax" 8 | ]; 9 | }; 10 | 11 | ghelp = _: prev: { 12 | files = builtins.removeAttrs prev.files [ 13 | # Unused integrations. 14 | "ghelp-geiser.el" 15 | "ghelp-lspce.el" 16 | ]; 17 | 18 | packageRequires = prev.packageRequires // { 19 | # Used integrations. 20 | sly = "0"; 21 | helpful = "0"; 22 | }; 23 | }; 24 | 25 | magit = _: prev: { 26 | files = prev.files // { 27 | "lisp/Makefile" = "Makefile"; 28 | }; 29 | }; 30 | 31 | org-contrib = _: prev: { 32 | files = builtins.removeAttrs prev.files [ 33 | # Unused integrations. 34 | "lisp/ob-stata.el" 35 | ]; 36 | }; 37 | 38 | org-noter = _: prev: { 39 | packageRequires = prev.packageRequires // { 40 | pdf-tools = "0"; 41 | }; 42 | }; 43 | 44 | rustic = _: prev: { 45 | files = builtins.removeAttrs prev.files [ 46 | # Unused integrations. 47 | "rustic-flycheck.el" 48 | ]; 49 | packageRequires = builtins.removeAttrs prev.packageRequires [ 50 | # Unused integrations. 51 | "flycheck" 52 | ]; 53 | }; 54 | 55 | pairable = _: _: { 56 | src = lib.sourceByRegex rootPath [ 57 | "lisp" 58 | "lisp/pairable.el" 59 | ]; 60 | }; 61 | 62 | readable = _: _: { 63 | src = lib.sourceByRegex rootPath [ 64 | "lisp" 65 | "lisp/readable.el" 66 | ]; 67 | }; 68 | 69 | readable-mono-theme = _: _: { 70 | src = lib.sourceByRegex rootPath [ 71 | "lisp" 72 | "lisp/readable-mono-theme.el" 73 | ]; 74 | }; 75 | 76 | readable-typo-theme = _: _: { 77 | src = lib.sourceByRegex rootPath [ 78 | "lisp" 79 | "lisp/readable-typo-theme.el" 80 | ]; 81 | }; 82 | } 83 | -------------------------------------------------------------------------------- /nix/packages/emacs-env/packageOverrides.nix: -------------------------------------------------------------------------------- 1 | { 2 | stdenv, 3 | cmake, 4 | emacs, 5 | enchant2, 6 | gcc, 7 | libvterm-neovim, 8 | pkg-config, 9 | unzip, 10 | }: 11 | 12 | _final: prev: { 13 | all-the-icons = prev.all-the-icons.overrideAttrs (_: { 14 | preBuild = '' 15 | for i in data/data-*.el; do 16 | sed -i -e "1i ;;; -*- lexical-binding: t; -*-" $i 17 | done 18 | ''; 19 | }); 20 | 21 | cape = prev.cape.overrideAttrs (_: { 22 | preBuild = '' 23 | substituteInPlace cape-char.el \ 24 | --replace-fail "when-let" "when-let*" 25 | ''; 26 | }); 27 | 28 | corfu = prev.corfu.overrideAttrs (_: { 29 | preBuild = '' 30 | substituteInPlace corfu-popupinfo.el \ 31 | --replace-fail "if-let" "if-let*" \ 32 | --replace-fail "when-let" "when-let*" 33 | ''; 34 | }); 35 | 36 | devdocs = prev.devdocs.overrideAttrs (_: { 37 | preBuild = '' 38 | substituteInPlace devdocs.el --replace-fail "(require 'mathjax)" "(require 'mathjax nil t)" 39 | ''; 40 | }); 41 | 42 | jinx = prev.jinx.overrideAttrs ( 43 | old: 44 | let 45 | moduleSuffix = stdenv.targetPlatform.extensions.sharedLibrary; 46 | in 47 | { 48 | nativeBuildInputs = (old.nativeBuildInputs or [ ]) ++ [ pkg-config ]; 49 | buildInputs = (old.buildInputs or [ ]) ++ [ enchant2 ]; 50 | 51 | preBuild = '' 52 | NIX_CFLAGS_COMPILE="$($PKG_CONFIG --cflags enchant-2) $NIX_CFLAGS_COMPILE" 53 | $CC -I. -O2 -fPIC -shared -o jinx-mod${moduleSuffix} jinx-mod.c -lenchant-2 54 | rm *.c *.h 55 | ''; 56 | } 57 | ); 58 | 59 | magit = prev.magit.overrideAttrs (old: { 60 | preBuild = '' 61 | substituteInPlace Makefile --replace "include ../default.mk" "" 62 | make PKG=magit VERSION="${old.version}" magit-version.el 63 | sed -i -e "1i ;;; -*- lexical-binding: t; -*-" magit-version.el 64 | rm Makefile 65 | ''; 66 | }); 67 | 68 | nov = prev.nov.overrideAttrs (old: { 69 | propagatedBuildInputs = (old.propagatedBuildInputs or [ ]) ++ [ unzip ]; 70 | }); 71 | 72 | vterm = prev.vterm.overrideAttrs (old: { 73 | nativeBuildInputs = [ 74 | cmake 75 | gcc 76 | ]; 77 | buildInputs = old.buildInputs ++ [ libvterm-neovim ]; 78 | cmakeFlags = [ "-DEMACS_SOURCE=${emacs.src}" ]; 79 | preBuild = '' 80 | mkdir -p build 81 | cd build 82 | cmake .. 83 | make 84 | install -m444 -t . ../*.so 85 | install -m600 -t . ../*.el 86 | cp -r -t . ../etc 87 | rm -rf {CMake*,build,*.c,*.h,Makefile,*.cmake} 88 | ''; 89 | }); 90 | } 91 | -------------------------------------------------------------------------------- /nix/packages/emacs-env/registries.nix: -------------------------------------------------------------------------------- 1 | { rootPath, melpaSrc }: 2 | 3 | [ 4 | { 5 | name = "custom"; 6 | type = "melpa"; 7 | path = rootPath + "/recipes"; 8 | } 9 | { 10 | name = "melpa"; 11 | type = "melpa"; 12 | path = melpaSrc + "/recipes"; 13 | } 14 | { 15 | name = "gnu-archive"; 16 | type = "archive"; 17 | url = "https://elpa.gnu.org/packages/"; 18 | } 19 | { 20 | name = "nongnu-archive"; 21 | type = "archive"; 22 | url = "https://elpa.nongnu.org/nongnu/"; 23 | } 24 | ] 25 | -------------------------------------------------------------------------------- /recipes/adaptive-wrap: -------------------------------------------------------------------------------- 1 | (adaptive-wrap :fetcher github 2 | :repo "emacsmirror/adaptive-wrap") 3 | -------------------------------------------------------------------------------- /recipes/cobol-mode: -------------------------------------------------------------------------------- 1 | (cobol-mode :fetcher sourcehut 2 | :repo "hjelmtech/cobol-mode") 3 | -------------------------------------------------------------------------------- /recipes/compat: -------------------------------------------------------------------------------- 1 | (compat :fetcher github 2 | :repo "emacs-compat/compat") 3 | -------------------------------------------------------------------------------- /recipes/dired-git-info: -------------------------------------------------------------------------------- 1 | (dired-git-info :fetcher github 2 | :repo "clemera/dired-git-info") 3 | -------------------------------------------------------------------------------- /recipes/epithet: -------------------------------------------------------------------------------- 1 | (epithet :fetcher github 2 | :repo "oantolin/epithet") 3 | -------------------------------------------------------------------------------- /recipes/explain-pause-mode: -------------------------------------------------------------------------------- 1 | (explain-pause-mode :fetcher github 2 | :repo "lastquestion/explain-pause-mode") 3 | -------------------------------------------------------------------------------- /recipes/ghelp: -------------------------------------------------------------------------------- 1 | (ghelp :fetcher github 2 | :repo "casouri/ghelp") 3 | -------------------------------------------------------------------------------- /recipes/gptel-aibo: -------------------------------------------------------------------------------- 1 | (gptel-aibo :fetcher github 2 | :repo "dolmens/gptel-aibo") 3 | -------------------------------------------------------------------------------- /recipes/gptel-quick: -------------------------------------------------------------------------------- 1 | (gptel-quick :fetcher github 2 | :repo "karthink/gptel-quick") 3 | -------------------------------------------------------------------------------- /recipes/indent-bars: -------------------------------------------------------------------------------- 1 | (indent-bars :fetcher github 2 | :repo "jdtsmith/indent-bars") 3 | -------------------------------------------------------------------------------- /recipes/minuet: -------------------------------------------------------------------------------- 1 | (minuet :fetcher github 2 | :repo "milanglacier/minuet-ai.el") 3 | -------------------------------------------------------------------------------- /recipes/nov: -------------------------------------------------------------------------------- 1 | (nov :fetcher github 2 | :repo "emacsmirror/nov") 3 | -------------------------------------------------------------------------------- /recipes/org-contrib: -------------------------------------------------------------------------------- 1 | (org-contrib :fetcher sourcehut 2 | :repo "bzg/org-contrib") 3 | -------------------------------------------------------------------------------- /recipes/org-limit-image-size: -------------------------------------------------------------------------------- 1 | (org-limit-image-size :fetcher github 2 | :repo "misohena/org-inline-image-fix" 3 | :files ("org-limit-image-size.el")) 4 | -------------------------------------------------------------------------------- /recipes/pairable: -------------------------------------------------------------------------------- 1 | (pairable :fetcher github 2 | :repo "terlar/emacs-config" 3 | :files ("lisp/pairable.el")) 4 | -------------------------------------------------------------------------------- /recipes/plz: -------------------------------------------------------------------------------- 1 | (plz :fetcher github 2 | :repo "alphapapa/plz.el") 3 | -------------------------------------------------------------------------------- /recipes/queue: -------------------------------------------------------------------------------- 1 | (queue :fetcher github 2 | :repo "emacsmirror/queue") 3 | -------------------------------------------------------------------------------- /recipes/readable: -------------------------------------------------------------------------------- 1 | (readable :fetcher github 2 | :repo "terlar/emacs-config" 3 | :files ("lisp/readable.el")) 4 | -------------------------------------------------------------------------------- /recipes/readable-mono-theme: -------------------------------------------------------------------------------- 1 | (readable-mono-theme :fetcher github 2 | :repo "terlar/emacs-config" 3 | :files ("lisp/readable-mono-theme.el")) 4 | -------------------------------------------------------------------------------- /recipes/readable-typo-theme: -------------------------------------------------------------------------------- 1 | (readable-typo-theme :fetcher github 2 | :repo "terlar/emacs-config" 3 | :files ("lisp/readable-typo-theme.el")) 4 | -------------------------------------------------------------------------------- /recipes/spinner: -------------------------------------------------------------------------------- 1 | (spinner :fetcher github 2 | :repo "Malabarba/spinner.el") 3 | -------------------------------------------------------------------------------- /recipes/ultra-scroll: -------------------------------------------------------------------------------- 1 | (ultra-scroll :fetcher github 2 | :repo "jdtsmith/ultra-scroll") 3 | -------------------------------------------------------------------------------- /recipes/valign: -------------------------------------------------------------------------------- 1 | (valign :fetcher github 2 | :repo "casouri/valign") 3 | -------------------------------------------------------------------------------- /recipes/vundo: -------------------------------------------------------------------------------- 1 | (vundo :fetcher github 2 | :repo "casouri/vundo") 3 | -------------------------------------------------------------------------------- /recipes/ws-butler: -------------------------------------------------------------------------------- 1 | (ws-butler :fetcher github 2 | :repo "emacsmirror/nongnu_elpa" 3 | :branch "elpa/ws-butler") 4 | -------------------------------------------------------------------------------- /shell.nix: -------------------------------------------------------------------------------- 1 | let 2 | lock = builtins.fromJSON (builtins.readFile ./dev/flake.lock); 3 | in 4 | (import (fetchTarball { 5 | url = "https://github.com/edolstra/flake-compat/archive/${lock.nodes.flake-compat.locked.rev}.tar.gz"; 6 | sha256 = lock.nodes.flake-compat.locked.narHash; 7 | }) { src = ./dev; }).shellNix 8 | -------------------------------------------------------------------------------- /templates: -------------------------------------------------------------------------------- 1 | fundamental-mode 2 | 3 | (today (format-time-string "%Y-%m-%d")) 4 | 5 | prog-mode 6 | 7 | (fixme (if (derived-mode-p 'emacs-lisp-mode) ";; " comment-start) "FIXME ") 8 | (todo (if (derived-mode-p 'emacs-lisp-mode) ";; " comment-start) "TODO ") 9 | (bug (if (derived-mode-p 'emacs-lisp-mode) ";; " comment-start) "BUG ") 10 | (hack (if (derived-mode-p 'emacs-lisp-mode) ";; " comment-start) "HACK ") 11 | 12 | emacs-lisp-mode 13 | 14 | (autoload ";;;###autoload") 15 | (pt "(point)") 16 | (var "(defvar " p "\n \"" p "\")") 17 | (local "(defvar-local " p "\n \"" p "\")") 18 | (const "(defconst " p "\n \"" p "\")") 19 | (custom "(defcustom " p "\n \"" p "\"" n> ":type '" p ")") 20 | (face "(defface " p " '((t :inherit " p "))\n \"" p "\")") 21 | (group "(defgroup " p " nil\n \"" p "\"" n> ":group '" p n> ":prefix \"" p "-\")") 22 | (macro "(defmacro " p " (" p ")\n \"" p "\"" n> r> ")") 23 | (alias "(defalias '" p " '" p ")") 24 | (fun "(defun " p " (" p ")\n \"" p "\"" n> r> ")") 25 | (iflet "(if-let* (" p ")" n> r> ")") 26 | (whenlet "(when-let* (" p ")" n> r> ")") 27 | (whilelet "(while-let (" p ")" n> r> ")") 28 | (andlet "(and-let* (" p ")" n> r> ")") 29 | (cond "(cond" n "(" q "))" >) 30 | (pcase "(pcase " (p "scrutinee") n "(" q "))" >) 31 | (let "(let (" p ")" n> r> ")") 32 | (lett "(let* (" p ")" n> r> ")") 33 | (pcaselet "(pcase-let (" p ")" n> r> ")") 34 | (pcaselett "(pcase-let* (" p ")" n> r> ")") 35 | (rec "(letrec (" p ")" n> r> ")") 36 | (dotimes "(dotimes (" p ")" n> r> ")") 37 | (dolist "(dolist (" p ")" n> r> ")") 38 | (loop "(cl-loop for " p " in " p " do" n> r> ")") 39 | (command "(defun " p " (" p ")\n \"" p "\"" n> "(interactive" p ")" n> r> ")") 40 | (advice "(defun " (p "adv" name) " (&rest app)" n> p n> "(apply app))" n> 41 | "(advice-add #'" (p "fun") " " (p ":around") " #'" (s name) ")") 42 | (header ";;; " (file-name-nondirectory (or (buffer-file-name) (buffer-name))) 43 | " -- " p " -*- lexical-binding: t -*-" n 44 | ";;; Commentary:" n ";;; Code:" n n) 45 | (provide "(provide '" (file-name-base (or (buffer-file-name) (buffer-name))) ")" n 46 | ";;; " (file-name-nondirectory (or (buffer-file-name) (buffer-name))) 47 | " ends here" n) 48 | 49 | eshell-mode 50 | 51 | (for "for " (p "i") " in " p " { " q " }") 52 | (while "while { " p " } { " q " }") 53 | (until "until { " p " } { " q " }") 54 | (if "if { " p " } { " q " }") 55 | (ife "if { " p " } { " p " } { " q " }") 56 | (unl "unless { " p " } { " q " }") 57 | (unle "unless { " p " } { " p " } { " q " }") 58 | 59 | nix-mode 60 | 61 | (empty-sha256-hash "0000000000000000000000000000000000000000000000000000") 62 | (empty-sri-hash "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=") 63 | (mkOption > "mkOption {" n> "type = " (p "type" type) ";" n> "default = " (p "default" default) ";" n> "description = \"" (p "description" description) "\";" n> "};") 64 | (fetchFromGitHub > "fetchFromGitHub {" n> "owner = \"" (p "owner" owner) "\";" n> "repo = \"" (p "repo" repo) "\";" n> "rev = \"" (p "rev" rev) "\";" n> "hash = \"" (p "hash" hash) "\";" n> "};") 65 | 66 | org-mode 67 | 68 | (title "#+title: " p n "#+author: " p n "#+language: " p n n) 69 | (quote "#+begin_quote" n> r> n> "#+end_quote") 70 | (example "#+begin_example" n> r> n> "#+end_example") 71 | (center "#+begin_center" n> r> n> "#+end_center") 72 | (comment "#+begin_comment" n> r> n> "#+end_comment") 73 | (verse "#+begin_verse" n> r> n> "#+end_verse") 74 | (src "#+begin_src " p n> r> n> "#+end_src" :post (org-edit-src-code)) 75 | (elisp "#+begin_src emacs-lisp :tangle yes" n> r> n "#+end_src" :post (org-edit-src-code)) 76 | 77 | go-mode go-ts-mode 78 | 79 | (if > "if " p " {" n> r> n> "}" >) 80 | (if-else > "if " p " {" n> r> n> "} else {" n> p> n> "}" >) 81 | (if-else-if > "if " p " {" n> r> n> "} else if " p> " {" n> p> n> "}" >) 82 | (if-err > "if err != nil {" n> r> n> "}" >) 83 | --------------------------------------------------------------------------------