←back to thread

Emacs Lisp Elements

(protesilaos.com)
353 points robenkleene | 8 comments | | HN request time: 1.024s | source | bottom
Show context
tikhonj ◴[] No.43667636[source]
I've had a great time using Emacs Lisp over the past 15 years: it's one of the easiest ways to quickly whip up personalized tools for my own use, and, at the same time, my code has been surprisingly resilient and stable over this time.

And this is despite the fact that Emacs Lisp routinely flouts every single software engineering "best practice". The language is dynamically scoped by default! It simply doesn't have namespaces! Static types? Hah! (And I, an inveterate Haskeller, don't even miss them.) You can—and people routinely do—hook directly into all sorts of implementation details from other parts of the codebase.

And yet it just works. And it works remarkably well.

My theory: what matters isn't "best practices", it's have a coherent conceptual design and code that reflects that design. Emacs is designed around a small but expressive set of core concepts that it uses in a consistent manner. Text with properties, buffers, modes, commands, customization variables... Almost everything more complex in Emacs is structured out of these (+ a handful more), and, once you've internalized them, it's surprisingly easy to both learn new higher-level tools and to write your own.

The design of both the user interface and the code directly reflect these concepts which gives us a naturally close connection between the UI and the code (it's almost trivial to jump from an interaction to the code that powers it), makes both UI and code units effortlessly composable and generally makes it easier to understand what's going on and how we can change it.

replies(4): >>43667712 #>>43668618 #>>43671691 #>>43673457 #
1. golly_ned ◴[] No.43668618[source]
I’ve consistently failed to make writing elisp net positive for me for basically anything. I use it as a configuration language, and even then, for functions longer than a few lines, it’s still a lot of coding for very little benefit. I just can’t find things to improve in such a way that it’ll actually be worth writing elisp code for, especially compared to other tools (like a quick Python script or even a bash one-liner), or things within Emacs. What are the things you’ve written in elisp that have helped you?
replies(5): >>43669716 #>>43671521 #>>43672805 #>>43674680 #>>43688133 #
2. Rediscover ◴[] No.43669716[source]
> What are the things you’ve written in elisp that have helped you?

Usually tools to alleviate working with dumbass web-based (supposedly needing the corporate-approved browser) stuff for $DAY-JOB.

Oh, and an extension to allow emacs-w3m to handle lynx-style multibookmarks.

replies(1): >>43669985 #
3. prestonlibby ◴[] No.43669985[source]
> > What are the things you’ve written in elisp that have helped you? > > Usually tools to alleviate working with dumbass web-based (supposedly needing the corporate-approved browser) stuff for $DAY-JOB. > > Oh, and an extension to allow emacs-w3m to handle lynx-style multibookmarks.

This sparks my interest as I am in the early days of both customizing Emacs and attempting to displace some of my browsing with it as well. Could you elaborate further on this multibookmarks concept and perhaps an example of one of those alleviations for working with web-based workflows?

replies(1): >>43689185 #
4. 3036e4 ◴[] No.43671521[source]
I wrote a few simple helpers for special things I want to do in (mostly) org-mode, but 99% of "my" elisp is code that I copy-pasted into init.el from someone else. I love that small additions like that can be done by pasting a few lines of elisp into init.el instead of having to depend on full packages.

A few days ago I happened to see my 1998 .emacs file in an old backup. It was only around 100 lines, but I think most of those lines have survived into my current init.el. The oldest lines are probably over 30 years old now. The API is reasonably stable, but not perfect. My current file has lots of logic to handle running in older Emacs versions.

5. mplanchard ◴[] No.43672805[source]
I wasn’t satisfied with any of the pop up terminal libraries so I threw my own together in less than 50 LoC
6. tikhonj ◴[] No.43674680[source]
The biggest things have been utilities for running shells in Emacs (totally changed my day-to-day programming workflow for the better) and org-mode stuff (notes, slides for presentations, todos/scheduling/etc)

But a lot of other things have been more like small conveniences or one-off improvements—things that would not make sense if they took more than 20 minutes to write, but do make sense in Emacs. A few random examples: some custom ways to enter Unicode characters; a command to insert TODO comments; a different way to manage Emacs windows; a little package for jumping to locations I care about; a way to insert a file path into a buffer; a work-specific tool to go from UUIDs to internal URLs; some random stuff for authoring a book with Pandoc + LaTeX; a command to insert Haskell LANGUAGE pragmas (contributed upsteam!); and a bunch more that I'm forgetting.

As a bonus, writing these meant I didn't have to "learn" them in the sense that I know they exist and, if I gave them a keybinding, I did not have to memorize it.

None of these are a big deal on their own! But having an environment that reduces the friction to make small improvements is. Having a tool that I can orient around the way I want to work is qualitatively different from having a tool that makes me orient around how it works.

It's not even that much customization in some absolute sense; everything fits into a few thousand lines of Elisp spread across a few files in my dotfiles repo[1].

[1]: https://github.com/TikhonJelvis/dotfiles/tree/main/home/emac...

7. iLemming ◴[] No.43688133[source]
> I’ve consistently failed to make writing elisp net positive for me for basically anything.

That's sad to hear, because I somehow have the exact opposite experience. First, it was about fixing things in my config. Then I often would catch myself in a "why can't I do this better" state. And it could be anything. Like one day I was copying the current URL in the browser, and then switched again to copy the description. Next day I caught myself doing that again. And I realized - "shit, I never thought before how often I have to do this crap". Then I wrote a helper.

These days, I don't even blink, if I need something, I'll just start whipping up some shitty Elisp in my scratch buffer. And with help of LLM packages like gptel - it's a breeze. What's awesome is that I can play with that code even without having to save that shit anywhere. Sometimes, I realize the solution is not as easy to make as I initially thought, so I'd just leave it there in my scratch buffer. It sits there, sometimes marinating for weeks - I have a persistent scratch buffer. I even get excited when I stumble on a problem I want to optimize.

Few weeks ago I was in a pair-programming Zoom, and my colleague, let's call them Matthew, was screen sharing. I couldn't help distracting Matt asking questions like, what is that? Can you share this link? Wait a minute, don't scroll away, I need to write that down. etc.

After that I thought of solving that dilemma. I sat down and wrote a helper that calls tesseract to OCR text from an image in clipboard. Took me no more than 20 minutes. https://github.com/agzam/.doom.d/blob/main/modules/custom/wr...

8. Rediscover ◴[] No.43689185{3}[source]
Lynx is a web browser, bookmarking a page is done by hitting "adX" as in (a)dd (d)ocument to file (X). Or (a)dd (l)ink to (X). Nice and quick. The X is usually a lower case ASCII letter corresponding to a file. You can enable this mode (and the specific bookmark files) in lynx's config file. The Emacs extension uses the same keystrokes and, optionally, the same files.

Alleviations are (I'm intentionally vague here) for getting rid of finding a link, clicking through, repeat, repeat, repeat, repeat, just to get to where I need to be (like adding an update to a ticket). I usually only automate processes that are intended for use by mouse/pointer-driving users with an ability to comprehend what (and where) icons are - I have a self-imposed problem withe former and a physically/mentally imposed hard time with the latter.