This repository contains my GNU Emacs configuration files along with an in-depth chronicle of my crafting process. It includes links to valuable resources, in code, text and video, that have been important throughout my trajectory. In this sense, taking inspiration from @Munen’s insightful presentation ”Play Emacs like an instrument”, I have decided to expand his playful yet thoughtful metaphor into this unique creative process. Thus, this is the journey to craft emacs.d like a luthier.
- Wood Selection
- Design and Planning
- Shaping and Carving
- Stringing It Up
- Tunings and Sound Adjustment
- Composition and Performance
- Collaborative Jamming
- Ongoing Opus
ℹ️ The core of this project is built to my personal use case and workflow, which may or may not align with yours. The great news is that you are free, as in free software, to inspire yourself and change it to do what you mean. Check the license section for further details on that.
After having a solid grasp of Emacs basics, a good next move is learning from more experienced users. @Redguardtoo, in On the Shoulders of Giants, also writes about the importance of this type of approach. Since it is a longstanding community tradition the sharing of emacs.d, using all this shared knowledge as materia prima is an effective way to begin a vanilla Emacs journey.
Nowadays, in my case, I maintain locally a curated list of emacs.d repositories of my interest. When I wish to implement a new feature or workflow, I use these repositories as practical references. Also, around once per trimester, I review upstream changes to weigh whether any new idea or setting worth adapting into my configuration.
Therefore, this approach provides not only a source of hands-on configurations but also a window into evolving practices within the community.
If you are entirely new to Emacs, fear not. Further ahead, I provide some beginner-friendly guidance as well.
Emacs.d configurations can take various forms, but they typically fall into two main styles:
- Literate Programming style
- Emacs Lisp style
Initially, my configuration followed the literate programming style, utilizing the use-package
macro. It was managed through an Org file named after Odysseus, which I have kept in the repository for archival purposes. However, after using this style for 10 months, I developed a desire to deepen my understanding of Emacs Lisp. As a result, I decided to refactor my entire configuration (0e48f4d), shifting to an Emacs Lisp style without relying on use-package
. This refactoring allowed me not only to practice the Emacs Lisp way, but also to introduce modularity into my configuration, enabling me to create more shareable, manageable, and independent components.
.auth/
- Private directory for restricted settings and secure authentication within Emacs.
img/
- Directory containing images for the Emacs dashboard and for this repository.
local/
- Directory for offline utility files, including capture templates, presentation tools, and custom packages.
modules/
- Directory containing Emacs Lisp modules and configuration files.
snippets/
- Directory for programming snippets and templates.
early-init.el
(optional)- Pre-initialization settings. This file is loaded by Emacs.
init.el
- Package archive settings, global functions and variables, and system-wide configuration. This file is loaded by Emacs after early-init.el.
modules.el
- General configuration scopes that load pertinent prefix-config.el files. These files are loaded by init.el.
prefix.config.el
- Package configuration files with filenames inheriting module prefixes. These files are loaded by modules.el.
custom.el
(optional)- Minor adjustments and temporary testing settings. This is the last file loaded by init.el.
The diagram below provides a visual synthesis of the core Emacs Lisp files alongside the directory structure, arranged in loading sequence order from left to right.
Moving from the conceptual phase to implementation, the following list describes each module:
- Communication Module
- Responsible for emailing and communication apparatus.
- Design Module
- Responsible for designing and modeling processes.
- Functionality Module
- Responsible for implementing new functionalities into Emacs.
- Miscellaneous Utilities Module
- Responsible for introducing or extending general utilities.
- Navigation Module
- Responsible for managing navigation throughout Emacs.
- Org-Mode Module
- Responsible for setting the org-mode milieu.
- Programming Module
- Responsible for supporting programming workflows.
- Project Management Module
- Responsible for integrating projects and version control.
- Publishing Module
- Responsible for exporting and publishing material.
- Text Module
- Responsible for complying writing processes.
- Visual Module
- Responsible for looking and feeling aspects.
In order to have a more sensible naming standard, each module filename is assigned with an abbreviation prefix prepended by “tty” to avoid conflicts, as with org.el
. Thus, there are the following modules files:
init.el
└── modules/
├── tty-com.el communication module
├── tty-dsg.el design module
├── tty-func.el functionality module
├── tty-misc.el miscellaneous utilities module
├── tty-nav.el navigation module
├── tty-org.el org-mode module
├── tty-prog.el programming module
├── tty-proj.el project management module
├── tty-publ.el publishing module
├── tty-txt.el text module
└── tty-vis.el visual module
As mentioned earlier, in addition to managing general settings within its scope, each module is also responsible for loading relevant package configuration files. Each configuration file inherits its filename prefix from the module responsible for it. Thus, there are the following configuration files:
init.el
└── modules/
├── tty-com.el communication module
│ ├── tty-com-bbdb.el
│ ├── tty-com-erc.el
│ └── tty-com-gnus.el
├── tty-dsg.el design module
│ ├── tty-dsg-graphviz-dot.el
│ └── tty-dsg-plantuml.el
├── tty-func.el functionality module
│ ├── tty-func-embark.el
│ ├── tty-func-evil.el
│ ├── tty-func-expand-region.el
│ ├── tty-func-hungry-delete.el
│ ├── tty-func-move-dup.el
│ ├── tty-func-multiple-cursors.el
│ ├── tty-func-orderless.el
│ ├── _tty-func-popup-kill-ring.el
│ ├── tty-func-sudo-edit.el
│ ├── _tty-func-undo-tree.el
│ ├── tty-func-vundo.el
│ ├── tty-func-wgrep.el
│ └── tty-func-zzz-to-char.el
├── tty-misc.el miscellaneous utilities module
│ ├── tty-misc-bibtex.el
│ ├── tty-misc-centered-cursor.el
│ ├── tty-misc-company.el
│ ├── tty-misc-dired.el
│ ├── tty-misc-exec-path-from-shell.el
│ ├── tty-misc-nov.el
│ ├── tty-misc-olivetti.el
│ ├── tty-misc-paredit.el
│ ├── tty-misc-pdf-tools.el
│ └── tty-misc-vertico.el
├── tty-nav.el navigation module
│ ├── tty-nav-avy.el
│ ├── tty-nav-consult.el
│ ├── _tty-nav-helm.el
│ ├── tty-nav-switch-window.el
│ └── tty-nav-which-key.el
├── tty-org.el org-mode module
│ ├── tty-org-auto-tangle.el
│ ├── tty-org-bullets.el
│ ├── tty-org-noter.el
│ ├── tty-org-orgmdb.el
│ ├── tty-org-ref.el
│ ├── tty-org-roam.el
│ └── tty-org-toc-org.el
├── tty-prog.el programming module
│ ├── tty-prog-ansible.el
│ ├── tty-prog-c.el
│ ├── tty-prog-css.el
│ ├── tty-prog-eglot.el
│ ├── _tty-prog-flycheck.el
│ ├── tty-prog-flymake.el
│ ├── tty-prog-go.el
│ ├── tty-prog-html.el
│ ├── tty-prog-javascript.el
│ ├── tty-prog-json.el
│ ├── tty-prog-lisp.el
│ ├── _tty-prog-lsp.el
│ ├── tty-prog-lua.el
│ ├── tty-prog-markdown.el
│ ├── tty-prog-nix.el
│ ├── tty-prog-python.el
│ ├── tty-prog-rust.el
│ ├── tty-prog-scheme.el
│ ├── tty-prog-shell.el
│ ├── tty-prog-sql.el
│ ├── tty-prog-toml.el
│ ├── tty-prog-tree-sitter.el
│ ├── tty-prog-xml.el
│ ├── tty-prog-yaml.el
│ └── tty-prog-yasnippet.el
├── tty-proj.el project management module
│ ├── tty-proj-diff-hl.el
│ ├── tty-proj-magit.el
│ ├── tty-proj-project.el
│ └── _tty-proj-projectile.el
├── tty-publ.el publishing module
│ ├── tty-publ-easy-hugo.el
│ ├── tty-publ-htmlize.el
│ ├── tty-publ-ox-reveal.el
│ └── tty-publ-ox-twbs.el
├── tty-txt.el text module
│ ├── tty-txt-flyspell.el
│ ├── tty-txt-fountain.el
│ └── tty-txt-go-translate.el
└── tty-vis.el visual module
├── tty-vis-all-the-icons.el
├── tty-vis-beacon.el
├── tty-vis-dashboard.el
├── tty-vis-diminish.el
├── _tty-vis-gruvbox-theme.el
├── tty-vis-keycast.el
├── tty-vis-marginalia.el
├── tty-vis-modus-themes.el
├── _tty-vis-pulsar.el
├── tty-vis-rainbow.el
└── _tty-vis-spaceline.el
❔ Entries marked with an underscore indicate that they were deactivated in favour of another package. Read the commentary section in the given file for more information.
It is important to note that while the overview above suggests an one-to-one relationship between configuration files and packages, this is not always the case. Some configuration files are more inclined to handle a family of related packages. For instance, the tty-org-roam.el
file consolidates configurations for org-roam, org-roam-bibtex, and org-roam-ui packages.
At the Emacs Lisp file level, I have adapted the conventional library headers for this informal use case of a personal configuration. Each custom field added to the template is marked with the section comment separator ;;*
.
;;; foo.el --- Foo Title -*- lexical-binding: t -*-
;;; Commentary:
;; Crafting Emacs like a luthier.
;;; Code:
(require 'bar)
;;* Variables:
;;* Main:
;;* Bindings:
;;* Hooks:
;;* Appearance:
(provide 'foo)
;;; foo.el ends here
Although these custom fields are quite indicative, here are their purposes:
;;* Variables
: Section for defining variables.;;* Functions
: Section for defining functions.;;* Main
: Section for code execution.;;* Bindings
: Section for setting bindings.;;* Hooks
: Section for setting hooks.;;* Appearance
: Section for cosmetic changes.
By following this approach, the code base remains stable and structured, enabling a more seamless navigation, regardless of the quantity or size of the files. Still, searching for the section comment separator, ;;\*
, is often a handy way for moving into specific segments as well. To further streamline the process, a snippet, <h
TAB
, is also available for automating the template insertion into new Emacs Lisp files.
To bring the setup to life, start by cloning the repository and selecting what interests you the most:
git clone https://github.com/ttybitnik/emacs.d.git
A general setting that one may want to adjust from the outset is the package archives priorities in init.el
. The archives with higher values take precedence over the lower ones.
(setq package-archive-priorities
'(("gnu" . 4)
("nongnu" . 3)
("melpa" . 2)
("melpa-stable" . 1)))
If you are beginning your Emacs journey, do not skip the official tutorial help-with-tutorial
(C-h t). After that, I recommend familiarizing yourself with the big-bang M-x
and getting comfortable with the following commands:
help-for-help
(C-h C-h)describe-variable
(C-h v)describe-function
(C-h f)describe-symbol
(C-h o)describe-key
(C-h k)describe-mode
(C-h m)describe-package
(C-h P)info
(C-h i)
The above, in conjunction with the GNU Emacs Manual (C-h r) as reference, provide a solid foundation in Emacs basics. After having a good grasp of the basics, it is also really useful knowing about navigation through balanced expressions (sexp), org-mode speed keys and xref-find-definitions
(M-.).
If your ‘philosophy’ variable is non-nil, consider watching @Protesilaos’ presentations to get a deeper understanding of Emacs mnemonics and a thoughtful reflection on interacting with computers. If your ‘book-reader’ variable is non-nil as well, consider reading Mickey Petersen’s book “Mastering Emacs” for a comprehensive overview on Emacs along with some historical context.
Finally and most importantly, start playing Emacs.
Once using it, you will soon find the need for personal tunings and adjustments. There are numerous ways to perform these operations, and over time, you will accumulate various techniques in your toolkit. Given the extensive nature of my configuration, below I am sharing some of my favorite methods and tools along with a visual demonstration for managing its multiple files.
dired-jump
(C-x C-j) intomodules/
grep
(C-c M-s g) “foo” *wgrep-change-to-wgrep-mode
(C-c C-p)mc-mark-more
(C->)query-replace
(M-%)kmacro-start-macro-or-insert-counter
(<f3>)
⚠️ ️ This is a demonstration using the terminal as interface, no-window-system (nw), which means that certain visual elements may not display correctly due graphical/recording limitations.
One essential thing to have in mind while doing modifications is that very often the defaults are more powerful than you think. It is just a matter of taking time to study and practice them. Besides that, maintaining a stable configuration is more conducive to in-depth skill development. So do be deliberate and thoughtful with every change you make.
Instead of altering the configuration whenever something triggers you, I recommend capturing descriptive tasks (C-c c t org-capture
) once you have a workflow modification or a new idea in mind. Periodically, such as once every trimester, review this list of modification tasks. If they still make sense, proceed with their implementation. The custom.el
file is also handy for testing these new changes, serving as a sort of trial period before fully incorporating them into the configuration.
Emacs offers powerful tools from coding to prose. Below are some links to key features and workflows that play a central role in my daily usage. They cover a wide range of areas, from note-taking and knowledge management system to programming, writing, and publishing.
- Org-mode: A system for note-taking and project planning.
- KMS: Zettelkasten, org-roam (unlinked references), org-roam-bibtex (quick presentation).
- Sprints: Literate DevOps with Emacs.
- Blogging: Hugo, easy-hugo (blog with org-mode).
- Emailing: Practical guide to GNUS.
- Presenting: Reveal.js, org-reveal (classy slideshows from org-mode).
- Programming: Eglot, company-mode.
Embrace the collaborative jamming and contribute to the freedom of software. If you encounter a bug or identify areas for improvement in the packages you use, consider collaborating by reporting issues or contributing to code and documentation.
Staying connected with the community is also helpful. Below are some of my preferred ways to do it through gnus
.
- Emacs Mailiing Lists
- Emacs Devel
- Emacs Tangents
- Sasha Chua’s Emacs News
- System Crafters’ Newsletter
Among its peers, Emacs is a truly unique stradivarius—one that belongs to all of us and can be played by all of us. It embodies the elegance and wisdom of many experienced luthiers over the years. Thus, as I mentioned earlier, do not hesitate to appreciate and play with it as it is. Within Emacs lies an entire world of knowledge waiting to be discovered.
For all that, mastering such gracious instrument may take time. As one of my favorite blog titles on Emacs suggests, ”Learn Emacs in 10 years”, this journey can indeed be a lifelong commitment. However, with each day of practice, as you gather experience and uncover new areas and techniques, your proficiency evolves. It is an ongoing opus, a journey that every Emacs virtuoso embarked on with the spirit of continuous learning, practicing, and, of course, sharing. Let the freedom of its music play through your fingers.
This project is licensed under the GNU General Public License v3.0 (GPL-3.0), unless an exception is made explicit in context. The GPL is a copyleft license that guarantees the freedom to use, modify, and distribute software. It ensures that users have control over the software they use and promotes collaboration and sharing of knowledge. By requiring that derivative works of GPL-licensed software also be licensed under the GPL, the license ensures that the freedoms it provides are extended to future generations of users and developers.
See the COPYING
file for more information.