edit icon indicating copy to clipboard operation
edit copied to clipboard

Add support for extensions / plugins

Open lhecker opened this issue 11 months ago • 17 comments

We'd like to keep the core editor small so that it can be easily bundled on all variants of Windows. Proper syntax highlighting, language-server support, and similar, on the other hand will increase the size significantly. An extension model would allow us to split the editor up into smaller parts.

Very rough draft:

  • Expose all relevant APIs (UI, text buffer) via a C ABI straight from our binary
  • Add an extension loader which searches for nearby *.dll / *.so files
    • Perhaps also add some certificate checks for Windows? Not sure if this exists on other platforms.
    • Also, perhaps we should add some logic, so we don't load arbitrary extensions as admin / root
  • Extensions:
    • Should expose a built-with version number so we can perform compatibility checks / shims
    • We then load and execute its entrypoint
    • It can then load the C ABI dynamically from our executable (GetProcAddress / dlsym)
  • Initially, until we stabilize the API, we should keep all important extensions in-tree in this project

karunamurti on HN mentioned that we could use https://github.com/bytecodealliance/wasm-micro-runtime as an alternative to loading basic dynamic libraries.

Requested extensions

  • Mun (see #53)
  • Running external apps for formatting (see #136)
  • A hex editor (see #152)
  • An integrated terminal (see #552)
  • Code formatting (see #613)

lhecker avatar May 18 '25 12:05 lhecker

If you're going the route of ABI extensions via DLLs, my suggestion of Mun probably makes little sense, since it's meant to be embedded by a Rust app. In fact, I'm not sure it makes sense to have particular support for any specific language, unless it becomes a question of what calling convention to use in the ABI.

sdegutis avatar May 20 '25 14:05 sdegutis

I think it still could make sense in that it would make the extension creation a lot more accessible and portable, if there were an extension that exposes similar interfaces for use by whatever script language instead. Cause the idea of using shared libraries and C ABI means you have to compile them to native code per platform and on ABI change. Meanwhile, with such a scripting extension, only the maintainers of the scripting extension (and people who don't want to use it) would need to go through the added churn.

The question is if it wouldn't be better to just not use the C ABI approach and instead go for some different approach (e.g. IPC/RPC layer, WASM micro runtime, or whatever else that would work with the given design goal of keeping the binary small).

Jackenmen avatar May 20 '25 14:05 Jackenmen

Some of the features that are implemented in the core of other editors may end up being extensions for this editor. This means that IPC/RPC is impractical. Scripting languages could be possible, but likely also too impractical or too slow (e.g. think of implementing tree-sitter in Mun; Is that even possible?).

WASM is a possible choice indeed, but I'm not entirely sure I understand the binary size list on wasm-micro-runtime's readme. Does it mean it only needs ~3.7KB of binary size in the most minimal configuration? What would we miss out on if we use that? Could that load arbitrary WASM extensions?

lhecker avatar May 20 '25 16:05 lhecker

WASM is a possible choice indeed, but I'm not entirely sure I understand the binary size list on wasm-micro-runtime's readme. Does it mean it only needs ~3.7KB of binary size in the most minimal configuration? What would we miss out on if we use that? Could that load arbitrary WASM extensions?

From what I know through my wasm research (and I could be wrong), yes, the 3.7KB core would be able to load arbitrary wasm files/modules, if that's what you mean by extensions. The libc-wasi library would probably be redundant for you, since it's just an API bridge for wasm files to talk to the host OS (e.g. read/write files, etc), which I presume you would provide internally instead. Obviously the two interpreters would be unnecessary for you, and I think the AOT runtime would too, since it's not a concept inherent in wasm. But like I said, I could be wrong.

sdegutis avatar May 20 '25 16:05 sdegutis

@lhecker If I'm right about the above, and it's only 3.7KB of runtime code to load and execute an arbitrary wasm module, it would be a great alternative to DLLs, essentially providing the same functionality, though you'd still need to provide an internal API either way.

One interesting difference, though, is that you could eschew the ABI entirely, since wasm (afaik?) operates purely on the API level. I don't remember if you said you made a decision on the language based on ABI support, but if supporting a stable ABI restricted your options, using wasm would effectively lift those restrictions, e.g. you could use any language regardless of its ABI.

sdegutis avatar May 20 '25 16:05 sdegutis

The choice of writing my own TUI framework was related to plugins, because I wanted the TUI API to be easily exportable as a C API. I think this would also apply to WASM though, if that had been my plan all along.

lhecker avatar May 20 '25 16:05 lhecker

Right, what I'm saying is that if you were to only use WASM as the extension layer, and drop the C API/ABI entirely, you'd have different requirements that possibly lifts some of those restrictions, e.g. lets you choose languages that don't focus heavily on C ABI compatibility (looking at you Golang) or using a third party lib instead of TUI, etc.

Granted, it would be a very controversial decision to drop C ABI extension layer and move entirely to WASM, since C is currently still the king of the hill. But one that potentially could give just as much flexibility as C, though not as much speed (but close?). I just mention it because I'd never really thought about using WASM as an extension layer for desktop apps before. It's interesting...

sdegutis avatar May 20 '25 19:05 sdegutis

My two cents as somebody who just searched this in the issues page: a plugin api done via DLLs is not gonna end well, internal functions are (and should) inevitably going to be changed. A better idea, I feel, would be to a standardized api that communicates with the program using networking functions.

IoIxD avatar May 20 '25 21:05 IoIxD

My two cents as somebody who just searched this in the issues page: a plugin api done via DLLs is not gonna end well, internal functions are (and should) inevitably going to be changed. A better idea, I feel, would be to a standardized api that communicates with the program using networking functions.

There exist a marvel of software engineering for Windows — Far Manager, which absolutely refutes your statement.

It is intentionally designed as a DLL-plugins host. And most of its functionality is implemented as plugins.

awson avatar May 21 '25 02:05 awson

Oh it could absolutely be done. I just question if its a good idea as opposed to something more proper.

Far Manager is a clone of a file manager from the 1990s, so its not exactly a great example to point out when saying this is a good idea.

IoIxD avatar May 21 '25 02:05 IoIxD

WASM for addons has the added pro of being able the limit access to system resources and you would only need to compile once and it will work on all platforms

kalebm-woolloo avatar May 21 '25 05:05 kalebm-woolloo

Far Manager is a clone of a file manager from the 1990s, so its not exactly a great example to point out when saying this is a good idea.

This is a non sequitur.

Moreover, this very project is a "clone" of an editor from 1980s in exactly the same sense — it aims to be lightweight, fast and native.

And this is the rationale of why it was created.

Please, don't request to make another VS Code, the existing one is enough.

awson avatar May 21 '25 06:05 awson

internal functions are (and should) inevitably going to be changed

DLL or not-DLL dilemma is completely orthogonal to this.

It is an in-process vs out-of-process dilemma.

awson avatar May 21 '25 06:05 awson

We'd like to keep the core editor small so that it can be easily bundled on all variants of Windows.

... on all newer Windows variants.

I think WINE implemented older Windows versions good. But on WINE 9.0 Edit dont run. It ends with at minimum this error: Unimplemented function KERNEL32.dll.ReadConsoleInputExW called at address ...

I don't know, until which Windows Version the function ReadConsoleInputExW() exists..

theuserbl avatar May 21 '25 16:05 theuserbl

I don't know, until which Windows Version the function ReadConsoleInputExW() exists..

Windows 7

DHowett avatar May 21 '25 16:05 DHowett

Regardless: I see what you are trying to do here, and I think that it is off-topic for this issue. If you want to raise an issue about our Windows version compatibility, please file a new one.

Somebody has already filed a bug on Wine requesting the implementation of ReadConsoleInputExW.

DHowett avatar May 21 '25 16:05 DHowett

The Zed editor folks go into a lot of detail on leveraging WebAssembly and the WASM Component Model for their plugin / extension system on their dev blog post: Life of a Zed Extension: Rust, WIT, Wasm. Leveraging WASM Components as a plug-in system could be a great model to follow ✨.

rajsite avatar May 29 '25 04:05 rajsite