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

Reloading nested modules doesn't work in Fennel (stdio) #513

Closed
sarna opened this issue Jul 9, 2023 · 2 comments
Closed

Reloading nested modules doesn't work in Fennel (stdio) #513

sarna opened this issue Jul 9, 2023 · 2 comments
Labels

Comments

@sarna
Copy link

sarna commented Jul 9, 2023

When you reload a file using :ConjureFnlEvalReload, it takes a relative path to the file and strips the extension. So for example if you reload a file at ./foo/bar.fnl, the reload command will look like this: ,reload foo/bar. This is not the correct incantation:

To require a module that's in a subdirectory, take the file name, replace the slashes with dots, and remove the extension, then pass that to require. For instance, a file called lib/ui/menu.lua would be read when loading the module lib.ui.menu.
https://fennel-lang.org/tutorial#modules-and-multiple-files

Trying to reload a file like this will not actually reload a proper Fennel require - it will result in two different modules in package.loaded.

You can see for yourself by creating a ./foo/bar.fnl file with the following contents:

;; ./foo/bar.fnl
{:f #:hi}

In the current directory, open a new Fennel file in Neovim, and evaluate these expressions using Conjure:

;; ./usage.fnl
(local bar (require :foo.bar)) ;=> nil

(bar.f) ;=> "hi"

(icollect [k (pairs package.loaded)] (when (k:match :foo) k)) ;=> ["foo.bar"]

Now, open ./foo/bar.fnl again and change #:hi to something else:

;; ./foo/bar.fnl
{:f #:Hi}

Run :ConjureFnlEvalReload, the log will say:

; ,reload foo/bar
ok

Note the slash in the module name. Re-evaluating the expressions will yield surprising results:

;; ./usage.fnl
(bar.f) ;=> "hi"

(icollect [k (pairs package.loaded)] (when (k:match :foo) k)) ;=> ["foo.bar" "foo/bar"]

bar.f gives us the old result despite being reloaded, and in package.loaded we now have two "foo bar" modules.

Two possible fixes:

  • replace path separators in the module path with dots
  • don't try to guess the module name and instead ask the user every time which module should be reloaded (that's what the Emacs extension does, I heard).

And thanks a lot for Conjure, I really enjoy using it :)

@Olical
Copy link
Owner

Olical commented Jul 9, 2023

Good catch! Pushed a fix to the develop branch. Thank you!

@sarna
Copy link
Author

sarna commented Jul 9, 2023

Awesome! Thank you :)

@Olical Olical closed this as completed Jul 12, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants