Olical / aniseed

Neovim configuration and plugins in Fennel (Lisp compiled to Lua)
https://discord.gg/wXAMr8F
The Unlicense
610 stars 28 forks source link

How to include or use external modules in macros? #23

Closed kkharji closed 4 years ago

kkharji commented 4 years ago

Hey @Olical, finally I'm back at rewriting my config with aniseed. Currently I'm trying to leverage macros. However, I'm getting errors due to external module, I tried to define c in let expression, didn't work, also tried defining a local variable (local c (require aniseed.core)) at the top of the file, but that too didn't fix my issue.

Here is my macro.fnl, I'm basically writing a macro that would bind key definition or a list of definitions.

Thanks

{
 :bindkey
 (fn [m]
   (let [options (or (. m 4) {})
         opts (c.merge {:noremap true :silent true} options)
         buffer (. m :buffer)
         prefix {}
         formatrhs (fn [m]
                     (let [opts (or (. m 4) {})
                           dep (. opts :dep)
                           extra (if (not dep) ""
                                   (c.table? dep) (.. "<cmd>packadd " (table.concat dep " ") "<cr>")
                                   (c.string? dep) (.. "<cmd>packadd " dep "<cr>"))
                           rhs (if (. opts :lua) (.. extra "<cmd>" "lua " (. m 3) "<cr>")
                                 (. opts :cmd) (.. extra "<cmd>" (. m 3) "<cr>")
                                 :else (.. extra (. m 3) ))] rhs))]
     `(do 
        (each [mode _ (string.gmatch (. m 1) "(%w)")]
          (table.insert prefix mode))
        (each [_ key (pairs [ "cmd" "lua" "dep" "buffer"])]
          (c.assoc opts key nil))
        (each [_ mode (pairs prefix)]
          (if buffer
            (vim.schedule #(vim.api.nvim_buf_set_keymap buffer mode (. m 2) (formatrhs m) opts))
            :else
            (vim.schedule #(vim.api.nvim_set_keymap mode (. m 2) (formatrhs m) opts))))   
        )))

 :bindgroup
 (fn [group]
   `(c.run! bindkey group))
}
Olical commented 4 years ago

Hey, so this is because you're referring to a value in your macro file at runtime with (c.run! bindkey group), c is not defined at runtime, only at compile time.

If you would like c at runtime you'll need something like this:

 :bindgroup
 (fn [group]
   `(let [c (require :aniseed.core]
      (c.run! bindkey group)))

Does that make sense?

kkharji commented 4 years ago

@Olical thanks for your quick response, let me test and report back

kkharji commented 4 years ago

@Olical I got this error now

Compile error in /home/tami/.config/nvim/fnl/env/macros.fnl:39
  macro tried to bind c without gensym
   `(let [c (require :aniseed.core)]
* Try changing to c# when introducing identifiers inside macros.

Current code

{
 :bindkey
 (fn [m]
   `(let [c (require :aniseed.core)
          options (or (. m 4) {})
          opts (c.merge {:noremap true :silent true} options)
          buffer (. m :buffer)
          prefix {}
          formatrhs (fn [m]
                      (let [opts (or (. m 4) {})
                            dep (. opts :dep)
                            extra (if (not dep) ""
                                    (c.table? dep) (.. "<cmd>packadd " (table.concat dep " ") "<cr>")
                                    (c.string? dep) (.. "<cmd>packadd " dep "<cr>"))
                            rhs (if (. opts :lua) (.. extra "<cmd>" "lua " (. m 3) "<cr>")
                                  (. opts :cmd) (.. extra "<cmd>" (. m 3) "<cr>")
                                  :else (.. extra (. m 3) ))] rhs))]
      (do
        (each [mode _ (string.gmatch (. m 1) "(%w)")]
          (table.insert prefix mode))
        (each [_ key (pairs [ "cmd" "lua" "dep" "buffer"])]
          (c.assoc opts key nil))
        (each [_ mode (pairs prefix)]
          (if buffer
            (vim.schedule #(vim.api.nvim_buf_set_keymap buffer mode (. m 2) (formatrhs m) opts))
            :else
            (vim.schedule #(vim.api.nvim_set_keymap mode (. m 2) (formatrhs m) opts))))
        )))

 :bindgroup
 (fn [group]
   `(let [c (require :aniseed.core)]
      (c.run! bindkey group)))
}
Olical commented 4 years ago

Oh, since you're introducing a local in that let in a macro fennel forces you to use generated symbols, or gensym, with a # suffix as the error explains.

So just replace occurrences of c with c# and it should be okay. This should all be documented on the fennel website, although maybe not in deep detail, reading my Aniseed macros file might help you out too.

kkharji commented 4 years ago

Thanks a lot @Olical , I'm going to revisit this after I'm done with porting my config.