My Neovim configuration
local api = vim.api
local cmd = vim.cmd
local fn = vim.fn
local g = vim.g
local opt = vim.opt

--- Utility functions ---

echo = function(x)
  print(vim.inspect(x))
end

map = function(mode, lhs, rhs)
  api.nvim_set_keymap(mode, lhs, rhs, { noremap = true })
end

remap = function(mode, lhs, rhs)
  api.nvim_set_keymap(mode, lhs, rhs, {})
end

cmdmap = function(mode, lhs, rhs)
  map(mode, lhs, ("<cmd>%s<cr>"):format(rhs))
end

opmap = function(lhs, rhs)
  cmdmap("o", lhs, ("normal %s"):format(rhs))
end

unmap = api.nvim_del_keymap

buf_map = function(buf, mode, lhs, rhs)
  api.nvim_buf_set_keymap(buf, mode, lhs, rhs, { noremap = true })
end

buf_remap = function(buf, mode, lhs, rhs)
  api.nvim_buf_set_keymap(buf, mode, lhs, rhs, {})
end

buf_cmdmap = function(buf, mode, lhs, rhs)
  buf_map(buf, mode, lhs, ("<cmd>%s<cr>"):format(rhs))
end

buf_unmap = api.nvim_buf_del_keymap

--- Options ---

g.tex_flavor = "latex"
opt.autowriteall = true
opt.breakindent = true
opt.conceallevel = 2
opt.expandtab = true
opt.foldmethod = "marker"
opt.gdefault = true
opt.hlsearch = false
opt.joinspaces = false
opt.lazyredraw = true
opt.linebreak = true
opt.list = true
opt.listchars = { tab = "| ", trail = "", nbsp = "" }
opt.modeline = true
opt.number = true
opt.scrolloff = 999
opt.shiftwidth = 0
opt.shortmess = "aoOstTWAcF"
opt.showmode = false
opt.smartcase = true
opt.tabstop = 2
opt.termguicolors = true
opt.timeout = false
opt.undofile = true
opt.virtualedit = "block"

--- Mappings ---

cmdmap("n", ";", "w")
cmdmap("n", "<c-j>", "bnext")
cmdmap("n", "<c-k>", "bprevious")
cmdmap("n", "Q", "q")
cmdmap("n", "ZQ", "qa!")
cmdmap("n", "ZZ", "wqa")
cmdmap("n", "m,", "SidewaysLeft")
cmdmap("n", "m.", "SidewaysRight")
map("", "<c-v>", "v")
map("", "<m-h>", "<c-w>h")
map("", "<m-j>", "<c-w>j")
map("", "<m-k>", "<c-w>k")
map("", "<m-l>", "<c-w>l")
map("", "<space>", ":")
map("", "H", "^")
map("", "L", "$")
map("", "v", "<c-v>")
map("n", ",", "")
map("n", "-u", "yypVr-")
map("n", "=u", "yypVr=")
map("n", "_", "Vip:sort<cr>")
map("n", "gb", "<cmd>ls<cr>:b ")
map("n", "gm", "m")
map("n", "~", "g~l")
map("t", "<esc>", "<c-\\><c-n>")
map("x", "_", ":sort<cr>")
opmap("ii", "[%V]%")
remap("", "[[", "[s[")
remap("", "]]", "]s]")
remap("n", "M", "m$")
remap("n", "SW", "SaW")
remap("n", "Sp", "Sap")
remap("n", "Sw", "Saw")
remap("n", "cW", "ciW")
remap("n", "cp", "cip")
remap("n", "cw", "ciw")
remap("n", "dW", "daW")
remap("n", "dp", "dap")
remap("n", "dw", "daw")
remap("n", "mW", "maW")
remap("n", "mp", "map")
remap("n", "mw", "maw")
remap("x", "ii", "[%o]%")

--- Miscellaneous ---

cmd [[
  highlight conceal NONE
  autocmd BufReadPost * if line("'\"") >= 1 && line("'\"") <= line("$") | exe "normal! g`\"" | endif
  autocmd TextYankPost * silent! lua vim.highlight.on_yank()
]]

--- Plugins ---

