diff --git a/.chezmoiexternal.toml.tmpl b/.chezmoiexternal.toml.tmpl new file mode 100644 index 0000000..4e7c9db --- /dev/null +++ b/.chezmoiexternal.toml.tmpl @@ -0,0 +1,14 @@ +# chezmoi:template:left-delimiter=#{{ +#{{- /* vim: set filetype=toml: */ -}} +[".local/share/nvim/lazy/lazy.nvim"] + type = "archive" + url = "https://github.com/folke/lazy.nvim/archive/refs/tags/v10.15.1.tar.gz" + exact = true + stripComponents = 1 + +#{{ if eq .chezmoi.os "linux" }} +[".local/bin/nvim.appimage"] + type = "file" + url = "https://github.com/neovim/neovim/releases/download/v0.9.4/nvim.appimage" + executable = true +#{{ end }} diff --git a/dot_config/nvim/init.lua b/dot_config/nvim/init.lua new file mode 100644 index 0000000..6f637a6 --- /dev/null +++ b/dot_config/nvim/init.lua @@ -0,0 +1,5 @@ +require 'core.config' +require 'core.commands' +require 'core.keymaps' +vim.opt.runtimepath:prepend(vim.fn.stdpath('data') .. '/lazy/lazy.nvim') +require 'lazy' .setup('plugins', {}) diff --git a/dot_config/nvim/lua/core/commands.lua b/dot_config/nvim/lua/core/commands.lua new file mode 100644 index 0000000..7a40c6f --- /dev/null +++ b/dot_config/nvim/lua/core/commands.lua @@ -0,0 +1,2 @@ +vim.api.nvim_create_user_command('W', 'write', {}) +vim.api.nvim_create_user_command('Q', 'qall!', {}) diff --git a/dot_config/nvim/lua/core/config.lua b/dot_config/nvim/lua/core/config.lua new file mode 100644 index 0000000..f77c55b --- /dev/null +++ b/dot_config/nvim/lua/core/config.lua @@ -0,0 +1,38 @@ +vim.g.mapleader = ',' +vim.g.maplocalleader = ',' + +vim.opt.fileformats = { 'unix', 'dos', 'mac' } + +vim.opt.autochdir = true + +-- Tabs +vim.opt.shiftwidth = 4 +vim.opt.softtabstop = 4 +vim.opt.tabstop = 4 + +-- UI +vim.opt.matchtime = 2 +vim.opt.number = true +vim.opt.numberwidth = 4 +vim.opt.relativenumber = true +vim.opt.showmatch = true +vim.opt.spelllang = 'en_us' +vim.opt.wildmode = 'list:longest' + +-- Indent +vim.opt.copyindent = true +vim.opt.preserveindent = true +vim.opt.smartindent = true +vim.opt.shiftround = true + +-- Text Formatting/Layout +vim.opt.ignorecase = true +vim.opt.list = true +vim.opt.smartcase = true +vim.opt.wrap = false +vim.opt.whichwrap:append { + ['<'] = true, + ['>'] = true, + ['['] = true, + [']'] = true, +} diff --git a/dot_config/nvim/lua/core/keymaps.lua b/dot_config/nvim/lua/core/keymaps.lua new file mode 100644 index 0000000..911ac63 --- /dev/null +++ b/dot_config/nvim/lua/core/keymaps.lua @@ -0,0 +1,6 @@ +vim.keymap.set('n', 'l', ':nohlsearch') +vim.keymap.set('n', 'ts', [[:%s/\s\s*$//g]]) +vim.keymap.set('n', 'ss', ':setlocal spell!') +vim.keymap.set('n', 'p', ':set paste!') +vim.keymap.set('n', 'nn', ':set nonumber norelativenumber') +vim.keymap.set('n', 'rn', ':set number relativenumber') diff --git a/dot_config/nvim/lua/plugins/autocompletion.lua b/dot_config/nvim/lua/plugins/autocompletion.lua new file mode 100644 index 0000000..eaf283a --- /dev/null +++ b/dot_config/nvim/lua/plugins/autocompletion.lua @@ -0,0 +1,61 @@ +local function config() + local cmp = require 'cmp' + local luasnip = require 'luasnip' + + local function expand(args) + luasnip.lsp_expand(args.body) + end + + local function tab_mapping(fallback) + if cmp.visible() then + cmp.select_next_item() + elseif luasnip.expand_or_locally_jumpable() then + luasnip.expand_or_jump() + else + fallback() + end + end + + local function back_tab_mapping(fallback) + if cmp.visible() then + cmp.select_prev_item() + elseif luasnip.locally_jumpable(-1) then + luasnip.jump(-1) + else + fallback() + end + end + + cmp.setup { + enabled = true, + + snippet = { expand = expand }, + sources = { + { name = 'nvim_lsp' }, + { name = 'luasnip' }, + }, + + mapping = cmp.mapping.preset.insert { + [''] = cmp.mapping.select_next_item(), + [''] = cmp.mapping.select_prev_item(), + [''] = cmp.mapping.scroll_docs(-4), + [''] = cmp.mapping.scroll_docs(4), + [''] = cmp.mapping.complete({}), + [''] = cmp.mapping(tab_mapping, { 'i', 's' }), + [''] = cmp.mapping(back_tab_mapping, { 'i', 's' }), + [''] = cmp.mapping.confirm { + behavior = cmp.ConfirmBehavior.Replace, + select = true, + }, + }, + } +end + +return { + 'hrsh7th/nvim-cmp', + config = config, + dependencies = { + 'saadparwaiz1/cmp_luasnip', + 'hrsh7th/cmp-nvim-lsp', + }, +} diff --git a/dot_config/nvim/lua/plugins/base.lua b/dot_config/nvim/lua/plugins/base.lua new file mode 100644 index 0000000..be12771 --- /dev/null +++ b/dot_config/nvim/lua/plugins/base.lua @@ -0,0 +1,22 @@ +local config = function() + local wk = require 'which-key' + wk.setup() + wk.register { + ['c'] = { name = '[C]ode', _ = 'which_key_ignore' }, + ['d'] = { name = '[D]ocument', _ = 'which_key_ignore' }, + ['g'] = { name = '[G]it', _ = 'which_key_ignore' }, + ['h'] = { name = 'More git', _ = 'which_key_ignore' }, + ['r'] = { name = '[R]ename', _ = 'which_key_ignore' }, + ['s'] = { name = '[S]earch', _ = 'which_key_ignore' }, + ['w'] = { name = '[W]orkspace', _ = 'which_key_ignore' }, + } +end + +return { + 'folke/which-key.nvim', + config = config, + dependencies = { + { 'tpope/vim-sleuth', tag = 'v2.0' }, + { 'tpope/vim-surround', tag = 'v2.2' }, + }, +} diff --git a/dot_config/nvim/lua/plugins/lsp.lua b/dot_config/nvim/lua/plugins/lsp.lua new file mode 100644 index 0000000..5be18a9 --- /dev/null +++ b/dot_config/nvim/lua/plugins/lsp.lua @@ -0,0 +1,93 @@ +local function on_attach(_, bufnr) + local nmap = function(keys, func, desc) + if desc then + desc = 'LSP: ' .. desc + end + vim.keymap.set('n', keys, func, { buffer = bufnr, desc = desc }) + end + + nmap('rn', vim.lsp.buf.rename, '[R]e[n]ame') + nmap('ca', vim.lsp.buf.code_action, '[C]ode [A]ction') + + nmap('gd', require('telescope.builtin').lsp_definitions, '[G]oto [D]efinition') + nmap('gr', require('telescope.builtin').lsp_references, '[G]oto [R]eferences') + nmap('gI', require('telescope.builtin').lsp_implementations, '[G]oto [I]mplementation') + nmap('D', require('telescope.builtin').lsp_type_definitions, 'Type [D]efinition') + nmap('ds', require('telescope.builtin').lsp_document_symbols, '[D]ocument [S]ymbols') + nmap('ws', require('telescope.builtin').lsp_dynamic_workspace_symbols, '[W]orkspace [S]ymbols') + + -- See `:help K` for why this keymap + nmap('K', vim.lsp.buf.hover, 'Hover Documentation') + nmap('', vim.lsp.buf.signature_help, 'Signature Documentation') + + -- Lesser used LSP functionality + nmap('gD', vim.lsp.buf.declaration, '[G]oto [D]eclaration') + nmap('wa', vim.lsp.buf.add_workspace_folder, '[W]orkspace [A]dd Folder') + nmap('wr', vim.lsp.buf.remove_workspace_folder, '[W]orkspace [R]emove Folder') + nmap('wl', function() + print(vim.inspect(vim.lsp.buf.list_workspace_folders())) + end, '[W]orkspace [L]ist Folders') + + -- Create a command `:Format` local to the LSP buffer + vim.api.nvim_buf_create_user_command(bufnr, 'Format', function(_) + vim.lsp.buf.format() + end, { desc = 'Format current buffer with LSP' }) +end + +local function config() + local mason = require 'mason' + local mason_lspconfig = require 'mason-lspconfig' + local neodev = require 'neodev' + + mason.setup() + neodev.setup() + + local servers = { + -- clangd = {}, + -- pyright = {}, + -- rust_analyzer = {}, + -- tsserver = {}, + -- html = { filetypes = { 'html', 'twig', 'hbs'} }, + gopls = {}, + lua_ls = { + Lua = { + workspace = { checkThirdParty = false }, + telemetry = { enable = false }, + }, + }, + } + + local capabilities = vim.lsp.protocol.make_client_capabilities() + capabilities = require('cmp_nvim_lsp').default_capabilities(capabilities) + + mason_lspconfig.setup { + ensure_installed = vim.tbl_keys(servers), + } + + mason_lspconfig.setup_handlers { + function(server_name) + require('lspconfig')[server_name].setup { + capabilities = capabilities, + on_attach = on_attach, + settings = servers[server_name], + filetypes = (servers[server_name] or {}).filetypes, + } + end, + } +end + +return { + -- LSP Configuration & Plugins + 'neovim/nvim-lspconfig', + config = config, + dependencies = { + -- Automatically install LSPs to stdpath for neovim + 'williamboman/mason.nvim', + 'williamboman/mason-lspconfig.nvim', + -- Useful status updates for LSP + { 'j-hui/fidget.nvim', tag = 'legacy', opts = {} }, + -- Additional lua configuration, makes nvim stuff amazing! + 'folke/neodev.nvim', + 'folke/trouble.nvim', + }, +} diff --git a/dot_config/nvim/lua/plugins/snippets.lua b/dot_config/nvim/lua/plugins/snippets.lua new file mode 100644 index 0000000..a708593 --- /dev/null +++ b/dot_config/nvim/lua/plugins/snippets.lua @@ -0,0 +1,12 @@ +local function config() + local luasnip = require 'luasnip' + luasnip.setup() + luasnip.config.setup({}) +end + +return { + 'L3MON4D3/LuaSnip', + config = config, + tag = 'v2.*', + dependencies = {}, +} diff --git a/dot_config/nvim/lua/plugins/telescope.lua b/dot_config/nvim/lua/plugins/telescope.lua new file mode 100644 index 0000000..56d707c --- /dev/null +++ b/dot_config/nvim/lua/plugins/telescope.lua @@ -0,0 +1,97 @@ +-- Telescope live_grep in git root +-- Function to find the git root directory based on the current buffer's path +local function find_git_root() + -- Use the current buffer's path as the starting point for the git search + local current_file = vim.api.nvim_buf_get_name(0) + local current_dir + local cwd = vim.fn.getcwd() + -- If the buffer is not associated with a file, return nil + if current_file == '' then + current_dir = cwd + else + -- Extract the directory from the current file's path + current_dir = vim.fn.fnamemodify(current_file, ':h') + end + + -- Find the Git root directory from the current file's path + local git_root = vim.fn.systemlist('git -C ' .. vim.fn.escape(current_dir, ' ') .. ' rev-parse --show-toplevel')[1] + if vim.v.shell_error ~= 0 then + print('Not a git repository. Searching on current working directory') + return cwd + end + return git_root +end + +-- Custom live_grep function to search in git root +local function live_grep_git_root() + local git_root = find_git_root() + if git_root then + require('telescope.builtin').live_grep({ + search_dirs = { git_root }, + }) + end +end + +vim.api.nvim_create_user_command('LiveGrepGitRoot', live_grep_git_root, {}) + +local telescope_setup = { + defaults = { + mappings = { + i = { + [''] = false, + [''] = false, + }, + }, + }, +} + +local function config() + -- See `:help telescope` and `:help telescope.setup()` + local telescope = require('telescope') + local builtin = require('telescope.builtin') + local themes = require('telescope.themes') + + telescope.setup(telescope_setup) + + -- Enable telescope fzf native, if installed + pcall(telescope.load_extension, 'fzf') + + local fuzzy_find = function() + -- You can pass additional configuration to telescope to change theme, layout, etc. + builtin.current_buffer_fuzzy_find(themes.get_dropdown({ + winblend = 10, + previewer = false, + })) + end + + -- See `:help telescope.builtin` + vim.keymap.set('n', '?', builtin.oldfiles, { desc = '[?] Find recently opened files' }) + vim.keymap.set('n', '', builtin.buffers, { desc = '[ ] Find existing buffers' }) + vim.keymap.set('n', '/', fuzzy_find, { desc = '[/] Fuzzily search in current buffer' }) + vim.keymap.set('n', 'gf', builtin.git_files, { desc = 'Search [G]it [F]iles' }) + vim.keymap.set('n', 'sf', builtin.find_files, { desc = '[S]earch [F]iles' }) + vim.keymap.set('n', 'sh', builtin.help_tags, { desc = '[S]earch [H]elp' }) + vim.keymap.set('n', 'sw', builtin.grep_string, { desc = '[S]earch current [W]ord' }) + vim.keymap.set('n', 'sg', builtin.live_grep, { desc = '[S]earch by [G]rep' }) + vim.keymap.set('n', 'sG', live_grep_git_root, { desc = '[S]earch by [G]rep on Git Root' }) + vim.keymap.set('n', 'sd', builtin.diagnostics, { desc = '[S]earch [D]iagnostics' }) + vim.keymap.set('n', 'sr', builtin.resume, { desc = '[S]earch [R]esume' }) +end + +local is_make_installed = function() + return vim.fn.executable('make') == 1 +end + +return { + 'nvim-telescope/telescope.nvim', + branch = '0.1.x', + config = config, + dependencies = { + 'nvim-lua/plenary.nvim', + { + 'nvim-telescope/telescope-fzf-native.nvim', + cond = is_make_installed, + build = 'make', + }, + }, +} diff --git a/dot_config/nvim/lua/plugins/theme.lua b/dot_config/nvim/lua/plugins/theme.lua new file mode 100644 index 0000000..5e4282f --- /dev/null +++ b/dot_config/nvim/lua/plugins/theme.lua @@ -0,0 +1,17 @@ +local function config() + vim.cmd.colorscheme 'gruvbox' +end + +return { + 'morhetz/gruvbox', + priority = 1000, + config = config, + dependencies = { + 'nvim-lualine/lualine.nvim', + opts = { + options = { + theme = 'gruvbox', + }, + }, + }, +} diff --git a/dot_config/nvim/lua/plugins/tree.lua b/dot_config/nvim/lua/plugins/tree.lua new file mode 100644 index 0000000..fff5f15 --- /dev/null +++ b/dot_config/nvim/lua/plugins/tree.lua @@ -0,0 +1,60 @@ +vim.g.loaded_netrw = 1 +vim.g.loaded_netrwPlugin = 1 +vim.opt.termguicolors = true + +local function handle_closed(window) + local tab = vim.api.nvim_win_get_tabpage(window) + local buffer = vim.api.nvim_win_get_buf(window) + local info = vim.fn.getbufinfo(buffer)[1] + + local filter_window = function(w) + return w ~= window + end + + local windows = vim.tbl_filter(filter_window, vim.api.nvim_tabpage_list_wins(tab)) + local buffers = vim.tbl_map(vim.api.nvim_win_get_buf, windows) + + if info.name:match('.*NvimTree_%d*$') then + if not vim.tbl_isempty(buffers) then + require('nvim-tree.api').tree.close() + end + return + end + + if #buffers ~= 1 then + return + end + + local last_info = vim.fn.getbufinfo(buffers[1])[1] + if last_info.name:match('.*NvimTree_%d*$') then + vim.schedule(function() + if #vim.api.nvim_list_wins() == 1 then + vim.cmd 'quit' + else + vim.api.nvim_win_close(windows[1], true) + end + end) + end +end + +local config = function() + require('nvim-tree').setup() + vim.api.nvim_create_autocmd('WinClosed', { + nested = true, + callback = function() + local window = tonumber(vim.fn.expand('')) + vim.schedule_wrap(handle_closed(window)) + end, + }) +end + +return { + 'nvim-tree/nvim-tree.lua', + config = config, + keys = { + { 'nt', ':NvimTreeToggle', desc = 'toggle nvim tree' } + }, + dependencies = { + 'nvim-tree/nvim-web-devicons', opts = {} + }, +} diff --git a/dot_config/nvim/lua/plugins/treesitter.lua b/dot_config/nvim/lua/plugins/treesitter.lua new file mode 100644 index 0000000..f9092a0 --- /dev/null +++ b/dot_config/nvim/lua/plugins/treesitter.lua @@ -0,0 +1,93 @@ +local treesitter_config_setup = { + -- Add languages to be installed here that you want installed for treesitter + ensure_installed = { + 'bash', 'c', 'cpp', 'go', 'lua', 'python', 'rust', + 'tsx', 'javascript', 'typescript', 'vimdoc', 'vim', + }, + + auto_install = true, + sync_install = false, + + modules = {}, + ignore_install = {}, + + highlight = { enable = true }, + indent = { enable = true }, + + incremental_selection = { + enable = true, + keymaps = { + init_selection = '', + node_incremental = '', + scope_incremental = '', + node_decremental = '', + }, + }, + + textobjects = { + select = { + enable = true, + -- Automatically jump forward to textobj, similar to targets.vim + lookahead = true, + keymaps = { + -- You can use the capture groups defined in textobjects.scm + ['aa'] = '@parameter.outer', + ['ia'] = '@parameter.inner', + ['af'] = '@function.outer', + ['if'] = '@function.inner', + ['ac'] = '@class.outer', + ['ic'] = '@class.inner', + }, + }, + + swap = { + enable = true, + swap_next = { + ['a'] = '@parameter.inner', + }, + swap_previous = { + ['A'] = '@parameter.inner', + }, + }, + + move = { + enable = true, + -- whether to set jumps in the jumplist + set_jumps = true, + goto_next_start = { + [']m'] = '@function.outer', + [']]'] = '@class.outer', + }, + goto_next_end = { + [']M'] = '@function.outer', + [']['] = '@class.outer', + }, + goto_previous_start = { + ['[m'] = '@function.outer', + ['[['] = '@class.outer', + }, + goto_previous_end = { + ['[M'] = '@function.outer', + ['[]'] = '@class.outer', + }, + }, + }, +} + +local function treesitter_configs() + require('nvim-treesitter.configs').setup(treesitter_config_setup) +end + +local function config() + vim.defer_fn(treesitter_configs, 0) +end + +return { + -- Highlight, edit, and navigate code + 'nvim-treesitter/nvim-treesitter', + config = config, + build = ':TSUpdate', + dependencies = { + 'nvim-treesitter/nvim-treesitter-textobjects', + }, +} diff --git a/dot_config/profile/env.d/base.env.tmpl b/dot_config/profile/env.d/base.env.tmpl index 5cc1173..8142db5 100644 --- a/dot_config/profile/env.d/base.env.tmpl +++ b/dot_config/profile/env.d/base.env.tmpl @@ -38,8 +38,3 @@ NPM_CONFIG_USERCONFIG="${XDG_CONFIG_HOME}/npm/npmrc" #{{ if lookPath "rg" -}}# RIPGREP_CONFIG_PATH="${XDG_CONFIG_HOME}/ripgrep/config" #{{ end -}}# - -#{{ if or (lookPath "vim") (lookPath "nvim") -}}# -VIMINIT='source $XDG_CONFIG_HOME/vim/vimrc' -MYVIMRC='$XDG_CONFIG_HOME/vim/vimrc' -#{{- end }}# diff --git a/dot_config/vim/config.vim b/dot_config/vim/config.vim index 667ddb1..454eaa4 100644 --- a/dot_config/vim/config.vim +++ b/dot_config/vim/config.vim @@ -39,7 +39,6 @@ set colorcolumn=81 " Have tab complete work more like bash set wildmode=list:longest set whichwrap+=<,>,[,] -set magic " Turn on omni completion. Must have `filetype plugin on` to use. " To use, in insert mode press ctrl+x ctrl+o @@ -60,7 +59,8 @@ set list " UI set showcmd -set number relativenumber +set number +set relativenumber set numberwidth=4 set hidden diff --git a/dot_config/vim/settings.vim.tmpl b/dot_config/vim/settings.vim.tmpl index aa2b506..a14553e 100644 --- a/dot_config/vim/settings.vim.tmpl +++ b/dot_config/vim/settings.vim.tmpl @@ -3,7 +3,7 @@ """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" " fzf "{{ if lookPath "fzf" }} -Plug 'junegunn/fzf', { 'tag': '0.40.0' } +Plug 'junegunn/fzf', { 'tag': '0.43.0' } Plug 'junegunn/fzf.vim' map fz :GFiles diff --git a/dot_config/vim/xdg.vim b/dot_config/vim/xdg.vim index 1c5978e..1629874 100644 --- a/dot_config/vim/xdg.vim +++ b/dot_config/vim/xdg.vim @@ -1,6 +1,3 @@ -" use XDG -if empty($MYVIMRC) | let $MYVIMRC = expand('%:p') | endif - if empty($XDG_CACHE_HOME) | let $XDG_CACHE_HOME = $HOME.'/.cache' | endif if empty($XDG_CONFIG_HOME) | let $XDG_CONFIG_HOME = $HOME.'/.config' | endif if empty($XDG_DATA_HOME) | let $XDG_DATA_HOME = $HOME.'/.local/share' | endif diff --git a/dot_config/vim/vimrc b/dot_vimrc similarity index 100% rename from dot_config/vim/vimrc rename to dot_vimrc