My Emacs System
A attempt to document my emacs setup 🙃
Emacs is the best editor possible, at least for me, especially with the killer org-mode module.
I do all in a lot in Emacs:
- task and calendar management using org-mode.
- mail using gnus.
- programming in different languages (elisp, go, bash, …)
- interactive shell using either eshell or vterm.
This is my attempt to document my Emacs setup, inspired by The Emacs Operating System (EOS) or Complete Computing Environment and other litterate configurations, see Inspirations. In a gist, this is the litterate version of the configurations available in my monorepo.
What is this
The present document, referred to in the source code version as emacs.org
, contains the
bulk of my configurations for GNU Emacs. It is designed using principles of “literate
programming”: a combination of ordinary language and inline code blocks. Emacs knows how
to parse this file properly so as to evaluate only the elisp (“Emacs Lisp”) included
herein. The rest is for humans to make sense of my additions and their underlying
rationale.
Literate programming allows us to be more expressive and deliberate. Not only we can use typography to its maximum potential, but can also employ techniques such as internal links between sections. This makes the end product much better for end users, than a terse script.
I switched back and forth on using org-mode
and literate programming, so why re-using
it. First, I think I went for it the wrong way the first time. I copied part of the
configuration from elsewhere, sometimes without really needing what I was copying. for
some reason I think this is a common pattern when configuring Emacs. You start by using a
distribution (Doom Emacs, Spacemacs, …) or by copying configuration from all over the
place. Slowly but surely you realize this was a mistake as you didn’t learn anything, so
you reboot your configuration.
Why using GNU/Emacs ?
This is a question I thought I needed to answer, or at least, document why I am choosing GNU/Emacs as my primary editor. Protesilaos Stavrou has a video about it, really interesting.
There is a lot of reasons but for me, the following are the main ones:
- Open Source: this is a “of course”, but my editor has to be open-sourced. This seems
to be the norm these days anyway (and for a long time, with
vim
). - Lightweight: the editor should be relatively lightweight. I don’t want a full browser
loaded to edit files, and I want to be able to run it in a terminal, on a server.
vim
can do that (and sometimes,vim
orvi
is enough 👼). - Extensible: to be honest, this is the most important reason. I want to be able to extend my editor as much as possible.
GNU/Emacs checks all the boxes for me. Even though GNU/Emacs is probably not as
lightweight as vim
, it is definitely lightweight compared to all the Electron-based
editors (vscode, …). It is of course open-source, and since ages (almost as old as I am
😅). And best of all, GNU/Emacs is extensible as you couldn’t dream of. Emacs is a lisp
interpreter, and it is designed to be extended in order to meet the user’s
needs. Extensibility is the quintessential Emacs quality. You can modify any piece of
elisp in real time.
I’m also a huge fan of text-based software, a.k.a. do whatever you can using text :
reading mails, news, organizing notes and todos, all can be done in text. And GNU/Emacs
shines at this. For emails and news, you’ve got Gnus built-in, for notes and todos, the
wonderful org-mode
is the best thing on earth (seriously, this is the one mode that
made me switch from vim
).
Assumptions
I’ll make a few assumption in the following document (that may or may not be true):
nix
is available, either from NixOS or via an install of nix. I’ll try my best to support non-nix environment, but it’s definitely not my current focus.- As I am making the assumption that
nix
is available, I am also making the assumption that all the library required are already present (in myhome
, there is a file calledemacs.nix
that encapsulate those dependencies). This is why, by default use-package doesn’t use theensure
option in 99% of the configuration.
- As I am making the assumption that
- Any function I wrote is going to be prefixed by
vde/
so that it doesn’t conflicts with function that would have been defined elsewhere. - Any function imported from another configuration, without any change, should be kept as is and/or prefixed by an unique id. I’ll try to make sure to link to the configuration too.
Keybinding
As it is detailed in each part of this configuration, I am trying to setup keybinding in a mnemonics way so it’s easy to remember (and use). This is what spacemacs does with evil keybindings (aka vim-like keybindings). I am staying with the standard emacs keybinding as much as possible (as there is already some mnemonics in there).
There are countless jokes and comics on Emacs’s seemingly ridiculous keybindings. Good laughs indeed, but at the end of day, it’s not incomprehensible. It has well-defined conventions listed at Emacs Key Bindings Convention. In summary, the general rules are:
C-x
reserved for Emacs native essential keybindings: buffer, window, frame, file, directory, etc…C-c
reserved for user and major mode:C-c letter
reserved for user.<F5>
-<F9>
reserved for user.C-c C-letter
reserved for major mode.
- Don’t rebind
C-g
,C-h
andESC
.
To give a small example, most of my personal org-mode
keybinding will start with C-c
o
, as it is reserved for user, and o
is for org-mode
. For version control, it’s gonna
be C-c v
, for projects it’s gonna be C-c p
, etc…
prefix | “mode” |
---|---|
<F1> | |
<F2> | |
<F3> | built-in Register macro(s) |
<F4> | built-in Plays macro(s) |
<F5> | revert-buffer |
<F6> | |
<F7> | |
<F8> | |
<F9> | |
<F10> | |
<F11> | |
<F12> | |
C-c b |
Bookmarks (bookmark-plus ) |
C-c h |
Help (helpful , …) |
C-c n |
Navigation (avy , …) |
C-c o |
Org mode |
C-c p |
Projects (projectile , …) |
C-c v |
Version control (vc , magit , …) |
C-c w |
Window management (ace-window , …) |
C-x p |
Bookmarks (bookmark-plus , …) |
This table is not complete and I don’t intend to keep it complete here. Instead, there should be a table like this on each configuration file to describe what this config brings as keybinding.
See also:
COPYING
Copyright (c) 2013-2020 Vincent Demeester <vincent@sbr.pm>
This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this file. If not, see http://www.gnu.org/licenses/.
Base settings
This section contains configurations that are needed prior to the setup of everything
else. Anything that needs to be configured first should be in there, this includes the
init.el
and early-init.el
files content.
Early initialization
Starting with Emacs 27, an early-init.el
file can be used to do early configuration
and optimization.
Emacs can now be configured using an early init file. The file is called
early-init.el
, inuser-emacs-directory
. It is loaded very early in the startup process: before graphical elements such as the tool bar are initialized, and before the package manager is initialized. The primary purpose is to allow customizing how the package system is initialized given that initialization now happens before loading the regular init file (see below).We recommend against putting any customizations in this file that don’t need to be set up before initializing installed add-on packages, because the early init file is read too early into the startup process, and some important parts of the Emacs session, such as ’window-system’ and other GUI features, are not yet set up, which could make some customization fail to work.
We can use this to our advantage and optimize the initial loading of emacs.
Before Emacs 27, the init file was responsible for initializing the package manager by calling `package-initialize’. Emacs 27 changed the default behavior: It now calls `package-initialize’ before loading the init file.
(setq package-enable-at-startup nil)
Let’s inhibit resizing the frame at early stage.
(setq frame-inhibit-implied-resize t)
I never use the menu-bar, or the tool-bar or even the scroll-bar, so we can safely disable those very very early.
(menu-bar-mode -1) (tool-bar-mode -1) (scroll-bar-mode -1) (horizontal-scroll-bar-mode -1)
Finally we can try to avoid garbage collection at startup. The garbage collector can easily double startup time, so we suppress it at startup by turning up
gc-cons-threshold
(and perhapsgc-cons-percentage
) temporarily.(setq gc-cons-threshold 402653184 gc-cons-percentage 0.6)
Another small optimization concerns on
file-name-handler-alist
: on every .el and .elc file loaded during start up, it has to runs those regexps against the filename ; setting it tonil
and after initialization finished put the value back make the initialization process quicker.(defvar file-name-handler-alist-original file-name-handler-alist) (setq file-name-handler-alist nil)
However, it is important to reset it eventually. Not doing so will cause garbage collection freezes during long-term interactive use. Conversely, a
gc-cons-threshold
that is too small will cause stuttering. This will be done at the end.It’s also possible to put the theme and the font in
early-init.el
to speed the start.(defvar contrib/after-load-theme-hook nil "Hook run after a color theme is loaded using `load-theme'.") (defun contrib/run-after-load-theme-hook (&rest _) "Run `contrib/after-load-theme-hook'." (run-hooks 'contrib/after-load-theme-hook)) (advice-add #'load-theme :after #'contrib/run-after-load-theme-hook) (require 'modus-operandi-theme) (defun vde/modus-operandi () "Enable some Modus Operandi variables and load the theme. This is used internally by `vde/modus-themes-toggle'." (setq modus-operandi-theme-slanted-constructs t modus-operandi-theme-bold-constructs t modus-operandi-theme-subtle-diffs t modus-operandi-theme-rainbow-headings t modus-operandi-theme-section-headings nil modus-operandi-theme-scale-headings nil modus-operandi-theme-fringes 'subtle ; {nil,'subtle,'intense} modus-operandi-theme-mode-line '3d ; {nil,'3d,'moody} modus-operandi-theme-3d-modeline t modus-operandi-theme-faint-syntax nil modus-operandi-theme-intense-hl-line t modus-operandi-theme-intense-paren-match t modus-operandi-theme-prompts 'subtle ; {nil,'subtle,'intense} modus-operandi-theme-completions 'opinionated ; {nil,'moderate,'opinionated} modus-operandi-theme-diffs 'desaturated ; {nil,'desaturated,'fg-only} modus-operandi-theme-org-blocks 'greyscale ; {nil,'greyscale,'rainbow} modus-operandi-theme-variable-pitch-headings nil modus-operandi-theme-rainbow-headings t modus-operandi-theme-section-headings nil modus-operandi-theme-scale-headings t modus-operandi-theme-scale-1 1.05 modus-operandi-theme-scale-2 1.1 modus-operandi-theme-scale-3 1.15 modus-operandi-theme-scale-4 1.2) (load-theme 'modus-operandi t)) (defun vde/modus-operandi-custom () "Customize modus-operandi theme" (if (member 'modus-operandi custom-enabled-themes) (modus-operandi-theme-with-color-variables ; this macro allows us to access the colour palette (custom-theme-set-faces 'modus-operandi `(whitespace-tab ((,class (:background "#ffffff" :foreground "#cccccc")))) `(whitespace-space ((,class (:background "#ffffff" :foreground "#cccccc")))) `(whitespace-hspace ((,class (:background "#ffffff" :foreground "#cccccc")))) `(whitespace-newline ((,class (:background "#ffffff" :foreground "#cccccc")))) `(whitespace-indentation ((,class (:background "#ffffff" :foreground "#cccccc")))) )))) (add-hook 'contrib/after-load-theme-hook 'vde/modus-operandi-custom) (vde/modus-operandi) (defconst font-height 130 "Default font-height to use.") (defconst font-family-mono "Ubuntu Mono" "Default monospace font-family to use.") (defconst font-family-sans "Ubuntu Sans" "Default sans font-family to use.") ;; Middle/Near East: שלום, السّلام عليكم (when (member "Noto Sans Arabic" (font-family-list)) (set-fontset-font t 'arabic "Noto Sans Arabic")) (when (member "Noto Sans Hebrew" (font-family-list)) (set-fontset-font t 'arabic "Noto Sans Hebrew")) ;; Africa: ሠላም (when (member "Noto Sans Ethiopic" (font-family-list)) (set-fontset-font t 'ethiopic "Noto Sans Ethiopic")) ;; If font-family-mono or font-family-sans are not available, use the default Emacs face (when (member font-family-mono (font-family-list)) (set-face-attribute 'default nil :family font-family-mono :height font-height) (set-face-attribute 'fixed-pitch nil :family font-family-mono)) (when (member font-family-sans (font-family-list)) (set-face-attribute 'variable-pitch nil :family font-family-sans :weight 'regular)) ;; Ignore X resources; its settings would be redundant with the other settings ;; in this file and can conflict with later config (particularly where the ;; cursor color is concerned). (advice-add #'x-apply-session-resources :override #'ignore)
Reseting garbage collection and file-name-handler values.
(add-hook 'after-init-hook `(lambda () (setq gc-cons-threshold 67108864 ; 64mb gc-cons-percentage 0.1 file-name-handler-alist file-name-handler-alist-original) (garbage-collect)) t)
Initialization
I am using the portable dump feature (to speed things up) but I want to also start
without pdump
, so I need to take both cases into account.
(defvar sbr-dumped nil "non-nil when a dump file is loaded (because dump.el sets this variable).") (defmacro sbr-if-dump (then &rest else) "Evaluate IF if running with a dump file, else evaluate ELSE." (declare (indent 1)) `(if sbr-dumped ,then ,@else)) (sbr-if-dump (progn (global-font-lock-mode) (transient-mark-mode) (setq load-path sbr-dumped-load-path)) ;; add load-path’s and load autoload files (package-initialize))
First thing first, let’s define a emacs-start-time
constant to be able to compute the
time Emacs took to start.
(defconst emacs-start-time (current-time))
My configuration do not support Emacs version lower than 26.
(let ((minver 26)) (unless (>= emacs-major-version minver) (error "Your Emacs is too old -- this configuration requires v%s or higher" minver)))
One thing though, I am currently not necessarily running Emacs 27, so I am going to need
to have the same configuration in init.el
for a little bit of time.
Note: the lowest emacs version I wanna support is 26 (as of today, might evolve)
;; load early-init.el before Emacs 27.0 (unless (>= emacs-major-version 27) (message "Early init: Emacs Version < 27.0") (load (expand-file-name "early-init.el" user-emacs-directory)))
We also want our configuration to be working the same on any computer, this means we want
to define every option by ourselves, not relying on default files (default.el
) that
would be set by our distribution. This is where inhibit-default-init
comes into play,
setting it to non-nil inhibit loading the default
library.
We also want to inhibit some initial default start messages and screen. The default screen will be as bare as possible.
(setq inhibit-default-init t) ; Disable the site default settings (setq inhibit-startup-message t inhibit-startup-screen t)
Let’s also use y
or n
instead of yes
and no
when exiting Emacs.
(setq confirm-kill-emacs #'y-or-n-p)
One last piece to the puzzle is the default mode. Setting it to fundamental-mode means we
won’t load any heavy mode at startup (like org-mode
). We also want this scratch buffer
to be empty, so let’s set it as well
(setq initial-major-mode 'fundamental-mode
initial-scratch-message nil)
Unicode all the way
By default, all my systems are configured and support utf-8
, so let’s just make it a
default in Emacs ; and handle special case on demand.
(prefer-coding-system 'utf-8) (set-default-coding-systems 'utf-8) (set-language-environment 'utf-8) (set-selection-coding-system 'utf-8) (set-terminal-coding-system 'utf-8)
Package management with use-package
use-package
is a tool that streamlines the configuration of packages. It handles
everything from assigning key bindings, setting the value of customisation options,
writing hooks, declaring a package as a dependency for another, and so on.
The
use-package
macro allows you to isolate package configuration in your.emacs
file in a way that is both performance-oriented and, well, tidy. I created it because I have over 80 packages that I use in Emacs, and things were getting difficult to manage. Yet with this utility my total load time is around 2 seconds, with no loss of functionality!
With use-package
we can improve the start-up performance of Emacs in a few fairly simple
ways. Whenever a command is bound to a key it is configured to be loaded only once
invoked. Otherwise we can specify which functions should be autoloaded by means of the
:commands
keyword.
We need to setup the emacs package system and install use-package
if not present
already.
(require 'package) (setq package-archives '(("melpa" . "http://melpa.org/packages/") ("org" . "https://orgmode.org/elpa/") ("gnu" . "https://elpa.gnu.org/packages/"))) (setq package-archive-priorities '(("melpa" . 3) ("org" . 2) ("gnu" . 1))) (require 'tls) ;; From https://github.com/hlissner/doom-emacs/blob/5dacbb7cb1c6ac246a9ccd15e6c4290def67757c/core/core-packages.el#L102 (setq gnutls-verify-error (not (getenv "INSECURE")) ; you shouldn't use this tls-checktrust gnutls-verify-error tls-program (list "gnutls-cli --x509cafile %t -p %p %h" ;; compatibility fallbacks "gnutls-cli -p %p %h" "openssl s_client -connect %h:%p -no_ssl2 -no_ssl3 -ign_eof")) ;; Initialise the packages, avoiding a re-initialisation. (unless (bound-and-true-p package--initialized) (setq package-enable-at-startup nil) (package-initialize)) (setq load-prefer-newer t) ; Always load newer compiled files (setq ad-redefinition-action 'accept) ; Silence advice redefinition warnings ;; Init `delight' (unless (package-installed-p 'delight) (package-refresh-contents) (package-install 'delight)) ;; Configure `use-package' prior to loading it. (eval-and-compile (setq use-package-always-ensure nil) (setq use-package-always-defer nil) (setq use-package-always-demand nil) (setq use-package-expand-minimally nil) (setq use-package-enable-imenu-support t)) (unless (package-installed-p 'use-package) (package-refresh-contents) (package-install 'use-package)) (eval-when-compile (require 'use-package))
Early environment setup
I want to force =SSH_AUTH_SOCK
in Emacs to use my gpg-agent.
(setenv "SSH_AUTH_SOCK" "/run/user/1000/gnupg/S.gpg-agent.ssh")
custom.el
When you install a package or use the various customisation interfaces to tweak things to your liking, Emacs will append a piece of elisp to your init file. I prefer to have that stored in a separate file.
(defconst vde/custom-file (locate-user-emacs-file "custom.el") "File used to store settings from Customization UI.") (use-package cus-edit :config (setq custom-file vde/custom-file custom-buffer-done-kill nil ; Kill when existing custom-buffer-verbose-help nil ; Remove redundant help text custom-unlispify-tag-names nil ; Show me the real variable name custom-unlispify-menu-entries nil) (unless (file-exists-p custom-file) (write-region "" nil custom-file)) (load vde/custom-file 'no-error 'no-message))
Remove built-in org-mode
I want to make sure I am using the installed version of orgmode
(from my org
configuration) instead of the built-in one. To do that safely, let’s remove the built-in
version out of the load path.
(require 'cl-seq) (setq load-path (cl-remove-if (lambda (x) (string-match-p "org$" x)) load-path))
Loading configuration files
This org-mode
document tangles into several files in different folders :
config
for my configurationlisp
for imported code or library I’ve written and not yet published
I used to load them by hand in the init.el
file, which is very cumbersome, so let’s try
to automatically load them. I want to first load the file in the lisp
folder as they are
potentially used by my configuration (in config
).
Let’s define some functions that would do the job.
(defun vde/el-load-dir (dir) "Load el files from the given folder" (let ((files (directory-files dir nil "\.el$"))) (while files (load-file (concat dir (pop files)))))) (defun vde/short-hostname () "Return hostname in short (aka wakasu.local -> wakasu)" (string-match "[0-9A-Za-z-]+" system-name) (substring system-name (match-beginning 0) (match-end 0)))
Let’s define some constants early, based on the system, and the environment, to be able to use those later on to skip some package or change some configuration accordingly.
(defconst *sys/gui* (display-graphic-p) "Are we running on a GUI Emacs ?") (defconst *sys/linux* (eq system-type 'gnu/linux) "Are we running on a GNU/Linux system?") (defconst *sys/mac* (eq system-type 'darwin) "Are we running on a Mac system?") (defconst *sys/root* (string-equal "root" (getenv "USER")) "Are you a ROOT user?") (defconst *nix* (executable-find "nix") "Do we have nix? (aka are we running in NixOS or a system using nixpkgs)") (defconst *rg* (executable-find "rg") "Do we have ripgrep?") (defconst *gcc* (executable-find "gcc") "Do we have gcc?") (defconst *git* (executable-find "git") "Do we have git?") (defvar *sys/full* (member (vde/short-hostname) '("wakasu" "naruhodo")) ; "naruhodo" <- put naruhodo back in "Is it a full system ?") (defvar *sys/light* (not *sys/full*) "Is it a light system ?")
Now, in order to load lisp
and config
files, it’s just a matter of calling this
function with the right argument.
(add-to-list 'load-path (concat user-emacs-directory "lisp/")) (add-to-list 'load-path (concat user-emacs-directory "lisp/vorg")) (require 'init-func) (vde/el-load-dir (concat user-emacs-directory "/config/"))
Finally, I want to be able to load files for a specific machine, in case I need it (not entirely sure why yet but…)
(if (file-exists-p (downcase (concat user-emacs-directory "/hosts/" (vde/short-hostname) ".el"))) (load-file (downcase (concat user-emacs-directory "/hosts/" (vde/short-hostname) ".el"))))
Counting the time of loading
(let ((elapsed (float-time (time-subtract (current-time) emacs-start-time)))) (message "Loading %s...done (%.3fs)" load-file-name elapsed)) (add-hook 'after-init-hook `(lambda () (let ((elapsed (float-time (time-subtract (current-time) emacs-start-time)))) (message "Loading %s...done (%.3fs) [after-init]" ,load-file-name elapsed))) t)
Configurations
As seen above, I split my configurations in a config
folder. Each of those configuration
has its own documentation, on its own page. Ideally, each module is optional and can be
skipped if not desired. In practice though, I load all of them, because this is my
config. I haven’t really tried loading them all individually to make sure I don’t have
links between them.
- Core System
- keep emacs clean
- appearance
- editing
- navigation
- buffer and windows
- files (with dired)
- Version control
- Projects
- Programming
- emacs-lisp
- go
- nix
- Writing
- Task management
- Org-mode and agenda aka “My Organization Workflow”
- Communications
- Email configuration, notably using Gnus and notmuch.
Nix(eries)
Scripts
I have a few scripts and desktop files that I want to get installed in my environment.
capture
The first one is a capture command that starts a new frame using the org
daemon so that
I can quickly capture something from anywhere.
capture = pkgs.writeScriptBin "capture" '' #!${pkgs.stdenv.shell} emacsclient -s /run/user/1000/emacs/org -n -F '((name . "capture") (width . 150) (height . 90))' -e '(org-capture)' '';
emacsclient helpers
ec
will start an emacs “window” frame from the emacs org server.
ec = pkgs.writeScriptBin "ec" '' #!${pkgs.stdenv.shell} emacsclient -s /run/user/1000/emacs/org --create-frame $@ '';
ec
will start an emacs termimal frame from the emacs org server.
et = pkgs.writeScriptBin "et" '' #!${pkgs.stdenv.shell} emacsclient -s /run/user/1000/emacs/org --tty $@ '';
portable dump command
e
starts emacs using the portable dump.
e = pkgs.writeScriptBin "e" '' #!${pkgs.stdenv.shell} emacs --dump-file=~/.config/emacs/emacs.pdmp $@ '';
Desktop files
org-protocol.desktop
: this register the org protocol in xdg.[Desktop Entry] Name=org-protocol Exec=emacsclient -s /run/user/1000/emacs/org -n %u Type=Application Terminal=false Categories=System; MimeType=x-scheme-handler/org-protocol;
ec.desktop
: this starts a new frame on theorg
daemon.[Desktop Entry] Name=Emacs (client) Exec=ec Type=Application Terminal=false Categories=System; Icon=emacs;
capture.desktop
: this runs thecapture
script above[Desktop Entry] Name=Emacs capture Exec=capture Type=Application Terminal=false Categories=System; Icon=emacs;
And then, we need to link those up :
home.file.".local/share/applications/org-protocol.desktop".source = ./emacs/org-protocol.desktop; home.file.".local/share/applications/ec.desktop".source = ./emacs/ec.desktop; home.file.".local/share/applications/capture.desktop".source = ./emacs/capture.desktop;
Home packages
We need to install a few packages:
ditaa
andgraphiz
are there for org-mode and org-babelpandoc
is for when I when to migrate a document from markdown to org-mode or the oppositesqlite
is for packages likeforge
zip
is… always usefulcapture
is the script defined abovoe.
home.packages = with pkgs; [ ditaa graphviz pandoc sqlite zip # See if I can hide this under an option capture e ec et ];
programs.emacs
home-manager
comes with a modules named programs.emacs
, so we are going to use it
programs.emacs = { enable = true; package = pkgs.my.emacs; extraPackages = myExtraPackages; };
myExtraPackages = epkgs: with epkgs; [ ace-window aggressive-indent async avy bbdb beginend color-identifiers-mode company company-emoji company-go dash delight diredfl dired-collapse dired-git-info dired-narrow dired-quick-sort dired-rsync dired-subtree dockerfile-mode dumb-jump easy-kill edit-indirect envrc esh-autosuggest eshell-prompt-extras esup expand-region flimenu flycheck flycheck-golangci-lint git-annex git-commit gitattributes-mode gitconfig-mode github-review gitignore-mode go-mode go-stacktracer gotest goto-last-change hardhat helpful highlight highlight-indentation highlight-numbers ibuffer-vc icomplete-vertical iedit json-mode magit magit-annex magit-popup magit-todos markdown-mode minions modus-operandi-theme moody mwim nix-buffer nix-mode nixpkgs-fmt no-littering ob-async ob-go ob-http olivetti orderless org-capture-pop-frame org-gcal org-journal org-plus-contrib org-ql org-ref org-roam org-super-agenda org-superstar org-tree-slide org-web-tools orgit ox-pandoc pandoc-mode pdf-tools pkgs.bookmark-plus pkgs.dired-plus projectile python-mode rainbow-delimiters rainbow-mode rg ripgrep scratch shr-tag-pre-highlight smartparens symbol-overlay trashed try undo-tree use-package visual-fill-column visual-regexp vterm web-mode wgrep whole-line-or-region with-editor xterm-color yaml-mode ];
Emacs server
services.emacs-server = { enable = true; package = pkgs.my.emacs; name = "org"; shell = pkgs.zsh + "/bin/zsh -i -c"; # FIXME do this in the derivation :) # extraOptions = "--dump-file=${config.home.homeDirectory}/.config/emacs/emacs.pdmp"; };
Commands and sessions variables
Let’s define some useful commands that can be used
Let’s define some
Legacy
home.sessionVariables = { EDITOR = "et"; ALTERNATE_EDITOR = "et"; };
Configuration layout
Here we define the emacs.nix
file that gets generated by the source blocks in our Org
document. This is the file that actually gets loaded on startup. The placeholders in
angled brackets correspond to the NAME
directives above the SRC
blocks throughout this
document.
# Note: this file is autogenerated from an org-mode file. { config, lib, pkgs, ... }: with lib; let <<script-capture>> <<script-e>> <<script-et>> <<script-ec>> <<myExtraPackages>> in { <<desktop-files>> <<packages>> <<programs.emacs>> <<emacs-server>> <<legacy>> }
Inspirations
This is inspired by a crazy amount of configurations (litterate or note):
- Protesilaos Stravou’s dotemacs
- Doom Emacs Configuration from tecosaur
- https://gitlab.com/ndw/dotfiles
- https://github.com/MatthewZMD/.emacs.d
- https://github.com/alhassy/emacs.d
- https://github.com/chmouel/emacs-config
- https://github.com/seagle0128/.emacs.d
- https://github.com/hlissner/doom-emacs
- http://doc.norang.ca/org-mode.html
And also:
Links
Here is a compilation of random articles around GNU/Emacs that I found interesting to share. I may add comment on those too.
Emacs Tramp tricks emacs