123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127 |
- ;;; 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!}
|