Ronaldo's Emacs literate configuration
Table of Contents
- 1. Constants
- 2.
use-package
and MELPA - 3. Editor preferences (better default behaviour)
- 4. Buffers at initialisation
- 5. Creating a minimal, zen/distraction-free frame
- 6. Theming and Emacs aesthetics
- 7. LSP and completion
- 8. Major modes for languages
- 9. Org mode
- 10. Compilation mode
- 11. Activating disabled modes
- 12. Nicities
- 12.1. Automatically close and colorise bracket pairs with
electric-pair-mode
andrainbow-delimiters
- 12.2. Better
M-x
completion withvertico
,orderless
andmarginalia
- 12.3. Icons with
dired
andcorfu
integration (nerd-icons
) - 12.4. Show possible key bindings (
which-key
) - 12.5. Fold code (
yafolding
) - 12.6. Enlarge region with
moc
(Master of ceremonies) - 12.7. Smart abbreviations with
tempel
- 12.8. Dictionary search on region with
C-c d
(dictionary.el
)
- 12.1. Automatically close and colorise bracket pairs with
- 13. Lisp
- 14. The Emacs Shell (
eshell
) - 15. Gligan's custom functionality
- 16. Changelog
This document is a literate configuration made in Emacs' Org mode,
which is exported to two files: early-init.el
and init.el
. Emacs then
loads these files on startup.
This document is like a living organism; it is constantly changing and evolving.
Skim through the table of contents to find the sections that may be relevant to you. Take snippets as you fancy.
This is a note for inexperienced Emacs users. Emacs is a self documenting system. For you, this means that for every function and every variable you see possibly has documentation that you can use as a reference:
M-x describe-symbol
will give you information about variables.M-x describe-function
will help you understand the purspose of a function and how you should supply it with arguments.- Sometimes, the best form of documentation is the source code
itself. To go to the definition of a symbol, put your point (the
text cursor) on the symbol and press
M-.
(that is a normal ASCII dot).
Also note that many Emacs modes and packages have nice and helpful manuals à la GNU.
1. Constants
1.1. Theme constants
(defconst gligan/light-theme 'ellas) (defconst gligan/dark-theme 'cappuccino-noir) ; somnus
1.2. Font constants
(defconst gligan/fixed-pitch-font "Iosevka Comfy Motion") (defconst gligan/variable-pitch-font (if (eq system-type 'darwin) "Inter" "Iosevka Comfy Motion Duo")) (defconst gligan/semi-fixed-pitch-font "Iosevka Comfy Motion Duo") (defconst gligan/fixed-pitch-font-size 130) (defconst gligan/variable-pitch-font-size 160)
1.3. Frame aesthetic constants
(defconst gligan/spacious-frame t)
1.4. Constants for default choices
Major modes and compilers
(defconst gligan/scratch-buffer-mode 'c-mode) (defconst gligan/c-compiler (if (eq system-type 'darwin) "clang" "gcc"))
Go with the flow of other code editors and do things like them. (Who doesn't like to follow fads?)
(defconst gligan/fad-config nil)
1.5. Constants regarding folders and files
(defconst gligan/org-documents-folder "~/Documents/Org/") (defconst gligan/org-roam-folder (concat gligan/org-documents-folder "Notes/"))
2. use-package
and MELPA
(require 'package) (add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/")) (package-initialize)
3. Editor preferences (better default behaviour)
Use 2 spaces as indentation
(setq-default tab-width 2) (setq-default indent-tabs-mode nil)
Delete the active region when inserting text
(delete-selection-mode 1)
Make word-editing commands work with word components (subwords)
(global-subword-mode)
Display the column number and buffer size in the modeline
(column-number-mode 1) (size-indication-mode 1)
Enable word wrapping
(setq-default word-wrap t)
Different default mode for the scratch buffer
(setq initial-major-mode gligan/scratch-buffer-mode)
Display trailing whitespace (only in programming modes)
(add-hook 'prog-mode-hook (lambda () (setq show-trailing-whitespace t)))
Don't close Emacs by accident
(setq confirm-kill-emacs 'y-or-n-p)
Dates should be formatted as
DD/MM/YYYY
and weeks start on Monday.(setq calendar-date-style 'european) (setq calendar-week-start-day 1)
Pixel scrolling instead of line scrolling
(pixel-scroll-precision-mode 1)
Prefer short answers ("y or n") instead of "yes or no"
(setq use-short-answers t)
Don't repeat input lines in comint-mode
(setq-default comint-process-echoes t)
3.1. Mac OS behaviour
Use modifier keys as if the Mac keyboard were a standard one.
(when (eq system-type 'darwin) (setq mac-command-modifier 'meta mac-option-modifier 'alt mac-right-option-modifier nil ns-function-modifier 'hyper mac-pass-control-to-system nil))
4. Buffers at initialisation
I find this setup really nice when starting up a fresh instance of Emacs:
- A
*scratch*
buffer usingc-mode
(variablegligan/scratch-buffer-mode
). - A general
*lisp*
buffer and an*elisp*
(Emacs Lisp) buffer. - A
*notes*
buffer (usingtext-mode
).
This buffer setup is created by the function gligan/set-up-buffers
.
(defun gligan/set-up-buffers () (interactive) ;; Lisp buffer (with-current-buffer (generate-new-buffer "*lisp*") (lisp-mode)) ;; Emacs Lisp buffer (with-current-buffer (generate-new-buffer "*elisp*") (emacs-lisp-mode) (setq-local lexical-binding t)) ;; Notes buffer (with-current-buffer (generate-new-buffer "*notes*") (text-mode) (auto-fill-mode)))
I run this function with a hook after my whole Emacs configuration is loaded so that all the customisations applied after this section get applied to these temporary buffers.
(add-hook 'after-init-hook #'gligan/set-up-buffers)
5. Creating a minimal, zen/distraction-free frame
Start all frames maximised
(add-to-list 'default-frame-alist '(fullscreen . maximized))
Minimal window without buttons or scrollbars
(unless (eq system-type 'darwin) (menu-bar-mode -1)) (tool-bar-mode -1) (scroll-bar-mode -1)
Beautiful padding around the frame when the option is turned on.
(when gligan/spacious-frame (modify-all-frames-parameters '((internal-border-width . 15) (right-divider-width . 15) (left-fringe . 8) (right-fringe . 8))))
Backup files
(setq backup-directory-alist (cons "." (expand-file-name "backup" user-emacs-directory))) (setq auto-save-default t create-lockfiles nil make-backup-files nil) (setq kill-buffer-delete-autosave-files t)
Visual hacks
(setq frame-resize-pixelwise t)
(setq resize-mini-windows 'grow-only)
Use a thin cursor instead of a block
(setq-default cursor-type 'bar)
When using a thin cursor, highlighting the current line is a good idea so that your eyes don't get lost in the vast sea of code in all the buffers you have opened.
(use-package hl-line :custom (global-hl-line-sticky-flag t) :config (global-hl-line-mode 1))
No start-up visual noise: disable welcome buffer, and scratch buffer does not contain a "helpful" elisp comment.
(setq inhibit-startup-message t inhibit-startup-screen t initial-scratch-message nil)
Use the proportional font to display text buffers
(add-hook 'text-mode-hook #'variable-pitch-mode)
The problem is that
variable-pitch-mode
makes all text proportional, and oftentimes I have block codes.mixed-pitch
solves that:(use-package mixed-pitch :ensure t :defer t :hook (text-mode . mixed-pitch-mode))
Decluttering dired mode and showing human-readable file sizes
(use-package dired :hook ((dired-mode . dired-hide-details-mode) (dired-mode . dired-omit-mode )) :custom (dired-hide-details-hide-symlink-targets nil) (dired-free-space nil) (dired-mouse-drag-files t))
5.1. A simple, custom mode line
(setq mode-line-position-line-format "line %l") (setq mode-line-position-column-format "column %c") (setq mode-line-compact nil) (setq mode-line-right-align-edge 'right-margin) (setq-default mode-line-format (list "%e" " " '(:eval (if (package-installed-p 'nerd-icons) (nerd-icons-icon-for-buffer) "")) " " mode-line-buffer-identification " " '(:eval mode-name) " " "(" mode-line-position-line-format ", " mode-line-position-column-format ")" '(:eval (if (and (buffer-file-name) (buffer-modified-p)) " edited" "")) " " ;; (if (boundp 'mode-line-format-right-align) ;; mode-line-format-right-align "") ;; I'll wait for Emacs 30 to have this feature ;; mode-line-modes mode-line-misc-info))
5.2. "Look, ma, I'm just like vscode"
(when gligan/fad-config (add-hook 'prog-mode 'display-line-numbers-mode))
6. Theming and Emacs aesthetics
First, declare all external themes as safe (that way, Emacs won't ask you every time you load a theme wether to consider it safe or not):
(setq custom-safe-themes t)
Whenever I change the theme I may want to run some code along with it. That is why I create a hook:
(defvar gligan/after-theme-toggle-hook nil)
6.1. Blend title bar & frame opacity on MacOS
(when (eq system-type 'darwin) (add-to-list 'default-frame-alist '(ns-transparent-titlebar . t)))
6.2. Dark mode based on OS settings and custom toggle
The function gligan/toggle-theme
takes care of switching the system
theme.
(defun gligan/toggle-theme () "Toggle between the system's light and dark modes" (interactive) ;; Toggling the theme (cond ((custom-theme-enabled-p gligan/light-theme) (progn (disable-theme gligan/light-theme) (load-theme gligan/dark-theme))) ((custom-theme-enabled-p gligan/dark-theme) (progn (disable-theme gligan/dark-theme) (load-theme gligan/light-theme))) (t (load-theme gligan/light-theme))) ;; Hooks (run-hooks 'gligan/after-theme-toggle-hook))
(global-set-key (kbd "M-g t t") 'gligan/toggle-theme)
Whereas the auto-dark
package worries about keeping the Emacs theme
in sync with the OS.
(use-package auto-dark :ensure t :custom (auto-dark-light-theme gligan/light-theme) (auto-dark-dark-theme gligan/dark-theme) :config (auto-dark-mode t) (add-hook 'auto-dark-dark-mode-hook 'gligan/set-modeline-font) (add-hook 'auto-dark-light-mode-hook 'gligan/set-modeline-font) (add-hook 'auto-dark-dark-mode-hook 'gligan/spacious-frame-style-tweaks) (add-hook 'auto-dark-light-mode-hook 'gligan/spacious-frame-style-tweaks))
6.2.1. Switching MacOS's theme
(defun gligan/switch-macos-theme () (interactive) (when (eq system-type 'darwin) (do-applescript "tell application \"System Events\" tell appearance preferences set dark mode to not dark mode end tell end tell"))) (add-hook 'gligan/after-theme-toggle-hook 'gligan/switch-macos-theme)
6.3. Styling when gligan/spacious-frame
is t
(defun gligan/spacious-frame-style-tweaks () (when gligan/spacious-frame (let ((bg (face-attribute 'default :background))) (set-face-attribute 'window-divider nil :foreground bg) (set-face-attribute 'window-divider-first-pixel nil :foreground bg) (set-face-attribute 'window-divider-last-pixel nil :foreground bg)))) (gligan/spacious-frame-style-tweaks) (add-hook 'gligan/after-theme-toggle-hook 'gligan/spacious-frame-style-tweaks)
6.4. Custom fonts
(set-face-attribute 'default nil :family gligan/fixed-pitch-font :height gligan/fixed-pitch-font-size) (set-face-attribute 'fixed-pitch nil :family gligan/fixed-pitch-font :height gligan/fixed-pitch-font-size) (set-face-attribute 'variable-pitch nil :family gligan/variable-pitch-font :height gligan/variable-pitch-font-size)
6.4.1. Custom mode line font
(defun gligan/set-modeline-font () (set-face-attribute 'mode-line-active (selected-frame) :font gligan/semi-fixed-pitch-font) (set-face-attribute 'mode-line-inactive (selected-frame) :font gligan/semi-fixed-pitch-font)) (add-hook 'gligan/after-theme-toggle-hook 'gligan/set-modeline-font)
6.4.2. Font ligatures
With the font I'm using, ot all but most of the ligatures below work. As far as I know, all Iosevka and Cascadia Code ligatures are included in this list.
(use-package ligature :ensure t :hook (after-init . global-ligature-mode) :config (ligature-set-ligatures 't '("!!" "!!." "!=" "!==" "#!" "##" "###" "####" "#(" "#:" "#=" "#?" "#[" "#_" "#_(" "#{" "$>" "%%" "&&" "(*" "*)" "**" "***" "*/" "*>" "++" "+++" "+:" "+>" "--" "---" "--->" "-->" "-:" "-<" "-<<" "->" "->>" "-|" "-~" ".-" ".." "..." "..<" ".=" ".?" "/*" "//" "///" "/=" "/==" "/>" ":+" ":-" "://" "::" ":::" "::=" ":<" ":=" ":>" ";;" "<!--" "<!---" "<$" "<$>" "<*" "<******>" "<*>" "<+" "<+>" "<-" "<--" "<---" "<---->" "<--->" "<-->" "<-<" "<->" "</" "</>" "<:" "<<" "<<-" "<<<" "<<=" "<=" "<=<" "<==" "<===" "<====>" "<===>" "<==>" "<=>" "<>" "<|" "<|>" "<||" "<|||" "<~" "<~>" "<~~" "=!=" "=/=" "=:" "=:=" "=<<" "==" "===" "===>" "==>" "=>" "=>>" ">-" ">->" ">=" ">=>" ">>" ">>-" ">>=" ">>>" "?." "?:" "?=" "??" "[|" "\\\\" "]#" "^=" "__" "_|_" "www" "{|" "|-" "|=" "|>" "|]" "||" "||=" "||>" "|||>" "|}" "~-" "~=" "~>" "~@" "~~" "~~>")))
7. LSP and completion
7.1. The eglot
LSP client
Eglot is a minimalistic LSP client for Emacs. For Emacs >= 29
, it
comes installed by default. The main alternative to Eglot is lsp-mode,
which is more complete: it has more features and more customisations,
but it is slower and it does not come with Emacs.
(use-package eglot :ensure t :defer t :hook ((c++-mode c-mode haskell-mode nim-mode python-mode rust-mode tuareg-mode zig-mode) . eglot-ensure) :custom (eglot-autoshutdown t))
Here is a list of all the servers that Eglot can communicate to. On Fedora I had to install the following:
LSP features on C are achieved with
clangd
.(sudo) dnf install clang-tools-extra
- Haskell has
haskell-language-server
, that can be installed withghcup
. For Nim I use
nimlsp
:nimble install nimlsp
Python has many LSP servers, I use
pylsp
.pip install python-lsp-server
- Rust has
rust-analyzer
. OCaml needs
ocaml-lsp-server
and optionallyocamlformat
.opam install ocaml-lsp-server ocamlformat
- I can't build Zig's LSP server because it needs a custom version of the compiler.
7.2. Completion with corfu
(use-package corfu :ensure t :custom (corfu-cycle t) (corfu-auto nil) :init (global-corfu-mode))
8. Major modes for languages
8.1. OCaml
(use-package tuareg :ensure t :defer t) (use-package dune :ensure t :defer t) (use-package merlin :ensure t :defer t :custom (merlin-error-after-save nil) :config (add-hook 'tuareg-mode-hook #'merlin-mode)) (use-package merlin-eldoc :ensure t :defer t :hook (tuareg . merlin-eldoc-setup))
8.2. SML
(use-package sml-mode :custom (sml-indent-level 2) (sml-indent-args 2))
8.3. Zig
(use-package zig-mode :defer t :custom (zig-format-on-save nil) :config (zig-format-on-save-mode -1))
8.4. Shell mode
(setq sh-basic-offset 2)
8.5. Fish
(setq fish-indent-offset 2)
8.6. CSS
(setq css-indent-offset 2)
9. Org mode
These numbers below define the proportions of the org mode headers in contrast to the paragraph text.
(defun gligan/org-mode-font-setup () (dolist (face '((org-document-title . 1.8) (org-level-1 . 1.3) (org-level-2 . 1.2) (org-level-3 . 1.1))) (set-face-attribute (car face) nil :font gligan/variable-pitch-font :weight 'regular :height (cdr face))))
(use-package org :hook ((org-mode . gligan/org-mode-font-setup) (org-mode . olivetti-mode) (org-mode . auto-fill-mode)) :custom (org-directory 'gligan/org-documents-folder) (org-hide-emphasis-markers t) (org-pretty-entities t) (org-startup-folded 'fold) (org-startup-indented t) (org-tags-column 0) (org-highlight-latex-and-related '(latex)) (org-src-tab-acts-natively t) (org-edit-src-content-indentation 0) (org-confirm-babel-evaluate nil))
9.1. Centering and auto-filling content
(use-package olivetti :ensure t)
9.2. Nice Org aesthetics
(use-package org-modern :ensure t :config (global-org-modern-mode 1))
9.3. Org Roam
(use-package org-roam :custom (org-roam-directory (file-truename gligan/org-roam-folder)) :config (org-roam-db-autosync-mode) :bind (("C-c n f" . org-roam-node-find) ("C-c n r" . org-roam-node-random) ("C-c n d" . org-roam-dailies-capture-today) ("C-c n D" . org-roam-dailies-goto-date) (:map org-mode-map (("C-c n i" . org-roam-node-insert) ("C-c n o" . org-id-get-create) ("C-c n t" . org-roam-tag-add) ("C-c n a" . org-roam-alias-add) ("C-c n l" . org-roam-buffer-toggle)))))
Optionally install the package org-roam-ui
to visualise your nodes and
links between them in a local browser page.
9.4. Org agenda
(defun gligan/custom-agenda-view () (interactive) (org-agenda nil "a")) (global-set-key (kbd "C-c a") 'org-agenda) (global-set-key (kbd "C-c s") 'gligan/custom-agenda-view)
(setq org-agenda-files (list gligan/org-documents-folder gligan/org-roam-folder (concat gligan/org-roam-folder "daily/") ) org-agenda-include-diary t)
My custom agenda views:
(setq org-agenda-custom-commands '(("a" "Ronaldo's agenda view" ((tags-todo "ua" ((org-agenda-overriding-header "Universidad"))) (tags-todo "+PRIORITY=\"A\"" ((org-agenda-overriding-header "High Priority Tasks"))) (agenda) (todo "" ((org-agenda-overriding-header "All tasks")))) )))
org-agenda-include-diary
shows special calendar events in the diary
view.
;; (add-hook 'after-init-hook 'gligan/custom-agenda-view) ;; (add-hook 'org-agenda-mode-hook 'mixed-pitch-mode)
Now let's customise the looks of the agenda (mainly the fonts):
;; Variable pitch elements (dolist (face '(org-agenda-structure org-agenda-diary org-agenda-calendar-event)) (set-face-attribute face nil :font gligan/variable-pitch-font))
;; Fixed pitch elements (dolist (face '(org-agenda-date org-agenda-date-today)) (set-face-attribute face nil :font gligan/fixed-pitch-font))
;; (set-face-attribute 'org-agenda-structure nil :height 1.4)
10. Compilation mode
(setq-default compilation-scroll-output 'first-error)
(defun gligan/compile-command-for-buffer (&optional only-compile) ;; If the buffer is not associated with a file, then there is ;; nothing we can really do. (if (null (buffer-file-name)) compile-command (let* ((executable-name (format "%s.exe" (file-name-sans-extension (buffer-file-name)))) (buffer-extension (file-name-extension (buffer-file-name))) (command (pcase buffer-extension ("c" (format "%s %s -o %s" (if (eq system-type 'darwin) "clang" "gcc") (buffer-file-name) executable-name)) ("cpp" (format "%s -o %s" (if (eq system-type 'darwin) "clang++" "g++") (buffer-file-name) executable-name)) (_ nil)))) (cond (only-compile command) ;; The default compilation command ((null command) compile-command) ;; Compile and then execute the command (t (format "%s && %s" command executable-name))))))
(defun gligan/switch-to-compilation-buffer () (unless (string= (buffer-name) "*compilation*") (switch-to-buffer-other-window "*compilation*"))) (defun gligan/compile (&optional only-compile) (interactive (list ;; If given a prefix argument, then the command only compiles, and ;; does not run the executable (not (null current-prefix-arg)))) (compile (compilation-read-command (gligan/compile-command-for-buffer only-compile)) t) (gligan/switch-to-compilation-buffer)) (defun gligan/recompile () (interactive) (let ((last-text-scale (with-current-buffer "*compilation*" text-scale-mode-amount))) (compilation-start compile-command t) (gligan/switch-to-compilation-buffer) (text-scale-set last-text-scale)))
(global-set-key (kbd "C-c c") 'gligan/compile) (global-set-key (kbd "C-c x") 'gligan/recompile)
10.1. Colorise ANSI escape codes in compilation buffer
ansi-color
is part of Emacs.
(use-package ansi-color :config (defun gligan/colorise-compilation () (let ((inhibit-read-only t)) (ansi-color-apply-on-region compilation-filter-start (point)))) (add-hook 'compilation-filter-hook #'gligan/colorise-compilation))
11. Activating disabled modes
Narrow to region
(put 'narrow-to-region 'disabled nil)
Remember recently opened files to jump back to them easily
(recentf-mode 1) (global-set-key (kbd "C-x M-b") 'recentf)
12. Nicities
12.1. Automatically close and colorise bracket pairs with electric-pair-mode
and rainbow-delimiters
electric-pair-mode
is included with the Emacs distribution, so we just
have to turn it on globally:
(electric-pair-mode 1)
(use-package rainbow-delimiters :defer 3 :ensure t :hook (prog-mode . rainbow-delimiters-mode))
12.2. Better M-x
completion with vertico
, orderless
and marginalia
(use-package vertico :ensure t :custom (vertico-cycle t) (vertico-count 5) :config (vertico-mode)) (use-package savehist :ensure t :config (savehist-mode)) (use-package orderless :ensure t :custom (completion-styles '(orderless flex)) (completion-category-overrides '((eglot (styles . (orderless flex)))))) (use-package marginalia :ensure t :config (marginalia-mode))
12.3. Icons with dired
and corfu
integration (nerd-icons
)
(use-package nerd-icons :ensure t) (use-package nerd-icons-dired :ensure t :hook (dired-mode . nerd-icons-dired-mode)) (use-package nerd-icons-corfu :ensure t :after corfu :config (add-to-list 'corfu-margin-formatters #'nerd-icons-corfu-formatter))
12.4. Show possible key bindings (which-key
)
which-key
implements a menu that appears after a certain amount of
time when a half-pressed keybinding is entered, showing all the
possible routes or functions you can perform from there.
(use-package which-key :ensure t :defer 3 :config (which-key-mode))
12.5. Fold code (yafolding
)
Being able to fold regions of code is a feature that is quintessential
for any modern source code editor. yafolding
figures out the fold
regions through indentation, so it is language agnostic. I do not
customise the key bindings or any other setting – they are perfect
right out of the box for me. Below I leave the default key bindings:
C-RET |
Folds the current scope |
C-S-RET |
Folds the parent |
C-M-RET |
Folds the entire buffer |
(use-package yafolding :ensure t :defer 10 :hook (prog-mode . yafolding-mode))
12.6. Enlarge region with moc
(Master of ceremonies)
I don't like it when doing moc-focus
I see the currently highlighted
hl-line
and the parentheses matched. I disable them.
(use-package moc :bind ("C-c m" . moc-focus) :config (push '(remove-hl-line . ((hl-line . (:background (face-attribute 'default :background))) (show-paren-match . (:inverse-video nil)))) moc-face-remap-presets) (add-hook 'moc-focus-mode-hook (lambda () (moc-face-remap 'remove-hl-line))))
12.7. Smart abbreviations with tempel
The default templates file is located at
$HOME/.emacs.d/templates
. Tempel's template format is easy enough once
you create a few templates.
(use-package tempel :bind (("M-+" . tempel-complete)))
Let me briefly explain to you how the templates work with an example:
;; $HOME/.emacs.d/templates fundamental-mode (today (format-time-string "%Y-%m-%d")) c-mode c++-mode (guard "#ifndef " (r (upcase (file-name-base (buffer-name))) header-name) "_H" n "#define " header-name "_H" n n q n n "#endif /* " header-name "_H */" n)
The structure of the template file is as follows:
- You write the name of the modes you want this template to work with. Note that all derived modes will also have available the templates (for instance, the "today" template is defined for the fundamental mode, so all derived modes –pretty much all modes– will have available that template).
- After the mode names, we may have many s-expressions. Every sexp
starts with the name of the template and the rest of the list is
what it expands to.
- Strings just insert their content literally
- You can have Emacs Lisp expressions and their result will get
inserted (unless they are
nil
, which wouldn't insert anything). n
inserts a new line.- You can have named values that get repeated with
(r VALUE NAME)
– seeheader-name
in the example above. - When you reach the
q
, the template stops.
Now, in any buffer I can write "today", press C-+
and it expands to
today's date.
When you have multiple inputs in a templates you can go back and forth
between those inputs with C-{
and C-}
.
For more information, see the Tempel repo.
12.8. Dictionary search on region with C-c d
(dictionary.el
)
(setq dictionary-server "dict.org") (global-set-key (kbd "C-c d") #'dictionary-search)
13. Lisp
(defconst +cl-implementations+ '("sbcl" "ccl64" "clisp" "ecl")) (setq inferior-lisp-program (cl-find-if #'executable-find +cl-implementations+)) (unless inferior-lisp-program (message "No Common Lisp implementation found. Install one of %s" +cl-implementations+))
14. The Emacs Shell (eshell
)
The eshell-mode-map
is initially set to nil
internally in eshell, and
then it is populated locally. So, when I try to define-key
for
eshell-mode-map
I get an error. A workaround is to execute define-key
after eshell has loaded through a hook.
(use-package eshell) (defun gligan/eshell-terminal-clear () (interactive) (eshell/clear-scrollback) (eshell-send-input)) (defun gligan/custom-eshell-keys () (define-key eshell-mode-map (kbd "C-l") 'gligan/eshell-terminal-clear)) (add-hook 'eshell-mode-hook #'gligan/custom-eshell-keys)
15. Gligan's custom functionality
This section implements features for Emacs that I believe are easy and concise enough to write in my own configuration, without requiring external packages.
15.1. Transposing lines and region
Source: https://www.emacswiki.org/emacs/MoveText
(defun gligan/move-text-internal (arg) (cond ((and mark-active transient-mark-mode) (if (> (point) (mark)) (exchange-point-and-mark)) (let ((column (current-column)) (text (delete-and-extract-region (point) (mark)))) (forward-line arg) (move-to-column column t) (set-mark (point)) (insert text) (exchange-point-and-mark) (setq deactivate-mark nil))) (t (let ((column (current-column))) (beginning-of-line) (when (or (> arg 0) (not (bobp))) (forward-line) (when (or (< arg 0) (not (eobp))) (transpose-lines arg)) (forward-line -1)) (move-to-column column t)))))
(defun gligan/move-text-down (arg) (interactive "*p") (gligan/move-text-internal arg)) (defun gligan/move-text-up (arg) (interactive "*p") (gligan/move-text-internal (- arg)))
(global-set-key (kbd "M-p") 'gligan/move-text-up) (global-set-key (kbd "M-<up>") 'gligan/move-text-up) (global-set-key (kbd "M-n") 'gligan/move-text-down) (global-set-key (kbd "M-<down>") 'gligan/move-text-down)
15.2. Duplicate a line
(defun gligan/duplicate-line () (interactive) (duplicate-line) (next-line))
(global-set-key (kbd "C-c l") 'gligan/duplicate-line)
16. Changelog
Only substantial changes are recorded in this section.
- 2025-01-22
gligan/recompile
remembers text scale.
- 2025-01-21
- Created this change log.
- Removed
pulsar
package. - Compilation mode: moved to its own section, added custom compile commands, interactive compilation enabled by default (i.e. you can enter text in the compilation buffer and it gets sent to the process).
- Deleted
gligan/run-program
as its functionality is unnecesary given the new behaviour ofgligan/compile
.