aboutsummaryrefslogtreecommitdiff
path: root/fnl
diff options
context:
space:
mode:
authorsefidel <contact@sefidel.net>2022-02-10 00:24:03 +0900
committersefidel <contact@sefidel.net>2022-02-10 00:24:03 +0900
commit72d448e384249103748ee83b587c45924e4bc44d (patch)
tree2aa05a6aaf8c7aa37a8c278fd2fede6e62ff2218 /fnl
downloadnvimrc-72d448e384249103748ee83b587c45924e4bc44d.zip
Initial commit
Diffstat (limited to 'fnl')
-rw-r--r--fnl/nvrc/colors.fnl81
-rw-r--r--fnl/nvrc/events.fnl47
-rw-r--r--fnl/nvrc/ignite.fnl6
-rw-r--r--fnl/nvrc/keymaps.fnl45
-rw-r--r--fnl/nvrc/lib/io.fnl31
-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
-rw-r--r--fnl/nvrc/options.fnl51
-rw-r--r--fnl/nvrc/pack.fnl34
-rw-r--r--fnl/nvrc/packs/blankline.fnl11
-rw-r--r--fnl/nvrc/packs/cmp.fnl56
-rw-r--r--fnl/nvrc/packs/feline.fnl144
-rw-r--r--fnl/nvrc/packs/gitsigns.fnl7
-rw-r--r--fnl/nvrc/packs/lsp_signature.fnl15
-rw-r--r--fnl/nvrc/packs/lspconfig.fnl50
-rw-r--r--fnl/nvrc/packs/nvimtree.fnl44
-rw-r--r--fnl/nvrc/packs/telescope.fnl49
-rw-r--r--fnl/nvrc/packs/treesitter.fnl29
-rw-r--r--fnl/nvrc/utils.fnl127
25 files changed, 1159 insertions, 0 deletions
diff --git a/fnl/nvrc/colors.fnl b/fnl/nvrc/colors.fnl
new file mode 100644
index 0000000..854b79f
--- /dev/null
+++ b/fnl/nvrc/colors.fnl
@@ -0,0 +1,81 @@
+(local colors {:bg "#202020"
+ :nvimbg "#151515"
+ :fg "#cbc0ab"
+ :white "#e8e8d3"
+ :black "#181818"
+ :black2 "#101010"
+ :bblack "#252525"
+ :grey "#888888"
+ :grey2 "#666666"
+ :bgrey "#999999"
+ :red "#cf6a4c"
+ :orange "#fabb6e"
+ :yellow "#fad07a"
+ :lyellow "#ffe2a9"
+ :green "#99ad6a"
+ :skyblue "#8fbfdc"
+ :blue "#8197bf"
+ :violet "#c6b6ee"
+ :magenta "#f0a0c0"
+ :sign "#333333"})
+
+(fn colors.apply []
+ (local {: highlight} (require :nvrc.macro.color))
+ (vim.cmd "colorscheme jellybeans")
+
+ ; Buffer
+ (highlight :EndOfBuffer {:fg (. colors :bg)})
+ (highlight :FloatBorder {:fg (. colors :blue)})
+ (highlight :NormalFloat {:bg (. colors :bblack)})
+
+ ; Pmenu
+ (highlight :Pmenu {:bg (. colors :bblack)})
+ (highlight :PmenuSbar {:bg (. colors :bblack)})
+ (highlight :PmenuSel {:fg (. colors :orange) :bg (. colors :sign)})
+ (highlight :PmenuThumb {:bg (. colors :skyblue)})
+ (highlight :CmpItemAbbr {:fg (. colors :fg)})
+ (highlight :CmpItemAbbrMatch {:fg (. colors :fg)})
+ (highlight :CmpItemKind {:fg (. colors :fg)})
+ (highlight :CmpItemMenu {:fg (. colors :fg)})
+
+ ; Misc
+ (highlight :StatusLine {:bg (. colors :black)})
+ (highlight :StatusLineNC {:fg (. colors :grey) :bg (. colors :black) :underline true})
+ (highlight :LineNr {:fg (. colors :grey)})
+ (highlight :NvimInternalError {:fg (. colors :red)})
+ (highlight :VertSplit {:fg (. colors :grey2)})
+
+ ; Gitsigns
+ (highlight :DiffAdd {:fg (. colors :green) :bg (. colors :sign)})
+ (highlight :DiffChange {:fg (. colors :yellow) :bg (. colors :sign)})
+ (highlight :DiffChangeDelete {:fg (. colors :red) :bg (. colors :sign)})
+ (highlight :DiffModified {:fg (. colors :red) :bg (. colors :sign)})
+ (highlight :DiffDelete {:fg (. colors :red) :bg (. colors :sign)})
+
+ ; Nvimtree
+ (highlight :NvimTreeNormal {:bg (. colors :black)})
+ (highlight :NvimTreeNormalNC {:bg (. colors :black)})
+ (highlight :NvimTreeStatuslineNC {:fg (. colors :black) :bg (. colors :black)})
+ (highlight :NvimTreeVertSplit {:fg (. colors :black) :bg (. colors :black)})
+ (highlight :NvimTreeWindowPicker {:fg (. colors :red) :bg (. colors :black2)})
+ (highlight :NvimTreeIndentMarker {:fg (. colors :grey)})
+ (highlight :NvimTreeGitDirty {:fg (. colors :red)})
+ (highlight :NvimTreeRootFolder {:fg (. colors :red) :underline true})
+ (highlight :NvimTreeEmptyFolderName {:fg (. colors :skyblue)})
+ (highlight :NvimTreeFolderIcon {:fg (. colors :skyblue)})
+ (highlight :NvimTreeFolderName {:fg (. colors :skyblue)})
+ (highlight :NvimTreeOpenedFolderName {:fg (. colors :magenta)})
+ (highlight :NvimTreeEndOfBuffer {:fg (. colors :black2)})
+
+ ; Telescope
+ (highlight :TelescopeBorder {:fg (. colors :fg)})
+ (highlight :TelescopePromptBorder {:fg (. colors :fg)})
+ (highlight :TelescopePromptNormal {:fg (. colors :fg)})
+ (highlight :TelescopePromptPrefix {:fg (. colors :red)})
+ (highlight :TelescopeNormal {:bg :NONE})
+ (highlight :TelescopePreviewTitle {:fg (. colors :nvimbg) :bg (. colors :green)})
+ (highlight :TelescopePromptTitle {:fg (. colors :nvimbg) :bg (. colors :red)})
+ (highlight :TelescopeResultsTitle {:fg (. colors :nvimbg) :bg (. colors :skyblue)})
+ (highlight :TelescopeSelection {:link :Search}))
+
+colors
diff --git a/fnl/nvrc/events.fnl b/fnl/nvrc/events.fnl
new file mode 100644
index 0000000..a798fcf
--- /dev/null
+++ b/fnl/nvrc/events.fnl
@@ -0,0 +1,47 @@
+(import-macros {: au!
+ : ac!} :nvrc.macro.event)
+(import-macros {: set!
+ : setl!} :nvrc.macro.set)
+(local {: echo!} (require :nvrc.lib.io))
+
+(local {: line
+ : mode} vim.fn)
+(fn cmd! [...] (vim.cmd ...))
+(fn bufexists? [...] (= (vim.fn.bufexists ...) 1))
+
+; Restore cursor style to beam on exit
+(au! restore-cursor
+ (ac! VimLeave * #(set! guicursor ["a:ver75-blinkon0"])))
+
+; Restore the last cursor line
+(au! restore-last-cursor-line
+ (ac! BufReadPost * #(if (and (> (line "'\"") 1)
+ (<= (line "'\"") (line "$")))
+ (cmd! "normal! g'\""))))
+
+; Resize splits on window resize
+(au! resize-splits-on-resize
+ (ac! VimResized * "wincmd ="))
+
+;; Read file when it changes on disk
+(au! read-file-on-disk-change
+ (ac! [FocusGained BufEnter CursorHold CursorHoldI] *
+ #(if (and (not= :c (mode))
+ (not (bufexists? "[Command Line]")))
+ (cmd! "checktime")))
+ (ac! FileChangedShellPost *
+ #(echo! "File changed on disk. Buffer reloaded.")))
+
+(au! terminal-options
+ ;; Enter Terminal-mode (insert) automatically
+ (ac! TermOpen * "startinsert")
+ ;; Disables line number on terminal buffers
+ (ac! TermOpen * #(do
+ (setl! nonumber)
+ (setl! norelativenumber)))
+ ;; Disables spell on terminal buffers
+ (ac! TermOpen * #(setl! nospell))
+ ;; Disables sign column on terminal buffers
+ (ac! TermOpen * #(setl! signcolumn :no))
+ ;; Disables colorcolumn on terminal buffers
+ (ac! TermOpen * #(setl! colorcolumn [])))
diff --git a/fnl/nvrc/ignite.fnl b/fnl/nvrc/ignite.fnl
new file mode 100644
index 0000000..04f416b
--- /dev/null
+++ b/fnl/nvrc/ignite.fnl
@@ -0,0 +1,6 @@
+; Get the rocket going
+
+(require :nvrc.options)
+(require :nvrc.pack)
+(require :nvrc.keymaps)
+(require :nvrc.events)
diff --git a/fnl/nvrc/keymaps.fnl b/fnl/nvrc/keymaps.fnl
new file mode 100644
index 0000000..67b0d70
--- /dev/null
+++ b/fnl/nvrc/keymaps.fnl
@@ -0,0 +1,45 @@
+(import-macros {: map!} :nvrc.macro.keymap)
+(import-macros {: setv!} :nvrc.macro.set)
+
+(map! [n] :<space> "" "")
+(setv! mapleader " ")
+
+(map! [n :silent] :<leader>fe ":NvimTreeToggle <cr>")
+(map! [n :silent] :<leader>ft ":NvimTreeFocus <cr>")
+
+(map! [n :silent] :<leader>/
+ ":lua require('Comment.api').toggle_current_linewise() <cr>")
+(map! [v :silent] :<leader>/
+ ":lua require('Comment.api').toggle_linewise_op(vim.fn.visualmode()) <cr>")
+
+(map! [n :silent] :<leader>ff ":Telescope find_files <cr>")
+(map! [n :silent] :<leader>fc ":Telescope grep_string <cr>")
+(map! [n :silent] :<leader>fs ":Telescope live_grep <cr>")
+(map! [n :silent] :<leader>fa
+ ":Telescope find_files follow=true no_ignore=true hidden=true <cr>")
+(map! [n :silent] :<leader>fb ":Telescope buffers <cr>")
+(map! [n :silent] :<leader>gc ":Telescope git_commits <cr>")
+(map! [n :silent] :<leader>gs ":Telescope git_status <cr>")
+
+(map! [n] :f :<plug>Lightspeed_f)
+(map! [n] :F :<plug>Lightspeed_F)
+(map! [n] :t :<plug>Lightspeed_t)
+(map! [n] :T :<plug>Lightspeed_T)
+
+(map! [n :silent] :<leader>rm ":TZMinimalist <cr>")
+(map! [n :silent] :<leader>rf ":TZFocus <cr>")
+(map! [n :silent] :<leader>ra ":TZAtaraxis <cr>")
+
+(map! [t] :jk "<C-\\><C-n>")
+(map! [t :silent] :JK "<C-\\><C-n> :lua require ('nvrc.utils').close_buf() <cr>")
+(map! [n :silent] :<leader>tl ":Telescope terms <cr>")
+; FIXME This opens on top of existing vertical/horizontal term
+(map! [n :silent] :<leader>th ":execute 15 .. 'new +terminal' | let b:term_type = 'hori' <cr>")
+(map! [n :silent] :<leader>tv ":execute 'vnew +terminal' | let b:term_type = 'vert' <cr>")
+(map! [n :silent] :<leader>tn ":execute 'terminal' | let b:term_type = 'wind' <cr>")
+
+(map! [n :silent] :<leader>q ":lua require('nvrc.utils').close_buf() <cr>")
+(map! [n :silent] :<leader>ya ":%y+ <cr>")
+(map! [n :silent] :<leader>bn ":enew <cr>")
+(map! [n :silent] :<leader>wn ":tabnew <cr>")
+(map! [n :silent] :<leader>lt ":set nu! <cr>")
diff --git a/fnl/nvrc/lib/io.fnl b/fnl/nvrc/lib/io.fnl
new file mode 100644
index 0000000..7d20ed7
--- /dev/null
+++ b/fnl/nvrc/lib/io.fnl
@@ -0,0 +1,31 @@
+(fn cmd! [...] (vim.cmd ...))
+(local {: format
+ : sub} string)
+
+(fn str? [x]
+ (= :string (type x)))
+
+(lambda double-quote [s]
+ "Add double quotes at the beginning and end of the string."
+ (assert (str? s) "expected string for s")
+ (format "\"%s\"" s))
+
+(lambda echo! [s]
+ "Print a vim message without any format."
+ (cmd! (format "echom %s" (double-quote s))))
+
+(lambda warn! [s]
+ "Print a vim message with a warning format."
+ (cmd! (format "echohl WarningMsg
+ echom %s
+ echohl None" (double-quote s))))
+
+(lambda err! [s]
+ "Print a vim message with an error format."
+ (cmd! (format "echohl ErrorMsg
+ echom %s
+ echohl None" (double-quote s))))
+
+{: echo!
+ : warn!
+ : err!}
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}
diff --git a/fnl/nvrc/options.fnl b/fnl/nvrc/options.fnl
new file mode 100644
index 0000000..b9a59bc
--- /dev/null
+++ b/fnl/nvrc/options.fnl
@@ -0,0 +1,51 @@
+(import-macros {: set! : setv!} :nvrc.macro.set)
+(local {: disable-builtins!} (require :nvrc.macro.misc))
+
+(set! clipboard :unnamedplus)
+
+; Interface
+(set! cul)
+(set! cmdheight 1)
+(set! number)
+(set! numberwidth 2)
+(set! shortmess+ :sI)
+(set! splitbelow)
+(set! splitright)
+(set! termguicolors)
+(set! lazyredraw)
+
+; Style
+(set! expandtab)
+(set! tabstop 8)
+(set! shiftwidth 2)
+(set! smartindent)
+(set! list)
+(set! listchars {:tab ">-" :extends ">" :precedes "<" :trail "*" :nbsp "+"})
+
+; Miscellaneous
+(set! ignorecase)
+(set! smartcase)
+(set! mouse :a)
+(set! timeoutlen 400)
+(set! updatetime 250)
+(set! undofile)
+(set! whichwrap+ "<>[]hl")
+
+(disable-builtins! [:2html_plugin
+ :getscript
+ :getscriptPlugin
+ :gzip
+ :logipat
+ :netrw
+ :netrwPlugin
+ :netrwSettings
+ :netrwFileHandlers
+ :matchit
+ :tar
+ :tarPlugin
+ :rrhelper
+ :spellfile_plugin
+ :vimball
+ :vimballPlugin
+ :zip
+ :zipPlugin])
diff --git a/fnl/nvrc/pack.fnl b/fnl/nvrc/pack.fnl
new file mode 100644
index 0000000..a1c611a
--- /dev/null
+++ b/fnl/nvrc/pack.fnl
@@ -0,0 +1,34 @@
+(import-macros {: pack! : unpack!} :nvrc.macro.pack)
+
+(pack! :wbthomason/packer.nvim)
+(pack! :rktjmp/hotpot.nvim)
+(pack! :lewis6991/impatient.nvim)
+(pack! :nvim-lua/plenary.nvim {:module :plenary})
+
+(pack! :nanotech/jellybeans.vim {:event :VimEnter :config "require('nvrc.colors').apply()"})
+(pack! :feline-nvim/feline.nvim {:req :feline :after :jellybeans.vim})
+(pack! :lukas-reineke/indent-blankline.nvim {:event :BufRead :req :blankline})
+(pack! :NvChad/nvim-colorizer.lua {:event :BufRead})
+(pack! :nvim-treesitter/nvim-treesitter {:req :treesitter :defer :nvim-treesitter :run ":TSUpdate"})
+(pack! :lewis6991/gitsigns.nvim {:req :gitsigns :defer :gitsigns.nvim})
+(pack! :Pocco81/TrueZen.nvim {:cmd [:TZMinimalist :TZFocus :TZAtaraxis]})
+(pack! :stefandtw/quickfix-reflector.vim {:ft :qf})
+
+(pack! :neovim/nvim-lspconfig {:req :lspconfig :module :lspconfig :setup (fn []
+ ((. (require :nvrc.utils) :defer_unpack) :nvim-lspconfig 100)
+ (vim.defer_fn #(vim.cmd "if &ft == 'packer' | echo '' | else | silent! e %") 150))})
+(pack! :ray-x/lsp_signature.nvim {:req :lsp_signature :after :nvim-lspconfig})
+(pack! :hrsh7th/nvim-cmp {:req :cmp :event :InsertEnter})
+(pack! :hrsh7th/cmp-nvim-lsp {:after :nvim-cmp})
+
+(pack! :luukvbaal/stabilize.nvim {:after :jellybeans.vim :init :stabilize})
+(pack! :numToStr/Comment.nvim {:module :Comment :init :Comment})
+; TODO: https://github.com/kyazdani42/nvim-tree.lua/issues/951
+(pack! :kyazdani42/nvim-tree.lua {:req :nvimtree :cmd [:NvimTreeToggle :NvimTreeFocus] :commit "d8bf1ad"})
+(pack! :ggandor/lightspeed.nvim {:keys [:s :S :x :X :f :F]})
+(pack! :nvim-telescope/telescope.nvim {:req :telescope :module :telescope :cmd :Telescope})
+(pack! :boppyt/nvrc-extra)
+
+(pack! :bakpakin/fennel.vim {:ft :fennel})
+
+(unpack!)
diff --git a/fnl/nvrc/packs/blankline.fnl b/fnl/nvrc/packs/blankline.fnl
new file mode 100644
index 0000000..3139174
--- /dev/null
+++ b/fnl/nvrc/packs/blankline.fnl
@@ -0,0 +1,11 @@
+(local {: setup} (require :indent_blankline))
+
+(setup {:indentLine_enabled 1
+ :char "▏"
+ :filetype_exclude {:help :terminal
+ :packer :lspinfo
+ :TelescopePrompt :TelescopeResults
+ :lsp-installer ""}
+ :buftype_exclude {1 :terminal}
+ :show_trailing_blankline_indent false
+ :show_first_indent_level false})
diff --git a/fnl/nvrc/packs/cmp.fnl b/fnl/nvrc/packs/cmp.fnl
new file mode 100644
index 0000000..3b70af5
--- /dev/null
+++ b/fnl/nvrc/packs/cmp.fnl
@@ -0,0 +1,56 @@
+(import-macros {: set!} :nvrc.macro.opt)
+(local cmp (require :cmp))
+
+(set! completeopt "menuone,noselect")
+
+(local icons {:Text "(t)"
+ :Method "(m)"
+ :Function "(f)"
+ :Constructor "(cs)"
+ :Field "(s)"
+ :Variable "(v)"
+ :Class "(c)"
+ :Interface "(i)"
+ :Module "(m)"
+ :Property "(p)"
+ :Unit "(u)"
+ :Value "(v)"
+ :Enum "(e)"
+ :Keyword "(k)"
+ :Snippet "(sn)"
+ :Color "(co)"
+ :File "(fi)"
+ :Reference "(r)"
+ :Folder "(fl)"
+ :EnumMember "(em)"
+ :Constant "(cn)"
+ :Struct "(s)"
+ :Event "(ev)"
+ :Operator "(op)"
+ :TypeParameter "(tp)"})
+
+(cmp.setup {
+ :formatting {:format (fn [entry vim-item]
+ (set vim-item.kind
+ (string.format "%s %s"
+ (. icons vim-item.kind)
+ vim-item.kind))
+ (set vim-item.menu
+ (. {:nvim_lsp "[LSP]"}
+ entry.source.name))
+ vim-item)}
+ :mapping {:<C-p> (cmp.mapping.select_prev_item)
+ :<C-n> (cmp.mapping.select_next_item)
+ :<C-d> (cmp.mapping.scroll_docs (- 4))
+ :<C-f> (cmp.mapping.scroll_docs 4)
+ :<C-Space> (cmp.mapping.complete)
+ :<C-e> (cmp.mapping.close)
+ :<CR> (cmp.mapping.confirm {:behavior cmp.ConfirmBehavior.Replace
+ :select true})
+ :Tab (fn [fallback]
+ (if (cmp.visible) (cmp.select_next_item)"")
+ (fallback))
+ :<S-Tab> (fn [fallback]
+ (if (cmp.visible) (cmp.select_next_item)"")
+ (fallback))}
+ :sources {1 {:name :nvim_lsp}}})
diff --git a/fnl/nvrc/packs/feline.fnl b/fnl/nvrc/packs/feline.fnl
new file mode 100644
index 0000000..4953a7d
--- /dev/null
+++ b/fnl/nvrc/packs/feline.fnl
@@ -0,0 +1,144 @@
+(local feline (require :feline))
+(local lsp (require :feline.providers.lsp))
+(local lsp_severity vim.diagnostic.severity)
+(local vi_mode (require :feline.providers.vi_mode))
+(local git (require :feline.providers.git))
+
+(local colors (require :nvrc.colors))
+(local utils (require :nvrc.utils))
+
+(local vi_mode_colors {:NORMAL (. colors :green)
+ :INSERT (. colors :red)
+ :VISUAL (. colors :yellow)
+ :OP (. colors :green)
+ :BLOCK (. colors :skyblue)
+ :REPLACE (. colors :violet)
+ :V-REPLACE (. colors :violet)
+ :ENTER (. colors :skyblue)
+ :MORE (. colors :skyblue)
+ :SELECT (. colors :orange)
+ :COMMAND (. colors :green)
+ :SHELL (. colors :green)
+ :TERM (. colors :green)
+ :NONE (. colors :yellow)})