Software & Apps

sminez/ad: a customizable text editor

building crates.io version docs.rs

ad (pronounced AD) is an attempt to integrate a modal interface to edit the preferences of vi
and kakoune with Plan9’s expansion method Acme. Inside the ad Text is something you can execute as well as edit.

It is primarily intended as a playground for experimenting with implementing different text editor features and is currently not optimized or feature complete for use as your main text editor.

That said, if this sounds like something you might find interesting then please take a look and see what you think! Currently there isn’t much user-facing documentation so you’ll have to read the source code to find out what is and isn’t implemented.

ad It’s robust and feature-complete enough that you can try it out and see what you think. That said, there is currently very little documentation and there are likely to be various bugs and crashes in places that I haven’t fully tracked down yet. If you try this and find something broken, please raise an issue on GitHub so I can look into it.

You have been warned!

tour

ad aims to be a hybrid of pieces of different editors that I find most useful:

  • vim style modal editing to allow easy key bindings
  • convenient text navigation and selection from vim/kakoune
  • mini-buffer base user defined minor methods from emacs
  • sam/acme style editing commands for larger editing actions
  • acme style extension by exposing editor state and functionality for external client programs.
  • support for mouse based navigation and selection but not necessarily as the main way to use the editor like acme. That’s fine for desktop but most of the time I work on a laptop which makes that very clunky.

ad is the not trying to replace vim (or kakoune, or emacs) in terms of a widely hackable editor. Instead it strives to follow acme’s philosophy of integrationing development environment (instead of integrated). By which I mean that the purpose is to provide a comfortable editing environment to work that supports direct interaction with external tools and programs from the outside rather than pulling everything. on.

Given the (arguably questionable) intent of implementing everything from scratch, there’s a fair amount of functionality involved in ad which in turn is divided into several modules within the crate. Currently, I don’t structure things as individual boxes but that may change in the future.

This is a non-exhaustive list of some of the more interesting parts of the internals ad

  • buffer/content: a gap buffer implementation for the internal state of a Buffer.
  • dot: manipulate the current selection in the given buffer (including vim-like motions)
  • exec: minimal core implementation of same editing language
  • fsys: virtual filesystem interface to the editor state in the style of acme
  • nope: 9p protocol implementation behind the fsys module
    • Now moved to its own crate with available source code HERE.
  • regex: custom regex engine capable of working with character streams. It is nowhere near as performant as regex box (obvious) but it allows some flexibility to tinker with the exec command language.
  • TRIALS: TRIALS data structure for managing sequence based keybindings

I used it vim for years now (recently said Neo and in ours) and I really like the core editor itself. It was then that I discovered acme by a rare screencast from Russ Cox, which shows how you can interface with it via the plan filesystem protocol, allowing you to run anything you want inside the editor (in any language) as long as you can interact with that protocol . that I really like it, but the lack of modal editing and the need to use the mouse when I’m sitting at my laptop is hard to get used to, so I started looking at how to transfer some of the ideas of acme to vim (namely the load/execute semantics via the plumber and the idea of ​​exposing the editor state in a simple way to client programs).

vim has a many more built into it that I used to know (and I’ve been hacking my vimrc for years now) which is more than a little scary. What I want is a small, handy editor that I can hack around.

So…How hard is it?

For things that will be core parts of the experience (bindings, per-filetype configuration) I only go to hard code things. I’ll try to do it in a way that makes it easy to update/change but the whole thing would be a lot easier to write without a lot of config parsing.

That said, the more I worked on it, the more I wondered if it was structurally interesting ad
in the same way as penrose and make it as a library to write your own text editor? That needs some tweaking but might be interesting to check out…

  • Simple modal editing until I used VIM
  • Sed/Sam style editing commands
  • Acme-style use of external commands is in an embedded language:
    • Disclosure of current buffer / window state to external programs
    • Disclosure of external program events
    • Receive events from other programs
  • Virtual buffers for command output that can be hidden

The Sam style structures regular expressions

One goal of this project is to provide an implementation of “Structural Regular Expressions” which was first presented (to my knowledge) in Same text editor from plan9 by Rob Pike. This instruction
from Pike contains Sam’s command language which I used as a starting point for the command language ad. So far I haven’t been looking for a perfect match to Sam’s or Acme’s functionality but I am am looking to use the pieces that feel more useful. As the project progresses, I may add more but for now I’m happy to have a decent starting point for a structural regular expression engine implementation.

There is still a fair amount to do but so far the idea is to allow for repeated narrowing and looping of sub-matches within a buffer or file loaded from disk. (A streaming interface that works with stdin is coming but I need to figure out how best to buffer input and track partial matches in the regex engine to avoid slowing things down or have the engine -buffer and collect
all to its standard input before pairing).

The current machine can be used by -e and -f flags to run ad in headless mode, but hooking things into the interactive editor directly should be coming soon. For now, here’s a demo of some simple engine functionality:

$ cat examples/exec_scripts/result_fns.ad
,                              # set dot to be the full input (not required as this is the default)
x/fn@*?\{/                     # select all Rust function signatures up to the opening brace
g/->.*Result.*\{/              # keep those that return some form of Result
x/fn (\w+)@*?-> (.*?) \{/      # extract the function name and return type from the signature
p/($FILENAME) $1 returns $2/   # print them along with the filename using a template


$ ad -f examples/exec_scripts/result_fns.ad src/**/*.rs | head
(src/buffer/buffers.rs) open_or_focus returns io::Result<()>
(src/buffer/dot/cur.rs) fmt returns fmt::Result
(src/buffer/dot/mod.rs) fmt returns fmt::Result
(src/buffer/dot/range.rs) fmt returns fmt::Result
(src/buffer/edit.rs) fmt returns fmt::Result
(src/buffer/mod.rs) new_from_canonical_file_path returns io::Result<Self>
(src/exec/parse.rs) execute returns Result<(usize, usize), Error>
(src/exec/parse.rs) step returns Result<(usize, usize), Error>
(src/exec/parse.rs) try_parse returns Result<Self, Error>
(src/exec/parse.rs) validate returns Result<(), Error>

https://opengraph.githubassets.com/8ac5798eeb09100bf6187a6f4518eb3a54607c5676ef6ec9bb15d73d0dacd43c/sminez/ad

2024-12-18 00:37:06

Related Articles

Leave a Reply

Your email address will not be published. Required fields are marked *

Back to top button