require "paq" {
  -- Package manager --
  "savq/paq-nvim",
  -- Dependencies --
  "nvim-lua/plenary.nvim",
  -- Language support --
  "xigoi/vim-arturo",
  "alvan/vim-closetag",
  "pangloss/vim-javascript",
  "heavenshell/vim-jsdoc",
  "Julian/lean.nvim",
  "neovim/nvim-lspconfig",
  "alaviss/nim.nvim",
  "jose-elias-alvarez/null-ls.nvim",
  "sheerun/vim-polyglot",
  "nvim-treesitter/nvim-treesitter",
  "lervag/vimtex",
  -- Mappings --
  "svermeulen/vim-easyclip",
  "tommcdo/vim-exchange",
  "jeetsukumaran/vim-indentwise",
  "tpope/vim-repeat",
  "andrewradev/sideways.vim",
  "wellle/targets.vim",
  "tpope/vim-unimpaired",
  -- Utility --
  "norcalli/nvim-colorizer.lua",
  "lewis6991/gitsigns.nvim",
  "thinca/vim-localrc",
  "echasnovski/mini.nvim",
  "pbrisbin/vim-mkdir",
  "dcampos/nvim-snippy",
  -- Aesthetic --
  "lukas-reineke/indent-blankline.nvim",
  "kyazdani42/nvim-web-devicons",
  -- Collaboration --
  "editorconfig/editorconfig-vim",
  "jbyuki/instant.nvim",
  -- Startup --
  "lewis6991/impatient.nvim",
  -- Brower integration --
  {
    "glacambre/firenvim",
    run = function()
      return fn["firenvim#install"](0)
    end,
  },
}

-- impatient --
require "impatient"

-- colorizer --
require("colorizer").setup {
  ["*"] = { css = true },
}

-- gitsigns --
require("gitsigns").setup {
  signs = {
    add = { text = "+" },
    change = { text = "~" },
  },
}

-- indent-blankline --
cmd [[
  highlight IndentBlanklineIndent1 guifg=#880000 gui=nocombine
  highlight IndentBlanklineIndent2 guifg=#444400 gui=nocombine
  highlight IndentBlanklineIndent3 guifg=#005500 gui=nocombine
  highlight IndentBlanklineIndent4 guifg=#004444 gui=nocombine
  highlight IndentBlanklineIndent5 guifg=#0000aa gui=nocombine
  highlight IndentBlanklineIndent6 guifg=#440044 gui=nocombine
]]
require("indent_blankline").setup {
  char_highlight_list = {
    "IndentBlanklineIndent1",
    "IndentBlanklineIndent2",
    "IndentBlanklineIndent3",
    "IndentBlanklineIndent4",
    "IndentBlanklineIndent5",
    "IndentBlanklineIndent6",
  },
}

-- lspconfig --
local lsp_on_attach = function(before)
  return function(client, buf)
    if before then
      before(client, buf)
    end
    buf_cmdmap(buf, "n", "+", "lua vim.lsp.buf.code_action()")
    buf_cmdmap(buf, "n", "K", "lua vim.lsp.buf.hover()")
    buf_cmdmap(buf, "n", "[d", "lua vim.lsp.diagnostic.goto_prev()")
    buf_cmdmap(buf, "n", "]d", "lua vim.lsp.diagnostic.goto_next()")
    buf_cmdmap(buf, "n", "cm", "lua vim.lsp.buf.rename()")
    buf_cmdmap(buf, "n", "gl", "lua vim.lsp.diagnostic.show_line_diagnostics()")
    buf_cmdmap(buf, "n", "gq", "lua vim.lsp.buf.formatting()")
    if client.resolved_capabilities.goto_definition then
      buf_cmdmap(buf, "n", "gD", "lua vim.lsp.buf.declaration()")
      buf_cmdmap(buf, "n", "gd", "lua vim.lsp.buf.definition()")
    end
    if client.resolved_capabilities.document_formatting then
      cmd "autocmd BufWritePre <buffer> lua vim.lsp.buf.formatting_sync()"
    end
  end
