mattwparas / steel

An embedded scheme interpreter in Rust
Apache License 2.0
1.26k stars 56 forks source link

Dynamic Require Expressions #276

Open Talia-12 opened 1 month ago

Talia-12 commented 1 month ago

This refers to require expressions that can be outside of the top-level scope, or can accept arbitrary strings to determine where to require from (i.e. require at runtime). The usecase I have for this is that I'd like to add a system for project-specific plugins to my helix config (i.e. have a bunch of .scm files in the .helix directory in the project, and run all of them if I open helix in that project), and this is as far as I can tell currently not possible. (I have no idea how annoying this would be to add :sweat_smile:)

mattwparas commented 1 month ago

If you're willing to wait a couple days, I will have a lot of examples of this functioning in a certain form. It is possible today, and I can follow up with some examples in a few minutes

eval or load currently work, however they're limited to running at the top level environment, as in running (eval (require ...)) within a function somewhere, will actually insert the definitions into the global top level environment. This ends up working well within helix since the "top level" is effectively the interface to calling functions within the interpreter itself.

I would like to enable eval within a certain namespace, however that isn't yet implemented. It is on my to do list, however it unfortunately, is quite annoying :smile:

Talia-12 commented 1 month ago

some examples would be helpful! The interface I was originally intending to use was to iterate over all files in .helix/plugins/, load them, and call a helix-plugin! or init-plugin! method on them; I would also be fine with a solution that involved single .helix/helix.scm and .helix/init.scm files which are responsible for calling out to individual plugins. I think this would actually also require something like (map provide *some-list-of-functions*), not sure if that's supported either.

Also, while I'm asking questions, what do you think the most ergonomic way of taking a function required from somewhere and reproviding it in .helix with documentation describing what it does? If you're defining the function yourself you can add a ;;@doc comment where you define it, but if you're pulling it in from somewhere I'm not sure how to add an explainer to the helix command menu for it.

mattwparas commented 1 month ago

So I've adjusted the interface within helix to alleviate this. I just have some merge conflicts to address and then will have the update pushed - but the new way of doing this will just be to look at the global environment and find doc comments there.

So really, all that should be needed is a single init.scm which can call either (require ...) or (load-package! ...) (that is what I've called the dynamic require) - and if its exported (and has a doc comment), it will be available at the top level with the little pop up describing it.

mattwparas commented 1 month ago

Alright - apologies for the delay, but all of that is pushed now. You can find some examples here: