commit 7ee1e5bfb467ce1a335a556f7b93fffb568214ac Author: Ray Andrew <4437323+rayandrew@users.noreply.github.com> Date: Sun Jul 30 14:54:58 2023 -0500 initialize diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..cc5457a --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +tt.* +.tests +doc/tags +debug +.repro +foo.* +*.log +data diff --git a/init.lua b/init.lua new file mode 100644 index 0000000..dbf763f --- /dev/null +++ b/init.lua @@ -0,0 +1,3 @@ +local ray = require("rayandrew") + +ray.setup() diff --git a/lazy-lock.json b/lazy-lock.json new file mode 100644 index 0000000..fc53ec0 --- /dev/null +++ b/lazy-lock.json @@ -0,0 +1,47 @@ +{ + "LuaSnip": { "branch": "master", "commit": "e81cbe6004051c390721d8570a4a0541ceb0df10" }, + "bufferline.nvim": { "branch": "main", "commit": "99f0932365b34e22549ff58e1bea388465d15e99" }, + "cellular-automaton.nvim": { "branch": "main", "commit": "679943b8e1e5ef79aaeeaf4b00782c52eb4e928f" }, + "cloak.nvim": { "branch": "main", "commit": "c6a92e2fbc6b931bc9ed0d07e80931c2324e05cb" }, + "cmp-nvim-lsp": { "branch": "main", "commit": "44b16d11215dce86f253ce0c30949813c0a90765" }, + "copilot-cmp": { "branch": "master", "commit": "c2cdb3c0f5078b0619055af192295830a7987790" }, + "copilot.lua": { "branch": "master", "commit": "e48bd7020a98be217d85c006a298656294fd6210" }, + "dressing.nvim": { "branch": "master", "commit": "829bc80400651aea31b03d8fc9a99135512fe67a" }, + "flash.nvim": { "branch": "main", "commit": "967117690bd677cb7b6a87f0bc0077d2c0be3a27" }, + "harpoon": { "branch": "master", "commit": "21f4c47c6803d64ddb934a5b314dcb1b8e7365dc" }, + "indent-blankline.nvim": { "branch": "master", "commit": "4541d690816cb99a7fc248f1486aa87f3abce91c" }, + "lazy.nvim": { "branch": "main", "commit": "3ad55ae678876516156cca2f361c51f7952a924b" }, + "lsp-zero.nvim": { "branch": "v2.x", "commit": "73bc33fe9ad5a1d4501536fdd4755b3aa18c3392" }, + "lualine.nvim": { "branch": "master", "commit": "05d78e9fd0cdfb4545974a5aa14b1be95a86e9c9" }, + "mason-lspconfig.nvim": { "branch": "main", "commit": "e86a4c84ff35240639643ffed56ee1c4d55f538e" }, + "mason-null-ls.nvim": { "branch": "main", "commit": "ae0c5fa57468ac65617f1bf821ba0c3a1e251f0c" }, + "mason.nvim": { "branch": "main", "commit": "fe9e34a9ab4d64321cdc3ecab4ea1809239bb73f" }, + "mini.bufremove": { "branch": "main", "commit": "7821606e35c1ac931b56d8e3155f45ffe76ee7e5" }, + "mini.comment": { "branch": "main", "commit": "877acea5b2a32ff55f808fc0ebe9aa898648318c" }, + "neo-tree.nvim": { "branch": "v3.x", "commit": "981a43adcca25e7ccc3c589902d49f25e4d48ebc" }, + "noice.nvim": { "branch": "main", "commit": "894db25ec726d32047799d4d0a982b701bec453b" }, + "nui.nvim": { "branch": "main", "commit": "9e3916e784660f55f47daa6f26053ad044db5d6a" }, + "null-ls.nvim": { "branch": "main", "commit": "db09b6c691def0038c456551e4e2772186449f35" }, + "nvim-cmp": { "branch": "main", "commit": "c4e491a87eeacf0408902c32f031d802c7eafce8" }, + "nvim-lspconfig": { "branch": "master", "commit": "b6091272422bb0fbd729f7f5d17a56d37499c54f" }, + "nvim-navic": { "branch": "master", "commit": "9c89730da6a05acfeb6a197e212dfadf5aa60ca0" }, + "nvim-spectre": { "branch": "master", "commit": "3ba6edeea1390457caaf73e96ab9c086ff6f90e9" }, + "nvim-treesitter": { "branch": "master", "commit": "1c79da3300951e934f635eaf8703480b57644e7e" }, + "nvim-treesitter-context": { "branch": "master", "commit": "6f8f788738b968f24a108ee599c5be0031f94f06" }, + "nvim-treesitter-textobjects": { "branch": "master", "commit": "9e519b6146512c8e2e702faf8ac48420f4f5deec" }, + "nvim-ts-context-commentstring": { "branch": "main", "commit": "e9062e2dfb9854e6a927370f2d720de354c88524" }, + "nvim-web-devicons": { "branch": "master", "commit": "efbfed0567ef4bfac3ce630524a0f6c8451c5534" }, + "playground": { "branch": "master", "commit": "2b81a018a49f8e476341dfcb228b7b808baba68b" }, + "plenary.nvim": { "branch": "master", "commit": "267282a9ce242bbb0c5dc31445b6d353bed978bb" }, + "refactoring.nvim": { "branch": "master", "commit": "5359e74291164fcaeaaecdea9ba753ad54eb53d0" }, + "rose-pine": { "branch": "main", "commit": "e29002cbee4854a9c8c4b148d8a52fae3176070f" }, + "telescope.nvim": { "branch": "master", "commit": "b6fccfb0f7589a87587875206786daccba62acc3" }, + "todo-comments.nvim": { "branch": "main", "commit": "3094ead8edfa9040de2421deddec55d3762f64d1" }, + "trouble.nvim": { "branch": "main", "commit": "40aad004f53ae1d1ba91bcc5c29d59f07c5f01d3" }, + "undotree": { "branch": "master", "commit": "0e11ba7325efbbb3f3bebe06213afa3e7ec75131" }, + "vim-fugitive": { "branch": "master", "commit": "b3b838d690f315a503ec4af8c634bdff3b200aaf" }, + "vim-illuminate": { "branch": "master", "commit": "a2907275a6899c570d16e95b9db5fd921c167502" }, + "vim-tmux-navigator": { "branch": "master", "commit": "cdd66d6a37d991bba7997d593586fc51a5b37aa8" }, + "which-key.nvim": { "branch": "main", "commit": "7ccf476ebe0445a741b64e36c78a682c1c6118b7" }, + "zen-mode.nvim": { "branch": "main", "commit": "68f554702de63f4b7b6b6d4bcb10178f41a0acc7" } +} \ No newline at end of file diff --git a/lua/rayandrew/autocmds.lua b/lua/rayandrew/autocmds.lua new file mode 100644 index 0000000..8a13f41 --- /dev/null +++ b/lua/rayandrew/autocmds.lua @@ -0,0 +1,96 @@ +-- Taken from +-- https://github.com/LazyVim/LazyVim/blob/566049aa4a26a86219dd1ad1624f9a1bf18831b6/lua/lazyvim/config/autocmds.lua + +local function augroup(name) + return vim.api.nvim_create_augroup("lazyvim_" .. name, { clear = true }) +end + +-- Check if we need to reload the file when it changed +vim.api.nvim_create_autocmd({ "FocusGained", "TermClose", "TermLeave" }, { + group = augroup("checktime"), + command = "checktime", +}) + +-- Highlight on yank +vim.api.nvim_create_autocmd("TextYankPost", { + group = augroup("highlight_yank"), + callback = function() + vim.highlight.on_yank() + end, +}) + +-- resize splits if window got resized +vim.api.nvim_create_autocmd({ "VimResized" }, { + group = augroup("resize_splits"), + callback = function() + vim.cmd("tabdo wincmd =") + end, +}) + +-- go to last loc when opening a buffer +vim.api.nvim_create_autocmd("BufReadPost", { + group = augroup("last_loc"), + callback = function() + local exclude = { "gitcommit" } + local buf = vim.api.nvim_get_current_buf() + if vim.tbl_contains(exclude, vim.bo[buf].filetype) then + return + end + local mark = vim.api.nvim_buf_get_mark(buf, '"') + local lcount = vim.api.nvim_buf_line_count(buf) + if mark[1] > 0 and mark[1] <= lcount then + pcall(vim.api.nvim_win_set_cursor, 0, mark) + end + end, +}) + +-- close some filetypes with +vim.api.nvim_create_autocmd("FileType", { + group = augroup("close_with_q"), + pattern = { + "PlenaryTestPopup", + "help", + "lspinfo", + "man", + "notify", + "qf", + "spectre_panel", + "startuptime", + "tsplayground", + "neotest-output", + "checkhealth", + "neotest-summary", + "neotest-output-panel", + }, + callback = function(event) + vim.bo[event.buf].buflisted = false + vim.keymap.set( + "n", + "q", + "close", + { buffer = event.buf, silent = true } + ) + end, +}) + +-- wrap and check for spell in text filetypes +vim.api.nvim_create_autocmd("FileType", { + group = augroup("wrap_spell"), + pattern = { "gitcommit", "markdown" }, + callback = function() + vim.opt_local.wrap = true + vim.opt_local.spell = true + end, +}) + +-- Auto create dir when saving a file, in case some intermediate directory does not exist +vim.api.nvim_create_autocmd({ "BufWritePre" }, { + group = augroup("auto_create_dir"), + callback = function(event) + if event.match:match("^%w%w+://") then + return + end + local file = vim.loop.fs_realpath(event.match) or event.match + vim.fn.mkdir(vim.fn.fnamemodify(file, ":p:h"), "p") + end, +}) diff --git a/lua/rayandrew/init.lua b/lua/rayandrew/init.lua new file mode 100644 index 0000000..b0729fb --- /dev/null +++ b/lua/rayandrew/init.lua @@ -0,0 +1,11 @@ +local M = {} + +function M.setup() + require("rayandrew.set") + require("rayandrew.lazy") + require("rayandrew.autocmds") + require("rayandrew.remap") + require("rayandrew.theme").setup() +end + +return M diff --git a/lua/rayandrew/lazy.lua b/lua/rayandrew/lazy.lua new file mode 100644 index 0000000..f82c2b0 --- /dev/null +++ b/lua/rayandrew/lazy.lua @@ -0,0 +1,43 @@ +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", -- latest stable release + lazypath, + }) +end + +vim.opt.rtp:prepend(lazypath) + +require("lazy").setup({ + spec = { + { import = "rayandrew.plugins" }, + }, + defaults = { + lazy = false, + version = false, + }, + change_detection = { + enabled = true, + notify = false, + }, + checker = { enabled = true }, + performance = { + rtp = { + -- disable some rtp plugins + disabled_plugins = { + "gzip", + -- "matchit", + -- "matchparen", + -- "netrwPlugin", + "tarPlugin", + "tohtml", + "tutor", + "zipPlugin", + }, + }, + }, +}) diff --git a/lua/rayandrew/plugins.lua b/lua/rayandrew/plugins.lua new file mode 100644 index 0000000..d58ba26 --- /dev/null +++ b/lua/rayandrew/plugins.lua @@ -0,0 +1,1036 @@ +local load_textobjects = false + +return { + { "folke/lazy.nvim", version = "*" }, + { "nvim-lua/plenary.nvim", lazy = true }, + + ------------------------------ + -- Telescope + ------------------------------ + { + "nvim-telescope/telescope.nvim", + cmd = "Telescope", + dependencies = { "nvim-lua/plenary.nvim" }, + version = false, + keys = { + -- add a keymap to browse plugin files + { + "sp", + function() + local Util = require("rayandrew.util") + local fun = Util.telescope("live_grep") + fun() + end, + desc = "Find in Files (Grep)", + }, + { + "bb", + function() + local Util = require("rayandrew.util") + local fun = Util.telescope("buffers") + fun() + end, + desc = "List all opened buffers", + }, + { + "fF", + function() + local Util = require("rayandrew.util") + local fun = Util.telescope("files") + fun() + end, + desc = "Find Files (root dir)", + }, + { + "ff", + function() + local Util = require("rayandrew.util") + local fun = Util.telescope("files", { cwd = false }) + fun() + end, + desc = "Find Files (cwd)", + }, + }, + }, + + ------------------------------ + -- TreeSitter + ------------------------------ + { + "nvim-treesitter/nvim-treesitter", + build = ":TSUpdate", + dependencies = { + { + "nvim-treesitter/nvim-treesitter-textobjects", + init = function() + -- disable rtp plugin, as we only need its queries for mini.ai + -- In case other textobject modules are enabled, we will load them + -- once nvim-treesitter is loaded + require("lazy.core.loader").disable_rtp_plugin( + "nvim-treesitter-textobjects" + ) + load_textobjects = true + end, + }, + }, + opts = { + highlight = { enable = true }, + indent = { enable = true }, + ensure_installed = { + "bash", + "c", + "html", + "javascript", + "json", + "lua", + "luadoc", + "luap", + "markdown", + "markdown_inline", + "python", + "query", + "regex", + "rust", + "tsx", + "typescript", + "vim", + "vimdoc", + "yaml", + }, + incremental_selection = { + enable = true, + keymaps = { + init_selection = "", + node_incremental = "", + scope_incremental = false, + node_decremental = "", + }, + }, + }, + cmd = { "TSUpdateSync" }, + keys = { + { "", desc = "Increment selection" }, + { "", desc = "Decrement selection", mode = "x" }, + }, + config = function(_, opts) + if type(opts.ensure_installed) == "table" then + ---@type table + local added = {} + opts.ensure_installed = vim.tbl_filter(function(lang) + if added[lang] then + return false + end + added[lang] = true + return true + end, opts.ensure_installed) + end + require("nvim-treesitter.configs").setup(opts) + + if load_textobjects then + -- PERF: no need to load the plugin, if we only need its queries for mini.ai + if opts.textobjects then + for _, mod in ipairs({ "move", "select", "swap", "lsp_interop" }) do + if opts.textobjects[mod] and opts.textobjects[mod].enable then + local Loader = require("lazy.core.loader") + Loader.disabled_rtp_plugins["nvim-treesitter-textobjects"] = nil + local plugin = + require("lazy.core.config").plugins["nvim-treesitter-textobjects"] + require("lazy.core.loader").source_runtime(plugin.dir, "plugin") + break + end + end + end + end + end, + }, + { + "nvim-treesitter/playground", + }, + { + "nvim-treesitter/nvim-treesitter-context", + }, + + ------------------------------ + -- Color Scheme + ------------------------------ + { + "rose-pine/neovim", + name = "rose-pine", + lazy = true, + }, + + ------------------------------ + -- File Management + ------------------------------ + + -- file explorer + { + "nvim-neo-tree/neo-tree.nvim", + branch = "v3.x", + cmd = "Neotree", + dependencies = { + "nvim-lua/plenary.nvim", + "MunifTanjim/nui.nvim", + }, + keys = { + { + "fE", + function() + local Util = require("rayandrew.util") + require("neo-tree.command").execute({ + toggle = true, + dir = Util.get_root(), + }) + end, + desc = "Explorer NeoTree (root dir)", + }, + { + "fe", + function() + require("neo-tree.command").execute({ + toggle = true, + dir = vim.loop.cwd(), + }) + end, + desc = "Explorer NeoTree (cwd)", + }, + { + "E", + "fE", + desc = "Explorer NeoTree (root dir)", + remap = true, + }, + { + "e", + "fe", + desc = "Explorer NeoTree (cwd)", + remap = true, + }, + }, + deactivate = function() + vim.cmd([[Neotree close]]) + end, + init = function() + if vim.fn.argc() == 1 then + local stat = vim.loop.fs_stat(vim.fn.argv(0)) + if stat and stat.type == "directory" then + require("neo-tree") + end + end + end, + opts = { + sources = { "filesystem", "buffers", "git_status", "document_symbols" }, + open_files_do_not_replace_types = { + "terminal", + "Trouble", + "qf", + "Outline", + }, + filesystem = { + bind_to_cwd = false, + follow_current_file = { enabled = true }, + use_libuv_file_watcher = true, + }, + window = { + mappings = { + [""] = "none", + }, + }, + default_component_configs = { + indent = { + with_expanders = true, -- if nil and file nesting is enabled, will enable expanders + expander_collapsed = "", + expander_expanded = "", + expander_highlight = "NeoTreeExpander", + }, + }, + }, + config = function(_, opts) + require("neo-tree").setup(opts) + vim.api.nvim_create_autocmd("TermClose", { + pattern = "*lazygit", + callback = function() + if package.loaded["neo-tree.sources.git_status"] then + require("neo-tree.sources.git_status").refresh() + end + end, + }) + end, + }, + + -- search/replace in multiple files + { + "nvim-pack/nvim-spectre", + cmd = "Spectre", + opts = { open_cmd = "noswapfile vnew" }, + keys = { + { + "sr", + function() + require("spectre").open() + end, + desc = "Replace in files (Spectre)", + }, + }, + }, + + -- buffer remove + { + "echasnovski/mini.bufremove", + -- stylua: ignore + keys = { + { "bd", function() require("mini.bufremove").delete(0, false) end, desc = "Delete Buffer" }, + { "bD", function() require("mini.bufremove").delete(0, true) end, desc = "Delete Buffer (Force)" }, + }, + }, + + ------------------------------ + -- User Interface + ------------------------------ + + { + "folke/noice.nvim", + enabled = true, + event = "VeryLazy", + opts = { + lsp = { + override = { + ["vim.lsp.util.convert_input_to_markdown_lines"] = true, + ["vim.lsp.util.stylize_markdown"] = true, + ["cmp.entry.get_documentation"] = true, + }, + }, + routes = { + { + filter = { + event = "msg_show", + any = { + { find = "%d+L, %d+B" }, + { find = "; after #%d+" }, + { find = "; before #%d+" }, + }, + }, + view = "mini", + }, + }, + presets = { + bottom_search = true, + command_palette = true, + long_message_to_split = true, + inc_rename = true, + }, + }, + -- stylua: ignore + keys = { + { "", function() require("noice").redirect(vim.fn.getcmdline()) end, mode = "c", desc = "Redirect Cmdline" }, + { "snl", function() require("noice").cmd("last") end, desc = "Noice Last Message" }, + { "snh", function() require("noice").cmd("history") end, desc = "Noice History" }, + { "sna", function() require("noice").cmd("all") end, desc = "Noice All" }, + { "snd", function() require("noice").cmd("dismiss") end, desc = "Dismiss All" }, + { "", function() if not require("noice.lsp").scroll(4) then return "" end end, silent = true, expr = true, desc = "Scroll forward", mode = {"i", "n", "s"} }, + { "", function() if not require("noice.lsp").scroll(-4) then return "" end end, silent = true, expr = true, desc = "Scroll backward", mode = {"i", "n", "s"}}, + }, + }, + + { + "stevearc/dressing.nvim", + lazy = true, + init = function() + ---@diagnostic disable-next-line: duplicate-set-field + vim.ui.select = function(...) + require("lazy").load({ plugins = { "dressing.nvim" } }) + return vim.ui.select(...) + end + ---@diagnostic disable-next-line: duplicate-set-field + vim.ui.input = function(...) + require("lazy").load({ plugins = { "dressing.nvim" } }) + return vim.ui.input(...) + end + end, + }, + + -- buffer line + { + "akinsho/bufferline.nvim", + event = "VeryLazy", + keys = { + { "bp", "BufferLineTogglePin", desc = "Toggle pin" }, + { + "bP", + "BufferLineGroupClose ungrouped", + desc = "Delete non-pinned buffers", + }, + }, + opts = { + options = { + -- stylua: ignore + close_command = function(n) require("mini.bufremove").delete(n, false) end, + -- stylua: ignore + right_mouse_command = function(n) require("mini.bufremove").delete(n, false) end, + diagnostics = "nvim_lsp", + always_show_bufferline = false, + diagnostics_indicator = function(_, _, diag) + local icons = require("rayandrew.theme").icons.diagnostics + local ret = (diag.error and icons.Error .. diag.error .. " " or "") + .. (diag.warning and icons.Warn .. diag.warning or "") + return vim.trim(ret) + end, + offsets = { + { + filetype = "neo-tree", + text = "Neo-tree", + highlight = "Directory", + text_align = "left", + }, + }, + }, + }, + }, + + { + "lukas-reineke/indent-blankline.nvim", + event = { "BufReadPost", "BufNewFile" }, + opts = { + -- char = "▏", + char = "│", + filetype_exclude = { + "help", + "alpha", + "dashboard", + "neo-tree", + "Trouble", + "lazy", + "mason", + "notify", + "toggleterm", + "lazyterm", + }, + show_trailing_blankline_indent = false, + show_current_context = false, + }, + }, + + -- statusline + { + "nvim-lualine/lualine.nvim", + event = "VeryLazy", + opts = function() + local Util = require("rayandrew.util") + local icons = require("rayandrew.theme").icons + + return { + options = { + theme = "auto", + globalstatus = true, + disabled_filetypes = { statusline = { "dashboard", "alpha" } }, + }, + sections = { + lualine_a = { "mode" }, + lualine_b = { "branch" }, + lualine_c = { + { + "diagnostics", + symbols = { + error = icons.diagnostics.Error, + warn = icons.diagnostics.Warn, + info = icons.diagnostics.Info, + hint = icons.diagnostics.Hint, + }, + }, + { + "filetype", + icon_only = true, + separator = "", + padding = { left = 1, right = 0 }, + }, + { + "filename", + path = 1, + symbols = { modified = "  ", readonly = "", unnamed = "" }, + }, + -- stylua: ignore + { + function() return require("nvim-navic").get_location() end, + cond = function() return package.loaded["nvim-navic"] and require("nvim-navic").is_available() end, + }, + }, + lualine_x = { + -- stylua: ignore + { + function() return require("noice").api.status.command.get() end, + cond = function() return package.loaded["noice"] and require("noice").api.status.command.has() end, + color = Util.fg("Statement"), + }, + -- stylua: ignore + { + function() return require("noice").api.status.mode.get() end, + cond = function() return package.loaded["noice"] and require("noice").api.status.mode.has() end, + color = Util.fg("Constant"), + }, + -- stylua: ignore + { + function() return " " .. require("dap").status() end, + cond = function () return package.loaded["dap"] and require("dap").status() ~= "" end, + color = Util.fg("Debug"), + }, + { + require("lazy.status").updates, + cond = require("lazy.status").has_updates, + color = Util.fg("Special"), + }, + { + "diff", + symbols = { + added = icons.git.added, + modified = icons.git.modified, + removed = icons.git.removed, + }, + }, + }, + lualine_y = { + { "progress", separator = " ", padding = { left = 1, right = 0 } }, + { "location", padding = { left = 0, right = 1 } }, + }, + lualine_z = { + function() + return " " .. os.date("%R") + end, + }, + }, + extensions = { "neo-tree", "lazy" }, + } + end, + }, + + -- lsp symbol navigation for lualine. This shows where + -- in the code structure you are - within functions, classes, + -- etc - in the statusline. + { + "SmiteshP/nvim-navic", + lazy = true, + init = function() + local Util = require("rayandrew.util") + vim.g.navic_silence = true + Util.on_attach(function(client, buffer) + if client.server_capabilities.documentSymbolProvider then + require("nvim-navic").attach(client, buffer) + end + end) + end, + opts = function() + return { + separator = " ", + highlight = true, + depth_limit = 5, + icons = require("rayandrew.theme").icons.kinds, + } + end, + }, + + -- icons + { "nvim-tree/nvim-web-devicons", lazy = true }, + + -- ui components + { "MunifTanjim/nui.nvim", lazy = true }, + + ------------------------------ + -- LSP Configuration + ------------------------------ + + -- LSP Zero + { + "VonHeikemen/lsp-zero.nvim", + branch = "v2.x", + lazy = true, + config = function() + require("lsp-zero.settings").preset("recommended") + end, + }, + + -- Copilot + { + "zbirenbaum/copilot.lua", + cmd = "Copilot", + build = ":Copilot auth", + opts = { + suggestion = { enabled = false }, + panel = { enabled = false }, + filetypes = { + markdown = true, + help = true, + }, + }, + }, + + -- Autocompletion + { + "hrsh7th/nvim-cmp", + event = "InsertEnter", + dependencies = { + { "L3MON4D3/LuaSnip" }, + { + "zbirenbaum/copilot-cmp", + dependencies = "copilot.lua", + opts = {}, + config = function(_, opts) + local Util = require("rayandrew.util") + local copilot_cmp = require("copilot_cmp") + copilot_cmp.setup(opts) + -- attach cmp source whenever copilot attaches + -- fixes lazy-loading issues with the copilot cmp source + Util.on_attach(function(client) + if client.name == "copilot" then + copilot_cmp._on_insert_enter({}) + end + end) + end, + }, + }, + config = function() + require("lsp-zero.cmp").extend() + + local cmp = require("cmp") + local cmp_action = require("lsp-zero.cmp").action() + local cmp_select = { behavior = cmp.SelectBehavior.Select } + local sorting = require("cmp.config.default")().sorting + + cmp.setup({ + sources = { + { name = "copilot", group_index = 2 }, + { name = "nvim_lsp", group_index = 2 }, + { name = "path", group_index = 2 }, + { name = "luasnip", group_index = 2 }, + }, + mapping = { + [""] = cmp.mapping.complete(), + [""] = cmp_action.luasnip_jump_forward(), + [""] = cmp_action.luasnip_jump_backward(), + [""] = cmp.mapping.select_prev_item(cmp_select), + [""] = cmp.mapping.select_next_item(cmp_select), + [""] = cmp.mapping.confirm({ select = true }), + [""] = nil, + [""] = nil, + [""] = cmp.mapping.confirm({ + -- documentation says this is important. + -- I don't know why. + behavior = cmp.ConfirmBehavior.Replace, + select = false, + }), + }, + sorting, + }) + end, + }, + + -- LSP + { + "neovim/nvim-lspconfig", + cmd = "LspInfo", + event = { "BufReadPre", "BufNewFile" }, + dependencies = { + { "hrsh7th/cmp-nvim-lsp" }, + { "williamboman/mason-lspconfig.nvim" }, + { "williamboman/mason.nvim" }, + }, + config = function() + local lsp = require("lsp-zero") + + lsp.on_attach(function(_, bufnr) + local opts = { buffer = bufnr, remap = false } + + lsp.default_keymaps({ buffer = bufnr }) + + vim.keymap.set("n", "gd", function() + vim.lsp.buf.definition() + end, opts) + vim.keymap.set("n", "K", function() + vim.lsp.buf.hover() + end, opts) + vim.keymap.set("n", "vws", function() + vim.lsp.buf.workspace_symbol() + end, opts) + vim.keymap.set("n", "vd", function() + vim.diagnostic.open_float() + end, opts) + vim.keymap.set("n", "[d", function() + vim.diagnostic.goto_next() + end, opts) + vim.keymap.set("n", "]d", function() + vim.diagnostic.goto_prev() + end, opts) + vim.keymap.set("n", "ca", function() + vim.lsp.buf.code_action() + end, opts) + vim.keymap.set("n", "vrr", function() + vim.lsp.buf.references() + end, opts) + vim.keymap.set("n", "vrn", function() + vim.lsp.buf.rename() + end, opts) + vim.keymap.set("i", "", function() + vim.lsp.buf.signature_help() + end, opts) + end) + + -- (Optional) Configure lua language server for neovim + require("lspconfig").lua_ls.setup(lsp.nvim_lua_ls()) + + lsp.ensure_installed({ + "tsserver", + "rust_analyzer", + }) + + lsp.set_preferences({ + suggest_lsp_servers = false, + sign_icons = { + error = "E", + warn = "W", + hint = "H", + info = "I", + }, + }) + + lsp.format_on_save({ + format_opts = { + async = false, + timeout_ms = 10000, + }, + servers = { + ["null-ls"] = { "javascript", "typescript", "lua" }, + }, + }) + + lsp.setup() + + vim.diagnostic.config({ + virtual_text = true, + }) + end, + }, + + ------------------------------ + -- Formatter + ------------------------------ + { + "jay-babu/mason-null-ls.nvim", + event = { "BufReadPre", "BufNewFile" }, + dependencies = { + "williamboman/mason.nvim", + "jose-elias-alvarez/null-ls.nvim", + }, + opts = function() + local nls = require("null-ls") + + return { + -- sources = { + -- nls.builtins.formatting.fish_indent, + -- nls.builtins.diagnostics.fish, + -- nls.builtins.formatting.stylua, + -- nls.builtins.formatting.shfmt, + -- -- nls.builtins.diagnostics.flake8, + -- }, + + ensure_installed = nil, + automatic_installation = false, -- You can still set this to `true` + handlers = { + function() end, -- disables automatic setup of all null-ls sources + stylua = function(source_name, methods) + nls.register(nls.builtins.formatting.stylua) + end, + }, + } + end, + config = function(_, opts) + require("null-ls").setup({ + root_dir = require("null-ls.utils").root_pattern( + ".null-ls-root", + ".neoconf.json", + "Makefile", + ".git" + ), + }) + require("mason-null-ls").setup(opts) + end, + }, + + ------------------------------ + -- Utilities + ------------------------------ + { + "RRethy/vim-illuminate", + event = { "BufReadPost", "BufNewFile" }, + opts = { + delay = 200, + large_file_cutoff = 2000, + large_file_overrides = { + providers = { "lsp" }, + }, + }, + config = function(_, opts) + require("illuminate").configure(opts) + + local function map(key, dir, buffer) + vim.keymap.set("n", key, function() + require("illuminate")["goto_" .. dir .. "_reference"](false) + end, { + desc = dir:sub(1, 1):upper() .. dir:sub(2) .. " Reference", + buffer = buffer, + }) + end + + map("]]", "next") + map("[[", "prev") + + -- also set it after loading ftplugins, since a lot overwrite [[ and ]] + vim.api.nvim_create_autocmd("FileType", { + callback = function() + local buffer = vim.api.nvim_get_current_buf() + map("]]", "next", buffer) + map("[[", "prev", buffer) + end, + }) + end, + keys = { + { "]]", desc = "Next Reference" }, + { "[[", desc = "Prev Reference" }, + }, + }, + + -- comments + { "JoosepAlviste/nvim-ts-context-commentstring", lazy = true }, + { + "echasnovski/mini.comment", + event = "VeryLazy", + opts = { + options = { + custom_commentstring = function() + return require("ts_context_commentstring.internal").calculate_commentstring() + or vim.bo.commentstring + end, + }, + }, + }, + + { + "tpope/vim-fugitive", + }, + { + "theprimeagen/harpoon", + }, + { + "theprimeagen/refactoring.nvim", + }, + -- { + -- "github/copilot.vim", + -- }, + { + "eandrju/cellular-automaton.nvim", + }, + { + "laytan/cloak.nvim", + }, + { + "mbbill/undotree", + }, + + -- Folke + { + "folke/flash.nvim", + event = "VeryLazy", + vscode = true, + ---@type Flash.Config + opts = {}, + -- stylua: ignore + keys = { + { "s", mode = { "n", "x", "o" }, function() require("flash").jump() end, desc = "Flash" }, + { "S", mode = { "n", "o", "x" }, function() require("flash").treesitter() end, desc = "Flash Treesitter" }, + { "r", mode = "o", function() require("flash").remote() end, desc = "Remote Flash" }, + { "R", mode = { "o", "x" }, function() require("flash").treesitter_search() end, desc = "Treesitter Search" }, + { "", mode = { "c" }, function() require("flash").toggle() end, desc = "Toggle Flash Search" }, + }, + }, + { + "folke/trouble.nvim", + cmd = { "TroubleToggle", "Trouble" }, + opts = { use_diagnostic_signs = true }, + keys = { + { + "xx", + "TroubleToggle document_diagnostics", + desc = "Document Diagnostics (Trouble)", + }, + { + "xX", + "TroubleToggle workspace_diagnostics", + desc = "Workspace Diagnostics (Trouble)", + }, + { + "xL", + "TroubleToggle loclist", + desc = "Location List (Trouble)", + }, + { + "xQ", + "TroubleToggle quickfix", + desc = "Quickfix List (Trouble)", + }, + { + "[q", + function() + if require("trouble").is_open() then + require("trouble").previous({ skip_groups = true, jump = true }) + else + local ok, err = pcall(vim.cmd.cprev) + if not ok then + vim.notify(err, vim.log.levels.ERROR) + end + end + end, + desc = "Previous trouble/quickfix item", + }, + { + "]q", + function() + if require("trouble").is_open() then + require("trouble").next({ skip_groups = true, jump = true }) + else + local ok, err = pcall(vim.cmd.cnext) + if not ok then + vim.notify(err, vim.log.levels.ERROR) + end + end + end, + desc = "Next trouble/quickfix item", + }, + }, + }, + { + "folke/todo-comments.nvim", + cmd = { "TodoTrouble", "TodoTelescope" }, + event = { "BufReadPost", "BufNewFile" }, + config = true, + -- stylua: ignore + keys = { + { "]t", function() require("todo-comments").jump_next() end, desc = "Next todo comment" }, + { "[t", function() require("todo-comments").jump_prev() end, desc = "Previous todo comment" }, + { "xt", "TodoTrouble", desc = "Todo (Trouble)" }, + { "xT", "TodoTrouble keywords=TODO,FIX,FIXME", desc = "Todo/Fix/Fixme (Trouble)" }, + { "st", "TodoTelescope", desc = "Todo" }, + { "sT", "TodoTelescope keywords=TODO,FIX,FIXME", desc = "Todo/Fix/Fixme" }, + }, + }, + { + "folke/which-key.nvim", + event = "VeryLazy", + opts = { + plugins = { spelling = true }, + defaults = { + mode = { "n", "v" }, + ["g"] = { name = "+goto" }, + ["gz"] = { name = "+surround" }, + ["]"] = { name = "+next" }, + ["["] = { name = "+prev" }, + [""] = { name = "+tabs" }, + ["b"] = { name = "+buffer" }, + ["c"] = { name = "+code" }, + ["f"] = { name = "+file/find" }, + ["g"] = { name = "+git" }, + ["gh"] = { name = "+hunks" }, + ["q"] = { name = "+quit/session" }, + ["s"] = { name = "+search" }, + ["u"] = { name = "+ui" }, + ["w"] = { name = "+windows" }, + ["x"] = { name = "+diagnostics/quickfix" }, + }, + }, + config = function(_, opts) + local wk = require("which-key") + wk.setup(opts) + wk.register(opts.defaults) + end, + }, + { + "folke/zen-mode.nvim", + }, + + -- Flash Telescope config + { + "nvim-telescope/telescope.nvim", + optional = true, + opts = function(_, opts) + local function flash(prompt_bufnr) + require("flash").jump({ + pattern = "^", + label = { after = { 0, 0 } }, + search = { + mode = "search", + exclude = { + function(win) + return vim.bo[vim.api.nvim_win_get_buf(win)].filetype + ~= "TelescopeResults" + end, + }, + }, + action = function(match) + local picker = + require("telescope.actions.state").get_current_picker( + prompt_bufnr + ) + picker:set_selection(match.pos[1] - 1) + end, + }) + end + opts.defaults = vim.tbl_deep_extend("force", opts.defaults or {}, { + mappings = { n = { s = flash }, i = { [""] = flash } }, + }) + end, + }, + + -- Tmux + { + "christoomey/vim-tmux-navigator", + cmd = { + "TmuxNavigateLeft", + "TmuxNavigateDown", + "TmuxNavigateUp", + "TmuxNavigateRight", + }, + keys = { "", "", "", "" }, + }, + + -- Copilot Lualine + + { + "nvim-lualine/lualine.nvim", + -- optional = true, + event = "VeryLazy", + opts = function(_, opts) + local Util = require("rayandrew.util") + local colors = { + [""] = Util.fg("Special"), + ["Normal"] = Util.fg("Special"), + ["Warning"] = Util.fg("DiagnosticError"), + ["InProgress"] = Util.fg("DiagnosticWarn"), + } + table.insert(opts.sections.lualine_x, 2, { + function() + local icon = require("rayandrew.themes").icons.kinds.Copilot + local status = require("copilot.api").status.data + return icon .. (status.message or "") + end, + cond = function() + local ok, clients = + pcall(vim.lsp.get_active_clients, { name = "copilot", bufnr = 0 }) + return ok and #clients > 0 + end, + color = function() + if not package.loaded["copilot"] then + return + end + local status = require("copilot.api").status.data + return colors[status.status] or colors[""] + end, + }) + end, + }, +} diff --git a/lua/rayandrew/remap.lua b/lua/rayandrew/remap.lua new file mode 100644 index 0000000..e853c69 --- /dev/null +++ b/lua/rayandrew/remap.lua @@ -0,0 +1,216 @@ +local Util = require("rayandrew.util") + +------------------------------ +-- Buffers +------------------------------ + +Util.map("n", "fs", "w", { desc = "Save file" }) + +Util.map( + { "i", "v", "n", "s" }, + "", + "w", + { desc = "Save file" } +) + +-- Move Lines +Util.map("n", "", "m .+1==", { desc = "Move down" }) +Util.map("n", "", "m .-2==", { desc = "Move up" }) +Util.map("i", "", "m .+1==gi", { desc = "Move down" }) +Util.map("i", "", "m .-2==gi", { desc = "Move up" }) +Util.map("v", "", ":m '>+1gv=gv", { desc = "Move down" }) +Util.map("v", "", ":m '<-2gv=gv", { desc = "Move up" }) + +------------------------------ +-- Windowing + Navigation +------------------------------ + +-- better up/down +Util.map( + { "n", "x" }, + "j", + "v:count == 0 ? 'gj' : 'j'", + { expr = true, silent = true } +) +Util.map( + { "n", "x" }, + "k", + "v:count == 0 ? 'gk' : 'k'", + { expr = true, silent = true } +) + +-- resize +Util.map( + "n", + "", + "resize +2", + { desc = "Increase window height" } +) +Util.map( + "n", + "", + "resize -2", + { desc = "Decrease window height" } +) +Util.map( + "n", + "", + "vertical resize -2", + { desc = "Decrease window width" } +) +Util.map( + "n", + "", + "vertical resize +2", + { desc = "Increase window width" } +) + +-- split +Util.map( + "n", + "ws", + "split", + { desc = "[W]indow Horizontal [S]plit" } +) -- split horizontal +Util.map( + "n", + "wv", + "vsplit", + { desc = "[W]indow [V]ertical Split" } +) -- split vertical + +-- move +Util.map( + "n", + "wh", + "TmuxNavigateLeft", + { desc = "Go to Left [W]indow" } +) +Util.map( + "n", + "wj", + "TmuxNavigateDown", + { desc = "Go to [W]indow Below" } +) +Util.map( + "n", + "wk", + "TmuxNavigateUp", + { desc = "Go to Top [W]indow" } +) +Util.map( + "n", + "wl", + "TmuxNavigateRight", + { desc = "Go to Right [W]indow" } +) + +if Util.has("bufferline.nvim") then + Util.map( + "n", + "", + "BufferLineCyclePrev", + { desc = "Prev buffer" } + ) + Util.map( + "n", + "", + "BufferLineCycleNext", + { desc = "Next buffer" } + ) + Util.map("n", "[b", "BufferLineCyclePrev", { desc = "Prev buffer" }) + Util.map("n", "]b", "BufferLineCycleNext", { desc = "Next buffer" }) +else + Util.map("n", "", "bprevious", { desc = "Prev buffer" }) + Util.map("n", "", "bnext", { desc = "Next buffer" }) + Util.map("n", "[b", "bprevious", { desc = "Prev buffer" }) + Util.map("n", "]b", "bnext", { desc = "Next buffer" }) +end + +-- tabs +Util.map("n", "l", "tablast", { desc = "Last Tab" }) +Util.map("n", "f", "tabfirst", { desc = "First Tab" }) +Util.map("n", "", "tabnew", { desc = "New Tab" }) +Util.map("n", "]", "tabnext", { desc = "Next Tab" }) +Util.map("n", "d", "tabclose", { desc = "Close Tab" }) +Util.map( + "n", + "[", + "tabprevious", + { desc = "Previous Tab" } +) + +-- close +Util.map("n", "wq", "q", { desc = "[W]indow [Q]uit" }) -- quit + +------------------------------ +-- Clipboard +------------------------------ + +Util.map("x", "p", [["_dP]]) + +Util.map({ "n", "v" }, "y", [["+y]]) +Util.map("n", "Y", [["+Y]]) + +Util.map({ "n", "v" }, "d", [["_d]]) + +Util.map("i", "", "") + +Util.map("n", "Q", "") + +------------------------------ +-- Utilities +------------------------------ + +Util.map("n", "u", vim.cmd.UndotreeToggle) + +-- better indenting +Util.map("v", "<", "", ">gv") + +-- file permission +Util.map("n", "x", "!chmod +x %", { silent = true }) + +Util.map("n", "mr", "CellularAutomaton make_it_rain") + +------------------------------ +-- Terminal +------------------------------ + +-- lazygit +Util.map("n", "gg", function() + Util.float_term( + { "lazygit" }, + { cwd = Util.get_root(), esc_esc = false, ctrl_hjkl = false } + ) +end, { desc = "Lazygit (root dir)" }) +Util.map("n", "gG", function() + Util.float_term({ "lazygit" }, { esc_esc = false, ctrl_hjkl = false }) +end, { desc = "Lazygit (cwd)" }) + +-- float term +local lazyterm = function() + Util.float_term(nil, { cwd = Util.get_root() }) +end +Util.map("n", "ft", lazyterm, { desc = "Terminal (root dir)" }) +Util.map("n", "fT", function() + Util.float_term() +end, { desc = "Terminal (cwd)" }) +Util.map("n", "", lazyterm, { desc = "Terminal (root dir)" }) +Util.map("n", "", lazyterm, { desc = "Terminal (root dir)" }) +Util.map("n", "", lazyterm, { desc = "which_key_ignore" }) + +Util.map("t", "", "", { desc = "Enter Normal Mode" }) +Util.map("t", "", "wincmd h", { desc = "Go to left window" }) +Util.map("t", "", "wincmd j", { desc = "Go to lower window" }) +Util.map("t", "", "wincmd k", { desc = "Go to upper window" }) +Util.map("t", "", "wincmd l", { desc = "Go to right window" }) +Util.map("t", "", "close", { desc = "Hide Terminal" }) +Util.map("t", "", "close", { desc = "which_key_ignore" }) + +------------------------------ +-- Others +------------------------------ + +-- lazy +Util.map("n", "l", "Lazy", { desc = "Lazy" }) diff --git a/lua/rayandrew/set.lua b/lua/rayandrew/set.lua new file mode 100644 index 0000000..0a45dcb --- /dev/null +++ b/lua/rayandrew/set.lua @@ -0,0 +1,65 @@ +vim.g.mapleader = " " +vim.g.maplocalleader = "\\" + +local opt = vim.opt + +opt.autowrite = true -- Enable auto write +opt.backup = false +opt.clipboard = "unnamedplus" -- Sync with system clipboard +opt.completeopt = "menu,menuone,noselect" +opt.conceallevel = 3 -- Hide * markup for bold and italic +opt.confirm = true -- Confirm to save changes before exiting modified buffer +opt.cursorline = true -- Enable highlighting of the current line +opt.expandtab = true -- Use spaces instead of tabs +opt.formatoptions = "jcroqlnt" -- tcqj +opt.grepformat = "%f:%l:%c:%m" +opt.grepprg = "rg --vimgrep" +opt.hlsearch = false +opt.ignorecase = true -- Ignore case +opt.incsearch = true +opt.inccommand = "nosplit" -- preview incremental substitute +opt.laststatus = 0 +opt.list = true -- Show some invisible characters (tabs... +opt.mouse = "a" -- Enable mouse mode +opt.nu = true +opt.number = true -- Print line number +opt.pumblend = 10 -- Popup blend +opt.pumheight = 10 -- Maximum number of entries in a popup +opt.relativenumber = true -- Relative line numbers +opt.scrolloff = 4 -- Lines of context +opt.sessionoptions = { "buffers", "curdir", "tabpages", "winsize" } +opt.shiftround = true -- Round indent +opt.shiftwidth = 2 -- Size of an indent +opt.shortmess:append({ W = true, I = true, c = true }) +opt.showmode = false -- Dont show mode since we have a statusline +opt.sidescrolloff = 8 -- Columns of context +opt.signcolumn = "yes" -- Always show the signcolumn, otherwise it would shift the text each time +opt.smartcase = true -- Don't ignore case with capitals +opt.smartindent = true -- Insert indents automatically +opt.softtabstop = 2 +opt.spelllang = { "en" } +opt.splitbelow = true -- Put new windows below current +opt.splitright = true -- Put new windows right of current +opt.swapfile = false +opt.tabstop = 2 -- Number of spaces tabs count for +opt.termguicolors = true -- True color support +opt.timeoutlen = 300 +opt.undodir = os.getenv("HOME") .. "/.vim/undodir" +opt.undofile = true +opt.undolevels = 10000 +opt.updatetime = 200 -- Save swap file and trigger CursorHold +opt.wildmode = "longest:full,full" -- Command-line completion mode +opt.winminwidth = 5 -- Minimum window width +opt.wrap = false -- Disable line wrap + +if vim.fn.has("nvim-0.9.0") == 1 then + opt.splitkeep = "screen" + opt.shortmess:append({ C = true }) +end + +-- Fix markdown indentation settings +vim.g.markdown_recommended_style = 0 + +opt.isfname:append("@-@") + +opt.colorcolumn = "80" diff --git a/lua/rayandrew/theme.lua b/lua/rayandrew/theme.lua new file mode 100644 index 0000000..c4d68ad --- /dev/null +++ b/lua/rayandrew/theme.lua @@ -0,0 +1,80 @@ +local M = {} + +M.colorscheme = "rose-pine" + +function M.setup() + -- taken from https://github.com/LazyVim/LazyVim/blob/566049aa4a26a86219dd1ad1624f9a1bf18831b6/lua/lazyvim/config/init.lua#L117C3-L129C5 + require("lazy.core.util").try(function() + if type(M.colorscheme) == "function" then + M.colorscheme() + else + vim.cmd.colorscheme(M.colorscheme) + end + end, { + msg = "Could not load your colorscheme", + on_error = function(msg) + require("lazy.core.util").error(msg) + vim.cmd.colorscheme("habamax") + end, + }) +end + +M.icons = { + dap = { + Stopped = { "󰁕 ", "DiagnosticWarn", "DapStoppedLine" }, + Breakpoint = " ", + BreakpointCondition = " ", + BreakpointRejected = { " ", "DiagnosticError" }, + LogPoint = ".>", + }, + diagnostics = { + Error = " ", + Warn = " ", + Hint = " ", + Info = " ", + }, + git = { + added = " ", + modified = " ", + removed = " ", + }, + kinds = { + Array = " ", + Boolean = " ", + Class = " ", + Color = " ", + Constant = " ", + Constructor = " ", + Copilot = " ", + Enum = " ", + EnumMember = " ", + Event = " ", + Field = " ", + File = " ", + Folder = " ", + Function = " ", + Interface = " ", + Key = " ", + Keyword = " ", + Method = " ", + Module = " ", + Namespace = " ", + Null = " ", + Number = " ", + Object = " ", + Operator = " ", + Package = " ", + Property = " ", + Reference = " ", + Snippet = " ", + String = " ", + Struct = " ", + Text = " ", + TypeParameter = " ", + Unit = " ", + Value = " ", + Variable = " ", + }, +} + +return M diff --git a/lua/rayandrew/util.lua b/lua/rayandrew/util.lua new file mode 100644 index 0000000..1eb0938 --- /dev/null +++ b/lua/rayandrew/util.lua @@ -0,0 +1,173 @@ +-- shamelessly copied from +-- https://github.com/LazyVim/LazyVim/blob/main/lua/lazyvim/util/init.lua + +local M = {} + +---@param on_attach fun(client, buffer) +function M.on_attach(on_attach) + vim.api.nvim_create_autocmd("LspAttach", { + callback = function(args) + local buffer = args.buf + local client = vim.lsp.get_client_by_id(args.data.client_id) + on_attach(client, buffer) + end, + }) +end + +function M.fg(name) + ---@type {foreground?:number}? + local hl = vim.api.nvim_get_hl and vim.api.nvim_get_hl(0, { name = name }) + or vim.api.nvim_get_hl_by_name(name, true) + local fg = hl and hl.fg or hl.foreground + return fg and { fg = string.format("#%06x", fg) } +end + +function M.map(mode, lhs, rhs, opts) + local has_handler, handler = pcall(require, "lazy.core.handler") + if has_handler then + local keys = handler.handlers.keys + ---@cast keys LazyKeysHandler + -- do not create the keymap if a lazy keys handler exists + if not keys.active[keys.parse({ lhs, mode = mode }).id] then + opts = opts or {} + opts.silent = opts.silent ~= false + vim.keymap.set(mode, lhs, rhs, opts) + end + return + end + + vim.keymap.set(mode, lhs, rhs, opts) +end + +M.root_patterns = { ".git", "lua" } + +-- returns the root directory based on: +-- * lsp workspace folders +-- * lsp root_dir +-- * root pattern of filename of the current buffer +-- * root pattern of cwd +---@return string +function M.get_root() + ---@type string? + local path = vim.api.nvim_buf_get_name(0) + path = path ~= "" and vim.loop.fs_realpath(path) or nil + ---@type string[] + local roots = {} + if path then + for _, client in pairs(vim.lsp.get_active_clients({ bufnr = 0 })) do + local workspace = client.config.workspace_folders + local paths = workspace + and vim.tbl_map(function(ws) + return vim.uri_to_fname(ws.uri) + end, workspace) + or client.config.root_dir and { client.config.root_dir } + or {} + for _, p in ipairs(paths) do + local r = vim.loop.fs_realpath(p) + if path:find(r, 1, true) then + roots[#roots + 1] = r + end + end + end + end + table.sort(roots, function(a, b) + return #a > #b + end) + ---@type string? + local root = roots[1] + if not root then + path = path and vim.fs.dirname(path) or vim.loop.cwd() + ---@type string? + root = vim.fs.find(M.root_patterns, { path = path, upward = true })[1] + root = root and vim.fs.dirname(root) or vim.loop.cwd() + end + ---@cast root string + return root +end + +function M.telescope(builtin, opts) + local params = { builtin = builtin, opts = opts } + return function() + builtin = params.builtin + opts = params.opts + opts = vim.tbl_deep_extend("force", { cwd = M.get_root() }, opts or {}) + if builtin == "files" then + if vim.loop.fs_stat((opts.cwd or vim.loop.cwd()) .. "/.git") then + opts.show_untracked = true + builtin = "git_files" + else + builtin = "find_files" + end + end + if opts.cwd and opts.cwd ~= vim.loop.cwd() then + opts.attach_mappings = function(_, map) + map("i", "", function() + local action_state = require("telescope.actions.state") + local line = action_state.get_current_line() + M.telescope( + params.builtin, + vim.tbl_deep_extend( + "force", + {}, + params.opts or {}, + { cwd = false, default_text = line } + ) + )() + end) + return true + end + end + + require("telescope.builtin")[builtin](opts) + end +end + +---@type table +local terminals = {} + +function M.float_term(cmd, opts) + opts = vim.tbl_deep_extend("force", { + ft = "lazyterm", + size = { width = 0.9, height = 0.9 }, + }, opts or {}, { persistent = true }) + ---@cast opts LazyCmdOptions|{interactive?:boolean, esc_esc?:false} + + local termkey = vim.inspect({ + cmd = cmd or "shell", + cwd = opts.cwd, + env = opts.env, + count = vim.v.count1, + }) + + if terminals[termkey] and terminals[termkey]:buf_valid() then + terminals[termkey]:toggle() + else + terminals[termkey] = require("lazy.util").float_term(cmd, opts) + local buf = terminals[termkey].buf + vim.b[buf].lazyterm_cmd = cmd + if opts.esc_esc == false then + vim.keymap.set("t", "", "", { buffer = buf, nowait = true }) + end + if opts.ctrl_hjkl == false then + vim.keymap.set("t", "", "", { buffer = buf, nowait = true }) + vim.keymap.set("t", "", "", { buffer = buf, nowait = true }) + vim.keymap.set("t", "", "", { buffer = buf, nowait = true }) + vim.keymap.set("t", "", "", { buffer = buf, nowait = true }) + end + + vim.api.nvim_create_autocmd("BufEnter", { + buffer = buf, + callback = function() + vim.cmd.startinsert() + end, + }) + end + + return terminals[termkey] +end + +function M.has(plugin) + return require("lazy.core.config").spec.plugins[plugin] ~= nil +end + +return M diff --git a/stylua.toml b/stylua.toml new file mode 100644 index 0000000..421c3d9 --- /dev/null +++ b/stylua.toml @@ -0,0 +1,3 @@ +indent_type = "Spaces" +indent_width = 2 +column_width = 80