Hacker News new | past | comments | ask | show | jobs | submit login
The Emacs Package Developer's Handbook (2017) (alphapapa.github.io)
156 points by rauhl on March 8, 2019 | hide | past | favorite | 25 comments



Oooh, https://gitlab.com/ambrevar/emacs-gif-screencast looks interesting.

There's a ton of good stuff in here … there goes my weekend. The organisation is a bit idiosyncratic, but I think it works.


https://asciinema.org/

I sometimes record deployments, bug fixes, refactoring, etc...


I just started reading the geiser.el elisp code with the long-term objective of obtaining evaluation support for kawa scheme. I don't feel I master elisp yet but I'm at the point where I'm not afraid of hacking together some dirty elisp code. Even so, I didn't think there were so many relevant topics I didn't even hear about. Great resource for my objective and skill level I guess.


Interesting, I was just starting to dig into geiser as well! (But for Gerbil scheme, though Kawa is interesting to me as well)


I'm interested in kawa for scripting an application I'm trying to make in java/scala. Scala's Ammonite somehow works too and I just wrote one of those dirty hacks to wrap an ammonite repl running in a term window so I could use ammonite's completion and execution in an org-mode buffer to explore/script things. However, sometimes lisps make interactive exploring a little simpler and that's why I initially embedded clojure. Clojure's emacs tooling is spectacular, so much that it feels like I'm actually extending emacs with java libraries. But with clojure I had 2 problems:

- embedding a clojure repl the usual way after the update to java 11 started giving some error I couldn't solve. Sure, I could just juse java 8. Or use my project as a jar dependency, but doing java -jar ... and already having a nRepl server running is simpler than adding a jar to the classpath from a repl

- licensing: I still don't know which license to use between bsd/apache and gpl, but in case I go with the gpl there is that epl/gpl incompatibility for distribution. However, even for this I think there are workarounds that would be ok for my case

The point is that kawa doesn't have these last 2 problems at all, and writing geiser support is a good elisp practice that also produces something that may reveal itself useful later.

And that's why I'm interested in continuing the geiser-kawa attempt that https://gitlab.com/mthl posted at https://gitlab.com/jaor/geiser/issues/55. I evaluated several other languages/platforms before choosing java, but eventually only java and javascript had the killer library. I went java.


I am always amazed at how many libraries and tools there are for programming in Elisp. One of the things that make it so fun.


It's always been a really rich environment, but it's amazing how much dynamism the whole ecosystem gained by introducing package.el and ELPA, plus to a lesser extent use-package.

Without package management, keeping even relatively simple Emacs setups working was not that easy. Now, it's trivial. And thanks to that lots of parts have been modernized and the whole community is really vibrant.

Emacs has now a really nice completion framework (avy) and auto-complete (company). Plus, IMHO the best git porcelain of any platform (magit), outliner (org) and mail user agent (notmuch, plus some bits of gnus).


Yeah sometimes I feel like I don't want to use emacs anymore, but then I think about magit and org.

After using spacemacs for a couple years, I've started rebuilding my own. There was too much stuff going on I didn't understand and when something breaks I have no idea what to do.

Now that I know about general, ivy/swiper/counsel, use-package, and some of the other building blocks... It's pretty cool.

You know what it reminds me of? npm ~ducks~


I do agree that building your own is the only way to progress learning Emacs and most complex pieces of software. I would also add that relying on as few packages as possible, and some that are well-known and maintained is important.

My .emacs is very short, and I strive to simplify it as much as I can so that it doesn't become fragile or a liability to maintain. It's just a bit of setqs, use-package boilerplate, and 2-liner configurations for ido, company, org, magit, notmuch, pdf-tools, auctex, ess, anaconda and a few others.

That way I avoid npm-like insanities.


Do you live as much as possible in Emacs?

How do you deal psychologically with all the niceties that you give up with so little configuration?

The first innovation outside of Emacs that springs to mind is find-and-replace that lets you easily switch between literal, case-insensitive, regex, current line/selection/whole file, and current file/across multiple files.

Do you just have to tell yourself, “Well, other environments have such niceties, but I’m giving them up in exchange for other niceties that Emacs offers?”


> The first innovation outside of Emacs that springs to mind is find-and-replace that lets you easily switch between literal, case-insensitive, regex, current line/selection/whole file, and current file/across multiple files.

Not sure what you mean, but from my experience, you can do all that in Emacs. They're not one feature, but a couple distinct one. Incremental find/replace with or without regex, literal, case-insensitive within a buffer is one facility, easily accessible through C-s / C-r / C-M-s / C-M-r keys (they're all for the same feature, just "s" for forwards, "r" for backwards, also press Meta for regexes), you can switch "modes" on the fly, switch to replacement mode, or even show the whole list of matches, each with a single keychord.

Incremental searches across multiple files or open buffers can be done too, though it's not something I've tried personally (I usually pawn off multi-file searches to grep / find+grep combo, which have a built-in support in Emacs, and AFAIR also a polyfill for Windows). Consult [0] for discussion.

