A New State Of Affairs: Estate Mode

:: text-editing vim emacs composiphrase

While I’ve shed evil-mode, I still want to use modal editing🗽, of course. I wanted to shed the on-character cursor positioning as discussed previously, among other things. I considered several modal editing packages in emacs, and... ok, yeah, I wrote my own. I feel like I need to justify this.

(Note, this is part 2 in a series about my “new composable text editor”, Composiphrase. See the nit-picking part 1 here. See part 3 here. Though if you just want to read one, part 4 is the key piece.)

🗽: Or, as I’ve taken to calling it, GNU/modal editing stateful editing, since emacs uses the word “mode” for something unrelated.

There are a couple of modal editing packages, Modalka and Ryo, focused on letting you DIY your own key bindings, which is what I wanted. But they both just have one alternate mode, whereas I want the ability to have an arbitrary number of user-defined modes. Then there are a slew of modes that provide different takes on modal editing, with opinionated key bindings, etc. I want a blank slate to build my thing on top of. I could have just used evil-core.el, the core of evil-mode that defines the functionality for modal editing, without actually defining any modes. Arguably I should have done that, but it is much bigger and more complicated than I really want🔍.

🔍: Whenever I have looked at the evil-mode source code, eg. to fix some minor detail, or thinking about copying out some functionality, I end up deciding that it is too complex to bother with. Eg. every function that I thing I would like to use depends on two more functions that each depend on a couple more functions, etc. It’s not necessarily bad – what evil-mode does is complicated, and obviously it’s good for evil-mode to have things factored out such that it can share code between its various pieces. But its code sharing architecture doesn’t necessarily match my wants, and it has a lot of complexity in supporting things that I don’t care about, or even supporting things that I actively want to move away from. (Or perhaps even more critically, it’s not architected to make it easy to poach single functions out of the code base within a period of 10 minutes, and aside from my recent binge of emacs overhauling, my typical session of fussing with emacs is too short to dig through what it’s doing and try to re-use code.) Anyway, evil-core.el is an order of magnitude larger than estate.el, and evil-states.el is an order of magnitude larger than estate-default-states.el. So while I could see growing estate to handle things that evil-mode has already implemented, given that I’m basically already happy with estate-mode, I find it very doubtful that it will grow that much.

So I wrote estate-mode. It includes estate.el, which is fairly similar in spirit to evil-core, except much smaller with fewer bells and whistles. It lets you define new states, where each state has entry/exit hooks, a keymap, and a buffer-local keymap. If you use suppress-keymap on the state keymap, then it is not an insert-like mode (by unsetting all keys otherwise bound to self-insert).

Also it has estate-default-states.el, which defines normal-state, insert-state, visual-state, and pager-state. Most of these states have just a bit of custom logic each. For example the visual-state uses a hook so that it activates whenever the region becomes active. The insert-state collects edits into a single undo element, and has a helper to let you bundle some extra commands into the undo element.

And it comes with no bindings. You DIY that, or get it from another package. I’ll provide a demo package that puts together estate-mode with my other new packages to create what I believe to be a pretty compelling modal editing UI.

I’m not sure it’s really “done”🛑, but I want to make a demo for my other packages, and it’s a necessary part. In particular, there are 2 big features that I would like, that evil-mode has, but that I’m not sure I want to bother implementing: visual-line mode and visual-block mode. I really like both of these, and currently miss them. But they also both add complexity, and I’m living without them, and... don’t miss them that much? Anyway, emacs has a rectangle selection feature, though by itself it is less complete than evil-mode’s visual block mode (which is better than vim’s visual block mode, by the way, it is one of the features where evil-mode clearly improved upon vim while still being very faithful to it). There are approximately 2 things I use rectangle selection for, and I think only one is missing from what is obviously doable with the emacs version. Visual line mode is much more vim bread-and-butter. It is nice to eg. yy copy lines and then P/p paste them above/below the current line without worrying where on the line the cursor currently is. I might add a visual line mode, and in fact started a very poor incomplete version of it. But I just had so many other things to do with respect to my editor overhaul that I decided it wasn’t a priority.

🛑: I mean, I’m putting it out because I want to make a demo, but most of the code that I’ve actually cobbled together is somewhat janky. In the process of hurriedly building out pieces, I’ve made some mistakes on other parts such that they are fundamentally broken outside of narrow situations. I’ve had time pressure. I’ve cared more about writing the features that I immediately want to start using than I have about learning emacs testing frameworks and figure out how to write good tests. So despite the fact that I promise, I really do care a lot about testing, software quality, verification, etc, this is demo-ware. But... I use it as my daily driver now. At least my use case of estate-mode works ok. ¯\_(ツ)_/¯

Also, I’ve been reconsidering visual line mode. I wrote a bunch about it, but then that tangent became longer than the original post about estate-mode. So maybe it will be the next entry.