-- {{{ plugins local gh = 'https://github.com/' local plugins = { { src = 'https://git.sprouting.cloud/sprouting.cloud/sproutingcolour', name = 'sproutingcolour' }, -- colorscheme { src = gh .. 'MunifTanjim/nui.nvim', name = 'nui' }, { src = gh .. 'catgoose/nvim-colorizer.lua', name = 'colorizer' }, -- show colours of colour codes { src = gh .. 'echasnovski/mini.nvim', name = 'mini' }, -- a bunch of useful plugins { src = gh .. 'folke/noice.nvim', name = 'noice' }, { src = gh .. 'folke/snacks.nvim', name = 'snacks' }, { src = gh .. 'kdheepak/lazygit.nvim', name = 'lazygit' }, { src = gh .. 'neovim/nvim-lspconfig', name = 'lspconfig' }, -- LSP support { src = gh .. 'nvim-lua/plenary.nvim', name = 'plenary' }, { src = gh .. 'ray-x/go.nvim', name = 'go' }, -- Go specific language support { src = gh .. 'ray-x/guihua.lua', name = 'guihua' }, -- required for go.nvim { src = gh .. 'stevearc/conform.nvim', name = 'conform' }, { src = gh .. 'folke/which-key.nvim', name = 'whichkey' }, { src = gh .. 'mikavilpas/yazi.nvim', name = 'yazi' }, { src = gh .. 'nvimdev/dashboard-nvim', name = 'dashboard' }, { src = gh .. 'nvim-treesitter/nvim-treesitter', name = 'treesitter' }, { src = gh .. 'coder/claudecode.nvim', name = 'claudecode' }, { src = gh .. 'Dan7h3x/neaterm.nvim', name = 'neaterm' }, } vim.pack.add(plugins) local function update_plugins() local plist = {} for _, v in ipairs(plugins) do table.insert(plist, v.name) end vim.pack.update(plist) end -- }}} -- {{{ Global settings vim.g.mapleader = ' ' vim.g.maplocalleader = ' ' vim.g.have_nerd_font = true -- Common defaults vim.opt.clipboard = 'unnamedplus' vim.opt.cursorline = true vim.opt.expandtab = true vim.opt.hlsearch = true vim.opt.inccommand = 'split' vim.opt.modeline = true vim.opt.mouse = 'a' vim.opt.number = true vim.opt.preserveindent = true vim.opt.relativenumber = true vim.opt.ruler = true vim.opt.scrolloff = 5 vim.opt.shiftwidth = 2 vim.opt.showmode = true vim.opt.showtabline = 1 vim.opt.softtabstop = 2 vim.opt.tabstop = 2 vim.opt.termguicolors = true vim.opt.listchars = { tab = '» ', trail = '·', nbsp = '␣' } vim.opt.inccommand = 'split' -- Set foldmethod, change in .editorconfig of projects vim.opt.foldmethod = 'marker' -- General gui settings vim.o.guifont = 'JetBrainsMono Nerd Font:12' -- Neovide settings if vim.g.neovide then vim.env.PATH = '/usr/local/bin:' .. vim.env.PATH vim.env.PATH = '/usr/local/go/bin:' .. vim.env.PATH vim.env.PATH = '/opt/homebrew/bin:' .. vim.env.PATH vim.env.PATH = vim.env.HOME .. '/.local/bin:' .. vim.env.PATH vim.env.PATH = vim.env.HOME .. '/.cargo/bin:' .. vim.env.PATH vim.env.PATH = vim.env.HOME .. '/.local/cargo/bin:' .. vim.env.PATH vim.env.PATH = vim.env.HOME .. '/go/bin:' .. vim.env.PATH vim.env.PATH = vim.env.HOME .. '/.local/npm/bin:' .. vim.env.PATH end vim.cmd.colorscheme 'sprouting-dark' -- }}} -- {{{ Helper functions function R(name) require("plenary.reload").reload_module(name) end -- }}} require('snacks').setup({ -- {{{ animate = {}, dim = {}, image = {}, indent = {}, lazygit = {}, picker = {}, }) -- }}} require('colorizer').setup({}) require('conform').setup({ -- {{{ formatters_by_ft = { ansible = { 'ansible-lint' }, buf = { 'buf' }, cmake = { 'cmake_format' }, go = { 'goimports' }, markdown = { 'cbfmt', 'mdformat' }, sql = { 'sqlfluff' }, terraform = { 'terraform_fmt' }, templ = { 'go tool templ fmt' }, }, }) vim.g.snacks_animate = true -- }}} -- {{{ ferminal scratch pad terminal local ferminal = {} local state = { floating = { buf = -1, win = -1, }, } local function create_floating_window(opts) opts = opts or {} local width = opts.width or math.floor(vim.o.columns * 0.8) local height = opts.height or math.floor(vim.o.lines * 0.8) -- Calculate the position to center the window local col = math.floor((vim.o.columns - width) / 2) local row = math.floor((vim.o.lines - height) / 2) -- Create a buffer local buf = nil if vim.api.nvim_buf_is_valid(opts.buf) then buf = opts.buf else buf = vim.api.nvim_create_buf(false, true) -- No file, scratch buffer end -- Define window configuration local win_config = { relative = 'editor', width = width, height = height, col = col, row = row, style = 'minimal', -- No borders or extra UI elements border = 'rounded', } -- Create the floating window local win = vim.api.nvim_open_win(buf, true, win_config) return { buf = buf, win = win } end ferminal.toggle_terminal = function() if not vim.api.nvim_win_is_valid(state.floating.win) then state.floating = create_floating_window { buf = state.floating.buf } if vim.bo[state.floating.buf].buftype ~= 'terminal' then vim.cmd.terminal() end else vim.api.nvim_win_hide(state.floating.win) end end -- }}} -- {{{ Language configurations require('go').setup() -- }}} require('noice').setup({ -- {{{ lsp = { override = { ['vim.lsp.util.convert_input_to_markdown_lines'] = true, ['vim.lsp.util.stylize_markdown'] = true, }, }, popupmenu = { enabled = true, backend = 'nui', }, notify = { enabled = true, view = 'notify', }, routes = { { view = 'notify', filter = { event = 'msg_showmode' }, }, }, }) -- }}} require('yazi').setup({ -- {{{ open_for_directories = true, keymaps = { show_help = '', }, }) vim.g.loaded_netrwPlugin = 1 -- }}} require('dashboard').setup({ -- {{{ theme = 'hyper', config = { shortcut = { { desc = '󰊳 Update ', group = '@property', key = 'u', action = update_plugins }, { desc = ' Projects ', group = 'label', key = 'p', action = Snacks.picker.projects }, { desc = '󰪶 Files ', group = 'OkMsg', key = 'f', action = Snacks.picker.files }, { desc = '󰿅 Quit ', group = 'ErrorMsg', key = 'q', action = ':q' }, }, packages = { enable = false }, -- show number of installed plugins project = { enable = true, limit = 8, label = '', action = Snacks.picker.projects }, }, }) -- }}} require('which-key').setup({ -- {{{ preset = 'modern', }) -- }}} require('nvim-treesitter').setup({ -- {{{ install_dir = vim.fn.stdpath('data') .. '/site' }) require('nvim-treesitter').install({ 'asm', 'awk', 'bash', 'c', 'c_sharp', 'caddy', 'cmake', 'comment', 'cpp', 'css', 'csv', 'desktop', 'diff', 'dockerfile', 'dtd', 'editorconfig', 'elm', 'fortran', 'gdscript', 'git_config', 'git_rebase', 'gitattributes', 'gitcommit', 'gitignore', 'go', 'gomod', 'gosum', 'gowork', 'gpg', 'hcl', 'helm', 'html', 'http', 'javascript', 'jinja', 'jinja_inline', 'jq', 'json', 'json5', 'kotlin', 'llvm', 'lua', 'luadoc', 'luap', 'make', 'markdown', 'markdown_inline', 'meson', 'muttrc', 'nasm', 'nginx', 'ninja', 'php', 'php_only', 'phpdoc', 'powershell', 'printf', 'properties', 'regex', 'requirements', 'robot', 'robots_txt', 'rst', 'rust', 'scss', 'sql', 'ssh_config', 'templ', 'terraform', 'tmux', 'toml', 'typescript', 'udev', 'vala', 'vim', 'vimdoc', 'vue', 'xml', 'yaml', 'zig', 'zsh', }) -- Enable treesitter vim.api.nvim_create_autocmd('FileType', { callback = function() pcall(vim.treesitter.start) vim.bo.indentexpr = "v:lua.require'nvim-treesitter'.indentexpr()" end, }) -- Done nvim-treesitter }}} require('claudecode').setup({ -- {{{ cwd_provider = function(ctx) local cwd = require('claudecode.cwd').git_root(ctx.file_dir or ctx.cwd) or ctx.file_dir or ctx.cwd return cwd end, }) -- Done claudecode }}} require('neaterm').setup() -- {{{ -- Done neaterm }}} -- Filetype configuration {{{ vim.filetype.add({ extension = { Containerfile = 'dockerfile', Dockerfile = 'dockerfile', containerfile = 'containerfile', dockerfile = 'dockerfile', j2 = 'jinja', jinja = 'jinja', jinja2 = 'jinja', tf = 'terraform', tfstate = 'json', tfvars = 'terraform', templ = 'templ', }, }) -- }}} -- {{{ LSP Configuration local lspproto = vim.lsp.protocol local lspconfig = vim.lsp.config local lspenable = vim.lsp.enable local capabilities = lspproto.make_client_capabilities() -- Formatter autocmd vim.api.nvim_create_autocmd({ 'BufWritePre' }, { callback = function(args) require("conform").format({ bufnr = args.buf }) end, }) -- Simple lspconfigs vim.lsp.config('ansiblels', capabilities) vim.lsp.config('bashls', capabilities) vim.lsp.config('buf_ls', capabilities) vim.lsp.config('clangd', capabilities) vim.lsp.config('gopls', capabilities) vim.lsp.config('intelephense', capabilities) vim.lsp.config('jinja_lsp', capabilities) vim.lsp.config('nginx_language_server', capabilities) vim.lsp.config('pyright', capabilities) vim.lsp.config('sqlls', capabilities) vim.lsp.config('templ', capabilities) vim.lsp.config('terraformls', capabilities) vim.lsp.config('qmlls', capabilities) vim.lsp.config('zls', capabilities) -- LSP with more advanced configuration local caps_snippt_support = function() local caps = lspproto.make_client_capabilities() caps.textDocument.completion.completionItem.snippetSupport = true return caps end vim.lsp.config('cssls', { capabilities = caps_snippt_support() }) vim.lsp.config('html', { capabilities = caps_snippt_support(), filetypes = { 'html', 'templ' } }) vim.lsp.config('htmx', { capabilities = caps_snippt_support(), filetypes = { 'html', 'templ' } }) vim.lsp.config('jsonls', { capabilities = caps_snippt_support() }) vim.lsp.config('dockerls', { settings = { docker = { languageserver = { formatter = { ignoreMultilineInstructions = true }, } } } }) vim.lsp.config('eslint', { on_attach = function(_, bufnr) vim.api.nvim_create_autocmd('BufWritePre', { buffer = bufnr, command = 'EslintFixAll', }) end, }) vim.lsp.config('lua_ls', { on_init = function(client) if client.workspace_folders then local path = client.workspace_folders[1].name if vim.uv.fs_stat(path .. '/.luarc.json') or vim.uv.fs_stat(path .. '/.luarc.jsonc') then return end end client.config.settings.Lua = vim.tbl_deep_extend('force', client.config.settings.Lua, { runtime = { version = 'LuaJIT' }, workspace = { checkThirdParty = false, library = { vim.env.VIMRUNTIME, '${3rd}/luv/library' } }, format = { enable = true, defaultConfig = { indent_style = 'space', indent_size = '2' } }, diagnostics = { globals = { 'vim', 'Snacks', 'MiniSessions', 'MiniPick', 'MiniStatusline' } }, }) end, settings = { Lua = {} } }) vim.lsp.config('templ', { cmd = { 'go', 'tool', 'github.com/a-h/templ/cmd/templ', 'lsp' }, }) vim.lsp.config('tailwindcss', { capabilities = capabilities, filetypes = { 'templ', 'astro', 'javascript', 'typescript', 'react' }, settings = { tailwindCSS = { includeLanguages = { templ = 'html', }, }, }, }) vim.lsp.config('yamlls', { format = { enable = true, bracketSpacing = true }, }) lspenable({ 'ansiblels', 'bashls', 'buf_ls', 'clangd', 'cssls', 'dockerls', 'eslint', 'eslint', 'gopls', 'html', 'htmx', 'intelephense', 'jinja_lsp', 'jsonls', 'lua_ls', 'nginx_language_server', 'pyright', 'qmlls', 'sqlls', 'tailwindcss', 'templ', 'terraformls', 'zls', }) -- end LSPConfig }}} -- {{{ mini.nvim setup require('mini.basics').setup() require('mini.ai').setup({ n_lines = 200 }) require('mini.align').setup() require('mini.completion').setup() require('mini.diff').setup() require('mini.extra').setup() require('mini.git').setup() require('mini.icons').setup() require('mini.move').setup() require('mini.operators').setup() require('mini.pairs').setup() require('mini.snippets').setup() require('mini.splitjoin').setup() require('mini.statusline').setup({ content = { active = function() local check_macro_recording = function() if vim.fn.reg_recording() ~= '' then return '@' .. vim.fn.reg_recording() else return '' end end -- configure statusline for active windows local mode, mode_hl = MiniStatusline.section_mode { trunc_width = 120 } local git = MiniStatusline.section_git { trunc_width = 40 } local diff = MiniStatusline.section_diff { trunc_width = 75 } local diagnostics = MiniStatusline.section_diagnostics { trunc_width = 75 } local lsp = MiniStatusline.section_lsp { trunc_width = 75 } local filename = MiniStatusline.section_filename { trunc_width = 140 } local fileinfo = MiniStatusline.section_fileinfo { trunc_width = 120 } local location = MiniStatusline.section_location { trunc_width = 75 } local search = MiniStatusline.section_searchcount { trunc_width = 75 } local macro = check_macro_recording() return MiniStatusline.combine_groups { { hl = mode_hl, strings = { mode } }, { hl = 'MiniStatuslineDevinfo', strings = { git, diff, diagnostics, lsp } }, '%<', -- Mark general truncate point { hl = 'MiniStatuslineFilename', strings = { filename } }, '%=', -- End left alignment { hl = 'MiniStatuslineFilename', strings = { macro } }, { hl = 'MiniStatuslineFileinfo', strings = { fileinfo } }, { hl = mode_hl, strings = { search, location } }, } end, use_icons = true, set_vim_settings = true, }, }) -- }}} -- {{{ which-key config local wk = require('which-key') local wke = require('which-key.extras') wk.add({ { -- Normal Mode { '', '>>', desc = 'increase tab depth of line' }, { '', '<<', desc = 'decrease tab depth of line' }, -- file group { 'f', group = 'file' }, { 'fb', 'Yazi', desc = '[f]ile [b]rowser' }, { 'fd', 'Yazi cwd', desc = '[f]ile browser for current [d]irectory' }, { 'fp', Snacks.picker.files, desc = '[f]ile [p]icker' }, { 'fg', Snacks.picker.grep, desc = '[f]ile [g]rep picker' }, { 'fz', Snacks.picker.zoxide, desc = '[f]ile [z]oxide picker' }, -- buffer group { 'b', group = 'buffers', expand = function() return wke.expand.buf() end }, { 'be', 'e %', desc = '[b]uffer r[e]load' }, { 'bp', Snacks.picker.buffers, desc = '[b]uffer [p]icker' }, { 'bl', Snacks.picker.lines, desc = '[b]uffer pick [l]ine' }, -- project group { 'pp', Snacks.picker.projects, desc = '[p]ick [p]roject' }, -- help group { 'h', group = 'help' }, { 'hh', Snacks.picker.help, desc = '[h]pick [h]elp' }, { 'hk', Snacks.picker.keymaps, desc = '[h]pick [k]eymaps' }, { 'hi', Snacks.picker.icons, desc = '[h]pick icon' }, -- git group { 'g', group = 'git' }, { 'gi', 'LazyGit', desc = 'lazy[g][i]t open' }, { 'gc', 'LazyGitCurrentFile', desc = 'lazy[g]it [c]urrent file' }, { 'go', 'LazyGitConfig', desc = 'lazy[g]it c[o]nfig' }, { 'gl', 'LazyGitLog', desc = 'Lazy[g]it [l]og' }, -- lsp group { 'l', group = 'LSP' }, { 'lh', vim.lsp.buf.hover, desc = '[l]sp [h]over Documentation' }, { 'ls', vim.lsp.buf.signature_help, desc = '[l]sp [s]ignature help' }, { 'lr', vim.lsp.buf.rename, desc = '[l]sp [r]ename' }, { 'lf', vim.lsp.buf.format, desc = '[l]sp [f]ormat buffer' }, { 'lgD', Snacks.picker.lsp_declarations, desc = '[l]sp [g]oto [D]eclaration' }, { 'lgI', Snacks.picker.lsp_implementations, desc = '[l]sp [g]oto [I]mplementation' }, { 'lgS', Snacks.picker.lsp_workspace_symbols, desc = '[l]sp [g]oto workspace [S]ymbol' }, { 'lgd', Snacks.picker.lsp_definitions, desc = '[l]sp [g]oto [d]efinition' }, { 'lgr', Snacks.picker.lsp_references, desc = '[l]sp [g]oto [r]eferences' }, { 'lgs', Snacks.picker.lsp_symbols, desc = '[l]sp [g]oto document [s]ymbol' }, { 'lde', vim.diagnostic.open_float, desc = '[l]sp [d]iagnostic [e]rror messages' }, { 'ldq', vim.diagnostic.setloclist, desc = '[l]sp [d]iagnostic [q]uickfix list' }, -- claude code { 'a', group = 'Claude' }, { 'ac', "ClaudeCode", desc = "Toggle Claude" }, { 'af', "ClaudeCodeFocus", desc = "Focus Claude" }, { 'ar', "ClaudeCode --resume", desc = "Resume Claude" }, { 'aC', "ClaudeCode --continue", desc = "Continue Claude" }, { 'am', "ClaudeCodeSelectModel", desc = "Select Claude Model" }, { 'ab', "ClaudeCodeAdd %", desc = "Add current buffer" }, { 'as', "ClaudeCodeSend", mode = 'v', desc = "Send to Claude" }, { 'as', "ClaudeCodeTreeAdd", desc = "Add file", ft = { "NvimTree", "neo-tree", "oil", "minifiles", "netrw" }, }, { 'aa', "ClaudeCodeDiffAccept", desc = "Accept diff" }, { 'ad', "ClaudeCodeDiffDeny", desc = "Deny diff" }, -- diagnostics { '[d', function() vim.diagnostic.jump({ count = -1, float = true }) end, desc = 'goto previous [d]iagnostic message' }, { ']d', function() vim.diagnostic.jump({ count = 1, float = true }) end, desc = 'goto next [d]iagnostic message' }, -- misc { '', ':nohl', desc = 'Clear Highlights' }, { 'tt', ferminal.toggle_terminal, desc = '[t]oggle floating [t]erminal' }, { 'rr', ':source %', desc = 'sou[r]ce cu[r]rent file as neovim lua' }, }, { -- Visual Mode mode = 'v', { '', '>>', desc = 'increase tab depth of selection' }, { '', '<<', desc = 'decrease tab depth of selection' }, }, { -- Insert Mode mode = 'i', { '', vim.lsp.buf.signature_help, desc = 'signature help' }, { '', vim.lsp.buf.hover, desc = 'Hover [d]ocumentation' }, { '', '', desc = 'restore tab functionality' }, { '', '', desc = 'restore de-tab functionality' }, }, { -- Terminal Mode mode = 't', { '', '', desc = 'Exit terminal mode' }, -- Window navigation { '', 'h', desc = 'Navigate to left window' }, { '', 'j', desc = 'Navigate to lower window' }, { '', 'k', desc = 'Navigate to upper window' }, { '', 'l', desc = 'Navigate to right window' }, -- Tab navigation { '', 'tabprev', desc = 'Navigate to previous tab' }, { '', 'tabnext', desc = 'Navigate to next tab' }, }, { -- Normal, Insert mode mode = { 'n', 'i' }, -- Window navigation { '', 'h', desc = 'Navigate to left window' }, { '', 'j', desc = 'Navigate to lower window' }, { '', 'k', desc = 'Navigate to upper window' }, { '', 'l', desc = 'Navigate to right window' }, -- Tab navigation { '', 'tabprev', desc = 'Navigate to previous tab' }, { '', 'tabnext', desc = 'Navigate to next tab' }, }, }) -- }}}