end
local lspconfig = require "lspconfig"
-- pipx install 'python-lsp-server[all]'
lspconfig.pylsp.setup {
  on_attach = lsp_on_attach(function(client)
    client.resolved_capabilities.document_formatting = false
    client.resolved_capabilities.document_range_formatting = false
  end),
}
-- npm install -g typescript typescript-language-server
lspconfig.tsserver.setup {
  on_attach = lsp_on_attach(function(client)
    client.resolved_capabilities.document_formatting = false
    client.resolved_capabilities.document_range_formatting = false
  end),
}

-- null-ls --
local null_ls = require "null-ls"
null_ls.setup {
  on_attach = lsp_on_attach(),
  sources = {
    null_ls.builtins.code_actions.gitsigns,
    null_ls.builtins.code_actions.proselint,
    null_ls.builtins.diagnostics.chktex,
    null_ls.builtins.diagnostics.cppcheck,
    null_ls.builtins.formatting.black,
    -- npm install -g @fsouza/prettierd
    null_ls.builtins.formatting.prettierd,
    null_ls.builtins.formatting.reorder_python_imports,
    null_ls.builtins.formatting.stylua,
    require "null-sources/nimcheck",
    require "null-sources/nim-nvim",
  },
}

-- lean --
require("lean").setup {
  abbreviations = { builtin = true },
  lsp = { on_attach = lsp_on_attach },
  lsp3 = { on_attach = lsp_on_attach },
  mappings = true,
}

-- mini --
require("mini.base16").setup {
  palette = {
    base00 = "#000000",
    base01 = "#111111",
    base02 = "#333333",
    base03 = "#bbbbbb",
    base04 = "#dddddd",
    base05 = "#ffffff",
    base06 = "#ffffff",
    base07 = "#ffffff",
    base09 = "#ff2222",
    base08 = "#ff9922",
    base0A = "#ff22ff",
    base0B = "#22ff22",
    base0C = "#4444ff",
    base0D = "#22ffff",
    base0E = "#ffff22",
    base0F = "#999999",
  },
  use_cterm = false,
}
require("mini.comment").setup {}
-- require("mini.completion").setup {}
require("mini.jump").setup {
  mappings = {
    repeat_jump = "",
  },
  highlight_delay = 0,
}
require("mini.pairs").setup { fly_mode = true }
require("mini.sessions").setup {
  directory = fn.stdpath "config" .. "/sessions",
}
require("mini.starter").setup {
  evaluate_single = true,
}
require("mini.statusline").setup {}
require("mini.surround").setup {
  n_lines = 100,
  mappings = {
    add = "S",
    delete = "ds",
    find_left = "[s",
    find = "]s",
    highlight = "",
    replace = "cs",
    update_n_lines = "",
  },
}
require("mini.tabline").setup {}

-- snippy --
require("snippy").setup {}
cmd [[
  imap <expr> <tab> snippy#can_expand() ? '<Plug>(snippy-expand)' : '<tab>'
  imap <expr> <m-j> snippy#can_jump(1) ? '<Plug>(snippy-next)' : '<nop>'
  imap <expr> <m-k> snippy#can_jump(-1) ? '<Plug>(snippy-previous)' : '<nop>'
  smap <expr> <m-j> snippy#can_jump(1) ? '<Plug>(snippy-next)' : '<nop>'
  smap <expr> <m-k> snippy#can_jump(-1) ? '<Plug>(snippy-previous)' : '<nop>'
]]

-- treesitter --
require("nvim-treesitter.configs").setup {
  ensure_installed = "maintained",
  highlight = { enable = true },
  incremental_selection = {
    enable = true,
    keymaps = {
      init_selection = "<m-n>",
      node_incremental = "<m-n>",
      scope_incremental = "<m-b>",
      node_decremental = "<m-m>",
    },
  },
}

-- vimscript plugins --
g.EasyClipAlwaysMoveCursorToEndOfPaste = true
g.EasyClipPreserveCursorPositionAfterYank = true
g.EasyClipShareYanks = true
g.instant_username = "xigoi"
g.localrc_filename = ".xigoi.vim"
g.localrc_filetype = ".xigoi.%s.vim"
g.polyglot_disabled = {
  "html",
  "javascript",
}