Editing-wise, I can't think of an outside-Emacs innovation that couldn't - and wouldn't - get ported over, ending up better than in its source place because of how Emacs deep interoperability makes all features together better than the sum of them. The main convenience you're abandoning when switching from an IDE to Emacs is the lack of deep semantic features - like really smart autocomplete, or high-quality automatic refactors - but with the development and popularization of Language Server Protocol and Debug Adapter Protocol, one can hope this won't be a problem much longer.

--

[0] - https://www.reddit.com/r/emacs/comments/7tf1ln/incremental_s...


Not sure what you mean, but from my experience, you can do all that in Emacs. They're not one feature, but a couple distinct one.

That’s why I said “easily switch between”. As in, a single piece of UI. If you’ve used any modern editor or IDE I’m sure you’ve seen this.

I can't think of an outside-Emacs innovation that couldn't - and wouldn't - get ported over

The person I was talking to uses fairly stock Emacs, so that’s not a useful point.


Although I'm relatively young, I've been using seriously Emacs for a decade an a half. Till quite recently, I only used Emacs for editing code and outlines in Org.

However, I moved a lot of my workflow into Emacs because I became really frustrated with ncurses applications like Mutt. They tend to be little silos that do not compose well with other Unix applications, unlike classical non-interactive Unix utilities. Furthermore, their configuration languages tend to be small, clunky and inflexible DSLs.

The little epiphany was realising Emacs is not a text editor, but a text-mode Lisp machine. Mostly everything is an elisp function and thus incredibly flexible and dynamic.

These days, I try to compute in 3 platforms: Emacs (for text applications, which covers most of my workflow), a web browser (Firefox, for web applications) and a terminal (xterm, for low-level Unix plumbing). I manage these 3 from a manual tiling window manager (StumpWM). I rarely use native applications.

This setup has brought tons of relief on my previous frustrations with computing. Plus, it's quite simple and mostly portable. I could migrate back to e.g. macOS and I would only need to adjust my window manager.

I think it's also irreducible. Moving web applications into Emacs is likely to cause some friction, and vice versa. I could possibly use Emacs terminal facilities, but I think keeping these separate is less fragile.

The other poster has addressed your other questions really well, I think. I have used IDEs like Visual Studio or Eclipse. And frankly, the 1% I still miss on Emacs for some languages will be covered by the Language Server Protocol.

For new and niche languages, Emacs tends to have great facilities while other IDEs tend to offer no support at all, which for me outweighs everything else. Things like Prolog, Mozart/Oz or Coq have really neat modes for Emacs.


Echoing this sentiment. I find use-package really nice for simplifying one's .emacs. I only use about 17 packages but I decided to go full greybeard and tangle my init file from an org-mode document and use-package helps keep it clean.


"Without package management, keeping even relatively simple Emacs setups working was not that easy. Now, it's trivial."

Trivial, but wide open to getting owned by anyone who puts their malware on to an Emacs package repo.

This is why I still do all my package management by hand. That way I can audit any Emacs package I want before I install or use it.


You probably meant ivy for the completion framework. The avy package is pretty good too (but is not a completion framework).


I suspect because statistically programmers are in their editor, they're just a distraction away from playing with elisp.


> I suspect because statistically programmers are in their editor, they're just a distraction away from playing with elisp.

I think that's one reason, but not the only one. But they all fall in the 'barrier of entry' theme.

You are literally two keystrokes away from being able to replace any running elisp code in your editor (C-x C-e). You have a default scratch buffer every time you start the editor. You don't have to create packages or do anything else to start coding. You can inspect everything, even ask which function is run when you type a character, which will take you right to the source code, which allows you to copy, modify, eval, and then paste it right into your .emacs when you are done.

After that, you just uploaded the file somewhere for other people to use, if you are so inclined. Historically, they would just plop the file right on their .emacs.d.

Now, you can go the extra mile and make a package. Which is comparatively easy as you already have the code written and it just needs a home.

One time, I created a few commands to query Jira (grab issues assigned to me and stuff like that). It took me more time reading Atlassian's spec than it took to code the whole thing.

I've also reproduced the entire ending of Portal (the game) in Emacs, complete with synchronized lyrics, the ascii art and the color scheme (before color-themes was a thing). That was pretty easy to do.

Compare with other editors, even some of the 'cooler' ones (like VS Code). It is not obvious what to do if you want to change something, or where it even is. The config file is not programmable. You need to figure out how to create a package first, and only then start writing code. And that's VSCode. Some don't even allow you that much flexibility, other than maybe invoking shell commands.

And don't get me started on "IDEs" like Eclipse. Last time I extended it, I required two running copies of the environment and a full blown 'project' in order to add a lowly menu entry.


Historically, they would just plop the file right on their .emacs.d

With Emacs I'm more likely to try and extend some part of the editor than I am with Vim. A significant percentage of Vim users make heavy use of plugins; and I feel that "don't do it myself" lends to fewer plugins of higher quality.


> You are literally two keystrokes away from being able to replace any running elisp code in your editor (C-x C-e).

lol, I am actually one keystroke away: F2 pulls up ~/.emacs.d/init.el

