diff --git a/init.lua b/init.lua index a076ec0..00d56f4 100644 --- a/init.lua +++ b/init.lua @@ -1,13 +1,10 @@ --- if Neovim 0.9+, use vim.loade speedup module loading -if vim.loader then - vim.loader.enable() +if vim.loader then + vim.loader.enable() end --- all use dump print _G.dd = function(...) - require("util.debug").dump(...) + require("util.debug").dump(...) end vim.print = _G.dd --- use plugin require("config.lazy") diff --git a/lua/config/autocmds.lua b/lua/config/autocmds.lua index d36e594..a9d3f98 100644 --- a/lua/config/autocmds.lua +++ b/lua/config/autocmds.lua @@ -1,12 +1,14 @@ -- Turn off paste mode when leaving insert vim.api.nvim_create_autocmd("InsertLeave", { - pattern = "*", - command = "set nopaste", + pattern = "*", + command = "set nopaste", }) + -- Disable the concealing in some file formats +-- The default conceallevel is 3 in LazyVim vim.api.nvim_create_autocmd("FileType", { - pattern = { "json", "jsonc", "markdown" }, - callback = function() - vim.opt.conceallevel = 0 - end, + pattern = { "json", "jsonc", "markdown" }, + callback = function() + vim.opt.conceallevel = 0 + end, }) diff --git a/lua/config/keymaps.lua b/lua/config/keymaps.lua index b95b2ad..4a8a5bb 100644 --- a/lua/config/keymaps.lua +++ b/lua/config/keymaps.lua @@ -1,13 +1,11 @@ local discipline = require("m1ngsama.discipline") -discipline.trigger() +-- discipline.cowboy() --- Neovim api to replace classic vim.api.nvim_set_keymap local keymap = vim.keymap local opts = { noremap = true, silent = true } - --- Keymap without affecting the registers +-- Do things without affecting the registers keymap.set("n", "x", '"_x') keymap.set("n", "p", '"0p') keymap.set("n", "P", '"0P') @@ -25,10 +23,50 @@ keymap.set("v", "D", '"_D') keymap.set("n", "+", "") keymap.set("n", "-", "") --- Dlete a word backwards +-- Delete a word backwards keymap.set("n", "dw", 'vb"_d') -- Select all keymap.set("n", "", "ggG") +-- Save with root permission (not working for now) +--vim.api.nvim_create_user_command('W', 'w !sudo tee > /dev/null %', {}) + -- Disable continuations +keymap.set("n", "o", "o^Da", opts) +keymap.set("n", "O", "O^Da", opts) + +-- Jumplist +keymap.set("n", "", "", opts) + +-- New tab +keymap.set("n", "te", ":tabedit") +keymap.set("n", "", ":tabnext", opts) +keymap.set("n", "", ":tabprev", opts) +-- Split window +keymap.set("n", "ss", ":split", opts) +keymap.set("n", "sv", ":vsplit", opts) +-- Move window +keymap.set("n", "sh", "h") +keymap.set("n", "sk", "k") +keymap.set("n", "sj", "j") +keymap.set("n", "sl", "l") + +-- Resize window +keymap.set("n", "", "<") +keymap.set("n", "", ">") +keymap.set("n", "", "+") +keymap.set("n", "", "-") + +-- Diagnostics +keymap.set("n", "", function() + vim.diagnostic.goto_next() +end, opts) + +keymap.set("n", "r", function() + require("m1ngsama.hsl").replaceHexWithHSL() +end) + +keymap.set("n", "i", function() + require("m1ngsama.lsp").toggleInlayHints() +end) diff --git a/lua/config/lazy.lua b/lua/config/lazy.lua index a86e2e3..014aa3b 100644 --- a/lua/config/lazy.lua +++ b/lua/config/lazy.lua @@ -1,73 +1,87 @@ --- lazy 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, -}) + 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 = { - -- add LazyVim and import plugins - { - "LazyVim/LazyVim", - import = "lazyvim.plugins", - opts = { - colorscheme = "solarized-osaka", - news = { - lazyvim = true, - neovim = true, - }, - }, - }, - { import = "lazyvim.plugins.extras.linting.eslint" }, - { import = "lazyvim.plugins.extras.formatting.prettier" }, - { import = "lazyvim.plugins.extras.lang.typescript" }, - { import = "lazyvim.plugins.extras.lang.json" }, - { import = "lazyvim.plugins.extras.lang.markdown" }, - { import = "lazyvim.plugins.extras.lang.rust" }, - { import = "lazyvim.plugins.extras.lang.tailwind" }, - { import = "lazyvim.plugins.extras.coding.copilot" }, - { import = "lazyvim.plugins.extras.dap.core" }, - { import = "lazyvim.plugins.extras.util.mini-hipatterns" }, - { import = "lazyvim.plugins.extras.coding.yanky" }, - { import = "lazyvim.plugins.extras.editors.mini-files" }, - { import = "lazyvim.plugins.extras.util.project" }, - }, - defaults = { - lazy = false, - version = false, - }, - -- automatically check for plugin updates - checker = { enabled = true }, -performance = { - cache = { - enabled = true, - }, - rtp = { - disabled_plugins = { - "gzip", - "netrwPlugin", - "rplugin", - "tarPlugin", - "tohtml", - "tutor", - "zipPlugin", - }, - }, - }, - ui = { - custom_keys = { - ["d"] = function(plugin) - dd(plugin) - end, - }, - }, - debug = false, + spec = { + -- add LazyVim and import its plugins + { + "LazyVim/LazyVim", + import = "lazyvim.plugins", + opts = { + colorscheme = "solarized-osaka", + news = { + lazyvim = true, + neovim = true, + }, + }, + }, + -- import any extras modules here + { import = "lazyvim.plugins.extras.linting.eslint" }, + { import = "lazyvim.plugins.extras.formatting.prettier" }, + { import = "lazyvim.plugins.extras.lang.typescript" }, + { import = "lazyvim.plugins.extras.lang.json" }, + -- { import = "lazyvim.plugins.extras.lang.markdown" }, + { import = "lazyvim.plugins.extras.lang.rust" }, + { import = "lazyvim.plugins.extras.lang.tailwind" }, + -- { import = "lazyvim.plugins.extras.ai.copilot" }, + -- { import = "lazyvim.plugins.extras.dap.core" }, + -- { import = "lazyvim.plugins.extras.vscode" }, + { import = "lazyvim.plugins.extras.util.mini-hipatterns" }, + -- { import = "lazyvim.plugins.extras.test.core" }, + -- { import = "lazyvim.plugins.extras.coding.yanky" }, + -- { import = "lazyvim.plugins.extras.editor.mini-files" }, + -- { import = "lazyvim.plugins.extras.util.project" }, + { import = "plugins" }, + }, + defaults = { + -- By default, only LazyVim plugins will be lazy-loaded. Your custom plugins will load during startup. + -- If you know what you're doing, you can set this to `true` to have all your custom plugins lazy-loaded by default. + lazy = false, + -- It's recommended to leave version=false for now, since a lot the plugin that support versioning, + -- have outdated releases, which may break your Neovim install. + version = false, -- always use the latest git commit + -- version = "*", -- try installing the latest stable version for plugins that support semver + }, + dev = { + path = "~/.ghq/github.com", + }, + checker = { enabled = true }, -- automatically check for plugin updates + performance = { + cache = { + enabled = true, + -- disable_events = {}, + }, + rtp = { + -- disable some rtp plugins + disabled_plugins = { + "gzip", + -- "matchit", + -- "matchparen", + "netrwPlugin", + "rplugin", + "tarPlugin", + "tohtml", + "tutor", + "zipPlugin", + }, + }, + }, + ui = { + custom_keys = { + ["d"] = function(plugin) + dd(plugin) + end, + }, + }, + debug = false, }) diff --git a/lua/config/options.lua b/lua/config/options.lua index 4767b8e..218f64d 100644 --- a/lua/config/options.lua +++ b/lua/config/options.lua @@ -1,7 +1,6 @@ vim.g.mapleader = " " --- open and save file as utf-8 -vim.opt.encoding = "utf-8" +vim.opt.encoding = "utf-8" vim.opt.fileencoding = "utf-8" vim.opt.number = true @@ -10,25 +9,39 @@ vim.opt.title = true vim.opt.autoindent = true vim.opt.smartindent = true vim.opt.hlsearch = true - --- disabled the file~ vim.opt.backup = false - vim.opt.showcmd = true vim.opt.cmdheight = 1 vim.opt.laststatus = 3 vim.opt.expandtab = true -vim.opt.scolloff = 10 - --- vim.opt.shell = "fish" +vim.opt.scrolloff = 10 +vim.opt.shell = "fish" vim.opt.backupskip = { "/tmp/*", "/private/tmp/*" } - --- use :substitute preview split windows vim.opt.inccommand = "split" -vim.opt.ignorecase = true +vim.opt.ignorecase = true -- Case insensitive searching UNLESS /C or capital in search vim.opt.smarttab = true vim.opt.breakindent = true -vim.opt.shiftwidth = true -vim.opt.tabstop = true -vim.opt.title = true -vim.opt.title = true +vim.opt.shiftwidth = 2 +vim.opt.tabstop = 2 +vim.opt.wrap = false -- No Wrap lines +vim.opt.backspace = { "start", "eol", "indent" } +vim.opt.path:append({ "**" }) -- Finding files - Search down into subfolders +vim.opt.wildignore:append({ "*/node_modules/*" }) +vim.opt.splitbelow = true -- Put new windows below current +vim.opt.splitright = true -- Put new windows right of current +vim.opt.splitkeep = "cursor" +vim.opt.mouse = "" + +-- Undercurl +vim.cmd([[let &t_Cs = "\e[4:3m"]]) +vim.cmd([[let &t_Ce = "\e[4:0m"]]) + +-- Add asterisks in block comments +vim.opt.formatoptions:append({ "r" }) + +vim.cmd([[au BufNewFile,BufRead *.astro setf astro]]) +vim.cmd([[au BufNewFile,BufRead Podfile setf ruby]]) + +if vim.fn.has("nvim-0.8") == 1 then + vim.opt.cmdheight = 0 +end diff --git a/lua/m1ngsama/discipline.lua b/lua/m1ngsama/discipline.lua new file mode 100644 index 0000000..ff2c0d5 --- /dev/null +++ b/lua/m1ngsama/discipline.lua @@ -0,0 +1,36 @@ +local M = {} + +function M.cowboy() + ---@type table? + local ok = true + for _, key in ipairs({ "h", "j", "k", "l", "+", "-" }) do + local count = 0 + local timer = assert(vim.uv.new_timer()) + local map = key + vim.keymap.set("n", key, function() + if vim.v.count > 0 then + count = 0 + end + if count >= 10 and vim.bo.buftype ~= "nofile" then + ok = pcall(vim.notify, "Hold it Cowboy!", vim.log.levels.WARN, { + icon = "🤠", + id = "cowboy", + keep = function() + return count >= 10 + end, + }) + if not ok then + return map + end + else + count = count + 1 + timer:start(2000, 0, function() + count = 0 + end) + return map + end + end, { expr = true, silent = true }) + end +end + +return M diff --git a/lua/m1ngsama/discipline.lua.bak b/lua/m1ngsama/discipline.lua.bak deleted file mode 100644 index eb8d071..0000000 --- a/lua/m1ngsama/discipline.lua.bak +++ /dev/null @@ -1,38 +0,0 @@ -local M = {} - -function M.trigger() - ---@type table? - local id - local ok = true - for _, key in ipairs({ "h", "j", "k", "l", "+", "-" }) do - local count = 0 - local timer = assert(vim.loop,new_timer()) - local map = key - vim.keymap.set("n", key, function() - if vim.v.count > 0 then - count = 0 - end - if count >= 10 then - ok, id = pcall(vim.notify, "Hold on! XD", vim.log.levels.WARN, { - icon = "🔫", - replace = id, - keep = function() - return count >= 10 - end, - }) - if not ok then - id = nil - retrun map - end - else - count = count + 1 - timer:start(2000, 0, function() - count = 0 - end) - return map - end - end, { expr = true, silent = true }) - end -end - -return M diff --git a/lua/m1ngsama/hsl.lua b/lua/m1ngsama/hsl.lua new file mode 100644 index 0000000..4c97404 --- /dev/null +++ b/lua/m1ngsama/hsl.lua @@ -0,0 +1,154 @@ +-- https://github.com/EmmanuelOga/columns/blob/master/utils/color.lua + +local M = {} + +local hexChars = "0123456789abcdef" + +function M.hex_to_rgb(hex) + hex = string.lower(hex) + local ret = {} + for i = 0, 2 do + local char1 = string.sub(hex, i * 2 + 2, i * 2 + 2) + local char2 = string.sub(hex, i * 2 + 3, i * 2 + 3) + local digit1 = string.find(hexChars, char1) - 1 + local digit2 = string.find(hexChars, char2) - 1 + ret[i + 1] = (digit1 * 16 + digit2) / 255.0 + end + return ret +end + +--[[ + * Converts an RGB color value to HSL. Conversion formula + * adapted from http://en.wikipedia.org/wiki/HSL_color_space. + * Assumes r, g, and b are contained in the set [0, 255] and + * returns h, s, and l in the set [0, 1]. + * + * @param Number r The red color value + * @param Number g The green color value + * @param Number b The blue color value + * @return Array The HSL representation +]] +function M.rgbToHsl(r, g, b) + local max, min = math.max(r, g, b), math.min(r, g, b) + local h = 0 + local s = 0 + local l = 0 + + l = (max + min) / 2 + + if max == min then + h, s = 0, 0 -- achromatic + else + local d = max - min + if l > 0.5 then + s = d / (2 - max - min) + else + s = d / (max + min) + end + if max == r then + h = (g - b) / d + if g < b then + h = h + 6 + end + elseif max == g then + h = (b - r) / d + 2 + elseif max == b then + h = (r - g) / d + 4 + end + h = h / 6 + end + + return h * 360, s * 100, l * 100 +end + +--[[ + * Converts an HSL color value to RGB. Conversion formula + * adapted from http://en.wikipedia.org/wiki/HSL_color_space. + * Assumes h, s, and l are contained in the set [0, 1] and + * returns r, g, and b in the set [0, 255]. + * + * @param Number h The hue + * @param Number s The saturation + * @param Number l The lightness + * @return Array The RGB representation +]] +function M.hslToRgb(h, s, l) + local r, g, b + + if s == 0 then + r, g, b = l, l, l -- achromatic + else + function hue2rgb(p, q, t) + if t < 0 then + t = t + 1 + end + if t > 1 then + t = t - 1 + end + if t < 1 / 6 then + return p + (q - p) * 6 * t + end + if t < 1 / 2 then + return q + end + if t < 2 / 3 then + return p + (q - p) * (2 / 3 - t) * 6 + end + return p + end + + local q + if l < 0.5 then + q = l * (1 + s) + else + q = l + s - l * s + end + local p = 2 * l - q + + r = hue2rgb(p, q, h + 1 / 3) + g = hue2rgb(p, q, h) + b = hue2rgb(p, q, h - 1 / 3) + end + + return r * 255, g * 255, b * 255 +end + +function M.hexToHSL(hex) + local hsluv = require("solarized-osaka.hsluv") + local rgb = M.hex_to_rgb(hex) + local h, s, l = M.rgbToHsl(rgb[1], rgb[2], rgb[3]) + + return string.format("hsl(%d, %d, %d)", math.floor(h + 0.5), math.floor(s + 0.5), math.floor(l + 0.5)) +end + +--[[ + * Converts an HSL color value to RGB in Hex representation. + * @param Number h The hue + * @param Number s The saturation + * @param Number l The lightness + * @return String The hex representation +]] +function M.hslToHex(h, s, l) + local r, g, b = M.hslToRgb(h / 360, s / 100, l / 100) + + return string.format("#%02x%02x%02x", r, g, b) +end + +function M.replaceHexWithHSL() + -- Get the current line number + local line_number = vim.api.nvim_win_get_cursor(0)[1] + + -- Get the line content + local line_content = vim.api.nvim_buf_get_lines(0, line_number - 1, line_number, false)[1] + + -- Find hex code patterns and replace them + for hex in line_content:gmatch("#[0-9a-fA-F]+") do + local hsl = M.hexToHSL(hex) + line_content = line_content:gsub(hex, hsl) + end + + -- Set the line content back + vim.api.nvim_buf_set_lines(0, line_number - 1, line_number, false, { line_content }) +end + +return M diff --git a/lua/m1ngsama/lsp.lua b/lua/m1ngsama/lsp.lua new file mode 100644 index 0000000..a52e945 --- /dev/null +++ b/lua/m1ngsama/lsp.lua @@ -0,0 +1,7 @@ +local M = {} + +function M.toggleInlayHints() + vim.lsp.inlay_hint.enable(0, not vim.lsp.inlay_hint.is_enabled()) +end + +return M diff --git a/lua/plugins/coding.lua b/lua/plugins/coding.lua new file mode 100644 index 0000000..963e401 --- /dev/null +++ b/lua/plugins/coding.lua @@ -0,0 +1,97 @@ +return { + -- Create annotations with one keybind, and jump your cursor in the inserted annotation + { + "danymat/neogen", + keys = { + { + "cc", + function() + require("neogen").generate({}) + end, + desc = "Neogen Comment", + }, + }, + opts = { snippet_engine = "luasnip" }, + }, + + -- Incremental rename + { + "smjonas/inc-rename.nvim", + cmd = "IncRename", + config = true, + }, + + -- Refactoring tool + { + "ThePrimeagen/refactoring.nvim", + keys = { + { + "r", + function() + require("refactoring").select_refactor() + end, + mode = "v", + noremap = true, + silent = true, + expr = false, + }, + }, + opts = {}, + }, + + -- Go forward/backward with square brackets + { + "echasnovski/mini.bracketed", + event = "BufReadPost", + config = function() + local bracketed = require("mini.bracketed") + bracketed.setup({ + file = { suffix = "" }, + window = { suffix = "" }, + quickfix = { suffix = "" }, + yank = { suffix = "" }, + treesitter = { suffix = "n" }, + }) + end, + }, + + -- Better increase/descrease + { + "monaqa/dial.nvim", + -- stylua: ignore + keys = { + { "", function() return require("dial.map").inc_normal() end, expr = true, desc = "Increment" }, + { "", function() return require("dial.map").dec_normal() end, expr = true, desc = "Decrement" }, + }, + config = function() + local augend = require("dial.augend") + require("dial.config").augends:register_group({ + default = { + augend.integer.alias.decimal, + augend.integer.alias.hex, + augend.date.alias["%Y/%m/%d"], + augend.constant.alias.bool, + augend.semver.alias.semver, + augend.constant.new({ elements = { "let", "const" } }), + }, + }) + end, + }, + + { + "simrat39/symbols-outline.nvim", + keys = { { "cs", "SymbolsOutline", desc = "Symbols Outline" } }, + cmd = "SymbolsOutline", + opts = { + position = "right", + }, + }, + + { + "nvim-cmp", + dependencies = { "hrsh7th/cmp-emoji" }, + opts = function(_, opts) + table.insert(opts.sources, { name = "emoji" }) + end, + }, +} diff --git a/lua/plugins/colorscheme.lua b/lua/plugins/colorscheme.lua new file mode 100644 index 0000000..b126b70 --- /dev/null +++ b/lua/plugins/colorscheme.lua @@ -0,0 +1,12 @@ +return { + { + "craftzdog/solarized-osaka.nvim", + lazy = true, + priority = 1000, + opts = function() + return { + transparent = true, + } + end, + }, +} diff --git a/lua/plugins/editor.lua b/lua/plugins/editor.lua new file mode 100644 index 0000000..507f52d --- /dev/null +++ b/lua/plugins/editor.lua @@ -0,0 +1,237 @@ +return { + { + enabled = false, + "folke/flash.nvim", + ---@type Flash.Config + opts = { + search = { + forward = true, + multi_window = false, + wrap = false, + incremental = true, + }, + }, + }, + + { + "echasnovski/mini.hipatterns", + event = "BufReadPre", + opts = { + highlighters = { + hsl_color = { + pattern = "hsl%(%d+,? %d+%%?,? %d+%%?%)", + group = function(_, match) + local utils = require("solarized-osaka.hsl") + --- @type string, string, string + local nh, ns, nl = match:match("hsl%((%d+),? (%d+)%%?,? (%d+)%%?%)") + --- @type number?, number?, number? + local h, s, l = tonumber(nh), tonumber(ns), tonumber(nl) + --- @type string + local hex_color = utils.hslToHex(h, s, l) + return MiniHipatterns.compute_hex_color_group(hex_color, "bg") + end, + }, + }, + }, + }, + + { + "dinhhuy258/git.nvim", + event = "BufReadPre", + opts = { + keymaps = { + -- Open blame window + blame = "gb", + -- Open file/folder in git repository + browse = "go", + }, + }, + }, + + { + "nvim-telescope/telescope.nvim", + dependencies = { + { + "nvim-telescope/telescope-fzf-native.nvim", + build = "make", + }, + "nvim-telescope/telescope-file-browser.nvim", + }, + keys = { + { + "fP", + function() + require("telescope.builtin").find_files({ + cwd = require("lazy.core.config").options.root, + }) + end, + desc = "Find Plugin File", + }, + { + ";f", + function() + local builtin = require("telescope.builtin") + builtin.find_files({ + no_ignore = false, + hidden = true, + }) + end, + desc = "Lists files in your current working directory, respects .gitignore", + }, + { + ";r", + function() + local builtin = require("telescope.builtin") + builtin.live_grep({ + additional_args = { "--hidden" }, + }) + end, + desc = "Search for a string in your current working directory and get results live as you type, respects .gitignore", + }, + { + "\\\\", + function() + local builtin = require("telescope.builtin") + builtin.buffers() + end, + desc = "Lists open buffers", + }, + { + ";t", + function() + local builtin = require("telescope.builtin") + builtin.help_tags() + end, + desc = "Lists available help tags and opens a new window with the relevant help info on ", + }, + { + ";;", + function() + local builtin = require("telescope.builtin") + builtin.resume() + end, + desc = "Resume the previous telescope picker", + }, + { + ";e", + function() + local builtin = require("telescope.builtin") + builtin.diagnostics() + end, + desc = "Lists Diagnostics for all open buffers or a specific buffer", + }, + { + ";s", + function() + local builtin = require("telescope.builtin") + builtin.treesitter() + end, + desc = "Lists Function names, variables, from Treesitter", + }, + { + "sf", + function() + local telescope = require("telescope") + + local function telescope_buffer_dir() + return vim.fn.expand("%:p:h") + end + + telescope.extensions.file_browser.file_browser({ + path = "%:p:h", + cwd = telescope_buffer_dir(), + respect_gitignore = false, + hidden = true, + grouped = true, + previewer = false, + initial_mode = "normal", + layout_config = { height = 40 }, + }) + end, + desc = "Open File Browser with the path of the current buffer", + }, + }, + config = function(_, opts) + local telescope = require("telescope") + local actions = require("telescope.actions") + local fb_actions = require("telescope").extensions.file_browser.actions + + opts.defaults = vim.tbl_deep_extend("force", opts.defaults, { + wrap_results = true, + layout_strategy = "horizontal", + layout_config = { prompt_position = "top" }, + sorting_strategy = "ascending", + winblend = 0, + mappings = { + n = {}, + }, + }) + opts.pickers = { + diagnostics = { + theme = "ivy", + initial_mode = "normal", + layout_config = { + preview_cutoff = 9999, + }, + }, + } + opts.extensions = { + file_browser = { + theme = "dropdown", + -- disables netrw and use telescope-file-browser in its place + hijack_netrw = true, + mappings = { + -- your custom insert mode mappings + ["n"] = { + -- your custom normal mode mappings + ["N"] = fb_actions.create, + ["h"] = fb_actions.goto_parent_dir, + ["/"] = function() + vim.cmd("startinsert") + end, + [""] = function(prompt_bufnr) + for i = 1, 10 do + actions.move_selection_previous(prompt_bufnr) + end + end, + [""] = function(prompt_bufnr) + for i = 1, 10 do + actions.move_selection_next(prompt_bufnr) + end + end, + [""] = actions.preview_scrolling_up, + [""] = actions.preview_scrolling_down, + }, + }, + }, + } + telescope.setup(opts) + require("telescope").load_extension("fzf") + require("telescope").load_extension("file_browser") + end, + }, + + { + "saghen/blink.cmp", + opts = { + completion = { + menu = { + winblend = vim.o.pumblend, + }, + }, + signature = { + window = { + winblend = vim.o.pumblend, + }, + }, + }, + }, + + { + "3rd/image.nvim", + build = false, -- so that it doesn't build the rock https://github.com/3rd/image.nvim/issues/91#issuecomment-2453430239 + opts = { + processor = "magick_cli", + }, + }, +} diff --git a/lua/lsp.lua b/lua/plugins/lsp.lua similarity index 88% rename from lua/lsp.lua rename to lua/plugins/lsp.lua index 47815be..3f03ea8 100644 --- a/lua/lsp.lua +++ b/lua/plugins/lsp.lua @@ -12,6 +12,7 @@ return { "tailwindcss-language-server", "typescript-language-server", "css-lsp", + "clangd", }) end, }, @@ -132,6 +133,28 @@ return { }, }, }, + gopls = { + settings = { + gopls = { + analyses = { + unusedparams = true, + shadow = true, + }, + staticcheck = true, + }, + }, + }, + clangd = { + cmd = { "clangd", "--background-index" }, + filetypes = { "c", "cpp", "objc", "objcpp" }, + root_dir = function(...) + return require("lspconfig.util").root_pattern( + "compile_commands.json", + "compile_flags.txt", + ".git" + )(...) + end, + }, }, setup = {}, }, diff --git a/lua/plugins/treesitter.lua b/lua/plugins/treesitter.lua new file mode 100644 index 0000000..f3443d2 --- /dev/null +++ b/lua/plugins/treesitter.lua @@ -0,0 +1,67 @@ +return { + { "nvim-treesitter/playground", cmd = "TSPlaygroundToggle" }, + + { + "nvim-treesitter/nvim-treesitter", + opts = { + ensure_installed = { + "astro", + "cmake", + "cpp", + "css", + "fish", + "gitignore", + "go", + "graphql", + "http", + "java", + "php", + "rust", + "scss", + "sql", + "svelte", + }, + + -- matchup = { + -- enable = true, + -- }, + + -- https://github.com/nvim-treesitter/playground#query-linter + query_linter = { + enable = true, + use_virtual_text = true, + lint_events = { "BufWrite", "CursorHold" }, + }, + + playground = { + enable = true, + disable = {}, + updatetime = 25, -- Debounced time for highlighting nodes in the playground from source code + persist_queries = true, -- Whether the query persists across vim sessions + keybindings = { + toggle_query_editor = "o", + toggle_hl_groups = "i", + toggle_injected_languages = "t", + toggle_anonymous_nodes = "a", + toggle_language_display = "I", + focus_language = "f", + unfocus_language = "F", + update = "R", + goto_node = "", + show_help = "?", + }, + }, + }, + config = function(_, opts) + require("nvim-treesitter.configs").setup(opts) + + -- MDX + vim.filetype.add({ + extension = { + mdx = "mdx", + }, + }) + vim.treesitter.language.register("markdown", "mdx") + end, + }, +} diff --git a/lua/plugins/ui.lua b/lua/plugins/ui.lua new file mode 100644 index 0000000..692fd8f --- /dev/null +++ b/lua/plugins/ui.lua @@ -0,0 +1,170 @@ +return { + -- messages, cmdline and the popupmenu + { + "folke/noice.nvim", + opts = function(_, opts) + table.insert(opts.routes, { + filter = { + event = "notify", + find = "No information available", + }, + opts = { skip = true }, + }) + local focused = true + vim.api.nvim_create_autocmd("FocusGained", { + callback = function() + focused = true + end, + }) + vim.api.nvim_create_autocmd("FocusLost", { + callback = function() + focused = false + end, + }) + table.insert(opts.routes, 1, { + filter = { + cond = function() + return not focused + end, + }, + view = "notify_send", + opts = { stop = false }, + }) + + opts.commands = { + all = { + -- options for the message history that you get with `:Noice` + view = "split", + opts = { enter = true, format = "details" }, + filter = {}, + }, + } + + vim.api.nvim_create_autocmd("FileType", { + pattern = "markdown", + callback = function(event) + vim.schedule(function() + require("noice.text.markdown").keys(event.buf) + end) + end, + }) + + opts.presets.lsp_doc_border = true + end, + }, + + { + "rcarriga/nvim-notify", + opts = { + timeout = 5000, + }, + }, + + { + "snacks.nvim", + opts = { + scroll = { enabled = false }, + }, + keys = {}, + }, + + -- buffer line + { + "akinsho/bufferline.nvim", + event = "VeryLazy", + keys = { + { "", "BufferLineCycleNext", desc = "Next tab" }, + { "", "BufferLineCyclePrev", desc = "Prev tab" }, + }, + opts = { + options = { + mode = "tabs", + -- separator_style = "slant", + show_buffer_close_icons = false, + show_close_icon = false, + }, + }, + }, + + -- filename + { + "b0o/incline.nvim", + dependencies = { "craftzdog/solarized-osaka.nvim" }, + event = "BufReadPre", + priority = 1200, + config = function() + local colors = require("solarized-osaka.colors").setup() + require("incline").setup({ + highlight = { + groups = { + InclineNormal = { guibg = colors.magenta500, guifg = colors.base04 }, + InclineNormalNC = { guifg = colors.violet500, guibg = colors.base03 }, + }, + }, + window = { margin = { vertical = 0, horizontal = 1 } }, + hide = { + cursorline = true, + }, + render = function(props) + local filename = vim.fn.fnamemodify(vim.api.nvim_buf_get_name(props.buf), ":t") + if vim.bo[props.buf].modified then + filename = "[+] " .. filename + end + + local icon, color = require("nvim-web-devicons").get_icon_color(filename) + return { { icon, guifg = color }, { " " }, { filename } } + end, + }) + end, + }, + + -- statusline + { + "nvim-lualine/lualine.nvim", + opts = function(_, opts) + local LazyVim = require("lazyvim.util") + opts.sections.lualine_c[4] = { + LazyVim.lualine.pretty_path({ + length = 0, + relative = "cwd", + modified_hl = "MatchParen", + directory_hl = "", + filename_hl = "Bold", + modified_sign = "", + readonly_icon = " 󰌾 ", + }), + } + end, + }, + + { + "folke/zen-mode.nvim", + cmd = "ZenMode", + opts = { + plugins = { + gitsigns = true, + tmux = true, + kitty = { enabled = false, font = "+2" }, + }, + }, + keys = { { "z", "ZenMode", desc = "Zen Mode" } }, + }, + + { + "folke/snacks.nvim", + opts = { + dashboard = { + preset = { + header = [[ + ██████╗ ███████╗██╗ ██╗ █████╗ ███████╗██╗ ██╗███████╗███████╗ + ██╔══██╗██╔════╝██║ ██║██╔══██╗██╔════╝██║ ██║██╔════╝██╔════╝ + ██║ ██║█████╗ ██║ ██║███████║███████╗██║ ██║█████╗ █████╗ + ██║ ██║██╔══╝ ╚██╗ ██╔╝██╔══██║╚════██║██║ ██║██╔══╝ ██╔══╝ + ██████╔╝███████╗ ╚████╔╝ ██║ ██║███████║███████╗██║██║ ███████╗ + ╚═════╝ ╚══════╝ ╚═══╝ ╚═╝ ╚═╝╚══════╝╚══════╝╚═╝╚═╝ ╚══════╝ + ]], + }, + }, + }, + }, +} diff --git a/lua/util/debug.lua b/lua/util/debug.lua new file mode 100644 index 0000000..136823f --- /dev/null +++ b/lua/util/debug.lua @@ -0,0 +1,158 @@ +-- selene: allow(global_usage) + +local M = {} + +function M.get_loc() + local me = debug.getinfo(1, "S") + local level = 2 + local info = debug.getinfo(level, "S") + while info and (info.source == me.source or info.source == "@" .. vim.env.MYVIMRC or info.what ~= "Lua") do + level = level + 1 + info = debug.getinfo(level, "S") + end + info = info or me + local source = info.source:sub(2) + source = vim.loop.fs_realpath(source) or source + return source .. ":" .. info.linedefined +end + +---@param value any +---@param opts? {loc:string} +function M._dump(value, opts) + opts = opts or {} + opts.loc = opts.loc or M.get_loc() + if vim.in_fast_event() then + return vim.schedule(function() + M._dump(value, opts) + end) + end + opts.loc = vim.fn.fnamemodify(opts.loc, ":~:.") + local msg = vim.inspect(value) + vim.notify(msg, vim.log.levels.INFO, { + title = "Debug: " .. opts.loc, + on_open = function(win) + vim.wo[win].conceallevel = 3 + vim.wo[win].concealcursor = "" + vim.wo[win].spell = false + local buf = vim.api.nvim_win_get_buf(win) + if not pcall(vim.treesitter.start, buf, "lua") then + vim.bo[buf].filetype = "lua" + end + end, + }) +end + +function M.dump(...) + local value = { ... } + if vim.tbl_isempty(value) then + value = nil + else + value = vim.tbl_islist(value) and vim.tbl_count(value) <= 1 and value[1] or value + end + M._dump(value) +end + +function M.extmark_leaks() + local nsn = vim.api.nvim_get_namespaces() + + local counts = {} + + for name, ns in pairs(nsn) do + for _, buf in ipairs(vim.api.nvim_list_bufs()) do + local count = #vim.api.nvim_buf_get_extmarks(buf, ns, 0, -1, {}) + if count > 0 then + counts[#counts + 1] = { + name = name, + buf = buf, + count = count, + ft = vim.bo[buf].ft, + } + end + end + end + table.sort(counts, function(a, b) + return a.count > b.count + end) + dd(counts) +end + +function estimateSize(value, visited) + if value == nil then + return 0 + end + local bytes = 0 + + -- initialize the visited table if not already done + --- @type table + visited = visited or {} + + -- handle already-visited value to avoid infinite recursion + if visited[value] then + return 0 + else + visited[value] = true + end + + if type(value) == "boolean" or value == nil then + bytes = 4 + elseif type(value) == "number" then + bytes = 8 + elseif type(value) == "string" then + bytes = string.len(value) + 24 + elseif type(value) == "function" then + bytes = 32 -- base size for a function + -- add size of upvalues + local i = 1 + while true do + local name, val = debug.getupvalue(value, i) + if not name then + break + end + bytes = bytes + estimateSize(val, visited) + i = i + 1 + end + elseif type(value) == "table" then + bytes = 40 -- base size for a table entry + for k, v in pairs(value) do + bytes = bytes + estimateSize(k, visited) + estimateSize(v, visited) + end + local mt = debug.getmetatable(value) + if mt then + bytes = bytes + estimateSize(mt, visited) + end + end + return bytes +end + +function M.module_leaks(filter) + local sizes = {} + for modname, mod in pairs(package.loaded) do + if not filter or modname:match(filter) then + local root = modname:match("^([^%.]+)%..*$") or modname + -- root = modname + sizes[root] = sizes[root] or { mod = root, size = 0 } + sizes[root].size = sizes[root].size + estimateSize(mod) / 1024 / 1024 + end + end + sizes = vim.tbl_values(sizes) + table.sort(sizes, function(a, b) + return a.size > b.size + end) + dd(sizes) +end + +function M.get_upvalue(func, name) + local i = 1 + while true do + local n, v = debug.getupvalue(func, i) + if not n then + break + end + if n == name then + return v + end + i = i + 1 + end +end + +return M