diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 00000000000..960f340fc29 Binary files /dev/null and b/.DS_Store differ diff --git a/.gitignore b/.gitignore index 005b535b606..2b4c29baf91 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,5 @@ tags test.sh .luarc.json nvim - spell/ lazy-lock.json diff --git a/init.lua b/init.lua index b98ffc6198a..04d62fff8c5 100644 --- a/init.lua +++ b/init.lua @@ -1,7 +1,23 @@ --[[ ===================================================================== -==================== READ THIS BEFORE CONTINUING ==================== +===================== READ THIS BEFORE CONTINUING ==================== +===================================================================== +======== .-----. ======== +======== .----------------------. | === | ======== +======== |.-""""""""""""""""""-.| |-----| ======== +======== || || | === | ======== +======== || KICKSTART.NVIM || |-----| ======== +======== || || | === | ======== +======== || || |-----| ======== +======== ||:Tutor || |:::::| ======== +======== |'-..................-'| |____o| ======== +======== `"")----------------(""` ___________ ======== +======== /::::::::::| |::::::::::\ \ no mouse \ ======== +======== /:::========| |==hjkl==:::\ \ required \ ======== +======== '""""""""""""' '""""""""""""' '""""""""""' ======== +======== ======== +===================================================================== ===================================================================== ======== .-----. ======== ======== .----------------------. | === | ======== @@ -407,11 +423,53 @@ require('lazy').setup({ -- You can put your default mappings / updates / etc. in here -- All the info you're looking for is in `:help telescope.setup()` -- - -- defaults = { - -- mappings = { - -- i = { [''] = 'to_fuzzy_refine' }, - -- }, - -- }, + defaults = { + mappings = { + i = { + [''] = 'move_selection_next', + [''] = 'move_selection_previous', + }, + }, + file_ignore_patterns = { '.git/' }, + }, + pickers = { + find_files = { + hidden = true, + -- Include .env.local files even if they're gitignored + find_command = { + 'rg', '--files', '--hidden', '--no-ignore-vcs', + '--glob', '!.git/*', + '--glob', '!node_modules/*', + '--glob', '!.next/*', + '--glob', '!dist/*', + '--glob', '!build/*', + }, + }, + live_grep = { + additional_args = function() + return { + '--hidden', '--no-ignore-vcs', + '--glob', '!.git/*', + '--glob', '!node_modules/*', + '--glob', '!.next/*', + '--glob', '!dist/*', + '--glob', '!build/*', + } + end, + }, + grep_string = { + additional_args = function() + return { + '--hidden', '--no-ignore-vcs', + '--glob', '!.git/*', + '--glob', '!node_modules/*', + '--glob', '!.next/*', + '--glob', '!dist/*', + '--glob', '!build/*', + } + end, + }, + }, -- pickers = {} extensions = { ['ui-select'] = { @@ -426,19 +484,20 @@ require('lazy').setup({ -- See `:help telescope.builtin` local builtin = require 'telescope.builtin' - vim.keymap.set('n', 'sh', builtin.help_tags, { desc = '[S]earch [H]elp' }) - vim.keymap.set('n', 'sk', builtin.keymaps, { desc = '[S]earch [K]eymaps' }) - vim.keymap.set('n', 'sf', builtin.find_files, { desc = '[S]earch [F]iles' }) - vim.keymap.set('n', 'ss', builtin.builtin, { desc = '[S]earch [S]elect Telescope' }) - vim.keymap.set('n', 'sw', builtin.grep_string, { desc = '[S]earch current [W]ord' }) - vim.keymap.set('n', 'sg', builtin.live_grep, { desc = '[S]earch by [G]rep' }) - vim.keymap.set('n', 'sd', builtin.diagnostics, { desc = '[S]earch [D]iagnostics' }) - vim.keymap.set('n', 'sr', builtin.resume, { desc = '[S]earch [R]esume' }) - vim.keymap.set('n', 's.', builtin.oldfiles, { desc = '[S]earch Recent Files ("." for repeat)' }) - vim.keymap.set('n', '', builtin.buffers, { desc = '[ ] Find existing buffers' }) + vim.keymap.set('n', 'fh', builtin.help_tags, { desc = '[F]ind [H]elp' }) + vim.keymap.set('n', 'fk', builtin.keymaps, { desc = '[F]ind [K]eymaps' }) + vim.keymap.set('n', 'ff', builtin.find_files, { desc = '[F]ind [F]iles' }) + vim.keymap.set('n', 'fs', builtin.builtin, { desc = '[F]ind [S]elect Telescope' }) + vim.keymap.set('n', 'fw', builtin.grep_string, { desc = '[F]ind current [W]ord' }) + vim.keymap.set('n', 'fg', builtin.live_grep, { desc = '[F]ind by [G]rep' }) + vim.keymap.set('n', '', builtin.live_grep, { desc = '[F]ind by [G]rep' }) + vim.keymap.set('n', 'fd', builtin.diagnostics, { desc = '[F]ind [D]iagnostics' }) + vim.keymap.set('n', 'fr', builtin.resume, { desc = '[F]ind [R]esume' }) + vim.keymap.set('n', 'f.', builtin.oldfiles, { desc = '[F]ind Recent Files ("." for repeat)' }) + vim.keymap.set('n', '/', builtin.buffers, { desc = '[ ] Find existing buffers' }) -- Slightly advanced example of overriding default behavior and theme - vim.keymap.set('n', '/', function() + vim.keymap.set('n', 'f/', function() -- You can pass additional configuration to Telescope to change the theme, layout, etc. builtin.current_buffer_fuzzy_find(require('telescope.themes').get_dropdown { winblend = 10, @@ -534,7 +593,12 @@ require('lazy').setup({ mode = mode or 'n' vim.keymap.set(mode, keys, func, { buffer = event.buf, desc = 'LSP: ' .. desc }) end - + vim.api.nvim_create_autocmd({ 'LspAttach' }, { + callback = function() + -- Map 'gd' to go to definition using Telescope's LSP definitions picker + vim.keymap.set('n', 'gd', require('telescope.builtin').lsp_definitions, { buffer = 0, desc = 'Go to definition' }) + end, + }) -- Rename the variable under your cursor. -- Most Language Servers support renaming across files, etc. map('grn', vim.lsp.buf.rename, '[R]e[n]ame') @@ -681,7 +745,8 @@ require('lazy').setup({ -- https://github.com/pmizio/typescript-tools.nvim -- -- But for many setups, the LSP (`ts_ls`) will work just fine - -- ts_ls = {}, + ts_ls = {}, + cssls = {}, -- lua_ls = { @@ -733,6 +798,63 @@ require('lazy').setup({ end, }, } + + local vue_language_server_path = vim.fn.expand '$MASON/packages' .. '/vue-language-server' .. '/node_modules/@vue/language-server' + local vue_plugin = { + name = '@vue/typescript-plugin', + location = vue_language_server_path, + languages = { 'vue' }, + configNamespace = 'typescript', + } + + local vtsls_config = { + settings = { + vtsls = { + tsserver = { + globalPlugins = { + vue_plugin, + }, + }, + }, + }, + filetypes = { 'typescript', 'javascript', 'javascriptreact', 'typescriptreact', 'vue' }, + } + + local vue_ls_config = { + on_init = function(client) + client.handlers['tsserver/request'] = function(_, result, context) + local clients = vim.lsp.get_clients { bufnr = context.bufnr, name = 'vtsls' } + if #clients == 0 then + vim.notify('Could not find `vtsls` lsp client, `vue_ls` would not work without it.', vim.log.levels.ERROR) + return + end + local ts_client = clients[1] + + local param = unpack(result) + local id, command, payload = unpack(param) + ts_client:exec_cmd({ + title = 'vue_request_forward', -- You can give title anything as it's used to represent a command in the UI, `:h Client:exec_cmd` + command = 'typescript.tsserverRequest', + arguments = { + command, + payload, + }, + }, { bufnr = context.bufnr }, function(_, r) + local response = r and r.body + -- TODO: handle error or response nil here, e.g. logging + -- NOTE: Do NOT return if there's an error or no response, just return nil back to the vue_ls to prevent memory leak + local response_data = { { id, response } } + + ---@diagnostic disable-next-line: param-type-mismatch + client:notify('tsserver/response', response_data) + end) + end + end, + } + -- nvim 0.11 or above + vim.lsp.config('vtsls', vtsls_config) + vim.lsp.config('vue_ls', vue_ls_config) + vim.lsp.enable { 'vtsls', 'vue_ls' } end, }, @@ -749,10 +871,28 @@ require('lazy').setup({ mode = '', desc = '[F]ormat buffer', }, + { + 'F', + function() + vim.g.disable_autoformat = not vim.g.disable_autoformat + if vim.g.disable_autoformat then + print('Autoformat disabled') + else + print('Autoformat enabled') + end + end, + mode = '', + desc = 'Toggle auto[F]ormat on save', + }, }, opts = { notify_on_error = false, format_on_save = function(bufnr) + -- Check if autoformat is globally disabled + if vim.g.disable_autoformat then + return nil + end + -- Disable "format_on_save lsp_fallback" for languages that don't -- have a well standardized coding style. You can add additional -- languages here or re-enable it for the disabled ones. @@ -768,11 +908,17 @@ require('lazy').setup({ end, formatters_by_ft = { lua = { 'stylua' }, - -- Conform can also run multiple formatters sequentially - -- python = { "isort", "black" }, - -- - -- You can use 'stop_after_first' to run the first available formatter from the list - -- javascript = { "prettierd", "prettier", stop_after_first = true }, + javascript = { 'prettierd', 'prettier', stop_after_first = true }, + typescript = { 'prettierd', 'prettier', stop_after_first = true }, + javascriptreact = { 'prettierd', 'prettier', stop_after_first = true }, + typescriptreact = { 'prettierd', 'prettier', stop_after_first = true }, + vue = { 'prettierd', 'prettier', stop_after_first = true }, + css = { 'prettierd', 'prettier', stop_after_first = true }, + scss = { 'prettierd', 'prettier', stop_after_first = true }, + html = { 'prettierd', 'prettier', stop_after_first = true }, + json = { 'prettierd', 'prettier', stop_after_first = true }, + yaml = { 'prettierd', 'prettier', stop_after_first = true }, + markdown = { 'prettierd', 'prettier', stop_after_first = true }, }, }, }, @@ -832,10 +978,11 @@ require('lazy').setup({ -- : Open menu or open docs if already open -- / or /: Select next/previous item -- : Hide menu - -- : Toggle signature help -- -- See :h blink-cmp-config-keymap for defining your own keymap - preset = 'default', + preset = 'super-tab', + [''] = { 'select_next', 'fallback' }, + [''] = { 'select_prev', 'fallback' }, -- For more advanced Luasnip keymaps (e.g. selecting choice nodes, expansion) see: -- https://github.com/L3MON4D3/LuaSnip?tab=readme-ov-file#keymaps @@ -851,6 +998,11 @@ require('lazy').setup({ -- By default, you may press `` to show the documentation. -- Optionally, set `auto_show = true` to show the documentation after a delay. documentation = { auto_show = false, auto_show_delay_ms = 500 }, + menu = { + border = 'rounded', + -- Show completion menu at cursor position + direction_priority = { 's', 'n' }, + }, }, sources = { @@ -876,28 +1028,6 @@ require('lazy').setup({ }, }, - { -- You can easily change to a different colorscheme. - -- Change the name of the colorscheme plugin below, and then - -- change the command in the config to whatever the name of that colorscheme is. - -- - -- If you want to see what colorschemes are already installed, you can use `:Telescope colorscheme`. - 'folke/tokyonight.nvim', - priority = 1000, -- Make sure to load this before all the other start plugins. - config = function() - ---@diagnostic disable-next-line: missing-fields - require('tokyonight').setup { - styles = { - comments = { italic = false }, -- Disable italics in comments - }, - } - - -- Load the colorscheme here. - -- Like many other themes, this one has different styles, and you could load - -- any other, such as 'tokyonight-storm', 'tokyonight-moon', or 'tokyonight-day'. - vim.cmd.colorscheme 'tokyonight-night' - end, - }, - -- Highlight todo, notes, etc in comments { 'folke/todo-comments.nvim', event = 'VimEnter', dependencies = { 'nvim-lua/plenary.nvim' }, opts = { signs = false } }, @@ -941,10 +1071,13 @@ require('lazy').setup({ { -- Highlight, edit, and navigate code 'nvim-treesitter/nvim-treesitter', build = ':TSUpdate', + dependencies = { + 'nvim-treesitter/nvim-treesitter-textobjects', + }, main = 'nvim-treesitter.configs', -- Sets main module to use for opts -- [[ Configure Treesitter ]] See `:help nvim-treesitter` opts = { - ensure_installed = { 'bash', 'c', 'diff', 'html', 'lua', 'luadoc', 'markdown', 'markdown_inline', 'query', 'vim', 'vimdoc' }, + ensure_installed = { 'bash', 'c', 'diff', 'html', 'lua', 'luadoc', 'markdown', 'markdown_inline', 'query', 'vim', 'vimdoc', 'vue', 'javascript', 'typescript', 'css' }, -- Autoinstall languages that are not installed auto_install = true, highlight = { @@ -955,6 +1088,44 @@ require('lazy').setup({ additional_vim_regex_highlighting = { 'ruby' }, }, indent = { enable = true, disable = { 'ruby' } }, + textobjects = { + select = { + enable = true, + lookahead = true, -- Automatically jump forward to textobj + keymaps = { + ['af'] = '@function.outer', + ['if'] = '@function.inner', + ['ac'] = '@class.outer', + ['ic'] = '@class.inner', + ['aa'] = '@parameter.outer', + ['ia'] = '@parameter.inner', + }, + }, + move = { + enable = true, + set_jumps = true, -- Add to jumplist + goto_next_start = { + [']m'] = '@function.outer', + [']c'] = '@class.outer', + [']a'] = '@parameter.inner', + }, + goto_next_end = { + [']M'] = '@function.outer', + [']C'] = '@class.outer', + [']A'] = '@parameter.inner', + }, + goto_previous_start = { + ['[m'] = '@function.outer', + ['[c'] = '@class.outer', + ['[a'] = '@parameter.inner', + }, + goto_previous_end = { + ['[M'] = '@function.outer', + ['[C'] = '@class.outer', + ['[A'] = '@parameter.inner', + }, + }, + }, }, -- There are additional nvim-treesitter modules that you can use to interact -- with nvim-treesitter. You should go explore a few and see what interests you: @@ -984,8 +1155,10 @@ require('lazy').setup({ -- This is the easiest way to modularize your config. -- -- Uncomment the following line and add your plugins to `lua/custom/plugins/*.lua` to get going. - -- { import = 'custom.plugins' }, + { import = 'custom.plugins' }, + { import = 'custom.themes' }, -- + -- For additional information with loading, sourcing and examples see `:help lazy.nvim-🔌-plugin-spec` -- Or use telescope! -- In normal mode type `sh` then write `lazy.nvim-plugin` @@ -1012,5 +1185,7 @@ require('lazy').setup({ }, }) +require 'arnoldlei.set' +require 'arnoldlei.remap' -- The line beneath this is called `modeline`. See `:help modeline` -- vim: ts=2 sts=2 sw=2 et diff --git a/lazy-lock.json b/lazy-lock.json new file mode 100644 index 00000000000..95d26921d83 --- /dev/null +++ b/lazy-lock.json @@ -0,0 +1,36 @@ +{ + "Comment.nvim": { "branch": "master", "commit": "e30b7f2008e52442154b66f7c519bfd2f1e32acb" }, + "LuaSnip": { "branch": "master", "commit": "73813308abc2eaeff2bc0d3f2f79270c491be9d7" }, + "blink.cmp": { "branch": "main", "commit": "327fff91fe6af358e990be7be1ec8b78037d2138" }, + "catppuccin": { "branch": "main", "commit": "da33755d00e09bff2473978910168ff9ea5dc453" }, + "conform.nvim": { "branch": "master", "commit": "cde4da5c1083d3527776fee69536107d98dae6c9" }, + "curl.nvim": { "branch": "main", "commit": "3ee14fbafc8169fc803e80562ce7ac5b4474bdff" }, + "fidget.nvim": { "branch": "main", "commit": "e32b672d8fd343f9d6a76944fedb8c61d7d8111a" }, + "git-blame.nvim": { "branch": "master", "commit": "9874ec1ec8bc53beb33b7cd82c092b85271a578b" }, + "github-theme": { "branch": "main", "commit": "c106c9472154d6b2c74b74565616b877ae8ed31d" }, + "gitsigns.nvim": { "branch": "main", "commit": "20ad4419564d6e22b189f6738116b38871082332" }, + "guess-indent.nvim": { "branch": "main", "commit": "84a4987ff36798c2fc1169cbaff67960aed9776f" }, + "harpoon": { "branch": "harpoon2", "commit": "87b1a3506211538f460786c23f98ec63ad9af4e5" }, + "lazy.nvim": { "branch": "main", "commit": "85c7ff3711b730b4030d03144f6db6375044ae82" }, + "lazydev.nvim": { "branch": "main", "commit": "5231c62aa83c2f8dc8e7ba957aa77098cda1257d" }, + "lazygit.nvim": { "branch": "main", "commit": "2305deed25bc61b866d5d39189e9105a45cf1cfb" }, + "mason-lspconfig.nvim": { "branch": "main", "commit": "b1d9a914b02ba5660f1e272a03314b31d4576fe2" }, + "mason-tool-installer.nvim": { "branch": "main", "commit": "517ef5994ef9d6b738322664d5fdd948f0fdeb46" }, + "mason.nvim": { "branch": "main", "commit": "57e5a8addb8c71fb063ee4acda466c7cf6ad2800" }, + "mini.icons": { "branch": "main", "commit": "ff2e4f1d29f659cc2bad0f9256f2f6195c6b2428" }, + "mini.nvim": { "branch": "main", "commit": "dce9bc4e19d02d5c37fe71c16f40f8a5536b0386" }, + "monokai-pro.nvim": { "branch": "master", "commit": "1ac671f6da720cba967d28d25c2f16b8b4e18808" }, + "nightfox.nvim": { "branch": "main", "commit": "ba47d4b4c5ec308718641ba7402c143836f35aa9" }, + "nvim-lspconfig": { "branch": "master", "commit": "95fe3c170753238d3ca4f760e79a991400677abc" }, + "nvim-treesitter": { "branch": "master", "commit": "42fc28ba918343ebfd5565147a42a26580579482" }, + "oil.nvim": { "branch": "master", "commit": "7e1cd7703ff2924d7038476dcbc04b950203b902" }, + "onedark.nvim": { "branch": "master", "commit": "6c10964f91321c6a0f09bcc41dd64e7a6602bc4f" }, + "oxocarbon.nvim": { "branch": "main", "commit": "9f85f6090322f39b11ae04a343d4eb9d12a86897" }, + "plenary.nvim": { "branch": "master", "commit": "b9fd5226c2f76c951fc8ed5923d85e4de065e509" }, + "telescope-fzf-native.nvim": { "branch": "main", "commit": "6fea601bd2b694c6f2ae08a6c6fab14930c60e2c" }, + "telescope-ui-select.nvim": { "branch": "master", "commit": "6e51d7da30bd139a6950adf2a47fda6df9fa06d2" }, + "telescope.nvim": { "branch": "master", "commit": "3a12a853ebf21ec1cce9a92290e3013f8ae75f02" }, + "todo-comments.nvim": { "branch": "main", "commit": "31e3c38ce9b29781e4422fc0322eb0a21f4e8668" }, + "tokyonight.nvim": { "branch": "main", "commit": "5da1b76e64daf4c5d410f06bcb6b9cb640da7dfd" }, + "which-key.nvim": { "branch": "main", "commit": "3aab2147e74890957785941f0c1ad87d0a44c15a" } +} diff --git a/lua/.DS_Store b/lua/.DS_Store new file mode 100644 index 00000000000..5ffd638f0aa Binary files /dev/null and b/lua/.DS_Store differ diff --git a/lua/arnoldlei/remap.lua b/lua/arnoldlei/remap.lua new file mode 100644 index 00000000000..653be3d3a6b --- /dev/null +++ b/lua/arnoldlei/remap.lua @@ -0,0 +1,70 @@ +vim.g.mapleader = ' ' +vim.keymap.set('n', '-', 'Oil', { desc = 'Open parent directory' }) +vim.keymap.set('n', 'pv', 'Oil', { desc = 'Open parent directory' }) + +-- Window splits +vim.keymap.set('n', '|', 'vsplit', { desc = 'Split window vertically' }) +vim.keymap.set('n', '_', 'split', { desc = 'Split window horizontally' }) + +-- Window navigation +-- vim.keymap.set('n', '', 'h', { desc = 'Move to left window' }) +-- vim.keymap.set('n', '', 'j', { desc = 'Move to window below' }) +-- vim.keymap.set('n', '', 'k', { desc = 'Move to window above' }) +-- vim.keymap.set('n', '', 'l', { desc = 'Move to right window' }) + +vim.keymap.set('v', 'J', ":m '>+1gv=gv") +vim.keymap.set('v', 'K', ":m '<-2gv=gv") + +vim.keymap.set('n', 'J', 'mzJ`z') +vim.keymap.set('n', '', 'zz') +vim.keymap.set('n', '', 'zz') +vim.keymap.set('n', 'n', 'nzzzv') +vim.keymap.set('n', 'N', 'Nzzzv') + +-- greatest remap ever +vim.keymap.set('x', 'p', [["_dP]]) + +-- next greatest remap ever : asbjornHaland +vim.keymap.set({ 'n', 'v' }, 'y', [["+y]]) +vim.keymap.set('n', 'Y', [["+Y]]) + +vim.keymap.set({ 'n', 'v' }, 'd', [["_d]]) + +-- This is going to get me cancelled +vim.keymap.set('i', '', '') + +vim.keymap.set('n', 'Q', '') +vim.keymap.set('n', '', 'silent !tmux neww tmux-sessionizer') +vim.keymap.set('n', 'f', vim.lsp.buf.format) + +-- vim.keymap.set("n", "", "cnextzz") +-- vim.keymap.set("n", "", "cprevzz") +vim.keymap.set('n', 'k', 'lnextzz') +vim.keymap.set('n', 'j', 'lprevzz') + +vim.keymap.set('n', 's', [[:%s/\<\>//gI]]) +vim.keymap.set('n', 'x', '!chmod +x %', { silent = true }) + +vim.keymap.set('n', 'vpp', 'e ~/.dotfiles/nvim/.config/nvim/lua/theprimeagen/packer.lua') +vim.keymap.set('n', 'mr', 'CellularAutomaton make_it_rain') + +vim.keymap.set('n', 'sf', ':source $HOME/.config/nvim/init.lua ', { desc = 'Source Neovim config' }) + +vim.keymap.set('n', '', function() + vim.cmd 'so' +end) + +-- Jump to beginning/end of method +vim.keymap.set('n', '[m', '[m', { desc = 'Jump to beginning of method' }) +vim.keymap.set('n', ']m', ']m', { desc = 'Jump to end of method' }) + +-- Diagnostic navigation with float +vim.keymap.set('n', '[d', function() + vim.diagnostic.goto_prev() + vim.diagnostic.open_float() +end, { desc = 'Go to previous diagnostic' }) + +vim.keymap.set('n', ']d', function() + vim.diagnostic.goto_next() + vim.diagnostic.open_float() +end, { desc = 'Go to next diagnostic' }) diff --git a/lua/arnoldlei/set.lua b/lua/arnoldlei/set.lua new file mode 100644 index 00000000000..2da762e40e8 --- /dev/null +++ b/lua/arnoldlei/set.lua @@ -0,0 +1,27 @@ +vim.opt.nu = true +vim.opt.relativenumber = true + +vim.opt.tabstop = 4 +vim.opt.softtabstop = 4 +vim.opt.shiftwidth = 4 +vim.opt.expandtab = true + +vim.opt.smartindent = true + +vim.opt.wrap = false + +vim.opt.swapfile = false +vim.opt.backup = false +vim.opt.undodir = os.getenv("HOME") .. "/.vim/undodir" +vim.opt.undofile = true + +-- vim.opt.hlsearch = false +-- vim.opt.incsearch = true + +vim.opt.termguicolors = true + +vim.opt.scrolloff = 8 +vim.opt.signcolumn = "yes" +vim.opt.isfname:append("@-@") + +vim.opt.colorcolumn = "80" diff --git a/lua/custom/.DS_Store b/lua/custom/.DS_Store new file mode 100644 index 00000000000..a7b0016a459 Binary files /dev/null and b/lua/custom/.DS_Store differ diff --git a/lua/custom/plugins/TEST.md b/lua/custom/plugins/TEST.md new file mode 100644 index 00000000000..478c4bce84e --- /dev/null +++ b/lua/custom/plugins/TEST.md @@ -0,0 +1 @@ +[a relative link](../../../README.md.md) diff --git a/lua/custom/plugins/comment.lua b/lua/custom/plugins/comment.lua new file mode 100644 index 00000000000..e6b597dbdc5 --- /dev/null +++ b/lua/custom/plugins/comment.lua @@ -0,0 +1,7 @@ +return { + 'numToStr/Comment.nvim', + opts = { + -- add any options here + }, + lazy = false, +} diff --git a/lua/custom/plugins/curl.lua b/lua/custom/plugins/curl.lua new file mode 100644 index 00000000000..293d8265e03 --- /dev/null +++ b/lua/custom/plugins/curl.lua @@ -0,0 +1,31 @@ +return { + "oysandvik94/curl.nvim", + cmd = { "CurlOpen" }, + dependencies = { + "nvim-lua/plenary.nvim", + }, + config = true, + keys = { + { "cc", "lua require('curl').open_curl_tab()", desc = "Open a curl tab scoped to the current working directory" }, + { "csc", "lua require('curl').create_scoped_collection()", desc = "Create or open a collection with a name from user input" }, + { "cgc", "lua require('curl').create_global_collection()", desc = "Create or open a global collection with a name from user input" }, + }, + on_attach = function (bufnr) + -- These commands will prompt you for a name for your collection + vim.keymap.set("n", "csc", function() + curl.create_scoped_collection() + end, { desc = "Create or open a collection with a name from user input" }) + + vim.keymap.set("n", "cgc", function() + curl.create_global_collection() + end, { desc = "Create or open a global collection with a name from user input" }) + + vim.keymap.set("n", "fsc", function() + curl.pick_scoped_collection() + end, { desc = "Choose a scoped collection and open it" }) + + vim.keymap.set("n", "fgc", function() + curl.pick_global_collection() + end, { desc = "Choose a global collection and open it" }) + end +} diff --git a/lua/custom/plugins/gitblame.lua b/lua/custom/plugins/gitblame.lua new file mode 100644 index 00000000000..97a16202f23 --- /dev/null +++ b/lua/custom/plugins/gitblame.lua @@ -0,0 +1,17 @@ +return { + 'f-person/git-blame.nvim', + -- load the plugin at startup + event = 'VeryLazy', + -- Because of the keys part, you will be lazy loading this plugin. + -- The plugin will only load once one of the keys is used. + -- If you want to load the plugin at startup, add something like event = "VeryLazy", + -- or lazy = false. One of both options will work. + opts = { + -- your configuration comes here + -- for example + enabled = true, -- if you want to enable the plugin + message_template = ' • <>', -- template for the blame message, check the Message template section for more options + date_format = '%m-%d-%Y %H:%M:%S', -- template for the date, check Date format section for more options + virtual_text_column = 1, -- virtual text start column, check Start virtual text at column section for more options + }, +} diff --git a/lua/custom/plugins/harpoon.lua b/lua/custom/plugins/harpoon.lua new file mode 100644 index 00000000000..c605ba9ab4b --- /dev/null +++ b/lua/custom/plugins/harpoon.lua @@ -0,0 +1,45 @@ +return { + 'ThePrimeagen/harpoon', + branch = 'harpoon2', + lazy = false, + dependencies = { + 'nvim-lua/plenary.nvim', + }, + config = function() + local harpoon = require 'harpoon' + harpoon:setup() + + -- Keymaps + vim.keymap.set('n', 'a', function() + harpoon:list():add() + end, { desc = 'Harpoon: Mark file' }) + + vim.keymap.set('n', '', function() + harpoon.ui:toggle_quick_menu(harpoon:list()) + end, { desc = 'Harpoon: Toggle quick menu' }) + + vim.keymap.set('n', '', function() + harpoon:list():select(1) + end, { desc = 'Harpoon: Go to file 1' }) + + vim.keymap.set('n', '', function() + harpoon:list():select(2) + end, { desc = 'Harpoon: Go to file 2' }) + + vim.keymap.set('n', '', function() + harpoon:list():select(3) + end, { desc = 'Harpoon: Go to file 3' }) + + vim.keymap.set('n', '', function() + harpoon:list():select(4) + end, { desc = 'Harpoon: Go to file 4' }) + + vim.keymap.set('n', 'hp', function() + harpoon:list():prev() + end, { desc = 'Harpoon: Previous buffer' }) + + vim.keymap.set('n', 'hn', function() + harpoon:list():next() + end, { desc = 'Harpoon: Next buffer' }) + end, +} diff --git a/lua/custom/plugins/lazygit.lua b/lua/custom/plugins/lazygit.lua new file mode 100644 index 00000000000..86d809114fb --- /dev/null +++ b/lua/custom/plugins/lazygit.lua @@ -0,0 +1,22 @@ +return { + 'kdheepak/lazygit.nvim', + lazy = false, + cmd = { + 'LazyGit', + 'LazyGitConfig', + 'LazyGitCurrentFile', + 'LazyGitFilter', + 'LazyGitFilterCurrentFile', + }, + -- optional for floating window border decoration + dependencies = { + 'nvim-telescope/telescope.nvim', + 'nvim-lua/plenary.nvim', + }, + config = function() + require('telescope').load_extension 'lazygit' + end, + keys = { + { 'gh', 'LazyGit', desc = 'LazyGit' }, + }, +} diff --git a/lua/custom/plugins/oil.lua b/lua/custom/plugins/oil.lua new file mode 100644 index 00000000000..8a8b577b0d5 --- /dev/null +++ b/lua/custom/plugins/oil.lua @@ -0,0 +1,40 @@ +return { + 'stevearc/oil.nvim', + ---@module 'oil' + ---@type oil.SetupOpts + opts = { + view_options = { + -- Show files and directories that start with "." + show_hidden = true, + -- This function defines what is considered a "hidden" file + is_hidden_file = function(name, bufnr) + local m = name:match '^%.' + return m ~= nil + end, + -- This function defines what will never be shown, even when `show_hidden` is set + is_always_hidden = function(name, bufnr) + return false + end, + -- Sort file names with numbers in a more intuitive order for humans. + -- Can be "fast", true, or false. "fast" will turn it off for large directories. + natural_order = 'fast', + -- Sort file and directory names case insensitive + case_insensitive = false, + sort = { + -- sort order can be "asc" or "desc" + -- see :help oil-columns to see which columns are sortable + { 'type', 'asc' }, + { 'name', 'asc' }, + }, + -- Customize the highlight group for the file name + highlight_filename = function(entry, is_hidden, is_link_target, is_link_orphan) + return nil + end, + }, + }, + -- Optional dependencies + dependencies = { { 'nvim-mini/mini.icons', opts = {} } }, + -- dependencies = { "nvim-tree/nvim-web-devicons" }, -- use if you prefer nvim-web-devicons + -- Lazy loading is not recommended because it is very tricky to make it work correctly in all situations. + lazy = false, +} diff --git a/lua/custom/plugins/theme-switcher.lua b/lua/custom/plugins/theme-switcher.lua new file mode 100644 index 00000000000..8ccbf0aa667 --- /dev/null +++ b/lua/custom/plugins/theme-switcher.lua @@ -0,0 +1,18 @@ +return { + dir = vim.fn.stdpath 'config' .. '/lua/theme-switcher', + name = 'theme-switcher', + lazy = false, + priority = 100, + config = function() + require('theme-switcher').setup { + save_on_select = true, + preview_on_navigate = true, + restore_on_startup = true, + } + + -- Keybindings (global, not buffer-specific) + vim.keymap.set('n', 'tt', function() + require('theme-switcher').open() + end, { desc = '[T]heme [T]oggle', noremap = true, silent = true }) + end, +} diff --git a/lua/custom/themes/theme.lua b/lua/custom/themes/theme.lua new file mode 100644 index 00000000000..02ccb684b0e --- /dev/null +++ b/lua/custom/themes/theme.lua @@ -0,0 +1,117 @@ +-- Default theme to load on startup +local DEFAULT_THEME = 'nightfox' + +return { + { + 'projekt0n/github-nvim-theme', + name = 'github-theme', + lazy = false, -- make sure we load this during startup if it is your main colorscheme + priority = 1000, -- make sure to load this before all the other start plugins + config = function() + require('github-theme').setup { + -- ... + } + + vim.cmd 'colorscheme github_dark' + end, + }, + -- Nightfox theme + { + 'EdenEast/nightfox.nvim', + lazy = false, + priority = 1000, + config = function() + require('nightfox').setup { + options = { + compile_path = vim.fn.stdpath 'cache' .. '/nightfox', + compile_file_suffix = '_compiled', + transparent = false, + terminal_colors = true, + dim_inactive = false, + module_default = true, + colorblind = { + enable = false, + simulate_only = false, + severity = { + protan = 0, + deutan = 0, + tritan = 0, + }, + }, + styles = { + comments = 'NONE', + conditionals = 'NONE', + constants = 'NONE', + functions = 'NONE', + keywords = 'NONE', + numbers = 'NONE', + operators = 'NONE', + strings = 'NONE', + types = 'NONE', + variables = 'NONE', + }, + inverse = { + match_paren = false, + visual = false, + search = false, + }, + modules = {}, + }, + palettes = {}, + specs = {}, + groups = {}, + } + end, + }, + + -- Oxocarbon theme + { + 'nyoom-engineering/oxocarbon.nvim', + lazy = false, + priority = 1000, + }, + + -- Tokyo Night theme + { + 'folke/tokyonight.nvim', + lazy = false, + priority = 1000, + config = function() + ---@diagnostic disable-next-line: missing-fields + require('tokyonight').setup { + styles = { + comments = { italic = false }, + }, + } + + -- Set default colorscheme on startup + vim.cmd.colorscheme(DEFAULT_THEME) + end, + }, + { + 'catppuccin/nvim', + name = 'catppuccin', + lazy = false, + priority = 1000, + config = function() + require('catppuccin').setup { + flavour = 'mocha', -- latte, frappe, macchiato, mocha + } + end, + }, + { + 'loctvl842/monokai-pro.nvim', + lazy = false, + priority = 1000, + }, + { + 'navarasu/onedark.nvim', + lazy = false, + priority = 1000, + config = function() + require('onedark').setup { + style = 'dark', -- dark, darker, cool, deep, warm, warmer + } + end, + }, +} diff --git a/lua/theme-switcher/fuzzy.lua b/lua/theme-switcher/fuzzy.lua new file mode 100644 index 00000000000..90f06e55122 --- /dev/null +++ b/lua/theme-switcher/fuzzy.lua @@ -0,0 +1,101 @@ +local M = {} + +-- Simple fuzzy match algorithm +-- Returns score (higher is better) or nil if no match +function M.fuzzy_match(str, pattern) + if pattern == '' then + return 1000 -- Empty pattern matches everything with high score + end + + str = str:lower() + pattern = pattern:lower() + + local str_idx = 1 + local pattern_idx = 1 + local score = 0 + local consecutive = 0 + local last_match_idx = 0 + + while pattern_idx <= #pattern do + local pattern_char = pattern:sub(pattern_idx, pattern_idx) + local found = false + + -- Search for pattern character in remaining string + while str_idx <= #str do + local str_char = str:sub(str_idx, str_idx) + + if str_char == pattern_char then + found = true + + -- Score bonuses + score = score + 1 + + -- Bonus for consecutive matches + if str_idx == last_match_idx + 1 then + consecutive = consecutive + 1 + score = score + consecutive * 5 + else + consecutive = 0 + end + + -- Bonus for matching at start + if str_idx == 1 then + score = score + 10 + end + + -- Bonus for matching after separator + if str_idx > 1 then + local prev_char = str:sub(str_idx - 1, str_idx - 1) + if prev_char == '-' or prev_char == '_' or prev_char == ' ' then + score = score + 8 + end + end + + last_match_idx = str_idx + str_idx = str_idx + 1 + break + end + + str_idx = str_idx + 1 + end + + if not found then + return nil -- Pattern doesn't match + end + + pattern_idx = pattern_idx + 1 + end + + return score +end + +-- Filter and sort themes by fuzzy match +function M.filter_themes(themes, query) + if query == '' then + return themes + end + + local matches = {} + + for _, theme in ipairs(themes) do + local score = M.fuzzy_match(theme, query) + if score then + table.insert(matches, { theme = theme, score = score }) + end + end + + -- Sort by score (descending) + table.sort(matches, function(a, b) + return a.score > b.score + end) + + -- Extract just the theme names + local filtered = {} + for _, match in ipairs(matches) do + table.insert(filtered, match.theme) + end + + return filtered +end + +return M diff --git a/lua/theme-switcher/init.lua b/lua/theme-switcher/init.lua new file mode 100644 index 00000000000..49cbafc8fb3 --- /dev/null +++ b/lua/theme-switcher/init.lua @@ -0,0 +1,216 @@ +local M = {} + +-- Configuration +local config = { + save_on_select = true, + preview_on_navigate = true, + restore_on_startup = true, +} + +-- Store original theme for preview cancellation +local original_theme = nil +local preview_enabled = false +local all_themes = {} +local filtered_themes = {} +local query = '' + +-- Setup function +function M.setup(user_config) + config = vim.tbl_deep_extend('force', config, user_config or {}) + + -- Restore saved theme on startup + if config.restore_on_startup then + local persistence = require 'theme-switcher.persistence' + local themes = require 'theme-switcher.themes' + local saved_theme = persistence.load_theme() + if saved_theme then + themes.apply_theme(saved_theme) + end + end + + -- Create user commands + vim.api.nvim_create_user_command('ThemeSwitcher', function() + M.open() + end, {}) + + vim.api.nvim_create_user_command('ThemeSwitcherSave', function() + local themes = require 'theme-switcher.themes' + local persistence = require 'theme-switcher.persistence' + local current = themes.get_current_theme() + persistence.save_theme(current) + vim.notify('Saved theme: ' .. current, vim.log.levels.INFO) + end, {}) +end + +-- Open theme switcher +function M.open() + local themes = require 'theme-switcher.themes' + local ui = require 'theme-switcher.ui' + + all_themes = themes.get_available_themes() + filtered_themes = all_themes + query = '' + + local current_theme = themes.get_current_theme() + + -- Store original for preview cancellation + original_theme = current_theme + preview_enabled = config.preview_on_navigate + + local buf, win = ui.create_window(filtered_themes, current_theme) + + M.setup_keymaps(buf) +end + +function M.setup_keymaps(buf) + local opts = { buffer = buf, nowait = true, silent = true } + + -- Close and cancel + vim.keymap.set('n', 'q', function() + M.cancel() + end, opts) + + vim.keymap.set('n', '', function() + M.cancel() + end, opts) + + -- Select and apply + vim.keymap.set('n', '', function() + M.select() + end, opts) + + -- Navigation with preview + vim.keymap.set('n', 'j', function() + vim.cmd 'normal! j' + M.preview() + end, opts) + + vim.keymap.set('n', 'k', function() + vim.cmd 'normal! k' + M.preview() + end, opts) + + vim.keymap.set('n', '', function() + vim.cmd 'normal! j' + M.preview() + end, opts) + + vim.keymap.set('n', '', function() + vim.cmd 'normal! k' + M.preview() + end, opts) + + vim.keymap.set('n', '', function() + vim.cmd 'normal! j' + M.preview() + end, opts) + + vim.keymap.set('n', '', function() + vim.cmd 'normal! k' + M.preview() + end, opts) + + -- Text input - any printable character + for i = 32, 126 do + local char = string.char(i) + vim.keymap.set('n', char, function() + M.add_char(char) + end, opts) + end + + -- Backspace + vim.keymap.set('n', '', function() + M.remove_char() + end, opts) + + vim.keymap.set('n', '', function() + M.remove_char() + end, opts) + + -- Clear input + vim.keymap.set('n', '', function() + M.clear_input() + end, opts) + + -- Toggle preview + vim.keymap.set('n', '', function() + preview_enabled = not preview_enabled + vim.notify(preview_enabled and 'Preview enabled' or 'Preview disabled', vim.log.levels.INFO) + end, opts) +end + +function M.add_char(char) + query = query .. char + M.update_filter() +end + +function M.remove_char() + if #query > 0 then + query = query:sub(1, -2) + M.update_filter() + end +end + +function M.clear_input() + query = '' + M.update_filter() +end + +function M.update_filter() + local fuzzy = require 'theme-switcher.fuzzy' + local ui = require 'theme-switcher.ui' + local themes = require 'theme-switcher.themes' + + filtered_themes = fuzzy.filter_themes(all_themes, query) + ui.update_display(filtered_themes, themes.get_current_theme(), query) +end + +-- Preview theme while navigating +function M.preview() + if not preview_enabled then + return + end + + local ui = require 'theme-switcher.ui' + local themes = require 'theme-switcher.themes' + + local selected = ui.get_selected_theme(filtered_themes) + if selected then + themes.apply_theme(selected) + end +end + +-- Select and apply theme +function M.select() + local ui = require 'theme-switcher.ui' + local themes = require 'theme-switcher.themes' + local persistence = require 'theme-switcher.persistence' + + local selected = ui.get_selected_theme(filtered_themes) + + if selected then + themes.apply_theme(selected) + + if config.save_on_select then + persistence.save_theme(selected) + end + + vim.notify('Applied theme: ' .. selected, vim.log.levels.INFO) + end + + ui.close_window() +end + +-- Cancel and restore original theme +function M.cancel() + local ui = require 'theme-switcher.ui' + local themes = require 'theme-switcher.themes' + + if preview_enabled and original_theme then + themes.apply_theme(original_theme) + end + + ui.close_window() +end + +return M diff --git a/lua/theme-switcher/persistence.lua b/lua/theme-switcher/persistence.lua new file mode 100644 index 00000000000..11301252237 --- /dev/null +++ b/lua/theme-switcher/persistence.lua @@ -0,0 +1,33 @@ +local M = {} + +local config_dir = vim.fn.stdpath 'data' +local theme_file = config_dir .. '/theme_preference.txt' + +-- Save theme preference +function M.save_theme(theme_name) + local file = io.open(theme_file, 'w') + if file then + file:write(theme_name) + file:close() + return true + end + return false +end + +-- Load theme preference +function M.load_theme() + local file = io.open(theme_file, 'r') + if file then + local theme = file:read '*all' + file:close() + return theme:match '^%s*(.-)%s*$' -- trim whitespace + end + return nil +end + +-- Delete preference +function M.clear_theme() + os.remove(theme_file) +end + +return M diff --git a/lua/theme-switcher/themes.lua b/lua/theme-switcher/themes.lua new file mode 100644 index 00000000000..e6716141d86 --- /dev/null +++ b/lua/theme-switcher/themes.lua @@ -0,0 +1,48 @@ +local M = {} + +-- Automatically detect installed colorschemes +function M.get_available_themes() + local themes = {} + + -- Get all available colorschemes from runtime paths + local colorscheme_files = vim.api.nvim_get_runtime_file('colors/*.vim', true) + local lua_colorschemes = vim.api.nvim_get_runtime_file('colors/*.lua', true) + + -- Combine both vim and lua colorschemes + vim.list_extend(colorscheme_files, lua_colorschemes) + + for _, file in ipairs(colorscheme_files) do + local name = vim.fn.fnamemodify(file, ':t:r') + table.insert(themes, name) + end + + -- Remove duplicates and sort + local seen = {} + local unique = {} + for _, theme in ipairs(themes) do + if not seen[theme] then + seen[theme] = true + table.insert(unique, theme) + end + end + + table.sort(unique) + return unique +end + +-- Get current colorscheme +function M.get_current_theme() + return vim.g.colors_name or 'default' +end + +-- Apply a theme +function M.apply_theme(theme_name) + local ok, err = pcall(vim.cmd.colorscheme, theme_name) + if not ok then + vim.notify('Failed to load theme: ' .. theme_name, vim.log.levels.ERROR) + return false + end + return true +end + +return M diff --git a/lua/theme-switcher/ui.lua b/lua/theme-switcher/ui.lua new file mode 100644 index 00000000000..84ad96e8b3e --- /dev/null +++ b/lua/theme-switcher/ui.lua @@ -0,0 +1,124 @@ +local M = {} + +-- Store window and buffer IDs +local win_id = nil +local buf_id = nil +local input_ns = nil + +-- Create floating window with search input +function M.create_window(themes, current_theme) + -- Calculate window size + local width = 60 + local height = math.min(#themes + 4, 20) -- +4 for header and input + + -- Calculate position (center of screen) + local row = math.floor((vim.o.lines - height) / 2) + local col = math.floor((vim.o.columns - width) / 2) + + -- Create buffer + buf_id = vim.api.nvim_create_buf(false, true) -- No file, scratch buffer + + -- Set buffer options + vim.api.nvim_buf_set_option(buf_id, 'bufhidden', 'wipe') + vim.api.nvim_buf_set_option(buf_id, 'filetype', 'theme-switcher') + vim.api.nvim_buf_set_option(buf_id, 'modifiable', false) + + -- Window options + local opts = { + relative = 'editor', + width = width, + height = height, + row = row, + col = col, + style = 'minimal', + border = 'rounded', + title = ' Theme Switcher ', + title_pos = 'center', + } + + -- Create window + win_id = vim.api.nvim_open_win(buf_id, true, opts) + + -- Window-local options + vim.api.nvim_win_set_option(win_id, 'cursorline', true) + vim.api.nvim_win_set_option(win_id, 'number', false) + vim.api.nvim_win_set_option(win_id, 'relativenumber', false) + + input_ns = vim.api.nvim_create_namespace 'theme-switcher-input' + + M.update_display(themes, current_theme, '') + + return buf_id, win_id +end + +-- Update the display with filtered themes +function M.update_display(themes, current_theme, query) + if not buf_id or not vim.api.nvim_buf_is_valid(buf_id) then + return + end + + vim.api.nvim_buf_set_option(buf_id, 'modifiable', true) + + local lines = {} + + -- Input line + table.insert(lines, '> ' .. query) + table.insert(lines, string.rep('─', vim.api.nvim_win_get_width(win_id) - 2)) + + -- Theme list + local current_line = 3 + for i, theme in ipairs(themes) do + local prefix = theme == current_theme and '● ' or ' ' + table.insert(lines, prefix .. theme) + + if theme == current_theme and query == '' then + current_line = i + 2 + end + end + + -- Handle empty results + if #themes == 0 then + table.insert(lines, ' No matches found') + end + + vim.api.nvim_buf_set_lines(buf_id, 0, -1, false, lines) + vim.api.nvim_buf_set_option(buf_id, 'modifiable', false) + + -- Set cursor to first theme (after separator) + if #themes > 0 then + vim.api.nvim_win_set_cursor(win_id, { query == '' and current_line or 3, 0 }) + else + vim.api.nvim_win_set_cursor(win_id, { 3, 0 }) + end +end + +-- Close window +function M.close_window() + if win_id and vim.api.nvim_win_is_valid(win_id) then + vim.api.nvim_win_close(win_id, true) + end + win_id = nil + buf_id = nil + input_ns = nil +end + +-- Get selected theme from cursor position +function M.get_selected_theme(themes) + if not win_id then + return nil + end + + local cursor = vim.api.nvim_win_get_cursor(win_id) + local line_num = cursor[1] + + -- Subtract 2 for input line and separator + local theme_idx = line_num - 2 + + if theme_idx >= 1 and theme_idx <= #themes then + return themes[theme_idx] + end + + return nil +end + +return M