diff --git a/init.lua b/init.lua index b98ffc6198a..a9dfc5dc212 100644 --- a/init.lua +++ b/init.lua @@ -91,7 +91,7 @@ vim.g.mapleader = ' ' vim.g.maplocalleader = ' ' -- Set to true if you have a Nerd Font installed and selected in the terminal -vim.g.have_nerd_font = false +vim.g.have_nerd_font = true -- [[ Setting options ]] -- See `:help vim.o` @@ -110,14 +110,6 @@ vim.o.mouse = 'a' -- Don't show the mode, since it's already in the status line vim.o.showmode = false --- Sync clipboard between OS and Neovim. --- Schedule the setting after `UiEnter` because it can increase startup-time. --- Remove this option if you want your OS clipboard to remain independent. --- See `:help 'clipboard'` -vim.schedule(function() - vim.o.clipboard = 'unnamedplus' -end) - -- Enable break indent vim.o.breakindent = true @@ -205,6 +197,29 @@ vim.keymap.set('n', '', '', { desc = 'Move focus to the upper win -- vim.keymap.set("n", "", "J", { desc = "Move window to the lower" }) -- vim.keymap.set("n", "", "K", { desc = "Move window to the upper" }) +-- Open terminal in horizontal split +vim.keymap.set('n', 'th', ':split | terminal', { desc = 'Terminal horizontal split' }) + +-- Open terminal in vertical split +vim.keymap.set('n', 'tv', ':vsplit | terminal', { desc = 'Terminal vertical split' }) + +-- Open terminal in new tab +vim.keymap.set('n', 'tt', ':tabnew | terminal', { desc = 'Terminal in new tab' }) + +-- Toggle terminal (requires a plugin like toggleterm.nvim) +vim.keymap.set('n', 'tf', ':ToggleTerm', { desc = 'Toggle floating terminal' }) + +-- relative line number +vim.opt.number = true +vim.opt.relativenumber = true + +-- autoreload when external changes +vim.opt.autoread = true + +-- paste does not yank in visual mode +-- Make Visual mode paste not clobber the default register +vim.keymap.set('x', 'p', '"_dP', { noremap = true, silent = true }) + -- [[ Basic Autocommands ]] -- See `:help lua-guide-autocommands` @@ -219,6 +234,9 @@ vim.api.nvim_create_autocmd('TextYankPost', { end, }) +local git_links = require 'custom.git_links' +vim.keymap.set({ 'n', 'v' }, 'go', git_links.open_github, { desc = 'Open in GitHub' }) + -- [[ Install `lazy.nvim` plugin manager ]] -- See `:help lazy.nvim.txt` or https://github.com/folke/lazy.nvim for more info local lazypath = vim.fn.stdpath 'data' .. '/lazy/lazy.nvim' @@ -246,6 +264,49 @@ rtp:prepend(lazypath) -- -- NOTE: Here is where you install your plugins. require('lazy').setup({ + -- your other plugins + { + -- TODO Set to use ccurl + -- Official installation from mistweaverco/kulala.nvim + 'mistweaverco/kulala.nvim', + ft = { 'http', 'rest' }, -- Supports both .http and .rest files + + opts = { + -- By default global keymaps are disabled + -- Set to true to enable all built-in keymaps + global_keymaps = false, + }, + keys = { + -- Request execution + { 'kr', 'lua require("kulala").run()', desc = 'Kulala: Run request' }, + { 'ka', 'lua require("kulala").run_all()', desc = 'Kulala: Run all requests' }, + { 'kR', 'lua require("kulala").replay()', desc = 'Kulala: Replay last request' }, + + -- View & Inspection + { 'kt', 'lua require("kulala").toggle_view()', desc = 'Kulala: Toggle view' }, + { 'ki', 'lua require("kulala").inspect()', desc = 'Kulala: Inspect current request' }, + { 'ks', 'lua require("kulala").show_stats()', desc = 'Kulala: Show stats' }, + + -- Navigation + { 'kn', 'lua require("kulala").jump_next()', desc = 'Kulala: Jump to next request' }, + { 'kp', 'lua require("kulala").jump_prev()', desc = 'Kulala: Jump to previous request' }, + + -- Copy/Paste & Scratchpad + { 'kc', 'lua require("kulala").copy()', desc = 'Kulala: Copy as cURL' }, + { 'kC', 'lua require("kulala").from_curl()', desc = 'Kulala: Paste from cURL' }, + { 'kb', 'lua require("kulala").scratchpad()', desc = 'Kulala: Open scratchpad' }, + + -- Environment management + { 'ke', 'lua require("kulala").set_selected_env()', desc = 'Kulala: Select environment' }, + { 'kg', 'lua require("kulala").download_graphql_schema()', desc = 'Kulala: Download GraphQL schema' }, + + -- Utility + { 'kx', 'lua require("kulala").close()', desc = 'Kulala: Close' }, + { 'kD', 'lua require("kulala").clear_cached_files()', desc = 'Kulala: Clear cache' }, + }, + }, + + -- more plugins -- NOTE: Plugins can be added with a link (or for a github repo: 'owner/repo' link). 'NMAC427/guess-indent.nvim', -- Detect tabstop and shiftwidth automatically @@ -274,16 +335,76 @@ require('lazy').setup({ { -- Adds git related signs to the gutter, as well as utilities for managing changes 'lewis6991/gitsigns.nvim', opts = { - signs = { - add = { text = '+' }, - change = { text = '~' }, - delete = { text = '_' }, - topdelete = { text = '‾' }, - changedelete = { text = '~' }, - }, + on_attach = function(bufnr) + local gitsigns = require 'gitsigns' + + local function map(mode, l, r, opts) + opts = opts or {} + opts.buffer = bufnr + vim.keymap.set(mode, l, r, opts) + end + + -- Detect branch once per buffer attach + local primary_branch = 'main' + local handle = io.popen 'git branch --list main master' + if handle then + local result = handle:read '*a' + handle:close() + if not string.find(result, 'main') and string.find(result, 'master') then + primary_branch = 'master' + end + end + + -- Navigation + map('n', ']c', function() + if vim.wo.diff then + vim.cmd.normal { ']c', bang = true } + else + gitsigns.nav_hunk 'next' + end + end, { desc = 'Jump to next git [c]hange' }) + + map('n', '[c', function() + if vim.wo.diff then + vim.cmd.normal { '[c', bang = true } + else + gitsigns.nav_hunk 'prev' + end + end, { desc = 'Jump to previous git [c]hange' }) + + -- Actions + map('v', 'hs', function() + gitsigns.stage_hunk { vim.fn.line '.', vim.fn.line 'v' } + end, { desc = 'git [s]tage hunk' }) + map('v', 'hr', function() + gitsigns.reset_hunk { vim.fn.line '.', vim.fn.line 'v' } + end, { desc = 'git [r]eset hunk' }) + + map('n', 'hs', gitsigns.stage_hunk, { desc = 'git [s]tage hunk' }) + map('n', 'hr', gitsigns.reset_hunk, { desc = 'git [r]eset hunk' }) + map('n', 'hS', gitsigns.stage_buffer, { desc = 'git [S]tage buffer' }) + map('n', 'hu', gitsigns.stage_hunk, { desc = 'git [u]ndo stage hunk' }) + map('n', 'hR', gitsigns.reset_buffer, { desc = 'git [R]eset buffer' }) + map('n', 'hp', gitsigns.preview_hunk, { desc = 'git [p]review hunk' }) + map('n', 'hb', gitsigns.blame_line, { desc = 'git [b]lame line' }) + map('n', 'hB', gitsigns.blame, { desc = 'git [B]lame toggle' }) + + -- Diff Mappings + map('n', 'hd', gitsigns.diffthis, { desc = 'git [d]iff against index' }) + map('n', 'hD', function() + gitsigns.diffthis '@' + end, { desc = 'git [D]iff against last commit' }) + + map('n', 'hm', function() + gitsigns.diffthis(primary_branch) + end, { desc = 'git diff against [m]ain/master' }) + + -- Toggles + map('n', 'ht', gitsigns.toggle_current_line_blame, { desc = '[t]oggle git show blame line' }) + map('n', 'hv', gitsigns.preview_hunk_inline, { desc = 'toggle git show deleted ([v]iew)' }) + end, }, }, - -- NOTE: Plugins can also be configured to run Lua code when they are loaded. -- -- This is often very useful to both group configuration, as well as handle @@ -437,6 +558,20 @@ require('lazy').setup({ 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', 'g', '', { desc = '[Git]' }) + vim.keymap.set('n', 'gl', builtin.git_bcommits, { desc = '[Git] Buffer Commits' }) + vim.keymap.set('n', 'gr', builtin.git_bcommits_range, { desc = '[Git] Buffer Commits Range' }) + vim.keymap.set('n', 'gb', builtin.git_branches, { desc = '[Git] Branches' }) + vim.keymap.set('n', 'gc', builtin.git_commits, { desc = '[Git] Commits' }) + vim.keymap.set('n', 'gf', builtin.git_files, { desc = '[Git] Files' }) + vim.keymap.set('n', 'gt', builtin.git_stash, { desc = '[Git] Stash' }) + vim.keymap.set('n', 'gs', builtin.git_status, { desc = '[Git] Status' }) + vim.keymap.set('n', 'gm', function() + builtin.git_commits { + git_command = { 'git', 'log', '--oneline', '--decorate', 'main..HEAD' }, + } + end, { desc = '[Git] Commits ahead of main' }) + -- Slightly advanced example of overriding default behavior and theme vim.keymap.set('n', '/', function() -- You can pass additional configuration to Telescope to change the theme, layout, etc. @@ -459,9 +594,28 @@ require('lazy').setup({ vim.keymap.set('n', 'sn', function() builtin.find_files { cwd = vim.fn.stdpath 'config' } end, { desc = '[S]earch [N]eovim files' }) + + vim.keymap.set('n', 'sag', function() + builtin.live_grep { + prompt_title = 'Live Grep (All Files)', + -- This function adds the flags to the underlying grep command + additional_args = function(args) + return { '--hidden', '--no-ignore', '--no-ignore-parent', '--glob=!**/.git/*' } + end, + } + end, { desc = '[S]earch [A]ll Files [G]rep)' }) + + vim.keymap.set('n', 'saf', function() + builtin.find_files { + prompt_title = 'Find All Files (Hidden + Ignored)', + hidden = true, -- Show hidden dotfiles + no_ignore = true, -- Ignore .gitignore rules + no_ignore_parent = true, -- Ignore .gitignore rules of all parents, too + file_ignore_patterns = { '.git/' }, -- <--- Explicitly remove the .git folder + } + end, { desc = '[S]earch [A]ll [F]iles' }) end, }, - -- LSP Plugins { -- `lazydev` configures Lua LSP for your Neovim config, runtime and plugins @@ -482,7 +636,10 @@ require('lazy').setup({ -- Automatically install LSPs and related tools to stdpath for Neovim -- Mason must be loaded before its dependents so we need to set it up here. -- NOTE: `opts = {}` is the same as calling `require('mason').setup({})` - { 'mason-org/mason.nvim', opts = {} }, + { + 'mason-org/mason.nvim', + opts = {}, + }, 'mason-org/mason-lspconfig.nvim', 'WhoIsSethDaniel/mason-tool-installer.nvim', @@ -573,10 +730,6 @@ require('lazy').setup({ map('grt', require('telescope.builtin').lsp_type_definitions, '[G]oto [T]ype Definition') -- This function resolves a difference between neovim nightly (version 0.11) and stable (version 0.10) - ---@param client vim.lsp.Client - ---@param method vim.lsp.protocol.Method - ---@param bufnr? integer some lsp support methods only in specific files - ---@return boolean local function client_supports_method(client, method, bufnr) if vim.fn.has 'nvim-0.11' == 1 then return client:supports_method(method, bufnr) @@ -585,12 +738,31 @@ require('lazy').setup({ end end + local client = vim.lsp.get_client_by_id(event.data.client_id) + + -- ========================================================================= + -- NEW: The gopls Semantic Tokens Workaround + -- ========================================================================= + if client and client.name == 'gopls' and not client.server_capabilities.semanticTokensProvider then + local semantic = client.config.capabilities.textDocument.semanticTokens + if semantic then + client.server_capabilities.semanticTokensProvider = { + full = true, + legend = { + tokenTypes = semantic.tokenTypes, + tokenModifiers = semantic.tokenModifiers, + }, + range = true, + } + end + end + -- ========================================================================= + -- The following two autocommands are used to highlight references of the -- word under your cursor when your cursor rests there for a little while. -- See `:help CursorHold` for information about when this is executed -- -- When you move your cursor, the highlights will be cleared (the second autocommand). - local client = vim.lsp.get_client_by_id(event.data.client_id) if client and client_supports_method(client, vim.lsp.protocol.Methods.textDocument_documentHighlight, event.buf) then local highlight_augroup = vim.api.nvim_create_augroup('kickstart-lsp-highlight', { clear = false }) vim.api.nvim_create_autocmd({ 'CursorHold', 'CursorHoldI' }, { @@ -631,7 +803,8 @@ require('lazy').setup({ vim.diagnostic.config { severity_sort = true, float = { border = 'rounded', source = 'if_many' }, - underline = { severity = vim.diagnostic.severity.ERROR }, + -- underline = { severity = vim.diagnostic.severity.ERROR }, + underline = true, signs = vim.g.have_nerd_font and { text = { [vim.diagnostic.severity.ERROR] = '󰅚 ', @@ -671,18 +844,154 @@ require('lazy').setup({ -- - settings (table): Override the default settings passed when initializing the server. -- For example, to see the options for `lua_ls`, you could go to: https://luals.github.io/wiki/settings/ local servers = { - -- clangd = {}, - -- gopls = {}, - -- pyright = {}, - -- rust_analyzer = {}, + clangd = {}, + + -- ========================================================================= + -- UPDATED: The unified "God Mode" gopls config + -- ========================================================================= + gopls = { + settings = { + gopls = { + -- Use just ONE method for build flags to avoid conflicts + buildFlags = { + '-tags', + 'functional,integration,small,medium,large', + }, + + -- Completion settings + completeUnimported = true, + usePlaceholders = true, + deepCompletion = true, + matcher = 'Fuzzy', + + -- Hover and signature help + hoverKind = 'FullDocumentation', + linkTarget = 'pkg.go.dev', + linksInHover = true, + + -- Static analysis and diagnostics + staticcheck = true, -- THIS automatically runs the officially supported staticcheck suite + + analyses = { + -- Only natively supported go vet / gopls checks go here + asmdecl = true, + assign = true, + atomic = true, + atomicalign = true, + bools = true, + buildtag = true, + cgocall = true, + composites = true, + copylock = true, + defers = true, + directive = true, + errorsas = true, + framepointer = true, + httpresponse = true, + ifaceassert = true, + loopclosure = true, + lostcancel = true, + nilfunc = true, + printf = true, + shift = true, + sigchanyzer = true, + slog = true, + stdmethods = true, + stringintconv = true, + structtag = true, + testinggoroutine = true, + tests = true, + timeformat = true, + unmarshal = true, + unreachable = true, + unsafeptr = true, + unusedresult = true, + deepequalerrors = true, + embed = true, + fillreturns = true, + infertypeargs = true, + nilness = true, + nonewvars = true, + noresultvalues = true, + shadow = true, + simplifycompositelit = true, + simplifyrange = true, + simplifyslice = true, + sortslice = true, + stubmethods = true, + undeclaredname = true, + unusedparams = true, + unusedvariable = true, + unusedwrite = true, + useany = true, + }, + + hints = { + assignVariableTypes = true, + compositeLiteralFields = true, + compositeLiteralTypes = true, + constantValues = true, + functionTypeParameters = true, + parameterNames = true, + rangeVariableTypes = true, + }, + + codelenses = { + gc_details = true, + generate = true, + regenerate_cgo = true, + test = true, + tidy = true, + upgrade_dependency = true, + vendor = true, + vulncheck = true, + }, + + gofumpt = true, + directoryFilters = { '-vendor' }, + }, + }, + + on_attach = function(client, bufnr) + if client.name == 'gopls' then + vim.api.nvim_create_autocmd('BufWritePre', { + buffer = bufnr, + callback = function() + vim.lsp.buf.code_action { + context = { diagnostics = {}, only = { 'source.organizeImports' } }, + apply = true, + } + end, + }) + end + end, + }, + -- ========================================================================= + + pyright = {}, + rust_analyzer = {}, -- ... etc. See `:help lspconfig-all` for a list of all the pre-configured LSPs -- -- Some languages (like typescript) have entire language plugins that can be useful: -- https://github.com/pmizio/typescript-tools.nvim -- -- But for many setups, the LSP (`ts_ls`) will work just fine - -- ts_ls = {}, - -- + ts_ls = { + settings = {}, + on_attach = function(client, bufnr) + client.server_capabilities.documentFormattingProvider = false + client.server_capabilities.documentRangeFormattingProvider = false + + -- Disable format on save for this buffer + vim.api.nvim_set_option_value('formatoptions', '', { buf = bufnr }) + vim.api.nvim_create_autocmd('BufWritePre', { + buffer = bufnr, + callback = function() + -- Do nothing, preventing format on save + end, + }) + end, + }, lua_ls = { -- cmd = { ... }, @@ -699,6 +1008,14 @@ require('lazy').setup({ }, }, } + -- + -- -- + -- -- FORCE GOPLS SETUP + -- -- + -- local gopls_config = servers.gopls + -- gopls_config.capabilities = vim.tbl_deep_extend('force', {}, capabilities, gopls_config.capabilities or {}) + -- require('lspconfig').gopls.setup(gopls_config) + -- -- Ensure the servers and tools above are installed -- @@ -716,26 +1033,44 @@ require('lazy').setup({ local ensure_installed = vim.tbl_keys(servers or {}) vim.list_extend(ensure_installed, { 'stylua', -- Used to format Lua code + 'sql-formatter', + 'prettier', + 'staticcheck', + 'goimports', + 'gofumpt', + 'gomodifytags', + 'impl', + 'golangci-lint', + 'delve', }) require('mason-tool-installer').setup { ensure_installed = ensure_installed } require('mason-lspconfig').setup { ensure_installed = {}, -- explicitly set to an empty table (Kickstart populates installs via mason-tool-installer) automatic_installation = false, - handlers = { - function(server_name) - local server = servers[server_name] or {} - -- This handles overriding only values explicitly passed - -- by the server configuration above. Useful when disabling - -- certain features of an LSP (for example, turning off formatting for ts_ls) - server.capabilities = vim.tbl_deep_extend('force', {}, capabilities, server.capabilities or {}) - require('lspconfig')[server_name].setup(server) - end, - }, + -- We are removing the handlers block here to prevent Mason + -- from silently skipping unmanaged/globally-installed binaries. } + + -- Ensure lspconfig is loaded so defaults are populated in Nvim 0.11 + require 'lspconfig' + + -- Explicitly set up all servers defined in the servers table. + for server_name, server in pairs(servers) do + server.capabilities = vim.tbl_deep_extend('force', {}, capabilities, server.capabilities or {}) + + if vim.fn.has 'nvim-0.11' == 1 then + -- Neovim 0.11+ native config API (prevents deprecation warning) + local def = vim.lsp.config[server_name] or {} + vim.lsp.config[server_name] = vim.tbl_deep_extend('force', def, server) + vim.lsp.enable(server_name) + else + -- Neovim 0.10 and earlier legacy API + require('lspconfig')[server_name].setup(server) + end + end end, }, - { -- Autoformat 'stevearc/conform.nvim', event = { 'BufWritePre' }, @@ -756,7 +1091,17 @@ require('lazy').setup({ -- 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. - local disable_filetypes = { c = true, cpp = true } + local disable_filetypes = { + c = true, + cpp = true, + typescript = true, + typescriptreact = true, + javascript = true, + javascriptreact = true, + python = true, + sql = true, + json = true, + } if disable_filetypes[vim.bo[bufnr].filetype] then return nil else @@ -768,12 +1113,19 @@ require('lazy').setup({ end, formatters_by_ft = { lua = { 'stylua' }, + sql = { 'sql_formatter' }, + json = { 'prettier' }, -- 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 }, }, + formatters = { + ['sql_formatter'] = { + prepend_args = { '-l', 'postgresql', '-c', '{"useTabs": true}' }, + }, + }, }, }, @@ -835,7 +1187,7 @@ require('lazy').setup({ -- : Toggle signature help -- -- See :h blink-cmp-config-keymap for defining your own keymap - preset = 'default', + preset = 'super-tab', -- For more advanced Luasnip keymaps (e.g. selecting choice nodes, expansion) see: -- https://github.com/L3MON4D3/LuaSnip?tab=readme-ov-file#keymaps @@ -875,7 +1227,6 @@ require('lazy').setup({ signature = { enabled = true }, }, }, - { -- 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. @@ -944,7 +1295,35 @@ require('lazy').setup({ 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', + 'go', + 'gomod', + 'gowork', + 'gosum', + 'rust', + 'python', + 'json', + 'toml', + 'css', + 'helm', + 'dockerfile', + 'bash', + 'yaml', + 'sql', + 'hcl', + 'terraform', + }, -- Autoinstall languages that are not installed auto_install = true, highlight = { @@ -963,6 +1342,28 @@ require('lazy').setup({ -- - Show your current context: https://github.com/nvim-treesitter/nvim-treesitter-context -- - Treesitter + textobjects: https://github.com/nvim-treesitter/nvim-treesitter-textobjects }, + { + 'towolf/vim-helm', + event = 'BufReadPre', + config = function() + -- This plugin automatically detects helm files (including .tpl) + -- and sets the filetype to "helm" instead of "yaml" + end, + }, + { + 'fredrikaverpil/neotest-golang', + }, + { + 'nvim-mini/mini.icons', + opts = { + file = { + ['.go-version'] = { glyph = '', hl = 'MiniIconsBlue' }, + }, + filetype = { + gotmpl = { glyph = '󰟓', hl = 'MiniIconsGrey' }, + }, + }, + }, -- The following comments only work if you have downloaded the kickstart repo, not just copy pasted the -- init.lua. If you want these files, they are in the repository, so you can just download them and @@ -973,12 +1374,15 @@ require('lazy').setup({ -- Here are some example plugins that I've included in the Kickstart repository. -- Uncomment any of the lines below to enable them (you will need to restart nvim). -- - -- require 'kickstart.plugins.debug', - -- require 'kickstart.plugins.indent_line', - -- require 'kickstart.plugins.lint', - -- require 'kickstart.plugins.autopairs', - -- require 'kickstart.plugins.neo-tree', - -- require 'kickstart.plugins.gitsigns', -- adds gitsigns recommend keymaps + require 'kickstart.plugins.debug', + require 'kickstart.plugins.indent_line', + require 'kickstart.plugins.lint', + require 'kickstart.plugins.autopairs', + require 'kickstart.plugins.neo-tree', + vim.keymap.set('n', 'x', 'Neotree toggle', { desc = 'NeoTree Toggle' }), + vim.keymap.set('n', 'z', 'Neotree reveal', { desc = 'NeoTree Reveal' }), + require 'kickstart.plugins.gitsigns', -- adds gitsigns recommend keymaps + require 'custom.plugins', -- NOTE: The import below can automatically add your own plugins, configuration, etc from `lua/custom/plugins/*.lua` -- This is the easiest way to modularize your config. diff --git a/lua/custom/git_links.lua b/lua/custom/git_links.lua new file mode 100644 index 00000000000..001346c4086 --- /dev/null +++ b/lua/custom/git_links.lua @@ -0,0 +1,40 @@ +local M = {} + +M.open_github = function() + -- Get current file path relative to the git project root + local file_path = vim.fn.systemlist('git ls-files --full-name ' .. vim.fn.expand '%')[1] + if not file_path or file_path == '' then + print 'File not tracked by git.' + return + end + + -- Get remote URL and clean it up (handles HTTPS and SSH) + local remote = vim.fn.system('git config --get remote.origin.url'):gsub('\n', ''):gsub('%.git$', '') + if remote:match '^git@' then + remote = remote:gsub(':', '/'):gsub('git@', 'https://') + end + + -- Get current branch + local branch = vim.fn.system('git rev-parse --abbrev-ref HEAD'):gsub('\n', '') + + -- Get line numbers (handles single line or visual selection) + local line_start = vim.fn.line 'v' + local line_end = vim.fn.line '.' + if line_start > line_end then + line_start, line_end = line_end, line_start + end + + local line_anchor = 'L' .. line_end + if vim.fn.mode():match '[vV]' then + line_anchor = 'L' .. line_start .. '-L' .. line_end + end + + -- Build and open the URL + local url = string.format('%s/blob/%s/%s#%s', remote, branch, file_path, line_anchor) + + -- Linux only: using xdg-open in the background to avoid freezing Neovim + vim.fn.jobstart({ 'xdg-open', url }, { detach = true }) + print 'Opened in GitHub' +end + +return M diff --git a/lua/custom/plugins/init.lua b/lua/custom/plugins/init.lua index be0eb9d8d7a..ff38bf7735f 100644 --- a/lua/custom/plugins/init.lua +++ b/lua/custom/plugins/init.lua @@ -2,4 +2,41 @@ -- I promise not to create any merge conflicts in this directory :) -- -- See the kickstart.nvim README for more information -return {} +return { + { + 'mistweaverco/kulala.nvim', + keys = { + { 'Rs', desc = 'Send request' }, + { 'Ra', desc = 'Send all requests' }, + { 'Rb', desc = 'Open scratchpad' }, + }, + ft = { 'http', 'rest' }, + opts = { + -- your configuration comes here + global_keymaps = false, + global_keymaps_prefix = 'R', + kulala_keymaps_prefix = '', + }, + }, + { + 'nvim-neo-tree/neo-tree.nvim', + version = '*', + dependencies = { + 'nvim-lua/plenary.nvim', + 'MunifTanjim/nui.nvim', + 'nvim-tree/nvim-web-devicons', + }, + lazy = false, + opts = { + filesystem = { + visible = false, + window = { + mappings = { + ['.'] = 'set_root', -- Set current directory as root + ['H'] = 'toggle_hidden', -- Toggle hidden files with 'H' + }, + }, + }, + }, + }, +} diff --git a/lua/kickstart/plugins/debug.lua b/lua/kickstart/plugins/debug.lua index 8e332bf2ff9..8c81d08c049 100644 --- a/lua/kickstart/plugins/debug.lua +++ b/lua/kickstart/plugins/debug.lua @@ -121,16 +121,16 @@ return { } -- Change breakpoint icons - -- vim.api.nvim_set_hl(0, 'DapBreak', { fg = '#e51400' }) - -- vim.api.nvim_set_hl(0, 'DapStop', { fg = '#ffcc00' }) - -- local breakpoint_icons = vim.g.have_nerd_font - -- and { Breakpoint = '', BreakpointCondition = '', BreakpointRejected = '', LogPoint = '', Stopped = '' } - -- or { Breakpoint = '●', BreakpointCondition = '⊜', BreakpointRejected = '⊘', LogPoint = '◆', Stopped = '⭔' } - -- for type, icon in pairs(breakpoint_icons) do - -- local tp = 'Dap' .. type - -- local hl = (type == 'Stopped') and 'DapStop' or 'DapBreak' - -- vim.fn.sign_define(tp, { text = icon, texthl = hl, numhl = hl }) - -- end + vim.api.nvim_set_hl(0, 'DapBreak', { fg = '#e51400' }) + vim.api.nvim_set_hl(0, 'DapStop', { fg = '#ffcc00' }) + local breakpoint_icons = vim.g.have_nerd_font + and { Breakpoint = '', BreakpointCondition = '', BreakpointRejected = '', LogPoint = '', Stopped = '' } + or { Breakpoint = '●', BreakpointCondition = '⊜', BreakpointRejected = '⊘', LogPoint = '◆', Stopped = '⭔' } + for type, icon in pairs(breakpoint_icons) do + local tp = 'Dap' .. type + local hl = (type == 'Stopped') and 'DapStop' or 'DapBreak' + vim.fn.sign_define(tp, { text = icon, texthl = hl, numhl = hl }) + end dap.listeners.after.event_initialized['dapui_config'] = dapui.open dap.listeners.before.event_terminated['dapui_config'] = dapui.close @@ -138,11 +138,25 @@ return { -- Install golang specific config require('dap-go').setup { + dap_configurations_from_gopls = false, delve = { -- On Windows delve must be run attached or it crashes. -- See https://github.com/leoluz/nvim-dap-go/blob/main/README.md#configuring detached = vim.fn.has 'win32' == 0, }, } + dap.configurations.go = dap.configurations.go or {} + table.insert(dap.configurations.go, { + type = 'go', + name = 'Attach remote (localhost:2345)', + mode = 'remote', + request = 'attach', + -- Connect to the port, not PID + port = 2345, + host = '127.0.0.1', + substitutePath = { + { from = '${workspaceFolder}', to = vim.fn.getcwd() }, + }, + }) end, } diff --git a/lua/kickstart/plugins/neo-tree.lua b/lua/kickstart/plugins/neo-tree.lua index c7067891df0..2d028336136 100644 --- a/lua/kickstart/plugins/neo-tree.lua +++ b/lua/kickstart/plugins/neo-tree.lua @@ -16,6 +16,7 @@ return { opts = { filesystem = { window = { + use_libuv_file_watcher = true, mappings = { ['\\'] = 'close_window', },