Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Direct Eval of Fennel Expressions #23

Closed
Kethku opened this issue Nov 13, 2023 · 5 comments
Closed

Direct Eval of Fennel Expressions #23

Kethku opened this issue Nov 13, 2023 · 5 comments
Labels
enhancement New feature or request

Comments

@Kethku
Copy link

Kethku commented Nov 13, 2023

Heya! A couple months ago I converted my neovim config off of aniseed and to Nfnl and have for the most part been loving it. The approach seems to be a much nicer set of tradeoffs and makes debugging issues a little easier.

One part of aniseed I've been missing though is some way to evaluate or resource a given fennel file. I find myself somewhat frequently editing part of my config and wanting to quickly run some part of it either to update the configuration live and move on or test some of the changes.

I'm curious about what the recommend way to do that would be. I know that I could just open the lua file and evaluate that directly but that requires figuring out where the compiled lines landed which takes time and thinking. Maybe there could be a setting to store the source maps for the compilation and have some command which looks up the equivalent lua file or range in the compiled lua file and evaluates that transparently?

Maybe I'm thinking to hard and there is a simpler approach I'm overlooking. Any help would be appreciated!

Thanks for your continued work on making neovim a nicer place to write software. I've used your stuff for years now and really appreciate the attention you clearly put into it <3

@Olical
Copy link
Owner

Olical commented Nov 15, 2023

So I wrote a silly approach first because I had a brain fart, you can ignore that and skip to the "Decent idea" section that you mentioned in your initial question. I'm leaving it there because showing how you'd call the internal compiling functions is kinda interesting anyway.

So the ideal approach would be Conjure automatically detecting nfnl as opposed to Aniseed and using nfnl as it's evaluation backend for the Fennel client. I'm not there yet but we can sort of mimic what Conjure would be doing by calling the appropriate internal functions.

Silly but interesting idea here

(fn mod.into-string [{: root-dir : path : cfg : source : batch?}]

So we don't have an eval module yet, but that might be a nice wrapper to add. What we can do is call the compile function and then pass that to luaeval in vimscript or loadstring when called from Lua which is basically eval inside a Lua 5.1 context which LuaJIT is (IIRC).

(local compile (require :nfnl.compile))
(local config (require :nfnl.config))
(local fs (require :nfnl.fs))

(let [file-path (vim.fn.expand "%")
      file-dir (fs.basename file-path)
      {: root-dir : cfg} (config.find-and-load file-dir)
      {: result : error : status}
      (compile.into-string 
        {:root-dir root-dir
         :path file-path
         :cfg cfg
         :source "(+ 10 20 30)"
         :batch? false})]
  (if (= :ok status)
    ((loadstring result))
    (error error)))

Hooking this up to a mapping and maybe replacing the file-path with some other good source for the file you're working with should be good. It's maybe overkill though!

It also handles stuff like if you try to compile a macro file it'll instead go and compile your non-macro files, which might surprise many people but I'm trying my best to never let compile Lua output get stale. Really when calling this "compile string" function, if you give it a macro file it should return an error and do nothing. The calling parent function should do the compilation of non-macro files, but that shouldn't effect you.

Decent idea below here

As you say, we could also load the Lua file from disk that's already been compiled by nfnl. Should've used that as my initial example, but it still stands as an interesting example of how you'd call internal compilation functions I guess? So in that case (should've done this first! Your idea is much simpler! I'm silly!), you'd map some key to this:

(dofile (fs.fnl-path->lua-path (vim.fn.expand "%")))

Which means we just rely on all the existing plumbing to compile your Fennel to Lua then you have a mapping that executes those Lua files using the Fennel files original path. You could basically set up :luafile ... but :nfnlfile ... and then give it :nfnlfile % which could then in turn be bound to a mapping. Maaaaybe this should be a core feature, it's really neat.

And it sorta fits the theme of nfnl of doing as little as possible leaning on existing Lua and Neovim systems as much as possible. Ignore the first half of this, it's just me getting distracted and it's not helpful, I just didn't want to delete it :D

@Kethku
Copy link
Author

Kethku commented Nov 19, 2023

Awesome. Thanks for the suggestion. I'll play with this in my personal config and if it seems to work I'll open a PR

@Olical Olical added the enhancement New feature or request label Nov 27, 2023
Olical added a commit that referenced this issue Nov 30, 2023
@Olical
Copy link
Owner

Olical commented Nov 30, 2023

Okay, now the example will look like:

(local nfnl (require :nfnl.api))
(nfnl.dofile)

Which will run the matching Lua file from disk while you're looking at a Fennel file. Going to hook that up to a command so it's :luafile natively and we'll have :nfnlfile as an equivalent which will call this new function.

Then I think we'll want equivalents for :lua and :luado, maybe another that just prints out the compiled output instead of executing it as well.

All of these will be thin command wrappers around nfnl.api methods which you can call from your own Fennel / Lua.

Olical added a commit that referenced this issue Nov 30, 2023
@Olical
Copy link
Owner

Olical commented Nov 30, 2023

Done, this is all under :NfnlFile which takes an optional argument and defaults to %. I hope this helps! If this works well I'll probably add more API methods and commands that map to them.

The command will ONLY be created in Fennel buffers where a .nfnl.fnl configuration file is detected. Not strictly required, but I like keeping nfnl entirely out of the way unless you explicitly ask for it (by creating the file) so it won't accidentally clash with some other Fennel plugin in another project or something. I'm probably being too careful here but still.

@Kethku
Copy link
Author

Kethku commented Mar 9, 2024

This works great, but I'm now running into #36 closing for now.

@Kethku Kethku closed this as completed Mar 9, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants