Emacs literate configuration
Ducks
Introduction
To compile literate configuration setup init.el to point to this file. Make sure this file is not named `init.org` as org-babel will generate a .el file too and we don’t want it to be init
Core
Header
This will generate a header at the top of the tangled file to indicate it is generated and is not meant to be modified directly.
1;; -*- lexical-binding: t -*-
2;; This file has been generated from dotemacs.org file. DO NOT EDIT.
3;; Sources are available from https://github.com/shravantata/org
4
5;; Copyright (C) 2024 Shravan Tata Ramalingasetty
6
7;; This file is free software; you can redistribute it and/or modify
8;; it under the terms of the GNU General Public License as published by
9;; the Free Software Foundation; either version 3, or (at your option)
10;; any later version.
11
12;; This file is distributed in the hope that it will be useful,
13;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15;; GNU General Public License for more details.
16
17;; For a full copy of the GNU General Public License
18;; see <https://www.gnu.org/licenses/>.
1(defvar rougier/init-start-time (current-time) "Time when init.el was started")
2(defvar rougier/section-start-time (current-time) "Time when section was started")
3(defun rougier/report-time (section)
4 (message "%-36s %.2fs"
5 (concat section " " "section time: ")
6 (float-time (time-subtract (current-time) rougier/section-start-time))))
7(message "---------------------------------------------------------------")
Basic information
Set basic information such as name and contact details of the primary user
1(setq user-full-name "Shravan Tata Ramalingasetty"
2 user-mail-address "shravantr@gmail.com")
Early init
This file is loaded before the package system and GUI is initialized, so in it you can customize variables that affect the package initialization process, such as package-enable-at-startup, package-load-list, and package-user-dir
1;; Early initialization before running the init script
2(setq
3 site-run-file nil ; No site-wide run-time initializations
4 inhibit-default-init t ; No site-wide default library
5 gc-cons-threshold most-positive-fixnum ; Very large threshold for garbage collector during init
6 package-enable-at-startup nil) ; We'll use straight.el
7
8(setq native-comp-eln-load-path
9 (list (expand-file-name "eln-cache" user-emacs-directory)))
10
11;; Reset garbage collector limit after init process has ended (8Mo)
12(add-hook 'after-init-hook
13 #'(lambda () (setq gc-cons-threshold (* 8 1024 1024))))
14
15(setq package-enable-at-startup nil)
Defaults
1(setq
2 ;; Confirm before exiting emacs
3 confirm-kill-emacs 'yes-or-no-p
4 ;; Do not echo
5 inhibit-startup-echo-area-message nil
6 ;; Don't describe a scratch message
7 initial-scratch-message nil
8 ;; Start full screen and maximized
9 initial-frame-alist (quote ((fullscreen . maximized)))
10 ;; start every frame maximized
11 default-frame-alist (quote ((fullscreen . maximized)))
12 ;; Never ding at me, ever.
13 ring-bell-function 'ignore
14 ;; Save existing clipboard text into the kill ring before replacing it.
15 save-interprogram-paste-before-kill t
16 ;; Prompts should go in the minibuffer, not in a GUI.
17 use-dialog-box nil
18 ;; Fix undo in commands affecting the mark.
19 mark-even-if-inactive nil
20 ;; Let C-k delete the whole line.
21 kill-whole-line t
22 ;; search should be case-sensitive by default
23 case-fold-search nil
24 ;; I want to close these fast, so switch to it so I can just hit 'q'
25 help-window-select t
26 ;; this certainly can't hurt anything
27 delete-by-moving-to-trash t
28 ;; keep the point in the same place while scrolling
29 scroll-preserve-screen-position t
30 ;; highlight error messages more aggressively
31 next-error-message-highlight t
32 ;; don't let the minibuffer muck up my window tiling
33 read-minibuffer-restore-windows t
34 ;; scope save prompts to individual projects
35 save-some-buffers-default-predicate 'save-some-buffers-root
36 ;; don't keep duplicate entries in kill ring
37 kill-do-not-save-duplicates t
38 ;;; Performance
39 ;; Prefer loading newer compiled files
40 load-prefer-newer t
41 ;; Increase how much is read from processes in a single chunk (default is 4kb).
42 read-process-output-max (* 512 1024) ; 512kb
43 ;; Reduce rendering/line scan work by not rendering cursors or regions in
44 ;; non-focused windows.
45 highlight-nonselected-windows nil
46 ;; Disable warnings from the legacy advice API. They aren't useful.
47 ad-redefinition-action 'accept
48 ;; Don't ping things that look like domain names.
49 ffap-machine-p-known 'reject
50 ;; By default, Emacs "updates" its ui more often than it needs to
51 idle-update-delay 1.0
52 ;; The title bar
53 ns-use-proxy-icon nil
54 frame-title-format nil)
55
56
57(setq-default cursor-in-non-selected-windows nil)
58
59(defvar minimal-emacs-frame-title-format "%b – Emacs"
60 "Template for displaying the title bar of visible and iconified frame.")
61
62(defvar minimal-emacs-debug nil
63 "Non-nil to enable debug.")
64
65;; Suppress compiler warnings and don't inundate users with their popups.
66(setq native-comp-async-report-warnings-errors
67 (or minimal-emacs-debug 'silent))
68(setq native-comp-warning-on-missing-source minimal-emacs-debug)
69
70(setq debug-on-error minimal-emacs-debug
71 jka-compr-verbose minimal-emacs-debug)
72
73(setq byte-compile-warnings minimal-emacs-debug)
74(setq byte-compile-verbose minimal-emacs-debug)
75
76(add-to-list 'default-frame-alist '(ns-transparent-titlebar . t))
77(add-to-list 'default-frame-alist '(ns-appearance . light))
Welcome message
1(let ((inhibit-message t))
2 (message "Welcome Shravan Tata! / Don't just get used to your tool, make it get used to you! ")
3 (message (format "Initialization time: %s" (emacs-init-time))))
Package management
Setup the package management used by emacs to manage and install the necessary packages on the fly at the load time.
1(message "Setting up emacs package management...")
Bootstrap straight.el
Using straight.el for package management and disable checking (for speedup).
1(setq straight-check-for-modifications nil)
1(defvar bootstrap-version)
2(let ((bootstrap-file
3 (expand-file-name "straight/repos/straight.el/bootstrap.el" user-emacs-directory))
4 (bootstrap-version 6))
5 (unless (file-exists-p bootstrap-file)
6 (with-current-buffer
7 (url-retrieve-synchronously
8 "https://raw.githubusercontent.com/radian-software/straight.el/develop/install.el"
9 'silent 'inhibit-cookies)
10 (goto-char (point-max))
11 (eval-print-last-sexp)))
12 (load bootstrap-file nil 'nomessage))
Custom paths
1;; User path for saving files
2;; (setq prelude-savefile-dir (expand-file-name "lisp" user-emacs-directory))
3
4;; path to store lisp byte code
5(add-to-list 'load-path
6 (expand-file-name "lisp" user-emacs-directory))
7;; path to store custom themes
8(add-to-list 'custom-theme-load-path
9 (expand-file-name "themes" user-emacs-directory))
10
11
12;; store all backup and autosave files in the tmp dir
13(setq backup-directory-alist
14 `((".*" . ,temporary-file-directory)))
15(setq auto-save-file-name-transforms
16 `((".*" ,temporary-file-directory t)))
Package profiling
1(setq use-package-compute-statistics t)
Packages installation
List all the packages that are required to be installed for the current configuration of emacs
1(setq package-list
2 '(
3 ;; package configuration
4 use-package ; A configuration macro for simplifying your .emacs
5 ;; emacs
6 gcmh ; Garbage collector magic hack
7 esup ; Emacs profiler
8 ;; editing
9 crux ; A Collection of Ridiculously Useful eXtensions for Emacs.
10 multiple-cursors ; Edit multiple cursors
11 ;; interface
12 eyebrowse ; A simple-minded way of managing window configs
13 orderless ; Use space-separated search terms in any order when completing with Icomplete or the default interface
14 smartparens ; Smart parentheses
15 ag ; faster search (requires system installation)
16 ;; visual
17 zone ; Mode to avoid zoning out
18 olivetti ; Pleasant reading
19 ;; themes
20 nano-theme ; Nano theme from rougier
21 spacemacs-theme ; Spacemacs theme
22 catppuccin-theme ; Catppuccin theme
23 ;; navigation
24 imenu-list ; Show imenu entries in a separate buffer
25 ;; mini-buffer
26 ;; helm ; A powerful completion and selection narrowing framework
27 corfu ; Completion Overlay Region FUnction
28 orderless ; orderless completion style
29 vertico ; a performant and minimalistic vertical completion UI
30 cape ; Cape provides Completion At Point Extensions which can be used in combination with the Corfu
31 marginalia ; Show document of function in ==M-x=,
32 consult ; provides various practical commands
33 mini-frame ; Show minibuffer in child frame on read-from-minibuffer
34 ;; minibuffer-header
35 ;; modeline
36 spaceline ; Spacemacs themed modeline
37 ;; parsing
38 tree-sitter ; tree-sitter
39 tree-sitter-langs ; tree-sitter-langs
40 ;; versioning
41 magit ; A Git porcelain inside Emacs
42 diff-hl ; Highlights uncommitted changes in the gutter
43 git-gutter ; Show git line status
44 ;; history
45 undo-tree ; Shows a tree like structure of the history
46 ;; file
47 dired-subtree ; Dired extensions
48 openwith ; Open files appropriately using external apps
49 ;; project management
50 projectile ; Project interaction library for Emacs
51 consult-projectile
52 consult-project-extra ; extra features for project management
53 ;; citations
54 citar ; Citation-related commands for org, latex, markdown
55 citeproc ; A CSL 1.0.2 Citation Processor
56 ;; orgmode
57 org-bullets ; Shows org-mode bullets as pretty UTF-8 characters
58 svg-lib ; svg tags and icons from rougier
59 svg-tag-mode ; svg tags and icons from rougier
60 bibtex ; for reference management
61 org-ref ; Reference manager for orgmode
62 ox-hugo ; Hugo exporter for org mode
63 org-modern ; Modern theming for org mode language
64 langtool ; English grammar and spelling check
65 flycheck-languagetool ; Text suggestions for english
66 ;; proselint ; a linter for English prose
67 writegood-mode ; Text analysis
68 smog
69 ;; powerthesaurus ; Finding synonyms, antonyms, and related terms
70 ;; programming
71 ;; general
72 ;; lsp-mode
73 guess-language ; Robust automatic language detection
74 rainbow-delimiters ; Adds colors to delimiters
75 yasnippet ; yet another snippet
76 yasnippet-snippets ; snippets for many programming languages
77 flycheck ; Modern on-the-fly syntax checking
78 whitespace ; Mode for remove whitespaces
79 ;; workflow
80 snakemake-mode ; Major mode for snakemake files
81 ;; python
82 elpy ; Python Development Environment
83 jedi ; Python auto-completion package
84 sphinx-doc ; Doc pages for python
85 cython-mode ; Cython major mode
86 flycheck-cython ; Syntax checking for cython
87 fill-column-indicator ; Column indicator for python
88 column-enforce-mode ; Column enforcement for python
89 pyenv-mode ; Environments for python
90 pyvenv ; Activate virtual environments for python
91 isortify ; For formating python imports
92 ;; GL
93 glsl-mode ; model GLSL shaders
94 ;; godot
95 gdscript-mode ; Godot programming mode
96 ;; lisp
97 paredit ; paredit
98 ;; html
99 htmlize ; Convert buffer text and decorations to HTML
100 markdown-mode ; Major mode for Markdown-formatted text
101 ;; yaml
102 yaml-mode ; Major mode for editing yaml files
103 ;; latex
104 company-auctex ; auto-completion for latex
105 ;; help
106 ;; flyspell-correct-popup ; Correcting words with flyspell via popup interface
107 ;; flyspell-popup ; Correcting words with Flyspell in popup menus
108 helpful ; A better help buffer
109 which-key ; shows you possible keybindings when you type a partial keybinding
110 ;; remote
111 ssh ; ssh mode remote file connection
112 ;; misc
113 all-the-icons ; Excellent library of icons for filetypes
114 all-the-icons-completion ;
115 mode-icons ; Icons for filetypes in modeline
116 exec-path-from-shell ; Reflect system paths in Emacs
117 ;; whisper ; Speech to text
118 ;; AI
119 gptel ; AI LLM interface for emacs
120 ;; fun
121 xkcd ; xkcd config
122 ;; versioning
123 llama ; requirement for magit
124 )
125 )
126
127;; Exception for org to use system org version
128(straight-use-package '(org :type built-in))
129
130;; Install packages that are not yet installed
131(dolist (package package-list)
132 (straight-use-package package))
133
134;; Special case for ospl-mode
135(straight-use-package
136 '(ospl-mode :type git :host github :repo "arrdem/ospl-mode"))
137
138;; Special case for pdf-tools that has recently (2022) changed maintainer
139(straight-use-package
140 '(pdf-tools :type git :host github :repo "vedang/pdf-tools"))
141
142;; Display org properties in the agenda buffer (modified version)
143(straight-use-package
144 '(org-agenda-property :type git :host github :repo "Malabarba/org-agenda-property"))
145
146(straight-use-package
147 '(shell-maker :type git :host github :repo "xenodium/chatgpt-shell" :files ("shell-maker.el")))
148
149(straight-use-package
150 '(chatgpt-shell :type git :host github :repo "xenodium/chatgpt-shell" :files ("chatgpt-shell.el")))
151
152(straight-use-package
153 '(indent-bars :type git :host github :repo "jdtsmith/indent-bars"))
154
155
156(straight-use-package
157 '(org-appear :type git :host github :repo "awth13/org-appear"))
158
159(straight-use-package
160 '(pinerose-emacs :type git :host github :repo "konrad1977/pinerose-emacs"))
161
162(straight-use-package
163 '(aider :type git :host github :repo "tninja/aider.el"))
Customization
Since init.el will be generated from this file, we save customization in a dedicated file.
1(setq custom-file (concat user-emacs-directory "custom.el"))
2
3(when (file-exists-p custom-file)
4 (load custom-file nil t))
A GNU Emacs library to ensure environment variables inside Emacs look the same as in the user’s shell.
This sets $MANPATH, $PATH and exec-path from your shell, but only when executed in a GUI frame on OS X and Linux.
https://github.com/purcell/exec-path-from-shell
1(when (memq window-system '(mac ns x))
2 (exec-path-from-shell-initialize))
Encoding
We tell emacs to use UTF-8 encoding as much as possible.
1(set-default-coding-systems 'utf-8) ; Default to utf-8 encoding
2(prefer-coding-system 'utf-8) ; Add utf-8 at the front for automatic detection.
3(set-terminal-coding-system 'utf-8) ; Set coding system of terminal output
4(set-keyboard-coding-system 'utf-8) ; Set coding system for keyboard input on TERMINAL
5(set-language-environment "UTF-8") ;
Global
1(add-hook 'after-init-hook #'global-flycheck-mode)
Recent files
50 Recents files with some exclusion (regex patterns).
1(require 'recentf)
2
3(setq recentf-max-menu-items 10
4 recentf-max-saved-items 100
5 recentf-exclude '()
6 ;; disable recentf-cleanup on Emacs start, because it can cause
7 ;; problems with remote files
8 recentf-auto-cleanup 'never
9 )
10
11(let (message-log-max)
12 (recentf-mode 1))
History
Remove text properties for kill ring entries (see https://emacs.stackexchange.com/questions/4187). This saves a lot of time when loading it.
1(defun unpropertize-kill-ring ()
2 (setq kill-ring (mapcar 'substring-no-properties kill-ring)))
3
4(add-hook 'kill-emacs-hook 'unpropertize-kill-ring)
We save every possible history we can think of.
1(require 'savehist)
2
3(setq kill-ring-max 50
4 history-length 50)
5
6(setq savehist-additional-variables
7 '(kill-ring
8 command-history
9 set-variable-value-history
10 custom-variable-history
11 query-replace-history
12 read-expression-history
13 minibuffer-history
14 read-char-history
15 face-name-history
16 bookmark-history
17 file-name-history))
18
19 (put 'minibuffer-history 'history-length 50)
20 (put 'file-name-history 'history-length 50)
21 (put 'set-variable-value-history 'history-length 25)
22 (put 'custom-variable-history 'history-length 25)
23 (put 'query-replace-history 'history-length 25)
24 (put 'read-expression-history 'history-length 25)
25 (put 'read-char-history 'history-length 25)
26 (put 'face-name-history 'history-length 25)
27 (put 'bookmark-history 'history-length 25)
No duplicates in history
1(setq history-delete-duplicates t)
Start history mode.
1(let (message-log-max)
2 (savehist-mode))
Server
Server start.
1(require 'server)
2
3(unless (server-running-p)
4 (server-start))
Post
1;; Make gc pauses faster by decreasing the threshold.
2(setq gc-cons-threshold (* 2 1000 1000))
Garbage
Used by DOOM to manage garbage collection
1(use-package gcmh
2 :demand
3 :config
4 (gcmh-mode 1))
Definitions
Local function definitions to facilitate emacs setup
1(defun waveparticle/langtool-autosave-hook ()
2 ;; Check grammar with langtool before save
3 (add-hook 'before-save-hook 'langtool-check-buffer nil 'local))
Benchmark
1(rougier/report-time "Core")
Interface
1(setq rougier/section-start-time (current-time))
Frame
1;; Disable horizontal scroll bars in GUI
2(when (fboundp 'horizontal-scroll-bar-mode)
3 (horizontal-scroll-bar-mode 0))
Window
Winner mode is a global minor mode that records the changes in the window configuration
1(winner-mode t)
1(setq-default window-divider-default-right-width 6 ; Vertical window divider
2 window-divider-default-places 'right-only
3 left-margin-width 0
4 right-margin-width 0
5 window-combination-resize nil) ; Do not resize windows proportionally
6
7(window-divider-mode 1)
Setup windmove to easily move between windows
1(require 'windmove)
2
3;; use command key on Mac
4(windmove-default-keybindings 'super)
5;; wrap around at edges
6(setq windmove-wrap-around t)
Setup eyebrowse to create and interact with workspaces
1(require 'eyebrowse)
2
3;; Enable eyebrowse mode
4(eyebrowse-mode t)
5;; Start the new window to be as empty as possible
6(setq eyebrowse-new-workspace t)
7;; bind keys for easier movement between windows
8(bind-key "M-1" #'eyebrowse-switch-to-window-config-1 'eyebrowse-mode-map)
9(bind-key "M-2" #'eyebrowse-switch-to-window-config-2 'eyebrowse-mode-map)
10(bind-key "M-3" #'eyebrowse-switch-to-window-config-3 'eyebrowse-mode-map)
11(bind-key "M-4" #'eyebrowse-switch-to-window-config-4 'eyebrowse-mode-map)
Buffers
Set unique buffer names
1(message "Personal config :. uniquify...")
2;; meaningful names for buffers with the same name
3;; from prelude
4;; https://github.com/bbatsov/prelude
5(require 'uniquify)
6(setq uniquify-buffer-name-style 'forward)
7(setq uniquify-separator "/")
8(setq uniquify-after-kill-buffer-p t) ; rename after killing uniquified
9(setq uniquify-ignore-buffers-re "^\\*") ; don't muck with special buffers
Dialog
Pop up windows are needed for `display-buffer` to able to split window. For example, for magit to create a new window for writing the commit message.
1(tool-bar-mode -1) ; remove tool bar
2(scroll-bar-mode -1) ; remove scroll bar
3(tooltip-mode -1) ; remove tooltips
4
5(setq-default show-help-function nil ; No help text
6 use-file-dialog nil ; No file dialog
7 use-dialog-box nil ; No dialog box
8 ;; pop-up-windows nil ; No pop windows
9)
Specific case for OSX since menubar is desktop-wide (see emacs.stackexchange.com/questions/28121) and emacs-mac documentation.
1(menu-bar-mode 1)
Key bindings
Section to remap general keybindings. Should be used sparingly!
1;; Stop opening buffer list accidently
2(unbind-key "C-x C-b")
1;; (global-set-key (kbd "C-S-<left>") 'tabbar-backward)
2;; (global-set-key (kbd "C-S-<right>") 'tabbar-forward)
3;; (global-set-key (kbd "C-S-<up>") 'tabbar-backward-group)
4;; (global-set-key (kbd "C-S-<down>") 'tabbar-forward-group)
5;; (global-set-key (kbd "C-h") 'delete-backward-char)
6;; (global-set-key (kbd "M-h") 'delete-backward-word)
Navigation
Keyboard
The mode displays the key bindings following your currently entered incomplete command (a ;; prefix) in a popup.
1
2(require 'which-key)
3
4(which-key-mode)
Mouse
Mouse avoidance to move the mouse pointer away from the cursor
1
2(setq-default mouse-yank-at-point t) ; Yank at point rather than pointer
3'(mouse-avoidance-mode (quote animate) nil (avoid))
Mouse active in tty mode.
1
2(unless (display-graphic-p)
3 (xterm-mouse-mode 1)
4 (global-set-key (kbd "<mouse-4>") #'scroll-down-line)
5 (global-set-key (kbd "<mouse-5>") #'scroll-up-line))
Sound
Disable the bell (auditory or visual).
1(setq-default visible-bell nil ; No visual bell
2 ring-bell-function 'ignore) ; No bell
Scroll
Smoother scrolling
1(pixel-scroll-precision-mode)
1(setq-default scroll-conservatively 101 ; Avoid recentering when scrolling far
2 scroll-margin 2 ; Add a margin when scrolling vertically
3 recenter-positions '(5 bottom)) ; Set re-centering positions
Clipboard
Allows system and Emacs clipboard to communicate smoothly (both ways)
1(setq-default select-enable-clipboard t) ; Merge system's and Emacs' clipboard
Make sure clipboard works properly in tty mode on OSX.
1(defun my/paste-from-osx ()
2 (shell-command-to-string "pbpaste"))
3
4(defun my/copy-to-osx (text &optional push)
5 (let ((process-connection-type nil))
6 (let ((proc (start-process "pbcopy" "*Messages*" "pbcopy")))
7 (process-send-string proc text)
8 (process-send-eof proc))))
9
10(when (and (not (display-graphic-p))
11 (eq system-type 'darwin))
12 (setq interprogram-cut-function #'my/copy-to-osx
13 interprogram-paste-function #'my/paste-from-osx))
Help
Helpful is an alternative to the built-in Emacs help that provides much more contextual information. It is a bit slow to load so we do need load it explicitly.
1(setq help-window-select t) ; Focus new help windows when opened
2
3(bind-key "C-h f" #'helpful-callable) ; Look up callable
4(bind-key "C-h v" #'helpful-variable) ; Look up variable
5(bind-key "C-h k" #'helpful-key) ; Look up key
6(bind-key "C-c C-d" #'helpful-at-point) ; Look up the current symbol at point
7(bind-key "C-h F" #'helpful-function) ; Look up *F*unctions (excludes macros).
8(bind-key "C-h C" #'helpful-command) ; Look up *C*ommands.
Widgets
1;; No ugly button for checkboxes
2(setq widget-image-enable nil)
Text
Shorten confirmation inputs
1(setq-default
2 use-short-answers t ; Replace yes/no prompts with y/n
3 confirm-nonexistent-file-or-buffer nil ; Ok to visit non existent files
4 )
Replace text when writing over a region
1;; overwrite selected text
2(delete-selection-mode t)
Some other defaults
1;; Double-spaces after periods is morally wrong.
2(setq sentence-end-double-space nil)
Typography
- Column width increased to 88 from default 80. Black (python linter) suggests this to be a better default over the legacy 80 chars
- Nicer and cleaner ellipsis
1(setq-default
2 fill-column 88 ; Default line width increased by 8 chars
3 sentence-end-double-space nil ; Use a single space after dots
4 bidi-paragraph-direction 'left-to-right ; Faster
5 truncate-string-ellipsis "…" ; Nicer ellipsis
6 )
1;; Nicer glyphs for continuation and wrap
2
3(defface my-wrap-symbol-face
4 '((t (:family "JetBrains Mono"
5 :weight light)))
6 "Specific face for wrap symbol")
7
8(set-display-table-slot standard-display-table
9 'truncation (make-glyph-code ?… 'my-wrap-symbol-face))
10
11(set-display-table-slot standard-display-table
12 'wrap (make-glyph-code ?↩ 'my-wrap-symbol-face))
Fix a bug on OSX in term mode & zsh (spurious “%” after each command)
1(when (eq system-type 'darwin)
2 (add-hook 'term-mode-hook
3 (lambda ()
4 (setq buffer-display-table (make-display-table)))))
Make sure underline is positionned at the very bottom.
1(setq x-underline-at-descent-line nil
2 x-use-underline-position-properties t
3 underline-minimum-offset 10)
Project
Use projectile to navigate easily between projects
1(require 'projectile)
2
3(projectile-mode +1)
4
5(if (eq system-type 'darwin)
6 ;; Recommended keymap prefix on macOS
7 (define-key projectile-mode-map (kbd "s-p") 'projectile-command-map)
8 ;; Recommended keymap prefix on Windows/Linux
9 (define-key projectile-mode-map (kbd "C-c p") 'projectile-command-map)
10 )
Use projectile to launch dired when invoked
1(setq projectile-switch-project-action #'projectile-dired)
Disable projectile when using tramp to speed things
1(defadvice projectile-on (around exlude-tramp activate)
2 "This should disable projectile when visiting a remote file"
3 (unless (--any? (and it (file-remote-p it))
4 (list
5 (buffer-file-name)
6 list-buffers-directory
7 default-directory
8 dired-directory))
9 ad-do-it))
Setup projecticle to automatically discover projects
1(setq projectile-auto-discover nil)
2(add-hook 'after-init-hook #'(lambda () (projectile-discover-projects-in-directory "~/projects" 7)))
Files
Filesystems, autosaves and backups
Emacs is super fond of littering filesystems with backups and autosaves, since it was built with the assumption that multiple users could be using the same Emacs instance on the same filesystem. This was valid in 1980. It is no longer the case.
1(setq make-backup-files nil auto-save-default nil create-lockfiles nil)
Configure dired
1(message "Personal config :. dired-subtree...")
2
3(require 'dired-subtree)
4
5(bind-keys :map dired-mode-map
6 ("i" . dired-subtree-insert)
7 (";" . dired-subtree-remove))
8
9(when (eq system-type 'darwin)
10 (setq insert-directory-program "gls" dired-use-ls-dired t)
11 (setq dired-listing-switches "-al --group-directories-first")
12 )
13
14(when (eq system-type 'gnu/linux)
15 (setq dired-listing-switches "-aBhl --group-directories-first")
16 )
17
18(setq dired-kill-when-opening-new-dired-buffer t)
configure ssh for remote files
1(require 'ssh)
2
3(add-hook 'ssh-mode-hook
4 (lambda ()
5 (setq ssh-directory-tracking-mode t)
6 (shell-dirtrack-mode t)
7 (setq dirtrackp nil)))
1;; tramp, for sudo access
2(require 'tramp)
3;; keep in mind known issues with zsh - see emacs wiki
4(setq tramp-default-method "ssh")
Benchmark
1
2(rougier/report-time "Interface")
Search
Use ag as alternate to default search. Requires system installation
1; Highlight search results when using ag
2(setq ag-highlight-search t)
Visual
1
2(setq rougier/section-start-time (current-time))
Font
Some defaults for EMACS
It’s good that Emacs supports the wide variety of file encodings it does, but UTF-8 should always, always be the default.
1(set-charset-priority 'unicode)
2(prefer-coding-system 'utf-8-unix)
This is the font stack we install:
- Default font: JetBrains Mono 12pt Regular
- Italic font: JetBrains Mono 12pt Light
- Bold font: JetBrains Mono 12pt Bold
- Unicode font: jetBrains Mono 14pt Light
- Icon font: JetBrains Mono Nerd 12pt Light
┌───────────────────────────────────────────────┐ │ The quick brown fox jumps over the lazy dog │ │ The quick brown fox jumps over the lazy dog ┼─ JetBrains Mono Italic │ The quick brown fox jumps over the lazy dog ├─ JetBrains Mono Bold └─┼───────────────────────────┼─────────────────┘ JetBrains Mono Nerd JetBrains Mono
1(set-face-attribute 'default nil
2 :family "JetBrains Mono"
3 :weight 'regular
4 :height 128)
5
6(set-face-attribute 'bold nil
7 :family "JetBrains Mono"
8 :weight 'bold)
9
10(set-face-attribute 'italic nil
11 :family "JetBrains Mono"
12 :weight 'light
13 :slant 'italic)
14
15(set-fontset-font t 'unicode
16 (font-spec :name "Jetbrains Mono"
17 :weight 'light
18 :size 13) nil)
19
20(set-fontset-font t '(#xe000 . #xffdd)
21 (font-spec :name "JetBrainsMono Nerd Font"
22 :size 13) nil)
Splash screen
Add a splash screen image and welcome message with some stats
1(add-to-list 'load-path "~/fork/emacs-splash/")
2(require 'splash-screen)
Colors
Themes
Catppuccin
1(load-theme 'catppuccin :no-confirm)
2(setq catppuccin-flavor 'latte);; or 'latte, 'macchiato, or 'mocha or 'frappe
3
4;; ;; Change colors
5;; (catppuccin-set-color 'base "#000000") ;; change base to #000000 for the currently active flavor
6;; (catppuccin-set-color 'crust "#222222" 'frappe) ;; change crust to #222222 for frappe
7;; (set-face-attribute 'region nil :background "#434C5E")
8(catppuccin-reload)
Leuven
1(load-theme 'leuven t)
Nord theme
1(load-theme 'nord t)
Typography
1(setq x-underline-at-descent-line nil
2 x-use-underline-position-properties t
3 underline-minimum-offset 10)
Fancy icons
Enable mode-icons
1(require 'mode-icons)
2(mode-icons-mode t)
Configure all-the-icons to work with required types
In order for the icons to work it is very important that you install the Resource Fonts included in this package, they are available in the fonts directory.
1(all-the-icons-completion-mode)
2(add-hook 'marginalia-mode-hook #'all-the-icons-completion-marginalia-setup)
Focus
Use zone mode is avoid blank staring at the screen
1(require 'zone)
2(zone-when-idle 30000)
Misc
1;; No ugly button for checkboxes
2(setq widget-image-enable nil)
Benchmark
1(rougier/report-time "Visual")
Editing
1(setq rougier/section-start-time (current-time))
Default mode
Default & initial mode is text.
1(setq-default initial-major-mode 'text-mode ; Initial mode is text
2 default-major-mode 'text-mode) ; Default mode is text
Visual line mode for prog and text modes
1(add-hook 'text-mode-hook 'visual-line-mode)
2(add-hook 'prog-mode-hook 'visual-line-mode)
Tree-sitter
1(setq major-mode-remap-alist
2 '((python-mode . python-ts-mode)))
3
4;; (yaml-mode . yaml-ts-mode)
5;; (bash-mode . bash-ts-mode)
6;; (js2-mode . js-ts-mode)
7;; (typescript-mode . typescript-ts-mode)
8;; (json-mode . json-ts-mode)
9;; (css-mode . css-ts-mode)
Text
Subword movement lets us treat “EmacsIsAwesome” as three words ─“Emacs”, “Is”, and “Awesome”─ which is desirable since such naming is common among coders. Now, for example, M-f moves along each subword.
1(global-subword-mode 1)
2;; (diminish 'subword-mode)
Multiple cursors for editing
1(require 'multiple-cursors)
2(multiple-cursors-mode t)
3(bind-key "C-S-c C-S-c" #'mc/edit-lines)
4(bind-key "C->" #'mc/mark-next-like-this)
5(bind-key "C-<" #'mc/mark-previous-like-this)
6(bind-key "C-c C-<" #'mc/mark-all-like-this)
1(require 'indent-bars)
2
3;; indent-bars will not attempt stipple display, but instead use simple characters e.g. |; see an example
4;; M-x version should say Carbon, not NS.
5;; The NS build has partial stipple support in master, which may be released in Emacs v30.
6(setq indent-bars-prefer-character t
7 indent-bars-display-on-blank-lines nil
8 indent-bars-width-frac 0.5
9 )
10
11;; modes to enabel indent bars by default
12(add-hook 'python-mode-hook 'indent-bars-mode)
13(setq indent-bars-treesit-support t
14 indent-bars-treesit-wrap '((python function_definition
15 class_definition
16 for_statement
17 if_statement
18 with_statement
19 while_statement
20 argument_list
21 parameters
22 list
23 list_comprehension
24 dictionary
25 dictionary_comprehension
26 parenthesized_expression
27 subscript))
28 indent-bars-treesit-ignore-blank-lines-types '("module")
29 )
30(add-hook 'yaml-mode-hook 'indent-bars-mode)
whitespace-mode config
1;; whitespace-mode config
2(require 'whitespace)
3(setq whitespace-line-column 80) ;; limit line length
4(setq whitespace-style '(face tabs empty trailing lines-tail))
5(add-hook 'before-save-hook 'whitespace-cleanup)
1(require 'ospl-mode)
History
Setup undo-tree
1(global-undo-tree-mode)
2(setq undo-tree-limit 240000)
3
4;; Prevent undo tree files from polluting your git repo
5(setq undo-tree-history-directory-alist '(("." . "~/.emacs.d/undo")))
Tabulations
No tabulation, ever.
1(setq-default indent-tabs-mode nil ; Stop using tabs to indent
2 tab-always-indent 'complete ; Indent first then try completions
3 tab-width 4) ; Smaller width for tab characters
4
5;; Let Emacs guess Python indent silently
6(setq python-indent-guess-indent-offset t
7 python-indent-guess-indent-offset-verbose nil)
Parenthesis
Paren mode for highlighting matching parenthesis
1(require 'paren)
2;; (setq show-paren-style 'expression)
3(setq show-paren-style 'parenthesis)
4(setq show-paren-when-point-in-periphery t)
5(setq show-paren-when-point-inside-paren nil)
6(show-paren-mode)
1(electric-pair-mode)
Rainbow delimiters
1(require 'rainbow-delimiters)
2(add-hook 'prog-mode-hook #'rainbow-delimiters-mode)
Disable blinking matching paren
1;; disable annoying blink-matching-paren
2(setq blink-matching-paren nil)
Imenu list
Imenu setup
1(require 'imenu-list)
2(setq-default imenu-max-item-length 1000)
3(bind-key "M-'" #'imenu-list-smart-toggle)
4(setq-default imenu-auto-rescan t)
5(setq imenu-list-size 0.15)
6(set-default 'imenu-auto-rescan t)
7
8;; Focus window on imenu immediately after activation
9(setq imenu-list-focus-after-activation t)
10;; Depth of org headings in the imenu buffer
11(setq org-imenu-depth 3)
Highlight
Highlighting of the current line (native mode)
1(require 'hl-line)
2(global-hl-line-mode)
PDF Tools
For retina display (OSX)
1;; (require 'pdf-tools)
2
3(add-hook 'doc-view-mode-hook 'pdf-tools-install)
4
5;; Using line numbers breaks the pdf-viewer
6(add-hook 'pdf-view-mode-hook (lambda () (nlinum-mode -1)))
7
8(setq-default pdf-view-use-scaling t
9 pdf-view-use-imagemagick nil)
Benchmark
1(rougier/report-time "Editing")
Minibuffer & Modeline
1(setq rougier/section-start-time (current-time))
General
Display time in modeline
1(display-time-mode 1) ; display time in minibar
Consult
We replace some of emacs functions with their consult equivalent
1(require 'consult)
2(setq consult-preview-key nil) ; No live preview
3
4(bind-key "C-x C-r" #'consult-recent-file)
5(bind-key "C-x h" #'consult-outline)
6(bind-key "C-x b" #'consult-buffer)
7(bind-key "C-c h" #'consult-history)
8;; (bind-key "M-:" #'consult-complex-command)
For the consult-goto-line and consult-line commands, we define our owns with live preview (independently of the consult-preview-key)
1(defun rougier/consult-line ()
2 "Consult line with live preview"
3
4 (interactive)
5 (let ((consult-preview-key 'any)
6 (mini-frame-resize 'grow-only)) ;; !! Important
7 (consult-line)))
8
9(bind-key "C-s" #'rougier/consult-line)
1(defun rougier/consult-goto-line ()
2 "Consult goto line with live preview"
3
4 (interactive)
5 (let ((consult-preview-key 'any))
6 (consult-goto-line)))
7
8(bind-key "M-g g" #'rougier/consult-goto-line)
9(bind-key "M-g M-g" #'rougier/consult-goto-line)
Extra packages for consult projects
1(require 'consult-project-extra)
Enable binding with projectile (project-management)
1(require 'consult-projectile)
2(consult projectile)
Vertico
Vertico provides a performant and minimalistic vertical completion UI based on the default completion system but aims to be highly flexible, extensible and modular.
1(require 'vertico)
2;; (setq completion-styles '(basic substring partial-completion flex))
3(setq vertico-resize nil ; How to resize the Vertico minibuffer window.
4 vertico-count 8 ; Maximal number of candidates to show.
5 vertico-count-format nil) ; No prefix with number of entries
6
7(vertico-mode)
Tweaking settings
1(setq vertico-grid-separator
2 #(" | " 2 3 (display (space :width (1))
3 face (:background "#ECEFF1")))
4
5 vertico-group-format
6 (concat #(" " 0 1 (face vertico-group-title))
7 #(" " 0 1 (face vertico-group-separator))
8 #(" %s " 0 4 (face vertico-group-title))
9 #(" " 0 1 (face vertico-group-separator
10 display (space :align-to (- right (-1 . right-margin) (- +1)))))))
11
12(set-face-attribute 'vertico-group-separator nil
13 :strike-through t)
14(set-face-attribute 'vertico-current nil
15 :inherit '(default shadow))
16(set-face-attribute 'completions-first-difference nil
17 :inherit '(default))
Bind shift-tab for completion
1(bind-key "<backtab>" #'minibuffer-complete vertico-map)
Completion-at-point and completion-in-region (see https://github.com/minad/vertico#completion-at-point-and-completion-in-region)
1(setq completion-in-region-function
2 (lambda (&rest args)
3 (apply (if vertico-mode
4 #'consult-completion-in-region
5 #'completion--in-region)
6 args)))
Prefix the current candidate (See https://github.com/minad/vertico/wiki#prefix-current-candidate-with-arrow)
1(defun minibuffer-format-candidate (orig cand prefix suffix index _start)
2 (let ((prefix (if (= vertico--index index)
3 " "
4 " ")))
5 (funcall orig cand prefix suffix index _start)))
6
7(advice-add #'vertico--format-candidate
8 :around #'minibuffer-format-candidate)
1(defun vertico--prompt-selection ()
2 "Highlight the prompt"
3
4 (let ((inhibit-modification-hooks t))
5 (set-text-properties (minibuffer-prompt-end) (point-max)
6 '(face (bold highlight)))))
See https://github.com/minad/vertico/issues/145
1(defun minibuffer-vertico-setup ()
2
3 (setq truncate-lines t)
4 (setq completion-in-region-function
5 (if vertico-mode
6 #'consult-completion-in-region
7 #'completion--in-region)))
8
9(add-hook 'vertico-mode-hook #'minibuffer-vertico-setup)
10(add-hook 'minibuffer-setup-hook #'minibuffer-vertico-setup)
Recommended settings to work with vertico for tramp-ssh remote files
1(setq completion-styles '(orderless basic)
2 completion-category-overrides '((file (styles basic partial-completion))))
Marginalia
Pretty straightforward.
1(require 'marginalia)
2
3(setq-default marginalia-ellipsis "…" ; Nicer ellipsis
4 marginalia-align 'right ; right alignment
5 marginalia-align-offset -1) ; one space on the right
6
7(marginalia-mode)
Minibuffer
Miniframe
1(require 'mini-frame)
2
3(defcustom rougier/minibuffer-position 'bottom
4 "Minibuffer position, one of 'top or 'bottom"
5 :type '(choice (const :tag "Top" top)
6 (const :tag "Bottom" bottom))
7 :group 'nano-minibuffer)
8
9
10(defun rougier/minibuffer--frame-parameters ()
11 "Compute minibuffer frame size and position."
12
13 ;; Quite precise computation to align the minibuffer and the
14 ;; modeline when they are both at top position
15 (let* ((edges (window-pixel-edges)) ;; (left top right bottom)
16 (body-edges (window-body-pixel-edges)) ;; (left top right bottom)
17 (left (nth 0 edges)) ;; Take margins into account
18 (top (nth 1 edges)) ;; Drop header line
19 (right (nth 2 edges)) ;; Take margins into account
20 (bottom (nth 3 body-edges)) ;; Drop header line
21 (left (if (eq left-fringe-width 0)
22 left
23 (- left (frame-parameter nil 'left-fringe))))
24 (right (nth 2 edges))
25 (right (if (eq right-fringe-width 0)
26 right
27 (+ right (frame-parameter nil 'right-fringe))))
28 (border 1)
29 (width (- right left (* 1 border)))
30
31 ;; Window divider mode
32 (width (- width (if (and (bound-and-true-p window-divider-mode)
33 (or (eq window-divider-default-places 'right-only)
34 (eq window-divider-default-places t))
35 (window-in-direction 'right (selected-window)))
36 window-divider-default-right-width
37 0)))
38 (y (- top border)))
39
40 (append `((left-fringe . 0)
41 (right-fringe . 0)
42 (user-position . t)
43 (foreground-color . ,(face-foreground 'highlight nil 'default))
44 (background-color . ,(face-background 'highlight nil 'default)))
45 (cond ((and (eq rougier/minibuffer-position 'bottom))
46 `((top . -1)
47 (left . 0)
48 (width . 1.0)
49 (child-frame-border-width . 0)
50 (internal-border-width . 0)))
51 (t
52 `((left . ,(- left border))
53 (top . ,y)
54
55 (width . (text-pixels . ,width))
56 (child-frame-border-width . ,border)
57 (internal-border-width . 0)))))))
58
59 (set-face-background 'child-frame-border (face-foreground 'shadow))
60 (setq mini-frame-default-height 3)
61 (setq mini-frame-create-lazy t)
62 (setq mini-frame-show-parameters 'rougier/minibuffer--frame-parameters)
63 (setq mini-frame-ignore-commands
64 '("edebug-eval-expression" debugger-eval-expression))
65 (setq mini-frame-internal-border-color (face-foreground 'shadow))
66
67 (setq mini-frame-resize-min-height 3)
68 (setq mini-frame-resize t)
69 ;; (setq mini-frame-resize 'grow-only)
70 ;; (setq mini-frame-default-height (+ 1 vertico-count))
71 ;; (setq mini-frame-resize-height (+ 1 vertico-count))
72 ;; (setq mini-frame-resize nil)
Mini-frame mode OFF
1;; (mini-frame-mode 1)
More a hack than a fix but the code below improve the mini-frame resize by setting position explicity. CURRENTLY INACTIVE
1(defun rougier/mini-frame--resize-mini-frame (frame)
2 "Resize FRAME vertically only.
3This function used as value for `resize-mini-frames' variable."
4 (funcall mini-frame--fit-frame-function
5 frame
6 mini-frame-resize-max-height
7 (if (eq mini-frame-resize 'grow-only)
8 (max (frame-parameter frame 'height)
9 mini-frame-resize-min-height)
10 mini-frame-resize-min-height)
11 ;; A max-width must be included to work around a bug in Emacs which
12 ;; causes wrapping to not be taken into account in some situations
13 ;; https://debbugs.gnu.org/cgi/bugreport.cgi?bug=56102
14 (window-body-width)
15 nil
16 'vertically)
17
18 (if (eq rougier/minibuffer-position 'top)
19 (modify-frame-parameters mini-frame-completions-frame `((top . 0)))
20 (modify-frame-parameters mini-frame-completions-frame `((top . (- 1))))))
Modeline
Get modeline from spaceline
1(require 'spaceline)
2(require 'spaceline-config)
3
4(spaceline-spacemacs-theme)
5
6(spaceline-toggle-minor-modes-off)
7
8(setq powerline-default-separator 'arrow-fade)
Benchmark
1(rougier/report-time "Modeline")
Programming
1(setq rougier/section-start-time (current-time))
General
Use yasnippets for generating useful snippets very useful in tandem with yasnippet-snippets package
1(require 'yasnippet)
2(yas-global-mode 1) ; Enable yasnippets globally
3(setq yas-indent-line 'auto) ; the other option is the value: 'fixed
1(add-to-list 'auto-mode-alist '("[Mm]akefile\\'" . makefile-gmake-mode))
Workflow
Snakemake
1(require 'snakemake-mode)
2;; Enable snake mode
3(add-to-list 'auto-mode-alist '("\\.smk\\'" . snakemake-mode))
4(add-to-list 'auto-mode-alist '("[Ss]nakefile\\'" . snakemake-mode))
C/C++
Linux C standards
1(defun linux-c-mode ()
2"C mode with adjusted defaults for use with the Linux
3kernel."
4(interactive)
5(c-mode)
6(setq c-indent-level 8)
7(setq c-brace-imaginary-offset 0)
8(setq c-brace-offset -8)
9(setq c-argdecl-indent 8)
10(setq c-label-offset -8)
11(setq c-continued-statement-offset 8)
12(setq indent-tabs-mode nil)
13(setq tab-width 8))
14This will define the M-x linux-c-mode command. When hacking on a module, if
15you put the string -*- linux-c -*- somewhere on the first two lines, this mode
16will be automatically invoked. Also, you may want to add
17(setq auto-mode-alist (cons '("/usr/src/linux.*/.*\\.[ch]
18$" . linux-c-mode)
19auto-mode-alist))
Lisp
Python
Configuration that helps writing python code a better experience.
List of requirements are:
- Code completion
- Documentation
- Jump to definition
- Send region/buffer to REPL (interpreted languages)
- Identification of code issues
- Auto format/organize/clean code
- https://github.com/dadadel/pyment
Set python environment path
1(setenv "PYTHONPATH" (shell-command-to-string "$SHELL --login -c 'echo -n $PYTHONPATH'"))
Setup elpy, in order to use all the features (such as navigation with M-.), you’ll need to install some python libraries:
1pip install flake8 snakeviz
2# For linux
3sudo apt install python3-jedi black python3-autopep8 yapf3 python3-yapf
4# For mac
5brew install python3-jedi black python3-autopep8 yapf3 python3-yapf
Use snakeviz to profile code with `elpy-profile-buffer-or-region`
1(require 'elpy)
2(with-eval-after-load 'elpy
3 (delete 'elpy-module-yasnippet elpy-modules))
4
5(elpy-enable)
6
7(setq elpy-rpc-python-command "python")
8(setq elpy-remove-modeline-lighter nil)
9(setq elpy-rpc-backend "jedi") ; auto-completed backend
10(setq python-check-command "flake8") ; Syntax checker
11
12(setq python-shell-interpreter "ipython"
13 python-shell-interpreter-args "-i --simple-prompt"
14 python-shell-prompt-detect-failure-warning nil)
15(add-to-list 'python-shell-completion-native-disabled-interpreters
16 "ipython")
17
18;; remove highlight-indentation
19(setq elpy-modules (delq 'elpy-module-highlight-indentation elpy-modules))
Setup flycheck with elpy
1(require 'flycheck)
2
3(when (require 'flycheck nil t)
4 (setq elpy-modules (delq 'elpy-module-flymake elpy-modules))
5 (add-hook 'elpy-mode-hook 'flycheck-mode))
Enforce column limits
1;; COLUMN ENFORCEMENT
2(require 'fill-column-indicator)
3(add-hook 'python-mode-hook 'fci-mode)
4(require 'column-enforce-mode)
5(add-hook 'python-mode-hook 'column-enforce-mode)
6(setq column-enforce-column 88)
Setup python virtual environments
1(require 'pyenv-mode)
2(pyenv-mode)
3
4;; remove default keybindings
5(unbind-key "C-c C-s" pyenv-mode-map)
6(unbind-key "C-c C-u" pyenv-mode-map)
7
8(setenv "WORKON_HOME" (concat (expand-file-name "~/.virtualenvs/versions/") (shell-command-to-string "echo $(pyenv version-name) | tr -d '\n'")))
9(setenv "VIRTUALENVWRAPPER_HOOK_DIR" (concat (expand-file-name "~/.virtualenvs/versions/") (shell-command-to-string "echo $(pyenv version-name) | tr -d '\n'")))
Setup pyvenv
1;; (setq pyvenv-exec-shell "/bin/zsh")
2;; (setq pyvenv-virtualenvwrapper-python (shell-command-to-string "echo $(pyenv which python)"))
Setup sphinx-doc for sphinx compatible docstrings and documenting
1(add-hook 'python-mode-hook (lambda ()
2 (require 'sphinx-doc)
3 (sphinx-doc-mode t)))
4(setq sphinx-doc-include-types t)
Add python code folding hook with hideshow minor mode
1(add-hook 'python-mode-hook 'hs-minor-mode)
Use isortify to sort python imports according to pep8 standards.
1(require 'isortify)
Cython
Setup for cython mode
1
2(require 'cython-mode)
3
4(autoload 'cython-mode "cython-mode" "Mode for editing Cython source files")
5
6(add-to-list 'auto-mode-alist '("\\.pyx\\'" . cython-mode))
7(add-to-list 'auto-mode-alist '("\\.pxd\\'" . cython-mode))
8(add-to-list 'auto-mode-alist '("\\.pxi\\'" . cython-mode))
Setup flycheck for cython mode
1
2(require 'flycheck)
3
4(add-hook 'cython-mode-hook 'flycheck-mode)
xml
Configure nxml mode
1;; (add-hook 'nxml-mode-hook (lambda () (line-number-mode 0)))
2;; (add-hook 'nxml-mode-hook (lambda () (linum-mode 0)))
3(add-hook 'nxml-mode-hook (lambda () (undo-tree-mode -1)))
yaml
1(require 'yaml-mode)
2
3; If you wish to have Return key automatically indent cursor on new line
4(add-hook 'yaml-mode-hook
5 (lambda ()
6 (define-key yaml-mode-map "\C-m" 'newline-and-indent))
7 )
Latex
1(require 'smartparens-latex)
2
3(defun apm-latex-mode-setup ()
4 "Tweaks and customisations for LaTeX mode."
5 (turn-on-auto-fill)
6 (abbrev-mode +1)
7 ;; smartparens latex support
8 (smartparens-mode +1)
9 ;; Enable source-correlate for Control-click forward/reverse search.
10 (TeX-source-correlate-mode 1)
11 ;; enable math mode in latex
12 (LaTeX-math-mode 1)
13 ;; Enable reftex
14 (turn-on-reftex)
15 ;; integrate with company
16 (company-auctex-init)
17 )
18
19(require 'tex-site)
20
21(require 'company-auctex)
22(company-auctex-init)
23
24(setq-default TeX-auto-save t
25 TeX-parse-self t
26 TeX-PDF-mode t
27 reftex-plug-into-AUCTeX t
28 TeX-source-correlate-start-server t
29 TeX-master nil
30 )
31
32(add-hook 'LaTeX-mode-hook #'apm-latex-mode-setup)
33
34(add-hook 'LaTeX-mode-hook
35 (lambda ()
36 (font-latex-add-keywords '(("citep" "*[[{")) 'reference)
37 (font-latex-add-keywords '(("citet" "*[[{")) 'reference)
38 (font-latex-add-keywords '(("autoref" "*[[{")) 'reference))
39 )
40
41(setq TeX-command-extra-options "-shell-escape")
Add support for formatting latex text to one sentence per line with ospl mode. This helps tracking changes easier and better.
1(add-hook 'LaTeX-mode-hook 'ospl-mode)
1(add-hook 'LaTeX-mode-hook 'olivetti-mode)
nim
1;; (require 'nim-mode)
Jinja
1(message "Personal config :. jinja...")
2;; Jinja
3(use-package mmm-jinja2
4 :straight t)
5(use-package jinja2-mode
6 :straight t)
7(load "~/.emacs.d/elpa/mmm-jinja2-20170313.1420/mmm-jinja2.el")
8(add-to-list 'auto-mode-alist '("\\.jinja2\\.wbt'" . html-mode))
9(mmm-add-mode-ext-class 'html-mode "\\.jinja2\\.wbt'" 'jinja2)
10
11
12(add-to-list 'auto-mode-alist '("\\.jinja2\\'" . yaml-mode))
13(mmm-add-mode-ext-class 'yaml-mode "\\.jinja2\\'" 'jinja2)
Godot
Formatting code with gdformat requires installing gdtoolkit
1pip install gdtoolkit
1(setq gdscript-godot-executable "/path/to/godot")
GL
GLSL
1(require 'glsl-mode)
2(add-to-list 'auto-mode-alist '("\\.glsl\\'" . glsl-mode))
Benchmark
1
2(rougier/report-time "Programming")
Completion
1
2(setq rougier/section-start-time (current-time))
Company
Company is a text completion framework for Emacs. The name stands for “complete anything”. It uses pluggable back-ends and front-ends to retrieve and display completion candidates.
http://company-mode.github.io/
1;; (add-hook 'after-init-hook 'global-company-mode)
2
3(bind-key "C-c i" #'company-complete)
4
5(add-hook 'emacs-lisp-mode-hook
6 (lambda ()
7 (paredit-mode t)
8 (rainbow-delimiters-mode t)
9 (show-paren-mode 1)
10 ))
11
12(add-hook 'lisp-interaction-mode
13 (lambda ()
14 (paredit-mode t)
15 (rainbow-delimiters-mode t)
16 (show-paren-mode 1)
17 ))
Corfu
Corfu enhances completion at point with a small completion popup.
1
2(require 'corfu)
3
4(setq corfu-cycle t ; Enable cycling for `corfu-next/previous'
5 corfu-auto t ; Enable auto completion
6 corfu-auto-delay 60.0 ; Delay before auto-completion shows up
7 corfu-separator ?\s ; Orderless field separator
8 corfu-quit-at-boundary nil ; Never quit at completion boundary
9 corfu-quit-no-match t ; Quit when no match
10 corfu-preview-current nil ; Disable current candidate preview
11 corfu-preselect-first nil ; Disable candidate preselection
12 corfu-on-exact-match nil ; Configure handling of exact matches
13 corfu-echo-documentation nil ; Disable documentation in the echo area
14 corfu-scroll-margin 5) ; Use scroll margin
15
16(global-corfu-mode)
A few more useful configurations…
1
2;; TAB cycle if there are only few candidates
3(setq completion-cycle-threshold 3)
4
5;; Emacs 28: Hide commands in M-x which do not apply to the current mode.
6;; Corfu commands are hidden, since they are not supposed to be used via M-x.
7(setq read-extended-command-predicate
8 #'command-completion-default-include-p)
9
10;; Enable indentation+completion using the TAB key.
11;; completion-at-point is often bound to M-TAB.
12(setq tab-always-indent 'complete)
13
14;; Completion in source blocks
15(require 'cape)
16
17(add-to-list 'completion-at-point-functions 'cape-symbol)
Orderless
Allow completion based on space-separated tokens, out of order.
1
2(require 'orderless)
3
4(setq completion-styles '(substring orderless basic)
5 orderless-component-separator 'orderless-escapable-split-on-space
6 read-file-name-completion-ignore-case t
7 read-buffer-completion-ignore-case t
8 completion-ignore-case t)
Benchmark
1
2(rougier/report-time "Completion")
Writing
1(setq rougier/section-start-time (current-time))
English
Tools and setup for making writing articles enjoyable and easy
Whisper
1;; Speech to text
2(require 'whisper)
3
4(bind-key "C-c r" #'whisper-run)
5(bind-key "C-c f" #'whisper-file)
6
7(setq whisper-install-directory "~/softwares/install/speech2text/" ;; "/tmp/"
8 whisper-model "base" ;; "medium" was tested but is too slow
9 whisper-language "en"
10 whisper-translate nil)
Langtool
- https://emacstil.com/til/2022/03/06/run-grammar-check-on-org-buffers-automatically-with-languagetool/
- https://dev.languagetool.org/http-server.html
1(require 'langtool)
2
3(bind-key "\C-x4w" #'langtool-check)
4(bind-key "\C-x4W" #'langtool-check-done)
5(bind-key "\C-x4l" #'langtool-switch-default-language)
6(bind-key "\C-x44" #'langtool-show-message-at-point)
7(bind-key "\C-x4c" #'langtool-correct-buffer)
8
9(setq langtool-java-classpath "/opt/homebrew/Cellar/languagetool:/opt/homebrew/Cellar/languagetool/6.5/*")
10(setq langtool-language-tool-jar "/opt/homebrew/Cellar/languagetool/6.5/libexec/languagetool-commandline.jar")
11(setq langtool-language-tool-server-jar "/opt/homebrew/Cellar/languagetool/6.5/libexec/languagetool-server.jar")
12(setq langtool-server-user-arguments '("-p" "8081" "--config" "~/.config/server.properties"))
13(setq langtool-http-server-host "localhost")
14(setq langtool-http-server-port 8081)
15
16;; Text suggestions
17(require 'flycheck-languagetool)
18
19(setq flycheck-languagetool-server-jar "/opt/homebrew/Cellar/languagetool/6.5/libexec/languagetool-server.jar")
20(setq flycheck-languagetool-server-port "8081")
21(setq flycheck-languagetool-language "en-GB")
22
23;; (add-hook 'text-mode-hook #'flycheck-languagetool-setup)
24;; (add-hook 'LaTeX-mode-hook #'flycheck-languagetool-setup)
25;; (add-hook 'org-mode-hook #'flycheck-languagetool-setup)
26;; (add-hook 'org-mode-hook 'waveparticle/langtool-autosave-hook)
27;; (add-hook 'text-mode-hook 'waveparticle/langtool-autosave-hook)
28;; (add-hook 'LaTeX-mode-hook 'waveparticle/langtool-autosave-hook)
Proselint : Requires system installation first
`pip install proselint`
1(require 'flycheck)
2
3(flycheck-define-checker proselint
4 "A linter for prose."
5 :command ("proselint" source-inplace)
6 :error-patterns
7 ((warning line-start (file-name) ":" line ":" column ": "
8 (id (one-or-more (not (any " ")))) (message) line-end))
9 :modes (gfm-mode
10 markdown-mode
11 org-mode
12 text-mode
13 latex-mode))
14 ;; :next-checkers ((warning . valec)))
Vale: Requires system installation first
`brew install vale`
- https://vale.sh/docs/vale-cli/installation/
- https://emacstil.com/til/2022/03/05/setting-up-vale-prose-linter-on-emacs/
1(flycheck-define-checker valec
2 "A checker for prose"
3 :command ("vale" "--output" "line" source)
4 :standard-input nil
5 :error-patterns
6 ((error line-start (file-name) ":" line ":" column ":"
7 (id (one-or-more (not (any ":")))) ":" (message) line-end))
8 :modes (markdown-mode
9 org-mode
10 text-mode
11 latex-mode))
12(add-to-list 'flycheck-checkers 'valec 'append)
Writegood-mode
1(require 'writegood-mode)
2
3(bind-key "C-c g" #'writegood-mode)
4(bind-key "C-c C-g C-g" #'writegood-grade-level)
5(bind-key "C-c C-g C-e" #'writegood-reading-ease)
6
7(add-hook 'org-mode-hook #'writegood-mode)
Smog: Requires system installation first
`brew install style`
1(require 'smog)
2
3(setq smog-command "style -L en")
Powerthesaurus
Markdown
1(add-hook 'markdown-mode-hook #'ospl-mode)
Benchmark
1(rougier/report-time "Writing")
AI
GPTel
1;; Use Ollama models instead of ChatGPT
2;; OPTIONAL configuration
3(setq
4 gptel-model '"deepseek-coder:6.7b"
5 gptel-backend (gptel-make-ollama "Ollama"
6 :host "localhost:11434"
7 :stream t
8 :models '("deepseek-coder:6.7b")))
RESOURCES
https://github.com/captainflasmr/ollama-buddy
A friendly Emacs interface for interacting with Ollama models. This package provides a convenient way to integrate Ollama’s local LLM capabilities directly into your Emacs workflow with little or no configuration required.
Org
1(setq rougier/section-start-time (current-time))
General
1(setq-default
2 org-directory "~/projects/personal/org/core" ; Default org files
3 org-ellipsis " ·" ; Nicer ellipsis
4 org-hide-emphasis-markers t ; Hide markers
5 org-hide-leading-stars t ; Hide leading stars
6 org-adapt-indentation nil
7 org-cycle-separator-lines 0 ; Number of empty lines between sections
8 org-use-tag-inheritance nil ; Tags ARE NOT inherited
9 org-use-property-inheritance t ; Properties ARE inherited
10 org-indent-indentation-per-level 2 ; Indentation per level
11 org-indent-mode nil ; Org identation for better readability
12 org-startup-indented t ; Startup indent
13 org-startup-folded 'show2levels ; Startup in folded view.
14 org-link-use-indirect-buffer-for-internals t ; Indirect buffer for internal links
15 org-fontify-quote-and-verse-blocks t ; Specific face for quote and verse blocks
16 org-src-fontify-natively t ; fontify src blocks
17 org-src-tab-acts-natively t
18 org-src-preserve-indentation nil ; Preserve indentation for exporting
19 org-fontify-whole-block-delimiter-line t ; Fontify whole block
20 org-edit-src-content-indentation 0
21 org-return-follows-link nil ; Follow links when hitting return
22 org-image-actual-width nil ; Resize image to window width
23 org-indirect-buffer-display 'other-window ; Tab on a task expand it in a new window
24 org-outline-path-complete-in-steps nil ; No steps in path display
25 org-list-allow-alphabetical t ; Allow alphabets in org list
26 org-fold-catch-invisible-edits nil ; Avoid editing invisible fields in org-mode
27 org-list-demote-modify-bullet '(("+" . "-") ("-" . "+") ("*" . "+") ("1." . "a.")) ; Set the order of list symbols
28 org-tags-column -80 ; Set the tags alignment (88 following black!)
29 org-auto-align-tags t
30 org-catch-invisible-edits 'show-and-error ; Disable invisible edits
31 org-pretty-entities t ; insert special characters LaTeX-style
32 org-confirm-babel-evaluate nil ; No confirmation before executing code
33 org-blank-before-new-entry '((heading) (plain-list-item . auto))
34 org-archive-location ".%s_archive::" ; Org archive files are hidden
35 )
Better latex preview (see https://stackoverflow.com/questions/30151338)
1(setq org-latex-create-formula-image-program 'dvisvgm)
We adapt fill functions according to the indent level.
1(defun rougier/calc-offset-on-org-level ()
2 "Calculate offset (in chars) on current level in org mode file."
3
4 (* (or (org-current-level) 0) org-indent-indentation-per-level))
5
6(defun rougier/org-fill-paragraph (&optional justify region)
7 "Calculate apt fill-column value and fill paragraph."
8
9 (let* ((fill-column (- fill-column (rougier/calc-offset-on-org-level))))
10 (org-fill-paragraph justify region)))
11
12(defun rougier/org-auto-fill-function ()
13 "Calculate apt fill-column value and do auto-fill"
14
15 (let* ((fill-column (- fill-column (rougier/calc-offset-on-org-level))))
16 (org-auto-fill-function)))
17
18(defun rougier/org-mode-hook ()
19 (setq fill-paragraph-function #'rougier/org-fill-paragraph
20 normal-auto-fill-function #'rougier/org-auto-fill-function))
21
22(add-hook 'org-load-hook 'rougier/org-mode-hook)
23(add-hook 'org-mode-hook 'rougier/org-mode-hook)
Org bullets to replace stars * with better symbols
1(require 'org-bullets)
2(add-hook 'org-mode-hook (lambda () (org-bullets-mode 1)))
1;; Hide org markup for README
2(setq org-hide-emphasis-markers t)
Add better looking icons for org tasks
1(defun org-icons ()
2 "Beautify org mode keywords."
3 (setq prettify-symbols-alist '(("TODO" . "")
4 ("WAIT" . "")
5 ("NOPE" . "")
6 ("DONE" . "")
7 ("CONTACT" . "")
8 ("[#A]" . "")
9 ("[#B]" . "")
10 ("[#C]" . "")
11 ("[ ]" . "")
12 ("[X]" . "")
13 ("[-]" . "")
14 ("#+BEGIN_SRC" . "")
15 ("#+END_SRC" . "―")
16 ("#+begin_src" . "")
17 ("#+end_src" . "―")
18 (":PROPERTIES:" . "")
19 (":END:" . "―")
20 ("#+STARTUP:" . "")
21 ("#+TITLE: " . "")
22 ("#+RESULTS:" . "")
23 ("#+NAME:" . "")
24 ("#+ROAM_TAGS:" . "")
25 ("#+FILETAGS:" . "")
26 ("#+HTML_HEAD:" . "")
27 ("#+SUBTITLE:" . "")
28 ("#+AUTHOR:" . "")
29 (":Effort:" . "")
30 ("SCHEDULED:" . "")
31 ("DEADLINE:" . "")
32 ))
33 (prettify-symbols-mode))
34
35(add-hook 'org-mode-hook 'org-icons)
org modern look
1(with-eval-after-load 'org (global-org-modern-mode))
Fix for missing unicode symbol in org-modern
1(setq org-modern-fold-stars
2 '(("▶" . "▼")
3 ("▷" . "▽")
4 ("⏵" . "⏷")
5 ("▹" . "▿")
6 ("▸" . "▾")))
1(setq org-modern-table nil)
2(setq org-modern-table-vertical nil)
3(setq org-modern-table-horizontal nil)
1(add-hook 'org-mode-hook 'org-appear-mode)
1(add-hook 'org-mode-hook 'olivetti-mode)
1(add-hook 'org-mode-hook 'ospl-mode)
Key bindings
Org mode specific keybindings
1(bind-key "C-c !" #'org-time-stamp-inactive)
Encryption
1;; Enable org-crypt
2(require 'org-crypt)
3(org-crypt-use-before-save-magic)
4
5;; Set default GPG key to use for encryption
6;; Replace with your key ID from gpg --list-secret-keys
7(setq org-crypt-key "shravantr@gmail.com")
8
9;; Disable backup files for encrypted .org files
10(setq backup-directory-alist
11 `((".*" . ,temporary-file-directory)))
12(setq auto-save-file-name-transforms
13 `((".*" ,temporary-file-directory t)))
14
15;; Don't write sensitive data to disk in clear text
16(setq auth-sources
17 '((:source "~/.emacs.d/secrets/.authinfo.gpg")))
18
19;; Encrypt all entries with the "crypt" tag
20(setq org-tags-exclude-from-inheritance (quote ("crypt")))
21
22;; Use minibuffer for GPG password prompt
23(setq epg-pinentry-mode 'loopback)
24
25;; Allow GPG to prompt for passphrase in Emacs
26(setenv "GPG_AGENT_INFO" nil)
27
28;; Force GPG to use minibuffer for password
29(setq epg-gpg-program "gpg") ; or "gpg" depending on your system
30
31;; GPG key selection options
32(setq epa-file-encrypt-to nil)
33(setq epa-file-select-keys nil)
34
35;; Auto-save settings for encrypted files
36(setq org-crypt-disable-auto-save t)
37
38;; Function to encrypt all marked regions in a file
39(defun org-encrypt-all-entries ()
40 "Encrypt all top-level entries in the current file."
41 (interactive)
42 (org-map-entries
43 (lambda ()
44 (org-encrypt-entry)
45 (message "Encrypted entry %s" (org-get-heading t t t t)))
46 "crypt" 'file))
47
48;; Function to decrypt all entries temporarily
49(defun org-decrypt-all-entries ()
50 "Decrypt all entries in the current file."
51 (interactive)
52 (org-map-entries
53 (lambda ()
54 (org-decrypt-entry)
55 (message "Decrypted entry %s" (org-get-heading t t t t)))
56 "crypt" 'file))
echo GETPIN | pinentry-mac
Fixes
Have to downgrade to version 2.4.0 or below. Currently the easiest to do on MacOS is brew install gnupg@2.2.0
- https://www.masteringemacs.org/article/keeping-secrets-in-emacs-gnupg-auth-sources
- https://www.reddit.com/r/emacs/comments/18d6fmt/how_to_lock_yourself_out_of_a_gpg_encrypted_file/
- https://www.reddit.com/r/emacs/comments/137r7j7/comment/jley3s5/?utm_source=share&utm_medium=web3x&utm_name=web3xcss&utm_term=1&utm_content=share_button
For documentation,
Resources
-
Useful commands
- gpg-connect-agent reloadagent /bye
Templates
1;; This is needed as of Org 9.2
2(require 'org-tempo)
3
4(add-to-list 'org-structure-template-alist '("sh" . "src sh"))
5(add-to-list 'org-structure-template-alist '("el" . "src emacs-lisp"))
6(add-to-list 'org-structure-template-alist '("py" . "src python"))
7(add-to-list 'org-structure-template-alist '("tex" . "src latex"))
8(add-to-list 'org-structure-template-alist '("go" . "src go"))
9(add-to-list 'org-structure-template-alist '("yaml" . "src yaml"))
10(add-to-list 'org-structure-template-alist '("json" . "src json"))
Babel
1;; Set languages org-babel supports
2(org-babel-do-load-languages
3 'org-babel-load-languages
4 (quote
5 ((awk .t)
6 (ditaa .t)
7 (shell .t)
8 (python .t)
9 (latex .t)
10 (emacs-lisp .t)))
11 )
Citations
Org 9.5 and above has native support for citations with `org-cite` package.
Links for reference:
- https://blog.tecosaur.com/tmio/2021-07-31-citations.html
- https://kristofferbalintona.me/posts/202206141852/
- https://github.com/jkitchin/org-ref
- https://github.com/emacs-citar/citar
- https://rgoswami.me/posts/org-note-workflow/#bibliography
1
2(require 'bibtex)
3
4(setq org-cite-export-processors
5 '((md . (csl "chicago-fullnote-bibliography.csl")) ; Footnote reliant
6 (latex . biblatex) ; For humanities
7 (odt . (csl "chicago-fullnote-bibliography.csl")) ; Footnote reliant
8 (t . (csl "modern-language-association.csl")) ; Fallback
9 ))
1(require 'org-ref)
Notes
Writing and reading notes with org
- https://github.com/weirdNox/org-noter
- https://rgoswami.me/posts/org-note-workflow/#org-ref
- https://zettelkasten.de/introduction/
Exports
Setup default list of exporters
1
2(setq org-export-backends '(ascii beamer html icalendar latex md odt))
Setup latex exports
1;; Setup to run with minted packages to embed code in latex exports
2(setq org-latex-pdf-process
3 '("pdflatex -shell-escape -interaction nonstopmode -output-directory %o %f"
4 "pdflatex -shell-escape -interaction nonstopmode -output-directory %o %f"
5 "pdflatex -shell-escape -interaction nonstopmode -output-directory %o %f"))
Export code with syntax highlighting using minted. Has a system dependency!
1(setq org-latex-listings 'minted)
2(setq org-latex-minted-options
3 '(("frame" "lines") ("linenos=true")))
Blog
1(require 'ox-hugo)
Getting Things Done (GTD)
Configure the refile file location to capture the notes
1(setq org-directory "~/projects/personal/org/core/")
2(setq org-agenda-files (list "refile.org"))
Setup a simple org capture template
1(setq org-capture-templates
2 `(("i" "Inbox" entry (file "refile.org")
3 ,(concat "* TODO %?\n" "/Entered on/ %U"))))
and setup a keyboard shortcut (C-c c):
1(define-key global-map (kbd "C-c c") 'org-capture)
TASKS
1(setq org-todo-keywords
2 (quote ((sequence "TODO(t)" "WORKING(w)" "|" "DONE(d)" "DELEGATED(e@)")
3 (sequence "HOLD(h@/!)" "FUTURE(f@/!)" "|" "CANCELLED(c@/!)" "PHONE(p@)" "MEETING(m@)")
4 (sequence "BUY(b)" "|" "DROPPED(x@/!)" "BOUGHT(o)")
5 (sequence "CONTACT(k)" "|" "DROPPED(x@/!)" "CONTACTED(j@/!)")
6 )))
1(setq org-todo-keyword-faces
2 (quote (("TODO" :foreground "red" :weight bold)
3 ("WORKING" :foreground "orange" :weight bold)
4 ("DONE" :foreground "forest green" :weight bold)
5 ("HOLD" :foreground "yellow" :weight bold)
6 ("FUTURE" :foreground "magenta" :weight bold)
7 ("CANCELLED" :foreground "forest green" :weight bold)
8 ("MEETING" :foreground "forest green" :weight bold)
9 ("PHONE" :foreground "forest green" :weight bold)
10 ("CONTACT" :foreground "blue" :weight bold)
11 )
12 )
13 )
RESOURCES
Benchmark
1(rougier/report-time "Org")
Agenda
General
Load libraries.
1(require 'org-agenda)
2(require 'org-agenda-property)
Open agenda(s)
1(bind-key "C-c a" #'org-agenda)
Files
1(setq org-agenda-files
2 '(
3 "~/projects/personal/org/work/"
4 "~/projects/personal/org/work/career/"
5 "~/projects/personal/org/work/dev/"
6 "~/projects/personal/org/work/research/"
7 "~/projects/personal/org/personal/"
8 "~/projects/personal/org/personal/daily/"
9 "~/projects/personal/org/personal/lifestyle/"
10 "~/projects/personal/org/projects/"
11 "~/projects/personal/org/library/"
12 )
13 )
Settings
1(setq org-agenda-window-setup 'current-window
2 org-agenda-restore-windows-after-quit t
3 org-agenda-show-all-dates nil
4 org-agenda-time-in-grid t
5 org-agenda-show-current-time-in-grid t
6 org-agenda-start-on-weekday 1
7 org-agenda-span 7
8 org-agenda-hide-tags-regexp "." ; No tags
9 ; org-agenda-hide-tags-regexp nil) ; All tags
10 org-agenda-tags-column 0
11 ; org-agenda-tags-column -79) ; Left aling
12 org-agenda-block-separator nil
13 org-agenda-category-icon-alist nil
14 org-agenda-skip-deadline-if-done t
15 org-agenda-skip-scheduled-if-done t
16 org-agenda-sticky t)
Prefix format
1(setq org-agenda-prefix-format
2 '((agenda . "%i %?-12t%s")
3 (todo . "%i")
4 (tags . "%i")
5 (search . "%i")))
Sorting strategy
1(setq org-agenda-sorting-strategy
2 '((agenda deadline-down scheduled-down todo-state-up time-up
3 habit-down priority-down category-keep)
4 (todo priority-down category-keep)
5 (tags timestamp-up priority-down category-keep)
6 (search category-keep)))
Minimal time grid
1(setq org-agenda-time-grid
2 '((daily today require-timed)
3 ()
4 "......" "----------------"))
5
6(setq org-agenda-current-time-string " now")
Holidays
1(require 'cal-iso)
2(require 'holidays)
3
4(defvar us-holidays nil
5 "US holidays")
6
7(defvar india-holidays nil
8 "India holidays")
9
10(defvar birthdays nil
11 "Birthdays")
12
13(setq us-holidays
14 `((holiday-fixed 1 1 "New year's Day")
15 (holiday-fixed 5 1 "Labour Day")
16 (holiday-fixed 5 8 "Victory in Europe Day")
17 (holiday-fixed 7 14 "Bastille day")
18 (holiday-fixed 8 15 "Assumption of Mary")
19 (holiday-fixed 11 11 "Armistice 1918")
20 (holiday-fixed 11 1 "All Saints' Day")
21 (holiday-fixed 12 25 "Christmas Day")
22 (holiday-easter-etc 0 "Easter Sunday")
23 (holiday-easter-etc 1 "Easter Monday")
24 (holiday-easter-etc 39 "Ascension Day")
25 (holiday-easter-etc 50 "Whit Monday")
26 (holiday-sexp
27 '(if (equal
28 (holiday-easter-etc 49)
29 (holiday-float 5 0 -1 nil))
30 (car (car (holiday-float 6 0 1 nil)))
31 (car (car (holiday-float 5 0 -1 nil))))
32 "Mother's Day")))
33
34(setq calendar-holidays french-holidays ; French holidays
35 calendar-week-start-day 1 ; Week starts on Monday
36 calendar-mark-diary-entries-flag nil) ; Do not show diary entries
37
38; Mark today in calendar
39(add-hook 'calendar-today-visible-hook #'calendar-mark-today)
Week day name with holidays
1(defun rougier/org-agenda-format-date (date)
2 "Org agenda date format displaying holidays"
3 (let* ((dayname (calendar-day-name date))
4 (day (cadr date))
5 (month (car date))
6 (monthname (calendar-month-name month))
7 (year (nth 2 date))
8 (holidays (calendar-check-holidays date)))
9 (concat "\n"
10 dayname " "
11 (format "%d " day)
12 monthname " "
13 (format "%d" year)
14 (if holidays (format " (%s)" (nth 0 holidays)))
15 "\n")))
16
17(setq org-agenda-format-date #'rougier/org-agenda-format-date)
Daily agenda
The daily agenda
1(add-to-list 'org-agenda-custom-commands
2 '("a" "Agenda"
3 ((agenda "Agenda"
4 ((org-agenda-todo-keyword-format "%s")
5 (org-agenda-skip-deadline-if-done nil)
6 (org-deadline-warning-days 3)
7 (org-agenda-overriding-header nil))))))
Some decorations for the agenda
1(defun rougier/org-agenda-highlight-todo (x)
2 (let* ((done (string-match-p (regexp-quote ":DONE:") x))
3 (canceled (string-match-p (regexp-quote "~") x))
4 (x (replace-regexp-in-string ":TODO:" "" x))
5 (x (replace-regexp-in-string ":DONE:" "" x))
6 (x (replace-regexp-in-string "~" "" x))
7 (x (if (and (boundp 'org-agenda-dim) org-agenda-dim)
8 (propertize x 'face 'nano-faded) x))
9 (x (if done (propertize x 'face 'nano-faded) x))
10 (x (if canceled (propertize x 'face 'nano-faded) x)))
11 x))
12
13(advice-add 'org-agenda-highlight-todo
14 :filter-return #'rougier/org-agenda-highlight-todo)
Timestamp tags for the agenda (bold means inverse video below):
now -> now 9:00 -> 9h00 9:30-10:00 -> 9h30 | 30mn -> ANYTIME
1(require 'svg-lib)
2(require 'svg-tag-mode)
3
4(defun rougier/svg-tag-timestamp (&rest args)
5 "Create a timestamp SVG tag for the time at point."
6
7 (interactive)
8 (let ((inhibit-read-only t))
9
10 (goto-char (point-min))
11 (while (search-forward-regexp
12 "\\(\([0-9]/[0-9]\):\\)" nil t)
13 (set-text-properties (match-beginning 1) (match-end 1)
14 `(display ,(svg-tag-make "ANYTIME"
15 :face 'nano-faded
16 :inverse nil
17 :padding 3 :alignment 0))))
18
19 (goto-char (point-min))
20 (while (search-forward-regexp
21 "\\([0-9]+:[0-9]+\\)\\(\\.+\\)" nil t)
22
23 (set-text-properties (match-beginning 1) (match-end 2)
24 `(display ,(svg-tag-make (match-string 1)
25 :face 'nano-faded
26 :margin 4 :alignment 0))))
27
28 (goto-char (point-min))
29 (while (search-forward-regexp
30 "\\([0-9]+:[0-9]+\\)\\(\\.*\\)" nil t)
31
32 (set-text-properties (match-beginning 1) (match-end 2)
33 `(display ,(svg-tag-make (match-string 1)
34 :face 'nano-default
35 :inverse t
36 :margin 4 :alignment 0))))
37 (goto-char (point-min))
38 (while (search-forward-regexp
39 "\\([0-9]+:[0-9]+\\)\\(-[0-9]+:[0-9]+\\)" nil t)
40 (let* ((t1 (parse-time-string (match-string 1)))
41 (t2 (parse-time-string (substring (match-string 2) 1)))
42 (t1 (+ (* (nth 2 t1) 60) (nth 1 t1)))
43 (t2 (+ (* (nth 2 t2) 60) (nth 1 t2)))
44 (d (- t2 t1)))
45
46 (set-text-properties (match-beginning 1) (match-end 1)
47 `(display ,(svg-tag-make (match-string 1)
48 :face 'nano-faded
49 :crop-right t)))
50 ;; 15m: ¼, 30m:½, 45m:¾
51 (if (< d 60)
52 (set-text-properties (match-beginning 2) (match-end 2)
53 `(display ,(svg-tag-make (format "%2dm" d)
54 :face 'nano-faded
55 :crop-left t :inverse t)))
56 (set-text-properties (match-beginning 2) (match-end 2)
57 `(display ,(svg-tag-make (format "%1dH" (/ d 60))
58 :face 'nano-faded
59 :crop-left t :inverse t
60 :padding 2 :alignment 0))))))))
1(add-hook 'org-agenda-mode-hook #'rougier/svg-tag-timestamp)
2(advice-add 'org-agenda-redo :after #'rougier/svg-tag-timestamp)
Tasks agenda
A custom date format function using svg tags (progress pies) for the task agenda.
1(defun rougier/org-agenda-custom-date ()
2 (interactive)
3 (let* ((timestamp (org-entry-get nil "TIMESTAMP"))
4 (timestamp (or timestamp (org-entry-get nil "DEADLINE"))))
5 (if timestamp
6 (let* ((delta (- (org-time-string-to-absolute (org-read-date nil nil timestamp))
7 (org-time-string-to-absolute (org-read-date nil nil ""))))
8 (delta (/ (+ 1 delta) 30.0))
9 (face (cond ;; ((< delta 0.25) 'nano-popout)
10 ;; ((< delta 0.50) 'nano-salient)
11 ((< delta 1.00) 'nano-default)
12 (t 'nano-faded))))
13 (concat
14 (propertize " " 'face nil
15 'display (svg-lib-progress-pie
16 delta nil
17 :background (face-background face nil 'default)
18 :foreground (face-foreground face)
19 :margin 0 :stroke 2 :padding 1))
20 " "
21 (propertize
22 (format-time-string "%d/%m" (org-time-string-to-time timestamp))
23 'face 'nano-popout)))
24 " ")))
The task agenda
1(add-to-list 'org-agenda-custom-commands
2 '("x" "Tasks"
3 ((todo "TODO" ;; "PROJECT"
4 ( (org-agenda-todo-keyword-format ":%s:")
5 (org-agenda-prefix-format '((todo . " ")))
6 (org-agenda-skip-function '(org-agenda-skip-entry-if 'timestamp))
7 (org-agenda-overriding-header (propertize " Todo \n" 'face 'nano-strong))))
8
9 (tags "+TALK+TIMESTAMP>=\"<now>\""
10 ((org-agenda-span 90)
11 (org-agenda-max-tags 5)
12 (org-agenda-prefix-format '((tags . " %(rougier/org-agenda-custom-date) ")))
13 (org-agenda-overriding-header "\n Upcoming talks\n")))
14
15 (tags "TEACHING+TIMESTAMP>=\"<now>\""
16 ((org-agenda-span 90)
17 (org-agenda-max-tags 5)
18 (org-agenda-prefix-format '((tags . " %(rougier/org-agenda-custom-date) ")))
19 (org-agenda-overriding-header "\n Upcoming lessons\n")))
20
21 (tags "TRAVEL+TIMESTAMP>=\"<now>\""
22 ((org-agenda-span 90)
23 (org-agenda-max-tags 5)
24 (org-agenda-prefix-format '((tags . " %(rougier/org-agenda-custom-date) ")))
25 (org-agenda-overriding-header "\n Upcoming travels\n")))
26
27 (tags "DEADLINE>=\"<today>\""
28 ((org-agenda-span 90)
29 (org-agenda-max-tags 5)
30 (org-agenda-prefix-format '((tags . " %(rougier/org-agenda-custom-date) ")))
31 (org-agenda-overriding-header "\n Upcoming deadlines\n"))))))
Update
We install a time to refresh the daily agenda (a) at regular intervals such that the current time is up to date.
1(defvar rougier/org-agenda-update-delay 60)
2(defvar rougier/org-agenda-update-timer nil)
3
4(defun rougier/org-agenda-update ()
5 "Refresh daily agenda view"
6
7 (when rougier/org-agenda-update-timer
8 (cancel-timer rougier/org-agenda-update-timer))
9
10 (let ((window (get-buffer-window "*Org Agenda(a)*" t)))
11 (when window
12 (with-selected-window window
13 (let ((inhibit-message t))
14 (org-agenda-redo)))))
15
16 (setq rougier/org-agenda-update-timer
17 (run-with-idle-timer
18 (time-add (current-idle-time) rougier/org-agenda-update-delay)
19 nil
20 'rougier/org-agenda-update)))
21
22(run-with-idle-timer rougier/org-agenda-update-delay t 'rougier/org-agenda-update)
Versioning
Git
1
2(require 'git-gutter)
3
4(global-git-gutter-mode +1)
Configure ediff
1
2(setq ediff-window-setup-function 'ediff-setup-windows-plain)
Magit
Set keybindings for magit
1(require 'llama)
1;; Taken from prelude
2;; Magit creates some global keybindings by default
3;; but it's a nice to complement them with this one
4(global-set-key (kbd "C-c g") 'magit-file-dispatch)
5(global-set-key (kbd "C-=") 'er/expand-region)
Prevent magit from writing in the header line.
1(advice-add 'magit-set-header-line-format :override #'ignore)
Add fringe on the left side of magit windows such that we can highlight region using the fringe.
1(add-hook 'magit-mode-setup-hook
2 #'(lambda ()
3 (interactive)
4 (set-window-fringes nil (* 2 (window-font-width)) 0)))
System
1(require 'openwith)
2(openwith-mode t)
3(setq openwith-associations '(("\\.mp4\\'" "vlc" (file))))