nixos-dotfiles

nixos-dotfiles

https://git.tonybtw.com/nixos-dotfiles.git git://git.tonybtw.com/nixos-dotfiles.git

Initial commit.

Commit
6aa5cfb9bcb7b9261cde89eeb953c4abf20d92bc
Author
tonybanters <tonybanters@gmail.com>
Date
2026-01-26 08:26:42

Diff

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..e033bc6
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+lazy-lock.json
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..1779e97
--- /dev/null
+++ b/README.md
@@ -0,0 +1,117 @@
+# Neovim Keybinds Documentation
+
+This document provides a simple and organized overview of all the custom keybinds defined in my Neovim configuration.
+
+## General Keybinds
+
+| Mode | Key             | Action                                                                                      |
+|------|-----------------|---------------------------------------------------------------------------------------------|
+| `n`  | `<leader>cd`    | Open Ex mode (`:Ex`)                                                                        |
+| `n`  | `J`             | Join lines while keeping the cursor in place                                                |
+| `n`  | `<C-d>`         | Scroll half-page down and keep the cursor centered                                          |
+| `n`  | `<C-u>`         | Scroll half-page up and keep the cursor centered                                            |
+| `n`  | `n`             | Move to next search result and keep it centered                                             |
+| `n`  | `N`             | Move to previous search result and keep it centered                                         |
+| `n`  | `Q`             | Disable Ex mode                                                                             |
+| `n`  | `<C-k>`         | Jump to next quickfix entry and keep it centered                                            |
+| `n`  | `<C-j>`         | Jump to previous quickfix entry and keep it centered                                        |
+| `n`  | `<leader>k`     | Jump to next location entry and keep it centered                                            |
+| `n`  | `<leader>j`     | Jump to previous location entry and keep it centered                                        |
+| `i`  | `<C-c>`         | Exit insert mode (acts like `Esc`)                                                          |
+| `n`  | `<leader>x`     | Make current file executable (`chmod +x`)                                                   |
+| `n`  | `<leader>u`     | Toggle Undotree                                                                             |
+| `n`  | `<leader>rl`    | Reload the Neovim config (`~/.config/nvim/init.lua`)                                        |
+| `n`  | `<leader><leader>` | Source the current file (`:so`)                                                          |
+
+---
+
+## Visual Mode Keybinds
+
+| Mode | Key             | Action                                                                                      |
+|------|-----------------|---------------------------------------------------------------------------------------------|
+| `v`  | `J`             | Move selected block down                                                                    |
+| `v`  | `K`             | Move selected block up                                                                      |
+| `x`  | `<leader>p`     | Paste without overwriting clipboard                                                         |
+| `v`  | `<leader>y`     | Yank into system clipboard (even on SSH)                                                    |
+
+---
+
+## Linting and Formatting
+
+| Mode | Key             | Action                                                                                      |
+|------|-----------------|---------------------------------------------------------------------------------------------|
+| `n`  | `<leader>cc`    | Run `php-cs-fixer` to lint and format PHP files                                             |
+| `n`  | `<F3>`          | Format code (`LSP`)                                                                         |
+
+---
+
+## Telescope Keybinds
+
+| Mode | Key             | Action                                                                                      |
+|------|-----------------|---------------------------------------------------------------------------------------------|
+| `n`  | `<leader>ff`    | Find files                                                                                  |
+| `n`  | `<leader>fg`    | Find git-tracked files                                                                      |
+| `n`  | `<leader>fo`    | Open recent files                                                                           |
+| `n`  | `<leader>fq`    | Open quickfix list                                                                          |
+| `n`  | `<leader>fh`    | Open help tags                                                                              |
+| `n`  | `<leader>fb`    | Open buffer list                                                                            |
+| `n`  | `<leader>fs`    | Grep current string                                                                         |
+| `n`  | `<leader>fc`    | Grep instances of the current file name without the extension                               |
+| `n`  | `<leader>fi`    | Find files in Neovim configuration directory (`~/.config/nvim/`)                            |
+
+---
+
+## Harpoon Integration
+
+| Mode | Key             | Action                                                                                      |
+|------|-----------------|---------------------------------------------------------------------------------------------|
+| `n`  | `<leader>a`     | Add current file to Harpoon list                                                            |
+| `n`  | `<C-e>`         | Toggle Harpoon quick menu                                                                   |
+| `n`  | `<leader>fl`    | Open Harpoon window with Telescope                                                          |
+| `n`  | `<C-p>`         | Go to previous Harpoon mark                                                                 |
+| `n`  | `<C-n>`         | Go to next Harpoon mark                                                                     |
+
+---
+
+## LSP Keybinds
+
+| Mode      | Key        | Action                                                                                      |
+|-----------|------------|---------------------------------------------------------------------------------------------|
+| `n`       | `K`        | Show hover information                                                                      |
+| `n`       | `gd`       | Go to definition                                                                            |
+| `n`       | `gD`       | Go to declaration                                                                           |
+| `n`       | `gi`       | Go to implementation                                                                        |
+| `n`       | `go`       | Go to type definition                                                                       |
+| `n`       | `gr`       | Show references                                                                             |
+| `n`       | `gs`       | Show signature help                                                                         |
+| `n`       | `gl`       | Show diagnostics in a floating window                                                       |
+| `n`       | `<F2>`     | Rename symbol                                                                               |
+| `n`, `x`  | `<F3>`     | Format code asynchronously                                                                 |
+| `n`       | `<F4>`     | Show code actions                                                                           |
+
+---
+
+## Miscellaneous
+
+| Mode | Key             | Action                                                                                      |
+|------|-----------------|---------------------------------------------------------------------------------------------|
+| `n`  | `<leader>dg`    | Run `DogeGenerate` (comment documentation generation)                                       |
+| `n`  | `<leader>s`     | Replace all instances of the word under the cursor on the current line                      |
+
+---
+
+# LSP servers:
+
+I am migrating my lsp config to /lua/plugins/lsp.lua because nvim v0.11 allows a very minimal debloated way to setup language server protocols. 
+
+Below is a running list of what and how to install the lsp's that are going to be configured in this build. I will avoid mason for now because I think its better to have full control over your system, and not outsource it to mason. Just uncommonet `return {` in /plugins/lsp.lua from the original lspconfig if you want to go that route.
+
+1. { lua-language-server } 
+  - refer to distro ( pacman -Ss lua-language-server )
+2. { css-language-server --studio, html-language-server }
+  - npm install -g vscode-langservers-extracted
+3. { intelephense }
+  - npm install -g intelephense
+4. { typescript-language-server }
+  - npm install -g typescript-language-server typescript
+
diff --git a/after/ftplugin/goon.lua b/after/ftplugin/goon.lua
new file mode 100644
index 0000000..2059624
--- /dev/null
+++ b/after/ftplugin/goon.lua
@@ -0,0 +1,2 @@
+vim.bo.commentstring = "// %s"
+vim.bo.comments = "s:/*,m: *,ex:*/,://"
diff --git a/after/ftplugin/jsonc.lua b/after/ftplugin/jsonc.lua
new file mode 100644
index 0000000..e1833b8
--- /dev/null
+++ b/after/ftplugin/jsonc.lua
@@ -0,0 +1,9 @@
+local set = vim.opt_local
+
+set.shiftwidth = 2
+set.tabstop = 2
+set.softtabstop = 2
+set.expandtab = true
+
+set.number = true
+set.relativenumber = true
diff --git a/after/ftplugin/man.lua b/after/ftplugin/man.lua
new file mode 100644
index 0000000..f21d675
--- /dev/null
+++ b/after/ftplugin/man.lua
@@ -0,0 +1,8 @@
+local set = vim.opt_local
+set.number = true
+set.relativenumber = true
+set.number = true
+set.relativenumber = false
+set.wrap = true
+set.linebreak = true
+set.conceallevel = 0
diff --git a/after/ftplugin/nix.lua b/after/ftplugin/nix.lua
new file mode 100644
index 0000000..6425eda
--- /dev/null
+++ b/after/ftplugin/nix.lua
@@ -0,0 +1,8 @@
+local set = vim.opt_local
+
+set.shiftwidth = 2
+set.tabstop = 2
+set.softtabstop = 2
+set.expandtab = true
+set.number = true
+set.relativenumber = true
diff --git a/after/plugin/colors.lua b/after/plugin/colors.lua
new file mode 100644
index 0000000..e9af665
--- /dev/null
+++ b/after/plugin/colors.lua
@@ -0,0 +1,6 @@
+vim.cmd.colorscheme("tokyonight")
+vim.cmd("hi Directory guibg=NONE")
+vim.cmd("hi SignColumn guibg=NONE")
+vim.api.nvim_set_hl(0, "Normal", { bg = "none" })
+vim.api.nvim_set_hl(0, "NormalFloat", { bg = "none" })
+vim.api.nvim_set_hl(0, "LineNr", { bg = "none" })
diff --git a/after/plugin/completion.lua b/after/plugin/completion.lua
new file mode 100644
index 0000000..da77d42
--- /dev/null
+++ b/after/plugin/completion.lua
@@ -0,0 +1,27 @@
+local cmp = require("cmp")
+
+cmp.setup({
+    preselect = cmp.PreselectMode.Item,
+    completion = { completeopt = "menu,menuone,noinsert" },
+    window = { documentation = cmp.config.window.bordered() },
+    mapping = cmp.mapping.preset.insert({
+        ["<CR>"] = cmp.mapping.confirm({ select = false }),
+        ["<C-e>"] = cmp.mapping.abort(),
+        ["<C-Space>"] = cmp.mapping.complete(),
+        ["<C-n>"] = cmp.mapping.select_next_item({ behavior = cmp.SelectBehavior.Select }),
+        ["<C-p>"] = cmp.mapping.select_prev_item({ behavior = cmp.SelectBehavior.Select }),
+        ["<C-f>"] = cmp.mapping.scroll_docs(4),
+        ["<C-u>"] = cmp.mapping.scroll_docs(-4),
+        ["<Tab>"] = cmp.mapping(function(fallback)
+            if cmp.visible() then cmp.select_next_item() else fallback() end
+        end, { "i", "s" }),
+        ["<S-Tab>"] = cmp.mapping(function()
+            if cmp.visible() then cmp.select_prev_item() end
+        end, { "i", "s" }),
+    }),
+    sources = {
+        { name = "nvim_lsp" },
+        { name = "path" },
+        { name = "buffer", keyword_length = 3 },
+    },
+})
diff --git a/after/plugin/harpoon.lua b/after/plugin/harpoon.lua
new file mode 100644
index 0000000..cb0ddfc
--- /dev/null
+++ b/after/plugin/harpoon.lua
@@ -0,0 +1,21 @@
+local harpoon = require("harpoon")
+harpoon:setup()
+
+vim.keymap.set("n", "<leader>a", function() harpoon:list():add() end)
+vim.keymap.set("n", "<C-e>", function() harpoon.ui:toggle_quick_menu(harpoon:list()) end)
+vim.keymap.set("n", "<C-p>", function() harpoon:list():prev() end)
+vim.keymap.set("n", "<C-n>", function() harpoon:list():next() end)
+
+vim.keymap.set("n", "<leader>fl", function()
+    local conf = require("telescope.config").values
+    local themes = require("telescope.themes")
+    local file_paths = {}
+    for _, item in ipairs(harpoon:list().items) do
+        table.insert(file_paths, item.value)
+    end
+    require("telescope.pickers").new(themes.get_ivy({ prompt_title = "Working List" }), {
+        finder = require("telescope.finders").new_table({ results = file_paths }),
+        previewer = conf.file_previewer({}),
+        sorter = conf.generic_sorter({}),
+    }):find()
+end, { desc = "Open harpoon window" })
diff --git a/after/plugin/one-liners.lua b/after/plugin/one-liners.lua
new file mode 100644
index 0000000..63ed17e
--- /dev/null
+++ b/after/plugin/one-liners.lua
@@ -0,0 +1,6 @@
+require("lualine").setup({ options = { theme = "tokyonight" } })
+require("nvim-highlight-colors").setup({})
+require("orgmode").setup({
+    org_agenda_files = "~/orgfiles/**/*",
+    org_default_notes_file = "~/orgfiles/refile.org",
+})
diff --git a/after/plugin/telescope.lua b/after/plugin/telescope.lua
new file mode 100644
index 0000000..081311c
--- /dev/null
+++ b/after/plugin/telescope.lua
@@ -0,0 +1,31 @@
+local actions = require("telescope.actions")
+require("telescope").setup({
+    defaults = {
+        mappings = {
+            i = {
+                ["<C-k>"] = actions.move_selection_previous,
+                ["<C-j>"] = actions.move_selection_next,
+                ["<C-q>"] = actions.smart_send_to_qflist + actions.open_qflist,
+            },
+        },
+    },
+})
+
+local builtin = require("telescope.builtin")
+vim.keymap.set("n", "<leader>ff", builtin.find_files)
+vim.keymap.set("n", "<leader>fo", builtin.oldfiles)
+vim.keymap.set("n", "<leader>fq", builtin.quickfix)
+vim.keymap.set("n", "<leader>fh", builtin.help_tags, { desc = "Telescope help tags" })
+vim.keymap.set("n", "<leader>fb", builtin.buffers, { desc = "Telescope buffers" })
+vim.keymap.set("n", "<leader>fg", function()
+    builtin.grep_string({ search = vim.fn.input("Grep > ") })
+end)
+vim.keymap.set("n", "<leader>fc", function()
+    builtin.grep_string({ search = vim.fn.expand("%:t:r") })
+end, { desc = "Find current file" })
+vim.keymap.set("n", "<leader>fs", function()
+    builtin.grep_string({})
+end, { desc = "Find current string" })
+vim.keymap.set("n", "<leader>fi", function()
+    builtin.find_files({ cwd = "~/.config/nvim/" })
+end)
diff --git a/after/plugin/treesitter.lua b/after/plugin/treesitter.lua
new file mode 100644
index 0000000..495ac8c
--- /dev/null
+++ b/after/plugin/treesitter.lua
@@ -0,0 +1,49 @@
+vim.filetype.add({ extension = { goon = "goon" } })
+
+require("nvim-treesitter.parsers").goon = {
+    install_info = {
+        path = "/home/tony/repos/tree-sitter-goon",
+        files = { "src/parser.c" },
+        queries = "queries",
+    },
+    filetype = "goon",
+}
+
+local ts = require("nvim-treesitter")
+
+ts.setup({
+    install_dir = vim.fn.stdpath("data") .. "/site",
+})
+
+local parsers = {
+    "json", "python", "ron", "javascript", "haskell", "d", "query",
+    "typescript", "tsx", "rust", "zig", "php", "yaml", "html", "css",
+    "markdown", "markdown_inline", "bash", "lua", "vim", "vimdoc", "c",
+    "dockerfile", "gitignore", "astro",
+}
+
+vim.api.nvim_create_user_command("TSInstallAll", function()
+    ts.install(parsers)
+end, {})
+
+vim.api.nvim_create_autocmd("FileType", {
+    pattern = "*",
+    callback = function()
+        pcall(vim.treesitter.start)
+    end,
+})
+
+require("nvim-treesitter-textobjects").setup({
+    select = {
+        lookahead = true,
+    },
+})
+
+vim.keymap.set({ "x", "o" }, "af", function()
+    require("nvim-treesitter-textobjects.select").select_textobject("@function.outer", "textobjects")
+end)
+vim.keymap.set({ "x", "o" }, "if", function()
+    require("nvim-treesitter-textobjects.select").select_textobject("@function.inner", "textobjects")
+end)
+
+require("treesitter-context").setup({})
diff --git a/init.lua b/init.lua
new file mode 100644
index 0000000..36a1d08
--- /dev/null
+++ b/init.lua
@@ -0,0 +1,3 @@
+require("config.options")
+require("config.keybinds")
+require("manage").setup()
diff --git a/lua/config/keybinds.lua b/lua/config/keybinds.lua
new file mode 100644
index 0000000..a2979b8
--- /dev/null
+++ b/lua/config/keybinds.lua
@@ -0,0 +1,66 @@
+-- KEYBINDS
+vim.g.mapleader = " "
+vim.keymap.set("n", "<leader>cd", vim.cmd.Ex)
+
+vim.keymap.set("v", "J", ":m '>+1<CR>gv=gv") -- Alt Up/Down in vscode
+vim.keymap.set("v", "K", ":m '<-2<CR>gv=gv")
+
+vim.keymap.set("n", "J", "mzJ`z")       -- Remap joining lines
+vim.keymap.set("n", "<C-d>", "<C-d>zz") -- Keep cursor in place while moving up/down page
+vim.keymap.set("n", "<C-u>", "<C-u>zz")
+vim.keymap.set("n", "n", "nzzzv")       -- center screen when looping search results
+vim.keymap.set("n", "N", "Nzzzv")
+
+-- paste and don't replace clipboard over deleted text
+vim.keymap.set("x", "<leader>p", [["_dP]])
+vim.keymap.set({ "n", "v" }, "<leader>d", [["_d]])
+
+
+-- sometimes in insert mode, control-c doesn't exactly work like escape
+vim.keymap.set("i", "<C-c>", "<Esc>")
+
+-- add binds for Control J/K to scroll thru quickfix list
+vim.keymap.set("n", "<C-j>", "<cmd>cnext<CR>zz")
+vim.keymap.set("n", "<C-k>", "<cmd>cprev<CR>zz")
+
+-- What the heck is Ex mode?
+vim.keymap.set("n", "Q", "<nop>")
+
+vim.keymap.set("n", "<leader>k", "<cmd>lnext<CR>zz")
+vim.keymap.set("n", "<leader>j", "<cmd>lprev<CR>zz")
+
+-- getting Alex off my back :)
+vim.keymap.set("n", "<leader>dg", "<cmd>DogeGenerate<cr>")
+
+-- lint / format php files for LC
+vim.keymap.set("n", "<leader>cc", "<cmd>!php-cs-fixer fix % --using-cache=no<cr>")
+
+-- Replace all instances of whatever is under cursor (on line)
+vim.keymap.set("n", "<leader>s", [[:s/\<<C-r><C-w>\>//gI<Left><Left><Left>]])
+
+-- make file executable
+vim.keymap.set("n", "<leader>x", "<cmd>!chmod +x %<CR>", { silent = true })
+
+-- yank into clipboard even if on ssh
+vim.keymap.set('n', '<leader>y', '<Plug>OSCYankOperator')
+vim.keymap.set('v', '<leader>y', '<Plug>OSCYankVisual')
+
+-- reload without exiting vim
+vim.keymap.set("n", "<leader>rl", "<cmd>source ~/.config/nvim/init.lua<cr>")
+
+vim.keymap.set("n", "<leader>u", vim.cmd.UndotreeToggle)
+
+-- Quickfix list stuff
+vim.keymap.set("n", "<leader>cl", ":cclose<CR>", { silent = true })
+vim.keymap.set("n", "<leader>co", ":copen<CR>", { silent = true })
+vim.keymap.set("n", "<leader>cn", ":cnext<CR>zz")
+vim.keymap.set("n", "<leader>cp", ":cprev<CR>zz")
+vim.keymap.set("n", "<leader>li", ":checkhealth vim.lsp<CR>", { desc = "LSP Info" })
+
+-- run make in current working directory
+vim.keymap.set("n", "<leader>mm", "<cmd>make<CR>")
+
+-- source file
+vim.keymap.set("n", "<leader><leader>", function()
+    vim.cmd("so")
+end)
diff --git a/lua/config/options.lua b/lua/config/options.lua
new file mode 100644
index 0000000..52de0a7
--- /dev/null
+++ b/lua/config/options.lua
@@ -0,0 +1,55 @@
+-- OPTIONS
+local set = vim.opt
+
+--line nums
+set.relativenumber = true
+set.number = true
+
+-- indentation and tabs
+set.tabstop = 4
+set.shiftwidth = 4
+set.autoindent = true
+set.expandtab = true
+
+-- search settings
+set.ignorecase = true
+set.smartcase = true
+
+-- appearance
+set.termguicolors = true
+set.background = "dark"
+set.signcolumn = "yes"
+
+-- cursor line
+set.cursorline = true
+
+-- 80th column
+set.colorcolumn = "80"
+
+-- clipboard
+set.clipboard:append("unnamedplus")
+
+-- backspace
+set.backspace = "indent,eol,start"
+
+-- split windows
+set.splitbelow = true
+set.splitright = true
+
+-- dw/diw/ciw works on full-word
+set.iskeyword:append("-")
+
+-- keep cursor at least 8 rows from top/bot
+set.scrolloff = 8
+
+-- undo dir settings
+set.swapfile = false
+set.backup = false
+set.undodir = os.getenv("HOME") .. "/.vim/undodir"
+set.undofile = true
+
+-- incremental search
+set.incsearch = true
+
+-- faster cursor hold
+set.updatetime = 50
diff --git a/lua/manage.lua b/lua/manage.lua
new file mode 100644
index 0000000..50989f3
--- /dev/null
+++ b/lua/manage.lua
@@ -0,0 +1,86 @@
+---@diagnostic disable: undefined-field
+local M = {}
+local plug_dir = vim.fn.stdpath("data") .. "/plugins"
+
+local function ensure(spec)
+    local repo = type(spec) == "string" and spec or spec[1]
+    local name = repo:match(".+/(.+)$")
+    local path = plug_dir .. "/" .. name
+
+    if not vim.uv.fs_stat(path) then
+        vim.fn.mkdir(plug_dir, "p")
+        local cmd = { "git", "clone", "--depth=1" }
+        if spec.branch then
+            table.insert(cmd, "-b")
+            table.insert(cmd, spec.branch)
+        end
+        table.insert(cmd, "https://github.com/" .. repo)
+        table.insert(cmd, path)
+        print("Installing " .. name .. "...")
+        vim.fn.system(cmd)
+    end
+
+    vim.opt.rtp:append(path)
+    local lua_path = path .. "/lua"
+    if vim.uv.fs_stat(lua_path) then
+        package.path = package.path .. ";" .. lua_path .. "/?.lua;" .. lua_path .. "/?/init.lua"
+    end
+end
+
+function M.setup()
+    for _, spec in ipairs(require("plugin-list")) do
+        ensure(spec)
+    end
+end
+
+function M.update()
+    local handle = vim.uv.fs_scandir(plug_dir)
+    if not handle then return print("No plugins installed") end
+    while true do
+        local name, t = vim.uv.fs_scandir_next(handle)
+        if not name then break end
+        if t == "directory" then
+            print("Updating " .. name .. "...")
+            vim.fn.system({ "git", "-C", plug_dir .. "/" .. name, "pull", "--ff-only" })
+        end
+    end
+    print("Done!")
+end
+
+function M.list()
+    local handle = vim.uv.fs_scandir(plug_dir)
+    if not handle then return print("No plugins installed") end
+    while true do
+        local name, t = vim.uv.fs_scandir_next(handle)
+        if not name then break end
+        if t == "directory" then print(name) end
+    end
+end
+
+function M.clean()
+    local installed = {}
+    local handle = vim.uv.fs_scandir(plug_dir)
+    if handle then
+        while true do
+            local name, t = vim.uv.fs_scandir_next(handle)
+            if not name then break end
+            if t == "directory" then installed[name] = true end
+        end
+    end
+
+    local wanted = {}
+    for _, spec in ipairs(require("plugin-list")) do
+        local repo = type(spec) == "string" and spec or spec[1]
+        wanted[repo:match(".+/(.+)$")] = true
+    end
+
+    for name in pairs(installed) do
+        if not wanted[name] then
+            print("Removing " .. name .. "...")
+            vim.fn.delete(plug_dir .. "/" .. name, "rf")
+        end
+    end
+    print("Done!")
+end
+
+return M
diff --git a/lua/plugin-list.lua b/lua/plugin-list.lua
new file mode 100644
index 0000000..02f3925
--- /dev/null
+++ b/lua/plugin-list.lua
@@ -0,0 +1,22 @@
+return {
+    "nvim-lua/plenary.nvim",
+    "nvim-tree/nvim-web-devicons",
+    { "nvim-treesitter/nvim-treesitter", branch = "main" },
+    { "nvim-treesitter/nvim-treesitter-textobjects", branch = "main" },
+    "nvim-treesitter/nvim-treesitter-context",
+    "hrsh7th/nvim-cmp",
+    "hrsh7th/cmp-nvim-lsp",
+    "hrsh7th/cmp-path",
+    "hrsh7th/cmp-buffer",
+    "nvim-telescope/telescope.nvim",
+    { "ThePrimeagen/harpoon", branch = "harpoon2" },
+    "folke/tokyonight.nvim",
+    "nvim-lualine/lualine.nvim",
+    "brenoprata10/nvim-highlight-colors",
+    "nvim-orgmode/orgmode",
+    "tpope/vim-fugitive",
+    "mbbill/undotree",
+    "ojroques/vim-oscyank",
+    "kkoomen/vim-doge",
+    "captbaritone/better-indent-support-for-php-with-html",
+}
diff --git a/plugin/flterm.lua b/plugin/flterm.lua
new file mode 100644
index 0000000..d766181
--- /dev/null
+++ b/plugin/flterm.lua
@@ -0,0 +1,55 @@
+-- Remap leaving 'terminal mode' to double tap esc
+vim.keymap.set("t", "<esc><esc>", "<c-\\><c-n>")
+
+local state = {
+    floating = {
+        buf = -1,
+        win = -1,
+    }
+}
+
+local function open_floating_terminal(opts)
+    opts = opts or {}
+    local width = opts.width or math.floor(vim.o.columns * 0.8)
+    local height = opts.height or math.floor(vim.o.lines * 0.8)
+
+    local row = math.floor((vim.o.lines - height) / 2)
+    local col = math.floor((vim.o.columns - width) / 2)
+
+    local buf = nil
+    if vim.api.nvim_buf_is_valid(opts.buf) then
+        buf = opts.buf
+    else
+        buf = vim.api.nvim_create_buf(false, true)
+    end
+    if not buf then
+        error("Failed to create buffer")
+    end
+
+    local win = vim.api.nvim_open_win(buf, true, {
+        relative = 'editor',
+        width = width,
+        height = height,
+        row = row,
+        col = col,
+        style = 'minimal',
+        border = 'rounded',
+    })
+
+    return { buf = buf, win = win }
+end
+
+local toggle_terminal = function()
+    if not vim.api.nvim_win_is_valid(state.floating.win) then
+        state.floating = open_floating_terminal({ buf = state.floating.buf });
+        if vim.bo[state.floating.buf].buftype ~= "terminal" then
+            vim.cmd.terminal()
+            vim.cmd("startinsert!")
+        end
+    else
+        vim.api.nvim_win_hide(state.floating.win)
+    end
+end
+
+vim.api.nvim_create_user_command("Flterm", toggle_terminal, {})
+vim.api.nvim_set_keymap('n', '<leader>ft', [[:Flterm<CR>]], { noremap = true, silent = true })
diff --git a/plugin/lsp.lua b/plugin/lsp.lua
new file mode 100644
index 0000000..8bbc49e
--- /dev/null
+++ b/plugin/lsp.lua
@@ -0,0 +1,270 @@
+vim.lsp.config('*', {
+    root_markers = { '.git' },
+})
+
+vim.diagnostic.config({
+    virtual_text  = true,
+    severity_sort = true,
+    float         = {
+        style  = 'minimal',
+        border = 'rounded',
+        source = 'if_many',
+        header = '',
+        prefix = '',
+    },
+    signs         = {
+        text = {
+            [vim.diagnostic.severity.ERROR] = '✘',
+            [vim.diagnostic.severity.WARN]  = '▲',
+            [vim.diagnostic.severity.HINT]  = '⚑',
+            [vim.diagnostic.severity.INFO]  = '»',
+        },
+    },
+})
+
+local orig = vim.lsp.util.open_floating_preview
+---@diagnostic disable-next-line: duplicate-set-field
+function vim.lsp.util.open_floating_preview(contents, syntax, opts, ...)
+    opts            = opts or {}
+    opts.border     = opts.border or 'rounded'
+    opts.max_width  = opts.max_width or 80
+    opts.max_height = opts.max_height or 24
+    opts.wrap       = opts.wrap ~= false
+    return orig(contents, syntax, opts, ...)
+end
+
+vim.api.nvim_create_autocmd('LspAttach', {
+    group = vim.api.nvim_create_augroup('my.lsp', {}),
+    callback = function(args)
+        local client = assert(vim.lsp.get_client_by_id(args.data.client_id))
+        local buf    = args.buf
+        local map    = function(mode, lhs, rhs) vim.keymap.set(mode, lhs, rhs, { buffer = buf }) end
+
+        map('n', 'K', vim.lsp.buf.hover)
+        map('n', 'gd', vim.lsp.buf.definition)
+        map('n', 'gD', vim.lsp.buf.declaration)
+        map('n', 'gi', vim.lsp.buf.implementation)
+        map('n', 'go', vim.lsp.buf.type_definition)
+        map('n', 'gr', vim.lsp.buf.references)
+        map('n', 'gs', vim.lsp.buf.signature_help)
+        map('n', 'gl', vim.diagnostic.open_float)
+        map('n', '<F2>', vim.lsp.buf.rename)
+        map({ 'n', 'x' }, '<F3>', function() vim.lsp.buf.format({ async = true }) end)
+        map('n', '<F4>', vim.lsp.buf.code_action)
+
+        if client:supports_method('textDocument/documentHighlight') then
+            local highlight_augroup = vim.api.nvim_create_augroup('my.lsp.highlight', { clear = false })
+            vim.api.nvim_create_autocmd({ 'CursorHold', 'CursorHoldI' }, {
+                buffer = buf,
+                group = highlight_augroup,
+                callback = vim.lsp.buf.document_highlight,
+            })
+            vim.api.nvim_create_autocmd({ 'CursorMoved', 'CursorMovedI' }, {
+                buffer = buf,
+                group = highlight_augroup,
+                callback = vim.lsp.buf.clear_references,
+            })
+        end
+
+        local excluded_filetypes = { php = true, c = true, cpp = true }
+        if not client:supports_method('textDocument/willSaveWaitUntil')
+            and client:supports_method('textDocument/formatting')
+            and not excluded_filetypes[vim.bo[buf].filetype]
+        then
+            vim.api.nvim_create_autocmd('BufWritePre', {
+                group = vim.api.nvim_create_augroup('my.lsp.format', { clear = false }),
+                buffer = buf,
+                callback = function()
+                    vim.lsp.buf.format({ bufnr = buf, id = client.id, timeout_ms = 1000 })
+                end,
+            })
+        end
+    end,
+})
+local caps = require("cmp_nvim_lsp").default_capabilities()
+vim.lsp.config['luals'] = {
+    cmd = { 'lua-language-server' },
+    filetypes = { 'lua' },
+    root_markers = { { '.luarc.json', '.luarc.jsonc' }, '.git' },
+    capabilities = caps,
+    settings = {
+        Lua = {
+            runtime = { version = 'LuaJIT' },
+            diagnostics = { globals = { 'vim' } },
+            workspace = {
+                checkThirdParty = false,
+                library = vim.api.nvim_get_runtime_file('', true),
+            },
+            telemetry = { enable = false },
+        },
+    },
+}
+
+vim.lsp.config['cssls'] = {
+    cmd = { 'vscode-css-language-server', '--stdio' },
+    filetypes = { 'css', 'scss', 'less' },
+    root_markers = { 'package.json', '.git' },
+    capabilities = caps,
+    settings = {
+        css = { validate = true },
+        scss = { validate = true },
+        less = { validate = true },
+    },
+}
+
+vim.lsp.config['phpls'] = {
+    cmd = { 'intelephense', '--stdio' },
+    filetypes = { 'php' },
+    root_markers = { 'composer.json', '.git' },
+    capabilities = caps,
+    settings = {
+        intelephense = {
+            files = {
+                maxSize = 5000000, -- default 5MB
+            },
+        },
+    },
+}
+
+vim.lsp.config['ts_ls'] = {
+    cmd = { 'typescript-language-server', '--stdio' },
+    filetypes = {
+        'javascript', 'javascriptreact', 'javascript.jsx',
+        'typescript', 'typescriptreact', 'typescript.tsx',
+    },
+    root_markers = { 'package.json', 'tsconfig.json', 'jsconfig.json', '.git' },
+    capabilities = caps,
+    settings = {
+        completions = {
+            completeFunctionCalls = true,
+        },
+    },
+}
+
+vim.lsp.config['zls'] = {
+    cmd = { 'zls' },
+    filetypes = { 'zig', 'zir' },
+    root_markers = { 'zls.json', 'build.zig', '.git' },
+    capabilities = caps,
+    settings = {
+        zls = {
+            enable_build_on_save = true,
+            build_on_save_step = "install",
+            warn_style = false,
+            enable_snippets = true,
+        }
+    }
+}
+
+vim.lsp.config['nil_ls'] = {
+    cmd = { 'nil' },
+    filetypes = { 'nix' },
+    root_markers = { 'flake.nix', 'default.nix', '.git' },
+    capabilities = caps,
+    settings = {
+        ['nil'] = {
+            formatting = {
+                command = { "alejandra" }
+            }
+        }
+    }
+}
+
+vim.lsp.config['rust_analyzer'] = {
+    cmd = { 'rust-analyzer' },
+    filetypes = { 'rust' },
+    root_markers = { 'Cargo.toml', 'rust-project.json', '.git' },
+    capabilities = caps,
+    settings = {
+        ['rust-analyzer'] = {
+            cargo = { allFeatures = true },
+            formatting = {
+                command = { "rustfmt" }
+            },
+        },
+    },
+}
+
+-- C / C++ via clangd
+vim.lsp.config['clangd'] = {
+    cmd = {
+        'clangd',
+        '--background-index',
+        '--clang-tidy',
+        '--header-insertion=never',
+        '--completion-style=detailed',
+        '--query-driver=/nix/store/*-gcc-*/bin/gcc*,/nix/store/*-clang-*/bin/clang*,/run/current-system/sw/bin/cc*',
+    },
+    filetypes = { 'c', 'cpp', 'objc', 'objcpp' },
+    root_markers = { 'compile_commands.json', '.clangd', 'configure.ac', 'Makefile', '.git' },
+    capabilities = caps,
+    init_options = {
+        fallbackFlags = { '-std=c23' }, -- Default to C23
+    },
+}
+
+vim.lsp.config['c3lsp'] = {
+    cmd = { 'c3-lsp' },
+    filetypes = { 'c3' },
+    root_markers = { 'project.json', '.git' },
+    capabilities = caps,
+}
+
+vim.lsp.config['serve_d'] = {
+    cmd = { 'serve-d' },
+    filetypes = { 'd' },
+    root_markers = { 'dub.sdl', 'dub.json', '.git' },
+    capabilities = caps,
+}
+
+vim.lsp.config['jsonls'] = {
+    cmd = { 'vscode-json-languageserver', '--stdio' },
+    filetypes = { 'json', 'jsonc' },
+    root_markers = { 'package.json', '.git', 'config.jsonc' },
+    capabilities = caps,
+}
+
+vim.lsp.config['hls'] = {
+    cmd = { 'haskell-language-server-wrapper', '--lsp' },
+    filetypes = { 'haskell', 'lhaskell' },
+    root_markers = { 'stack.yaml', 'cabal.project', 'package.yaml', '*.cabal', 'hie.yaml', '.git' },
+    capabilities = caps,
+    settings = {
+        haskell = {
+            formattingProvider = 'fourmolu',
+            plugin = {
+                semanticTokens = { globalOn = false }
+            },
+        },
+    },
+}
+
+vim.lsp.config['gopls'] = {
+    cmd = { 'gopls' },
+    filetypes = { 'go', 'gomod', 'gowork', 'gotmpl' },
+    root_markers = { 'go.mod', 'go.work', '.git' },
+    capabilities = caps,
+    settings = {
+        gopls = {
+            analyses = {
+                unusedparams = true,
+            },
+            staticcheck = true,
+        },
+    },
+}
+
+vim.filetype.add({
+    extension = {
+        h = 'c',
+        c3 = 'c3',
+        d = 'd',
+    },
+})
+
+---@diagnostic disable-next-line: invisible
+for name, _ in pairs(vim.lsp.config._configs) do
+    if name ~= '*' then -- Skip the wildcard config
+        vim.lsp.enable(name)
+    end
+end
diff --git a/plugin/quickformat.lua b/plugin/quickformat.lua
new file mode 100644
index 0000000..038dadf
--- /dev/null
+++ b/plugin/quickformat.lua
@@ -0,0 +1,40 @@
+local function reformat_parenthesized_content()
+    local bufnr = vim.api.nvim_get_current_buf()
+    local row = vim.api.nvim_win_get_cursor(0)[1]
+    local line = vim.api.nvim_buf_get_lines(bufnr, row - 1, row, false)[1]
+
+    local inside = line:match("%((.-)%)")
+    if not inside then
+        vim.notify(
+            "No content found inside parentheses",
+            vim.log.levels.ERROR
+        )
+        return
+    end
+
+    local prefix = line:match("^(.-)%(") or ""
+    local suffix = line:match("%)(.*)$") or ""
+
+    local parts = vim.split(inside, ",%s*")
+    if #parts == 0 then
+        vim.notify("No comma-separated content found", vim.log.levels.ERROR)
+        return
+    end
+
+    local new_lines = {}
+    table.insert(new_lines, prefix .. "(")
+    for i, part in ipairs(parts) do
+        if i < #parts then
+            table.insert(new_lines, "        " .. part .. ",")
+        else
+            table.insert(new_lines, "        " .. part)
+        end
+    end
+    table.insert(new_lines, "    )" .. suffix)
+
+    vim.api.nvim_buf_set_lines(bufnr, row - 1, row, false, new_lines)
+end
+
+vim.keymap.set("n", "<leader>qq", function()
+    reformat_parenthesized_content()
+end)
diff --git a/queries/goon/highlights.scm b/queries/goon/highlights.scm
new file mode 100644
index 0000000..893c012
--- /dev/null
+++ b/queries/goon/highlights.scm
@@ -0,0 +1,55 @@
+; Keywords
+"let" @keyword
+"if" @keyword.conditional
+"then" @keyword.conditional
+"else" @keyword.conditional
+"import" @keyword.import
+
+; Literals
+(string) @string
+(string_content) @string
+(escape_sequence) @string.escape
+(number) @number
+(boolean) @boolean
+
+; Identifiers
+(identifier) @variable
+
+; Types
+(type_annotation) @type
+
+; Fields
+(record_field
+  key: (identifier) @property)
+
+(field_access
+  (identifier) @property)
+
+; Functions
+(call_expression
+  function: (identifier) @function.call)
+
+; Operators
+"=" @operator
+":" @punctuation.delimiter
+"?" @operator
+"..." @operator
+"." @punctuation.delimiter
+
+; Punctuation
+"{" @punctuation.bracket
+"}" @punctuation.bracket
+"[" @punctuation.bracket
+"]" @punctuation.bracket
+"(" @punctuation.bracket
+")" @punctuation.bracket
+";" @punctuation.delimiter
+"," @punctuation.delimiter
+
+; Interpolation
+(interpolation
+  "${" @punctuation.special
+  "}" @punctuation.special)
+
+; Comments
+(comment) @comment