(it's actually it's worse than that because F2 actually cycles through my most-used emacs startup files)


I have shaved many elisp yaks in my day.


I think there’s lots of things about elisp the language which make it easy to hack on too. In no particular order:

1. Dynamism+late binding+late failure means that, although it is hard to write fully “correct” code (and correct is ill-defined/impossible), it is very easy to write code that does work in the common cases without having to care about the uncommon cases.

2. Dynamism makes it possible to extend existing code with more functionality. You can get at any function and easily add your own code to run before/after/around it, or just redefine it to do what you want.

3. Macros make it much easier to do a lot with a little and mean there are far fewer language limitations than in other PLs because one can usually macro around them. E.g. emacs didn’t support lexical scope natively until recently but for a long time supported it with cl macros.

4. Dynamic scope makes global scope local, which means that having lots of globally scoped variables (for various eg options) isn’t so bad so there are lots of these and these then allow one to tweak the behaviour of functions by letting these variables. (e.g. if you have a function that determines some arguments for a program foo and then runs it, you can run that program remotely by doing (let ((foo-executable "ssh") (foo-other-args (append (list "some-host" foo-executable) foo-other-args))) ...)

5. Many internal data structures are simple arrangements of lists, symbols, and strings that are easy to inspect and easy to modify. They are so easy to modify that many come with a spec of their structure that is automatically turned into a gui to modify it.

6. Buffer-local variables are a super convenient way of attaching state to a buffer and a buffer is a super logical place to attach a lot of state to. There are some caveats, e.g. often one wants buffer groups of some kind but these are much less common in the simple case.

7. Symbols are much better than strings. They are faster, feel more natural, and are much easier to attach things to. It seems weird to imagine JavaScript having some global object mapping nearly every string to an object listing various different properties of that string but symbol plists tend to feel pretty natural and are a handy way to extend things.

8. It’s reasonably easy to not have independent things stepping on each other’s toes. Typically if you can write down a unique symbol for your thing then it won’t really conflict with other things. You can use it for global/buffer-local scope. You can use it for a property in symbol plists without stepping on other properties.

9. There are hooks for extension built in all over the place.

10. Your code gets to do things instantly. With many languages you can’t do the useful thing you wanted to do until you can get the data in/out of it which is often a lot of work. It’s even more work if you want something interactive, and even more work if you want something better than curses. Even for an “easy to get going” language like JavaScript you can’t really build on what’s come before. You typically have to start by building up most of the environment you want to work in by yourself first. In emacs it’s already there and you can use everything that’s there for free. There is no building up your environment because your environment is the one and only environment.

11. Essentially anything you can do with keys is just a regular elisp function called interactively. It is easy to make a function a command by telling it what things you care about which means that most commands correspond to functions that take extra arguments which are useful when calling non-interactively.

12. Nearly everything is native. The things that aren’t in elisp are typically only very fundamental or boring things. And all this code is on your machine, emacs knows where it is and you can read it. If you want to understand something you can jump to definition and have a look. You don’t need to wait for the package maintainer to fix things, just write the fix yourself and stick it in your .emacs. In other editors/systems the bug might be much deeper. You don’t want to have to build everything from source to be able to fix bugs yourself. In emacs you are effectively building everything interesting from source (except without really doing any work most of the time thanks to the abomination of unexec) so it easy to hack on.

13. Emacs has lots more experimental things than other editors/languages because the users write them (to scratch itches) and accept them. One can wonder why an emacs user might be more likely to accept rough edges than a user of (say) vscode. One could stereotype that the typical emacs user is more used to code that is rough or buggy, or that the typical vs code user is more used to code that doesn’t do anything useful. Or maybe it is just that emacs being rough around the edges is the price one must pay for the smug superiority of using what is (objectively) the best system for hacking for hackers by hackers. One could suggest that some of these arguments also apply to vim users accepting an editor rough around the edges and this is partly true but despite the larger number of people who use vim, there seems to be quite different work done there (typically it’s focused only on editing and much less on big complicated useful things like magit/org/calc). Then again I’m pretty sure writing vimscript is a fate worse than death so that is probably why.


I would add the pervasive documentation built into the system for every function and variable, and the ability to find the source for any function instantly. The whole Lisp machine heritage is totally optimized for “developer experience” and helps the user of the system ease into hacking on the system.

Also the highly imperative Logo-like model of coding is, though kind of clunky at times, also extremely intuitive and straightforward. Your programs often work the same way you work: go to the other buffer, search forward for a regexp, kill the line, go back to the beginning, and so on, just like “editor macros.” So there’s no funky abstraction frameworks with models and controllers and whatnot, just buffers with cursors basically.


12.5. In addition to being able to take a look, you can modify the .el.gz in-place. I've done that to fix how org-babel-execute:sql calls the postgresql interpreter (it was ignoring the header args that let you set the user, host, etc).


I'm in the middle of bundling some of my Elisp code into a production-quality package, so this will come in handy. Thanks 'rauhl for posting it!




Consider applying for YC's Summer 2025 batch! Applications are open till May 13

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: