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