From db7dd381ff6f39535853e9c798388bdb5042692e Mon Sep 17 00:00:00 2001 From: Marco Dalla Stella Date: Fri, 2 Jan 2026 18:52:59 +0100 Subject: [PATCH] Initial commit --- .stylua.toml | 7 + init.lua | 34 +++ plugin/10_options.lua | 124 ++++++++++ plugin/20_keymaps.lua | 219 ++++++++++++++++++ plugin/30_mini.lua | 528 ++++++++++++++++++++++++++++++++++++++++++ plugin/40_plugins.lua | 133 +++++++++++ 6 files changed, 1045 insertions(+) create mode 100644 .stylua.toml create mode 100644 init.lua create mode 100644 plugin/10_options.lua create mode 100644 plugin/20_keymaps.lua create mode 100644 plugin/30_mini.lua create mode 100644 plugin/40_plugins.lua diff --git a/.stylua.toml b/.stylua.toml new file mode 100644 index 0000000..dfbc07e --- /dev/null +++ b/.stylua.toml @@ -0,0 +1,7 @@ +column_width = 85 +line_endings = "Unix" +indent_type = "Spaces" +indent_width = 2 +quote_style = "AutoPreferSingle" +call_parentheses = "Always" +collapse_simple_statement = "Always" diff --git a/init.lua b/init.lua new file mode 100644 index 0000000..47dbb6e --- /dev/null +++ b/init.lua @@ -0,0 +1,34 @@ +-- Bootstrap 'mini.nvim' manually in a way that it gets managed by 'mini.deps' +local mini_path = vim.fn.stdpath('data') .. '/site/pack/deps/start/mini.nvim' +if not vim.loop.fs_stat(mini_path) then + vim.cmd('echo "Installing `mini.nvim`" | redraw') + local origin = 'https://github.com/nvim-mini/mini.nvim' + local clone_cmd = { 'git', 'clone', '--filter=blob:none', origin, mini_path } + vim.fn.system(clone_cmd) + vim.cmd('packadd mini.nvim | helptags ALL') + vim.cmd('echo "Installed `mini.nvim`" | redraw') +end + +-- Plugin manager +require('mini.deps').setup() + +-- Shared config table +_G.Config = {} + +-- Define custom autocommand group and helper to create an autocommand. +-- Autocommands are Neovim's way to define actions that are executed on events +-- (like creating a buffer, setting an option, etc.). +-- +-- See also: +-- - `:h autocommand` +-- - `:h nvim_create_augroup()` +-- - `:h nvim_create_autocmd()` +local gr = vim.api.nvim_create_augroup('custom-config', {}) +_G.Config.new_autocmd = function(event, pattern, callback, desc) + local opts = { group = gr, pattern = pattern, callback = callback, desc = desc } + vim.api.nvim_create_autocmd(event, opts) +end + +-- Some plugins and 'mini.nvim' modules only need setup during startup if Neovim +-- is started like `nvim -- path/to/file`, otherwise delaying setup is fine +_G.Config.now_if_args = vim.fn.argc(-1) > 0 and MiniDeps.now or MiniDeps.later diff --git a/plugin/10_options.lua b/plugin/10_options.lua new file mode 100644 index 0000000..e1e2e12 --- /dev/null +++ b/plugin/10_options.lua @@ -0,0 +1,124 @@ +-- ┌──────────────────────────┐ +-- │ Built-in Neovim behavior │ +-- └──────────────────────────┘ +-- +-- This file defines Neovim's built-in behavior. The goal is to improve overall +-- usability in a way that works best with MINI. +-- +-- Here `vim.o.xxx = value` sets default value of option `xxx` to `value`. +-- See `:h 'xxx'` (replace `xxx` with actual option name). +-- +-- Option values can be customized on per buffer or window basis. +-- See 'after/ftplugin/' for common example. + +-- stylua: ignore start +-- The next part (until `-- stylua: ignore end`) is aligned manually for easier +-- reading. Consider preserving this or remove `-- stylua` lines to autoformat. + +-- General ==================================================================== +vim.g.mapleader = ' ' -- Use `` as key + +vim.o.mouse = 'a' -- Enable mouse +vim.o.mousescroll = 'ver:25,hor:6' -- Customize mouse scroll +vim.o.switchbuf = 'usetab' -- Use already opened buffers when switching +vim.o.undofile = true -- Enable persistent undo + +vim.o.shada = "'100,<50,s10,:1000,/100,@100,h" -- Limit ShaDa file (for startup) + +vim.opt.clipboard = 'unnamedplus' + +-- Enable all filetype plugins and syntax (if not enabled, for better startup) +vim.cmd('filetype plugin indent on') +if vim.fn.exists('syntax_on') ~= 1 then vim.cmd('syntax enable') end + +-- UI ========================================================================= +vim.o.breakindent = true -- Indent wrapped lines to match line start +vim.o.breakindentopt = 'list:-1' -- Add padding for lists (if 'wrap' is set) +vim.o.colorcolumn = '+1' -- Draw column on the right of maximum width +vim.o.cursorline = true -- Enable current line highlighting +vim.o.linebreak = true -- Wrap lines at 'breakat' (if 'wrap' is set) +vim.o.list = true -- Show helpful text indicators +vim.o.number = true -- Show line numbers +vim.o.pumheight = 10 -- Make popup menu smaller +vim.o.ruler = false -- Don't show cursor coordinates +vim.o.shortmess = 'CFOSWaco' -- Disable some built-in completion messages +vim.o.showmode = false -- Don't show mode in command line +vim.o.signcolumn = 'yes' -- Always show signcolumn (less flicker) +vim.o.splitbelow = true -- Horizontal splits will be below +vim.o.splitkeep = 'screen' -- Reduce scroll during window split +vim.o.splitright = true -- Vertical splits will be to the right +vim.o.winborder = 'single' -- Use border in floating windows +vim.o.wrap = false -- Don't visually wrap lines (toggle with \w) + +vim.o.cursorlineopt = 'screenline,number' -- Show cursor line per screen line + +-- Special UI symbols. More is set via 'mini.basics' later. +vim.o.fillchars = 'eob: ,fold:╌' +vim.o.listchars = 'extends:…,nbsp:␣,precedes:…,tab:> ' + +-- Folds (see `:h fold-commands`, `:h zM`, `:h zR`, `:h zA`, `:h zj`) +vim.o.foldlevel = 10 -- Fold nothing by default; set to 0 or 1 to fold +vim.o.foldmethod = 'indent' -- Fold based on indent level +vim.o.foldnestmax = 10 -- Limit number of fold levels +vim.o.foldtext = '' -- Show text under fold with its highlighting + +-- Editing ==================================================================== +vim.o.autoindent = true -- Use auto indent +vim.o.expandtab = true -- Convert tabs to spaces +vim.o.formatoptions = 'rqnl1j'-- Improve comment editing +vim.o.ignorecase = true -- Ignore case during search +vim.o.incsearch = true -- Show search matches while typing +vim.o.infercase = true -- Infer case in built-in completion +vim.o.shiftwidth = 2 -- Use this number of spaces for indentation +vim.o.smartcase = true -- Respect case if search pattern has upper case +vim.o.smartindent = true -- Make indenting smart +vim.o.spelloptions = 'camel' -- Treat camelCase word parts as separate words +vim.o.tabstop = 2 -- Show tab as this number of spaces +vim.o.virtualedit = 'block' -- Allow going past end of line in blockwise mode + +vim.o.iskeyword = '@,48-57,_,192-255,-' -- Treat dash as `word` textobject part + +-- Pattern for a start of numbered list (used in `gw`). This reads as +-- "Start of list item is: at least one special character (digit, -, +, *) +-- possibly followed by punctuation (. or `)`) followed by at least one space". +vim.o.formatlistpat = [[^\s*[0-9\-\+\*]\+[\.\)]*\s\+]] + +-- Built-in completion +vim.o.complete = '.,w,b,kspell' -- Use less sources +vim.o.completeopt = 'menuone,noselect,fuzzy,nosort' -- Use custom behavior + +-- Autocommands =============================================================== + +-- Don't auto-wrap comments and don't insert comment leader after hitting 'o'. +-- Do on `FileType` to always override these changes from filetype plugins. +local f = function() vim.cmd('setlocal formatoptions-=c formatoptions-=o') end +_G.Config.new_autocmd('FileType', nil, f, "Proper 'formatoptions'") + +-- There are other autocommands created by 'mini.basics'. See 'plugin/30_mini.lua'. + +-- Diagnostics ================================================================ + +-- Neovim has built-in support for showing diagnostic messages. This configures +-- a more conservative display while still being useful. +-- See `:h vim.diagnostic` and `:h vim.diagnostic.config()`. +local diagnostic_opts = { + -- Show signs on top of any other sign, but only for warnings and errors + signs = { priority = 9999, severity = { min = 'WARN', max = 'ERROR' } }, + + -- Show all diagnostics as underline (for their messages type `ld`) + underline = { severity = { min = 'HINT', max = 'ERROR' } }, + + -- Show more details immediately for errors on the current line + virtual_lines = false, + virtual_text = { + current_line = true, + severity = { min = 'ERROR', max = 'ERROR' }, + }, + + -- Don't update diagnostics when typing + update_in_insert = false, +} + +-- Use `later()` to avoid sourcing `vim.diagnostic` on startup +MiniDeps.later(function() vim.diagnostic.config(diagnostic_opts) end) +-- stylua: ignore end diff --git a/plugin/20_keymaps.lua b/plugin/20_keymaps.lua new file mode 100644 index 0000000..87d551d --- /dev/null +++ b/plugin/20_keymaps.lua @@ -0,0 +1,219 @@ +-- ┌─────────────────┐ +-- │ Custom mappings │ +-- └─────────────────┘ +-- +-- This file contains definitions of custom general and Leader mappings. + +-- General mappings =========================================================== + +-- Use this section to add custom general mappings. See `:h vim.keymap.set()`. + +-- An example helper to create a Normal mode mapping +local nmap = function(lhs, rhs, desc) + -- See `:h vim.keymap.set()` + vim.keymap.set('n', lhs, rhs, { desc = desc }) +end + +-- Paste linewise before/after current line +-- Usage: `yiw` to yank a word and `]p` to put it on the next line. +nmap('[p', 'exe "put! " . v:register', 'Paste Above') +nmap(']p', 'exe "put " . v:register', 'Paste Below') + +-- Many general mappings are created by 'mini.basics'. See 'plugin/30_mini.lua' + +-- stylua: ignore start +-- The next part (until `-- stylua: ignore end`) is aligned manually for easier +-- reading. Consider preserving this or remove `-- stylua` lines to autoformat. + +-- Leader mappings ============================================================ + +-- Neovim has the concept of a Leader key (see `:h `). It is a configurable +-- key that is primarily used for "workflow" mappings (opposed to text editing). +-- Like "open file explorer", "create scratch buffer", "pick from buffers". +-- +-- In 'plugin/10_options.lua' is set to , i.e. press +-- whenever there is a suggestion to press . +-- +-- This config uses a "two key Leader mappings" approach: first key describes +-- semantic group, second key executes an action. Both keys are usually chosen +-- to create some kind of mnemonic. +-- Example: `f` groups "find" type of actions; `ff` - find files. +-- Use this section to add Leader mappings in a structural manner. +-- +-- Usually if there are global and local kinds of actions, lowercase second key +-- denotes global and uppercase - local. +-- Example: `fs` / `fS` - find workspace/document LSP symbols. +-- +-- Many of the mappings use 'mini.nvim' modules set up in 'plugin/30_mini.lua'. + +-- Create a global table with information about Leader groups in certain modes. +-- This is used to provide 'mini.clue' with extra clues. +-- Add an entry if you create a new group. +_G.Config.leader_group_clues = { + { mode = 'n', keys = 'b', desc = '+Buffer' }, + { mode = 'n', keys = 'e', desc = '+Explore/Edit' }, + { mode = 'n', keys = 'f', desc = '+Find' }, + { mode = 'n', keys = 'g', desc = '+Git' }, + { mode = 'n', keys = 'l', desc = '+Language' }, + { mode = 'n', keys = 'm', desc = '+Map' }, + { mode = 'n', keys = 'o', desc = '+Other' }, + { mode = 'n', keys = 's', desc = '+Session' }, + { mode = 'n', keys = 't', desc = '+Terminal' }, + { mode = 'n', keys = 'v', desc = '+Visits' }, + + { mode = 'x', keys = 'g', desc = '+Git' }, + { mode = 'x', keys = 'l', desc = '+Language' }, +} + +-- Helpers for a more concise `` mappings. +-- Most of the mappings use `...` string as a right hand side (RHS) in +-- an attempt to be more concise yet descriptive. See `:h `. +-- This approach also doesn't require the underlying commands/functions to exist +-- during mapping creation: a "lazy loading" approach to improve startup time. +local nmap_leader = function(suffix, rhs, desc) + vim.keymap.set('n', '' .. suffix, rhs, { desc = desc }) +end +local xmap_leader = function(suffix, rhs, desc) + vim.keymap.set('x', '' .. suffix, rhs, { desc = desc }) +end + +-- b is for 'Buffer'. Common usage: +-- - `bs` - create scratch (temporary) buffer +-- - `ba` - navigate to the alternative buffer +-- - `bw` - wipeout (fully delete) current buffer +local new_scratch_buffer = function() + vim.api.nvim_win_set_buf(0, vim.api.nvim_create_buf(true, true)) +end + +nmap_leader('ba', 'b#', 'Alternate') +nmap_leader('bd', 'lua MiniBufremove.delete()', 'Delete') +nmap_leader('bD', 'lua MiniBufremove.delete(0, true)', 'Delete!') +nmap_leader('bs', new_scratch_buffer, 'Scratch') +nmap_leader('bw', 'write', 'Write') + +-- e is for 'Explore' and 'Edit'. Common usage: +-- - `ed` - open explorer at current working directory +-- - `ef` - open directory of current file (needs to be present on disk) +-- - `ei` - edit 'init.lua' +-- - All mappings that use `edit_plugin_file` - edit 'plugin/' config files +local edit_plugin_file = function(filename) + return string.format('edit %s/plugin/%s', vim.fn.stdpath('config'), filename) +end +local explore_at_file = 'lua MiniFiles.open(vim.api.nvim_buf_get_name(0))' +local explore_quickfix = function() + for _, win_id in ipairs(vim.api.nvim_tabpage_list_wins(0)) do + if vim.fn.getwininfo(win_id)[1].quickfix == 1 then return vim.cmd('cclose') end + end + vim.cmd('copen') +end + +nmap_leader('ed', 'lua MiniFiles.open()', 'Directory') +nmap_leader('ef', explore_at_file, 'File directory') +nmap_leader('ei', 'edit $MYVIMRC', 'init.lua') +nmap_leader('ek', edit_plugin_file('20_keymaps.lua'), 'Keymaps config') +nmap_leader('em', edit_plugin_file('30_mini.lua'), 'MINI config') +nmap_leader('en', 'lua MiniNotify.show_history()', 'Notifications') +nmap_leader('eo', edit_plugin_file('10_options.lua'), 'Options config') +nmap_leader('ep', edit_plugin_file('40_plugins.lua'), 'Plugins config') +nmap_leader('eq', explore_quickfix, 'Quickfix') + +-- f is for 'Fuzzy Find'. Common usage: +-- - `ff` - find files; for best performance requires `ripgrep` +-- - `fg` - find inside files; requires `ripgrep` +-- - `fh` - find help tag +-- - `fr` - resume latest picker +-- - `fv` - all visited paths; requires 'mini.visits' +-- +-- All these use 'mini.pick'. See `:h MiniPick-overview` for an overview. +local pick_workspace_symbols_live = 'Pick lsp scope="workspace_symbol_live"' + +nmap_leader('f/', 'Pick history scope="/"', '"/" history') +nmap_leader('f:', 'Pick history scope=":"', '":" history') +nmap_leader('fb', 'Pick buffers', 'Buffers') +nmap_leader('fd', 'Pick diagnostic scope="all"', 'Diagnostic workspace') +nmap_leader('fD', 'Pick diagnostic scope="current"', 'Diagnostic buffer') +nmap_leader('ff', 'Pick files', 'Files') +nmap_leader('fg', 'Pick grep_live', 'Grep live') +nmap_leader('fG', 'Pick grep pattern=""', 'Grep current word') +nmap_leader('fh', 'Pick help', 'Help tags') +nmap_leader('fH', 'Pick hl_groups', 'Highlight groups') +nmap_leader('fl', 'Pick buf_lines scope="all"', 'Lines (all)') +nmap_leader('fL', 'Pick buf_lines scope="current"', 'Lines (buf)') +nmap_leader('fr', 'Pick resume', 'Resume') +nmap_leader('fR', 'Pick lsp scope="references"', 'References (LSP)') +nmap_leader('fs', pick_workspace_symbols_live, 'Symbols workspace (live)') +nmap_leader('fS', 'Pick lsp scope="document_symbol"', 'Symbols document') +nmap_leader('fv', 'Pick visit_paths cwd=""', 'Visit paths (all)') +nmap_leader('fV', 'Pick visit_paths', 'Visit paths (cwd)') + +-- l is for 'Language'. Common usage: +-- - `ld` - show more diagnostic details in a floating window +-- - `lr` - perform rename via LSP +-- - `ls` - navigate to source definition of symbol under cursor +-- +-- NOTE: most LSP mappings represent a more structured way of replacing built-in +-- LSP mappings (like `:h gra` and others). This is needed because `gr` is mapped +-- by an "replace" operator in 'mini.operators' (which is more commonly used). +local formatting_cmd = 'lua require("conform").format({lsp_fallback=true})' + +nmap_leader('la', 'lua vim.lsp.buf.code_action()', 'Actions') +nmap_leader('ld', 'lua vim.diagnostic.open_float()', 'Diagnostic popup') +nmap_leader('lf', formatting_cmd, 'Format') +nmap_leader('li', 'lua vim.lsp.buf.implementation()', 'Implementation') +nmap_leader('lh', 'lua vim.lsp.buf.hover()', 'Hover') +nmap_leader('lr', 'lua vim.lsp.buf.rename()', 'Rename') +nmap_leader('lR', 'lua vim.lsp.buf.references()', 'References') +nmap_leader('ls', 'lua vim.lsp.buf.definition()', 'Source definition') +nmap_leader('lt', 'lua vim.lsp.buf.type_definition()', 'Type definition') + +xmap_leader('lf', formatting_cmd, 'Format selection') + +-- m is for 'Map'. Common usage: +-- - `mt` - toggle map from 'mini.map' (closed by default) +-- - `mf` - focus on the map for fast navigation +-- - `ms` - change map's side (if it covers something underneath) +nmap_leader('mf', 'lua MiniMap.toggle_focus()', 'Focus (toggle)') +nmap_leader('mr', 'lua MiniMap.refresh()', 'Refresh') +nmap_leader('ms', 'lua MiniMap.toggle_side()', 'Side (toggle)') +nmap_leader('mt', 'lua MiniMap.toggle()', 'Toggle') + +-- o is for 'Other'. Common usage: +-- - `oz` - toggle between "zoomed" and regular view of current buffer +nmap_leader('or', 'lua MiniMisc.resize_window()', 'Resize to default width') +nmap_leader('ot', 'lua MiniTrailspace.trim()', 'Trim trailspace') +nmap_leader('oz', 'lua MiniMisc.zoom()', 'Zoom toggle') + +-- s is for 'Session'. Common usage: +-- - `sn` - start new session +-- - `sr` - read previously started session +-- - `sd` - delete previously started session +local session_new = 'MiniSessions.write(vim.fn.input("Session name: "))' + +nmap_leader('sd', 'lua MiniSessions.select("delete")', 'Delete') +nmap_leader('sn', 'lua ' .. session_new .. '', 'New') +nmap_leader('sr', 'lua MiniSessions.select("read")', 'Read') +nmap_leader('sw', 'lua MiniSessions.write()', 'Write current') + +-- t is for 'Terminal' +nmap_leader('tT', 'horizontal term', 'Terminal (horizontal)') +nmap_leader('tt', 'vertical term', 'Terminal (vertical)') + +-- v is for 'Visits'. Common usage: +-- - `vv` - add "core" label to current file. +-- - `vV` - remove "core" label to current file. +-- - `vc` - pick among all files with "core" label. +local make_pick_core = function(cwd, desc) + return function() + local sort_latest = MiniVisits.gen_sort.default({ recency_weight = 1 }) + local local_opts = { cwd = cwd, filter = 'core', sort = sort_latest } + MiniExtra.pickers.visit_paths(local_opts, { source = { name = desc } }) + end +end + +nmap_leader('vc', make_pick_core('', 'Core visits (all)'), 'Core visits (all)') +nmap_leader('vC', make_pick_core(nil, 'Core visits (cwd)'), 'Core visits (cwd)') +nmap_leader('vv', 'lua MiniVisits.add_label("core")', 'Add "core" label') +nmap_leader('vV', 'lua MiniVisits.remove_label("core")', 'Remove "core" label') +nmap_leader('vl', 'lua MiniVisits.add_label()', 'Add label') +nmap_leader('vL', 'lua MiniVisits.remove_label()', 'Remove label') +-- stylua: ignore end diff --git a/plugin/30_mini.lua b/plugin/30_mini.lua new file mode 100644 index 0000000..442871f --- /dev/null +++ b/plugin/30_mini.lua @@ -0,0 +1,528 @@ +-- ┌────────────────────┐ +-- │ MINI configuration │ +-- └────────────────────┘ +-- +-- This file contains configuration of the MINI parts of the config. +-- It contains only configs for the 'mini.nvim' plugin (installed in 'init.lua'). + +local now, later = MiniDeps.now, MiniDeps.later +local now_if_args = _G.Config.now_if_args + +-- Common configuration presets. Example usage: +-- - `` in Insert mode - save and go to Normal mode +-- - `go` / `gO` - insert empty line before/after in Normal mode +-- - `gy` / `gp` - copy / paste from system clipboard +-- - `\` + key - toggle common options. Like `\h` toggles highlighting search. +-- - `` (four combos) - navigate between windows. +-- - `` in Insert/Command mode - navigate in that mode. +-- +-- See also: +-- - `:h MiniBasics.config.options` - list of adjusted options +-- - `:h MiniBasics.config.mappings` - list of created mappings +-- - `:h MiniBasics.config.autocommands` - list of created autocommands +now(function() + require('mini.basics').setup({ + options = { basic = false }, + mappings = { + -- Create `` mappings for window navigation + windows = true, + -- Create `` mappings for navigation in Insert and Command modes + move_with_alt = true, + }, + }) +end) + +-- Icon provider. Usually no need to use manually. It is used by plugins like +-- 'mini.pick', 'mini.files', 'mini.statusline', and others. +now(function() + -- Set up to not prefer extension-based icon for some extensions + local ext3_blocklist = { scm = true, txt = true, yml = true } + local ext4_blocklist = { json = true, yaml = true } + require('mini.icons').setup({ + use_file_extension = function(ext, _) + return not (ext3_blocklist[ext:sub(-3)] or ext4_blocklist[ext:sub(-4)]) + end, + }) + + -- Mock 'nvim-tree/nvim-web-devicons' for plugins without 'mini.icons' support. + -- Not needed for 'mini.nvim' or MiniMax, but might be useful for others. + later(MiniIcons.mock_nvim_web_devicons) + + -- Add LSP kind icons. Useful for 'mini.completion'. + later(MiniIcons.tweak_lsp_kind) +end) + +-- Miscellaneous small but useful functions. Example usage: +-- - `oz` - toggle between "zoomed" and regular view of current buffer +-- - `or` - resize window to its "editable width" +-- - `:lua put_text(vim.lsp.get_clients())` - put output of a function below +-- cursor in current buffer. Useful for a detailed exploration. +-- - `:lua put(MiniMisc.stat_summary(MiniMisc.bench_time(f, 100)))` - run +-- function `f` 100 times and report statistical summary of execution times +-- +-- Uses `now()` for `setup_xxx()` to work when started like `nvim -- path/to/file` +now(function() + -- Makes `:h MiniMisc.put()` and `:h MiniMisc.put_text()` public + require('mini.misc').setup() + + -- Change current working directory based on the current file path. It + -- searches up the file tree until the first root marker ('.git' or 'Makefile') + -- and sets their parent directory as a current directory. + -- This is helpful when simultaneously dealing with files from several projects. + MiniMisc.setup_auto_root() + + -- Restore latest cursor position on file open + MiniMisc.setup_restore_cursor() + + -- Synchronize terminal emulator background with Neovim's background to remove + -- possibly different color padding around Neovim instance + MiniMisc.setup_termbg_sync() +end) + +-- Notifications provider. Shows all kinds of notifications in the upper right +-- corner (by default). Example usage: +-- - `:h vim.notify()` - show notification (hides automatically) +-- - `en` - show notification history +-- +-- See also: +-- - `:h MiniNotify.config` for some of common configuration examples. +now(function() require('mini.notify').setup() end) + +-- Session management. A thin wrapper around `:h mksession` that consistently +-- manages session files. Example usage: +-- - `sn` - start new session +-- - `sr` - read previously started session +-- - `sd` - delete previously started session +now(function() require('mini.sessions').setup() end) + +-- Start screen. This is what is shown when you open Neovim like `nvim`. +-- Example usage: +-- - Type prefix keys to limit available candidates +-- - Navigate down/up with `` and `` +-- - Press `` to select an entry +-- +-- See also: +-- - `:h MiniStarter-example-config` - non-default config examples +-- - `:h MiniStarter-lifecycle` - how to work with Starter buffer +now(function() require('mini.starter').setup() end) + +-- Statusline. Sets `:h 'statusline'` to show more info in a line below window. +-- See also: +-- - `:h MiniStatusline-example-content` - example of default content. Use it to +-- configure a custom statusline by setting `config.content.active` function. +now(function() require('mini.statusline').setup() end) + +-- Tabline. Sets `:h 'tabline'` to show all listed buffers in a line at the top. +-- Buffers are ordered as they were created. Navigate with `[b` and `]b`. +now(function() require('mini.tabline').setup() end) + +-- Extra 'mini.nvim' functionality. +-- +-- See also: +-- - `:h MiniExtra.pickers` - pickers. Most are mapped in `f` group. +-- Calling `setup()` makes 'mini.pick' respect 'mini.extra' pickers. +-- - `:h MiniExtra.gen_ai_spec` - 'mini.ai' textobject specifications +-- - `:h MiniExtra.gen_highlighter` - 'mini.hipatterns' highlighters +later(function() require('mini.extra').setup() end) + +-- Extend and create a/i textobjects, like `:h a(`, `:h a'`, and more). +-- Contains not only `a` and `i` type of textobjects, but also their "next" and +-- "last" variants that will explicitly search for textobjects after and before +-- cursor. Example usage: +-- - `ci)` - *c*hange *i*inside parenthesis (`)`) +-- - `di(` - *d*elete *i*inside padded parenthesis (`(`) +-- - `yaq` - *y*ank *a*round *q*uote (any of "", '', or ``) +-- - `vif` - *v*isually select *i*inside *f*unction call +-- - `cina` - *c*hange *i*nside *n*ext *a*rgument +-- - `valaala` - *v*isually select *a*round *l*ast (i.e. previous) *a*rgument +-- and then again reselect *a*round new *l*ast *a*rgument +-- +-- See also: +-- - `:h text-objects` - general info about what textobjects are +-- - `:h MiniAi-builtin-textobjects` - list of all supported textobjects +-- - `:h MiniAi-textobject-specification` - examples of custom textobjects +later(function() + local ai = require('mini.ai') + ai.setup({ + -- 'mini.ai' can be extended with custom textobjects + custom_textobjects = { + -- Make `aB` / `iB` act on around/inside whole *b*uffer + B = MiniExtra.gen_ai_spec.buffer(), + -- For more complicated textobjects that require structural awareness, + -- use tree-sitter. This example makes `aF`/`iF` mean around/inside function + -- definition (not call). See `:h MiniAi.gen_spec.treesitter()` for details. + F = ai.gen_spec.treesitter({ a = '@function.outer', i = '@function.inner' }), + }, + + -- 'mini.ai' by default mostly mimics built-in search behavior: first try + -- to find textobject covering cursor, then try to find to the right. + -- Although this works in most cases, some are confusing. It is more robust to + -- always try to search only covering textobject and explicitly ask to search + -- for next (`an`/`in`) or last (`al`/`il`). + -- Try this. If you don't like it - delete next line and this comment. + search_method = 'cover', + }) +end) + +-- Align text interactively. Example usage: +-- - `gaip,` - `ga` (align operator) *i*nside *p*aragraph by comma +-- - `gAip` - start interactive alignment on the paragraph. Choose how to +-- split, justify, and merge string parts. Press `` to make it permanent, +-- press `` to go back to initial state. +-- +-- See also: +-- - `:h MiniAlign-example` - hands-on list of examples to practice aligning +-- - `:h MiniAlign.gen_step` - list of support step customizations +-- - `:h MiniAlign-algorithm` - how alignment is done on algorithmic level +later(function() require('mini.align').setup() end) + +-- Remove buffers. Opened files occupy space in tabline and buffer picker. +-- When not needed, they can be removed. Example usage: +-- - `bw` - completely wipeout current buffer (see `:h :bwipeout`) +-- - `bW` - completely wipeout current buffer even if it has changes +-- - `bd` - delete current buffer (see `:h :bdelete`) +later(function() require('mini.bufremove').setup() end) + +-- Show next key clues in a bottom right window. Requires explicit opt-in for +-- keys that act as clue trigger. +-- +-- See also: +-- - `:h MiniClue-examples` - examples of common setups +-- - `:h MiniClue.ensure_buf_triggers()` - use it to enable triggers in buffer +-- - `:h MiniClue.set_mapping_desc()` - change mapping description not from config +later(function() + local miniclue = require('mini.clue') + -- stylua: ignore + miniclue.setup({ + -- Define which clues to show. By default shows only clues for custom mappings + -- (uses `desc` field from the mapping; takes precedence over custom clue). + clues = { + -- This is defined in 'plugin/20_keymaps.lua' with Leader group descriptions + Config.leader_group_clues, + miniclue.gen_clues.builtin_completion(), + miniclue.gen_clues.g(), + miniclue.gen_clues.marks(), + miniclue.gen_clues.registers(), + -- This creates a submode for window resize mappings. Try the following: + -- - Press `s` to make a window split. + -- - Press `+` to increase height. Clue window still shows clues as if + -- `` is pressed again. Keep pressing just `+` to increase height. + -- Try pressing `-` to decrease height. + -- - Stop submode either by `` or by any key that is not in submode. + miniclue.gen_clues.windows({ submode_resize = true }), + miniclue.gen_clues.z(), + }, + -- Explicitly opt-in for set of common keys to trigger clue window + triggers = { + { mode = 'n', keys = '' }, -- Leader triggers + { mode = 'x', keys = '' }, + { mode = 'n', keys = '\\' }, -- mini.basics + { mode = 'n', keys = '[' }, -- mini.bracketed + { mode = 'n', keys = ']' }, + { mode = 'x', keys = '[' }, + { mode = 'x', keys = ']' }, + { mode = 'i', keys = '' }, -- Built-in completion + { mode = 'n', keys = 'g' }, -- `g` key + { mode = 'x', keys = 'g' }, + { mode = 'n', keys = "'" }, -- Marks + { mode = 'n', keys = '`' }, + { mode = 'x', keys = "'" }, + { mode = 'x', keys = '`' }, + { mode = 'n', keys = '"' }, -- Registers + { mode = 'x', keys = '"' }, + { mode = 'i', keys = '' }, + { mode = 'c', keys = '' }, + { mode = 'n', keys = '' }, -- Window commands + { mode = 'n', keys = 'z' }, -- `z` key + { mode = 'x', keys = 'z' }, + }, + window = { + config = { + width = 50, + }, + }, + }) +end) + +-- Command line tweaks. Improves command line editing with: +-- - Autocompletion. Basically an automated `:h cmdline-completion`. +-- - Autocorrection of words as-you-type. Like `:W`->`:w`, `:lau`->`:lua`, etc. +-- - Autopeek command range (like line number at the start) as-you-type. +later(function() require('mini.cmdline').setup() end) + +-- Comment lines. Provides functionality to work with commented lines. +-- Uses `:h 'commentstring'` option to infer comment structure. +-- The built-in `:h commenting` is based on 'mini.comment'. Yet this module is +-- still enabled as it provides more customization opportunities. +later(function() require('mini.comment').setup() end) + +-- Completion and signature help. Implements async "two stage" autocompletion: +-- - Based on attached LSP servers that support completion. +-- - Fallback (based on built-in keyword completion) if there is no LSP candidates. +-- +-- It also works with snippet candidates provided by LSP server. Best experience +-- when paired with 'mini.snippets' (which is set up in this file). +later(function() + -- Customize post-processing of LSP responses for a better user experience. + -- Don't show 'Text' suggestions (usually noisy) and show snippets last. + local process_items_opts = { kind_priority = { Text = -1, Snippet = 99 } } + local process_items = function(items, base) + return MiniCompletion.default_process_items(items, base, process_items_opts) + end + require('mini.completion').setup({ + lsp_completion = { + -- Without this config autocompletion is set up through `:h 'completefunc'`. + -- Although not needed, setting up through `:h 'omnifunc'` is cleaner + -- (sets up only when needed) and makes it possible to use ``. + source_func = 'omnifunc', + auto_setup = false, + process_items = process_items, + }, + }) + + -- Set 'omnifunc' for LSP completion only when needed. + local on_attach = function(ev) + vim.bo[ev.buf].omnifunc = 'v:lua.MiniCompletion.completefunc_lsp' + end + _G.Config.new_autocmd('LspAttach', nil, on_attach, "Set 'omnifunc'") + + -- Advertise to servers that Neovim now supports certain set of completion and + -- signature features through 'mini.completion'. + vim.lsp.config('*', { capabilities = MiniCompletion.get_lsp_capabilities() }) +end) + +-- Work with diff hunks that represent the difference between the buffer text and +-- some reference text set by a source. Default source uses text from Git index. +-- Also provides summary info used in developer section of 'mini.statusline'. +-- Example usage: +-- - `ghip` - apply hunks (`gh`) within *i*nside *p*aragraph +-- - `gHG` - reset hunks (`gH`) from cursor until end of buffer (`G`) +-- - `ghgh` - apply (`gh`) hunk at cursor (`gh`) +-- - `gHgh` - reset (`gH`) hunk at cursor (`gh`) +-- - `go` - toggle overlay +-- +-- See also: +-- - `:h MiniDiff-overview` - overview of how module works +-- - `:h MiniDiff-diff-summary` - available summary information +-- - `:h MiniDiff.gen_source` - available built-in sources +later(function() require('mini.diff').setup() end) + +-- Navigate and manipulate file system +-- +-- See also: +-- - `:h MiniFiles-navigation` - more details about how to navigate +-- - `:h MiniFiles-manipulation` - more details about how to manipulate +-- - `:h MiniFiles-examples` - examples of common setups +later(function() + -- Enable directory/file preview + require('mini.files').setup({ windows = { preview = false } }) + + -- Add common bookmarks for every explorer. Example usage inside explorer: + -- - `'c` to navigate into your config directory + -- - `g?` to see available bookmarks + local add_marks = function() + MiniFiles.set_bookmark('c', vim.fn.stdpath('config'), { desc = 'Config' }) + local minideps_plugins = vim.fn.stdpath('data') .. '/site/pack/deps/opt' + MiniFiles.set_bookmark('p', minideps_plugins, { desc = 'Plugins' }) + MiniFiles.set_bookmark('w', vim.fn.getcwd, { desc = 'Working directory' }) + end + _G.Config.new_autocmd('User', 'MiniFilesExplorerOpen', add_marks, 'Add bookmarks') +end) + +-- Highlight patterns in text. Like `TODO`/`NOTE` or color hex codes. +-- See also: +-- - `:h MiniHipatterns-examples` - examples of common setups +later(function() + local hipatterns = require('mini.hipatterns') + local hi_words = MiniExtra.gen_highlighter.words + hipatterns.setup({ + highlighters = { + -- Highlight a fixed set of common words. Will be highlighted in any place, + -- not like "only in comments". + fixme = hi_words({ 'FIXME', 'Fixme', 'fixme' }, 'MiniHipatternsFixme'), + hack = hi_words({ 'HACK', 'Hack', 'hack' }, 'MiniHipatternsHack'), + todo = hi_words({ 'TODO', 'Todo', 'todo' }, 'MiniHipatternsTodo'), + note = hi_words({ 'NOTE', 'Note', 'note' }, 'MiniHipatternsNote'), + + -- Highlight hex color string (#aabbcc) with that color as a background + hex_color = hipatterns.gen_highlighter.hex_color(), + }, + }) +end) + +-- Visualize and work with indent scope. It visualizes indent scope "at cursor" +-- with animated vertical line. Provides relevant motions and textobjects. +-- Example usage: +-- - `cii` - *c*hange *i*nside *i*ndent scope +-- - `Vaiai` - *V*isually select *a*round *i*ndent scope and then again +-- reselect *a*round new *i*indent scope +-- - `[i` / `]i` - navigate to scope's top / bottom +-- +-- See also: +-- - `:h MiniIndentscope.gen_animation` - available animation rules +later(function() require('mini.indentscope').setup( + { + draw = { + animation = require('mini.indentscope').gen_animation.none() + } + } +) end) + +-- Jump within visible lines to pre-defined spots via iterative label filtering. +-- See also: +-- - `:h MiniJump2d.gen_spotter` - list of available spotters +later(function() require('mini.jump2d').setup() end) + +-- Special key mappings. +-- See also: +-- - `:h MiniKeymap-examples` - examples of common setups +-- - `:h MiniKeymap.map_multistep()` - map multi-step action +-- - `:h MiniKeymap.map_combo()` - map combo +later(function() + require('mini.keymap').setup() + -- Navigate 'mini.completion' menu with `` / `` + MiniKeymap.map_multistep('i', '', { 'pmenu_next' }) + MiniKeymap.map_multistep('i', '', { 'pmenu_prev' }) + -- On `` try to accept current completion item, fall back to accounting + -- for pairs from 'mini.pairs' + MiniKeymap.map_multistep('i', '', { 'pmenu_accept', 'minipairs_cr' }) + -- On `` just try to account for pairs from 'mini.pairs' + MiniKeymap.map_multistep('i', '', { 'minipairs_bs' }) +end) + +-- Autopairs functionality. Insert pair when typing opening character and go over +-- right character if it is already to cursor's right. Also provides mappings for +-- `` and `` to perform extra actions when inside pair. +-- Example usage in Insert mode: +-- - `(` - insert "()" and put cursor between them +-- - `)` when there is ")" to the right - jump over ")" without inserting new one +-- - `(` - always insert a single "(" literally. This is useful since +-- 'mini.pairs' doesn't provide particularly smart behavior, like auto balancing +later(function() + -- Create pairs not only in Insert, but also in Command line mode + require('mini.pairs').setup({ modes = { command = true } }) +end) + +-- Autopairs functionality. Insert pair when typing opening character and go over +-- right character if it is already to cursor's right. Also provides mappings for +-- `` and `` to perform extra actions when inside pair. +-- Example usage in Insert mode: +-- - `(` - insert "()" and put cursor between them +-- - `)` when there is ")" to the right - jump over ")" without inserting new one +-- - `(` - always insert a single "(" literally. This is useful since +-- 'mini.pairs' doesn't provide particularly smart behavior, like auto balancing +later(function() + -- Create pairs not only in Insert, but also in Command line mode + require('mini.pairs').setup({ modes = { command = true } }) +end) + +-- Pick anything with single window layout and fast matching. This is one of +-- the main usability improvements as it powers a lot of "find things quickly" +-- workflows. +-- See also: +-- - `:h MiniPick-overview` - overview of picker functionality +-- - `:h MiniPick-examples` - examples of common setups +-- - `:h MiniPick.builtin` and `:h MiniExtra.pickers` - available pickers; +-- Execute one either with Lua function, `:Pick ` command, or +-- one of `f` mappings defined in 'plugin/20_keymaps.lua' +later(function() require('mini.pick').setup() end) + +-- Manage and expand snippets (templates for a frequently used text). +-- Typical workflow is to type snippet's (configurable) prefix and expand it +-- into a snippet session. +-- +-- How to manage snippets: +-- - 'mini.snippets' itself doesn't come with preconfigured snippets. Instead there +-- is a flexible system of how snippets are prepared before expanding. +-- They can come from pre-defined path on disk, 'snippets/' directories inside +-- config or plugins, defined inside `setup()` call directly. +-- - This config, however, does come with snippet configuration: +-- - 'snippets/global.json' is a file with global snippets that will be +-- available in any buffer +-- - 'after/snippets/lua.json' defines personal snippets for Lua language +-- - 'friendly-snippets' plugin configured in 'plugin/40_plugins.lua' provides +-- a collection of language snippets +-- +-- How to expand a snippet in Insert mode: +-- - If you know snippet's prefix, type it as a word and press ``. Snippet's +-- body should be inserted instead of the prefix. +-- - If you don't remember snippet's prefix, type only part of it (or none at all) +-- and press ``. It should show picker with all snippets that have prefixes +-- matching typed characters (or all snippets if none was typed). +-- Choose one and its body should be inserted instead of previously typed text. +-- +-- How to navigate during snippet session: +-- - Snippets can contain tabstops - places for user to interactively adjust text. +-- Each tabstop is highlighted depending on session progression - whether tabstop +-- is current, was or was not visited. If tabstop doesn't yet have text, it is +-- visualized with special "ghost" inline text: • and ∎ by default. +-- - Type necessary text at current tabstop and navigate to next/previous one +-- by pressing `` / ``. +-- - Repeat previous step until you reach special final tabstop, usually denoted +-- by ∎ symbol. If you spotted a mistake in an earlier tabstop, navigate to it +-- and return back to the final tabstop. +-- - To end a snippet session when at final tabstop, keep typing or go into +-- Normal mode. To force end snippet session, press ``. +-- +-- See also: +-- - `:h MiniSnippets-overview` - overview of how module works +-- - `:h MiniSnippets-examples` - examples of common setups +-- - `:h MiniSnippets-session` - details about snippet session +-- - `:h MiniSnippets.gen_loader` - list of available loaders +-- later(function() +-- -- Define language patterns to work better with 'friendly-snippets' +-- local latex_patterns = { 'latex/**/*.json', '**/latex.json' } +-- local lang_patterns = { +-- tex = latex_patterns, +-- plaintex = latex_patterns, +-- -- Recognize special injected language of markdown tree-sitter parser +-- markdown_inline = { 'markdown.json' }, +-- } +-- +-- local snippets = require('mini.snippets') +-- local config_path = vim.fn.stdpath('config') +-- snippets.setup({ +-- snippets = { +-- -- Always load 'snippets/global.json' from config directory +-- snippets.gen_loader.from_file(config_path .. '/snippets/global.json'), +-- -- Load from 'snippets/' directory of plugins, like 'friendly-snippets' +-- snippets.gen_loader.from_lang({ lang_patterns = lang_patterns }), +-- }, +-- }) +-- +-- -- By default snippets available at cursor are not shown as candidates in +-- -- 'mini.completion' menu. This requires a dedicated in-process LSP server +-- -- that will provide them. To have that, uncomment next line (use `gcc`). +-- -- MiniSnippets.start_lsp_server() +-- end) + +-- Surround actions: add/delete/replace/find/highlight. Working with surroundings +-- is surprisingly common: surround word with quotes, replace `)` with `]`, etc. +-- This module comes with many built-in surroundings, each identified by a single +-- character. It searches only for surrounding that covers cursor and comes with +-- a special "next" / "last" versions of actions to search forward or backward +-- (just like 'mini.ai'). All text editing actions are dot-repeatable (see `:h .`). +-- +-- Example usage (this may feel intimidating at first, but after practice it +-- becomes second nature during text editing): +-- - `saiw)` - *s*urround *a*dd for *i*nside *w*ord parenthesis (`)`) +-- - `sdf` - *s*urround *d*elete *f*unction call (like `f(var)` -> `var`) +-- - `srb[` - *s*urround *r*eplace *b*racket (any of [], (), {}) with padded `[` +-- - `sf*` - *s*urround *f*ind right part of `*` pair (like bold in markdown) +-- - `shf` - *s*urround *h*ighlight current *f*unction call +-- - `srn{{` - *s*urround *r*eplace *n*ext curly bracket `{` with padded `{` +-- - `sdl'` - *s*urround *d*elete *l*ast quote pair (`'`) +-- - `vaWsa` - *v*isually select *a*round *W*ORD and *s*urround *a*dd +-- spaces (``) +-- +-- See also: +-- - `:h MiniSurround-builtin-surroundings` - list of all supported surroundings +-- - `:h MiniSurround-surrounding-specification` - examples of custom surroundings +-- - `:h MiniSurround-vim-surround-config` - alternative set of action mappings +later(function() require('mini.surround').setup() end) + +-- Highlight and remove trailspace. Temporarily stops highlighting in Insert mode +-- to reduce noise when typing. Example usage: +-- - `ot` - trim all trailing whitespace in a buffer +later(function() require('mini.trailspace').setup() end) + diff --git a/plugin/40_plugins.lua b/plugin/40_plugins.lua new file mode 100644 index 0000000..bc35234 --- /dev/null +++ b/plugin/40_plugins.lua @@ -0,0 +1,133 @@ +-- ┌─────────────────────────┐ +-- │ Plugins outside of MINI │ +-- └─────────────────────────┘ +-- +-- This file contains installation and configuration of plugins outside of MINI. +-- They significantly improve user experience in a way not yet possible with MINI. +-- These are mostly plugins that provide programming language specific behavior. +-- +-- Use this file to install and configure other such plugins. + +-- Make concise helpers for installing/adding plugins in two stages +local add, later = MiniDeps.add, MiniDeps.later +local now_if_args = _G.Config.now_if_args + +-- Tree-sitter ================================================================ + +-- Tree-sitter is a tool for fast incremental parsing. It converts text into +-- a hierarchical structure (called tree) that can be used to implement advanced +-- and/or more precise actions: syntax highlighting, textobjects, indent, etc. +-- +now_if_args(function() + add({ + source = 'nvim-treesitter/nvim-treesitter', + -- Update tree-sitter parser after plugin is updated + hooks = { post_checkout = function() vim.cmd('TSUpdate') end }, + }) + add({ + source = 'nvim-treesitter/nvim-treesitter-textobjects', + -- Use `main` branch since `master` branch is frozen, yet still default + -- It is needed for compatibility with 'nvim-treesitter' `main` branch + checkout = 'main', + }) + + -- Define languages which will have parsers installed and auto enabled + local languages = { + -- These are already pre-installed with Neovim. Used as an example. + 'lua', + 'vimdoc', + 'markdown', + -- Add here more languages with which you want to use tree-sitter + -- To see available languages: + -- - Execute `:=require('nvim-treesitter').get_available()` + -- - Visit 'SUPPORTED_LANGUAGES.md' file at + -- https://github.com/nvim-treesitter/nvim-treesitter/blob/main + } + local isnt_installed = function(lang) + return #vim.api.nvim_get_runtime_file('parser/' .. lang .. '.*', false) == 0 + end + local to_install = vim.tbl_filter(isnt_installed, languages) + if #to_install > 0 then require('nvim-treesitter').install(to_install) end + + -- Enable tree-sitter after opening a file for a target language + local filetypes = {} + for _, lang in ipairs(languages) do + for _, ft in ipairs(vim.treesitter.language.get_filetypes(lang)) do + table.insert(filetypes, ft) + end + end + local ts_start = function(ev) vim.treesitter.start(ev.buf) end + _G.Config.new_autocmd('FileType', filetypes, ts_start, 'Start tree-sitter') +end) + +-- Language servers =========================================================== + +-- Language Server Protocol (LSP) is a set of conventions that power creation of +-- language specific tools. It requires two parts: +-- - Server - program that performs language specific computations. +-- - Client - program that asks server for computations and shows results. +-- +-- Add it now if file (and not 'mini.starter') is shown after startup. +now_if_args(function() + add('neovim/nvim-lspconfig') + + -- Use `:h vim.lsp.enable()` to automatically enable language server based on + -- the rules provided by 'nvim-lspconfig'. + -- Use `:h vim.lsp.config()` or 'after/lsp/' directory to configure servers. + -- Uncomment and tweak the following `vim.lsp.enable()` call to enable servers. + vim.lsp.enable({ + -- -- For example, if `lua-language-server` is installed, use `'lua_ls'` entry + 'lua_ls', + }) +end) + +-- Formatting ================================================================= + +-- Programs dedicated to text formatting (a.k.a. formatters) are very useful. +-- Neovim has built-in tools for text formatting (see `:h gq` and `:h 'formatprg'`). +-- They can be used to configure external programs, but it might become tedious. +-- +-- The 'stevearc/conform.nvim' plugin is a good and maintained solution for easier +-- formatting setup. +later(function() + add('stevearc/conform.nvim') + + -- See also: + -- - `:h Conform` + -- - `:h conform-options` + -- - `:h conform-formatters` + require('conform').setup({ + -- Map of filetype to formatters + -- Make sure that necessary CLI tool is available + formatters_by_ft = { lua = { 'stylua' } }, + }) +end) + +-- Mason ====================================================================== +now_if_args(function() + add('mason-org/mason.nvim') + require('mason').setup() +end) + +-- Catppuccin ================================================================= +MiniDeps.now(function() + add({ source = 'catpuccin/nvim', name = 'catppuccin' }) + require('catppuccin').setup({ + flavour = 'mocha', + dim_inactive = { + enabled = true + } + }) + vim.cmd('colorscheme catppuccin') +end) + +-- Neogit ===================================================================== +later(function () + add({ + source = 'NeogitOrg/neogit', + depends = { 'nvim-lua/plenary.nvim' } + }) + local neogit = require('neogit') + neogit.setup() + vim.keymap.set("n", "gg", neogit.open, { desc = "Open Neogit UI" }) +end)