aboutsummaryrefslogtreecommitdiff
path: root/fnl/nvrc/macro
diff options
context:
space:
mode:
Diffstat (limited to 'fnl/nvrc/macro')
-rw-r--r--fnl/nvrc/macro/color.fnl9
-rw-r--r--fnl/nvrc/macro/event.fnl63
-rw-r--r--fnl/nvrc/macro/keymap.fnl46
-rw-r--r--fnl/nvrc/macro/misc.fnl1
-rw-r--r--fnl/nvrc/macro/pack.fnl80
-rw-r--r--fnl/nvrc/macro/set.fnl79
-rw-r--r--fnl/nvrc/macro/thread.fnl15
-rw-r--r--fnl/nvrc/macro/toolkit.fnl39
8 files changed, 332 insertions, 0 deletions
diff --git a/fnl/nvrc/macro/color.fnl b/fnl/nvrc/macro/color.fnl
new file mode 100644
index 0000000..9636956
--- /dev/null
+++ b/fnl/nvrc/macro/color.fnl
@@ -0,0 +1,9 @@
+(fn tbl? [x]
+ (= :table (type x)))
+
+(fn highlight [group-arg colset]
+ "Add a highlighting group."
+ (each [_ group (ipairs (if (tbl? group-arg) group-arg [group-arg]))]
+ (vim.api.nvim_set_hl 0 group colset)))
+
+{: highlight}
diff --git a/fnl/nvrc/macro/event.fnl b/fnl/nvrc/macro/event.fnl
new file mode 100644
index 0000000..3453431
--- /dev/null
+++ b/fnl/nvrc/macro/event.fnl
@@ -0,0 +1,63 @@
+(import-macros {: as->} :nvrc.macro.thread)
+
+(local {: format} string)
+(local {: insert : concat} table)
+
+(local {: fn? : gensym-checksum : vlua} (require :nvrc.macro.toolkit))
+
+(fn last [xs]
+ (. xs (length xs)))
+
+(fn ->str [x]
+ (tostring x))
+
+(fn includes? [xs x]
+ (accumulate [is? false _ v (ipairs xs) :until is?]
+ (= v x)))
+
+(lambda au! [name ...]
+ "Defines an autocommand group using the vim API."
+ `(do
+ (vim.cmd ,(format "augroup %s" name))
+ (vim.cmd :autocmd!)
+ (do
+ ,...)
+ (vim.cmd "augroup END")))
+
+(lambda aub! [name ...]
+ "Defines a buffer-local autocommand group using the vim API."
+ `(do
+ (vim.cmd ,(format "augroup %s" name))
+ (vim.cmd "autocmd! * <buffer>")
+ (do
+ ,...)
+ (vim.cmd "augroup END")))
+
+(lambda ac! [events pattern ...]
+ "Defines an autocommand using the vim API."
+ (let [events (as-> [$ events] (if (sequence? $) $ [$])
+ (icollect [_ v (ipairs $)]
+ (->str v)) (concat $ ","))
+ pattern (as-> [$ pattern] (if (sequence? $) $ [$])
+ (icollect [_ v (ipairs $)]
+ (->str v)) (concat $ ","))
+ once? (or (includes? [...] `++once) (includes? [...] :++once))
+ nested? (or (includes? [...] `++nested) (includes? [...] :++nested))
+ command (last [...])]
+ (if (fn? command)
+ (let [fsym (gensym-checksum "__" command)]
+ `(do
+ (global ,fsym ,command)
+ (vim.cmd ,(format (if (and once? nested?)
+ "autocmd %s %s ++once ++nested call %s" once?
+ "autocmd %s %s ++once call %s" nested?
+ "autocmd %s %s ++nested call %s"
+ "autocmd %s %s call %s")
+ events pattern (vlua fsym)))))
+ `(vim.cmd ,(format (if (and once? nested?)
+ "autocmd %s %s ++once ++nested %s" once?
+ "autocmd %s %s ++once %s" nested?
+ "autocmd %s %s ++nested %s" "autocmd %s %s %s")
+ events pattern command)))))
+
+{: au! : aub! : ac!}
diff --git a/fnl/nvrc/macro/keymap.fnl b/fnl/nvrc/macro/keymap.fnl
new file mode 100644
index 0000000..7a784ab
--- /dev/null
+++ b/fnl/nvrc/macro/keymap.fnl
@@ -0,0 +1,46 @@
+(local {: gmatch} string)
+(local {: insert} table)
+
+(local {: fn?} (require :nvrc.macro.toolkit))
+
+(fn ->str [x]
+ (tostring x))
+
+(fn nil? [x]
+ (= nil x))
+
+(fn str? [x]
+ (= :string (type x)))
+
+(fn tbl? [x]
+ (= :table (type x)))
+
+(lambda map! [[modes & options] lhs rhs ?desc]
+ "Defines a new mapping using the lua API.
+ Supports all the options that the API supports."
+ (assert-compile (sym? modes) "expected symbol for modes" modes)
+ (assert-compile (tbl? options) "expected table for options" options)
+ (assert-compile (str? lhs) "expected string for lhs" lhs)
+ (assert-compile (or (str? rhs) (list? rhs) (fn? rhs) (sym? rhs))
+ "expected string or list or function or symbol for rhs" rhs)
+ (assert-compile (or (nil? ?desc) (str? ?desc))
+ "expected string or nil for description" ?desc)
+ (let [modes (icollect [char (gmatch (->str modes) ".")]
+ char)
+ options (collect [_ v (ipairs options)]
+ (->str v)
+ true)
+ rhs (if (and (not (fn? rhs)) (list? rhs)) `#,rhs rhs)
+ desc (if (and (not ?desc) (or (fn? rhs) (sym? rhs))) (view rhs) ?desc)
+ options (if desc (doto options (tset :desc desc)) options)]
+ `(vim.keymap.set ,modes ,lhs ,rhs ,options)))
+
+(lambda mapb! [[modes & options] lhs rhs ?description]
+ "Defines a new mapping using the lua API.
+ Supports all the options that the API supports.
+ Automatically sets the `:buffer` option."
+ (let [options (doto options
+ (insert :buffer))]
+ (map! [modes (unpack options)] lhs rhs ?description)))
+
+{: map! : mapb!}
diff --git a/fnl/nvrc/macro/misc.fnl b/fnl/nvrc/macro/misc.fnl
new file mode 100644
index 0000000..cde60ce
--- /dev/null
+++ b/fnl/nvrc/macro/misc.fnl
@@ -0,0 +1 @@
+{:disable-builtins! #(vim.tbl_map #(tset vim.g (.. :loaded_ $) 1) $)}
diff --git a/fnl/nvrc/macro/pack.fnl b/fnl/nvrc/macro/pack.fnl
new file mode 100644
index 0000000..5ba7896
--- /dev/null
+++ b/fnl/nvrc/macro/pack.fnl
@@ -0,0 +1,80 @@
+(fn str? [x]
+ (= :string (type x)))
+
+(fn nil? [x]
+ (= nil x))
+
+(fn tbl? [x]
+ (= :table (type x)))
+
+(local {: format} string)
+(local {: insert} table)
+
+(global nvrc/pack [])
+(global nvrc/rock [])
+
+(lambda pack [identifier ?options]
+ "Returns a mixed table with the identifier as the first sequential element
+ and options as hash-table items.
+ See https://github.com/wbthomason/packer.nvim for information about the
+ options."
+ (assert-compile (str? identifier) "expected string for identifier" identifier)
+ (assert-compile (or (nil? ?options) (tbl? ?options))
+ "expected table for options" ?options)
+ (let [options (or ?options {})
+ options (collect [k v (pairs options)]
+ (if
+ (= k :req) (values :config (format "require('nvrc.packs.%s')" v))
+ (= k :init) (values :config (format "require('%s').setup()" v))
+ (= k :defer) (values :setup (format "require('nvrc.utils').defer_unpack('%s', 5)" v))
+ (values k v)))]
+ (doto options
+ (tset 1 identifier))))
+
+(lambda pack! [identifier ?options]
+ "Declares a plugin with its options.
+ This is a mixed table saved on the global compile-time variable nvrc/pack.
+ See https://github.com/wbthomason/packer.nvim for information about the
+ options."
+ (assert-compile (str? identifier) "expected string for identifier" identifier)
+ (assert-compile (or (nil? ?options) (tbl? ?options))
+ "expected table for options" ?options)
+ (insert nvrc/pack (pack identifier ?options)))
+
+(lambda rock [identifier ?options]
+ "Returns a mixed table with the identifier as the first sequential element
+ and options as hash-table items.
+ See https://github.com/wbthomason/packer.nvim for information about the
+ options."
+ (assert-compile (str? identifier) "expected string for identifier" identifier)
+ (assert-compile (or (nil? ?options) (tbl? ?options))
+ "expected table for options" ?options)
+ (let [options (or ?options {})]
+ (doto options
+ (tset 1 identifier))))
+
+(lambda rock! [identifier ?options]
+ "Declares a plugin with its options.
+ This is a mixed table saved on the global compile-time variable nvrc/rock.
+ See https://github.com/wbthomason/packer.nvim for information about the
+ options."
+ (assert-compile (str? identifier) "expected string for identifier" identifier)
+ (assert-compile (or (nil? ?options) (tbl? ?options))
+ "expected table for options" ?options)
+ (insert nvrc/rock (rock identifier ?options)))
+
+(lambda unpack! []
+ "Initializes the plugin manager with the previously declared plugins and
+ their options."
+ (let [packs (icollect [_ v (ipairs nvrc/pack)]
+ `(use ,v))
+ rocks (icollect [_ v (ipairs nvrc/rock)]
+ `(use_rocks ,v))]
+ `((. (require :packer) :startup) #(do
+ ,(unpack (icollect [_ v (ipairs packs) :into rocks] v))))))
+
+{: pack
+ : pack!
+ : rock
+ : rock!
+ : unpack!}
diff --git a/fnl/nvrc/macro/set.fnl b/fnl/nvrc/macro/set.fnl
new file mode 100644
index 0000000..144bdef
--- /dev/null
+++ b/fnl/nvrc/macro/set.fnl
@@ -0,0 +1,79 @@
+(local {: fn? : gensym-checksum : vlua} (require :nvrc.macro.toolkit))
+
+(fn str? [x]
+ (= :string (type x)))
+
+(fn ->str [x]
+ (tostring x))
+
+(fn nil? [x]
+ (= nil x))
+
+(fn includes? [xs x]
+ (accumulate [is? false _ v (ipairs xs) :until is?]
+ (= v x)))
+
+(lambda set! [name ?value]
+ "Set a vim option via the lua API.
+ The name of the option must a symbol.
+ If no value is specified, if the name begins with 'no' the value
+ becomes false, true otherwise."
+ (assert-compile (sym? name) "expected symbol for name" name)
+ (let [name (->str name)
+ value (or ?value (not (name:match "^no")))
+ name (or (name:match "^no(.+)$") name)]
+ (if (fn? value)
+ (let [vsym (gensym-checksum "__" value)]
+ `(do
+ (global ,vsym ,value)
+ (tset vim.opt ,name ,(vlua vsym))))
+ (match (name:sub -1)
+ "+" `(: (. vim.opt ,(name:sub 1 -2)) :append ,value)
+ "-" `(: (. vim.opt ,(name:sub 1 -2)) :remove ,value)
+ "^" `(: (. vim.opt ,(name:sub 1 -2)) :prepend ,value)
+ _ `(tset vim.opt ,name ,value)))))
+
+(lambda setl! [name ?value]
+ "Set a vim local option via the lua API.
+ The name of the option must a symbol.
+ If no value is specified, if the name begins with 'no' the value
+ becomes false, true otherwise."
+ (assert-compile (sym? name) "expected symbol for name" name)
+ (let [name (->str name)
+ value (or ?value
+ (not (name:match "^no")))
+ name (or (name:match "^no(.+)$")
+ name)]
+ (if (fn? value)
+ (let [fsym (gensym-checksum "__" value)]
+ `(do
+ (global ,fsym ,value)
+ (tset vim.opt_local ,name ,(vlua fsym))))
+ (match (name:sub -1)
+ :+ `(: (. vim.opt_local ,(name:sub 1 -2)) :append ,value)
+ :- `(: (. vim.opt_local ,(name:sub 1 -2)) :remove ,value)
+ :^ `(: (. vim.opt_local ,(name:sub 1 -2)) :prepend ,value)
+ _ `(tset vim.opt_local ,name ,value)))))
+
+(lambda setv! [name value]
+ "Set a vim variable via the lua API.
+ The name can be either a symbol or a string.
+ If the name begins with [gbwt] followed by [/:.], the name
+ is scoped to the respective scope."
+ (assert-compile (or (str? name) (sym? name))
+ "expected string or symbol for name" name)
+ (let [name (->str name)
+ scope (when (includes? ["g/" "b/" "w/" "t/"
+ "g." "b." "w." "t."
+ "g:" "b:" "w:" "t:"] (name:sub 1 2))
+ (name:sub 1 1))
+ name (if
+ (nil? scope) name
+ (name:sub 3))]
+ `(tset ,(match scope
+ :b 'vim.b
+ :w 'vim.w
+ :t 'vim.t
+ _ 'vim.g) ,name ,value)))
+
+{: set! : setl! : setv!}
diff --git a/fnl/nvrc/macro/thread.fnl b/fnl/nvrc/macro/thread.fnl
new file mode 100644
index 0000000..9060b04
--- /dev/null
+++ b/fnl/nvrc/macro/thread.fnl
@@ -0,0 +1,15 @@
+(local {: insert} table)
+
+(lambda as-> [[binding expr] ...]
+ "A threading macro where the first argument is the value binded to the
+ second argument, which must be a symbol.
+ This binding is valid for the whole body of the threading macro."
+ (assert-compile (sym? binding) "expected symbol for binding" binding)
+ `(let [,binding ,expr
+ ,(unpack (accumulate [exprs [] _ expr (ipairs [...])]
+ (doto exprs
+ (insert binding)
+ (insert expr))))]
+ ,binding))
+
+{: as->}
diff --git a/fnl/nvrc/macro/toolkit.fnl b/fnl/nvrc/macro/toolkit.fnl
new file mode 100644
index 0000000..8a2bc50
--- /dev/null
+++ b/fnl/nvrc/macro/toolkit.fnl
@@ -0,0 +1,39 @@
+(local {: format} string)
+
+(fn ->str [x]
+ (tostring x))
+
+(fn head [xs]
+ (. xs 1))
+
+(fn fn? [x]
+ "Returns whether the parameter(s) is a function.
+ A function is defined as any list with 'fn or 'hashfn as
+ their first element."
+ (and (list? x) (or (= `fn (head x)) (= `hashfn (head x)))))
+
+(lambda gensym-checksum [...]
+ "Generates a new symbol from the checksum of the object
+ passed as a parameter.
+ The parameter first is casted into a string using the
+ function `fennel.view`.
+ If only one parameter is passed to the function the return
+ value is the checksum as a symbol.
+ If two parameters are passed, the first one is considered
+ the prefix.
+ If three parameters are passed, the first one is considered
+ the prefix and the last one is considered the suffix.
+ This function depends on the md5 library and the fennel library."
+ (match [...]
+ [prefix object suffix] (let [{: view} (require :fennel)
+ {:sumhexa md5} (require :md5)]
+ (sym (.. prefix (md5 (view object)) suffix)))
+ [prefix object] (gensym-checksum prefix object "")
+ [object] (gensym-checksum "" object "")))
+
+(lambda vlua [x]
+ "Return a symbol mapped to `v:lua.%s()`, where `%s` is the symbol."
+ (assert-compile (sym? x) "expected symbol for x" x)
+ (format "v:lua.%s()" (->str x)))
+
+{: fn? : gensym-checksum : vlua}