home

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

commit 2523eedd0a78c76c5ed688d6cc2ce4dd676e8824
parent cecbf1f326ba6c75ec9ed5221c701ee93a0475a0
Author: Vincent Demeester <vincent@sbr.pm>
Date:   Thu, 26 Nov 2020 18:25:40 +0100

Remove docs/ folder…

… not used nor up-to-date anymore…

Signed-off-by: Vincent Demeester <vincent@sbr.pm>

Diffstat:
Ddocs/.setupfile.org | 3---
Ddocs/emacs.org | 1402-------------------------------------------------------------------------------
Ddocs/images/2020-02-29-13-46-08.png | 2--
Ddocs/images/2020-02-29-14-41-59.png | 2--
Ddocs/images/2020-03-03-21-57-41.png | 2--
Ddocs/images/2020-03-03-21-59-22.png | 2--
Ddocs/index.org | 45---------------------------------------------
Ddocs/install/bootstrap.org | 2--
Ddocs/install/fedora.org | 2--
Ddocs/install/nixos.org | 2--
Ddocs/mails.org | 429-------------------------------------------------------------------------------
11 files changed, 0 insertions(+), 1893 deletions(-)

diff --git a/docs/.setupfile.org b/docs/.setupfile.org @@ -1,3 +0,0 @@ -#+AUTHOR: Vincent Demeester -#+KEYWORDS: configuration -#+EXCLUDE_TAGS: noexport diff --git a/docs/emacs.org b/docs/emacs.org @@ -1,1402 +0,0 @@ -#+TITLE: Vincent Demeester's .emacs.d -#+SETUPFILE: ./.setupfile.org -#+FILETAGS: emacs - -#+TOC: headlines 3 - -* Overview -:PROPERTIES: -:CUSTOM_ID: h:64b142be-1326-479b-ab6e-e88ca298f56d -:END: -** Canonical links to this document -:PROPERTIES: -:CUSTOM_ID: h:9e025e71-b8c5-4cd3-88cc-c81f1e026d13 -:END: - -- HTML version :: [[https://vincent.demeester.fr/configurations/emacs.html][vincent.demeester.fr/configurations/emacs.html]] -- Git repo :: [[https://gitlab.com/vdemeester/home/-/tree/master/tools/emacs][https://gitlab.com/vdemeester/home/-/tree/master/tools/emacs]] - -** What is this -:PROPERTIES: -:CUSTOM_ID: h:6cf02bfd-0266-456f-be5f-728c75e3013e -:END: - -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. - -#+BEGIN_QUOTE -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. -#+END_QUOTE - -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. - -I'm taking [[https://protesilaos.com/][Protesilaos Stavrou]] approach on writing and configuring this file (see [[https://protesilaos.com/dotemacs/][his -dotemacs]]), although I am not loading it directly. I prefer using the [[https://orgmode.org/manual/tangle.html][tangle]] feature of -=org-mode= instead of loading it using ~org-babel~ function. This allows me to document my -configuration and generating final(s) ~.el~ files. Those files can then load and/or -pre-compile, without the need to load =org= first. It also means that I can add code -pieces in there that won't be /tangle/, like usage example ; and I also can use this to -generate any additional file I need, whatever the programming language they are written -in. [[https://protesilaos.com/][Protesilaos Stavrou]] is not my only source, here are some others: - -+ 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: - -- [[https://sriramkswamy.github.io/dotemacs/][Emacs configuration file]] -- [[https://blog.d46.us/advanced-emacs-startup/][Advanced Techniques for Reducing Emacs Startup Time]] -- [[https://www.bartuka.com/posts/emacs-config/index.html][@bartuka: emacs.d]] -- [[http://www.howardism.org/Technical/Emacs/getting-boxes-done.html][Getting Boxes Done]] -- [[https://idiocy.org/emacs-fonts-and-fontsets.html][Emacs, fonts and fontsets]] -- [[https://spin.atomicobject.com/2016/05/27/write-emacs-package/][A Simple Guide to Writing & Publishing Emacs Packages]] -- [[https://alphapapa.github.io/emacs-package-dev-handbook/][The Emacs Package Developer's Handbook]] - -** Why using GNU/Emacs ? -:PROPERTIES: -:CUSTOM_ID: h:165fca5a-b87d-4140-963b-658a2438e769 -:END: - -This is a question I thought I needed to answer, or at least, document why I am choosing -GNU/Emacs as my primary editor. [[https://protesilaos.com/][Protesilaos Stavrou]] has a [[https://protesilaos.com/codelog/2019-12-20-vlog-switch-emacs/][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= or =vi= 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 -:PROPERTIES: -:CUSTOM_ID: h:657c38cd-d910-42c2-bd8c-8c20171a8bd5 -:END: - -I'll make a few assumption in the following document (that may or may not be true): - -- [[https://nixos.org/nix/][~nix~]] is available, either from [[https://nixos.org][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 my [[https://github.com/vdemeester/home][~home~]], there is a file - called [[https://github.com/vdemeester/home/blob/master/modules/profiles/emacs.nix][~emacs.nix~]] that encapsulate those dependencies). This is why, by default - *use-package* doesn't use the =ensure= option in 99% of the configuration. -- 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. - -*** TODO 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 [[https://www.spacemacs.org/][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 [[https://www.gnu.org/software/emacs/manual/html%5Fnode/elisp/Key-Binding-Conventions.html][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= and =ESC=. - -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=, …) | - -See also: -- https://karl-voit.at/2018/07/08/emacs-key-bindings/ -- https://www.masteringemacs.org/article/mastering-key-bindings-emacs -- http://www.wilfred.me.uk/blog/2018/01/06/the-emacs-guru-guide-to-key-bindings/ - -** COPYING -:PROPERTIES: -:CUSTOM_ID: h:d4cfb344-dcff-4144-951a-8197c5ae2c84 -:END: - -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 -:PROPERTIES: -:CUSTOM_ID: h:e483cc48-eb2d-42a7-93ca-3e1a37fa6a7c -:END: - -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. - -** Initiazing emacs -:PROPERTIES: -:CUSTOM_ID: h:4886d661-e2e0-4a75-bf3f-e85aef27b50c -:END: - -Starting with Emacs 27, an =early-init.el= file can be used to do early configuration -and optimization. - -#+begin_quote -Emacs can now be configured using an early init file. The file is called ~early-init.el~, -in ~user-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. -#+end_quote - -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. - - #+INCLUDE: "../tools/emacs/early-init.el" src emacs-lisp :range-begin "PkgStartup" :range-end "-PkgStartup" :lines "3-4" - -- Let's inhibit resizing the frame at early stage. - - #+INCLUDE: "../tools/emacs/early-init.el" src emacs-lisp :range-begin "FrameResize" :range-end "-FrameResize" :lines "7-8" - -- I never use the /menu-bar/, or the /tool-bar/ or even the /scroll-bar/, so we can safely - disable those very very early. - - #+INCLUDE: "../tools/emacs/early-init.el" src emacs-lisp :range-begin "DisableUI" :range-end "-DisableUI" :lines "11-17" - -- 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 perhaps ~gc-cons-percentage~) temporarily. - - #+INCLUDE: "../tools/emacs/early-init.el" src emacs-lisp :range-begin "GarbageCollection" :range-end "-GarbageCollection" :lines "20-22" - -- 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 to ~nil~ and after initialization finished put the value back make the initialization - process quicker. - - #+INCLUDE: "../tools/emacs/early-init.el" src emacs-lisp :range-begin "FileNameHandler" :range-end "-FileNameHandler" :lines "25-27" - - 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. - - #+INCLUDE: "../tools/emacs/early-init.el" src emacs-lisp :range-begin "AfterInitHook" :range-end "-AfterInitHook" :lines "110-116" - -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)/ - -#+INCLUDE: "../tools/emacs/init.el" src emacs-lisp :range-begin "CheckVer" :range-end "-CheckVer" :lines "25-35" - -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. - -#+INCLUDE: "../tools/emacs/init.el" src emacs-lisp :range-begin "Inhibit" :range-end "-Inhibit" :lines "38-42" - -Let's also use =y= or =n= instead of =yes= and =no= when exiting Emacs. - -#+INCLUDE: "../tools/emacs/init.el" src emacs-lisp :range-begin "Confirm" :range-end "-Confirm" :lines "45-46" - -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 - -#+INCLUDE: "../tools/emacs/init.el" src emacs-lisp :range-begin "DefaultMode" :range-end "-DefaultMode" :lines "49-51" - -*** Unicode all the way -:PROPERTIES: -:CUSTOM_ID: h:df45a01a-177d-4909-9ce7-a5423e0ea20f -:END: - -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. - -#+INCLUDE: "../tools/emacs/init.el" src emacs-lisp :range-begin "Unicode" :range-end "-Unicode" :lines "54-59" - -*** Package management with =use-package= -:PROPERTIES: -:CUSTOM_ID: h:112262a1-dd4d-4a50-a9e2-85b36bbbd95b -:END: - -=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. - -#+begin_quote -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! -#+end_quote - -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. - -#+INCLUDE: "../tools/emacs/init.el" src emacs-lisp :range-begin "UsePackageSetup" :range-end "-UsePackageSetup" :lines "62-111" - -*** =custom.el= -:PROPERTIES: -:CUSTOM_ID: h:1ddaf27e-ff7c-424e-8615-dd0bd22b685f -:END: - -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. - -#+INCLUDE: "../tools/emacs/init.el" src emacs-lisp :range-begin "CustomFile" :range-end "-CustomFile" :lines "116-131" - -*** Remove built-in =org-mode= -:PROPERTIES: -:CUSTOM_ID: h:9462c0d7-03be-4231-8f22-ce1a04be32b1 -:END: - -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. - -#+INCLUDE: "../tools/emacs/init.el" src emacs-lisp :range-begin "NoBuiltinOrg" :range-end "-NoBuiltinOrg" :lines "134-140" - -*** Loading configuration files -:PROPERTIES: -:CUSTOM_ID: h:d6aebc56-aadb-4b01-8404-bb922d12f8a8 -:END: - -This =org-mode= document /tangles/ into several files in different folders : -- ~config~ for my configuration -- ~lisp~ 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. - -#+INCLUDE: "../tools/emacs/init.el" src emacs-lisp :range-begin "LoadCfgFunc" :range-end "-LoadCfgFunc" :lines "143-153" - -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. - -#+INCLUDE: "../tools/emacs/init.el" src emacs-lisp :range-begin "CfgConstant" :range-end "-CfgConstant" :lines "156-187" - -Now, in order to load ~lisp~ and ~config~ files, it's just a matter of calling this -function with the right argument. - -#+INCLUDE: "../tools/emacs/init.el" src emacs-lisp :range-begin "CfgLoad" :range-end "-CfgLoad" :lines "190-194" - -Finally, I want to be able to load files for a specific machine, in case I need it (not -entirely sure why yet but…) - -#+INCLUDE: "../tools/emacs/init.el" src emacs-lisp :range-begin "CfgHostLoad" :range-end "-CfgHostLoad" :lines "197-199" - -*** Counting the time of loading -:PROPERTIES: -:CUSTOM_ID: h:2b645e95-6776-4f5b-a318-e5a915943881 -:END: - -#+INCLUDE: "../tools/emacs/init.el" src emacs-lisp :range-begin "LastInit" :range-end "-LastInit" :lines "202-213" - -** ~PATH~'s customization -:PROPERTIES: -:header-args: :tangle config/00-environments.el -:CUSTOM_ID: h:2a72b00e-ea97-4a3b-a70c-cbbe648df428 -:END: - -To make sure my emacs instance and my user environment setup is always /similar/, I use -=exec-path-from-shell=. - -#+begin_quote -Ever find that a command works in your shell, but not in Emacs? - -This happens a lot on OS X, where an Emacs instance started from the GUI inherits a -default set of environment variables. - -This library solves this problem by copying important environment variables from the -user's shell: it works by asking your shell to print out the variables of interest, then -copying them into the Emacs environment. -#+end_quote - -#+begin_src emacs-lisp -(use-package exec-path-from-shell ; Set up environment variables - :if (display-graphic-p) - :unless (eq system-type 'windows-nt) - :config - (setq exec-path-from-shell-variables - '("PATH" ; Full path - "INFOPATH" ; Info directories - "GOPATH" ; Golang path - )) - (exec-path-from-shell-initialize)) - -(setenv "PAGER" "cat") -(setenv "TERM" "xterm-256color") -#+end_src - - -** Keep emacs clean -:PROPERTIES: -:header-args: :tangle config/00-clean.el -:CUSTOM_ID: h:8a9d7d0d-0900-4261-a9e3-923a0afc1324 -:END: - -I want to keep the =~/.emacs.d= folder as clean as possible. The [[https://github.com/emacscollective/no-littering][no-littering]] project -helps wit that. - -#+begin_quote -The default paths used to store configuration files and persistent data are not consistent -across Emacs packages. This isn't just a problem with third-party packages but even with -built-in packages. - -Some packages put these files directly in user-emacs-directory or $HOME or in a -subdirectory of either of the two or elsewhere. Furthermore sometimes file names are used -that don't provide any insight into what package might have created them. - -This package sets out to fix this by changing the values of path variables to put -configuration files in no-littering-etc-directory (defaulting to ~/.emacs.d/etc/) and -persistent data files in no-littering-var-directory (defaulting to ~/.emacs.d/var/), and -by using descriptive file names and subdirectories when appropriate. This is similar to a -color-theme; a "path-theme" if you will. -#+end_quote - -Let's configure it *and* make sure we load it as soon as possible (hence the -=config/00-clean.el=). - -As I am loading =recentf= during this cleanup part, I need to setup recentf before 😅. In -a gist: - -- I keep about 200 items. -- I don't want the /auto-cleanup/ of recentf items to happen when the mode is loaded (a.k.a. - at startup). It is configured to run after 360s of idle time. -- I don't really want to show the Nth number of the items. -- I don't want recentf to save remote, =su= and =sudo= items (=ssh:=, =sudo:=, …) - -#+begin_src emacs-lisp -(use-package recentf - :config - (setq recentf-max-saved-items 200 - recentf-auto-cleanup 360 - recentf-show-file-shortcuts-flag nil) - (recentf-mode 1) - (add-to-list 'recentf-exclude "^/\\(?:ssh\\|su\\|sudo\\)?:") - ;; Magic advice to rename entries in recentf when moving files in - ;; dired. - (defun rjs/recentf-rename-notify (oldname newname &rest args) - (if (file-directory-p newname) - (rjs/recentf-rename-directory oldname newname) - (rjs/recentf-rename-file oldname newname))) - - (defun rjs/recentf-rename-file (oldname newname) - (setq recentf-list - (mapcar (lambda (name) - (if (string-equal name oldname) - newname - oldname)) - recentf-list)) - recentf-cleanup) - - (defun rjs/recentf-rename-directory (oldname newname) - ;; oldname, newname and all entries of recentf-list should already - ;; be absolute and normalised so I think this can just test whether - ;; oldname is a prefix of the element. - (setq recentf-list - (mapcar (lambda (name) - (if (string-prefix-p oldname name) - (concat newname (substring name (length oldname))) - name)) - recentf-list)) - recentf-cleanup) - - (advice-add 'dired-rename-file :after #'rjs/recentf-rename-notify)) - -(use-package no-littering ; Keep .emacs.d clean - :config - (require 'recentf) - (add-to-list 'recentf-exclude no-littering-var-directory) - (add-to-list 'recentf-exclude no-littering-etc-directory) - - ;; Move this in its own thing - (setq - create-lockfiles nil - delete-old-versions t - kept-new-versions 6 - kept-old-versions 2 - version-control t) - - (setq - backup-directory-alist - `((".*" . ,(no-littering-expand-var-file-name "backup/"))) - auto-save-file-name-transforms - `((".*" ,(no-littering-expand-var-file-name "auto-save/") t)))) -#+end_src - -** Server mode -:PROPERTIES: -:CUSTOM_ID: h:51ffd089-63c6-4ba6-8cc5-4c888521ef3a -:END: - -My current setup involves a =emacs --daemon= systemd service. We want to start the server -if it's not already running, so that =emacsclient= can connect to it. - -#+INCLUDE: "../tools/emacs/config/01-server.el" src emacs-lisp :range-begin "UseServer" :range-end "-UseServer" :lines "7-10" - -** Base typeface configurations -:PROPERTIES: -:CUSTOM_ID: h:117f0725-0708-43b9-b191-0956ad0a0a7a -:END: - -Let's configure the font that Emacs will use. In the emacs world this is call =face=. I am -a big fan of the [[https://design.ubuntu.com/font/][=Ubuntu= fonts]], so this is the set of font family I use, if available. If -the =Ubuntu= font are not available on the system, I am just letting Emacs start with its -default font. - -#+INCLUDE: "../tools/emacs/config/config-appearance.el" src emacs-lisp :range-begin "TypeFaceConfiguration" :range-end "-TypeFaceConfiguration" :lines "6-28" - -** Typeface suitability test -:PROPERTIES: -:CUSTOM_ID: h:293b5c57-a3d4-4d53-ab7d-dd05a264748d -:END: - - Here is a simple test I have come up with to make an initial assessment of the overall - quality of the font: can you discern the character at a quick glance? If yes, your choice - of typeface is good prima facie, else search for something else. - - -()[]{}<>«»‹› -6bB8&0ODdo -1tiIlL| -!ij -5$Ss -7Zz -gqp -nmMN -uvvwWuuw -x×X -.,·°;:¡!¿? -:; -`' -‘’ -''" -' -" -“” -—-~≈=_.… - -Sample character set -Check for monospacing and Greek glyphs - -ABCDEFGHIJKLMNOPQRSTUVWXYZ -abcdefghijklmnopqrstuvwxyz -1234567890#%^* -ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ -αβγδεζηθικλμνξοπρστυφχψω - -שלום, السّلام عليكم - -ሠላም - -* TODO Selection candidates and search methods -:PROPERTIES: -:CUSTOM_ID: h:4323a022-5419-48f7-acf9-7af94e43eddf -:END: - -** TODO Completion framework and extras -:PROPERTIES: -:CUSTOM_ID: h:f352f694-f22c-4e19-b1ff-fdd8405ef8c0 -:END: - -One of the optimal way of using Emacs is through searching and narrowing selection -candidates. Spend less time worrying about where things are on the screen and more on how -fast you can bring them into focus. This is, of course, a matter of realigning priorities, -as we still wish to control every aspect of the interface. - -Since the day I started using Emacs, I used multiple completion framework, from the -/built-in/ =ido-mode=, to =ivy= (and =counsel=) passing through =helm= at some point. I -never experimented with any sort of customisations to the generic minibuffer -experience. Nor did I ever bother with the oldest built-in tool of the sort (icomplete) -that is designed to complement the minibuffer's internal mechanisms for matching -items, until I've watched [[https://protesilaos.com/codelog/2020-02-26-emacs-icomplete/][Protesilaos video on it]]. - -It turns out that, despite appearances to the contrary, the defaults are very powerful, -opening up a range of possibilities to those eager to learn and experiment (a common theme -in Emacs). - -In the following package declarations I am defining several functions that enhance the -experience of icomplete. These are part of a learning process to (i) explore the internals -of Emacs and study how various problems are solved with elisp, and (ii) determine how far -one can go, in terms of efficient functionality, without deviating from the norms inherent -to the tools that are shipped with Emacs. - -*** TODO Minibuffer essentials and Icomplete (built-in completion) -:PROPERTIES: -:CUSTOM_ID: h:5fb80d63-6c5b-4d2d-9755-ffe48c851b73 -:END: - - The minibuffer is the locus of extended command interaction. Whether it is about offering - input to a prompt, performing a search, executing a function by its name, the minibuffer - remains at the epicentre. The default experience is far more powerful than it seems to - be. It can get even better by tweaking the available customisation options and defining - our own extensions. -* TODO Directory, buffer and window management -:PROPERTIES: -:CUSTOM_ID: h:88c7f450-bb9d-41f6-a8f9-3082a32d3179 -:END: - -* Applications and utilities -:PROPERTIES: -:CUSTOM_ID: h:8219f8ae-d4a8-4b9d-9a4a-3e457d69751e -:END: - -This section includes configurations for programs like email clients, messages, knowledge -database and other /applications/ that runs in Emacs. Most of those should be the "killer -apps" of the Emacs ecosystem. - -** Org-mode (personal information manager) -:PROPERTIES: -:header-args: :tangle config/config-org.el -:CUSTOM_ID: h:c8fd2624-6c91-4b89-9645-4261ca85d584 -:END: - -I am an heavy user of [[https://orgmode.org/][=org-mode=]]. This is most likely *the one* mode that made me switch -back to GNU/Emacs years back. - -#+begin_quote -Org mode is for keeping notes, maintaining TODO lists, planning projects, and authoring -documents with a fast and effective plain-text system. -#+end_quote - -I'm going to quote [[https://protesilaos.com/dotemacs/#h:4e8347de-415e-4804-b383-d61499e05ca1][Protesilaos Stavrou]] too as he describe it way better than I would do. - -#+begin_quote - Org offers you the basic tools to organise your life in super-efficient ways using - nothing but plain text. - -In its purest form, Org is a markup language that is similar to Markdown: symbols are used -to denote the meaning of a construct in its context, such as what may represent a headline -element or a phrase that calls for emphasis. - -What lends Org its super powers though is everything else built around it: a rich corpus -of elisp functions that automate, link, combine, enhance, structure, or otherwise enrich -the process of using this otherwise simple markup language. This very document is written -in org-mode while its website version is produced by a function that exports Org notation -into its HTML equivalent. -#+end_quote - -I am using =org-mode= for managing my tasks and partly my daily agenda, for /journaling/, -knowledge database (taking notes on stuff) and publishing documents (right now mainly on -[[https://sbr.pm][sbr.pm]]). I have been using =org-mode= for a while now, I feel some of my configuration may -be heavily /tailored/ to my needs. - -The /base/ user keybinding for =org-mode= (and related modes) is =C-c o= (e.g. showing -agenda is =C-c o a=, capture is =C-c o c=, …). - -*** Base settings :ATTACH: -:PROPERTIES: -:CUSTOM_ID: h:9287c076-1944-4c13-b4e4-c7cbc6587358 -:ID: 1f74bbae-c4a1-4723-977e-e48900fcd1c7 -:END: - -First, let's define some basic constants, mainly on how my main =org= folder is organized. - -#+INCLUDE: "../tools/emacs/config/config-org.el" src emacs-lisp :range-begin "OrgConstants" :range-end "-OrgConstants" :lines "7-17" - -In a nutshell, I am currently trying the following organization, with =~/desktop/org/= as -the base of almost all =org-mode= things: - -+ =projects= is the main /TODO/ folder. It holds todos and current projects along with ideas. - - =inbox.org= is my inbox, where most of my captured todo, ideas and link will be store, - waiting for reviews. - - =incubate.org= is where I store my ideas that could become projects at some point. It - is also waiting for reviews (once a week more or less). - - =next.org= is where simple todos are stored, quick one shot /things/ that do not need - a project to be created. - - ={project}.org= are files that holds a project information and todos. It can be - /long-lived/ projects (like =redhat.org= or =tekton.org=) or, prefered, /short-lived/ - projects, like =rework-infra.org= or =tekton-beta.org=. Once a project is marked as - done or completed, it either goes into the =archive=, or into =technical= ; if it can - be published. -+ =technical= is the public / to-be-published documents and /public/ knowledge base. It can holds todos, but its main - purpose is to be publish, at [[https://sbr.pm][sbr.pm]]. Thus, it's organization is the same as the - website. -+ =personal= is my private knowledge base. Those are private information or notes that I - don't want to publish *and* might be encrypted (using =gnupg=). -+ =archive= holds all archived files (projects, todos from =projects= files, …) - -Additionnaly, I may have =org-mode= files and /todos/ in other files, like in my -=~/.emacs.d= folder or my [[https://github.com/vdemeester/home][=home=]] configuration. - -I want a way to quickly jump to certain =org-mode= files, like =next.org= or the -=inbox.org=. For this, we can use the emacs [[https://www.gnu.org/software/emacs/manual/html_node/emacs/Registers.html][registers]] and more accurately the [[https://www.gnu.org/software/emacs/manual/html_node/emacs/File-Registers.html#File-Registers][file -registers]]. - -#+INCLUDE: "../tools/emacs/config/config-org.el" src emacs-lisp :range-begin "OrgRegisters" :range-end "-OrgRegisters" :lines "20-24" - -With this, I can jump to the inbox with ~C-x r j i~, to the journal using ~C-x r j j~, … - -Let's setup the base of =org-mode=, with the following things in mind: - -- Agenda :: =org-agenda-files= contains =~/desktop/org/=, =~/.emacs.d/= and - =~/.config/nixpkgs/=. The rest of the configuration will happen when configuring - =org-agenda=. -- Navigation and key bindings :: - + As said before, =C-c o= is the prefix of my user specific keybindings - - =C-c o l= is to store the link (default keybinding is =C-c C-l=) - - =C-c o r r= is to refile a task from an org-mode buffer (default keybinding is =C-c - C-w=, and there is a different keybinding when in an org-mode agenda buffer) - + Activating [[https://orgmode.org/manual/Speed-Keys.html][/speed commands/]], aka being able to use one keystroke to do some action (like - changing the TODO state, …) - + =C-a=, =C-e= and =C-k= should be =org-mode= aware. This is achieved by setting - =org-special-ctrl-a/e= and =org-special-ctrl-k= to =t=. -- To-do settings :: My current setup of /todo-keywords/ (a.k.a. =org-todo-keywords=) might - be more complicated that it should be but I've been using it a while - now. =org-todo-keywords= is a list of sequences, I have three: - + =TODO= → =NEXT= → =STARTED= → =DONE= /or/ =CANCELED= - + =WAITING= → =SOMEDAY= → move to a =TODO= or =CANCELED= - + =IDEA= → move to a =TODO= or =CANCELED= - - I am leaning towards simplifying this, especially as =NEXT= is not really useful (I have - =next.org= for this), and =IDEA= or =WAITING= are not really used either (=IDEA= goes - into =incubate.org= and I don't seem to use =WAITING=). - - /I need to update and document =org-todo-state-tags-triggers= too/ -- Tags :: I am using generic tags and some groups. Groups allow to define mutually - exclusive tags, like =#home= and =#work= (can't be both). This is achieve by using - =:startgroup= and =:endgroup= in the =org-tag-alist= variable. It is also possible to - define [[https://orgmode.org/manual/Tag-Hierarchy.html#Tag-Hierarchy][tag hierarchies]] but I didn't look into it yet. - - I also want to have tag inheritance, aka children entry inherits their parent's tag — - even though it may have a cost (search, …), it allows to reduce lots of /duplications/. -- Refile :: In the =org-mode= jargon, this means moving an entry from one heading (parent - entry) to another. This move can be done across files. =org-mode= displays a list of - choice, this list is controlled by the =org-refile-targets= variable. - - The =org-refile-targets= is pretty powerful if you read the doc. You specify a list of - file and some /search/ options for org to build its list from. Those options can be the - level of the entry, some tag, regular expression, … In my case, I want this list to be - all the =org= file in the =project= folder and also the =inbox.org= file. For the inbox, - I want to look only at level 0 (aka root), for the other, I want to look at level 1 (aka - root and sub entries). - - I also changed the default way to show the refile targets (=level1/level2/level3=) to - include the file name. When refiling, you can either do the completion hierarchically - (select the file, then the first level, …) or you can display all the choice at once. I - tend to prefer having all the choice at once and let my completion framework (=ivy= as - of now) to do the /fuzzy/ selection. - - Finally, I want to be able to create new node if I want, while refiling, so I'm setting - =org-refile-allow-creating-parent-nodes= to =confirm=, to ask me if I am sure 👼. -- User Interface :: - + I want, by default, to display the effort and clock summary on org columns, so I am - setting the =org-columns-default-format= to do that. - - [[./images/2020-02-29-13-46-08.png]] - - + I want to /fontify/ the whole header line (it tends to look better for some theme) - + I want things /pretty/, hence the =org-pretty-entities= 😹 - + When a entry (or a drawer) is closed, I like having a visual cue that it is. I chose - the =…= character to show that. It can be set with =org-ellipsis=. -- Logging :: =org-mode= allows to write the time (or a note) on a entry state change, this - is achieved by the =org-log-*= variables. On marking entries as =DONE= or when - rescheduling them (or changing the deadline), I want to mark the time. - - Additionally, when I log those state changes, I don't want them to pollute the content - of the to-do (aka description, …). Setting =org-log-int-drawer= will insert those logs - in a =LOGBOOK= drawer (same as the property drawer). -- Archiving :: I don't want to pollute my current folder with =_archive= files, so I am - redefining =org-archive-location= to archive to my =org-default-completed-dir=, also - using =datetree= to put archived items in a datetree. -- Miscellaneous :: - + I am setting up =org-use-property-inheritance= to make children node inherit their - parent property. It has a cost on search but I feel, as for tag inheritance, it is - worth the cost. - + Still on properties, =org-global-properties= allows you to add values to properties - that will show in the completion when setting those. For example, setting =EFFORT_ALL= - to a list, will give you those options when you are trying to set the effort property. - + I am setting =org-enforce-todo-dependencies= to make sure a parent entry cannot be - mark as done if children are not in complete state (=DONE=, =CANCELLED=, …). - + I want to add a new blank line whenever I create a new entry *but* I don't want that - extra new blank line when adding a new list item. =org-blank-before-new-entry= allow - to customize that behaviour. - + I don't want to load inline image at startup ; it slows down for nothing. - -/The =ensure org-plus-contrib= is there to make sure I am loading the =org= module from my -nix configuration and not the built-in =org= module (that might lag in terms of version)/ - -#+INCLUDE: "../tools/emacs/config/config-org.el" src emacs-lisp :range-begin "OrgMain" :range-end "-OrgMain" :lines "27-102" - -I've set-up an =org-mode= hook to add few modes to the default setup. -- I am really annoyed by trailing white-space so I want them to be shown -- If the major mod is not =org-agenda-mode= (a sub-mode of =org-mode=) - + I set the =fill-column= to ~90~ (instead of the usual ~80~), and I enable =auto-fill= mode. - + I turn on =auto-revert-mode= so that the buffer is always up-to-date. - + I like to have header indented, so I'm enabling =org-indent-mode=. - -#+INCLUDE: "../tools/emacs/config/config-org.el" src emacs-lisp :range-begin "OrgHook" :range-end "-OrgHook" :lines "105-117" - -Let's also use =org-id=… - -#+INCLUDE: "../tools/emacs/config/config-org.el" src emacs-lisp :range-begin "OrgId" :range-end "-OrgId" :lines "120-149" - -… and =org-crypt= (for encrypted =org-mode= files). - -#+INCLUDE: "../tools/emacs/config/config-org.el" src emacs-lisp :range-begin "OrgCrypt" :range-end "-OrgCrypt" :lines "152-157" - -**** TODO Refiling -:PROPERTIES: -:CUSTOM_ID: h:da7330fb-2b24-4bc8-a9a8-7bf6b7ef3761 -:END: - -Heavily based on [[http://www.howardism.org/Technical/Emacs/getting-more-boxes-done.html][Getting Boxes Done, the Code]] and [[http://www.howardism.org/Technical/Emacs/getting-even-more-boxes-done.html][Refiling Trees to Files]]. -There is also [[https://stackoverflow.com/questions/11902620/org-mode-how-do-i-create-a-new-file-with-org-capture][emacs - Org-Mode - How do I create a new file with org-capture? - Stack Overflow]] - -*** TODO Agenda -:PROPERTIES: -:CUSTOM_ID: h:ba2a773a-88d1-4df9-a98c-5e547ee50691 -:END: - -The =org-mode= agenda is *the* source of my day-to-day organization. This is how I know -what I have to do that, what I can do. This is also where I log my work (see /Clocking/ -below). - -#+begin_quote -Due to the way Org works, TODO items, time-stamped items, and tagged headlines can be -scattered throughout a file or even a number of files. To get an overview of open action -items, or of events that are important for a particular date, this information must be -collected, sorted and displayed in an organized way. -#+end_quote - -Invoking =org-agenda= presents a list of possible options. There as a list of built-in -agenda views, where =a= shows all the items that have date assigned to them (=SCHEDULED= -or =DEADLINE=), =t= for listing to-dos, =T= for listing to-dos with a specific state and -=m= for more advanced matching possibilities. - -I am using [[https://github.com/alphapapa/org-super-agenda/][=org-super-agenda=]] to /supercharge/ the =org-mode= agenda 👼 to define my own -agenda views. This allows to group things and overall set-up the agenda view I want. This -agenda view uses the =n= key. - -#+INCLUDE: "../tools/emacs/config/config-org.el" src emacs-lisp :range-begin "OrgAgenda" :range-end "-OrgAgenda" :lines "160-209" - -Let's try to get my work calendar entries in my agenda too. It is a little bit tricky 👼. - -#+INCLUDE: "../tools/emacs/config/config-org.el" src emacs-lisp :range-begin "OrgGcal" :range-end "-OrgGcal" :lines "212-226" - -*** Habits :ATTACH: -:PROPERTIES: -:CUSTOM_ID: h:291bae2c-f3eb-4c2a-9415-606afa28ac86 -:ID: 17a3ed73-aaca-4a18-8ed1-3efe7bac855a -:END: - -Org has the ability to track the consistency of a special category of -TODO, called /habits/. - -#+begin_quote -What’s really useful about habits is that they are displayed along -with a consistency graph, to show how consistent you’ve been at getting -that task done in the past. This graph shows every day that the task -was done over the past three weeks, with colors for each day. The -colors used are: - -Blue - If the task was not to be done yet on that day. -Green - If the task could have been done on that day. -Yellow - If the task was going to be overdue the next day. -Red - If the task was overdue on that day. -#+end_quote - -This look as followed in the agenda. - -[[./images/2020-02-29-14-41-59.png]] - -#+INCLUDE: "../tools/emacs/config/config-org.el" src emacs-lisp :range-begin "OrgHabit" :range-end "-OrgHabit" :lines "229-234" - -*** TODO Sources -:PROPERTIES: -:CUSTOM_ID: h:82c3b800-9d80-408d-b3b6-54dc15b0590c -:END: - -#+INCLUDE: "../tools/emacs/config/config-org.el" src emacs-lisp :range-begin "OrgSrc" :range-end "-OrgSrc" :lines "237-244" - -*** TODO Capture -:PROPERTIES: -:CUSTOM_ID: h:b29abe71-6e9a-4ddf-8519-453170212777 -:END: - -The =org-capture= tool is a powerful way to quickly produce some kind of structured -information with little interruption of your workflow. With =org-agenda=, this is one of -the most used feature of =org-mode= (at least for me). - -Each template is accessed via a key. These are listed in a buffer when you call -=org-capture=. Unique keys give direct access to their template, whereas templates that -share a common initial key will produce a second selection list with the remaining -options. This is very interesting when you want to group some capture template together -(like templates related to /work/, …). - -#+INCLUDE: "../tools/emacs/config/config-org.el" src emacs-lisp :range-begin "OrgCaptureStart" :range-end "-OrgCaptureStart" :lines "247-251" - -Some of my capture template are big and hard to read if embedded in the =emacs-lisp= -code. The good thing is that =org-mode= is able to load the template from files too 💃. - -Here is a list of my templates: -- Default :: Store a link (mainly used with =org-protocol=) and take a random note - - #+INCLUDE: "../tools/emacs/config/config-org.el" src emacs-lisp :range-begin "OrgCaptureOldTemplate" :range-end "-OrgCaptureOldTemplate" :lines "254-259" - -- Tasks :: /work/ task, like reviewing a PR, or cleaning a folder. - - #+INCLUDE: "../tools/emacs/config/config-org.el" src emacs-lisp :range-begin "OrgCaptureTask" :range-end "-OrgCaptureTask" :lines "262-274" - -- journaling :: As I use =org-mode= for my /journal/ too, I need capture entry for - it. I currently have two types of journal entry : - - *This changed, I am using =org-journal= now, this needs to be updated* - - + standard: one title and some text - - #+INCLUDE: "../tools/emacs/etc/orgmode/journal.org" src org - - + worklog: related to work, to be able to say what I did, what I wanted to do, problems, - … during the daily - - #+INCLUDE: "../tools/emacs/etc/orgmode/worklog.org" src org - - -- weekly review :: each and every week, I am going through this item to make my review of - the week. - - #+INCLUDE: "../tools/emacs/etc/orgmode/weekly.org" src org - - -- blog posts :: - - #+INCLUDE: "../tools/emacs/config/config-org.el" src emacs-lisp :range-begin "OrgCaptureBlog" :range-end "-OrgCaptureBlog" :lines "284-286" - -#+INCLUDE: "../tools/emacs/config/config-org.el" src emacs-lisp :range-begin "OrgCaptureEnd" :range-end "-OrgCaptureEnd" :lines "289-290" - -#+INCLUDE: "../tools/emacs/config/config-org.el" src emacs-lisp :range-begin "OrgProtocol" :range-end "-OrgProtocol" :lines "293-295" - -*** Clocking -:PROPERTIES: -:CUSTOM_ID: h:264afe05-79e3-4bff-aafc-9fc726c4034b -:END: - -I am heavily using the clocking along with =org-agenda=. My usual workflow, related to -clocking is : - -- I bring the Agenda up -- I clock the task I am working on, using =I= in the agenda -- When I stop working on the task - + if the task is completed, I use =t d= to mark it as done, the clock should - automatically stop. - + if the task is not completed, I use =O= to stop the clock - -In addition to that workflow, I want to switch the state of the task to =STARTED= when I -am clocking-in, if it's not already =STARTED=. - -#+INCLUDE: "../tools/emacs/config/config-org.el" src emacs-lisp :range-begin "OrgClock" :range-end "-OrgClock" :lines "298-391" - -*** TODO Links -:PROPERTIES: -:CUSTOM_ID: h:afc81fbb-f7a0-401c-8b56-19f51edebd88 -:END: - -#+INCLUDE: "../tools/emacs/config/config-org.el" src emacs-lisp :range-begin "OrgAttach" :range-end "-OrgAttach" :lines "394-398" - -#+INCLUDE: "../tools/emacs/config/config-org.el" src emacs-lisp :range-begin "OrgLinks" :range-end "-OrgLinks" :lines "401-435" - -*** TODO Litterate programming -:PROPERTIES: -:CUSTOM_ID: h:b5f6beba-6195-4ff0-a194-502ac2a9e3da -:END: - -#+INCLUDE: "../tools/emacs/config/config-org.el" src emacs-lisp :range-begin "OrgBabel" :range-end "-OrgBabel" :lines "438-486" - -*** TODO Exporting -:PROPERTIES: -:CUSTOM_ID: h:afad00e0-367c-4c7b-b191-e3ed72be754b -:END: - -#+INCLUDE: "../tools/emacs/config/config-org.el" src emacs-lisp :range-begin "OrgExportCfg" :range-end "-OrgExportCfg" :lines "489-494" - -** TODO Email and newsgroup -:PROPERTIES: -:CUSTOM_ID: h:afa562d5-b07e-413b-8c1d-2d489fb72900 -:END: - -I have been back and forth on using email inside Emacs, from ~mu4e~ to ~notmuch~. In the -past I have used Thunderbird, and for a while now, I have been only using webmail UI for -emails (and mobile apps of course). I recently re-discover [[https://www.gnus.org/][Gnus]] as a mail reader, so my -current setup is the following: - -- [[https://www.gnus.org/][Gnus]], the Emacs built-in newsreader and email client. -- ~notmuch~ to be able to browse my mail backups (using ~isync~, …), see [[https://sbr.pm/technical/mail-setup.html][here]] for the - current setup. - -One of the main reason to rely on [[https://www.gnus.org/][Gnus]] instead of ~notmuch~ for the mails, is that I don't -need to worry about some complex mechanism for syncing, storing and indexing email. I -still use ~notmuch~ with ~isync~ to backup my mails somewhere, with the possibility to -search them. - -*** Base email settings -:PROPERTIES: -:CUSTOM_ID: h:765191a3-81cb-4e6e-9360-6a42b2a55b0f -:END: - -Before configuring any email client, we need to establish some essentials: who we are, -where our credentials are stored and whether encryption is supported. - -#+INCLUDE: "../tools/emacs/config/config-mails.el" src emacs-lisp :range-begin "AuthSource" :range-end "-AuthSource" :lines "12-17" - -*** Gnus -:PROPERTIES: -:CUSTOM_ID: h:0aeec7d8-b6c9-4244-8c10-2788c6e89cc5 -:END: - -The documentation describes Gnus as the /"coffee-brewing, all singing, all dancing, -kitchen sink newsreader"/. It is massive, which means the learning curve is more or less -similar to =org-mode=. You need to go slowly, starting simple and enhance your workflow -and configuration along the way. - -Now some basic information on the abstractions that Gnus relies on: - -1. The default Gnus buffer is called "Group". It will present you with a list of all the - news sources you have subscribed to. By default, Gnus only displays messages that have - not been read. The same applies for groups. The "Group" buffer will be empty the very - first time you log in because you have not subscribed to anything yet. Use =g= to - fetch new messages from the sources. If you only want to refresh the group at point, - do it with =M-g=. -2. The "Server" buffer contains a list with all the sources you have specified for - discovering news. In my case, these are my email accounts and a Usenet server where - mailing lists are hosted. To access the "Server" buffer from inside the "Group" - buffer, just hit the caret sign =^=. To subscribe to an item, place the point over it - and hit =u=. Do that for your email's inbox and for whatever mailing lists you intend - to follow. -3. The "Summary" buffer contains all the messages of a group. Hitting the return key over - a message will split the view in two, with the list above and the message below. Use - =n= or =p= to move to the next or previous unread message (or =N= and =P= to just the - next/prev). You access the "Summary" buffer both from the "Group" and the "Server" by - entering a group. - -As noted, Gnus will only show you a list of unread items. To view all your groups, hit -=L=. Use the lower case version =l= to view only the unread ones. To produce a Summary -buffer with read items, hit =C-u RET= over a group and specify the number of messages you -want to list (the other option is =C-u M-g= from inside the Summary). Another useful trick -for the Summary buffer is the use of the caret sign (=^=) to show you the previous message -that the current item is a reply to. - -/Note: this is in a =gnus/init.el= file that is loaded when the =gnus= command is -ran. This means it is only loaded whenever I need to use =gnus= and not before/ - -**** Account settings -:PROPERTIES: -:CUSTOM_ID: h:be7bbb5b-4b13-49f0-8044-b79363ccba7f -:END: - -Let's first configure the essentials of Gnus. - -The =gnus-select-method= sets the default method for fetching news items. As I want to -read mail from several accounts in addition to following Usenet sources, I choose to set -it to nil. - -The =gnus-secondary-select-methods= is where my accounts are specified. Each =nnimap= list -points to a specific line in my =authinfo.gpg= file. My emails all use the same server so -this method allows me to specify the username (email) and password combination for each of -them /without/ making this information public. I am not sure whether the =nnimap-stream= -and =nnimap-authinfo-file= are needed, but I keep them for the sake of completeness. - -- [[http://www.cataclysmicmutation.com/2010/11/multiple-gmail-accounts-in-gnus/][Multiple GMail Accounts in Gnus - Cataclysmic Mutation]] -- [[https://github.com/redguardtoo/mastering-emacs-in-one-year-guide/blob/master/gnus-guide-en.org][mastering-emacs-in-one-year-guide/gnus-guide-en.org at master · redguardtoo/mastering-emacs-in-one-year-guide]] - -#+INCLUDE: "../tools/gnus/init.el" src emacs-lisp :range-begin "GnusCfg" :range-end "-GnusCfg" :lines "3-61" - -Let's also give to gnus my GnuPG key. - -#+INCLUDE: "../tools/gnus/init.el" src emacs-lisp :range-begin "GnusMmlSec" :range-end "-GnusMmlSec" :lines "64-68" - - -**** Gnus agent -:PROPERTIES: -:CUSTOM_ID: h:2beac436-62ba-4b52-acc5-559016ec477f -:END: - -Gnus has something call the "agent", which represent the bridge between Gnus and the -server it connects to. Gnus is said to be "plugged" when a connection is established, -otherwise it is "unplugged". - -Technicalities aside, we basically use this to save a local copy of the items we have -already fetched from the server. We can also use the agent to configure the handling of -local messages. For example, we can set an expiry date, after which the message is -deleted, or we can create a queue of outgoing messages when Gnus is in an unplugged state. - -#+INCLUDE: "../tools/gnus/init.el" src emacs-lisp :range-begin "GnusAgent" :range-end "-GnusAgent" :lines "71-85" - -**** Gnus asynchronous operations -:PROPERTIES: -:CUSTOM_ID: h:c089372e-4aeb-4daf-96d5-77a997ff2dd0 -:END: - -By default, Gnus performs all its actions in a synchronous fashion. This means that Emacs -is blocked until Gnus has finished. By enabling this library, we can use certain functions -in a non-blocking way. I do this for [[#h:8cd8c972-ba38-40c2-b30f-68a4233593d6][sending email]]. - -#+INCLUDE: "../tools/gnus/init.el" src emacs-lisp :range-begin "GnusAsync" :range-end "-GnusAsync" :lines "88-93" - -**** Gnus group -:PROPERTIES: -:CUSTOM_ID: h:4e52ab94-4e54-41df-a43e-db0c8d23a55a -:END: - -Let's dig a bit more into groups : - -+ A group can be assigned a level of importance. This is a grade whose highest score is 1 - and the lowest is 6 (customisable though). Each level has a different colour. To assign - a new value to the group at point, do it with =S l= and then give it a number. Once you - have graded your groups, you can perform various actions on a per-level basis. For - example, to refresh all levels from 1 up to 3 but not higher, pass a numeric argument to - the standard =g= command. So =C-3 g= (this is the same as =C-u 3 g=). -+ Groups can be organised by topic. Create a new one with =T n= and give it a name. Move - a group to a topic with =T m=. To toggle the view of topics use =t= (I have a hook that - does this automatically at startup). The level of indentation tells us whether a topic - is a sub-set of another. Use =TAB= or =C-u TAB= to adjust it accordingly. As with - levels, you can operate on a per-topic basis. For example, to catch up on all the news - of a given topic (mark all as read), you place the point over it, hit =c= and then - confirm your choice. - -Note that =gnus-group-sort-functions= requires the most important function to be declared -last. - -#+INCLUDE: "../tools/gnus/init.el" src emacs-lisp :range-begin "GnusGroup" :range-end "-GnusGroup" :lines "96-112" - -**** Gnus Summary -:PROPERTIES: -:CUSTOM_ID: h:dfe4a692-1f0f-44c7-8d72-a1488e4ef80b -:END: - -Threads should not be hidden, while messages whose root has been removed should be grouped -together in some meaningful way. Furthermore, when moving up or down in the list of -messages using just =n= or =p=, I want to go to the next message, regardless of whether it -has been read or not. I can otherwise rely on standard Emacs motions. - -The formatting of the threads using Unicode characters was taken from the [[https://www.emacswiki.org/emacs/GnusFormatting][relevant Emacs -wiki entry]] plus some minor tweaks by me. - -The =gnus-user-date-format-alist=, this basically adapts the date to whether the message -was within the day or the one before, else falls back to a default value. It is then -called with =%&user-date;=. - -#+INCLUDE: "../tools/gnus/init.el" src emacs-lisp :range-begin "GnusSummary" :range-end "-GnusSummary" :lines "124-167" - -Gnus summary displays a mark for each messages, those `O`, `!`, … Let's first describe -what are those marks (from the [[https://www.gnu.org/software/emacs/manual/html_node/gnus/Marking-Articles.html#Marking-Articles][documentation]]) and which one make the more sense for me. -Most of those marks can be set using the =M= prefix (or =M M=) from the Summary buffer. - -First there is two groups of /marks/ : *unread* and *read*. Note they do not entirely map -to what IMAP defines or what you would see in another mail UI (webmail, …). - -+ *unread*: those will appear by default on a Summary buffer (almost 😜) - - =<SPC>= are the /standard/ unread, never read. Once a mail is read you can mark it back as - unread with =M M u u=. - - =!= is for /ticked/. This is similar to the *starred* thread/message on GMail (or - Thunderbird, … — in ~notmuch~ it appears as =flagged=). Those will always appear in - the summary, so this is mainly for really important message to be remembered all the - time. - - =?= is for /dormant/. This is similar to /ticked/ *but* the article will only appear - if there is a follow-up of the message. This would be a good use of "waiting for an - answer so keep it". -+ *read*: those will not appear by default on a Summary buffer - - =r= and =R= are /just read/ (like in the /reading session/) more or less - - =O= is /read/ in an older session - - =Y= is for /too low of a score/, this means this message got automatically read - because it had low score (/more on that later/). - - =E= is for /marked as expirable/, so that Gnus can delete/expunge them (or do - something else — /more on that later/). - - =M= is for /duplicated/. - - =K=, =X= are for /killed/, =C= is for /catchup/ =Q= is for /sparsely reffed article/ - and =G= is for cancelled — not sure what this means yet… - -**** Gnus intersection with Dired -:PROPERTIES: -:CUSTOM_ID: h:35901f1a-4a24-46a8-bc8f-a334cd156f2b -:END: - -We can use the built-in directory editor (file manager) as a more convenient way of -performing certain tasks that relate to emails, such as attaching all the marked items of -the =dired= buffer to an email we are currently composing or wish to initiate the -composition of. - -Run =C-h m= inside of a Dired buffer that has =gnus-dired-mode= enabled and search for -"gnus" to see all the relevant key bindings and the functions they call. I only ever use -=C-c C-m C-a= (=C-m= is the same as =RET=). - -#+INCLUDE: "../tools/gnus/init.el" src emacs-lisp :range-begin "GnusDired" :range-end "-GnusDired" :lines "188-191" - -**** TODO Searching mails -:PROPERTIES: -:CUSTOM_ID: h:8288c9b3-cfe2-4599-a55b-9b2b1c71f524 -:END: - -**** TODO Subscribing to RSS -:PROPERTIES: -:CUSTOM_ID: h:259bbc05-4ea6-43b7-bfef-0036434a86f8 -:END: - -*** TODO Sending mails -:PROPERTIES: -:CUSTOM_ID: h:8cd8c972-ba38-40c2-b30f-68a4233593d6 -:END: - -#+INCLUDE: "../tools/emacs/config/config-mails.el" src emacs-lisp :range-begin "SendmailCfg" :range-end "-SendmailCfg" :lines "30-44" - -#+INCLUDE: "../tools/emacs/config/config-mails.el" src emacs-lisp :range-begin "MessageCfg" :range-end "-MessageCfg" :lines "47-65" - -*** TODO ~notmuch~ configuration -:PROPERTIES: -:CUSTOM_ID: h:b67b377e-0fbc-4237-857c-641cdf2de1cf -:END: - -#+INCLUDE: "../tools/emacs/config/config-mails.el" src emacs-lisp :range-begin "Notmuch" :range-end "-Notmuch" :lines "68-86" - -* User interface and interactions -:PROPERTIES: -:CUSTOM_ID: h:93826a52-2f51-437b-8625-ce7cd36d53b6 -:END: -** Mouse -:PROPERTIES: -:CUSTOM_ID: h:cb0ad0e0-62a8-469a-970d-074a423b720d -:header-args: :tangle config/setup-mouse.el -:END: - -The value of mouse-wheel-scroll-amount means the following: - -- By default scroll by one line. -- Hold down Shift to do so by five lines. -- Hold down Meta to scroll half a screen. -- Hold down Control to adjust the size of the text. This is added in Emacs 27. - -By enabling mouse-drag-copy-region we automatically place the mouse selection to the kill -ring. This is the same behaviour as terminal emulators that place the selection to the -clipboard (or the primary selection). - -The other options in short: - -- Hide mouse pointer while typing. -- Enable mouse scroll. -- Faster wheel movement means faster scroll. - -#+begin_src emacs-lisp -(use-package mouse - :config - (setq mouse-wheel-scroll-amount - '(1 - ((shift) . 5) - ((meta) . 0.5) - ((control) . text-scale))) - (setq make-pointer-invisible t - mouse-wheel-progressive-speed t - mouse-wheel-follow-mouse t) - :hook (after-init . mouse-wheel-mode)) -#+end_src - -** Theme -:PROPERTIES: -:CUSTOM_ID: h:18fcf62d-a919-4614-803d-f5d28bc47985 -:END: - -*** My own theme :ATTACH: -:PROPERTIES: -:CUSTOM_ID: h:1a7c1e91-d3c5-4395-b956-8001a1a1a393 -:END: - -I navigate between themes, but the more I use Emacs (or any editor really), the more I -lean towards writing my own. Those theme are base on [[https://github.com/Jannis/emacs-constant-theme][=emacs-constant-theme=]] which is "A -calm, almost monochrome color theme for Emacs with a dark and light variant". - -My main goal is to make a theme that, at least for syntax highlighting, differs from the -usual color(ful) themes. The reason come from a [[https://www.linusakesson.net/programming/syntaxhighlighting/][bunch]] [[https://jameshfisher.com/2014/05/11/your-syntax-highlighter-is-wrong/][of]] [[https://www.robertmelton.com/project/syntax-highlighting-off/][articles]] and [[https://asylum.madhouse-project.org/blog/2018/09/06/the-brutalist-path/][repositories]] that -discuss how, /maybe/ the way we see and use syntax highlighting today is not optimum. This -is a _touchy_ subject to see the least but it does make sense to me: I want to highlight -comments (because they may be important to understand the code), and I don't want to -highlight the language keyword more than the actual code. - -I wrote two version, a dark one and a light one. I currently mainly use the light theme -(as this is when I do work 😅). - -**** Light theme -:PROPERTIES: -:CUSTOM_ID: h:8997adc9-8681-4d3a-a118-616866895f93 -:END: - -[[./images/2020-03-03-21-57-41.png]] - -#+INCLUDE: ../tools/emacs/lisp/shortbrain-light-theme.el src emacs-lisp - -**** Dark theme -:PROPERTIES: -:CUSTOM_ID: h:e986baca-a7dc-463e-85ee-ea10fb69bf0f -:END: - -[[./images/2020-03-03-21-59-22.png]] - -#+INCLUDE: ../tools/emacs/lisp/shortbrain-theme.el src emacs-lisp - -* TODO Programming -:PROPERTIES: -:CUSTOM_ID: h:635a27c4-5ff9-46e4-8d42-283d316cf4d6 -:END: - -* Nix-ies -:PROPERTIES: -:CUSTOM_ID: h:8bc69da9-b49c-4ddd-a6c9-b944aad993a1 -:END: - -This is where the magic happens, when using [[https://nixos.org/nix/][~nix~]] or [[https://nixos.org][NixOS]] with [[https://github.com/rycee/home-manager][~home-manager~]]. In a gist -we will create a set of nix files that tangle, get dependencies and generate the correct -emacs package with the packages used inside the configuration. This means, if I add a -=(use-package magit)= in my configuration, and I tangle / re-execute this script(s), I now -have a new packaged installed as part of my Emacs package. This is *heavily* inspired by -[[https://matthewbauer.us/bauer/][Matthew Bauer's bauer]] emacs configuration. - -** Required lisp libraries -:PROPERTIES: -:CUSTOM_ID: h:316fd3ee-ab99-4f01-ba5a-1a91c54bc334 -:END: - -We need a way to list packages used in the configuration using ~use-package~. This is -coming straight from [[https://matthewbauer.us/bauer/][Matthew Bauer's bauer]]. - -#+INCLUDE: ../tools/emacs/lisp/use-package-list.el src emacs-lisp - -The idea is to run some like the following. - -#+begin_src bash :tangle no -emacs --batch --quick \ - -L /nix/store/acm9rskhx237xb16zdy7vx6r1m5n8q58-emacs-packages-deps/share/emacs/site-lisp/elpa/use-package-20191126.2034/use-package-* \ - -l /home/vincent/.emacs.d/lisp/use-package-list.el \ - --eval "(use-package-list \"/home/vincent/.emacs.d/init.el\")" -#+end_src - -* External libraries -:PROPERTIES: -:CUSTOM_ID: h:96ce2856-182e-42c8-a8b3-418c38124dcc -:END: -** ~gotest-ui.el~ -:PROPERTIES: -:CUSTOM_ID: h:a94b8ba9-2d74-4fb3-a43a-58f4cd6e5141 -:END: - -From [[https://github.com/antifuchs/gotest-ui-mode/][antifuchs/gotest-ui-mode]]. - -#+INCLUDE: ../tools/emacs/lisp/gotest-ui.el src emacs-lisp - -** Org mode links -:PROPERTIES: -:CUSTOM_ID: h:80cc4939-759a-456b-8dfd-220dd8b48727 -:END: - -I am defining additonal org-mode links for my day to day usage. - -- ~ol-github.el~: link to GitHub repositories, issues and pull-requests. - - #+INCLUDE: ../tools/emacs/lisp/vorg/ol-github.el src emacs-lisp - -- ~ol-gitlab.el~: link to GitLab repositories, issues and merge-requests. - - #+INCLUDE: ../tools/emacs/lisp/vorg/ol-gitlab.el src emacs-lisp - -- ~ol-rg.el~: link to a =rg= search buffer. - - #+INCLUDE: ../tools/emacs/lisp/vorg/ol-rg.el src emacs-lisp - -- ~ol-ripgrep.el~: link to a =ripgrep= search buffer. - - #+INCLUDE: ../tools/emacs/lisp/vorg/ol-ripgrep.el src emacs-lisp - -- ~ol-grep.el~: link to a =grep= search buffer. - - #+INCLUDE: ../tools/emacs/lisp/vorg/ol-grep.el src emacs-lisp - -And that's all folks 💃 diff --git a/docs/images/2020-02-29-13-46-08.png b/docs/images/2020-02-29-13-46-08.png @@ -1 +0,0 @@ -../../.git/annex/objects/55/Q5/SHA256E-s97137--f85767c14dd416690fd03ef84d921f4fd929a657475e4f54a89b872cb2efcabd.png/SHA256E-s97137--f85767c14dd416690fd03ef84d921f4fd929a657475e4f54a89b872cb2efcabd.png- \ No newline at end of file diff --git a/docs/images/2020-02-29-14-41-59.png b/docs/images/2020-02-29-14-41-59.png @@ -1 +0,0 @@ -../../.git/annex/objects/69/zm/SHA256E-s63416--f96bb89ef7260c82a6283061a8e467125b94eb4ecb7320526e27c1525163b87e.png/SHA256E-s63416--f96bb89ef7260c82a6283061a8e467125b94eb4ecb7320526e27c1525163b87e.png- \ No newline at end of file diff --git a/docs/images/2020-03-03-21-57-41.png b/docs/images/2020-03-03-21-57-41.png @@ -1 +0,0 @@ -../../.git/annex/objects/gJ/73/SHA256E-s187193--b4e362cf1c5ed2b36c31d01cf604426d04c6b32bdee894e4171537994a81bb83.png/SHA256E-s187193--b4e362cf1c5ed2b36c31d01cf604426d04c6b32bdee894e4171537994a81bb83.png- \ No newline at end of file diff --git a/docs/images/2020-03-03-21-59-22.png b/docs/images/2020-03-03-21-59-22.png @@ -1 +0,0 @@ -../../.git/annex/objects/2m/1f/SHA256E-s191294--c002b6c041d7350bbe1e9a919b3ef2451f030739de70fb04f17d8c758ed48d80.png/SHA256E-s191294--c002b6c041d7350bbe1e9a919b3ef2451f030739de70fb04f17d8c758ed48d80.png- \ No newline at end of file diff --git a/docs/index.org b/docs/index.org @@ -1,45 +0,0 @@ -#+TITLE: Configurations -#+FILETAGS: #home infra configuration dotfiles -#+SETUPFILE: ./.setupfile.org -#+LINK: monorepo https://git.sr.ht/~vdemeester/home - -This set of pages and articles are describing and discussing my configurations. By -configurations I mean the [[https://dotfiles.github.io/][dotfiles]] for miscellaneous software and operating systems (like -[[https://nixos.org][=NixOS=]], or [[https://www.gnu.org/software/emacs/][GNU Emacs]]). This documents comes from my [[monorepo][monorepo]] for my personal tools and -infrastructure. I'm trying to use [[https://nixos.org/nix/][Nix]] as much as possible for those configuration, using -[[https://nixos.org][=NixOS=]] and [[https://rycee.gitlab.io/home-manager/][=home-manager=]]. But it is not limited to this. The goal of my [[monorepo][monorepo]] is: - -- Centralized (sometimes /literate/) configurations -- Shareable nix modules (e.g. =zsh= configuration on =nixos= and using =home-manager=) -- One repository to rule all my configurations, for all my machines. -- Reproductible and testable configurations - -On idea is also to try to do something like "[[https://willschenk.com/articles/2020/leveraging_disposability_for_exploration/][Leveraging disposability for exploration]]", -aka "how to play around without leaving a mess". I'll try my best to make everything -reproducible and easily testable without making /a mess/. Nix/NixOS should help with that… - -The following part of this page tries to present an organization to all my -configurations ; but there is a [[file:sitemap.org][sitemap]] if you want to see all the content. - -* TODO Setup - -My [[monorepo][monorepo]] can be used on multiple system — [[https://nixos.org][=NixOS=]] and [[https://fedoraproject.org/][Fedora]] mainly, but it should work -on anything that can run [[https://nixos.org/nix][Nix]] is available, and where [[https://rycee.gitlab.io/home-manager/][=home-manager=]] works. - -- [[file:install/nixos.org][How to install on NixOS]] explains how to setup and use the [[monorepo][monorepo]] when installing NixOS -- [[file:install/fedora.org][How to install on Fedora]] explains how to setup and use the [[monorepo][monorepo]] when installing on - Fedora (after the installation) -- [[file:install/bootstrap.org][Bootstrap & install]] scripts explained - -* TODO NixOS - -* TODO Tools - -** TODO Emacs - -* Triage - -Those are =work-in-progress= document, that needs to be refined, redefined or completed. - -- [[file:mails.org][My email setup]] -- [[file:emacs.org][Vincent Demeester's .emacs.d]] diff --git a/docs/install/bootstrap.org b/docs/install/bootstrap.org @@ -1,2 +0,0 @@ -#+TITLE: Bootstrap script -#+SETUPFILE: ../.setupfile.org diff --git a/docs/install/fedora.org b/docs/install/fedora.org @@ -1,2 +0,0 @@ -#+TITLE: Fedora installation -#+SETUPFILE: ../.setupfile.org diff --git a/docs/install/nixos.org b/docs/install/nixos.org @@ -1,2 +0,0 @@ -#+TITLE: NixOS installation -#+SETUPFILE: ../.setupfile.org diff --git a/docs/mails.org b/docs/mails.org @@ -1,429 +0,0 @@ -#+TITLE: My email setup -#+SUBTITLE: A very opiniated mail setup -#+SETUPFILE: ./.setupfile.org - -#+BEGIN_abstract -This article presents my opinionated email setup, client side. By opinionated I mean that -it requires quite some stuff (like =nixpkgs=) and is cli/emacs/… oriented. -#+END_abstract - -I used to read my mails only through the web interface of my mail provider (GMail for the -most part), or through my phone. As I'm trying to use my phone less, at least for work, -and as I wanted to not have a gmail tab always opened on my browser, I decided to -configure an email client on my laptops/desktops. - -#+TOC: headlines 1 - -So far, I ended up using the following tools: - -- [[http://isync.sourceforge.net/mbsync.html][~mbsync~]] to sync mails between server and laptop/desktop. -- [[https://marlam.de/msmtp/][~msmtp~]] to send mails. -- [[https://notmuchmail.org/][~notmuch~]] to index, and tag mails. -- [[https://www.gnu.org/software/emacs/][~emacs~]] with [[https://www.gnu.org/software/emacs/manual/html_node/gnus/][~gnus~]] and [[https://notmuchmail.org/notmuch-emacs/][~notmuch~]] for reading/sending mails. -- [[http://astroidmail.github.io/][~astroid~]] for cases where I want another GUI than emacs. - -Something a bit special here is that I also use [[https://github.com/rycee/home-manager][~home-manager~]]… and [[https://github.com/rycee/home-manager][~home-manager~]] has -modules for those tools, so we are going to use thoses. - -* Module -:PROPERTIES: -:CUSTOM_ID: h:db00a56e-c928-47d4-a784-3b2d2600759c -:END: - -Let's start by defining the module, the usual Nix way. - -#+begin_src nix :tangle ./modules/profiles/mails.nix - # Generated from an org file 💃 - # See : https://sbr.pm/technical/configurations/mails.html - { config, lib, pkgs, ... }: - - with lib; - let - cfg = config.profiles.mails; - in - { -#+end_src - -Let's now define options. As of now, except ~enable~ (to activate or not the module) I -don't have any options in mind. - -#+begin_src nix :tangle ./modules/profiles/mails.nix -options = { - profiles.mails = { - enable = mkEnableOption "Enable mails configuration"; - sync = mkEnableOption "Enable sync mail service"; - frequency = mkOption { - default = "*:0/30"; - description = "Frequency at which the mail should be checked"; - type = types.str; - }; - }; -}; -#+end_src - -Finally, create the configuration. - -#+begin_src nix :tangle ./modules/profiles/mails.nix -config = mkIf cfg.enable (mkMerge [ - { -#+end_src - -* Base settings -:PROPERTIES: -:CUSTOM_ID: h:e492a4cf-41e5-4091-9fc3-1294bef31875 -:END: - -** Accounts -:PROPERTIES: -:CUSTOM_ID: h:ddef34cf-07c6-4ae1-abc9-129440ded5e2 -:END: - -The next step is to actually define the accounts we want use and where we want to store -email, amongst other need. - -- We want to store mails in ~desktop/mails/{account}~. -- We don't want to input password each and every time so we're using an encrypted file - ([[https://www.gnupg.org/gph/en/manual/x110.html][symmetric encryption using GnuPG]] with a passphrase file). -- We're gonna enable diverse modules on each account - + ~mbsync~ to sync the mail with some setupts (like specific rules for GMail specific - folders) - + ~notmuch~ for email indexing - + ~msmtp~ to send a mail, using the account's smtp server - + ~astroid~ for a GUI - -#+begin_src nix :tangle ./modules/profiles/mails.nix -accounts.email = { - maildirBasePath = "desktop/mails"; - accounts = { - "redhat" = { - address = "vdemeest@redhat.com"; - userName = "vdemeest@redhat.com"; - realName = "Vincent Demeester"; - passwordCommand = "${pkgs.gnupg}/bin/gpg -q --for-your-eyes-only --no-tty --exit-on-status-write-error --batch --passphrase-file ${config.home.homeDirectory}/sync/rh.pass -d ${config.home.homeDirectory}/desktop/documents/rh.pass.gpg"; - imap.host = "imap.gmail.com"; - smtp.host = "smtp.gmail.com"; - mbsync = { - enable = true; - create = "both"; - expunge = "both"; - patterns = ["*" "![Gmail]*" "[Gmail]/Sent Mail" "[Gmail]/Starred" "[Gmail]/All Mail"]; - extraConfig = { - channel = { - Sync = "All"; - }; - account = { - Timeout = 120; - PipelineDepth = 1; - }; - }; - }; - notmuch.enable = cfg.sync; - astroid.enable = cfg.sync; - msmtp.enable = true; - }; - "perso" = { - address = "vinc.demeester@gmail.com"; - userName = "vinc.demeester@gmail.com"; - realName = "Vincent Demeester"; - passwordCommand = "${pkgs.gnupg}/bin/gpg -q --for-your-eyes-only --no-tty --exit-on-status-write-error --batch --passphrase-file ${config.home.homeDirectory}/sync/perso.pass -d ${config.home.homeDirectory}/desktop/documents/perso.pass.gpg"; - imap.host = "imap.gmail.com"; - smtp.host = "smtp.gmail.com"; - mbsync = { - enable = true; - create = "both"; - expunge = "both"; - patterns = ["*" "![Gmail]*" "[Gmail]/Sent Mail" "[Gmail]/Starred" "[Gmail]/All Mail"]; - extraConfig = { - channel = { - Sync = "All"; - }; - account = { - Timeout = 120; - PipelineDepth = 1; - }; - }; - }; - notmuch.enable = cfg.sync; - astroid.enable = cfg.sync; - msmtp.enable = true; - }; - "prv" = { - primary = true; - address = "vincent@demeester.fr"; - userName = "vincent@demeester.fr"; - realName = "Vincent Demeester"; - passwordCommand = "${pkgs.gnupg}/bin/gpg -q --for-your-eyes-only --no-tty --exit-on-status-write-error --batch --passphrase-file ${config.home.homeDirectory}/sync/prv.pass -d ${config.home.homeDirectory}/desktop/documents/prv.pass.gpg"; - imap.host = "mail.gandi.net"; - smtp.host = "mail.gandi.net"; - mbsync = { - enable = true; - create = "both"; - expunge = "both"; - patterns = ["*"]; - extraConfig = { - channel = { - Sync = "All"; - }; - account = { - Timeout = 120; - PipelineDepth = 1; - }; - }; - }; - notmuch.enable = cfg.sync; - astroid.enable = cfg.sync; - msmtp.enable = true; - }; - }; -}; -#+end_src - -To create the pasword files: -- create =~/desktop/documents/{account}.pass.gpg= file, you need to create a - =~/desktop/documents/prv.pass= file with the actual password. -- create =~/sync/{account}.pass= with a passphrase (long, complex, whatever…) -- encrypt =~/desktop/documents/{account}.pass.gpg= with the following command - - #+begin_src bash - gpg --batch --yes --symmetric --passphrase-file ~/sync/{account}.pass --encrypt {account.pass} - #+end_src - -- remove =~/desktop/documents/{account}.pass= - - -** ~msmtp~ wrapper -:PROPERTIES: -:CUSTOM_ID: h:cc9d0707-d775-49ef-884d-ae65174fb259 -:END: - -As I have multiple accounts, I need to be able to send mails from those multiple accounts -too. For this we will use ~msmtp~. We will ~$HOME/.nix-profile/bin/msmtp~ to make sure it -uses ~--read-envolep-from~. This means it will look at what ~FROM~ header is set in the -e-mail and use the correct account accordingly. - -#+begin_src nix :tangle ./modules/profiles/mails.nix -home.file."bin/msmtp" = { - text = '' - #!${pkgs.stdenv.shell} - ${pkgs.libnotify}/bin/notify-send "Sending mail ✉️" - ${pkgs.msmtp}/bin/msmtp --read-envelope-from $@ - ''; - executable = true; -}; -#+end_src - -We also want to make sure we enable ~msmtp~. - -#+begin_src nix :tangle ./modules/profiles/mails.nix -programs.msmtp.enable = true; -#+end_src - -And that should be all for the base settings, so let's close that part - -#+begin_src nix :tangle ./modules/profiles/mails.nix -} -#+end_src - - -* Syncing -:PROPERTIES: -:CUSTOM_ID: h:47e38880-580e-4335-a504-b3c9c580ec91 -:END: - -I may not want to sync and index mails on all computers. In practice, I only do that on -one computer and I sync these mails with the others. - -#+begin_src nix :tangle ./modules/profiles/mails.nix -(mkIf cfg.sync { -#+end_src - -** Service -:PROPERTIES: -:CUSTOM_ID: h:2b822f1b-cd0a-430d-8942-3ad21a4bcaa1 -:END: - -Now that all the configuration are defined (and generated once we run [[https://github.com/rycee/home-manager][~home-manager~]]), -we're going to enable the ~mbsync~ service to synchronize email at the given frequency. - -#+begin_src nix :tangle ./modules/profiles/mails.nix -services.mbsync = { - enable = true; - preExec = "${config.xdg.configHome}/mbsync/preExec"; - postExec = "${config.xdg.configHome}/mbsync/postExec"; - frequency = cfg.frequency; -}; -#+end_src - -We also setup ~preExec~ and ~postExec~ hooks on the service to be able to run commands -before and after actually running ~mbsync~. - -- ~preExec~ has two main purpose : - - + Create the accounts mail folder — this is *only* useful for the first run ever, but it - is required. - + Move mails on the right folders - - from Inbox to elsewhere (All mails, …) - - (in the future) to the right folders (from the tags) - -#+begin_src nix :tangle ./modules/profiles/mails.nix -xdg.configFile."mbsync/preExec" = { - text = '' - #!${pkgs.stdenv.shell} - - export NOTMUCH_CONFIG=${config.xdg.configHome}/notmuch/notmuchrc - export NMBGIT=${config.xdg.dataHome}/notmuch/nmbug - - ${pkgs.coreutils}/bin/mkdir -p ${config.home.homeDirectory}/desktop/mails/redhat ${config.home.homeDirectory}/desktop/mails/perso - ${pkgs.afew}/bin/afew -C ${config.xdg.configHome}/notmuch/notmuchrc -m -v - ''; - executable = true; -}; -#+end_src - -- ~postExec~ will index the new emails in the ~notmuch~ database and tag mail accordingly - (to their folders and other rules in place). - -#+begin_src nix :tangle ./modules/profiles/mails.nix -xdg.configFile."mbsync/postExec" = { - text = '' - #!${pkgs.stdenv.shell} - - export NOTMUCH_CONFIG=${config.xdg.configHome}/notmuch/notmuchrc - export NMBGIT=${config.xdg.dataHome}/notmuch/nmbug - - ${pkgs.notmuch}/bin/notmuch new - ${pkgs.afew}/bin/afew -C ${config.xdg.configHome}/notmuch/notmuchrc --tag --new -v - # Remove inbox (lower-case) - ${pkgs.notmuch}/bin/notmuch tag -inbox -- tag:inbox - # Remove Inbox tagged message that are not in an Inbox - ${pkgs.notmuch}/bin/notmuch tag -Inbox -- not folder:redhat/Inbox and not folder:perso/Inbox and tag:Inbox - ${pkgs.libnotify}/bin/notify-send "Mails synced 📬" - ''; - executable = true; -}; -#+end_src - -Finally, let's define custom commands to simplify my mail usage. Those should be nix -package in the near future — as of now, it is a bit ugly as I'm creating binaries inside -~$HOME/bin~ instead of relying of Nix. - -- ~msync~ is an helper to run quickly ~mbsync~ systemd service from anywhere - -#+begin_src nix :tangle ./modules/profiles/mails.nix -home.file."bin/msync" = { - text = '' - #!${pkgs.stdenv.shell} - ${pkgs.libnotify}/bin/notify-send "Syncing mails 📫️" - systemctl --user start mbsync - ''; - executable = true; -}; -#+end_src - - -** Programs -:PROPERTIES: -:CUSTOM_ID: h:8e918ee0-4ef7-4f98-b170-dcfea20c6443 -:END: - -Additionally we can enable some programs and customize their behavior. Let's enable -~programs.mbsync~, which has for effect to put ~mbsync~ binary in ~PATH~ so that the user -(us) can call it. Same goes for ~programs.msmtp~ and ~programs.notmuch~. - -#+begin_src nix :tangle ./modules/profiles/mails.nix -programs.mbsync.enable = true; -programs.notmuch.enable = true; -#+end_src - -*** Afew -:PROPERTIES: -:CUSTOM_ID: h:74f4160b-d34a-490e-b56a-ad3d0e5f966c -:END: - -[[https://github.com/afewmail/afew][~afew~]] is "an initial tagging script for notmuch mail". We're going to define some extra -configuration to enable some filters and ~MailMover~ rules. - -Note: This should go away at some point as these rules are not dynamic enough for my usage. - -#+begin_src nix :tangle ./modules/profiles/mails.nix -programs.afew = { - enable = true; - extraConfig = '' - [SpamFilter] - [KillThreadsFilter] - [ListMailsFilter] - [ArchiveSentMailsFilter] - [FolderNameFilter] - maildir_separator = / - - [MailMover] - folders = perso/Inbox redhat/Inbox - rename = true - - perso/Inbox = 'NOT tag:Inbox':"perso/[Gmail]/All Mail" - redhat/Inbox = 'NOT tag:Inbox':"redhat/[Gmail]/All Mail" - ''; -}; -#+end_src - -*** Astroid -:PROPERTIES: -:CUSTOM_ID: h:2d4558d2-0596-4c80-bab0-f259385375b1 -:END: - -[[https://github.com/astroidmail/astroid/][~astroid~]] is a "graphical threads-with-tags style, lightweight and fast, e-mail client for -Notmuch". My main e-mail client is ~emacs~ with the ~notmuch~ mode, but sometimes I want a -GUI, mainly to see wanky HTML mails that would not render correctly some times. - -#+begin_src nix :tangle ./modules/profiles/mails.nix -programs.astroid = { - enable = true; - externalEditor = "emacsclient -c"; - extraConfig = { - startup.queries.inbox = "tag:Inbox"; - startup.queries.inbox_perso = "folder:perso/Inbox"; - startup.queries.inbox_redhat = "folder:redhat/Inbox"; - }; -}; -#+end_src - -And that's all for the sync part, so let's close it - -#+begin_src nix :tangle ./modules/profiles/mails.nix -}) -#+end_src - -* Close the module -:PROPERTIES: -:CUSTOM_ID: h:7672fedf-2afa-4eb1-a9f2-38a6aada5f5f -:END: - -#+begin_src nix :tangle ./modules/profiles/mails.nix -]); -} -#+end_src - - -* References -:PROPERTIES: -:CUSTOM_ID: h:7012be97-2b81-44e9-b9bb-8c4147e3d561 -:END: - -- [[https://copyninja.info/blog/email_setup.html][My personal Email setup - Notmuch, mbsync, postfix and dovecot]] -- [[https://anarc.at/blog/2016-05-12-email-setup/][Notmuch, offlineimap and Sieve setup - anarcat]] -- [[https://github.com/kzar/davemail]] -- [[https://martinralbrecht.wordpress.com/2016/05/30/handling-email-with-emacs/][Handling Email with Emacs – malb::blog]] -- [[https://kirang.in/post/emacs-as-email-client-with-offlineimap-and-mu4e-on-osx/][Emacs as email client with offlineimap and mu4e on OS X]] -- [[http://cachestocaches.com/2017/3/complete-guide-email-emacs-using-mu-and-/][A Complete Guide to Email in Emacs using Mu and Mu4e]] -- [[https://notmuchmail.org/emacstips/#index24h2][emacstips]] -- [[https://kkatsuyuki.github.io/notmuch-conf/][notmuch + emacs + offlineimap configuration procedure]] -- [[https://wiki.archlinux.org/index.php/Isync][isync - ArchWiki]] -- [[https://superuser.com/questions/437027/emacs-and-multiple-smtp-servers][email - Emacs and Multiple SMTP servers - Super User]] -- [[https://notanumber.io/2016-10-03/better-email-with-mu4e/][Better Email with mu4e | NaN]] -- [[https://wwwtech.de/articles/2016/jul/my-personal-mail-setup][My personal mail setup]] -- [[https://foobacca.co.uk/blog/2013/04/initial-tagging-and-afew/][initial tagging and afew - Foobacca]] -- [[https://martinralbrecht.wordpress.com/2016/05/30/handling-email-with-emacs/][Handling Email with Emacs – malb::blog]] -- [[http://deferred.io/2016/01/18/how-i-email.html][How I email, 2016 edition]] -- [[https://bostonenginerd.com/posts/notmuch-of-a-mail-setup-part-2-notmuch-and-emacs/][Notmuch of mail a setup Part 2 - notmuch and Emacs | Assorted Nerdery]] -- [[http://www.johnborwick.com/2019/02/09/notmuch-gmailieer.html][Checking email with gmailieer + notmuch + Emacs | John’s Blog]] -- [[https://blog.einval.eu/2019/06/one-year-with-notmuch.html][One year with Notmuch]]