Jelajahi Sumber

feat(neovim): add `nvim` config

Joe 1 tahun lalu
induk
melakukan
472f02bd28
48 mengubah file dengan 2686 tambahan dan 0 penghapusan
  1. 1 0
      .config/.gitignore
  2. 1 0
      .config/git/ignore
  3. 8 0
      .config/nvim/.gitignore
  4. 119 0
      .config/nvim/custom/bit-browser/lua/bit-browser/init.lua
  5. 148 0
      .config/nvim/custom/command-palette/lua/command-palette/init.lua
  6. 9 0
      .config/nvim/custom/jonathandarker/.gitignore
  7. 2 0
      .config/nvim/custom/jonathandarker/colors/jonathandarker.vim
  8. 184 0
      .config/nvim/custom/jonathandarker/lua/jonathandarker/colors/default.lua
  9. 7 0
      .config/nvim/custom/jonathandarker/lua/jonathandarker/colors/lsp/default.lua
  10. 5 0
      .config/nvim/custom/jonathandarker/lua/jonathandarker/colors/lsp/init.lua
  11. 7 0
      .config/nvim/custom/jonathandarker/lua/jonathandarker/colors/plugins/gitsigns.lua
  12. 14 0
      .config/nvim/custom/jonathandarker/lua/jonathandarker/colors/plugins/init.lua
  13. 7 0
      .config/nvim/custom/jonathandarker/lua/jonathandarker/colors/plugins/nvim-treesitter-context.lua
  14. 45 0
      .config/nvim/custom/jonathandarker/lua/jonathandarker/colors/plugins/status-beast.lua
  15. 7 0
      .config/nvim/custom/jonathandarker/lua/jonathandarker/colors/plugins/telescope-nvim.lua
  16. 1 0
      .config/nvim/custom/jonathandarker/lua/jonathandarker/colors/plugins/vim-floaterm.lua
  17. 55 0
      .config/nvim/custom/jonathandarker/lua/jonathandarker/colors/treesitter/default.lua
  18. 6 0
      .config/nvim/custom/jonathandarker/lua/jonathandarker/colors/treesitter/init.lua
  19. 6 0
      .config/nvim/custom/jonathandarker/lua/jonathandarker/colors/treesitter/languages/python.lua
  20. 12 0
      .config/nvim/custom/jonathandarker/lua/jonathandarker/init.lua
  21. 58 0
      .config/nvim/custom/jonathandarker/lua/jonathandarker/palette.lua
  22. 103 0
      .config/nvim/custom/jxdash/lua/jxdash/init.lua
  23. 19 0
      .config/nvim/custom/proj-conf/lua/proj-conf/health.lua
  24. 85 0
      .config/nvim/custom/proj-conf/lua/proj-conf/init.lua
  25. 20 0
      .config/nvim/custom/proj-conf/lua/proj-conf/lint/init.lua
  26. 190 0
      .config/nvim/custom/proj-conf/lua/proj-conf/lsp/init.lua
  27. 13 0
      .config/nvim/custom/proj-conf/lua/proj-conf/projects/deno_typescript_monorepo.lua
  28. 45 0
      .config/nvim/custom/proj-conf/lua/proj-conf/projects/ruff_pyright.lua
  29. 6 0
      .config/nvim/custom/proj-conf/lua/proj-conf/save-formatter.lua
  30. 144 0
      .config/nvim/custom/save-formatter/lua/save-formatter/init.lua
  31. 30 0
      .config/nvim/custom/status-beast/lua/status-beast/highlights.lua
  32. 272 0
      .config/nvim/custom/status-beast/lua/status-beast/init.lua
  33. 214 0
      .config/nvim/custom/status-beast/lua/status-beast/maps.lua
  34. 111 0
      .config/nvim/init.lua
  35. 114 0
      .config/nvim/lua/plugins/command-palette.lua
  36. 56 0
      .config/nvim/lua/plugins/completion.lua
  37. 80 0
      .config/nvim/lua/plugins/floatingterminal.lua
  38. 101 0
      .config/nvim/lua/plugins/git.lua
  39. 7 0
      .config/nvim/lua/plugins/lint.lua
  40. 45 0
      .config/nvim/lua/plugins/lsp.lua
  41. 10 0
      .config/nvim/lua/plugins/proj-conf.lua
  42. 5 0
      .config/nvim/lua/plugins/spell.lua
  43. 93 0
      .config/nvim/lua/plugins/style.lua
  44. 83 0
      .config/nvim/lua/plugins/telescope.lua
  45. 75 0
      .config/nvim/lua/plugins/text-objects.lua
  46. 47 0
      .config/nvim/lua/plugins/treesitter.lua
  47. 11 0
      .config/zsh/.zshrc
  48. 5 0
      .github/README.md

+ 1 - 0
.config/.gitignore

@@ -8,6 +8,7 @@
 !jonathandarker/
 !lazydocker/
 !lazygit/
+!nvim/
 !prettier/
 !skhd/
 !surfingkeys/

+ 1 - 0
.config/git/ignore

@@ -6,6 +6,7 @@
 ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ###
 
 # Repository configurations
+.proj-conf.neovim
 .git-blame-ignore-revs
 
 # Private

+ 8 - 0
.config/nvim/.gitignore

@@ -0,0 +1,8 @@
+# ignore everything...
+*
+!.gitignore
+# except directories...
+!*/
+# ...and these:
+!**/*.lua
+!**/*.vim

+ 119 - 0
.config/nvim/custom/bit-browser/lua/bit-browser/init.lua

@@ -0,0 +1,119 @@
+local pickers = require("telescope.pickers")
+local actions = require("telescope.actions")
+local action_state = require("telescope.actions.state")
+local finders = require("telescope.finders")
+local conf = require("telescope.config").values
+local entry_display = require("telescope.pickers.entry_display")
+
+-- Utility function: navigate diagnostics
+local diagnostic = function(next, severity)
+    local opts = {}
+    if severity then opts.severity = { min = severity } end
+    if next then
+        return vim.diagnostic.goto_next(opts)
+    else
+        return vim.diagnostic.goto_prev(opts)
+    end
+end
+
+-- Utility function: navigate git hunks (if gitsigns is installed)
+local githunk
+local gitsigns
+if pcall(require, "gitsigns") then
+    gitsigns = require("gitsigns")
+    githunk = function(next)
+        if (next) then
+            gitsigns.next_hunk()
+        else
+            gitsigns.prev_hunk()
+        end
+        vim.defer_fn(function()
+            vim.schedule(function() gitsigns.preview_hunk_inline() end)
+        end, 100)
+    end
+else
+    githunk = function(_) end
+end
+
+local targets = {
+    {
+        "Error", "Any error diagnostic in the current buffer",
+        function() diagnostic(true, vim.diagnostic.severity.ERROR) end,
+        function() diagnostic(false, vim.diagnostic.severity.ERROR) end
+    }, {
+    "Warn", "Any warn or error diagnostic in the current buffer",
+    function() diagnostic(true, vim.diagnostic.severity.WARN) end,
+    function() diagnostic(false, vim.diagnostic.severity.WARN) end
+}, {
+    "Info", "Any info, warn, or error diagnostic in the current buffer",
+    function() diagnostic(true, vim.diagnostic.severity.INFO) end,
+    function() diagnostic(false, vim.diagnostic.severity.INFO) end
+}, {
+    "Diagnostic",
+    "Any diagnostic in the current buffer, regardless of severity",
+    function() diagnostic(true) end, function() diagnostic(false) end
+}, {
+    "Search", "The last search made with /",
+    function()
+        vim.fn.search(vim.fn.getreginfo("/")["regcontents"][1])
+    end,
+    function()
+        vim.fn.search(vim.fn.getreginfo("/")["regcontents"][1], "b")
+    end
+}, {
+    "Git", "Next diff hunk in current buffer", function()
+    githunk(true)
+end, function() githunk(false) end
+}
+}
+local target = targets[4]
+
+local set_target = function(index) target = targets[index] end
+
+local open_picker
+open_picker = function(opts)
+    pickers.new(opts, {
+        prompt_title = "Bit-Browse Target",
+        finder = finders.new_table({
+            results = targets,
+            entry_maker = function(entry)
+                local displayer = entry_display.create({
+                    separator = " ▏",
+                    items = { { width = 32 }, { remaining = true } }
+                })
+                return {
+                    value = entry,
+                    display = function()
+                        return displayer({ { entry[1] }, { entry[2] } })
+                    end,
+                    ordinal = string.format("%s %s", entry[1], entry[2])
+                }
+            end
+        }),
+        sorter = conf.generic_sorter(),
+        attach_mappings = function(prompt_bufnr, _)
+            actions.select_default:replace(function()
+                actions.close(prompt_bufnr)
+                target = action_state.get_selected_entry().value
+            end)
+            return true
+        end
+    }):find()
+end
+
+local function add_item() end
+
+local function next_item() target[3]() end
+
+local function prev_item() target[4]() end
+
+local function get_target() return target[1] end
+
+return {
+    open = open_picker,
+    add = add_item,
+    next = next_item,
+    prev = prev_item,
+    set_target = set_target,
+    get_target = get_target
+}

+ 148 - 0
.config/nvim/custom/command-palette/lua/command-palette/init.lua

