Olical / aniseed

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

autocmd, autocmds, augroup macros #135

Closed randomizedthinking closed 1 year ago

randomizedthinking commented 1 year ago

Here are three macros for setting up autocmd and augroup. I can create a PR if you think it is reasonable to have.

(macro autocmd [event opt]
  `(vim.api.nvim_create_autocmd
    ,event ,opt))

(macro autocmds [...]
  (var form `(do))
  (each [_ v (ipairs [...])]
    (table.insert form
                  `(autocmd ,(unpack v))))
  (table.insert form 'nil)
  form)

(macro augroup [name ...]
  (var cmds `(do))
  (var group (sym :group))
  (each [_ v (ipairs [...])]
    (let [(event opt) (unpack v)]
      (tset opt :group group)
      (table.insert cmds `(autocmd ,event ,opt))))
  (table.insert cmds 'nil)
  `(let [,group
         (vim.api.nvim_create_augroup ,name {:clear true})]
     ,cmds))

(autocmd
 [:BufNewFile :BufRead] {:pattern [:*.txt :*.text] :command "setf text"})

;; vim.api.nvim_create_autocmd({"BufNewFile", "BufRead"}, {pattern = {"*.txt", "*.text"}, command = "setf text"})

(autocmds
 [[:BufNewFile :BufRead] {:pattern [:*.txt :*.text] :command "setf text"     }]
 [[:BufNewFile :BufRead] {:pattern [:*vifmrc]       :command "setf vifm"     }]
 [[:BufNewFile :BufRead] {:pattern [:*/tmux/conf]   :command "setf tmux"     }]
 [[:BufNewFile :BufRead] {:pattern [:*/git/config]  :command "setf gitconfig"}]
 [[:BufNewFile :BufRead] {:pattern [:*fetchmail]    :command "setf fetchmail"}]
 [[:BufNewFile :BufRead] {:pattern [:*procmailrc]   :command "setf procmail" }]
 [[:BufNewFile :BufRead] {:pattern [:*muttrc]       :command "setf muttrc"   }])

;; do
;;   vim.api.nvim_create_autocmd({"BufNewFile", "BufRead"}, {pattern = {"*.txt", "*.text"}, command = "setf text"})
;;   vim.api.nvim_create_autocmd({"BufNewFile", "BufRead"}, {pattern = {"*vifmrc"}, command = "setf vifm"})
;;   vim.api.nvim_create_autocmd({"BufNewFile", "BufRead"}, {pattern = {"*/tmux/conf"}, command = "setf tmux"})
;;   vim.api.nvim_create_autocmd({"BufNewFile", "BufRead"}, {pattern = {"*/git/config"}, command = "setf gitconfig"})
;;   vim.api.nvim_create_autocmd({"BufNewFile", "BufRead"}, {pattern = {"*fetchmail"}, command = "setf fetchmail"})
;;   vim.api.nvim_create_autocmd({"BufNewFile", "BufRead"}, {pattern = {"*procmailrc"}, command = "setf procmail"})
;;   vim.api.nvim_create_autocmd({"BufNewFile", "BufRead"}, {pattern = {"*muttrc"}, command = "setf muttrc"})
;; end

(augroup :my-group
 [[:BufNewFile :BufRead] {:pattern [:*vifmrc]     :command "setf vifm"     }]
 [[:BufNewFile :BufRead] {:pattern [:*/tmux/conf] :command "setf tmux"     }]
 [[:BufNewFile :BufRead] {:pattern [:*muttrc]     :command "setf muttrc"   }])

;; local group = vim.api.nvim_create_augroup("my-group", {clear = true})
;; vim.api.nvim_create_autocmd({"BufNewFile", "BufRead"}, {pattern = {"*vifmrc"}, command = "setf vifm", group = group})
;; vim.api.nvim_create_autocmd({"BufNewFile", "BufRead"}, {pattern = {"*/tmux/conf"}, command = "setf tmux", group = group})
;; vim.api.nvim_create_autocmd({"BufNewFile", "BufRead"}, {pattern = {"*muttrc"}, command = "setf muttrc", group = group})
Olical commented 1 year ago

Oh this is pretty neat, maybe a separate macros file that people can require would be best 🤔 I regret the one large macro file in the current system and don't want to keep adding to it since it can collide with other names the user wishes to use. I'll have a play and see if I can get this into a file like aniseed.macros.autocmds or something like that.

Olical commented 1 year ago

Pushed some changes to the develop branch, added this code and some docs on how to include it. Usage looks like this:

(module aniseed.view
  {require {fnl aniseed.fennel}
   import-macros [[ac :aniseed.macros.autocmds]]})

(ac.autocmd
 [:BufNewFile :BufRead] {:pattern [:*.txt :*.text] :command "setf text"})

What do you think? I added some new stuff to the module macro so we can call import-macros properly now.

randomizedthinking commented 1 year ago

That's good. Maybe we can import all macros using require-macros?

Fennel has issues when a macro is referencing other macros. For instance, the augroup macro uses autocmd macro. If the macro autocmd is in a namespace ac, then ac.augroup would have problems at macroexpanding.

Olical commented 1 year ago

require-macros was deprecated in Fennel 0.4.0 and we're on 1.3.0 now, so there's a good chance they'll remove require-macros entirely at some point. I can't recommend it's use anywhere now, even if Aniseed legacy things rely on it.

As for the macro expanding issue, we should be able to work around that by referring to the macro outside of the generated code. As long as the macro code refers to it's sibling macros and the generated code doesn't require another layer of macro expansion, it should be fine. I'll check that now and adjust the code if required.

Olical commented 1 year ago

There you go, see that latest commit for the fix. Macros can refer to each other when in "macro land" as long as the bottom of the call stack returns some quoted code. But macros can call other macros directly just fine. I think this is correct and good practice, the other way that we had before can fall victim to variable shadowing bugs.

Grazfather commented 1 year ago

Found this issue browsing through the repo. I guess this should be closed since the macros are in the tree.

I find I still use require-macros because having to qualify the macros with a prefix removes some of the brevity I appreciate macros for. Is there a way to use import-macros and dump the macros into the namespace?

Olical commented 1 year ago
(module foo
  {import-macros [[{: autocmd} :aniseed.macros.autocmds]]})

(autocmd ...)

This might be what you're looking for, pay close attention to the number of sub-tables. You can't use import-macros and have it splat all macros from inside into your context, that's just describing require-macros which is deprecated for that reason I think. The language appears to be trying to remove implicit scope pollution in favour of explicit.

Olical commented 1 year ago

This was a relatively recent addition to Aniseed, so wasn't possible to express this in the module macro until probably the most recent version.

Grazfather commented 1 year ago

Right on. Thank you, that works, but I was hoping to not have to specify each macro I want to import (I have a bunch of macros of my own). I'll cave and do it this way eventually.