Folders and files
| Name | Name | Last commit date | ||
|---|---|---|---|---|
Repository files navigation
#+AUTHOR: Rahul Martim Juliato #+EMAIL: rahul.juliato@gmail.com #+OPTIONS: toc: nil #+HTML: <p align="center"> #+HTML: <img src="https://github.com/LionyxML/emacs-solo/releases/download/assets/emacs-solo-logo.png" alt="Project Logo" width="300"/> #+HTML: <br/> #+HTML: <img src="https://img.shields.io/badge/Emacs-31%2B-green.svg" alt="Emacs 31+"/> #+HTML: <img src="https://img.shields.io/badge/License-GPLv3-blue.svg" alt="GPLv3 License"/> #+HTML: </p> #+HTML: <p align="center"> #+HTML: A <em>fast</em>, <em>powerful</em> and <em>modular</em> Emacs configuration that favors built-in functionality over third-party packages. #+HTML: </p> #+HTML: <p align="center"> #+HTML: <a href="#obligatory-screenshots"><strong>Screenshots</strong></a> · #+HTML: <a href="#as-seen-on-system-crafters"><strong>System Crafters Demo</strong></a> · #+HTML: <a href="#minimum-emacs-version"><strong>Emacs Version</strong></a> · #+HTML: <a href="#optional-dependencies"><strong>Optional Dependencies</strong></a> · #+HTML: <a href="#installation"><strong>Installation</strong></a> · #+HTML: <a href="#disclaimer"><strong>Disclaimer</strong></a> · #+HTML: <a href="#how-do-i"><strong>FAQ</strong></a> #+HTML: </p> #+HTML: <hr /> * Emacs Solo This is what you see as soon as you start Emacs: #+BEGIN_SRC elisp ███████╗███╗ ███╗ █████╗ ██████╗███████╗ ███████╗ ██████╗ ██╗ ██████╗ ██╔════╝████╗ ████║██╔══██╗██╔════╝██╔════╝ ██╔════╝██╔═══██╗██║ ██╔═══██╗ █████╗ ██╔████╔██║███████║██║ ███████╗ ███████╗██║ ██║██║ ██║ ██║ ██╔══╝ ██║╚██╔╝██║██╔══██║██║ ╚════██║ ╚════██║██║ ██║██║ ██║ ██║ ███████╗██║ ╚═╝ ██║██║ ██║╚██████╗███████║ ███████║╚██████╔╝███████╗╚██████╔╝ ╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝ ╚═════╝╚══════╝ ╚══════╝ ╚═════╝ ╚══════╝ ╚═════╝ Loading time : 0.172725 seconds Packages : 0 #+END_SRC Emacs Solo is a configuration I use when I want to go back to the roots and challenge myself by using Emacs with only built-in features. It aims to be minimalist, at least in spirit. Yes, there are over 3000 lines of code, but most of that comes from organizing things cleanly and building small, reusable modules. Compared to full-featured distributions, it's still lean and focused. The configuration favors Emacs built-ins, configured my way. But when something essential is missing (like margin git gutters), a small, hacky workaround is always added. ** Obligatory Screenshots *** Overall View: [[https://github.com/LionyxML/emacs-solo/releases/download/assets/demo-01-overall.png]] #+html:<details open> #+html:<summary><h3>More screenshots here...</h3></summary> *** iComplete (in buffer completion) + Flymake + Gutter: [[https://github.com/LionyxML/emacs-solo/releases/download/assets/demo-02-icomplete-flymake-gutter.png]] *** Help Variable: [[https://github.com/LionyxML/emacs-solo/releases/download/assets/demo-03-help-var.png]] *** iComplete Vertical: [[https://github.com/LionyxML/emacs-solo/releases/download/assets/demo-04-icomplete-vertical.png]] *** Eshell: [[https://github.com/LionyxML/emacs-solo/releases/download/assets/demo-05-eshell.png]] *** Dired + Gutter: [[https://github.com/LionyxML/emacs-solo/releases/download/assets/demo-06-dired-with-gutter.png]] [[https://github.com/LionyxML/emacs-solo/releases/download/assets/demo-07-dired-with-gutter-2.png]] *** Well behaved mode-line: [[https://github.com/LionyxML/emacs-solo/releases/download/assets/demo-08-mode-line.png]] *** In Emacs Solo you find configurations for: [[https://github.com/LionyxML/emacs-solo/releases/download/assets/demo-09-single-init-file-with-sections.png]] *** Emacs Solo also has a lot of extra mini-packages built-in: [[https://github.com/LionyxML/emacs-solo/releases/download/assets/demo-10-single-init-file-with-sections-2.png]] You can use =C-c d= or =M-x container-menu RET= to open a podman / docker container manager. [[https://github.com/LionyxML/emacs-solo/releases/download/assets/demo-12-container-management.png]] Or you can use =C-c G= or =M-x gh-menu RET= to open a =gh= (github cli) UI: [[https://github.com/LionyxML/emacs-solo/releases/download/assets/demo-13-gh-1.png]] [[https://github.com/LionyxML/emacs-solo/releases/download/assets/demo-13-gh-2.png]] Emacs Solo also ships with some very cool themes! We've got: **** Crafters [[https://github.com/LionyxML/emacs-solo/releases/download/assets/demo-14-tema-crafters.png]] **** Catppuccin [[https://github.com/LionyxML/emacs-solo/releases/download/assets/demo-14-tema-catppuccin.png]] **** GITS [[https://github.com/LionyxML/emacs-solo/releases/download/assets/demo-14-tema-gits.png]] **** Matrix [[https://github.com/LionyxML/emacs-solo/releases/download/assets/demo-14-tema-matrix.png]] And much more! #+html:</details> ** As seen on System Crafters! Also, check out the full demo of =Emacs Solo= in action, as seen on the System Crafters channel. In this video, David Wilson explores and learns from the configuration, showing how different settings and approaches are applied to create a more efficient and personalized Emacs setup. [[https://www.youtube.com/live/j_2QkCcf8zE?si=e8qvIFdyuV9j7d_y&t=1433][file:http://img.youtube.com/vi/j_2QkCcf8zE/0.jpg]] ** Minimum Emacs Version Emacs Solo always requires the latest stable release of Emacs, which is currently: =31.1= However, some bleeding-edge features may be tested as well. For those, you’ll need to compile Emacs from the master branch. I do my best to mark these features with the =EMACS-32= tag. ** Optional Dependencies It is recommended you have these programs in your system: - =ripgrep= (rg) This provides quicker project grep and xref navigation. If you opt to use regular =grep=, reset the customization of variable =grep-command=. - =ghostscript= This is necessary if you want to be able to use =doc-view= to see documents like PDFs. - =gls= MacOS comes with an implementation of =ls= that misses some nice switches from the gnu implementation (=gls= on homebrew). If you opt to use MacOS default =ls= you might need to change the =dired-listing-switches= variable. - =curl= Only needed if you'd like to upload text/images directly to 0x0.st site from Emacs Solo, by using either =emacs-solo/0x0-upload-text= or =emacs-solo/0x0-upload-file=. Also used for =emacs-solo-weather=, =emacs-solo-rate= and =emacs-solo-how-in= (cheat.sh queries). - =wget= If present on the system, emacs-solo =newsticker= config uses it instead of the internal fetcher. - =mpv= Only needed if you'd like to play videos directly from news in =newsticker=, play music from dired with dired music player =C-c m=, play something from a m3u file with =M-x m3u-visualizer-open-buffer=, listen to online radio with =C-c r=, or play YouTube results from =emacs-solo-yt=. - =rsync= Only needed if you'd like to use =emacs-solo/dired-rsync-copy=. - =ollama= Only needed if you'd like to use =emacs-solo/ollama-run-model=. - =gemini-cli= Only needed if you'd like to use =emacs-solo/gemini-chat=. - =claude= Only needed if you'd like to use =emacs-solo/claude-chat=. - =khard= Only needed if you'd like to use =emacs-solo/khard-...= functions. - =yt-dlp= Only needed if you'd like to use =youtube-search-async= from =emacs-solo-yt=. - =gh= (GitHub CLI) Only needed if you'd like to use the GitHub interface from =emacs-solo-gh= (PRs, issues, notifications). - =docker= / =podman= Only needed if you'd like to use the container management UI from =emacs-solo-container=. - =biome= / =prettier= / =shfmt= Only needed if you'd like to use the format-on-save feature from =emacs-solo-formatter=. The formatter is resolved per-project (local install preferred over global). - =eslint= Only needed if you'd like to use the Flymake ESLint backend from =emacs-solo-flymake-eslint=. - =languagetool= Only needed if you'd like to use the Flymake LanguageTool backend (grammar/spelling on prose) from =emacs-solo-flymake-languagetool=. Toggle it per buffer with =C-c ! C-t=, or set =emacs-solo-enable-flymake-languagetool= to =t= to have it on from the start in =text-mode= buffers. =C-c ! L= picks a language, =C-c ! C-l= cycles the favorites. - =rassumfrassum= Only needed if you'd like to use multiple LSP servers per buffer. In order to proper copy/paste from terminals (TUI), you need: - =pbcopy/pbpaste= (macOS) - =clip.exe/powershell.exe= (WSL) - =wl-copy/wl-paste= (Linux / FreeBSD with Wayland) - =xclip= (Linux / FreeBSD with Xorg) ** Installation Clone this repository into a directory of your liking and run Emacs with: #+BEGIN_SRC sh emacs --init-directory=YOUR_DIR #+END_SRC You can also simply copy *init.el*, *early-init.el* and the *lisp/* directory into any folder and issue the same command as above. And that's it, happy hacking! 🐂 ** Project Structure The configuration is split into two layers: - =init.el= / =early-init.el= — core configuration using Emacs built-ins. - =lisp/= — self-contained modules loaded via =require= at the end of =init.el=. ** Load Order & Where to Put Your Changes Emacs Solo loads in a fixed sequence. There are three optional files you can drop into your =user-emacs-directory= (the same folder as =init.el=) to extend it *without ever editing the tracked files*, so you stay easy to update: #+BEGIN_SRC text ╔═══════════════╗ ╔═══════════════════════╗ ║ early-init.el ║ ───▶ ║ private-early-init.el ║ ╚═══════════════╝ ╚═══════════════════════╝ ✗ DON'T TOUCH ✎ TOUCH (yours, optional) tracked / upstream early overrides: frame, fonts, loads custom-vars.el default-frame-alist, GC, flash colors │ ▼ ╔═══════════════╗ ╔═══════════════════════╗ ║ init.el ║ ───▶ ║ private.el ║ ╚═══════════════╝ ╚═══════════════════════╝ ✗ DON'T TOUCH ✎ TOUCH (yours, optional) tracked / upstream everything else: keybindings, reloads custom-vars, commands, mail/IRC/weather flows, requires lisp/* overrides... (loaded 0.5s idle after start) ───▶ loads ✗ stays updatable, leave alone ✎ edit freely #+END_SRC Rule of thumb: *never edit the =✗= files* (=early-init.el=, =init.el=, =lisp/*=) — leaving them untouched is what keeps you conflict-free when pulling upstream. Put your own code in the =✎= files instead. Pick the file by *when* your code needs to run: - =custom-vars.el= — settings written by =M-x customize=. Managed for you; you normally don't edit it by hand. - =private-early-init.el= — runs at the *end of* =early-init.el=, before any package or UI is set up. Use it only for things that must happen early: frame parameters, fonts, =default-frame-alist=, the flash-of-light colors, GC tweaks. Keep it small. - =private.el= — runs *after* startup (lazily, on first idle). This is the right place for almost everything: keybindings, custom commands, mail/IRC/weather flows, use-package for some 3rd party package you might need, etc. All three are loaded with =noerror= / =file-exists-p= guards, so they are *entirely optional* — absent files are silently skipped. Add only what you need and pull from upstream without conflicts. ** Disclaimer I’m happy to share this configuration with a catchy name, and I’d be genuinely delighted if you find it useful. 🙂 However, this is *not* intended to be a distribution. This means I may not cover every user's needs, nor will I accept every contribution that pushes it in that direction. I use this configuration daily for both personal and professional work, and like any custom setup, it reflects my own preferences. For example, this config does not include Python-specific settings, whether for Eglot or Tree-sitter. Since this is a real working setup and I’m not currently using Python, its absence might seem like an oversight. If you'd like to add your own modifications while staying up to date with Emacs Solo, simply create a =private.el= file in the same directory as =init.el=. A hook is already in place to load this private file after Emacs initializes. Of course, you can also fork it! (please do 😊) ** How do I... A FAQ-like section of common questions on how to do X with only Emacs Solo. #+html:<details open> #+html:<summary><h3>So, how do I...</h3></summary> *** 1.) Copy the current word under cursor? The usual answer is *M-b* to go back to the beginning of the word. *C-M-SPC* to expand the selection to the end of the word and *M-w*. *Custom Emacs Solo Solution*: Use the isearch way to search a word (it has better completion than C-M-SPC), like *M-s M-.* you can now just *M-w*. *** 2.) Edit multiple search entries at once? #+BEGIN_SRC text Original problem: I usually consult-outline, then embark-collect and wgrep... #+END_SRC You can start by using *occur*, or using *isearch* and then moving to occur. Next start the edit mode of the occur buffer with *e*. Make your changes, apply it with *C-c C-c* From Emacs 30.1 onward you can also use the combo: =replace-regexp-as-diff= for replacements in a single buffer, =multi-replace-regexp-as-diff= for multiple buffers, and =dired-do-replace-regexp-as-diff= to perform replace-regexp-as-diff *** 3.) Edit multiple search entries between several files at once? #+BEGIN_SRC text Original problem: I usually consult-grep, then use embark collect and wgrep... #+END_SRC Open dired on the root folder of where you search will happen. Mark some files and or folders with *m*. Use =dired-do-query-replace-regexp= or in a dired buffer hit =Q=. Confirm it all or one by one, use *?* to check the options. From Emacs 30.1 onward you can also use the combo: =replace-regexp-as-diff= for replacements in a single buffer, =multi-replace-regexp-as-diff= for multiple buffers, and =dired-do-replace-regexp-as-diff= to perform replace-regexp-as-diff *** 4.) Read news, like with elfeed? You have two built-in options on Emacs. - =M-x gnus= - =M-x newsticker-treeview= *** 5.) How do I see logs and their diffs? =C-x v L= on a file inside your version controlled file. And over the line you have the commit, press =d= for diffing. If you wanna diff a range, mark the lines starting with =C-SPC= on the first line of the range, and again =C-SPC= in the last line of the range (the content of what you want must be selected, if the cursor is on first column of the line it won't be included), now use =d= to diff. *** 6.) How do I revert a hunk? =C-x v == will open the diff panel for the current file, restrict it to the hunk you'd like to revert with =r=, revert the direction of the diff with =R= and apply the diff with =C-c C-a=. From Emacs 31, we also have =C-c M-r= (=diff-revert-and-kill=), when on buffers generated by =C-x v == and =C-x v D=. *** 7.) Use (neo)vi(m) keybindings (aka Evil keybindings)? Emacs comes with =viper= which is a =vi= emulator. This means a lot of modern editing capabilities are missing. Take a look at the =use-package Emacs Solo-viper-extensions= section of the =init.el= file. Emacs Solo extends viper mode to include a bunch of more modern =evil-like= bindings. Just give it a try ;) =M-x viper-mode= *** 8.) Temporarily highlight some word? Use the powers of =highlight-regexp=! Over a word you want to make highlighted use =M-s h .= You can repeat it to other words and Emacs will handle different colors for you. To remove a highlight use =M-s h u= and select the highlighted regexp on the list. Find out about more options regarding highlighting with =M-s h ?=. *** 9.) Know what is changed when closing Emacs or several files? It is a common thing trying to close Emacs with =C-x C-c= just to find out one of your buffers has some modification and now Emacs asks if you'd like to save, override, etc. Emacs Solo provides the extra option =d=, which will generate a diff of the current file being asked to take action, so you can see if saving is needed. *** 10.) Show/Hide (toggle) hidden files in Dired? Use =dired-omit-mode=, which you can toggle with =C-x M-o=. Notice that this mode uses the regular expression defined in the =dired-omit-files= variable. Emacs Solo already customizes this to ignore files matching =^\\.= *** 11.) Open multiple terms/shells? Ever felt the need of some =multi-term= package on Emacs? Well, you don't really need it, at least not with the internal implementations of terminals and =eshell=. Just use the =C-u= universal argument command before calling your term/shell, like: =C-u M-x eshell= or =C-u C-x p e= or =C-u M-x term=, and so on. Now you have another instance of your term to work with, repeat this pattern if you need more instances. *** 12.) How do I select a single hunk out of many? From Emacs 31, we have after =C-x v == a new =C-c RET n= (=diff-delete-other-hunks=) option to do so. *** 13.) How do I edit commit messages? From =C-x v L=, you can press =e= and you'll be editing the commit message. This is available from Emacs 31 onward. *** 14.) How do I amend commits? From =C-x v v=, you can press =C-c C-e= and you'll be on 'amend' mode. *** 15.) Zoom fonts Only the current buffer: =C-x C--= =C-x C-+= / =C-x C-== =C-x C-0= The whole interface: =C-x C-M--= =C-x C-M-+= / =C-x C-M-= =C-x C-M-0= *** 16.) Visit an URL With =global-goto-address-mode= turned on, you can =C-c RET= over a link to open it on your default browser. =C-u C-c RET= will open it on the secondary browser, recommended: Emacs Solo defaults: #+BEGIN_SRC emacs-lisp (setq global-goto-address-mode t) (setq browse-url-secondary-browser-function 'eww-browse-url) #+END_SRC *** 17.) Increase/Decrease the resolution of PDFs The =doc-view-resolution= variable is the way to go. *** 18.) Open an URL under point Given =global-goto-address-mode= is set to =t=, we can =C-c RET= to url under point. This will use your system default browser. If you'd like to use =EWW= and never leave Emacs, simply set =browse-url-secondary-browser-function= to ='eww-browse-url=. This way you can =C-u C-c RET=. *** 19.) Open a file when path is under point Use =C-x f= and then =M-n= to get the path under point fed to =file-find=. *** 20.) Kill buffer and close window Usually =C-x k= kills a buffer, but it keeps the window opened. If you wish to kill and close window, use =C-x 4 0= (=kill-buffer-and-window=). *** 21.) Attach multiple files in message-mode? When on =gnus= and composing a message, if you'd like to attach multiple files using dired, just split with dired =C-x 4 d=, use =M-x turn-on-gnus-dired-mode RET=, mark files with =m= and use =C-c RET C-a= to populate your composing buffer. *** 22.) Use multiple LSP servers per buffer? For this you need to use an external LSP multiplexer, so Eglot can connect to it. Eglot's author made his own implementation of such a program: [[https://github.com/joaotavora/rassumfrassum]]. Basically =C-u M-x eglot= and enter =rass -- server1 [options] -- server2 [options] --...=. You can read more about it in this blogpost: [[https://www.rahuljuliato.com/posts/eglot-rassumfrassum]]. #+html:</details>