@@ -0,0 +1,148 @@
+-- === === === === === === == Fuzzy Command Lists == === === === === === === ===
+--
+-- A tiny custom picker for running misc. commands with the help of `telescope`.
+--
+-- Supports commands (consisting of titles, help text, and commands), and groups
+-- of commands (consisting of a title, description, and a nested subgroup).
+--
+-- Strongly inspired by: LinArcX/telescope-command-palette.nvim
+--
+-- === === === === ==== ==== === === === ===
+-- You can define the command palette here directly, or you can require this
+-- module and call `.add` instead.
+local palette = {}
+
+-- Since this depends on `telescope`, the bindings should only be set from
+-- `telescope`'s setup call
+local pickers = require("telescope.pickers")
+local themes = require("telescope.themes")
+local actions = require("telescope.actions")
+local action_state = require("telescope.actions.state")
+local finders = require("telescope.finders")
+local conf = require("telescope.config").values
+local entry_display = require("telescope.pickers.entry_display")
+
+local fn_as_str = function(item)
+    if type(item) == "function" then return item() end
+    return item
+end
+
+local open_palette
+open_palette = function(opts, name, table)
+    opts = opts or {}
+    name = name or "Command Palette"
+    table = table or palette
+    local name_width = 32
+    local desc_width = 64
+    for _, value in pairs(table) do
+        if fn_as_str(value[1]) ~= nil then
+            name_width = math.min(32, math.max(name_width,
+                string.len(fn_as_str(value[1]))))
+            desc_width = math.min(64, math.max(desc_width,
+                string.len(fn_as_str(value[2]))))
+        end
+    end
+    local has_descriptions = false;
+    for _, value in pairs(table) do
+        if string.len(fn_as_str(value[2])) > 0 then
+            has_descriptions = true;
+            break
+        end
+    end
+    pickers.new(
+        vim.tbl_deep_extend("force", themes.get_dropdown({}),
+            { layout_config = { width = 160 } }), {
+            prompt_title = name,
+            finder = finders.new_table({
+                results = table,
+                entry_maker = function(entry)
+                    if fn_as_str(entry[1]) == nil then return {} end
+                    local command_displayer =
+                        entry_display.create({
+                            separator = " ▏",
+                            items = {
+                                { width = name_width }, { width = desc_width },
+                                { remaining = true }
+                            }
+                        })
+                    local group_displayer = entry_display.create({
+                        separator = " ▏",
+                        items = { { width = name_width }, { remaining = true } }
+                    })
+
+                    local function make_display()
+                        local function_display = entry[3];
+                        if type(entry[3]) == "function" then
+                            function_display = "< function >"
+                        end
+                        -- Execute heading titles if necessary
+                        local main_title = fn_as_str(entry[1])
+                        local sub_title = fn_as_str(entry[2])
+                        -- If the third item in the entry is a table, then
+                        -- it must be a subgroup.
+                        if type(entry[3]) == "table" then
+                            return
+                                group_displayer({ { main_title }, { sub_title } })
+                        elseif has_descriptions then
+                            return command_displayer({
+                                { main_title }, { sub_title }, { function_display }
+                            })
+                        else
+                            return group_displayer({ { main_title }, { entry[3] } })
+                        end
+                    end
+
+                    return {
+                        value = entry,
+                        display = make_display,
+                        ordinal = fn_as_str(entry[1])
+                    }
+                end
+            }),
+            sorter = conf.generic_sorter(opts),
+            attach_mappings = function(prompt_bufnr, _)
+                actions.select_default:replace(function()
+                    actions.close(prompt_bufnr)
+                    local entry = action_state.get_selected_entry().value
+                    if type(entry[3]) == "table" then
+                        open_palette(opts, fn_as_str(entry[1]), entry[3])
+                    elseif type(entry[3]) == "string" then
+                        vim.api.nvim_exec(entry[3], true)
+                    elseif type(entry[3]) == "function" then
+                        entry[3]()
+                    end
+                end)
+                return true
+            end
+        }):find()
+end
+
+local open_full_palette = function(opts)
+    local full_palette = {}
+    local search
+    search = function(item)
+        for _, entry in pairs(item) do
+            if type(entry[3]) == "table" then
+                search(entry[3])
+            else
+                full_palette[#full_palette + 1] = entry
+            end
+        end
+    end
+    search(palette)
+    return open_palette(opts, "Full Command Palette", full_palette)
+end
+
+-- Pass a table consisting of commands or subgroups, and they will be added to
+-- the global command palette. This is useful for organizing commands by plugin.
+-- TODO: Allow adding to a subgroup by name
+local add_to_command_palette = function(table)
+    for i = 1, #table do palette[#palette + 1] = table[i] end
+end
+
+return {
+    open = open_palette,
+    open_full = open_full_palette,
+    palette = palette,
+    add = add_to_command_palette
+}

+ 9 - 0
.config/nvim/custom/jonathandarker/.gitignore

@@ -0,0 +1,9 @@
+# ignore everything...
+/*
+!.gitignore
+# ...except for these:
+!colors
+!colors/jonathandarker.vim
+!lua
+!lua/**/*.lua
+

+ 2 - 0
.config/nvim/custom/jonathandarker/colors/jonathandarker.vim

@@ -0,0 +1,2 @@
+lua require("jonathandarker").load()
+

+ 184 - 0
.config/nvim/custom/jonathandarker/lua/jonathandarker/colors/default.lua

@@ -0,0 +1,184 @@
+-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
+--
+-- Definitions for vim's default highlight groups.
+-- As much as possible, other highlight groups should be linked to these.
+--
+-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
+return {
+    load = function(p)
+        -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
+        -- Default syntax groups
+        -- https://neovim.io/doc/user/syntax.html#%3Asyntax
+        -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
+
+        p.hset("Normal", { fg = p.FOREGROUND })
+
+        p.hset("Constant", { fg = p.PLUM })
+        p.hset("String", { fg = p.GREEN })
+        p.link("Character", "String")
+        p.hset("Number", { fg = p.CYAN })
+        p.hset("Boolean", { fg = p.ORANGE })
+        p.link("Float", "Number")
+
+        p.hset("Function", { fg = p.YELLOW })
+        p.link("Identifier", "Normal")
+
+        p.hset("Keyword", { fg = p.ORANGE })
+        p.link("Statement", "Keyword")
+        p.link("Conditional", "Statement")
+        p.link("Repeat", "Statement")
+        p.link("Label", "Statement")
+        p.link("Operator", "Statement")
+        p.link("Exception", "Statement")
+
+        p.link("PreProc", "Statement")
+        p.link("Include", "Statement")
+        p.link("Define", "Statement")
+        p.link("Macro", "Statement")
+        p.link("PreCondit", "Statement")
+
+        p.link("Type", "Function")
+        p.hset("Typedef", { fg = p.PERIWINKLE })
+
+        p.link("StorageClass", "Keyword")
+        p.link("Structure", "Keyword")
+
+        p.hset("Comment", { fg = p.BACKGROUNDALT })
+
+        p.link("Special", "Keyword")
+        p.link("SpecialChar", "Keyword")
+        p.link("Tag", "Keyword")
+        p.link("Delimiter", "Keyword")
+        p.link("SpecialComment", "Special")
+        p.link("Debug", "Keyword")
+
+        p.hset("Underlined", { underline = true })
+
+        p.link("Ignore", "Normal")
+
+        p.hset("Error", { fg = p.RED })
+
+        p.hset("Todo", { fg = p.TODO_COMMENT })
+
+        -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
+        -- Default UI groups
+        -- https://neovim.io/doc/user/syntax.html#highlight-groups
+        -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
+
+        -- Window elements
+        p.link("ColorColumn", "WinSeparator")
+        p.hset("WinSeparator", { fg = p.BACKGROUNDALT, bg = p.BACKGROUND })
+        p.hset("EndOfBuffer", {})
+
+        -- WinBar
+        p.hset("WinBar",
+            { fg = p.BACKGROUNDALT, bg = p.BACKGROUND, underdashed = true })
+        p.hset("WinBarNC", {
+            fg = p.BACKGROUNDALT,
+            bg = p.BACKGROUND,
+            underdashed = true,
+            italic = true
+        })
+
+        -- Cursor
+        p.hset("Cursor", { bg = p.SPECIAL_CURSOR })
+        p.link("CursorIM", "Cursor")
+
+        -- Search
+        p.hset("Conceal", {})
+        p.link("CurSearch", "Visual")
+
+        -- CursorLine
+        p.hset("CursorLine", {})
+        p.hset("CursorLineNr", { fg = p.SPECIAL_CURSOR })
+        p.hset("CursorLineSign", {})
+
+        -- Diff
+        p.hset("DiffAdd", { bg = p.BACKGROUND })
+        p.hset("DiffChange", {})
+        p.hset("DiffDelete", {})
+        p.link("DiffText", "Normal")
+
+        -- Floats
+        p.hset("NormalFloat", { bg = p.BACKGROUNDALT, fg = p.FOREGROUND })
+        p.hset("FloatBorder", { fg = p.FOREGROUND })
+        p.hset("FloatTitle", { fg = p.ORANGE, bold = true })
+
+        -- Folds
+        p.hset("FoldColumn", {})
+        p.hset("CursorLineFold", {})
+        p.hset("Folded", { fg = p.BACKGROUNDALT, italic = true })
+
+        -- Line numbers
+        p.hset("LineNr", { bg = p.BACKGROUND, fg = p.BACKGROUNDALT })
+        p.link("LineNrAbove", "LineNr")
+        p.link("LineNrBelow", "LineNr")
+
+        -- Popup menu
+        p.hset("Pmenu", { fg = p.FOREGROUND, bg = p.BACKGROUNDALT })
+        p.hset("PmenuExtra", { fg = p.ORANGE, bg = p.BACKGROUNDALT })
+        p.hset("PmenuExtraSel", { fg = p.YELLOW, bg = p.BACKGROUNDALT })
+        p.hset("PmenuKind", {})
+        p.hset("PmenuKindSel", {})
+        p.hset("PmenuSbar", {})
+        p.hset("PmenuSel", { fg = p.ORANGE, bg = p.BACKGROUNDALT })
+        p.hset("PmenuThumb", {})
+
+        p.hset("Question", {})
+        p.hset("QuickFixLine", {})
+        p.hset("Scrollbar", {})
+        p.hset("Search", {})
+        p.hset("SignColumn", {})
+
+        -- Spell
+        p.hset("SpellBad", { undercurl = true, sp = p.PERIWINKLE })
+        p.hset("SpellRare", { undercurl = true, sp = p.PERIWINKLE })
+        p.hset("SpellCap", {})
+        p.hset("SpellLocal", {})
+
+        -- StatusLine
+        -- In truth, these two should display identically, but if Vim detects
+        -- that there is no difference, it will replace the gap in splits with
+        -- carets. Assuming that there is only one status bar, this is fine.
+        p.hset("StatusLine", { fg = p.BACKGROUND, bg = p.BACKGROUND })
+        p.hset("StatusLineNC", { fg = p.FOREGROUND, bg = p.FOREGROUND })
+
+        -- TabLine
+        p.hset("TabLine", { fg = p.FOREGROUND, bg = p.BACKGROUND })
+        p.link("TabLineFill", "TabLine")
+        p.link("TabLineSel", "TabLine")
+
+        -- Visual
+        p.hset("Visual", { underline = true })
+        p.link("VisualNOS", "Visual")
+
+        -- Terminal
+        p.link("TermCursor", "Cursor")
+        p.hset("TermCursorNC", {})
+
+        -- Commands
+        p.hset("Title", {})
+        p.hset("Tooltip", {})
+        p.hset("WarningMsg", {})
+        p.hset("WildMenu", {})
+
+        -- Whitespace
+        p.hset("Whitespace", { fg = p.SPECIAL_SUBTLE })
+        p.link("ExtraWhitespace", "Whitespace")
+        p.link("NonText", "Whitespace")
+        p.link("SpecialKey", "NonText")
+
+        -- Misc.
+        p.hset("IncSearch", {})
+        p.hset("MatchParen", {})
+        p.hset("Menu", {})
+        p.hset("ModeMsg", {})
+        p.hset("MoreMsg", {})
+        p.hset("MsgArea", {})
+        p.hset("MsgSeparator", {})
+        p.hset("NormalNC", {})
+        p.hset("Directory", {})
+        p.hset("Substitute", {})
+        p.hset("ErrorMsg", {})
+    end
+}

+ 7 - 0
.config/nvim/custom/jonathandarker/lua/jonathandarker/colors/lsp/default.lua

@@ -0,0 +1,7 @@
+return {
+    load = function(p)
+        p.link("LspInfoTip", "Comment")
+        p.link("LspCodeLens", "LspInfoTip")
+        p.link("LspInlayHint", "LspInfoTip")
+    end
+}

+ 5 - 0
.config/nvim/custom/jonathandarker/lua/jonathandarker/colors/lsp/init.lua

@@ -0,0 +1,5 @@
+return {
+    load = function(p)
+        require("jonathandarker.colors.lsp.default").load(p)
+    end
+}

+ 7 - 0
.config/nvim/custom/jonathandarker/lua/jonathandarker/colors/plugins/gitsigns.lua

@@ -0,0 +1,7 @@
+return {
+    load = function(p)
+        p.hset("GitSignsAddInline", { underline = true, sp = p.CHARTREUSE })
+        p.hset("GitSignsChangeInline", { underline = true, sp = p.BLUE })
+        p.hset("GitSignsDeleteInline", { underline = true, sp = p.BURGUNDY })
+    end
+}

+ 14 - 0
.config/nvim/custom/jonathandarker/lua/jonathandarker/colors/plugins/init.lua

@@ -0,0 +1,14 @@
+-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
+--
+-- Load Plugin-Specific Highlights
+--
+-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
+return {
+    load = function(p)
+        require("jonathandarker.colors.plugins.gitsigns").load(p)
+        require("jonathandarker.colors.plugins.nvim-treesitter-context").load(p)
+        require("jonathandarker.colors.plugins.telescope-nvim").load(p)
+        require("jonathandarker.colors.plugins.vim-floaterm").load(p)
+        require("jonathandarker.colors.plugins.status-beast").load(p)
+    end
+}

+ 7 - 0
.config/nvim/custom/jonathandarker/lua/jonathandarker/colors/plugins/nvim-treesitter-context.lua

@@ -0,0 +1,7 @@
+return {
+    load = function(p)
+        p.link("TreesitterContext", "Normal")
+        p.hset("TreesitterContextBottom",
+            { underdashed = true, sp = p.BACKGROUNDALT })
+    end
+}

+ 45 - 0
.config/nvim/custom/jonathandarker/lua/jonathandarker/colors/plugins/status-beast.lua

@@ -0,0 +1,45 @@
+return {
+    load = function(p)
+        p.hset("StatusBeastDiagnosticEmpty", {})
+        p.hset("StatusBeastDiagnosticInfo", { fg = p.BACKGROUNDALT })
+        p.hset("StatusBeastDiagnosticHint", { fg = p.YELLOW })
+        p.hset("StatusBeastDiagnosticWarn", { fg = p.ORANGE })
+        p.hset("StatusBeastDiagnosticError", { fg = p.BURGUNDY })
+        p.hset("StatusBeastGitEmpty", { fg = p.BACKGROUNDALT })
+        p.hset("StatusBeastGitAdd", { fg = p.GREEN })
+        p.hset("StatusBeastGitChange", { fg = p.CYAN })
+        p.hset("StatusBeastGitDelete", { fg = p.RED })
+        p.hset("StatusBeastBarNormal", {
+            fg = p.BACKGROUNDALT,
+            sp = p.BACKGROUNDALT,
+            underdashed = true
+        })
+        p.hset("StatusBeastBarHighlight",
+            { fg = p.FOREGROUND, sp = p.BACKGROUNDALT, underdashed = true })
+        p.hset("StatusBeastBarItalic",
+            { fg = p.BACKGROUNDALT, italic = true, underdashed = true })
+        p.hset("StatusBeastBarIcon",
+            { fg = p.ORANGE, sp = p.BACKGROUNDALT, underdashed = true })
+        p.hset("StatusBeastModeNormal", {
+            fg = p.BACKGROUNDALT,
+            sp = p.BACKGROUNDALT,
+            underdashed = true
+        })
+        p.hset("StatusBeastModeVisual",
+            { fg = p.MAGENTA, sp = p.BACKGROUNDALT, underdashed = true })
+        p.hset("StatusBeastModeSelect",
+            { fg = p.CYAN, sp = p.BACKGROUNDALT, underdashed = true })
+        p.hset("StatusBeastModeReplace",
+            { fg = p.GREEN, sp = p.BACKGROUNDALT, underdashed = true })
+        p.hset("StatusBeastModeInsert",
+            { fg = p.GREEN, sp = p.BACKGROUNDALT, underdashed = true })
+        p.hset("StatusBeastModeCommand",
+            { fg = p.ORANGE, sp = p.BACKGROUNDALT, underdashed = true })
+        p.hset("StatusBeastModeTerminal",
+            { fg = p.RED, sp = p.BACKGROUNDALT, underdashed = true })
+        p.hset("StatusBeastModeOther",
+            { fg = p.LILAC, sp = p.BACKGROUNDALT, underdashed = true })
+        p.hset("StatusBeastModeError",
+            { fg = p.RED, sp = p.BACKGROUNDALT, underdashed = true })
+    end
+}

+ 7 - 0
.config/nvim/custom/jonathandarker/lua/jonathandarker/colors/plugins/telescope-nvim.lua

@@ -0,0 +1,7 @@
+return {
+    load = function(p)
+        p.link("TelescopeBorder", "WinSeparator")
+        p.hset("TelescopeTitle", { fg = p.BACKGROUNDALT, italic = true })
+        p.hset("TelescopeSelection", { fg = p.ORANGE })
+    end
+}

+ 1 - 0
.config/nvim/custom/jonathandarker/lua/jonathandarker/colors/plugins/vim-floaterm.lua

@@ -0,0 +1 @@
+return { load = function(p) p.link("FloatermBorder", "WinSeparator") end }

+ 55 - 0
.config/nvim/custom/jonathandarker/lua/jonathandarker/colors/treesitter/default.lua

@@ -0,0 +1,55 @@
+return {
+    load = function(p)
+        p.link("@text.literal", "Comment")
+        p.link("@text.reference", "Identifier")
+        p.link("@text.title", "Title")
+        p.link("@text.uri", "Underlined")
+        p.link("@text.underline", "Underlined")
+        p.link("@text.todo", "Todo")
+
+        p.link("@comment", "Comment")
+        p.link("@punctuation", "Delimiter")
+
+        p.link("@constant", "Constant")
+        p.link("@constant.builtin", "Special")
+        p.link("@constant.macro", "Define")
+        p.link("@define", "Define")
+        p.link("@macro", "Macro")
+        p.link("@string", "String")
+        p.link("@string.escape", "SpecialChar")
+        p.link("@string.special", "SpecialChar")
+        p.link("@character", "Character")
+        p.link("@character.special", "SpecialChar")
+        p.link("@number", "Number")
+        p.link("@boolean", "Boolean")
+        p.link("@float", "Float")
+
+        p.link("@function", "Function")
+        p.link("@function.builtin", "Special")
+        p.link("@function.macro", "Macro")
+        p.link("@parameter", "Identifier")
+        p.link("@method", "Function")
+        p.link("@field", "Identifier")
+        p.link("@property", "Identifier")
+        p.link("@constructor", "Special")
+
+        p.link("@conditional", "Conditional")
+        p.link("@repeat", "Repeat")
+        p.link("@label", "Label")
+        p.link("@operator", "Operator")
+        p.link("@keyword", "Keyword")
+        p.link("@exception", "Exception")
+
+        p.link("@variable", "Identifier")
+        p.link("@type", "Type")
+        p.link("@type.definition", "Typedef")
+        p.link("@type.builtin", "@constant")
+        p.link("@storageclass", "StorageClass")
+        p.link("@structure", "Structure")
+        p.link("@namespace", "Identifier")
+        p.link("@include", "Include")
+        p.link("@preproc", "PreProc")
+        p.link("@debug", "Debug")
+        p.link("@tag", "Tagreturn")
+    end
+}

+ 6 - 0
.config/nvim/custom/jonathandarker/lua/jonathandarker/colors/treesitter/init.lua

@@ -0,0 +1,6 @@
+return {
+    load = function(p)
+        require("jonathandarker.colors.treesitter.default").load(p)
+        require("jonathandarker.colors.treesitter.languages.python").load(p)
+    end
+}

+ 6 - 0
.config/nvim/custom/jonathandarker/lua/jonathandarker/colors/treesitter/languages/python.lua

@@ -0,0 +1,6 @@
+return {
+    load = function(p)
+        -- Mostly for highlighting "self"
+        p.link("@variable.builtin.python", "@constant")
+    end
+}

+ 12 - 0
.config/nvim/custom/jonathandarker/lua/jonathandarker/init.lua

@@ -0,0 +1,12 @@
+local palette = require("jonathandarker.palette")
+return {
+    load = function()
+        local loaded = palette.load()
+        require("jonathandarker.colors.default").load(loaded)
+        require("jonathandarker.colors.plugins").load(loaded)
+        require("jonathandarker.colors.treesitter").load(loaded)
+        require("jonathandarker.colors.lsp").load(loaded)
+        return loaded
+    end,
+    palette = palette
+}

+ 58 - 0
.config/nvim/custom/jonathandarker/lua/jonathandarker/palette.lua

@@ -0,0 +1,58 @@
+local interpolate = function(source, target, percent)
+    local result = "#"
+    for _, i in pairs({ 2, 4, 6 }) do
+        local sval = tonumber(source:sub(i, i + 1), 16)
+        local tval = tonumber(target:sub(i, i + 1), 16)
+        local difference = tval - sval
+        local delta = math.floor(difference * (percent / 100))
+        local value = string.format("%x",
+            math.max(math.min(sval + delta, 255), 0))
+        if value:len() == 1 then value = "0" .. value end
+        result = result .. value
+    end
+    return result
+end
+
+return {
+    load = function()
+        local loaded = {}
+        local output = vim.fn.system([[
+            echo BLACK=$JONATHANDARKER_COLOR_00;
+            echo RED=$JONATHANDARKER_COLOR_01;
+            echo GREEN=$JONATHANDARKER_COLOR_02;
+            echo ORANGE=$JONATHANDARKER_COLOR_03;
+            echo CYAN=$JONATHANDARKER_COLOR_04;
+            echo MAGENTA=$JONATHANDARKER_COLOR_05;
+            echo LILAC=$JONATHANDARKER_COLOR_06;
+            echo SILVER=$JONATHANDARKER_COLOR_07;
+            echo GREY=$JONATHANDARKER_COLOR_08;
+            echo BURGUNDY=$JONATHANDARKER_COLOR_09;
+            echo CHARTREUSE=$JONATHANDARKER_COLOR_10;
+            echo YELLOW=$JONATHANDARKER_COLOR_11;
+            echo BLUE=$JONATHANDARKER_COLOR_12;
+            echo PLUM=$JONATHANDARKER_COLOR_13;
+            echo PERIWINKLE=$JONATHANDARKER_COLOR_14;
+            echo WHITE=$JONATHANDARKER_COLOR_15;
+            echo BACKGROUND=$JONATHANDARKER_COLOR_BG;
+            echo BACKGROUNDALT=$JONATHANDARKER_COLOR_BA;
+            echo FOREGROUND=$JONATHANDARKER_COLOR_FG;
+            echo FOREGROUNDALT=$JONATHANDARKER_COLOR_FA;
+        ]])
+        for definition in string.gmatch(output, "[^%s]+=[^%s]+") do
+            local name = definition:match("[^%s]+="):sub(1, -2)
+            local value = definition:match("=[^%s]+"):sub(2)
+            loaded[name] = value
+        end
+        loaded.SPECIAL_SUBTLE = interpolate(loaded.BACKGROUND,
+            loaded.FOREGROUND, 12)
+        loaded.SPECIAL_CURSOR = interpolate(loaded.FOREGROUND,
+            loaded.BACKGROUND, 10)
+        loaded.hset = function(group, config)
+            vim.api.nvim_set_hl(0, group, config)
+        end
+        loaded.link = function(group, target)
+            vim.api.nvim_set_hl(0, group, { link = target })
+        end
+        return loaded
+    end
+}

+ 103 - 0
.config/nvim/custom/jxdash/lua/jxdash/init.lua

@@ -0,0 +1,103 @@
+local display = vim.tbl_map(function(line)
+    return { { line, "" } }
+end, vim.split(
+    [[
+████████████████████████████████████████████████████████████████████████████████
+█                                                                              █
+█         Welcome to a new instance of                                         █
+█                                                                              █
+█         ███▄▄▄▄     ▄████████ ▄██████▄  ▄█    █▄   ▄█   ▄▄▄▄███▄▄▄▄          █
+█         ███▀▀▀██▄  ███    ██████    ██████    ███ ███ ▄██▀▀▀███▀▀▀██▄        █
+█         ███   ███  ███    █▀ ███    ██████    ███ ███▌███   ███   ███        █
+█         ███   ███ ▄███▄▄▄    ███    ██████    ███ ███▌███   ███   ███        █
+█         ███   ███▀▀███▀▀▀    ███    ██████    ███ ███▌███   ███   ███        █
+█         ███   ███  ███    █▄ ███    ██████    ███ ███ ███   ███   ███        █
+█         ███   ███  ███    ██████    ██████    ███ ███ ███   ███   ███        █
+█          ▀█   █▀   ██████████ ▀██████▀  ▀██████▀  █▀   ▀█   ███   █▀         █
+█                                                                              █
+█                              the hyperextensible Vim-based text editor       █
+█                                                                              █
+█         What follows is a minute subset of your options:                     █
+█                                                                              █
+█         ✦ Search the current working directory                     sf        █
+█                                                                              █
+█         ✦ Search all files in the current working directory        sa        █
+█                                                                              █
+█         ✦ Open a floating terminal                                stt        █
+█                                                                              █
+█         ✦ Open a floating instance of LazyGit                     sto        █
+█                                                                              █
+█         ✦ Open a command palette                                   sp        █
+█                                                                              █
+████████████████████████████████████████████████████████████████████████████████
+]], '\n'))
+
+local shown = false
+return {
+    setup = function()
+        local namespace = vim.api.nvim_create_namespace('jxdash')
+        vim.api.nvim_create_autocmd('UIEnter', {
+            group = vim.api.nvim_create_augroup('JxDashStartup',
+                { clear = true }),
+            callback = function()
+                if
+                    vim.api.nvim_buf_get_name(0) == ''
+                    and vim.g.read_from_stdin == nil
+                    and vim.api.nvim_get_mode().mode == 'n'
+                    and not shown
+                then
+                    vim.opt_local.number = false
+                    vim.opt_local.relativenumber = false
+                    vim.opt_local.signcolumn = "no"
+                    vim.opt_local.foldcolumn = "0"
+                    vim.opt_local.statuscolumn = ""
+                    local ids = {}
+                    -- Insert a space and undo it to erase previous contents
+                    -- without marking buffer as modified
+                    vim.api.nvim_feedkeys(
+                        vim.api.nvim_replace_termcodes("i <Esc>u", true,
+                            false,
+                            true), "n", false)
+                    table.insert(ids,
+                        vim.api.nvim_buf_set_extmark(0, namespace, 0, 0,
+                            {
+                                spell = false,
+                                strict = false,
+                                virt_text_pos = "overlay",
+                                virt_text = display[1]
+                            }))
+                    table.insert(ids,
+                        vim.api.nvim_buf_set_extmark(0, namespace, 0, 0,
+                            {
+                                spell = false,
+                                strict = false,
+                                virt_lines = vim.list_slice(display, 2)
+                            }))
+                    vim.schedule(function()
+                        vim.api.nvim_create_autocmd(
+                            { "TextChanged", "InsertEnter", "BufEnter" }, {
+                                once = true,
+                                buffer = 0,
+                                callback = function(_)
+                                    vim.opt_local.number = vim.go.number
+                                    vim.opt_local.relativenumber = vim.go
+                                        .relativenumber
+                                    vim.opt_local.signcolumn = vim.go.signcolumn
+                                    vim.opt_local.numberwidth = vim.go
+                                        .numberwidth
+                                    vim.opt_local.foldcolumn = vim.go.foldcolumn
+                                    vim.opt_local.statuscolumn = vim.go
+                                        .statuscolumn
+                                    for _, id in pairs(ids) do
+                                        vim.api.nvim_buf_del_extmark(0, namespace,
+                                            id)
+                                    end
+                                end
+                            })
+                    end)
+                    shown = true
+                end
+            end,
+        })
+    end
+}

+ 19 - 0
.config/nvim/custom/proj-conf/lua/proj-conf/health.lua

@@ -0,0 +1,19 @@
+local proj_conf = require("proj-conf")
+
+return {
+    check = function()
+        vim.health.start("Project Settings")
+        if proj_conf.status().loaded ~= true then
+            vim.health.warn("Not loaded")
+            return
+        end
+        vim.health.info("Initial settings: " ..
+            table.concat(proj_conf.status().initial, ", "))
+        for _, item in pairs(proj_conf.status().failed) do
+            vim.health.error(item)
+        end
+        for _, item in pairs(proj_conf.status().found) do
+            vim.health.ok(item)
+        end
+    end
+}

+ 85 - 0
.config/nvim/custom/proj-conf/lua/proj-conf/init.lua

@@ -0,0 +1,85 @@
+-- This plugin enables simple, safe, and reusable project-level settings. This
+-- plugin contains much configuration that is unlikely to be useful outside the
+-- context of the rest of this repository, aside from `./init.lua` and
+-- `./health.lua`.
+
+-- Configurations loaded into `init.lua` should contain a table of either
+-- configuration functions or the names of configuration functions (as strings).
+-- The keys of these tables must be globally unique, except for `default`, which
+-- is a special item that must be a table of zero or more configuration function
+-- names. These configurations will be aggregated and executed (in no particular
+-- order).
+
+-- If a file called `.proj-conf.neovim` is found in Neovim's working directory,
+-- then each line of that file will be parsed as the name of a configuration
+-- function. If no such file exists, then `default` will be used as the root
+-- setting. This allows composing project-specific settings.
+
+-- The appeal of this hack is enabling composable settings without needing to
+-- navigate the security challenges of `set exrc`.
+--
+local filename = ".proj-conf.neovim"
+
+local map = { default = {} }
+local status = {
+    initial = {},
+    found = {},
+    failed = {},
+    loaded = false
+}
+
+for _, i in pairs({
+    require("proj-conf.lsp"),
+    require("proj-conf.lint"),
+    require("proj-conf.save-formatter"),
+    require("proj-conf.projects.deno_typescript_monorepo"),
+    require("proj-conf.projects.ruff_pyright")
+}) do
+    map.default = vim.list_extend(map.default, i.default)
+    i.default = nil
+    map = vim.tbl_deep_extend("error", map, i)
+end
+
+local setup = function()
+    if status.loaded then
+        return
+    end
+    status.initial = {}
+    status.found = {}
+    status.failed = {}
+    status.loaded = false
+    local settings = {}
+    local add_to_settings
+    add_to_settings = function(item)
+        if type(map[item]) == "table" then
+            for _, key in pairs(map[item]) do add_to_settings(key) end
+            table.insert(status.initial, item)
+        else
+            settings[item] = true
+        end
+    end
+    if vim.fn.filereadable(filename) == 1 then
+        for line in io.lines(filename) do
+            if map[line] then add_to_settings(line) end
+        end
+    else
+        add_to_settings("default")
+        table.insert(status.initial, "default")
+    end
+    for item, _ in pairs(settings) do
+        if pcall(map[item]) then
+            table.insert(status.found, item)
+        else
+            table.insert(status.failed, item)
+        end
+    end
+    status.loaded = true
+end
+
+return {
+    setup = setup,
+    map = map,
+    status = function()
+        return status
+    end
+}

+ 20 - 0
.config/nvim/custom/proj-conf/lua/proj-conf/lint/init.lua

@@ -0,0 +1,20 @@
+local lint = require("lint")
+
+return {
+    default = {
+        "default_lint"
+    },
+    default_lint = {},
+    default_mypy_lint = function()
+        lint.linters_by_ft = {
+            python = { 'mypy', },
+            vim.api.nvim_create_autocmd({ "BufWritePost" }, {
+                group = vim.api.nvim_create_augroup(
+                    "nvim-lint-group", { clear = true }),
+                callback = function()
+                    require("lint").try_lint()
+                end,
+            })
+        }
+    end,
+}

+ 190 - 0
.config/nvim/custom/proj-conf/lua/proj-conf/lsp/init.lua

@@ -0,0 +1,190 @@
+local lspconfig = require("lspconfig")
+local capabilities = require("cmp_nvim_lsp").default_capabilities()
+
+return {
+    default = {
+        "default_lsp"
+    },
+    default_lsp = { "default_arduino_language_server_config",
+        "default_bashls_config", "default_basedpyright_config_and_typechecking",
+        "default_clangd_config", "default_cssls_config", "default_denols_config",
+        "default_gopls_config", "default_html_config", "default_jsonls_config",
+        "default_kotlin_language_server_config", "default_lemminx_config",
+        "default_lua_ls_config", "default_marksman_config",
+        "default_rust_analyzer_config", "default_sqlls_config",
+        "default_taplo_config", "default_terraformls_config",
+        "default_tsserver_config", "default_yamlls_config" },
+    default_arduino_language_server_config = function()
+        lspconfig.arduino_language_server.setup({
+            capabilities = capabilities
+        })
+    end,
+    default_bashls_config = function()
+        lspconfig.bashls.setup({ capabilities = capabilities })
+    end,
+    default_basedpyright_config = function()
+        lspconfig.basedpyright.setup({
+            capabilities = capabilities,
+            settings = {
+                basedpyright = {
+                    analysis = {
+                        typeCheckingMode = "standard",
+                    }
+                }
+            }
+        })
+    end,
+    default_clangd_config = function()
+        lspconfig.clangd.setup({ capabilities = capabilities })
+    end,
+    default_cssls_config = function()
+        lspconfig.cssls.setup({ capabilities = capabilities })
+    end,
+    default_denols_config = function()
+        lspconfig.denols.setup({
+            capabilities = capabilities,
+            root_dir = lspconfig.util
+                .root_pattern("deno.json", "deno.jsonc"),
+            single_file_support = false
+        })
+    end,
+    default_gopls_config = function()
+        lspconfig.gopls.setup({
+            capabilities = capabilities,
+            settings = {
+                gopls = {
+                    analyses = { unusedparams = true },
+                    staticcheck = true,
+                    gofumpt = true
+                }
+            }
+        })
+    end,
+    default_html_config = function()
+        lspconfig.html.setup({ capabilities = capabilities })
+    end,
+    default_jsonls_config = function()
+        lspconfig.jsonls.setup({ capabilities = capabilities })
+    end,
+    default_kotlin_language_server_config = function()
+        lspconfig.kotlin_language_server.setup(
+            { capabilities = capabilities })
+    end,
+    default_lemminx_config = function()
+        lspconfig.lemminx.setup({ capabilities = capabilities })
+    end,
+    default_lua_ls_config = function()
+        lspconfig.lua_ls.setup({
+            capabilities = capabilities,
+            settings = {
+                Lua = {
+                    workspace = { checkThirdParty = false },
+                    telemetry = { enable = false },
+                    hint = { enable = true },
+                    diagnostics = { globals = { "vim" } },
+                    format = {
+                        enable = true,
+                        defaultConfig = {
+                            indent_style = "space",
+                            indent_size = "4",
+                            max_line_length = "80",
+                        }
+                    },
+                }
+            }
+        })
+    end,
+    default_marksman_config = function()
+        lspconfig.marksman.setup({ capabilities = capabilities })
+    end,
+    default_ruff_lsp_config = function()
+        lspconfig.ruff_lsp.setup({ capabilities = capabilities })
+    end,
+    default_rust_analyzer_config = function()
+        lspconfig.rust_analyzer.setup({ capabilities = capabilities })
+    end,
+    default_sqlls_config = function()
+        lspconfig.sqlls.setup({ capabilities = capabilities })
+    end,
+    default_taplo_config = function()
+        lspconfig.taplo.setup({ capabilities = capabilities })
+    end,
+    default_terraformls_config = function()
+        lspconfig.terraformls.setup({ capabilities = capabilities })
+    end,
+    default_tsserver_config = function()
+        local inlayHints = {
+            includeInlayEnumMemberValueHints = true,
+            includeInlayFunctionLikeReturnTypeHints = true,
+            includeInlayFunctionParameterTypeHints = true,
+            includeInlayParameterNameHints = "all",
+            includeInlayParameterNameHintsWhenArgumentMatchesName = true,
+            includeInlayPropertyDeclarationTypeHints = true,
+            includeInlayVariableTypeHints = true
+        }
+        lspconfig.tsserver.setup({
+            capabilities = capabilities,
+            javascript = { inlayHints = inlayHints },
+            typescript = { inlayHints = inlayHints },
+            root_dir = lspconfig.util.root_pattern("package.json"),
+            single_file_support = false
+        })
+    end,
+    default_yamlls_config = function()
+        lspconfig.yamlls.setup({ capabilities = capabilities })
+    end,
+
+    default_basedpyright_config_and_typechecking = {
+        "default_basedpyright_config",
+        "default_basedpyright_typechecking_options"
+    },
+    default_basedpyright_typechecking_options = function()
+        local pickers = require("telescope.pickers")
+        local themes = require("telescope.themes")
+        local actions = require("telescope.actions")
+        local action_state = require("telescope.actions.state")
+        local finders = require("telescope.finders")
+        local conf = require("telescope.config").values
+        local get_basedpyright = function()
+            return vim.tbl_filter(function(l)
+                return l.name == "basedpyright"
+            end, vim.lsp.get_active_clients())[1]
+        end
+        require("command-palette").add({
+            { function()
+                if get_basedpyright() ~= nil then
+                    return "BasedPyright Typechecking"
+                end
+            end, "Set `typeCheckingMode` of BasedPyright",
+                function(opts)
+                    local current = get_basedpyright().settings.basedpyright
+                        .analysis.typeCheckingMode
+                    if current == nil then current = "unset" end
+                    pickers.new(themes.get_dropdown({}), {
+                        prompt_title = "BasedPyright Typechecking (Current: " ..
+                            current .. ")",
+                        finder = finders.new_table({
+                            results = vim.tbl_filter(
+                                function(r) return r ~= current end,
+                                { "off", "basic", "standard", "strict", "all" }),
+                        }),
+                        sorter = conf.generic_sorter(opts),
+                        attach_mappings = function(prompt_bufnr, _)
+                            actions.select_default:replace(function()
+                                actions.close(prompt_bufnr)
+                                local selection = action_state
+                                    .get_selected_entry()
+                                local client = get_basedpyright()
+                                client.settings.basedpyright.analysis.typeCheckingMode =
+                                    selection.value
+                                client.notify("workspace/didChangeConfiguration",
+                                    client.settings)
+                            end)
+                            return true
+                        end,
+                    }):find()
+                end
+            }
+        })
+    end
+}

+ 13 - 0
.config/nvim/custom/proj-conf/lua/proj-conf/projects/deno_typescript_monorepo.lua

@@ -0,0 +1,13 @@
+local formatter = require("save-formatter")
+
+return {
+    default = {},
+    deno_typescript_monorepo = { "deno_typescript_monorepo_format", "default_lsp" },
+    deno_typescript_monorepo_format = function()
+        formatter.enable(vim.tbl_deep_extend("force", formatter.default(), {
+            json = formatter.commands().deno,
+            jsonc = formatter.commands().deno,
+            markdown = formatter.commands().deno,
+        }))
+    end
+}

+ 45 - 0
.config/nvim/custom/proj-conf/lua/proj-conf/projects/ruff_pyright.lua

@@ -0,0 +1,45 @@
+local lspconfig = require("lspconfig")
+local capabilities = require("cmp_nvim_lsp").default_capabilities()
+local formatter = require("save-formatter")
+
+return {
+    default = {},
+    ruff_pyright = { "ruff_pyright_format", "default_jsonls_config",
+        "default_marksman_config",
+        "default_sqlls_config", "default_yamlls_config", "ruff_pyright_lsp",
+        "default_basedpyright_typechecking_options",
+        "default_mypy_lint" },
+    ruff_pyright_format = function()
+        formatter.enable(vim.tbl_deep_extend("force", formatter.default(), {
+            python = false,
+            ruff_lsp = true,
+        }))
+    end,
+    ruff_pyright_lsp = function()
+        lspconfig.ruff_lsp.setup({
+            capabilities = capabilities,
+            on_attach = function(client, _)
+                client.server_capabilities.hoverProvider = false
+            end,
+        })
+        lspconfig.basedpyright.setup({
+            capabilities = capabilities,
+            settings = {
+                basedpyright = {
+                    analysis = {
+                        typeCheckingMode = "off",
+                        autoSearchPaths = true,
+                        diagnosticMode = "openFilesOnly",
+                        useLibraryCodeForTypes = true,
+
+                        analyzeUnannotatedFunctions = true,
+                        reportUnreachable = true,
+                    },
+                    openFilesOnly = true,
+                    autoImportCompletions = true,
+                    disableOrganizeImports = true,
+                }
+            }
+        })
+    end
+}

+ 6 - 0
.config/nvim/custom/proj-conf/lua/proj-conf/save-formatter.lua

@@ -0,0 +1,6 @@
+local formatter = require("save-formatter")
+
+return {
+    default = {},
+    enable_global_save_formatter = function() formatter.enable() end
+}

+ 144 - 0
.config/nvim/custom/save-formatter/lua/save-formatter/init.lua

@@ -0,0 +1,144 @@
+local commands = {
+    prettier =
+    [[!prettier --write --ignore-path $XDG_CONFIG_HOME/prettier/ignore --config $XDG_CONFIG_HOME/prettier/config %:p]],
+    deno = [[!deno fmt %:p]],
+    black = [[!black %:p && isort %:p]],
+}
+
+local default = {
+    json = commands.prettier,
+    jsonc = commands.prettier,
+    html = commands.prettier,
+    css = commands.prettier,
+    markdown = commands.prettier,
+    denols = commands.deno,
+    python = commands.black,
+    lua_ls = true,
+}
+local enabled = {}
+
+local save_format = function(source)
+    if enabled[source] ~= nil then
+        if enabled[source] == true then
+            vim.api.nvim_exec("lua vim.lsp.buf.format()", true)
+            vim.api.nvim_exec("noautocmd write", true)
+        else
+            vim.api.nvim_exec(enabled[source], true)
+        end
+    end
+    vim.api.nvim_exec("e", true)
+end
+
+local global_autocmd_group = vim.api.nvim_create_augroup("SaveFormatterGlobal",
+    { clear = true })
+local setup = function()
+    vim.api.nvim_create_autocmd({ "BufWritePost" }, {
+        pattern = { "*" },
+        group = global_autocmd_group,
+        callback = function()
+            for _, lsp_data in pairs(vim.lsp.get_active_clients()) do
+                for buf_num, buf_active in pairs(lsp_data.attached_buffers) do
+                    if buf_num == vim.api.nvim_get_current_buf() and buf_active ==
+                        true and enabled[lsp_data.name] then
+                        save_format(lsp_data.name)
+                        return
+                    end
+                end
+            end
+            if enabled[vim.bo.filetype] ~= nil then
+                save_format(vim.bo.filetype)
+            end
+        end
+    })
+end
+
+local enable = function(items)
+    if not items then
+        enabled = vim.deepcopy(default)
+    else
+        enabled = vim.deepcopy(items)
+    end
+    for key, value in pairs(enabled) do
+        if value == false then
+            enabled[key] = nil
+        end
+    end
+    return enabled
+end
+local disable = function()
+    default = vim.deepcopy(enabled)
+    enabled = {}
+    return enabled
+end
+local add = function(item, value)
+    if value == nil then value = vim.deepcopy(default[item]) end
+    enabled[item] = vim.deepcopy(value)
+    return value
+end
+local remove = function(item)
+    default[item] = vim.deepcopy(enabled[item])
+    enabled[item] = nil
+end
+
+local pickers = require("telescope.pickers")
+local themes = require("telescope.themes")
+local actions = require("telescope.actions")
+local action_state = require("telescope.actions.state")
+local finders = require("telescope.finders")
+local conf = require("telescope.config").values
+local entry_display = require("telescope.pickers.entry_display")
+local picker = function(opts)
+    local items = {}
+    for key, value in pairs(enabled) do
+        if value ~= nil then
+            table.insert(items, { key, value })
+        end
+    end
+    pickers.new(themes.get_dropdown({}), {
+        prompt_title = "Save Formatter",
+        finder = finders.new_table({
+            results = items,
+            entry_maker = function(entry)
+                local desc = "LSP Format"
+                if type(entry[2]) == "string" then desc = entry[2] end
+                local displayer = entry_display.create({
+                    separator = " ▏",
+                    items = { { width = 16 }, { remaining = true } }
+                })
+                return {
+                    value = entry,
+                    display = function() return displayer({ { entry[1] }, { desc } }) end,
+                    ordinal = entry[1],
+                }
+            end,
+        }),
+        sorter = conf.generic_sorter(opts),
+        attach_mappings = function(prompt_bufnr, map)
+            map("n", "d", function(_)
+                local entry = action_state.get_selected_entry()
+                if entry ~= nil then
+                    remove(entry.value[1])
+                    actions.close(prompt_bufnr)
+                end
+            end)
+            actions.select_default:replace(function()
+                if add(action_state.get_current_line()) ~= nil then
+                    actions.close(prompt_bufnr)
+                end
+            end)
+            return true
+        end
+    }):find()
+end
+
+return {
+    add = add,
+    disable = disable,
+    enable = enable,
+    picker = picker,
+    remove = remove,
+    setup = setup,
+    commands = function() return commands end,
+    default = function() return default end,
+    enabled = function() return enabled end,
+}

+ 30 - 0
.config/nvim/custom/status-beast/lua/status-beast/highlights.lua

@@ -0,0 +1,30 @@
+return {
+    setup = function()
+        -- Default highlight groups. Looks best if customized.
+        vim.api.nvim_set_hl(0, "StatusBeastDiagnosticEmpty",
+            { link = "NonText" })
+        vim.api.nvim_set_hl(0, "StatusBeastDiagnosticInfo", { link = "Normal" })
+        vim.api.nvim_set_hl(0, "StatusBeastDiagnosticHint", { link = "Normal" })
+        vim.api.nvim_set_hl(0, "StatusBeastDiagnosticWarn", { link = "Normal" })
+        vim.api.nvim_set_hl(0, "StatusBeastDiagnosticError", { link = "Error" })
+        vim.api.nvim_set_hl(0, "StatusBeastGitEmpty", { link = "Normal" })
+        vim.api.nvim_set_hl(0, "StatusBeastGitAdd", { link = "DiffAdd" })
+        vim.api.nvim_set_hl(0, "StatusBeastGitChange", { link = "DiffChange" })
+        vim.api.nvim_set_hl(0, "StatusBeastGitDelete", { link = "DiffDelete" })
+        vim.api.nvim_set_hl(0, "StatusBeastModeNormal", { link = "Normal" })
+        vim.api.nvim_set_hl(0, "StatusBeastModeVisual", { link = "Normal" })
+        vim.api.nvim_set_hl(0, "StatusBeastModeSelect", { link = "Normal" })
+        vim.api.nvim_set_hl(0, "StatusBeastModeReplace", { link = "Normal" })
+        vim.api.nvim_set_hl(0, "StatusBeastModeInsert", { link = "Normal" })
+        vim.api.nvim_set_hl(0, "StatusBeastModeCommand", { link = "Normal" })
+        vim.api.nvim_set_hl(0, "StatusBeastModeTerminal", { link = "Normal" })
+        vim.api.nvim_set_hl(0, "StatusBeastModeOther", { link = "Normal" })
+        vim.api.nvim_set_hl(0, "StatusBeastStatusLine",
+            { link = "WinSeparator" })
+        vim.api.nvim_set_hl(0, "StatusBeastBarNormal", { link = "Normal" })
+        vim.api.nvim_set_hl(0, "StatusBeastBarHighlight", { link = "Cursor" })
+        vim.api.nvim_set_hl(0, "StatusBeastBarItalic", { link = "Italic" })
+        vim.api.nvim_set_hl(0, "StatusBeastBarIcon", { link = "Special" })
+        vim.api.nvim_set_hl(0, "StatusBeastBarError", { link = "Error" })
+    end
+}

+ 272 - 0
.config/nvim/custom/status-beast/lua/status-beast/init.lua

@@ -0,0 +1,272 @@
+local bitbrowser
+if pcall(require, "gitsigns") then
+    bitbrowser = require("bit-browser")
+else
+    bitbrowser = { get_target = function(_) return "NONE" end }
+end
+if not unpack then unpack = table.unpack end
+
+local setup = function()
+    require("status-beast.highlights").setup()
+    local maps = require("status-beast.maps")
+    -- Gutter options
+    vim.opt.number = true
+    vim.opt.relativenumber = true
+    vim.opt.signcolumn = "yes:1"
+    vim.opt.numberwidth = 3
+    -- Fold options
+    vim.opt.foldcolumn = "0"
+    vim.opt.foldlevel = 999
+    vim.opt.foldlevelstart = 999
+    vim.opt.foldenable = true
+
+    local get_gitsigns = function()
+        local found = "Empty"
+        local namespace = vim.api.nvim_get_namespaces()["gitsigns_signs_"]
+        if namespace == nil then return found end
+        local extmarks = vim.tbl_map(function(sign)
+                return sign[4]["sign_hl_group"]
+            end,
+            vim.api
+            .nvim_buf_get_extmarks(
+                vim.api
+                .nvim_win_get_buf(
+                    vim.g.statusline_winid), namespace,
+                { vim.v.lnum - 1, 0 },
+                { vim.v.lnum - 1, -1 },
+                { details = true }))
+        for _, v in pairs(extmarks) do
+            if v == "GitSignsDelete" then
+                return "Delete"
+            elseif v == "GitSignsChange" then
+                found = "Change"
+            elseif v == "GitSignsAdd" then
+                found = "Add"
+            end
+        end
+        return found
+    end
+
+    local diagnostics_map = { "Error", "Warn", "Info", "Hint", "Empty" }
+    local get_diagnostics = function()
+        local diagnostics = vim.tbl_map(function(sign)
+                return sign.severity
+            end,
+            vim.diagnostic
+            .get(
+                vim.api
+                .nvim_win_get_buf(
+                    vim.g.statusline_winid),
+                { lnum = vim.v.lnum - 1 }))
+        local index
+        if #diagnostics < 1 then
+            index = #diagnostics_map
+        else
+            index = math.min(unpack(diagnostics))
+            if index == nil or diagnostics_map[index] == nil then
+                index = #diagnostics_map
+            end
+        end
+        return diagnostics_map[index]
+    end
+
+    local get_mode = function()
+        local mode_code = vim.api.nvim_get_mode().mode
+        return maps.mode_map[mode_code] == nil and "Other" or
+            maps.mode_map[mode_code]
+    end
+    _G.StatusBeast = {
+        column = function()
+            local gitsign = get_gitsigns()
+            local diagnostic = get_diagnostics()
+            return table.concat({
+                "%#StatusBeastDiagnostic" .. diagnostic .. "#",
+                maps.diagnostic_icons[diagnostic] or "", "%=",
+                vim.v.relnum == 0 and "%#CursorLineNr#" or "%#LineNr#",
+                "%{&nu?(&rnu&&v:relnum?v:relnum:v:lnum):''}",
+                "%#StatusBeastGit" .. gitsign .. "#",
+                gitsign ~= "Empty" and "╏" or "¦"
+            }, "")
+        end,
+        line = function()
+            local s = {
+                -- Neovim icon
+                "%#StatusBeastBarHighlight#%#StatusBeastBarNormal#"
+            }
+            -- Mode
+            local mode = get_mode();
+            table.insert(s, "%#StatusBeastMode" .. mode .. "#" ..
+                string.upper(maps.mode_display_names[mode]) ..
+                "%#StatusBeastBarNormal#")
+            -- Date
+            table.insert(s,
+                "%#StatusBeastBarIcon# %#StatusBeastBarNormal#" ..
+                os.date("%H:%M"))
+            table.insert(s,
+                "%#StatusBeastBarIcon# %#StatusBeastBarNormal#" ..
+                os.date("%a, %b %d, W%V"))
+            -- Tabs
+            local current = vim.api.nvim_get_current_tabpage()
+            local tabpages = vim.api.nvim_list_tabpages()
+            if #tabpages > 1 then
+                for _, v in pairs(tabpages) do
+                    table.insert(s,
+                        (v == current and
+                            "%#StatusBeastBarIcon#󰓩 %#StatusBeastBarHighlight#" or
+                            "󰓪 %#StatusBeastBarItalic#") .. v ..
+                        "%#StatusBeastBarNormal#")
+                end
+            end
+            -- Directory and Position
+            table.insert(s,
+                "%#StatusBeastBarIcon# %#StatusBeastBarNormal#" ..
+                "%#StatusBeastBarItalic#" .. vim.fn.getcwd() ..
+                "%#StatusBeastBarNormal#" .. "%=" ..
+                "%#StatusBeastBarIcon#󰆿%#StatusBeastBarNormal#" ..
+                " %l:%c (%P)")
+            -- Search count
+            if vim.v.hlsearch ~= 0 then
+                local ok, result = pcall(vim.fn.searchcount,
+                    { maxcount = 998, timeout = 25 })
+                if ok and next(result) ~= nil then
+                    local denominator = math.min(result.total, result.maxcount)
+                    table.insert(s,
+                        "%#StatusBeastBarIcon# %#StatusBeastBarNormal#" ..
+                        string.format("%d/%d", result.current,
+                            denominator))
+                end
+            end
+            -- Selection length
+            if mode == "Visual" then
+                table.insert(s,
+                    "%#StatusBeastBarIcon#󱈄 %#StatusBeastBarNormal#L" ..
+                    tostring(
+                        math.abs(
+                            vim.fn.line("v") - vim.fn.line(".")) +
+                        1) .. ":C" ..
+                    tostring(
+                        math.abs(vim.fn.col("v") - vim.fn.col(".")) +
+                        1))
+            end
+            -- Bitbrowser
+            if bitbrowser.get_target() ~= "NONE" then
+                table.insert(s,
+                    "%#StatusBeastBarIcon#󱈇 %#StatusBeastBarNormal#" ..
+                    string.sub(bitbrowser.get_target(), 1, 1))
+            end
+            -- Macro
+            if vim.fn.reg_recording() ~= "" then
+                table.insert(s,
+                    "%#StatusBeastBarIcon#󰭆 %#StatusBeastBarNormal#" ..
+                    vim.fn.reg_recording())
+            end
+            -- LSP
+            for _, v in pairs(vim.lsp.buf_get_clients()) do
+                if v["attached_buffers"][vim.api.nvim_get_current_buf()] then
+                    table.insert(s,
+                        "%#StatusBeastBarIcon# %#StatusBeastBarNormal#" ..
+                        v["name"])
+                end
+            end
+            -- Git
+            local status_dict = vim.b.gitsigns_status_dict;
+            if (status_dict ~= nil) then
+                local status = vim.b.gitsigns_status
+                table.insert(s,
+                    "%#StatusBeastBarIcon# %#StatusBeastBarNormal#" ..
+                    status_dict.head ..
+                    (string.len(status) > 1 and " (" ..
+                        vim.b.gitsigns_status .. ")" or ""))
+            end
+            return "%#StatusBeastBarNormal# " .. table.concat(s, " ¦ ") .. " "
+        end,
+        win = function()
+            local buffer = vim.api.nvim_win_get_buf(vim.g.statusline_winid)
+            local name = vim.api.nvim_buf_get_name(buffer)
+            -- Unnamed
+            if string.len(name) == 0 or vim.fn.getfsize(name) < 0 then
+                return
+                " %#StatusBeastBarIcon#󱀶%#StatusBeastBarNormal# [No File]"
+            end
+
+            local relativename = string.sub(name,
+                string.len(vim.fn.getcwd()) + 1, 999)
+            local s = {}
+            -- Diagnostics
+            local diagnostics = vim.diagnostic.get(buffer, {
+                severity = vim.diagnostic.severity.ERROR
+            })
+            if #diagnostics > 0 then
+                table.insert(s,
+                    "%#StatusBeastBarError#" ..
+                    maps.diagnostic_icons["Error"] ..
+                    "%#StatusBeastBarNormal# ")
+            else
+                table.insert(s, "%#StatusBeastBarNormal# ")
+            end
+            -- Size
+            local filesize = vim.fn.getfsize(name)
+            local sizeabbrev = "B"
+            if filesize > 999 then
+                filesize = math.floor(filesize / 100)
+                sizeabbrev = "KB"
+            end
+            if filesize > 999 then
+                filesize = math.floor(filesize / 100)
+                sizeabbrev = "MB"
+            end
+            table.insert(s, tostring(filesize) .. sizeabbrev)
+            table.insert(s, " ¦ ")
+            -- Modified
+            if vim.fn.getbufinfo(buffer)[1].changed == 1 then
+                table.insert(s,
+                    "%#StatusBeastBarHighlight#%#StatusBeastBarNormal# ¦ ")
+            end
+            -- Icon
+            local fullname_icon = maps.file_node_exact_matches[vim.fn
+            .fnamemodify(name, ":t")]
+            local extension_icon = maps.file_node_extensions[vim.fn.fnamemodify(
+                name, ":e")]
+            table.insert(s, "%#StatusBeastBarIcon#")
+            if fullname_icon ~= nil then
+                table.insert(s, fullname_icon)
+            elseif extension_icon ~= nil then
+                table.insert(s, extension_icon)
+            else
+                table.insert(s, "%y")
+            end
+            table.insert(s, " %#StatusBeastBarNormal#")
+            -- Path
+            table.insert(s,
+                "%#StatusBeastBarHighlight#" ..
+                vim.fn.fnamemodify(name, ":t") ..
+                "%#StatusBeastBarNormal#")
+            local path_elements = vim.split(
+                vim.fn.fnamemodify(relativename, ":h"),
+                "/", true)
+            local reversed_path = {}
+            for i = #path_elements, 1, -1 do
+                reversed_path[#reversed_path + 1] = path_elements[i]
+            end
+            for _, v in pairs(reversed_path) do
+                if string.len(v) > 0 then
+                    table.insert(s, "  " .. v)
+                end
+            end
+            return "%#StatusBeastBarNormal# " .. table.concat(s) .. " "
+        end
+    }
+
+    -- Disable statusline
+    vim.opt.laststatus = 0
+    vim.opt.statusline = "%#StatusBeastStatusLine#%{repeat('-',winwidth('.'))}"
+    -- Set statuscolumn
+    vim.opt.statuscolumn = [[%!v:lua.StatusBeast.column()]]
+    -- Set tabline
+    vim.opt.showtabline = 2
+    vim.opt.tabline = [[%!v:lua.StatusBeast.line()]]
+    -- Set winbar
+    vim.opt.winbar = [[%!v:lua.StatusBeast.win()]]
+end
+
+return { setup = setup }

+ 214 - 0
.config/nvim/custom/status-beast/lua/status-beast/maps.lua

@@ -0,0 +1,214 @@
+return {
+    mode_map = {
+        ["n"] = "Normal",
+        ["niI"] = "Normal",
+        ["niR"] = "Normal",
+        ["niV"] = "Normal",
+        ["nt"] = "Normal",
+        ["ntT"] = "Normal",
+        ["v"] = "Visual",
+        ["vs"] = "Visual",
+        ["V"] = "Visual",
+        ["Vs"] = "Visual",
+        ["\22"] = "Visual",
+        ["\22s"] = "Visual",
+        ["s"] = "Select",
+        ["S"] = "Select",
+        ["\19"] = "Select",
+        ["i"] = "Insert",
+        ["ic"] = "Insert",
+        ["ix"] = "Insert",
+        ["R"] = "Insert",
+        ["Rc"] = "Insert",
+        ["Rx"] = "Insert",
+        ["Rv"] = "Insert",
+        ["Rvc"] = "Insert",
+        ["Rvx"] = "Insert",
+        ["r"] = "Insert",
+        ["c"] = "Command",
+        ["cv"] = "Command",
+        ["ce"] = "Command",
+        ["!"] = "Terminal",
+        ["t"] = "Terminal"
+    },
+    -- These should be the same length, to keep bar items from jumping around
+    mode_display_names = {
+        ["Other"] = "  Other",
+        ["Normal"] = "󰦨 Normal",
+        ["Visual"] = "󰈈 Visual",
+        ["Select"] = "󱈄 Select",
+        ["Insert"] = "󰷈 Insert",
+        ["Command"] = "    CMD",
+        ["Terminal"] = "   TERM"
+    },
+    diagnostic_icons = {
+        ["Error"] = "󰅚",
+        ["Warn"] = "󰀪",
+        ["Info"] = "󰋽",
+        ["Hint"] = "󰌶",
+        ["Empty"] = ""
+    },
+    file_node_extensions = {
+        ["styl"] = "",
+        ["sass"] = "",
+        ["scss"] = "",
+        ["htm"] = "",
+        ["html"] = "",
+        ["slim"] = "",
+        ["haml"] = "",
+        ["ejs"] = "",
+        ["css"] = "",
+        ["less"] = "",
+        ["md"] = "",
+        ["mdx"] = "",
+        ["markdown"] = "",
+        ["rmd"] = "",
+        ["json"] = "",
+        ["webmanifest"] = "",
+        ["js"] = "",
+        ["mjs"] = "",
+        ["jsx"] = "",
+        ["rb"] = "",
+        ["gemspec"] = "",
+        ["rake"] = "",
+        ["php"] = "",
+        ["py"] = "",
+        ["pyc"] = "",
+        ["pyo"] = "",
+        ["pyd"] = "",
+        ["coffee"] = "",
+        ["mustache"] = "",
+        ["hbs"] = "",
+        ["conf"] = "",
+        ["ini"] = "",
+        ["yml"] = "",
+        ["yaml"] = "",
+        ["toml"] = "",
+        ["bat"] = "",
+        ["mk"] = "",
+        ["jpg"] = "",
+        ["jpeg"] = "",
+        ["bmp"] = "",
+        ["png"] = "",
+        ["webp"] = "",
+        ["gif"] = "",
+        ["ico"] = "",
+        ["twig"] = "",
+        ["cpp"] = "",
+        ["c++"] = "",
+        ["cxx"] = "",
+        ["cc"] = "",
+        ["cp"] = "",
+        ["c"] = "",
+        ["cs"] = "",
+        ["h"] = "",
+        ["hh"] = "",
+        ["hpp"] = "",
+        ["hxx"] = "",
+        ["hs"] = "",
+        ["lhs"] = "",
+        ["nix"] = "",
+        ["lua"] = "",
+        ["java"] = "",
+        ["sh"] = "",
+        ["fish"] = "",
+        ["bash"] = "",
+        ["zsh"] = "",
+        ["ksh"] = "",
+        ["csh"] = "",
+        ["awk"] = "",
+        ["ps1"] = "",
+        ["ml"] = "λ",
+        ["mli"] = "λ",
+        ["diff"] = "",
+        ["db"] = "",
+        ["sql"] = "",
+        ["dump"] = "",
+        ["clj"] = "",
+        ["cljc"] = "",
+        ["cljs"] = "",
+        ["edn"] = "",
+        ["scala"] = "",
+        ["go"] = "",
+        ["dart"] = "",
+        ["xul"] = "",
+        ["sln"] = "",
+        ["suo"] = "",
+        ["pl"] = "",
+        ["pm"] = "",
+        ["t"] = "",
+        ["rss"] = "",
+        ["f#"] = "",
+        ["fsscript"] = "",
+        ["fsx"] = "",
+        ["fs"] = "",
+        ["fsi"] = "",
+        ["rs"] = "",
+        ["rlib"] = "",
+        ["d"] = "",
+        ["erl"] = "",
+        ["hrl"] = "",
+        ["ex"] = "",
+        ["exs"] = "",
+        ["eex"] = "",
+        ["leex"] = "",
+        ["heex"] = "",
+        ["vim"] = "",
+        ["ai"] = "",
+        ["psd"] = "",
+        ["psb"] = "",
+        ["ts"] = "",
+        ["tsx"] = "",
+        ["jl"] = "",
+        ["pp"] = "",
+        ["vue"] = "﵂",
+        ["elm"] = "",
+        ["swift"] = "",
+        ["xcplayground"] = "",
+        ["tex"] = "ﭨ",
+        ["r"] = "ﳒ",
+        ["rproj"] = "鉶",
+        ["sol"] = "ﲹ",
+        ["pem"] = ""
+    },
+    file_node_exact_matches = {
+        ["exact-match-case-sensitive-1.txt"] = "1",
+        ["exact-match-case-sensitive-2"] = "2",
+        ["gruntfile.coffee"] = "",
+        ["gruntfile.js"] = "",
+        ["gruntfile.ls"] = "",
+        ["gulpfile.coffee"] = "",
+        ["gulpfile.js"] = "",
+        ["gulpfile.ls"] = "",
+        ["mix.lock"] = "",
+        ["dropbox"] = "",
+        [".ds_store"] = "",
+        [".gitconfig"] = "",
+        [".gitignore"] = "",
+        [".gitattributes"] = "",
+        [".gitlab-ci.yml"] = "",
+        [".bashrc"] = "",
+        [".zshrc"] = "",
+        [".zshenv"] = "",
+        [".zprofile"] = "",
+        [".vimrc"] = "",
+        [".gvimrc"] = "",
+        ["_vimrc"] = "",
+        ["_gvimrc"] = "",
+        [".bashprofile"] = "",
+        ["favicon.ico"] = "",
+        ["license"] = "",
+        ["node_modules"] = "",
+        ["react.jsx"] = "",
+        ["procfile"] = "",
+        ["dockerfile"] = "",
+        ["docker-compose.yml"] = "",
+        ["rakefile"] = "",
+        ["config.ru"] = "",
+        ["gemfile"] = "",
+        ["makefile"] = "",
+        ["cmakelists.txt"] = "",
+        ["robots.txt"] = "ﮧ"
+    }
+
+}

+ 111 - 0
.config/nvim/init.lua

@@ -0,0 +1,111 @@
+-- === === === === === === === === Neovim Config === === === === === === === ===
+--
+-- A configuration for Neovim that aims to be beautiful, intuitive, and
+-- pragmatic about plugin usage, while providing a developer experience on par
+-- with professional IDEs. It is tuned for usage with a custom keyboard
+-- layout and terminal configuration, and may not be as useful in other setups.
+--
+-- This configuration leverages a combination of keymaps and omnibars to give
+-- quick access to a large amount of functionality in an intuitive way. Most
+-- keymaps are unchanged from stock Neovim, with the notable exception of
+-- remapping most `s<a-Z>` keymaps.
+--
+-- === === === === === === === === === === === === === === === === === === ===
+--
+-- Core Options
+--
+-- === === === === === === === === === === === === === === === === === === ===
+-- Incantation to render correctly in Alacritty/tmux/macOS
+vim.cmd([[
+    let &t_8f = "\<Esc>[38;2;%lu;%lu;%lum"
+    let &t_8b = "\<Esc>[48;2;%lu;%lu;%lum"
+    set termguicolors
+]])
+
+-- File options
+vim.opt.wrap = false
+vim.opt.encoding = "UTF-8"
+vim.opt.hlsearch = true
+vim.opt.spell = true
+vim.opt.spelllang = "en_us"
+
+-- Display options
+vim.opt.pumheight = 15
+vim.opt.laststatus = 2
+vim.opt.showtabline = 2
+vim.opt.showcmd = true
+vim.opt.cmdheight = 0
+vim.opt.number = true
+vim.opt.relativenumber = true
+
+vim.opt.splitbelow = true
+vim.opt.splitright = true
+
+vim.opt.expandtab = true
+vim.opt.tabstop = 4
+vim.opt.shiftwidth = 4
+
+-- === === === === === === === === === === === === === === === === === === ===
+--
+-- Lazy.nvim Configuration
+--
+-- `lazy.nvim` is a modern plugin manager for Neovim.
+--
+-- === === === === === === === === === === === === === === === === === === ===
+-- Bootstrapping `lazy`, as directed by GitHub docs:
+-- https://github.com/folke/lazy.nvim#-installation
+local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim"
+if not vim.loop.fs_stat(lazypath) then
+    vim.fn.system({
+        "git", "clone", "--filter=blob:none",
+        "https://github.com/folke/lazy.nvim.git", "--branch=stable", lazypath
+    })
+end
+vim.opt.rtp:prepend(lazypath)
+-- Add custom plugins to the runtimepath via lazy.
+local custom_runtime_path_root = vim.fn.stdpath("config") .. "/custom"
+local custom_runtime_paths = {}
+for _, filename in pairs(vim.split(vim.fn.glob(custom_runtime_path_root .. "/*"),
+    "\n")) do
+    table.insert(custom_runtime_paths, filename)
+end
+-- Load plugins
+require("lazy").setup("plugins", {
+    performance = { rtp = { paths = custom_runtime_paths } },
+    change_detection = { enabled = false },
+    defaults = { lazy = false }
+})
+-- === === === === === === === === === === === === === === === === === === ===
+--
+-- Keymaps
+--
+-- === === === === === === === === === === === === === === === === === === ===
+-- Use `Alt-Arrow` to navigate between panes
+vim.keymap.set("i", "<A-left>", "<C-\\><C-N><C-w>W")
+vim.keymap.set("i", "<A-right>", "<C-\\><C-N><C-w>w")
+vim.keymap.set("i", "<S-A-left>", "<C-\\><C-N>:tabnext<CR>")
+vim.keymap.set("i", "<S-A-right>", "<C-\\><C-N>:tabprevious<CR>")
+vim.keymap.set("n", "<A-left>", "<C-w>W")
+vim.keymap.set("n", "<A-right>", "<C-w>w")
+vim.keymap.set("n", "<S-A-left>", ":tabnext<CR>")
+vim.keymap.set("n", "<S-A-right>", ":tabprevious<CR>")
+-- Folds toggled by homerow roll
+vim.keymap.set("n", "sr", ": normal za<CR>")
+-- Buffer actions
+vim.keymap.set("n", "SV", ":vsp<CR>")
+vim.keymap.set("n", "SQ", ":q<CR>")
+vim.keymap.set("n", "SH", ":noh<CR>")
+-- Yank to system clipboard
+vim.keymap.set({ "n", 'v' }, "Y", "\"+y")
+-- Yank file properties to system clipboard
+local yank_filename = function(full, line)
+    local filename = vim.fn.expand("%")
+    if full then filename = vim.fn.expand("%:p") end
+    if line then filename = filename .. ":" .. vim.api.nvim_win_get_cursor(0)[1] end
+    vim.fn.setreg("+", filename)
+end
+vim.keymap.set("n", "Syan", function() yank_filename(true, false) end)
+vim.keymap.set("n", "Syal", function() yank_filename(true, true) end)
+vim.keymap.set("n", "Syrn", function() yank_filename(false, false) end)
+vim.keymap.set("n", "Syrl", function() yank_filename(false, true) end)
+vim.keymap.set("n", "Syf", function() yank_filename(false, false) end)

+ 114 - 0
.config/nvim/lua/plugins/command-palette.lua

@@ -0,0 +1,114 @@
+return {
+    {
+        dir = "../custom/command-palette",
+        name = "command-palette",
+        dependencies = { "nvim-telescope/telescope.nvim" },
+        enabled = true,
+        config = function(_, _)
+            local palette = require("command-palette")
+            palette.add({
+                {
+                    "Manage project", "", {
+                    {
+                        "Close project",
+                        "Safely close the project and then close the associated tmux pane",
+                        function()
+                            vim.api.nvim_create_autocmd({ "VimLeave" }, {
+                                pattern = { "*" },
+                                group = vim.api.nvim_create_augroup(
+                                    "tmux_close_group", { clear = true }),
+                                callback = function()
+                                    vim.api.nvim_exec("!tmux kill-pane",
+                                        false)
+                                end
+                            })
+                            vim.api.nvim_exec("qa", true)
+                        end
+                    }
+                }
+                }
+            })
+            vim.keymap.set("n", "sP", palette.open)
+            vim.keymap.set("n", "sp", palette.open_full)
+            vim.keymap.set("n", "sL", function()
+                palette.open({}, "LSP Finders", {
+                    { "Treesitter",         "", ":Telescope treesitter" },
+                    { "LSP References",     "", ":Telescope lsp_references" },
+                    { "LSP Incoming Calls", "", ":Telescope lsp_incoming_calls" },
+                    { "LSP Outgoing Calls", "", ":Telescope lsp_outgoing_calls" },
+                    {
+                        "LSP Document Symbols", "",
+                        ":Telescope lsp_document_symbols"
+                    },
+                    {
+                        "LSP Workspace Symbols", "",
+                        ":Telescope lsp_workspace_symbols"
+                    }, {
+                    "LSP Dynamic Workspace Symbols", "",
+                    ":Telescope lsp_dynamic_workspace_symbols"
+                }, { "Diagnostics",  "", ":Telescope diagnostics" },
+                    {
+                        "LSP Implementations", "",
+                        ":Telescope lsp_implementations"
+                    }, { "LSP Definitions", "", ":Telescope lsp_definitions" },
+                    {
+                        "LSP Type Definitions", "",
+                        ":Telescope lsp_type_definitions"
+                    }
+                })
+            end)
+        end
+    }, {
+    dir = "../../custom/bit-browser/",
+    name = "bit-browser",
+    enabled = true,
+    dependencies = { "command-palette" },
+    config = function(_, _)
+        local bitbrowser = require("bit-browser")
+        vim.keymap.set("n", "n", bitbrowser.next)
+        vim.keymap.set("n", "N", bitbrowser.prev)
+        vim.keymap.set("n", "sne", function()
+            bitbrowser.set_target(1);
+            bitbrowser.next()
+        end)
+        vim.keymap.set("n", "snw", function()
+            bitbrowser.set_target(2);
+            bitbrowser.next()
+        end)
+        vim.keymap.set("n", "sni", function()
+            bitbrowser.set_target(3);
+            bitbrowser.next()
+        end)
+        vim.keymap.set("n", "snd", function()
+            bitbrowser.set_target(4);
+            bitbrowser.next()
+        end)
+        vim.keymap.set("n", "sns", function()
+            bitbrowser.set_target(5);
+            bitbrowser.next()
+        end)
+        vim.keymap.set("n", "sng", function()
+            bitbrowser.set_target(6);
+            bitbrowser.next()
+        end)
+    end
+}, {
+    dir = "../custom/save-formatter",
+    name = "save-formatter",
+    dependencies = { "nvim-telescope/telescope.nvim", "command-palette" },
+    enabled = true,
+    config = function(_, _)
+        local formatter = require("save-formatter")
+        formatter.setup()
+        vim.keymap.set("n", "Sw",
+            function() vim.api.nvim_exec("w", true) end)
+        local palette = require("command-palette")
+
+        palette.add({
+            {
+                "Save Formatter", "Automatic formatting on save", formatter
+                .picker }
+        })
+    end
+}
+}

+ 56 - 0
.config/nvim/lua/plugins/completion.lua

@@ -0,0 +1,56 @@
+return {
+    "hrsh7th/nvim-cmp",
+    dependencies = {
+        "hrsh7th/cmp-nvim-lsp", "hrsh7th/cmp-buffer", "hrsh7th/cmp-path",
+        "hrsh7th/cmp-cmdline", "hrsh7th/cmp-nvim-lua", "hrsh7th/cmp-calc",
+        "hrsh7th/cmp-nvim-lsp-signature-help"
+    },
+    enabled = true,
+    lazy = false,
+    config = function(_, _)
+        local cmp = require("cmp")
+        local mapping = {
+            ["<Tab>"] = function(fallback)
+                if cmp.visible() then
+                    cmp.select_next_item(
+                        { behavior = cmp.SelectBehavior.Select })
+                else
+                    fallback()
+                end
+            end,
+            ["<S-Tab>"] = function(fallback)
+                if cmp.visible() then
+                    cmp.select_prev_item(
+                        { behavior = cmp.SelectBehavior.Select })
+                else
+                    fallback()
+                end
+            end,
+            ["<CR>"] = function(fallback)
+                if cmp.visible() and cmp.get_active_entry() then
+                    cmp.confirm({ behavior = cmp.ConfirmBehavior.Replace })
+                else
+                    fallback()
+                end
+            end
+        }
+        cmp.setup({
+            snippet = {},
+            mapping = mapping,
+            sources = cmp.config.sources({ { name = "nvim_lsp" } }, {
+                { name = "buffer" }, { name = "nvim_lua" }, { name = "calc" },
+                { name = "nvim_lsp_signature_help" }, { name = "path" }
+            })
+        })
+        cmp.setup.cmdline("/", {
+            mapping = cmp.mapping.preset.cmdline(),
+            sources = { { name = "buffer" } }
+        })
+        cmp.setup.cmdline(":", {
+            mapping = cmp.mapping.preset.cmdline(),
+            sources = cmp.config.sources({ { name = "path" } }, {
+                { name = "cmdline", option = { ignore_cmds = { "Man", "!" } } }
+            })
+        })
+    end
+}

+ 80 - 0
.config/nvim/lua/plugins/floatingterminal.lua

@@ -0,0 +1,80 @@
+return {
+    {
+        "voldikss/vim-floaterm",
+        enabled = true,
+        lazy = false,
+        config = function()
+            -- Floaterm config
+            vim.g.floaterm_autoinsert = true
+            vim.g.floaterm_autohide = 2
+            vim.g.floaterm_autoclose = 1
+            vim.g.floaterm_borderchars = "-¦-¦⌌⌍⌏⌎"
+            vim.g.floaterm_opener = "vsplit"
+            -- Config for interacting with terminals
+            vim.g.floaterm_lastused = ""
+            local term_group = vim.api.nvim_create_augroup("terminal",
+                { clear = true })
+            local terminal_callback = function()
+                vim.wo.colorcolumn = tostring(-1)
+                vim.opt.stc = ""
+                vim.b.number = false
+                vim.b.relativenumber = false
+                vim.b.winfixwidth = false
+            end
+            vim.api.nvim_create_autocmd({ "TermOpen" }, {
+                pattern = { "*" },
+                group = term_group,
+                callback = terminal_callback
+            })
+            vim.api.nvim_create_autocmd({ "BufWinEnter", "WinEnter" }, {
+                pattern = { "term://*" },
+                group = term_group,
+                callback = function()
+                    terminal_callback();
+                    vim.cmd(":startinsert");
+                end
+            })
+            vim.api.nvim_create_autocmd({ "BufEnter" }, {
+                pattern = { "*" },
+                group = term_group,
+                callback = function()
+                    vim.defer_fn(function()
+                        vim.schedule(function()
+                            if (vim.bo.filetype ~= "floaterm") then
+                                vim.cmd(":FloatermHide " ..
+                                    vim.g.floaterm_lastused)
+                            end
+                        end)
+                    end, 100)
+                end
+            })
+            -- Configure eight homerow terminals
+            function MakeTerm(shortcut, name, command, options)
+                vim.cmd(":nnoremap " .. shortcut ..
+                    " :lua vim.g.floaterm_lastused='" .. name ..
+                    "'; vim.api.nvim_exec2(\"FloatermShow " .. name ..
+                    "\", {})<CR>")
+                vim.cmd(":FloatermNew --name=" .. name .. " --title=" .. name ..
+                    " --silent --titleposition=left " .. options ..
+                    " /bin/zsh -c \"while true; do; " .. command ..
+                    "; done;\"")
+            end
+
+            MakeTerm("stt", "Alpha", "clear; zsh", "--width=1.0 --height=0.99")
+            MakeTerm("sts", "Beta", "clear; zsh", "--width=1.0 --height=0.99")
+            MakeTerm("str", "Gamma", "clear; zsh", "--width=1.0 --height=0.99")
+            MakeTerm("sta", "Delta", "clear; zsh", "--width=1.0 --height=0.99")
+            MakeTerm("stn", "Epsilon", "clear; zsh", "--width=80 --height=40")
+            MakeTerm("ste", "Zeta", "clear; zsh", "--width=80 --height=40")
+            MakeTerm("sti", "Eta", "lazydocker", "--width=2.0 --height=2.0")
+            MakeTerm("sto", "Theta", "lazygit", "--width=2.0 --height=2.0")
+            -- Keymaps
+            vim.keymap.set("t", "<Esc><Esc>", "<C-\\><C-n>:FloatermHide<CR>")
+            vim.keymap.set("t", "<Esc><Space>", "<Esc>")
+            vim.keymap.set("t", "<C-S-t>", "<C-\\><C-n>")
+            vim.keymap.set("t", "<S-Space>", "<Esc>")
+            vim.keymap.set("t", "<A-up>", "<C-\\><C-n>:FloatermHide<CR>")
+            vim.keymap.set("t", "<A-down>", "<C-\\><C-n>:FloatermNext<CR>")
+        end
+    }
+}

+ 101 - 0
.config/nvim/lua/plugins/git.lua

@@ -0,0 +1,101 @@
+return {
+    {
+        "lewis6991/gitsigns.nvim",
+        enabled = true,
+        lazy = false,
+        dependencies = { "nvim-telescope/telescope.nvim" },
+        config = function(_, opts)
+            local gitsigns = require("gitsigns")
+            gitsigns.setup {
+                diff_opts = {
+                    internal = true,
+                    linematch = 1,
+                    algorithm = "minimal"
+                },
+                signcolumn = true,
+                numhl = false,
+                linehl = false,
+                max_file_length = 50000,
+                word_diff = false,
+                show_deleted = false,
+                auto_attach = true,
+                attach_to_untracked = true
+            }
+
+            local pickers = require("telescope.pickers")
+            local actions = require("telescope.actions")
+            local action_state = require("telescope.actions.state")
+            local finders = require("telescope.finders")
+            local conf = require("telescope.config").values
+            local entry_display = require("telescope.pickers.entry_display")
+
+            local open_picker = function(title, command)
+                local displayer = entry_display.create({
+                    separator = " ▏",
+                    items = {
+                        { width = 16 }, { width = 64 }, { width = 24 },
+                        { remaining = true }
+                    }
+                })
+                local branches = vim.split(vim.fn.system(
+                        "git branch --list --sort committerdate --format '%(refname) ||!|| %(committerdate:relative) ||!|| branch: %(refname:short) ||!|| %(authorname) ||!|| %(subject)' | tac"),
+                    "\n")
+                local commits = vim.split(vim.fn.system(
+                        "git log --branches=\\* --pretty='format:%H ||!|| %cr ||!|| %(decorate:prefix=,suffix=,separator= ) ||!|| %an ||!|| %s'"),
+                    "\n")
+                local results = {}
+                for _, v in pairs(branches) do
+                    if string.len(v) > 10 then
+                        table.insert(results, v)
+                    end
+                end
+                for _, v in pairs(commits) do
+                    if string.len(v) > 10 then
+                        table.insert(results, v)
+                    end
+                end
+                pickers.new(opts, {
+                    prompt_title = title,
+                    finder = finders.new_table({
+                        results = results,
+                        entry_maker = function(entry)
+                            local s = vim.split(entry, "||!||")
+                            return {
+                                value = s[1],
+                                display = function()
+                                    return displayer({
+                                        { s[2] }, { s[3] }, { s[4] }, { s[5] }
+                                    })
+                                end,
+                                ordinal = string.format("%s %s", s[3], s[5])
+                            }
+                        end
+                    }),
+                    sorter = conf.generic_sorter(),
+                    attach_mappings = function(prompt_bufnr, _)
+                        actions.select_default:replace(function()
+                            actions.close(prompt_bufnr)
+                            local hash = action_state.get_selected_entry().value
+                            if command == "base" then
+                                vim.api.nvim_exec(
+                                    ":Gitsigns change_base " .. hash .. " true",
+                                    true)
+                            elseif command == "diff" then
+                                vim.api.nvim_exec(":Gitsigns diffthis " .. hash,
+                                    true)
+                            end
+                        end)
+                        return true
+                    end
+                }):find()
+            end
+            vim.keymap.set("n", "Sgd",
+                function()
+                    open_picker("Gitsigns Diff", "diff")
+                end)
+            vim.keymap.set("n", "Sgb", function()
+                open_picker("Gitsigns Change Base", "base")
+            end)
+        end
+    }
+}

+ 7 - 0
.config/nvim/lua/plugins/lint.lua

@@ -0,0 +1,7 @@
+return {
+    "mfussenegger/nvim-lint",
+    dependencies = { "williamboman/mason.nvim" },
+    enabled = true,
+    lazy = false,
+    config = function(_, _) end
+}

+ 45 - 0
.config/nvim/lua/plugins/lsp.lua

@@ -0,0 +1,45 @@
+return {
+    {
+        "neovim/nvim-lspconfig",
+        enabled = true,
+        lazy = false,
+        dependencies = { "williamboman/mason-lspconfig.nvim" },
+        config = function(_, _)
+            -- Install and configure servers
+            require("mason").setup()
+            require("mason-lspconfig").setup({
+                ensure_installed = {
+                    "arduino_language_server", "basedpyright", "bashls", "clangd",
+                    "cssls", "denols", "gopls", "html", "jsonls",
+                    "kotlin_language_server", "lemminx", "lua_ls", "marksman",
+                    "mypy", "ruff_lsp", "rust_analyzer", "sqlls", "taplo",
+                    "terraformls", "tsserver", "yamlls"
+                }
+            })
+            -- Configuration on attach
+            vim.api.nvim_create_autocmd("LspAttach", {
+                group = vim.api.nvim_create_augroup("UserLspConfig", {}),
+                callback = function(_)
+                    vim.keymap.set("n", "SR", vim.lsp.buf.rename)
+                    vim.keymap.set("n", "Sx", vim.lsp.buf.code_action)
+                    vim.keymap.set("n", "SI", function()
+                        vim.lsp.inlay_hint.enable(
+                            not vim.lsp.inlay_hint.is_enabled())
+                    end)
+                    vim.keymap.set("n", "<Space>", vim.lsp.buf.hover)
+                end
+            })
+        end
+    }, {
+    "williamboman/mason-lspconfig.nvim",
+    enabled = true,
+    lazy = false,
+    automatic_installation = true,
+    dependencies = { "williamboman/mason.nvim" }
+}, {
+    "williamboman/mason.nvim",
+    enabled = true,
+    lazy = false,
+    build = ":MasonUpdate"
+}
+}

+ 10 - 0
.config/nvim/lua/plugins/proj-conf.lua

@@ -0,0 +1,10 @@
+return {
+    dir = "../custom/proj-conf",
+    name = "proj-conf",
+    dependencies = { "neovim/nvim-lspconfig", "hrsh7th/nvim-cmp",
+        "mfussenegger/nvim-lint", "command-palette",
+        "nvim-telescope/telescope.nvim" },
+    enabled = true,
+    lazy = false,
+    config = function(_, _) require("proj-conf").setup() end
+}

+ 5 - 0
.config/nvim/lua/plugins/spell.lua

@@ -0,0 +1,5 @@
+return {
+    "psliwka/vim-dirtytalk",
+    build = ":DirtytalkUpdate",
+    config = function() vim.opt.spelllang = { "en_us", "programming" } end
+}

+ 93 - 0
.config/nvim/lua/plugins/style.lua

@@ -0,0 +1,93 @@
+return {
+    {
+        dir = "../custom/jonathandarker",
+        name = "jonathandarker",
+        lazy = false,
+        enabled = true,
+        config = function()
+            vim.cmd.colorscheme("jonathandarker")
+            vim.defer_fn(function()
+                vim.schedule(function()
+                    vim.cmd.colorscheme("jonathandarker")
+                end)
+            end, 100)
+            vim.opt.list = true
+            vim.opt.fillchars = "horiz:-," .. "horizup:-," .. "horizdown:-," ..
+                "vert:¦," .. "verthoriz:¦," ..
+                "vertleft:¦," .. "vertright:¦," ..
+                "eob:⠀"
+            vim.opt.listchars = "extends:›," .. "precedes:‹," ..
+                "tab:\\ ," .. "nbsp:·," .. "trail:·," ..
+                "space:·"
+        end
+    }, {
+    dir = "../custom/status-beast",
+    name = "status-beast",
+    dependencies = { "lewis6991/gitsigns.nvim", "bit-browser" },
+    enabled = true,
+    lazy = false,
+    config = function()
+        require("status-beast").setup()
+        vim.diagnostic.config({
+            virtual_text = false,
+            update_in_insert = true
+        })
+    end
+}, {
+    dir = "../custom/jxdash",
+    name = "jxdash",
+    enabled = true,
+    lazy = false,
+    config = function()
+        require("jxdash").setup()
+    end
+}, {
+    "norcalli/nvim-colorizer.lua",
+    enabled = true,
+    lazy = false,
+    config = function()
+        require("colorizer").setup({ "*" }, {
+            mode = "background",
+            RGB = true,
+            RRGGBB = true,
+            RRGGBBAA = true,
+            names = false,
+            rgb_fn = false,
+            hsl_fn = false,
+            css = false,
+            css_fn = false
+        })
+    end
+}, {
+    "lukas-reineke/virt-column.nvim",
+    enabled = true,
+    lazy = false,
+    config = function()
+        vim.opt.colorcolumn = tostring(80 + 1)
+        local cc_group = vim.api.nvim_create_augroup("colorcolumn",
+            { clear = true })
+        local filetype_colorcolumn_map = {
+            python = 88,
+            kotlin = 100,
+            julia = 92
+        }
+        vim.api.nvim_create_autocmd({ "FileType" }, {
+            pattern = { "*" },
+            group = cc_group,
+            callback = function(event)
+                local filetype = vim.bo[event.buf].filetype
+                local colorcolumn = filetype_colorcolumn_map[filetype]
+                if colorcolumn == nil then
+                    colorcolumn = 80
+                end
+                for _, w in pairs(vim.api.nvim_list_wins()) do
+                    if vim.api.nvim_win_get_buf(w) == event.buf then
+                        vim.wo[w].colorcolumn = tostring(colorcolumn + 1)
+                    end
+                end
+            end
+        })
+        require("virt-column").setup({ char = "⁚" })
+    end
+}
+}

+ 83 - 0
.config/nvim/lua/plugins/telescope.lua

@@ -0,0 +1,83 @@
+return {
+    {
+        "nvim-telescope/telescope.nvim",
+        enabled = true,
+        lazy = false,
+        cmd = "Telescope",
+        dependencies = {
+            "nvim-lua/plenary.nvim", "nvim-telescope/telescope-ui-select.nvim"
+        },
+        config = function(_, _)
+            local builtin = require("telescope.builtin")
+            require("telescope").setup({
+                extensions = {
+                    ["ui-select"] = { require("telescope.themes").get_dropdown() }
+                },
+                defaults = {
+                    ["borderchars"] = {
+                        "-", "¦", "-", "¦", "⌌", "⌍", "⌏", "⌎"
+                    },
+                    layout_strategy = "horizontal",
+                    layout_config = {
+                        horizontal = { width = { padding = 0 }, height = 0.99 }
+                    },
+                    cache_picker = {
+                        num_pickers = 100,
+                        limit_entries = 100,
+                        ignore_empty_prompt = true
+                    }
+                },
+                pickers = {
+                    live_grep = {
+                        additional_args = function(opts)
+                            return { "--hidden", "--glob=!**/.git/*" }
+                        end
+                    }
+                }
+            })
+            vim.keymap.set("n", "sf", function()
+                require("telescope").extensions.file_browser.file_browser({
+                    select_buffer = true,
+                    grouped = true,
+                    no_ignore = true,
+                    hidden = true,
+                    respect_gitignore = false,
+                    path = vim.fn.expand("%:p:h")
+                })
+            end, {})
+            vim.keymap.set("n", "ss", builtin.resume)
+            vim.keymap.set("n", "sS", builtin.pickers)
+            vim.keymap.set("n", "sa", builtin.find_files)
+            vim.keymap.set("n", "sg", builtin.git_files)
+            vim.keymap.set("n", "si", builtin.live_grep)
+            vim.keymap.set("n", "sb", builtin.buffers)
+            vim.keymap.set("n", "sj", builtin.jumplist)
+            vim.keymap.set("n", "sld", builtin.lsp_definitions)
+            vim.keymap.set("n", "slt", builtin.lsp_type_definitions)
+            vim.keymap.set("n", "slr", builtin.lsp_references)
+            vim.keymap.set("n", "sli", builtin.lsp_implementations)
+            vim.keymap.set("n", "sls", builtin.lsp_dynamic_workspace_symbols)
+            require("telescope").load_extension("ui-select")
+            require("telescope").load_extension("file_browser")
+        end
+    }, {
+    "nvim-telescope/telescope-file-browser.nvim",
+    dependencies = { "nvim-telescope/telescope.nvim" },
+    enabled = true,
+    lazy = false,
+    config = function(_, _)
+        require("telescope").setup({
+            extensions = {
+                file_browser = {
+                    respect_gitignore = false,
+                    hidden = { file_browser = true, folder_browser = true },
+                    hijack_netrw = true,
+                    display_stat = { date = false, size = true, mode = false },
+                    mappings = {}
+                }
+            }
+        })
+        require("telescope").load_extension("file_browser")
+    end
+}
+}

+ 75 - 0
.config/nvim/lua/plugins/text-objects.lua

@@ -0,0 +1,75 @@
+return {
+    {
+        "kylechui/nvim-surround",
+        config = function() require("nvim-surround").setup({}) end
+        -- Surround selection / text objects with characters
+        -- Surround a word in single quotes: viwS'
+        -- Visual mode: S
+        -- Normal mode: ys
+        -- Surrounds: ( { [ < ' " [t]ag [f]unction
+    }, {
+    "tpope/vim-commentary",
+    enabled = true,
+    lazy = false
+    -- Toggle line comments
+    -- Normal mode: gcc
+    -- Visual mode: gc
+}, {
+    "nvim-treesitter/nvim-treesitter-textobjects",
+    enabled = true,
+    lazy = false,
+    dependencies = { "nvim-treesitter/nvim-treesitter" },
+    config = function()
+        require("nvim-treesitter.configs").setup({
+            textobjects = {
+                select = {
+                    enable = true,
+                    lookahead = true,
+                    keymaps = {
+                        ["af"] = "@function.outer",
+                        ["if"] = "@function.inner",
+                        ["ac"] = "@class.outer",
+                        ["ic"] = "@class.inner",
+                        ["ap"] = "@parameter.outer",
+                        ["ip"] = "@parameter.inner",
+                        ["aa"] = "@parameter.outer",
+                        ["ia"] = "@parameter.inner",
+                        ["al"] = "@loop.outer",
+                        ["il"] = "@loop.inner",
+                        ["at"] = "@attribute.outer",
+                        ["it"] = "@attribute.inner",
+                        ["a="] = "@assignment.outer",
+                        ["i="] = "@assignment.inner",
+                        ["ab"] = "@block.outer",
+                        ["ib"] = "@block.inner"
+                    },
+                    include_surrounding_whitespace = true
+                },
+                swap = {
+                    enable = true,
+                    swap_next = {
+                        ["csf"] = "@function.inner",
+                        ["csc"] = "@class.inner",
+                        ["csp"] = "@parameter.inner",
+                        ["csa"] = "@parameter.inner",
+                        ["csl"] = "@loop.inner",
+                        ["cst"] = "@attribute.inner",
+                        ["cs="] = "@assignment.inner",
+                        ["csb"] = "@block.inner"
+                    },
+                    swap_previous = {
+                        ["cSf"] = "@function.inner",
+                        ["cSc"] = "@class.inner",
+                        ["cSp"] = "@parameter.inner",
+                        ["cSa"] = "@parameter.inner",
+                        ["cSl"] = "@loop.inner",
+                        ["cSt"] = "@attribute.inner",
+                        ["cS="] = "@assignment.inner",
+                        ["cSb"] = "@block.inner"
+                    }
+                }
+            }
+        })
+    end
+}
+}

+ 47 - 0
.config/nvim/lua/plugins/treesitter.lua

@@ -0,0 +1,47 @@
+return {
+    {
+        "nvim-treesitter/nvim-treesitter",
+        enabled = true,
+        lazy = false,
+        config = function(_, _)
+            local api = require("nvim-treesitter.configs")
+            api.setup({
+                ensure_installed = "all",
+                sync_install = false,
+                auto_install = true,
+                highlight = {
+                    enable = true,
+                    additional_vim_regex_highlighting = false
+                }
+            })
+            vim.opt.foldmethod = "expr"
+            vim.opt.foldexpr = "nvim_treesitter#foldexpr()"
+        end,
+        build = function()
+            require("nvim-treesitter.install").update({ with_sync = true })
+        end
+    }, {
+    "nvim-treesitter/nvim-treesitter-context",
+    enabled = true,
+    lazy = false,
+    dependencies = { "nvim-treesitter/nvim-treesitter" },
+    config = function(_, _)
+        require("treesitter-context").setup({
+            enable = true,
+            max_lines = 5,
+            min_window_height = 0,
+            line_numbers = true,
+            multiline_threshold = 20,
+            trim_scope = "outer",
+            mode = "cursor",
+            zindex = 20,
+            on_attach = nil
+        })
+        vim.api.nvim_set_hl(0, "TreesitterContextSeparator",
+            { link = "WinSeparator" })
+        vim.keymap.set("n", "sc", function()
+            require("treesitter-context").go_to_context(vim.v.count1)
+        end, { silent = true })
+    end
+}
+}

+ 11 - 0
.config/zsh/.zshrc

@@ -81,6 +81,17 @@ else
   eval `keychain --eval --quiet id_rsa`
 fi
 
+################################################################################
+# Aliases
+################################################################################
+
+# Redirect Neovim when running ZSH in Vim's Floaterm
+if command -v floaterm &> /dev/null
+then
+    alias n="floaterm"
+    alias nvim="floaterm"
+fi
+
 ################################################################################
 # fzf
 ################################################################################

+ 5 - 0
.github/README.md

@@ -51,6 +51,11 @@ simple terminal UI for both docker and docker-compose.
 Configuration for [lazygit](https://github.com/jesseduffield/lazygit/), a simple
 terminal UI for git commands.
 
+### [nvim (`~/.config/nvim/`)](./.config/nvim/)
+
+Configuration for [Neovim](https://neovim.io/), a hyperextensible Vim-based text
+editor.
+
 ### [prettier (`~/.config/prettier/`)](./.config/prettier/)
 
 Configuration for [Prettier](http://prettier.io), an opinionated code formatter.