127 lines
4.3 KiB
Fennel
127 lines
4.3 KiB
Fennel
;;; macros.fnl - useful macros
|
|
|
|
;; Helpful keymaping functions
|
|
(lambda bind! [modes key cmd ?a1 ?a2]
|
|
(let [desc (or ?a2 ?a1)
|
|
buf (if (and ?a1 ?a2) ?a1 ?a2)
|
|
opts { :noremap true
|
|
:silent true
|
|
:buffer buf }]
|
|
(when desc
|
|
(tset opts :desc desc))
|
|
(if (table? modes)
|
|
(let [output {}]
|
|
(each [_ mode (ipairs modes)]
|
|
(table.insert output `(vim.keymap.set ,mode ,key ,cmd ,opts)))
|
|
output)
|
|
`(vim.keymap.set ,modes ,key ,cmd ,opts))))
|
|
|
|
;; Better autocommands
|
|
(lambda hook! [hooks ?patterns callback]
|
|
(let [hook_table (if (= (type hooks) :table)
|
|
hooks
|
|
[ hooks ])
|
|
pattern_table (if (not ?patterns)
|
|
[]
|
|
(= (type ?patterns) :table)
|
|
?patterns
|
|
[ ?patterns ])]
|
|
(var group (.. (tostring (math.random 0 1000000000) "-config-hook")))
|
|
(each [_ hook (ipairs hook_table)]
|
|
(set group (.. group "-" hook)))
|
|
(each [_ pattern (ipairs pattern_table)]
|
|
(set group (.. group "-" pattern)))
|
|
`(vim.api.nvim_create_autocmd ,hook_table
|
|
{ :group
|
|
(vim.api.nvim_create_augroup ,group
|
|
{ :clear true })
|
|
:pattern ,pattern_table
|
|
:callback ,callback })))
|
|
|
|
;; Utility functions for use!
|
|
(lambda create-list-entries [...]
|
|
(let [output { :active-entry nil
|
|
:entries {} }]
|
|
(lambda output.process [self entry]
|
|
(var result false)
|
|
(when self.active-entry
|
|
(if (and (. self :entries self.active-entry :is-first)
|
|
(not (list? entry)))
|
|
(do (tset self :entries self.active-entry :data entry)
|
|
(set self.active-entry nil)
|
|
(set result true))
|
|
(= (type entry) :string)
|
|
(set self.active-entry nil)
|
|
(do (table.insert (. self :entries self.active-entry :data) entry)
|
|
(tset self :entries self.active-entry :is-first false)
|
|
(set result true))))
|
|
(when (and (= (type entry) :string) (. self :entries entry))
|
|
(assert-compile (not (. self :entries entry :present))
|
|
(.. "':" entry "' cannot appear more than once in `use'"))
|
|
(set self.active-entry entry)
|
|
(tset self :entries entry :present true)
|
|
(set result true))
|
|
result)
|
|
(lambda output.splice-into [self other]
|
|
(each [name entry (pairs self.entries)]
|
|
(when entry.present
|
|
(tset other name entry.data))))
|
|
(each [_ val (ipairs [...])]
|
|
(tset output :entries val { :present false :is-first true :data `(lambda [])}))
|
|
output))
|
|
|
|
;; Nicer macro for use
|
|
;; :config acts like use-package's :init and :config options,
|
|
;; taking in the following lisp expressions as its arguments
|
|
(lambda use! [repo ...]
|
|
(local output [ repo ])
|
|
(var last_key nil)
|
|
(var list_entries (create-list-entries :config :setup
|
|
:run))
|
|
(each [_ val (ipairs [...])]
|
|
(if last_key
|
|
(do (tset output last_key val)
|
|
(set last_key nil))
|
|
(not (list_entries:process val))
|
|
(set last_key val)))
|
|
(list_entries:splice-into output)
|
|
`(use ,output))
|
|
|
|
;; Call a plugin's `setup function'
|
|
(lambda setup! [pkg ...]
|
|
(local output [ ])
|
|
(var last_key nil)
|
|
(each [_ val (ipairs [...])]
|
|
(if last_key
|
|
(do (tset output last_key val)
|
|
(set last_key nil))
|
|
(set last_key val)))
|
|
`((. (require ,pkg) :setup) ,output))
|
|
|
|
;; Call module function
|
|
(lambda module-call! [mod func ...]
|
|
`((. (require ,mod) ,func) ,...))
|
|
|
|
;; Return module function
|
|
(lambda module-fn! [mod func]
|
|
`(. (require ,mod) ,func))
|
|
|
|
;; Basically does what the Emacs function of the same name does.
|
|
;; Wraps the code inside with a `winsaveview' and `winrestview'
|
|
(lambda save-excursion! [...]
|
|
(let [args [...]
|
|
len (# args)]
|
|
(tset args len `(let [retvar# ,(. args len)]
|
|
(vim.fn.winrestview save#)
|
|
retvar#))
|
|
`(let [save# (vim.fn.winsaveview)]
|
|
,(unpack args))))
|
|
|
|
{: bind!
|
|
: hook!
|
|
: use!
|
|
: setup!
|
|
: module-call!
|
|
: module-fn!
|
|
: save-excursion!}
|