The defaults are absolutely awful. The editor is pretty unusable without at least a hundred lines of ELisp: basic stuff like CUA, setting up fonts, disabling useless UI clutter, delete-selection-mode, rebinding a couple keys, setting up packages, explaining where to find coreutils on BSD systems, etc. And then you get to packages.
If you want to do anything remotely useful, you're gonna have to start installing random stuff from GNU ELPA, MELPA, etc. There's no package pinning or SemVer so you get what you get, packages sometimes break in mysterious ways. So you write more code to work around various broken stuff in packages.
I've gone through several iterations of throwing away my entire init.el and starting from scratch with just the bare minimum needed to get work done. At the current iteration, ELisp is still ~33% of all source code volume in my dotfiles repo[0]. I haven't pushed my latest effort to unbreak "jump to definition" (because apparently dumb-jump is deprecated??? and I need to use xref??? but it doesn't work???) so that'll likely go up.
I never wanted to write enough ELisp to justify calling it a program, but Emacs made me.
But then there is magit[1], which is so damn good, it makes every other VCS interface look like a sad joke. Which is problematic, because configuring Emacs itself is a bit of a sad joke. I want to just write code, not write code to make just writing code less of a pain. :(
The story is as old as Emacs itself. Many people (if not most) start using Emacs by treating it as "an editor". They think they have to configure it by tweaking settings and changing various options.
But Emacs is nothing but clay, an assortment of Lego pieces, building blocks, programmers' equivalent of IKEA furniture, DYI toolkit, etc.
It's not an editor, it's material for you to build your own editor.
> I never wanted to write enough ELisp
That's the mistake Emacs newcomers often make. If you truly want to master Emacs, there's no way around it - you have to accept Emacs Lisp. With all its flaws and incredible power.
If you hate Lisp because it's not like languages you learned and used before; it doesn't look like Python, Javascript or Ruby, then maybe you're missing something.
One needs to set aside their prejudice about parenthesis, learn structural editing commands, understand REPL-driven workflow, and then, once they are over that initial barrier, they may realize that all those [more popular] languages borrowed heavily from Lisp, and Lisp is an extremely nice programming language.
True craftsmen very often make their own tools. I am of course biased here, but in all honesty, every single professional I know, whom I can count as an Emacs power-user or even a master; Every single one of them is truly an incredible hacker.
ps.: "you" used here in the general sense, not targeted to the OC personally.
I've only been using Emacs for 20ish years. (That's more than half of my life.)
At some point I even used Emacs to read my email and RSS, but the stability problems with a single process handling both that and coding led me to try crazy workarounds, like running two instances... Which created problems of its own... Which was all eventually solved by moving back to dedicated apps for mail and news.
> If you hate Lisp because it's not like languages you learned and used before; it doesn't look like Python, Javascript or Ruby, then maybe you're missing something.
I really like Scheme, have had a good time with Common Lisp, wrote my own Lisp dialects for fun; in fact ELisp as a language is not that bad, once you get used to dynamic scoping etc.
My problem is the fact that you have to write actual software to work around deficiencies in your tools. If Emacs was magically rewritten overnight, bug-for-bug, in Scheme, Python, Rust, whatever else, I don't think it would change anything. The problem isn't the language, the problem is the editor/framework/runtime isn't aging well; GuileEmacs or REmacs were/are trying to address the internals, but the problems are running deep across every layer, including incidents like RMS trying to veto emoji support.
All I ask is that an editor do ~80% of the stuff that ~80% of its users want it to do, out of the box, without hassle. VSCode gets it, Jetbrains gets it, heck Notepad gets it. You don't need to write extra code just to convince e.g. GEdit to not shit itself when /bin/ls comes from a BSD userland.
Again, I'd switch to VSCode right now, if it had anything even remotely as good as magit.
>I am of course biased here, but in all honesty, every single professional I know, whom I can count as an Emacs power-user or even a master; Every single one of them is truly an incredible hacker.
Could be explained as selection bias, instead of a causal factor.
I find them awful too but many people are fine with these defaults.
> There's no package pinning or SemVer so you get what you get, packages sometimes break in mysterious ways. So you write more code to work around various broken stuff in packages.
There's however a way around it which you may like, seen your complaint... What I do, and it's not unheard of but definitely not the most common when it comes to Emacs, is that I load specific versions of packages. And I commit my entire Emacs setup in Git.
So when I upgrade packages (or install new ones) if anything goes wrong I can just checkout/restore a known fully working state.
There are trade offs when versioning your entire "emacs.d" directory but honestly I don't see many downsides. And I share that emacs.d between several user accounts / machines and any change I made are one "git pull" away.
When I start Emacs I don't check for packages / refresh package contents or anything like that: I only do that when I actually plan to upgrade packages (which I do maybe once every six months or so).
> I want to just write code, not write code to make just writing code less of a pain.
I'd say that's kinda a big selling point of Emacs though: you can write elisp code to make anything you do (not just writing code) less of a pain.
> I'd say that's kinda a big selling point of Emacs though: you can write elisp code to make anything you do (not just writing code) less of a pain.
I agree in principle, but in practice, I find myself writing a lot of ELisp just to work around Emacs' shortcomings. E.g. on macOS, to support dark/light theme switching integrated with the rest of the system, I need an external program[0], a shell script to tell that program to call emacsclient, a LaunchAgent to keep it running, an unholy build of Emacs with all of the GNU-unapproved Cocoa integrations that some kind soul is maintaining, and only THEN a piece of ELisp (which is also calling out to AppleScript) to actually change the theme[1]. And as I wrote this, I realised half of this glue didn't even make it into version control.
I've been using Emacs for about 20 years, and with every passing year I just wish there was *less* ELisp for me to think about. The actual useful customisations (like adding the +x bit on shell scripts) are few and far between, most of it is just glue and fixes.
> a shell script to tell that program to call emacsclient, a LaunchAgent to keep it running, an unholy build of Emacs with all of the GNU-unapproved Cocoa integrations that some kind soul is maintaining, and only THEN a piece of ELisp (which is also calling out to AppleScript) to actually change the theme[1]
Why isn't your Emacs session running dark-notify itself, reading its output, and switching accordingly? That seems to remove the need for shell script running emacsclient, the launch agent, and the OSA integration. (But also, I thought ns-do-applescript was stock Emacs? At least I had some ELisp using it and I only ever used emacsformacosox.)
> Why isn't your Emacs session running dark-notify itself, reading its output, and switching accordingly?
Thanks for the hint. Maybe I would try that first, if it popped into my head when I was originally writing it; but at this point, it works, and I want less stuff in init.el.
Also I will likely reuse the dark-notify script to change the theme in Terminal.app as well, and Terminal.app doesn't have an ELisp runtime. (Also very weird that Apple's own software doesn't properly support this.)
> But also, I thought ns-do-applescript was stock Emacs?
I don't know. I've switched to macOS only a couple years ago, and the Emacs build I've initially used didn't have it.
I've found using Doom Emacs to be a lot easier than handrolling an init file.
I understand the gripes though. Emacs really shines when you have a workflow that is poorly supported by mainstream tooling and you want to write your own. I don't know of any other editor that allows you to add keyboard shortcuts/commands/functionality that easily.
I generally like both Doom and Spacemacs, but they are an additional, huge layer on top of an already complex and complicated editor/runtime/framework. They're great when they give you 99% of what you need, but pretty terrible once you have to start digging.
My dream config file is probably 10-20 lines of my actual preferences, not 40-60k lines on top of which I have to add another several hundred.
Exactly the difference between emacs and most of the software world is that for most of the software world your post would end at “The defaults are absolutely awful. The editor is pretty unusable.”
"Sane defaults" is a thing, but the sanity supporting the defaults changes every couple of decades.
E.g., re the GP's complaint about lack of CUA: CUA is an IBM effort to standardize a dozen shortcuts that are considered more or less universally useful.
But Emacs predates CUA by a couple of decades, and supports easy access to an insanely wider (two, three orders of magnitude) space of functionality.
If you want CUA, Notepad is 100% conformant.
Disclaimer: Yes I would adore a clean pure new Emacs, but given the dearth of Stallmans, the new Emacs would take even longer to not have CUA by default.
Me too! I've always been baffled by the hate. If you come from vim, just use evil, install Doom Emacs or whatever. End of the day it's all just arbitrary muscle memory so once you get used to it all other keybindings (bar perhap vim) seems absurd.
Evil-mode is incredible, for me Emacs with evil is the best vi-derived editor in the world, beating neovim and vim by miles. But as an ex-Vim user and fairly recent Emacs convert I feel like a guest in a clubhouse full of old timers. It wouldn't be right for me to swagger around their domain, demanding they change things up to accommodate me. Evil mode is already a much warmer welcome than I'm entitled to, so what if it takes a line or two to configure? I'm very grateful to have what I have now, I don't need or want Emacs defaults changed.
I'm one of those weirdos that disable transient-mark-mode because I don't feel like it does the right thing for all situations where you use mark. Sometimes I want to use mark like a cheap bookmark and C-x C-x between mark and point, sometimes I use the rectangle commands and for those transient-mark-mode only makes things worse.
(I know the CUA mode has some fancy rectangle features, but that's not for me)
I enjoyed your article but I think the solution for me is to leave TMM disabled, though it makes me curious about what else I've missed in the last decade(s). You just made a sale of your book.
Me too :) One of the reasons why I fell in love with macOS - every text editing widget in the whole OS is very consistently using the basic Emacs keys like C-a, C-e, C-k, C-y, C-t, etc. That also makes Xcode (and most other IDEs) much less awful right out of the box ;)
I don't care for the defaults either, but I also don't care for CUA, so if you had your way the defaults would be just as objectionable to me as they are now. Since you can't make everybody happy, I think the best way forward is to continue the status quo, so at least you won't be forcing configuration on users who were previously fine with the default.
i too dislike CUA. if you use the terminal CUA usually does not work and insteas we get CUA-ish hacks. emacs bindings are usually readily available on the other hand
In other applications I mostly avoid the ctrl-v/ctrl-c and use X's highlighting and middleclicking system instead. When those aren't available, I actually prefer context menu copy/paste entries to the CUA shortcuts.
Mastering emacs is an amazing resource and one I have used countless times over the years. I have used emacs since my time in college (~14 years ago) and I still discover new things about it -- a lot from "mastering emacs". Anyway, thanks for all the great content!
Hey Mickey, another happy reader here. One question, looking at your site, I see mention of an "Emacs 28 edition." I've got v3 of the ebook, is there an update version from here?
I have been using plain out-of-the-box emacs for literally 40+ years. (I wrote the initial version of one of the commands that’s now built-in.) I do probably a third of my data cleaning work in keyboard macros. I am so used to and efficient with plain emacs that most customization just seems like unnecessary decoration — with the exception of major language modes, because language specific fwd/bkwd (s)expr is so useful.
Emacs in itself is worth studying to become better developer. The best minds in the computer industry have worked on this editor's design. For example I used to think single namespace in elisp is bad. But after used it for a while it feels having single namespace is probably good for cognitive ease. In contrast C++ offers namespace but when "using namespace" is used at the top of the file, the rest of the file contains only part of the namespace. This makes it harder to grep while reading source code. Although emacs have longer symbol names its cognitively much easier.
Emacs docs aren't perfect but they are a major, major strength of it and I wish so much other software would learn from it. The devs are really responsive too - good guys!
Please, try to get into the habit of not only sharing the keystrokes but also commands they bind to. With all different Emacs "distros" popping up, it's hard to track the bindings. "Is it in vanilla, Doom or Spacemacs?..."
My hope is for a convention to emerge where the proper etiquette of Emacs pedagogy would be always mentioning the command.
Also, I think you meant to say C-h r s <search_term>, where <s> binds to Info-search
Personally as somebody who is NOT a software dev Emacs is my favorite tool on Linux and I usually have 1 or 2 windows open at all times. Tramp in particular is like magic, I can natively browse remote directories, copy and edit files and run a terminal remotely through eshell. This is STILL something that VSCode struggles with, the Microsoft "Remote" extension has /bin/bash hardcoded in and fails if the remote machine doesn't have it.
I bought Mastering emacs on a whim after reading it but am still looking for more in-depth stuff about working with Emacs Lisp in particular.
I can do basic stuff alright, being able to jump into source in particular is very helpful to at least find snippets of code doing what I want, but I don't have a good sense of how to work effectively in it.
(For example, when trying to test things out I haven't really found a way much better than typing into scratch, selecting code and running it while staring at messages....)
I would gladly pay money to watch somebody just write and debug emacs lisp code for half an hour cuz I feel wanting for usability when trying to work with this.
> (For example, when trying to test things out I haven't really found a way much better than typing into scratch, selecting code and running it while staring at messages....)
Are you talking about when you're noodling, trying to figure how things work, or actually trying to build something?
For playing around, I found that scratch works ok, but I found a better workflow.
I end up using a daily note in org-roam, with #begin_src elisp... I then tag the heading with :REFILE:ELISP: so I can always find it later. Basically evaluate everything inline within that org-babel block.
When I'm building something, or driving towards a specific goal, I use buttercup [0] to write actual unit tests. If I squint, it kinda looks like TDD.
Finally, for debugging of running elisp, take a look at edebug [1]. It's a pretty standard looking debugger (if you used something like gdb). By default emacs uses debug which is not as friendly.
Just stumbled upon edebug yesterday after looking through the options that you can put in a `declare` form and it's become an invaluable portion of my workflow; if I may ask a noob question, is there an easy way to keep a persistent eye on a closure or arbitrary set of a variables, and is there a way to debug-step through disassembled code? Totally okay if you don't know off the top of your head, I'll have time to search for these eventually.
> is there a way to debug-step through disassembled code
That's what I've been using it for. Once you find a function you're interested in, call `eval-defun` in it. Next time it's executed you should get a prompt with a stack trace and ability to step through the code (with `n`) or evaluate an expression in context (`e`).
> if I may ask a noob question, is there an easy way to keep a persistent eye on a closure or arbitrary set of a variables
I discovered edebug last week when I finally had to; so we're in the same boat. My guess is "yes" :)
Thanks for getting back to me! I didn't know about evaluation in the current context, which should let me inspect and explore the environment like I wanted to.
To clarify for anyone reading, `eval-defun` needs to be called with a prefix argument to instrument the first function, and `edebug-instrument-callee` (`I`) can be used to instrument the function following point in edebug's source-code-buffer, which I think is what you reffered to as a backtrace; I printed the edebug manual and brought it to work with me, in which I see that you can get a real back trace by calling `edebug-pop-to-backtrace` (`d`).
By `disassembled `, I meant bytecode, which after thinking about for a bit, maybe it could be done with lapcode, which is like bytecode made of s-expressions, but what I'd really want is a way to see the stack. Anyway, that seems like a whole 'nother beast, outside the scope of edebug.
Edit: I was looking for an evaluation list, see `edebug-visit-eval-list` (`E`) and `edebug-update-eval-list` (`C-c C-u`) c:
There’s already been some good replies to your comments, but I want to throw in one more simple suggestion. You can learn a lot about Emacs lisp by reading and modifying other developers config files. Pick a few of the more complete well documented configurations and go through them picking out useful parts that you can assemble into your own config.
You will end up with just what you want and will learn more eLisp along the way.
I’ve done this for years and found it very helpful. Also learn how to use the scratch buffer — e.g. you can write a function and try it out and see it’s output easily with [C-j], that’s bound to the eval-print-last-sexpr function.
The built in help is amazing, there are at least 50 commands that provide some form of help or documentation, I use 3 very heavily: [C-h f] that’s describe-function, [C-h v] describe-variable, and [C-h k] describe-key.
As an Emacs user, I definitely enjoy always finding new things about it. Thanks to these kinds of discoveries I've been able to make my .emacs.d smaller and smaller in tiny increments due to being able to replace various packages downloaded from ELPA/MELPA with built-in ones.
Excellent! This is a wonderful function I did not know about. - I learn a lot about Emacs from Mickey Petersen, his book "Mastering Emacs" (highly recommended), and his articles on r/emacs. Thank you again for this article.
Emacs is an amazing editor and never ceases to surprise in a positive way.
The only complaint I have about Emacs is its look and feel and a lack of a usable Sidebar. If they could "steal" that from Sublime Text it would be perfect.
I think that the look and feel is what I like more about Emacs. Having such a complete environment full screen without much space waster makes me much more focused
to add to this, if there are things the speed bar doesn't do that you wish it did, the chance that there's no package for {specific thing you want} is vanishingly small.
The primary difficulty is in being able to find exactly what you're looking for. Precise terminology and specific terms of art (i.e. linting, directory traversal, syntax hiliting) will help here.
For me, speedbar is a no-go, since it opens in a new frame. If I switch to browser, and then back to Emacs buffer, it is still hidden behind a browser windows.
From sidebar, what I look is an exact equivalent of Sublime Text's sidebar.
- It opens in the same frame
- I can add/pin a folder tree there, it should be operable by mouse (open/close subtree, click to open a file in buffer or switch to it)
- Have a list of open files / buffers - clicking on it should switch to buffer
Currently looking at treemacs and neotree that were suggested by me. Previously I was giving up trying to configure them, now I may be more persistent.
Thanks! Never knew this existed. Would have been better if the sidebar was not shown in a new frame. There are third-party customizations to launch speedbar in the same frame though.
The defaults are absolutely awful. The editor is pretty unusable without at least a hundred lines of ELisp: basic stuff like CUA, setting up fonts, disabling useless UI clutter, delete-selection-mode, rebinding a couple keys, setting up packages, explaining where to find coreutils on BSD systems, etc. And then you get to packages.
If you want to do anything remotely useful, you're gonna have to start installing random stuff from GNU ELPA, MELPA, etc. There's no package pinning or SemVer so you get what you get, packages sometimes break in mysterious ways. So you write more code to work around various broken stuff in packages.
I've gone through several iterations of throwing away my entire init.el and starting from scratch with just the bare minimum needed to get work done. At the current iteration, ELisp is still ~33% of all source code volume in my dotfiles repo[0]. I haven't pushed my latest effort to unbreak "jump to definition" (because apparently dumb-jump is deprecated??? and I need to use xref??? but it doesn't work???) so that'll likely go up.
I never wanted to write enough ELisp to justify calling it a program, but Emacs made me.
But then there is magit[1], which is so damn good, it makes every other VCS interface look like a sad joke. Which is problematic, because configuring Emacs itself is a bit of a sad joke. I want to just write code, not write code to make just writing code less of a pain. :(
[0]: https://github.com/rollcat/dotfiles
[1]: https://magit.vc