This repository has been archived on 2024-10-28. You can view files and clone it, but cannot push or open issues or pull requests.
nvim-config/init.fnl

532 lines
22 KiB
Fennel

;;; init.fnl - primary init file
;; Initialize global `zander' prefix
(set _G.zander {})
;; Helpful keymaping functions
(macro bind! [mode 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))
`(vim.keymap.set ,mode ,key ,cmd ,opts)))
;; Better autocommands
(macro 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 "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 })))
;; Make space leader
(set vim.g.mapleader " ")
(bind! :n :<space> :<nop>)
;; Enable lua filetype
(set vim.g.do_filetype_lua true)
;; Some options
; Make the mouse work
(set vim.opt.mouse :a)
(set vim.opt.mousemodel :extend)
; Ignore case when a query is all lower case
(set vim.opt.ignorecase true)
(set vim.opt.smartcase true)
; Enable line numbering
(set vim.opt.number true)
; Make <tab> insert 4 spaces
(set vim.opt.expandtab true)
(set vim.opt.tabstop 4)
(set vim.opt.shiftwidth 4)
(set vim.opt.shiftround true)
; Auto-indent
(set vim.opt.autoindent true)
(set vim.opt.smartindent true)
; Give context while scrolling
(set vim.opt.scrolloff 4)
(set vim.opt.sidescrolloff 8)
; Make splitting better
(set vim.opt.splitbelow true)
(set vim.opt.splitright true)
; 24 bit color support
(set vim.opt.termguicolors true)
; Shell like completions
(set vim.opt.wildmode [ :list :longest ])
; Set completion options
(set vim.opt.completeopt [ :menu :menuone :noselect ])
; Make buffers hide when abandoned
(set vim.opt.hidden true)
; Save undo data
(set vim.opt.undofile true)
; Text width
(set vim.opt.textwidth 80)
; Spell options
(set vim.opt.spelllang :en_us)
(set vim.opt.spelloptions :camel)
; Allow more freedom with the cursor
(set vim.opt.virtualedit :block)
;; Disable netrw
(set vim.g.loaded_netrw 1)
(set vim.g.loaded_netrwPlugin 1)
;; Remove trailing whitespace
(fn remove_trailing_whitespace []
"Remove trailing whitespace from the whole file."
(let [res (pcall vim.cmd "%s/ \\+$//gc")]
(vim.cmd.nohlsearch)
(when (not res)
(print "File is clean"))))
(vim.api.nvim_create_user_command :RemoveTrailingWhitespace
remove_trailing_whitespace {})
(bind! :n :<leader>ws remove_trailing_whitespace)
;; Spell keybindings
(bind! :n :<leader>l (fn []
(let [new_spell (not (vim.opt_local.spell:get))]
(set vim.opt_local.spell new_spell)
(print (if new_spell
"Enabled Spellcheck"
"Disabled Spellcheck")))))
(fn jump_or_open_terminal []
"If no terminal buffer exists, create one. Otherwise, open new one."
(var term_count 0)
(var last_id 0)
(var terms [ ])
(each [_ id (pairs (vim.api.nvim_list_bufs))]
(let [name (vim.api.nvim_buf_get_name id)]
(when (vim.startswith name "term://")
(table.insert terms name)
(set term_count (+ term_count 1))
(set last_id id))))
(if (= term_count 0)
(vim.cmd.terminal)
(= term_count 1)
(vim.cmd.buffer last_id)
(vim.ui.select terms
{ :prompt "Terminal Buffers" }
(fn [choice]
(when choice
(vim.cmd.buffer choice))))))
(bind! :n :<leader>t jump_or_open_terminal)
;; Some keybindings for diagnostics
(bind! :n :<leader>e vim.diagnostic.open_float)
(bind! :n "[d" vim.diagnostic.goto_prev)
(bind! :n "]d" vim.diagnostic.goto_next)
(bind! :n :<leader>q vim.diagnostic.setloclist)
;; Some filetype settings
(vim.filetype.add { :filename {
".latexmkrc" :perl
"Jenkinsfile" :groovy }
:extensions {
"nasm" :nasm
"h" :c
"ui" :xml }})
;; Plugins (with packer.nvim)
(fn packer_init_callback [use]
;; Nicer macro for use
(macro use! [repo ...]
(local output [ repo ])
(var last_key nil)
(each [_ val (ipairs [...])]
(if last_key
(do (tset output last_key val)
(set last_key nil))
(set last_key val)))
`(use ,output))
;; Can be passed to :config of `use!'
;; to call a plugin's `setup' function
(macro 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)))
(let [req_var (gensym)]
`((. (require ,pkg) :setup) ,output)))
;; Packer
(use! :wbthomason/packer.nvim)
;; tangerine.nvim (auto fennel compile)
(use! :udayvir-singh/tangerine.nvim)
;; Treesitter
(use! :nvim-treesitter/nvim-treesitter
:config #(setup! "nvim-treesitter.configs"
:ensure_installed :all
:sync_install false
:auto_install true
:highlight { :enable true
:additional_vim_regex_highlighting false }
:indent { :enable true }))
;; nightfox.nvim (colorscheme)
(use! :EdenEast/nightfox.nvim
:after :nvim-treesitter
:config #(vim.cmd.colorscheme :carbonfox))
;; Devicons
(use! :kyazdani42/nvim-web-devicons)
;; lualine.nvim
(use! :nvim-lualine/lualine.nvim
:after [ :nightfox.nvim :nvim-web-devicons ]
:config #(setup! :lualine
:options { :section_separators ""
:component_separators "│" }
:sections { :lualine_x [
{ 1 #(.. "recording @" (vim.fn.reg_recording))
:cond #(not= (# (vim.fn.reg_recording)) 0) }
:encoding
:fileformat
:filetype ]}))
;; bufferline.nvim
(use! :akinsho/bufferline.nvim
:after [ :nvim-web-devicons :nightfox.nvim ]
:config #(setup! :bufferline
:options {
:always_show_bufferline false
:mode :tabs
:numbers :buffer-id
:show_buffer_close_icons false
:show_close_icon false }))
;; noice.nvim (ui overhaul)
(use! :folke/noice.nvim
:requires :MunifTanjim/nui.nvim
:config #(setup!
:noice
:lsp {
:override {
"vim.lsp.util.convert_input_to_markdown_lines" true
"vim.lsp.util.stylize_markdown" true
"cmp.entry.get_documentation" true }}
:presets {
:bottom_search true
:command_palette false
:long_message_to_split true
:inc_rename false
:lsp_doc_border false }
:cmdline {
:view :cmdline }))
;; dressing.nvim (better prmpts)
(use! :stevearc/dressing.nvim
:after :telescope.nvim
:config #(setup! :dressing
:input { :insert_only true }))
;; Telescope
(use! :nvim-telescope/telescope.nvim
:requires :nvim-lua/plenary.nvim
:after :noice.nvim
:config (fn []
(setup! :telescope
:defaults {
:mappings {
:i {
:<esc> :close
:<C-j> :move_selection_next
:<C-k> :move_selection_previous }
:n {
:<C-j> :move_selection_next
:<C-k> :move_selection_previous }}}
:pickers {
:buffers {
:sort_lastused true }}
:extensions {
:fzf {
:fuzzy true
:override_generic_sorter true
:override_file_sorter true
:case_mode :smart_case }})
(let [builtin (require :telescope.builtin)]
(bind! :n :<leader>fq builtin.quickfix)
(bind! :n :<leader>fr builtin.registers)
(bind! :n :<leader>fj builtin.jumplist)
(bind! :n :<leader>fa builtin.marks)
(bind! :n :<leader>fh builtin.help_tags)
(bind! :n :<leader>g builtin.live_grep)
(bind! :n :<leader>fg builtin.live_grep)
(bind! :n :<leader>G builtin.grep_string)
(bind! :n :<leader>fG builtin.grep_string)
(bind! :n :<leader>b builtin.buffers)
(bind! :n :gb builtin.buffers)
(bind! :n :<leader>fu builtin.git_status)
(bind! :n :<leader>fm builtin.man_pages)
(bind! :n :<leader>fe builtin.diagnostics)
(bind! :n :<leader>fp builtin.spell_suggest)
(bind! :n :<leader>i builtin.find_files)
(bind! :n :z= builtin.spell_suggest)
(bind! :n :<leader>ff (fn []
(let [code (os.execute "git rev-parse --is-inside-work-tree >/dev/null 2>&1")]
(if (= code 0)
(builtin.git_files)
(builtin.find_files))))))
((. (require :telescope) :load_extension) :noice)))
;; Telescope fzf
(use! :nvim-telescope/telescope-fzf-native.nvim
:after :telescope.nvim
:run "make"
:config #((. (require :telescope) :load_extension) :fzf))
;; Nvim surround
(use! :kylechui/nvim-surround
:config #(setup! :nvim-surround))
;; Leap
(use! :ggandor/leap.nvim
:after :nvim-treesitter
:config (fn []
((. (require :leap) :add_default_mappings))
(bind! :o :z "<plug>(leap-forward-to)")
(bind! :o :Z "<plug>(leap-backward-to)")
(vim.api.nvim_set_hl 0 :LeapBackdrop { :link :Comment })))
;; Leap spooky (remote operations)
(use! :ggandor/leap-spooky.nvim
:after :leap.nvim
:config #(setup! :leap-spooky))
;; Flit (leap for 'till' and 'forward' motions)
(use! :ggandor/flit.nvim
:after :leap.nvim
:config #(setup! :flit))
;; Comment.nvim
(use! :numToStr/Comment.nvim
:config #(setup! :Comment))
;; nvim-find-other
(use! "https://git.zander.im/Zander671/nvim-find-other.git"
:config (fn [] (setup! :nvim-find-other
:c [ "h" "H" ]
:h [ "c" "C" "cpp" "cxx" "c++" "cc" ]
:cpp [ "hpp" "hxx" "h++" "hh" "h" "H" ]
:hpp [ "cpp" "cxx" "c++" "cc" ])
(let [find_other (require :nvim-find-other)]
(vim.api.nvim_create_user_command
"FindOtherFile"
find_other.find_other_current_buffer
{})
(bind! :n :go find_other.find_other_current_buffer))))
(use! :RRethy/vim-illuminate
:config (fn []
((. (require :illuminate) :configure) { :providers [
"lsp"
"treesitter"
"ragex" ]
:modes_denylist [
:markdown
:text
:gitconfig
:gitignore ]
:delay 0 }
(hook! :FileType :lua #(vim.api.nvim_set_hl 0
:IlluminatedWordText
{})))))
;; Conjure (better lisp support)
(use! :Olical/conjure
:config
#(tset vim.g :conjure#filetype#fennel "conjure.client.fennel.stdio"))
;; Snippy
(use! :dcampos/nvim-snippy
:config #(let [map (require :snippy.mapping)]
(bind! [ :i :s ] :<tab> ((. map :next) :<tab>))
(bind! [ :i :s ] :<s-tab> (map.previous :<tab>))))
;; nvim-cmp (autocomplete)
(use! :hrsh7th/nvim-cmp
:requires [ :hrsh7th/cmp-buffer
:hrsh7th/cmp-path
:hrsh7th/cmp-cmdline
:hrsh7th/cmp-nvim-lsp
:PaterJason/cmp-conjure
:dcampos/cmp-snippy ]
:config #(let [cmp (require :cmp)
compare (require :cmp.config.compare)]
(cmp.setup
{ :snippet {
:expand #((. (require :snippy) :expand_snippet) $1.body) }
:mapping {
:<C-b> (cmp.mapping (cmp.mapping.scroll_docs -4)
[ :i :c ])
:<C-f> (cmp.mapping (cmp.mapping.scroll_docs 4)
[ :i :c ])
:<C-space> (cmp.mapping (cmp.mapping.complete)
[ :i :c ])
:<C-e> (cmp.mapping (cmp.mapping.abort)
[ :i :c ])
:<CR> (cmp.mapping
(cmp.mapping.confirm { :select false })
[ :i :c ])
:<C-j> (cmp.mapping
(cmp.mapping.select_next_item
{ :behavior cmp.SelectBehavior.Select })
[ :i :c ])
:<C-k> (cmp.mapping
(cmp.mapping.select_prev_item
{ :behavior cmp.SelectBehavior.Select })
[ :i :c ])
:<C-n> (cmp.mapping
(cmp.mapping.select_next_item
{ :behavior cmp.SelectBehavior.Select })
[ :i :c ])
:<C-p> (cmp.mapping
(cmp.mapping.select_prev_item
{ :behavior cmp.SelectBehavior.Select })
[ :i :c ])
:<down> (cmp.mapping
(cmp.mapping.select_next_item
{ :behavior cmp.SelectBehavior.Select })
[ :i :c ])
:<up> (cmp.mapping
(cmp.mapping.select_prev_item
{ :behavior cmp.SelectBehavior.Select })
[ :i :c ]) }
:sources (cmp.config.sources
[{ :name "nvim_lsp" :priority 2 }
{ :name "conjure" :priority 2 }
{ :name "snippy" :priority 1 }
{ :name "buffer" :priority 0 }
{ :name "path" :priority 0 }])
:sorting {
:priority_weight 2
:comparators [
compare.score
compare.locality
compare.recently_used
compare.offset
compare.order
; compare.scopes
; compare.exact
; compare.sort_text
; compare.kind
; compare.length
]}})
(cmp.setup.cmdline "/"
{ :mapping (cmp.mapping.preset.cmdline)
:sources (cmp.config.sources
[{ :name "buffer" }])})
(cmp.setup.cmdline ":"
{ :mapping (cmp.mapping.preset.cmdline)
:sources (cmp.config.sources
[{ :name "cmdline" }
{ :name "path" }])})))
;; lspconfig
(fn lsp_config_callback []
(fn _G.zander.lsp_on_attach [_ buf]
(bind! :n :gD vim.lsp.buf.declaration buf)
(bind! :n :gd vim.lsp.buf.definition buf)
(bind! :n :K vim.lsp.buf.hover buf)
(bind! :n :gI vim.lsp.buf.implementation buf)
(bind! :n :<C-k> vim.lsp.buf.signature_help buf)
(bind! :n :<leader>wa vim.lsp.buf.add_workspace_folder buf)
(bind! :n :<leader>wr vim.lsp.buf.remove_workspace_folder buf)
(bind! :n :<leader>wl #(print (vim.inspect
(vim.lsp.buf.list_workspace_folders))) buf)
(bind! :n :<leader>D vim.lsp.buf.type_definition buf)
(bind! :n :<leader>rn vim.lsp.buf.rename buf)
(bind! :n :<leader>cn vim.lsp.buf.code_action buf)
; (bind! :n :gr vim.lsp.buf.references buf)
(bind! :n :<leader>o #(vim.lsp.buf.format { :async true }) buf)
;; Some telescope commands
(let [builtin (require :telescope.builtin)]
(bind! :n :gr builtin.lsp_references buf)
(bind! :n :<leader>s builtin.lsp_dynamic_workspace_symbols buf)
(bind! :n :<leader>fs builtin.lsp_dynamic_workspace_symbols buf)
(bind! :n :<leader>fS builtin.lsp_workspace_symbols buf)
(bind! :n :<leader>d builtin.lsp_document_symbols buf)
(bind! :n :<leader>fd builtin.lsp_document_symbols buf)))
(fn _G.zander.lsp_get_data_dir [server root]
(let [resolved_path (vim.fn.resolve root)
joined_path (vim.fn.substitute resolved_path "\\/" "@" :g)]
(.. (vim.fn.fnamemodify (.. "~/.local/nvim/lsp-cache/"
server
"/")
":p") joined_path)))
(let [lsp (require :lspconfig)
lsp_cap ((. (require :cmp_nvim_lsp) :default_capabilities))]
(macro setup_server! [name ...]
(let [opts { :on_attach `_G.zander.lsp_on_attach
:capabilities `lsp_cap }]
(var last_key nil)
(each [_ val (ipairs [...])]
(if last_key
(do (tset opts last_key val)
(set last_key nil))
(set last_key val)))
`((. (. lsp ,name) :setup) ,opts)))
(setup_server! :ccls)
(setup_server! :cmake)
(setup_server! :gopls)
(setup_server! :rust_analyzer)
(setup_server! :texlab)
(setup_server! :sumneko_lua
:settings {
:Lua {
:runtime {
:version "LuaJIT" }
:diagnostics {
:globals [ "vim" ] }
:workspace {
:checkThirdParty false
:library (vim.api.nvim_get_runtime_file "" true) }
:telemetry {
:enable false }}})))
(use! :neovim/nvim-lspconfig
:after :cmp-nvim-lsp
:config lsp_config_callback)
(fn jdtls_config_callback []
(hook! :FileType :java
#(let [root_dir ((. (require :jdtls.setup) :find_root)
[ ".git" "mvnw" "gradlew" "build.gradle" ])
lsp_cap ((. (require :cmp_nvim_lsp) :default_capabilities))]
((. (require :jdtls) :start_or_attach)
{ :capabilities lsp_cap
:on_attach _G.zander.lsp_on_attach
:root_dir root_dir
:cmd [ "jdtls"
"-data"
(_G.zander.lsp_get_data_dir
:jdtls root_dir) ]}))))
(use! :mfussenegger/nvim-jdtls
:after :nvim-lspconfig
:config jdtls_config_callback))
(vim.cmd.packadd "packer.nvim")
(let [packer (require :packer)]
(packer.startup packer_init_callback))