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

Question about package macros #18

Closed
shaunsingh opened this issue Aug 13, 2022 · 3 comments
Closed

Question about package macros #18

shaunsingh opened this issue Aug 13, 2022 · 3 comments

Comments

@shaunsingh
Copy link

Hi! I was just wondering why

  1. choose to use a global to manage your list of plugins/rocks
  2. manage package/packages at compile-time instead of runtime

It would make sense to use a global if you were to part the pack! statements to different files and then unpack them at once, though thats much harder to do compile-time, and vice versa (as you have all the plugins in one file a local would work as well)

I was working on a "module system" (where sets of plugins and configurations are defined in a module thats loaded via a macro ala doomemacs) and was trying to part out the package declarations into their own files, but currently that means having to include them which gets messy very quickly

@datwaft
Copy link
Owner

datwaft commented Aug 13, 2022

The idea behind the macros that I use to manage packages was to reduce the nesting required.

For example, without macros you would need to do something like this:

(local packer (require "packer"))

(packer.startup
  (fn [use]
    (use "wbthomason/packer.nvim")
    (use {0 "tpope/vim-dispatch" :opt true :cmd ["Dispatch" "Make" "Focus" "Start"]})))

With my current macros you would something like:

(pack! "wbthomason/packer.nvim")
(pack! "tpope/vim-dispatch" {:opt true :cmd ["Dispatch" "Make" "Focus" "Start"]})

(unpack!)

As you can see it streamlines the process of declaring packages, making each line/statement a declaration of a package, without needing nesting at all.

This approach also has some weaknesses, I haven't tested recently if you can have multiple package definitions in multiple files, but a few months ago there was an issue with hotpot in which the global variables were reset each time the macros were imported, and so you couldn't define some packages in some file and after that add more packages in another file. (See rktjmp/hotpot.nvim#38, it is fixed right now).

Additionally, to my understanding the use of global variables in compile-time is not well defined in Fennel, so the functionality could be broken in future updates.

choose to use a global to manage your list of plugins/rocks

This is mainly a limitation of the approach I used. To let every package declaration be at root level I needed a way to save which packages had been declared, to later on expand that list of declarations into the code that the package manager requires to function. Without a global I cannot make macros communicate between each other to save the state, and therefore I wouldn't be able to have them at root level.

If you find a better solution let me know, as I also don't really like having macros do side-effects.

manage package/packages at compile-time instead of runtime

Technically the packages are not being managed at compile time, the macros don't execute any code to interface with Packer at compile-time, only expand to code that later on Neovim will use to interface with Packer at run-time.

The result of the previous example compiled to Lua would be:

local function _1_(use)
  use({"wbthomason/packer.nvim"})
  return use({opt = true, cmd = {"Dispatch", "Make", "Focus", "Start"}, "tpope/vim-dispatch"})
end
return (require("packer")).startup(_1_)

@datwaft
Copy link
Owner

datwaft commented Aug 13, 2022

I just did a quick test to see if the macros work between multiple files, and it seems they do, the only limitation is that you need to use include instead of require.

Here are the source files:

;; modules1.fnl
(import-macros {: pack!} :themis.pack)

(pack! "username1/package1")
(pack! "username1/package2")

;; modules2.fnl
(import-macros {: pack!} :themis.pack)

(pack! "username2/package1")
(pack! "username2/package2")

;; modules.fnl
(import-macros {: pack!
                : unpack!} :themis.pack)

(include "modules1")
(include "modules2")

(pack! "username/package1")
(pack! "username/package2")

(unpack!)

Here is the output:

package.preload["modules2"] = package.preload["modules2"] or function(...)
  return nil
end
package.preload["modules1"] = package.preload["modules1"] or function(...)
  return nil
end
require("modules1")
require("modules2")
local function _1_(use)
  use({"username1/package1"})
  use({"username1/package2"})
  use({"username2/package1"})
  use({"username2/package2"})
  use({"username/package1"})
  return use({"username/package2"})
end
return (require("packer")).startup(_1_)

@shaunsingh
Copy link
Author

Thanks for the help and explanations, the biggest issue I had with using include was that relative include wasn't working with hotpot, but that may be something on my end.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants