diff options
Diffstat (limited to 'common')
53 files changed, 8388 insertions, 0 deletions
diff --git a/common/config/nvim/.gitignore b/common/config/nvim/.gitignore new file mode 100644 index 0000000..f6f2fa2 --- /dev/null +++ b/common/config/nvim/.gitignore @@ -0,0 +1,4 @@ +plugin/packer_compiled.lua +startup.log +tmp +*.log diff --git a/common/config/nvim/README.md b/common/config/nvim/README.md new file mode 100644 index 0000000..2849262 --- /dev/null +++ b/common/config/nvim/README.md @@ -0,0 +1,33 @@ +## Neovim + +#### Dependencies + +nvm +nvm install --lts + +#### TODOS: + +- [ ] Markdown filetype plugin or autocommand to add two spaces each line +- [ ] Markdown filetype plugin or autocommand to make backtick auto-correct properly +- [x] Indent by filetype/fix global indent (2) +- [x] Check history or telescope history of last files edited or opened. +- [ ] - Windows native support configuration +- [ ] - Python debugger +- [ ] README file heirachcy +- [ ] Markdown snippet for code blocks with list, ie.- ``and -` ` +- [ ] Snippet for filler text with variations, ie. common sentences: The quick brown fox... and more and placeholder words +- [ ] Configure snippets.lua +- [ ] Documentation shortcuts for different languages quote in quote "locally" (preffered) or opening web browser +- [ ] Dictionary, an actual dictionary +- [ ] Null-ls/lsp keymap to check current buffer servers must check both same time + > NOTE: Different servers must be configured only to one or another, research null-ls being archived +- [ ] Don't highlight whitespaces in lazygit (maybe exclusively markdown) +- [ ] Configure prettier/prettierd servers to join a lot of different files (null-ls) +- [ ] Nvim-tree preview window similar to telescope +- [x] Nvim-tree behaviour when delete current buffer + > NOTE: One idea is to create an autocmd to make a blank window (hidden) as a secondary window but when creating a opening a new file it does not ask which split to open in +- [ ] Nvim-tree conditionally when open going in the opposite direction will go back to nvim-tree ie. going right then goes to nvim-tree but is conditionally because of tmux etc... +- [x] Substitute keybinding +- [ ] Snippet/filetype plugin for markdown tick boxes +- [ ] Delete lua/user/func.lua +- [ ] Clean entire config by prioritizing single quotation marks over double diff --git a/common/config/nvim/after/ftplugin/markdown.lua b/common/config/nvim/after/ftplugin/markdown.lua new file mode 100644 index 0000000..9a6427f --- /dev/null +++ b/common/config/nvim/after/ftplugin/markdown.lua @@ -0,0 +1,37 @@ +vim.wo.spell = true +vim.bo.spelllang = "en" +vim.wo.wrap = true +vim.wo.linebreak = true +vim.wo.breakindent = true +vim.wo.colorcolumn = "0" +vim.wo.conceallevel = 3 +vim.opt.softtabstop = 2 -- Tab key indents by 2 spaces. +vim.opt.shiftwidth = 2 -- >> indents by 2 spaces. +-- vim.g.markdown_recommended_style = 0 -- prevents markdown from changing tabs to 4 spaces + +vim.b[0].undo_ftplugin = "setlocal nospell nowrap nolinebreak nobreakindent conceallevel=0" + +vim.cmd([[ + autocmd FileType markdown iabbrev <buffer> `` `` +]]) + +require("nvim-surround").buffer_setup({ + surrounds = { + -- ["e"] = { + -- add = function() + -- local env = require("nvim-surround.config").get_input ("Environment: ") + -- return { { "\\begin{" .. env .. "}" }, { "\\end{" .. env .. "}" } } + -- end, + -- }, + ["b"] = { + add = { "**", "**" }, + find = "**.-**", + delete = "^(**)().-(**)()$", + }, + ["i"] = { + add = { "_", "_" }, + find = "_.-_", + delete = "^(_)().-(_)()$", + }, + }, +}) diff --git a/common/config/nvim/autoload/utils.vim b/common/config/nvim/autoload/utils.vim new file mode 100644 index 0000000..23a9178 --- /dev/null +++ b/common/config/nvim/autoload/utils.vim @@ -0,0 +1,237 @@ +" Toggle Zoom +function! utils#ZoomToggle() + if exists('t:zoomed') && t:zoomed + execute t:zoom_winrestcmd + let t:zoomed = 0 + else + let t:zoom_winrestcmd = winrestcmd() + resize + vertical resize + let t:zoomed = 1 + endif +endfunction +"command! ZoomToggle call ZoomToggle() + + +"------------------------------------------------- + +" Toggle DiagnosticsOpenFloat +function! utils#ToggleDiagnosticsOpenFloat() + " Switch the toggle variable + let g:DiagnosticsOpenFloat = !get(g:, 'DiagnosticsOpenFloat', 1) + + " Reset group + augroup OpenFloat + autocmd! + augroup END + + " Enable if toggled on + if g:DiagnosticsOpenFloat + augroup OpenFloat + autocmd! CursorHold * lua vim.diagnostic.open_float(nil, {focusable = false,}) + "autocmd! CursorHold,CursorHoldI * lua vim.diagnostic.open_float(nil, {focusable = false,}) + "autocmd! CursorHold,CursorHoldI * lua vim.diagnostic.open_float(nil, {focusable = false,}) print ("vim.diagnostic.open_float enabled...") + augroup END + endif +endfunction +"command! ToggleDiagonsticsOpenFloat call ToggleDiagnosticsOpenFloat() + + +"------------------------------------------------- + +" Toggle transparency +let t:is_transparent = 0 +function! utils#Toggle_transparent_background() + if t:is_transparent == 0 + hi Normal guibg=#111111 ctermbg=black + let t:is_transparent = 1 + else + hi Normal guibg=NONE ctermbg=NONE + let t:is_transparent = 0 + endif +endfunction +"nnoremap <leader>tb :call Toggle_transparent_background()<CR> + + +"------------------------------------------------- + +" Toggle statusline +let s:hidden_all = 0 +function! utils#ToggleHiddenAll() + if s:hidden_all == 0 + let s:hidden_all = 1 + set noshowmode + set noruler + set laststatus=0 + set noshowcmd + else + let s:hidden_all = 0 + set showmode + set ruler + set laststatus=2 + set showcmd + endif +endfunction +"nnoremap <S-h> :call ToggleHiddenAll()<CR> + + +"------------------------------------------------- + +" Open last closed buffer +function! OpenLastClosed() + let last_buf = bufname('#') + if empty(last_buf) + echo "No recently closed buffer found" + return + endif + let result = input("Open ". last_buf . " in (n)ormal (v)split, (t)ab or (s)plit ? (n/v/t/s) : ") + if empty(result) || (result !=# 'v' && result !=# 't' && result !=# 's' && result !=# 'n') + return + endif + if result ==# 't' + execute 'tabnew' + elseif result ==# 'v' + execute "vsplit" + elseif result ==# 's' + execute "split" + endif + execute 'b ' . last_buf +endfunction + + +"------------------------------------------------- + +" Toggle Diff +let g:diff_is_open = 0 + +function! utils#ToggleDiff() + if g:diff_is_open + windo diffoff + let g:diff_is_open = 0 + else + windo diffthis + let g:diff_is_open = 1 + endif +endfunction + + +"------------------------------------------------- + +" Verbose Toggle +function! utils#VerboseToggle() + if !&verbose + set verbosefile=~/.config/nvim/verbose.log + set verbose=15 + else + set verbose=0 + set verbosefile= + endif +endfunction + + +"------------------------------------------------- + +" Jump List +function! utils#GotoJump() + jumps + let j = input("Please select your jump: ") + if j != '' + let pattern = '\v\c^\+' + if j =~ pattern + let j = substitute(j, pattern, '', 'g') + execute "normal " . j . "\<c-i>" + else + execute "normal " . j . "\<c-o>" + endif + endif +endfunction + + +"------------------------------------------------- + +" Disable annoying auto line break +fu! utils#DisableBr() + set wrap + set linebreak + set nolist " list disables linebreak + set textwidth=0 + set wrapmargin=0 + set formatoptions-=t +endfu + +" Disable line breaks for all file types +autocmd! BufNewFile,BufRead *.* call utils#DisableBr() + + +"------------------------------------------------- + +" Annoying timestamp issue on write (The file has been changed since reading it...) +"function! utils#ProcessFileChangedShell() +" if v:fcs_reason == 'mode' || v:fcs_reason == 'time' +" let v:fcs_choice = '' +" else +" let v:fcs_choice = 'ask' +" endif +"endfunction +"autocmd FileChangedShell <buffer> call utils#ProcessFileChangedShell() +" +"let lastline = line('$') +"let bufcontents = getline(1, lastline) +"edit! +"call setline(1, bufcontents) +"if line('$') > lastline +" execute lastline+1.',$:d _' +"endif + +" Annoying timestamp issue on write (The file has been changed since reading it...) +function! utils#ProcessFileChangedShell() + if v:fcs_reason == 'mode' || v:fcs_reason == 'time' + let v:fcs_choice = '' + else + let v:fcs_choice = 'ask' + endif +endfunction + +" Triggered when the file is changed externally +autocmd FileChangedShell <buffer> call utils#ProcessFileChangedShell() + +" Triggered before writing the buffer to the file +autocmd BufWritePre <buffer> call utils#BeforeWrite() + +function! utils#BeforeWrite() + let lastline = line('$') + let bufcontents = getline(1, lastline) + edit! + call setline(1, bufcontents) + if line('$') > lastline + execute lastline+1.',$:d _' + endif +endfunction + + +"------------------------------------------------- + +" On The Fly Table mode +function! s:isAtStartOfLine(mapping) + let text_before_cursor = getline('.')[0 : col('.')-1] + let mapping_pattern = '\V' . escape(a:mapping, '\') + let comment_pattern = '\V' . escape(substitute(&l:commentstring, '%s.*$', '', ''), '\') + return (text_before_cursor =~? '^' . ('\v(' . comment_pattern . '\v)?') . '\s*\v' . mapping_pattern . '\v$') +endfunction + + +"------------------------------------------------- + +" :Rename {newname} +function! utils#RenameFile() + let old_name = expand('%') + let new_name = input('New file name: ', expand('%'), 'file') + if new_name != '' && new_name != old_name + exec ':saveas ' . new_name + exec ':silent !rm ' . old_name + redraw! + endif +endfunction + + +"------------------------------------------------- diff --git a/common/config/nvim/init.lua b/common/config/nvim/init.lua new file mode 100644 index 0000000..409f7c8 --- /dev/null +++ b/common/config/nvim/init.lua @@ -0,0 +1,149 @@ +--[[ + ███╗ ██╗███████╗ ██████╗ ██╗ ██╗██╗███╗ ███╗ + ████╗ ██║██╔════╝██╔═══██╗██║ ██║██║████╗ ████║ + ██╔██╗ ██║█████╗ ██║ ██║██║ ██║██║██╔████╔██║ + ██║╚██╗██║██╔══╝ ██║ ██║╚██╗ ██╔╝██║██║╚██╔╝██║ + ██║ ╚████║███████╗╚██████╔╝ ╚████╔╝ ██║██║ ╚═╝ ██║ + ╚═╝ ╚═══╝╚══════╝ ╚═════╝ ╚═══╝ ╚═╝╚═╝ ╚═╝ + " ------------------------------------------------ + Author: srdusr + Email: trevorgray@srdusr.com + Url: https://github.com/srdusr/nvim.git + ------------------------------------------------ " +--]] +--[[init.]] +-- ========================================================================== -- +-- == DEPENDENCIES == -- +-- ========================================================================== -- + +-- ripgrep - https://github.com/BurntSushi/ripgrep +-- fd - https://github.com/sharkdp/fd +-- git - https://git-scm.com/ +-- make - https://www.gnu.org/software/make/ +-- c compiler - gcc or tcc or zig + +-- -------------------------------------------------------------------------- -- + +-- ================================== -- +-- == Install neovim-nightly == -- +-- ================================== -- + +-- Download nvim-linux64.tar.gz: +--$ curl -L -o nvim-linux64.tar.gz https://github.com/neovim/neovim/releases/download/nightly/nvim-linux64.tar.gz +-- Extract: +--$ tar xzvf nvim-linux64.tar.gz --install-dir=/bin +-- Run: +--$ ./nvim-linux64/bin/nvim + +-- ---------------------------------- -- + +-- Initialize config with this one liner in the terminal +--$ nvim --headless -c 'call mkdir(stdpath("config"), "p") | exe "edit" stdpath("config") . "/init.lua" | write | quit' + +-- Command to see startup time +--$ nvim --startuptime startup.log -c exit && tail -100 startup.log + +-- Load impatient (Faster loading times) +local impatient_ok, impatient = pcall(require, "impatient") +if impatient_ok then + impatient.enable_profile() +end + +-- Schedule reading shadafile to improve the startup time +vim.opt.shadafile = "NONE" +vim.schedule(function() + vim.opt.shadafile = "" + vim.cmd("silent! rsh") +end) + +-- Load/reload modules +local modules = { + "user.pack", -- Packer plugin manager + "user.opts", -- Options + "user.keys", -- Keymaps + "user.mods", -- Modules/functions + "user.view", -- Colorscheme/UI + "plugins.web-devicons", + "plugins.treesitter", + "plugins.neodev", + "plugins.telescope", + "plugins.nvim-tree", + "plugins.lsp", + "plugins.cmp", + "plugins.quickfix", + --"plugins.snippets", + --"plugins.colorizer", + --"plugins.prettier", + --"plugins.git", + --"plugins.fugitive", + "plugins.gitsigns", + "plugins.sniprun", + "plugins.session", + "plugins.surround", + "plugins.neoscroll", + "plugins.statuscol", + "plugins.trouble", + "plugins.goto-preview", + "plugins.autopairs", + "plugins.navic", + "plugins.toggleterm", + "plugins.zen-mode", + "plugins.fidget", + "plugins.dap", + "plugins.neotest", + "plugins.heirline", + "plugins.dashboard", + "plugins.which-key", + "plugins.harpoon", + "plugins.leetcode", + "plugins.hardtime", + "plugins.notify", + "plugins.overseer", + "plugins.vimtex", + "plugins.indent-blankline", + --"plugins.modify-blend", +} + +-- Refresh module cache +for k, v in pairs(modules) do + package.loaded[v] = nil + require(v) +end + +-- Improve speed by disabling some default plugins/modules +local builtins = { + "gzip", + "zip", + "zipPlugin", + "tar", + "tarPlugin", + "getscript", + "getscriptPlugin", + "vimball", + "vimballPlugin", + "2html_plugin", + --"matchit", + --"matchparen", + "logiPat", + "rrhelper", + "netrw", + "netrwPlugin", + "netrwSettings", + "netrwFileHandlers", + "tutor_mode_plugin", + "fzf", + "spellfile_plugin", + "sleuth", +} + +for _, plugin in ipairs(builtins) do + vim.g["loaded_" .. plugin] = 1 +end +vim.g.do_filetype_lua = 1 +vim.g.did_load_filetypes = 0 + +-- Snippets +--vim.g.snippets = 'luasnip' + +-- Notifications +vim.notify = require("notify") -- Requires plugin "rcarriga/nvim-notify" diff --git a/common/config/nvim/lua/plugins/autopairs.lua b/common/config/nvim/lua/plugins/autopairs.lua new file mode 100644 index 0000000..90b62b1 --- /dev/null +++ b/common/config/nvim/lua/plugins/autopairs.lua @@ -0,0 +1,87 @@ +local status_ok, autopairs = pcall(require, "nvim-autopairs") +if not status_ok then + return +end + +autopairs.setup({ + check_ts = true, + ts_config = { + lua = { "string", "source" }, + javascript = { "string", "template_string" }, + java = false, + }, + map = "<M-e>", + pairs_map = { + ["<"] = ">", + }, + disable_filetype = { "TelescopePrompt", "spectre_panel" }, + disable_in_macro = true, + disable_in_visualblock = true, + enable_moveright = true, + enable_afterquote = true, -- add bracket pairs after quote + enable_check_bracket_line = false, --- check bracket in same line + enable_bracket_in_quote = true, -- + break_undo = true, -- switch for basic rule break undo sequence + --fast_wrap = { + -- chars = { "{", "[", "(", '"', "'" }, + -- pattern = string.gsub([[ [%'%"%)%>%]%)%}%,] ]], "%s+", ""), + -- offset = 0, -- Offset from pattern match + -- end_key = "$", + -- keys = "qwertyuiopzxcvbnmasdfghjkl", + -- check_comma = true, + -- highlight = "PmenuSel", + -- highlight_grey = "LineNr", + --}, +}) +local Rule = require("nvim-autopairs.rule") + +local cond = require("nvim-autopairs.conds") + +autopairs.add_rules({ + Rule("`", "'", "tex"), + Rule("$", "$", "tex"), + Rule(" ", " ") + :with_pair(function(opts) + local pair = opts.line:sub(opts.col, opts.col + 1) + return vim.tbl_contains({ "$$", "()", "{}", "[]", "<>" }, pair) + end) + :with_move(cond.none()) + :with_cr(cond.none()) + :with_del(function(opts) + local col = vim.api.nvim_win_get_cursor(0)[2] + local context = opts.line:sub(col - 1, col + 2) + return vim.tbl_contains({ "$ $", "( )", "{ }", "[ ]", "< >" }, context) + end), + Rule("$ ", " ", "tex"):with_pair(cond.not_after_regex(" ")):with_del(cond.none()), + Rule("[ ", " ", "tex"):with_pair(cond.not_after_regex(" ")):with_del(cond.none()), + Rule("{ ", " ", "tex"):with_pair(cond.not_after_regex(" ")):with_del(cond.none()), + Rule("( ", " ", "tex"):with_pair(cond.not_after_regex(" ")):with_del(cond.none()), + Rule("< ", " ", "tex"):with_pair(cond.not_after_regex(" ")):with_del(cond.none()), +}) + +autopairs.get_rule("$"):with_move(function(opts) + return opts.char == opts.next_char:sub(1, 1) +end) + +-- import nvim-cmp plugin (completions plugin) +local cmp = require("cmp") + +-- import nvim-autopairs completion functionality +local cmp_autopairs = require("nvim-autopairs.completion.cmp") + +-- make autopairs and completion work together +cmp.event:on( + "confirm_done", + cmp_autopairs.on_confirm_done({ + filetypes = { + tex = false, -- Disable for tex + }, + }) +) + +--local cmp_autopairs = require "nvim-autopairs.completion.cmp" +--local cmp_status_ok, cmp = pcall(require, "cmp") +--if not cmp_status_ok then +-- return +--end +--cmp.event:on("confirm_done", cmp_autopairs.on_confirm_done { map_char = { tex = "" } }) diff --git a/common/config/nvim/lua/plugins/cmp-gh-source.lua b/common/config/nvim/lua/plugins/cmp-gh-source.lua new file mode 100644 index 0000000..4990c35 --- /dev/null +++ b/common/config/nvim/lua/plugins/cmp-gh-source.lua @@ -0,0 +1,70 @@ +local ok, Job = pcall(require, 'plenary.job') +if not ok then + return +end + +local source = {} + +source.new = function() + local self = setmetatable({ cache = {} }, { __index = source }) + + return self +end + +source.complete = function(self, _, callback) + local bufnr = vim.api.nvim_get_current_buf() + + -- This just makes sure that we only hit the GH API once per session. + -- + -- You could remove this if you wanted, but this just makes it so we're + -- good programming citizens. + if not self.cache[bufnr] then + Job:new({ + -- Uses `gh` executable to request the issues from the remote repository. + 'gh', + 'issue', + 'list', + '--limit', + '1000', + '--json', + 'title,number,body', + + on_exit = function(job) + local result = job:result() + local ok, parsed = pcall(vim.json.decode, table.concat(result, '')) + if not ok then + vim.notify('Failed to parse gh result') + return + end + + local items = {} + for _, gh_item in ipairs(parsed) do + gh_item.body = string.gsub(gh_item.body or '', '\r', '') + + table.insert(items, { + label = string.format('#%s', gh_item.number), + documentation = { + kind = 'markdown', + value = string.format('# %s\n\n%s', gh_item.title, gh_item.body), + }, + }) + end + + callback({ items = items, isIncomplete = false }) + self.cache[bufnr] = items + end, + }):start() + else + callback({ items = self.cache[bufnr], isIncomplete = false }) + end +end + +source.get_trigger_characters = function() + return { '#' } +end + +source.is_available = function() + return vim.bo.filetype == 'gitcommit' +end + +require('cmp').register_source('gh_issues', source.new()) diff --git a/common/config/nvim/lua/plugins/cmp.lua b/common/config/nvim/lua/plugins/cmp.lua new file mode 100644 index 0000000..fe212fc --- /dev/null +++ b/common/config/nvim/lua/plugins/cmp.lua @@ -0,0 +1,354 @@ +-- Setup nvim-cmp. +vim.opt.completeopt = "menu,menuone,noselect" +--vim.g.completeopt = "menu,menuone,noselect,noinsert" +local cmp_status_ok, cmp = pcall(require, "cmp") +if not cmp_status_ok then + return +end +--local WIDE_HEIGHT = 40 + +local opts = { + -- whether to highlight the currently hovered symbol + -- disable if your cpu usage is higher than you want it + -- or you just hate the highlight + -- default: true + highlight_hovered_item = true, + show_guides = true, +} +require("symbols-outline").setup(opts) + +--local snippets_paths = function() +-- local plugins = { "friendly-snippets" } +-- local paths = {} +-- local path +-- local root_path = vim.env.HOME .. "/.vim/plugged/" +-- for _, plug in ipairs(plugins) do +-- path = root_path .. plug +-- if vim.fn.isdirectory(path) ~= 0 then +-- table.insert(paths, path) +-- end +-- end +-- return paths +--end +-- +--require("luasnip.loaders.from_vscode").lazy_load({ +-- paths = snippets_paths(), +-- include = nil, -- Load all languages +-- exclude = {}, +--}) + +--require("luasnip.loaders.from_vscode").lazy_load() +local lspkind = require("lspkind") +local kind_icons = { + Text = "", + Method = "m", --"", + Function = "", + Constructor = "", --"⚙️", + Field = "", + Variable = "", + Class = "ﴯ", + Interface = "", + Module = "", + Property = "", + Unit = "", + Value = "", + Enum = "", + Keyword = "", + Snippet = "", + Color = "", + File = "", + Reference = "", + Folder = "", + EnumMember = "", + Constant = "", + Struct = "", + Event = "", + Operator = "", + TypeParameter = "", +} +cmp.setup({ + snippet = { + --expand = function(args) + -- require("luasnip").lsp_expand(args.body) + --end, + expand = function(args) + local luasnip = require("luasnip") + if not luasnip then + return + end + luasnip.lsp_expand(args.body) + end, + }, + mapping = cmp.mapping.preset.insert({ + -- ["<CR>"] = cmp.mapping.confirm({ + -- behavior = cmp.ConfirmBehavior.Replace, + -- select = true, + -- }), + --["<C-k>"] = cmp.mapping(cmp.mapping.select_prev_item(), { 'i', 'c' }), + --["<C-j>"] = cmp.mapping(cmp.mapping.select_next_item(), { 'i', 'c' }), + ["<C-y>"] = cmp.mapping.confirm({ select = true }), + --["<C-e>"] = cmp.mapping.close(), + --['<C-e>'] = cmp.mapping({ + -- i = cmp.mapping.abort(), + -- c = cmp.mapping.close(), + --}), + ["<C-e>"] = cmp.mapping({ + i = function() + if cmp.visible() then + cmp.abort() + require("user.mods").toggle_completion() + require("notify")("completion off") + else + cmp.complete() + require("user.mods").toggle_completion() + require("notify")("completion on") + end + end, + }), + --["<CR>"] = cmp.mapping({ + -- i = function(fallback) + -- if cmp.visible() then + -- cmp.confirm({ behavior = cmp.ConfirmBehavior.Replace, select = false }) + -- require("user.mods").toggle_completion() + -- else + -- fallback() + -- end + -- end, + --}), + + -- ["<C-e>"] = cmp.mapping({ + -- i = function() + -- if cmp.visible() then + -- require("notify")("visible") + -- cmp.abort() + -- else + -- require("notify")("not visible") + -- cmp.complete() + -- end + -- end, + -- c = function() + -- if cmp.visible() then + -- require("notify")("visible") + -- cmp.close() + -- else + -- require("notify")("not visible") + -- cmp.complete() + -- end + -- end, + -- }), + --['<CR>'] = cmp.config.disable, + ["<C-u>"] = cmp.mapping.scroll_docs(-4), + ["<C-d>"] = cmp.mapping.scroll_docs(4), + ["<C-Space>"] = cmp.mapping.complete(), + --['<C-o>'] = function(fallback) + -- if cmp.visible() then + -- cmp.mapping.confirm({ select = true })(fallback) + -- else + -- cmp.mapping.complete()(fallback) + -- end + --end + }), + + sources = cmp.config.sources({ + --{ name = "nvim_lua" }, + { name = "luasnip" }, + --{ name = 'luasnip', option = { use_show_condition = false } }, + { name = "gh_issues" }, + { name = "nvim_lsp", max_item_count = 6 }, + { name = "nvim_lua" }, + --{ name = "luasnip" }, + --{ name = "luasnip", keyword_length = 4 }, + --{ name = "buffer", keyword_length = 3 }, + { name = "path" }, + { name = "buffer", max_item_count = 6 }, + --{ name = "buffer", option = { get_bufnrs = function() + -- return vim.api.nvim_list_bufs() + --end + --}}, + { name = "cmp_git" }, + { name = "spell" }, + { name = "zsh" }, + { name = "treesitter" }, + { name = "calc" }, + { name = "nvim_lsp_signature_help" }, + --{ name = "cmdline" }, + --{ name = 'treesitter' }, + --{ name = "cmdline", keyword_pattern = [=[[^[:blank:]\!]*]=] }, --exclamation mark hangs a bit without this + --{name = 'luasnip', keyword_length = 2}, + }), + formatting = { + --formatting = { + --local icons = kind_icons + --format = function(entry, vim_item) + ----vim_item.kind = string.format("%s", kind_icons[vim_item.kind]) + ----vim_item.kind = lspkind.presets.default[vim_item.kind] + --vim_item.kind = string.format('%s %s', kind_icons[vim_item.kind], vim_item.kind) -- This concatonates the icons with the name of the item kind + ----vim_item.kind = string.format("%s %s", icons[vim_item.kind], vim_item.kind) + --vim_item.menu = ({ + ----nvim_lsp = "LSP", + ----luasnip = "snip", + ----buffer = "buf", + ----path = "path", + ----cmdline = "cmd", + --buffer = "[buf]", + --nvim_lsp = "[LSP]", + --nvim_lua = "[api]", + --path = "[path]", + --luasnip = "[snip]", + --cmdline = "[cmd]", + --gh_issues = "[issues]", + --})[entry.source.name] + --return vim_item + --end, + format = lspkind.cmp_format({ + with_text = true, + menu = { + nvim_lsp = "[LSP]", + luasnip = "[snip]", + buffer = "[buf]", + nvim_lua = "[api]", + path = "[path]", + gh_issues = "[issues]", + spell = "[spell]", + zsh = "[zsh]", + treesitter = "[treesitter]", + calc = "[calc]", + nvim_lsp_signature_help = "[signature]", + cmdline = "[cmd]", + }, + }), + --}, + + -- + -- + --fields = { "abbr", "kind", "menu" }, + -- format = lspkind.cmp_format({ + -- mode = 'symbol_text', -- show only symbol annotations + -- maxwidth = 50, -- prevent the popup from showing more than provided characters (e.g 50 will not show more than 50 characters) + -- }) + --format = require('lspkind').cmp_format { + -- with_text = true, + -- menu = { + -- luasnip = "Snip", + -- buffer = "Buf", + -- nvim_lsp = "LSP", + -- path = "Path", + -- cmdline = "Cmd", + -- cmp_git = "Git", + -- }, + --}, + }, + --format = function(entry, vim_item) + -- -- Kind icons + -- --vim_item.kind = string.format("%s", kind_icons[vim_item.kind]) + -- vim_item.kind = lspkind.presets.default[vim_item.kind] + -- -- vim_item.kind = string.format('%s %s', kind_icons[vim_item.kind], vim_item.kind) -- This concatonates the icons with the name of the item kind + -- vim_item.menu = ({ + -- nvim_lsp = "LSP", + -- luasnip = "Snip", + -- buffer = "Buf", + -- path = "Path", + -- cmdline = "Cmd", + -- })[entry.source.name] + -- return vim_item + --end, + confirm_opts = { + behavior = cmp.ConfirmBehavior.Replace, + select = false, + }, + + event = {}, + + experimental = { + ghost_text = true, -- this feature conflicts with copilot.vim's preview. + hl_group = "Nontext", + --native_menu = false, + }, + + view = { + entries = { name = "custom", selection_order = "top_down" }, + }, + + window = { + --completion = cmp.config.window.bordered(), + completion = { + border = { "", "", "", " ", "", "", "", " " }, + --border = { "╭", "─", "╮", "│", "╯", "─", "╰", "│" }, + --border = { '', '', '', '', '', '', '', '' }, + --border = "CmpBorder", + winhighlight = "Normal:Pmenu,FloatBorder:Pmenu,CursorLine:PmenuSel,Search:None", + --winhighlight = "Normal:CmpPmenu,CursorLine:PmenuSel,Search:None", + }, + --documentation = cmp.config.window.bordered(), + documentation = { + --max_height = math.floor(WIDE_HEIGHT * (WIDE_HEIGHT / vim.o.lines)), + --max_width = math.floor((WIDE_HEIGHT * 2) * (vim.o.columns / (WIDE_HEIGHT * 2 * 16 / 9))), + border = { "", "", "", " ", "", "", "", " " }, + --border = { "╭", "─", "╮", "│", "╯", "─", "╰", "│" }, + winhighlight = "FloatBorder:NormalFloat", + }, + }, +}) + +cmp.setup.cmdline({ "/", "?" }, { + mapping = cmp.mapping.preset.cmdline(), + sources = { + { name = "buffer" }, + }, +}) + +cmp.setup.cmdline(":", { + mapping = { + ["<C-p>"] = cmp.mapping(cmp.mapping.select_prev_item(), { "i", "c" }), + ["<C-n>"] = cmp.mapping(cmp.mapping.select_next_item(), { "i", "c" }), + ["<C-y>"] = cmp.mapping(cmp.mapping.confirm({ select = true }), { "i", "c" }), + ["<C-e>"] = cmp.mapping(cmp.mapping.close(), { "i", "c" }), + ["<C-u>"] = cmp.mapping(cmp.mapping.scroll_docs(-4), { "i", "c" }), + ["<C-d>"] = cmp.mapping(cmp.mapping.scroll_docs(4), { "i", "c" }), + ["<C-Space>"] = cmp.mapping(cmp.mapping.complete(), { "i", "c" }), + --["<C-k>"] = cmp.mapping.select_prev_item(), + --["<C-j>"] = cmp.mapping.select_next_item(), + --['<C-y>'] = cmp.mapping.confirm({ select = true }), + --["<C-e>"] = cmp.mapping.close(), + ----['<CR>'] = cmp.config.disable, + --["<C-u>"] = cmp.mapping.scroll_docs(-4), + --["<C-d>"] = cmp.mapping.scroll_docs(4), + --["<C-Space>"] = cmp.mapping.complete(), + }, + + sources = cmp.config.sources({ + { name = "path" }, + }, { + --{ name = "cmdline" }, + { name = "cmdline", keyword_pattern = [=[[^[:blank:]\!]*]=], keyword_length = 3 }, + }), +}) + +return { + "micangl/cmp-vimtex", + config = function() + require("cmp_vimtex").setup({ + additional_information = { + info_in_menu = true, + info_in_window = true, + info_max_length = 60, + match_against_info = true, + symbols_in_menu = true, + }, + bibtex_parser = { + enabled = true, + }, + search = { + browser = "xdg-open", + default = "google_scholar", + search_engines = { + google_scholar = { + name = "Google Scholar", + get_url = require("cmp_vimtex").url_default_format("https://scholar.google.com/scholar?hl=en&q=%s"), + }, + -- Other search engines. + }, + }, + }) + end, +} diff --git a/common/config/nvim/lua/plugins/colorscheme.lua b/common/config/nvim/lua/plugins/colorscheme.lua new file mode 100644 index 0000000..be78ac8 --- /dev/null +++ b/common/config/nvim/lua/plugins/colorscheme.lua @@ -0,0 +1,344 @@ +--local function MyHighlights() +-- vim.cmd('highlight Visual cterm=NONE ctermbg=76 ctermfg=16 gui=NONE guibg=#5fd700 guifg=#000000') +-- vim.cmd('highlight StatusLine cterm=NONE ctermbg=231 ctermfg=160 gui=NONE guibg=#ffffff guifg=#d70000') +-- vim.cmd('highlight Normal cterm=NONE ctermbg=17 gui=NONE guibg=#00005f') +-- vim.cmd('highlight NonText cterm=NONE ctermbg=17 gui=NONE guibg=#00005f') +--end +-- +--local function setupMyColors() +-- vim.cmd('augroup MyColors') +-- vim.cmd('autocmd!') +-- vim.cmd('autocmd ColorScheme * call v:lua.MyHighlights()') +-- vim.cmd('augroup END') +--end +-- +--setupMyColors() + +--vim.api.nvim_command("highlight FoldColumn guibg=none") + +--vim.api.nvim_command("highlight SignColumn guifg=none guibg=none cterm=NONE ctermfg=none ctermbg=NONE gui=NONE") +--vim.api.nvim_command("highlight ColorColumn guifg=none guibg=none cterm=NONE ctermfg=none ctermbg=NONE gui=NONE") +--vim.api.nvim_command("highlight TabLineSel guibg=none guifg=none gui=bold") +--vim.api.nvim_command("highlight TabLineNC guibg=none gui=bold") +--vim.api.nvim_command("highlight StatusLine guibg=#333842 gui=bold") +--vim.api.nvim_command("highlight StatusLineNC guibg=none ctermfg=Cyan guifg=#80a0ff gui=bold") + +-- Custom colorscheme +--vim.cmd([[ +-- let g:terminal_color_0 = '#2e3436' +-- let g:terminal_color_1 = '#cc0000' +-- let g:terminal_color_2 = '#4e9a06' +-- let g:terminal_color_3 = '#c4a000' +-- let g:terminal_color_4 = '#3465a4' +-- let g:terminal_color_5 = '#75507b' +-- let g:terminal_color_6 = '#0b939b' +-- let g:terminal_color_7 = '#d3d7cf' +-- let g:terminal_color_8 = '#555753' +-- let g:terminal_color_9 = '#ef2929' +-- let g:terminal_color_10 = '#8ae234' +-- let g:terminal_color_11 = '#fce94f' +-- let g:terminal_color_12 = '#729fcf' +-- let g:terminal_color_13 = '#ad7fa8' +-- let g:terminal_color_14 = '#00f5e9' +-- let g:terminal_color_15 = '#eeeeec' +-- +-- set background=dark +-- execute "silent! colorscheme base16-eighties" +-- highlight Comment guifg=#585858 +-- highlight Normal guifg=#999999 +-- "highlight TabLine guifg=#333333 guibg=#777777 +-- "highlight TabLineSel guifg=#FA7F7F +-- highlight MatchParen gui=bold guibg=black guifg=limegreen +--]]) +--local colors = { +-- background = '#1c1c1c', +-- foreground = '#cacaca', +-- accent = '#fe5186', +-- blue = '#61afef', +-- cyan = '#3e8fb0', +-- dark_green = '#5faf5f', +-- dark_grey = '#222222', +-- dark_orange = '#ff5d62', +-- dark_red = '#bf1131', +-- dark_yellow = '#ffaf00', +-- green = '#98c379', +-- grey = '#2a2a2a', +-- light_grey = '#727169', +-- light_orange = '#ffa066', +-- light_pink = '#e46876', +-- light_yellow = '#e6db74', +-- magenta = '#c678dd', +-- orange = '#ff8700', +-- purple = '#af87d7', +-- red = '#c4384b', +-- violet = '#a9a1e1', +-- white = '#e3e3e3', +-- yellow = '#d7af5f', +--} +---- Base highlights to override themes to my preferences +--local base = { +-- CursorLine = { bg = 'none', fg = 'none' }, +-- -- Avoid changing the foreground color from the main theme +-- MatchParen = { fg = colors.accent, bg = 'none', bold = true }, +-- Visual = { bg = colors.grey, fg = 'none' }, +-- ActionPreviewBorder = { link = 'XMenuBorder' }, +-- ActionPreviewNormal = { link = 'XMenu' }, +-- CallHierarchyBorder = { link = 'XMenuBorder' }, +-- CallHierarchyNormal = { link = 'XMenu' }, +-- CodeActionBorder = { link = 'XMenuBorder' }, +-- CodeActionNormal = { link = 'XMenu' }, +-- DefinitionBorder = { link = 'XMenuBorder' }, +-- DefinitionNormal = { link = 'XMenu' }, +-- EndOfBuffer = { fg = colors.background }, +-- FinderBorder = { link = 'XMenuBorder' }, +-- FinderNormal = { link = 'XMenu' }, +-- FloatBorder = { link = 'XMenuBorder' }, +-- FloatNormal = { link = 'XMenu' }, +-- HoverBorder = { link = 'XMenuBorder' }, +-- HoverNormal = { link = 'XMenu' }, +-- NormalFloat = { link = 'XMenu' }, +-- OutlinePreviewBorder = { link = 'XMenuBorder' }, +-- OutlinePreviewNormal = { link = 'XMenu' }, +-- Pmenu = { link = 'XMenu' }, +-- RenameBorder = { link = 'XMenuBorder' }, +-- RenameNormal = { link = 'XMenu' }, +-- TerminalBorder = { link = 'XMenuBorder' }, +-- TerminalNormal = { link = 'XMenu' }, +-- Todo = { fg = colors.orange, bold = true }, +-- SagaNormal = { link = 'XMenu' }, +-- SagaBorder = { link = 'XMenuBorder' }, +-- StatusLine = { bg = colors.background, fg = colors.foreground }, +-- TitleString = { link = 'XMenu' }, +-- TitleIcon = { link = 'XMenu' }, +-- ActionPreviewTitle = { link = 'XMenu' }, +-- -- Mason +-- MasonHeader = { link = 'XMenu' }, +-- MasonNormal = { link = 'XMenu' }, +-- NvimTreeCursorColumn = { bg = 'none', fg = 'none' }, +-- --NvimTreeCursorLine = { bg = colors.dark_grey, fg = colors.accent }, +-- -- Telescope +-- TelescopeBorder = { link = 'XMenuBorder' }, +-- TelescopePromptBorder = { link = 'XMenuBorder' }, +-- TelescopePromptNormal = { link = 'XMenu', fg = colors.foreground }, +-- TelescopePromptPrefix = { link = 'XMenu', fg = colors.foreground }, +-- TelescopeNormal = { bg = colors.background }, +-- TelescopePreviewBorder = { link = 'XMenuBorder' }, +-- TelescopePreviewNormal = { link = 'XMenu', fg = colors.foreground }, +-- TelescopePreviewTitle = { fg = colors.background, bg = colors.light_orange }, +-- TelescopePreviewLine = { fg = colors.background, bg = colors.orange }, +-- TelescopePromptTitle = { fg = colors.background, bg = colors.light_orange }, +-- TelescopeResultsTitle = { fg = colors.background, bg = colors.light_orange }, +-- TelescopeResultsBorder = { link = 'XMenuBorder' }, +-- TelescopeResultsNormal = { link = 'XMenu' }, +--} +-- +--local theme = { +-- -- Transparent background +-- Conceal = { bg = 'none', fg = colors.foreground }, +-- FoldCoumn = { bg = 'none' }, +-- LineNr = { bg = 'none', fg = colors.grey }, +-- MsgArea = { bg = 'none', fg = colors.foreground }, +-- NonText = { bg = 'none', fg = colors.light_grey }, +-- Normal = { bg = 'none', fg = colors.foreground }, +-- NormalNC = { bg = 'none', fg = colors.foreground }, +-- SignColumn = { bg = 'none' }, +-- WinSeparator = { bg = 'none', fg = colors.grey }, +-- -- Language Syntax +-- Boolean = { fg = colors.grey }, +-- Character = { fg = colors.yellow }, +-- Comment = { fg = colors.light_grey }, +-- Conditional = { fg = colors.blue }, +-- Constant = { fg = colors.grey }, +-- Debug = { fg = colors.green }, +-- Define = { fg = colors.green }, +-- Delimiter = { fg = colors.grey }, +-- Error = { fg = colors.red }, +-- Exception = { fg = colors.dark_orange }, +-- Float = { fg = colors.light_pink }, +-- Function = { fg = colors.foreground }, +-- Identifier = { fg = colors.foreground }, +-- Ignore = { fg = colors.light_grey }, +-- Include = { fg = colors.dark_orange }, +-- Keyword = { fg = colors.blue }, +-- Label = { fg = colors.grey }, +-- Macro = { fg = colors.dark_orange }, +-- Number = { fg = colors.light_pink }, +-- Operator = { fg = colors.purple }, +-- PreCondit = { fg = colors.dark_orange }, +-- PreProc = { fg = colors.dark_orange }, +-- Repeat = { fg = colors.blue }, +-- Special = { fg = colors.dark_orange }, +-- SpecialChar = { fg = colors.dark_orange }, +-- SpecialComment = { fg = colors.orange }, +-- Statement = { fg = colors.blue }, +-- StorageClass = { fg = colors.light_orange }, +-- String = { fg = colors.yellow }, +-- Structure = { fg = colors.light_orange }, +-- Tag = { fg = colors.orange }, +-- Todo = { fg = colors.orange, bold = true }, +-- Type = { fg = colors.light_orange }, +-- Typedef = { fg = colors.foreground }, +-- Underlined = { fg = colors.foreground }, +-- -- Rest +-- ColorColumn = { bg = colors.dark_grey }, +-- Cursor = { bg = colors.accent }, +-- CursorColumn = { bg = 'none', fg = colors.accent }, +-- CursorLine = { bg = 'none', fg = 'none' }, +-- CursorLineNr = { bg = 'none', fg = colors.light_pink }, +-- Directory = { fg = colors.cyan, bold = true }, +-- ErrorMsg = { bg = 'none', fg = colors.red }, +-- IncSearch = { bg = colors.accent, fg = colors.foreground }, +-- MatchParen = { fg = colors.accent, bg = 'none', bold = true }, +-- Search = { bg = colors.accent }, +-- SpellBad = { bg = 'none', fg = 'none', undercurl = true, ctermbg = 'none', ctermfg = 'none' }, +-- SpellLocal = { bg = 'none', fg = 'none', undercurl = true, ctermbg = 'none', ctermfg = 'none' }, +-- SpellRare = { bg = 'none', fg = 'none', undercurl = true, ctermbg = 'none', ctermfg = 'none' }, +-- StatusLine = { fg = colors.foreground, bg = 'none' }, +-- StatusLineNC = { fg = 'none', bg = 'none' }, +-- Title = { fg = colors.blue, bg = '', bold = true }, +-- VertSplit = { bg = 'none', fg = colors.grey }, +-- Visual = { bg = colors.grey, fg = 'none' }, +-- -- Diagnostic +-- DiagnosticBorder = { link = 'XMenuBorder' }, +-- DiagnosticNormal = { link = 'XMenu' }, +-- DiagnosticError = { fg = colors.red }, +-- DiagnosticFloatingError = { link = 'XMenu' }, +-- DiagnosticFloatingHint = { link = 'XMenu' }, +-- DiagnosticFloatingInfo = { link = 'XMenu' }, +-- DiagnosticFloatingWarn = { link = 'XMenu' }, +-- DiagnosticSignHint = { fg = colors.grey, bold = true, bg = 'none' }, +-- DiagnosticUnderlineError = { undercurl = true }, +-- DiagnosticVirtualTextHint = { bg = 'none' }, +-- DiagnosticWarn = { fg = colors.yellow }, +-- -- nvim cmp +-- CmpItemAbbr = { fg = colors.foreground }, +-- CmpItemAbbrMatch = { fg = colors.dark_orange }, +-- CmpItemAbbrMatchFuzzy = { fg = colors.dark_orange }, +-- CmpBorder = { link = 'FloatBorder' }, +-- CmpDocBorder = { link = 'FloatBorder' }, +-- CmpItemMenuDefault = { link = 'NormalFloat' }, +-- CmpMenu = { link = 'NormalFloat' }, +-- -- cmp item kinds +-- CmpItemKindConstant = { fg = colors.light_pink }, +-- CmpItemKindFunction = { fg = colors.blue }, +-- CmpItemKindIdentifier = { fg = colors.purple }, +-- CmpItemKindField = { fg = colors.dark_orange }, +-- CmpItemKindVariable = { fg = colors.purple }, +-- CmpItemKindSnippet = { fg = colors.light_pink }, +-- CmpItemKindText = { fg = colors.foreground }, +-- CmpItemKindStructure = { fg = colors.blue }, +-- CmpItemKindType = { fg = colors.orange }, +-- CmpItemKindKeyword = { fg = colors.blue }, +-- CmpItemKindMethod = { fg = colors.purple }, +-- CmpItemKindConstructor = { fg = colors.blue }, +-- CmpItemKindFolder = { fg = colors.blue }, +-- CmpItemKindModule = { fg = colors.dark_orange }, +-- CmpItemKindProperty = { fg = colors.dark_orange }, +-- CmpItemKindEnum = { fg = colors.blue }, +-- CmpItemKindUnit = { fg = colors.green }, +-- CmpItemKindClass = { fg = colors.blue }, +-- CmpItemKindFile = { fg = colors.blue }, +-- CmpItemKindInterface = { fg = colors.blue }, +-- CmpItemKindColor = { fg = colors.yellow }, +-- CmpItemKindReference = { fg = colors.blue }, +-- CmpItemKindEnumMember = { fg = colors.green }, +-- CmpItemKindStruct = { fg = colors.blue }, +-- -- CmpItemKindValue = { fg = "" }, +-- -- CmpItemKindEvent = { fg = "" }, +-- CmpItemKindOperator = { fg = colors.purple }, +-- CmpItemKindTypeParameter = { fg = colors.light_pink }, +-- CmpItemKindCopilot = { fg = colors.green }, +-- -- LSPSaga +-- OutlinePreviewBorder = { link = 'NormalFloat' }, +-- OutlinePreviewNormal = { link = 'FloatBorder' }, +-- -- Diffview +-- DiffViewSignColumn = { bg = 'none' }, +-- -- Treesitter +-- -- ['@string'] = { fg = colors.yellow, bg = '' }, +-- ['@boolean'] = { fg = colors.dark_yellow }, +-- ['@character'] = { fg = colors.foreground }, +-- ['@character.special'] = { fg = colors.dark_orange }, +-- ['@comment'] = { link = 'Comment' }, +-- ['@conditional'] = { fg = colors.blue }, +-- ['@constant'] = { fg = colors.foreground }, +-- ['@constant.builtin'] = { fg = colors.dark_yellow }, +-- ['@constant.macro'] = { fg = colors.dark_orange }, +-- ['@constructor'] = { fg = colors.blue }, +-- ['@debug'] = { link = 'Debug' }, +-- ['@define'] = { link = "Define" }, +-- ['@exception'] = { fg = colors.dark_orange }, +-- ['@field'] = { link = 'Identifier' }, +-- ['@field.yaml'] = { fg = colors.light_orange }, +-- ['@float'] = { fg = colors.light_pink }, +-- ['@function'] = { link = 'Function' }, +-- ['@function.builtin'] = { fg = colors.dark_green }, +-- ['@function.macro'] = { fg = colors.dark_orange }, +-- ['@include'] = { fg = colors.dark_orange }, +-- ['@keyword'] = { link = 'Keyword' }, +-- ['@keyword.operator'] = { fg = colors.purple }, +-- ['@keyword.return'] = { fg = colors.dark_orange }, +-- ['@label'] = { fg = colors.blue }, +-- ['@macro'] = { fg = colors.dark_orange }, +-- ['@method'] = { fg = colors.foreground }, +-- ['@namespace'] = { fg = colors.foreground }, +-- ['@number'] = { link = 'Number' }, +-- ['@operator'] = { link = 'Operator' }, +-- ['@parameter'] = { fg = colors.foreground }, +-- ['@preproc'] = { link = 'PreProc' }, +-- ['@property'] = { fg = colors.foreground }, +-- ['@punctuation.Special'] = { fg = colors.purple }, +-- ['@punctuation.bracket'] = { fg = colors.purple }, +-- ['@punctuation.delimiter'] = { fg = colors.purple }, +-- ['@repeat'] = { link = 'Repeat' }, +-- ['@storageclass'] = { link = 'StorageClass' }, +-- ['@string.escape'] = { fg = colors.dark_orange }, +-- ['@string.regex'] = { fg = colors.green }, +-- ['@string.special'] = { fg = colors.dark_orange }, +-- ['@structure'] = { link = 'Structure' }, +-- ['@tag'] = { link = 'Tag' }, +-- ['@tag.attribute'] = { fg = colors.foreground }, +-- ['@tag.delimiter'] = { fg = colors.purple }, +-- ['@text.danger'] = { fg = colors.dark_orange }, +-- ['@text.literal'] = { link = 'String' }, +-- ['@text.reference'] = { fg = colors.green }, +-- ['@text.strong'] = { bold = true }, +-- ['@text.title'] = { link = 'Title' }, +-- ['@text.todo'] = { link = 'Todo' }, +-- ['@text.underline'] = { link = 'Underlined' }, +-- ['@text.uri'] = { fg = colors.blue }, +-- ['@text.warning'] = { link = 'Todo' }, +-- ['@type'] = { link = 'Type' }, +-- ['@type.definition'] = { link = 'Typedef' }, +-- ['@variable'] = { fg = colors.foreground }, +-- ['@variable.builtin'] = { fg = colors.light_orange }, +--} +-- +--local M = {} +-- +--local function _load(config) +-- for group, hl in pairs(config) do +-- if not vim.tbl_isempty(hl) then +-- vim.api.nvim_set_hl(0, group, hl) +-- end +-- end +--end +-- +-- +--function M.setup() +-- vim.api.nvim_set_hl(0, 'XMenu', { bg = colors.dark_grey, default = true }) +-- vim.api.nvim_set_hl(0, 'XMenuBorder', { bg = colors.dark_grey, fg = colors.dark_grey, default = true }) +-- vim.g.terminal_color_0 = colors.dark_grey +--end +-- +----function M.load(full) +---- _load(base) +---- +---- if not full then +---- _load_diagnostics() +---- return +---- end +---- +---- _load(theme) +----end +-- +--return M diff --git a/common/config/nvim/lua/plugins/dap.lua b/common/config/nvim/lua/plugins/dap.lua new file mode 100644 index 0000000..98ae3fd --- /dev/null +++ b/common/config/nvim/lua/plugins/dap.lua @@ -0,0 +1,253 @@ +local dap = require("dap") + +-- options +dap.defaults.fallback.switchbuf = "uselast" +dap.defaults.fallback.focus_terminal = true +dap.defaults.fallback.external_terminal = { + command = "/usr/bin/wezterm", + args = { "-e" }, +} + +-- Autocmds +vim.api.nvim_create_autocmd("FileType", { + pattern = { "dap-float" }, + callback = function(event) + vim.keymap.set("n", "<Tab>", "", { buffer = event.buf, silent = true }) + vim.keymap.set("n", "<S-Tab>", "", { buffer = event.buf, silent = true }) + end, +}) + +dap.adapters.cppdbg = { + id = "cppdbg", + type = "executable", + --command = vim.fn.stdpath('data') .. '/mason/bin/OpenDebugAD7', + command = os.getenv("HOME") .. "/apps/cpptools/extension/debugAdapters/bin/OpenDebugAD7", + --command = cpptools:get_install_path() .. '/extension/debugAdapters/bin/OpenDebugAD7' +} + +dap.adapters.codelldb = { + type = "server", + port = "${port}", + --host = "localhost", + --host = '127.0.0.1', + --port = 13000, -- 💀 Use the port printed out or specified with `--port` + executable = { + --command = os.getenv("HOME") .. '/apps/codelldb/extension/adapter/codelldb', + command = os.getenv("HOME") .. "/.vscode-oss/extensions/vadimcn.vscode-lldb-1.9.0-universal/adapter/codelldb", + args = { "--port", "${port}" }, + }, + --detached = true, +} + +dap.adapters.lldb = { + type = "executable", + command = "/usr/bin/lldb-vscode", + name = "lldb", +} +dap.configurations.cpp = { + { + name = "Debugger", + --type = "lldb", + --type = "cppdbg", + type = "codelldb", + request = "launch", + cwd = "${workspaceFolder}", + program = function() + return vim.fn.input("Path to executable: ", vim.fn.getcwd() .. "/", "file") + end, + --program = '${file}', + --program = function() + -- -- First, check if exists CMakeLists.txt + -- local cwd = vim.fn.getcwd() + -- if (file.exists(cwd, "CMakeLists.txt")) then + -- -- Todo. Then invoke cmake commands + -- -- Then ask user to provide execute file + -- return vim.fn.input("Path to executable: ", vim.fn.getcwd() .. "/", "file") + -- else + -- local fileName = vim.fn.expand("%:t:r") + -- if (not file.exists(cwd, "bin")) then + -- -- create this directory + -- os.execute("mkdir " .. "bin") + -- end + -- local cmd = "!gcc -g % -o bin/" .. fileName + -- -- First, compile it + -- vim.cmd(cmd) + -- -- Then, return it + -- return "${fileDirname}/bin/" .. fileName + -- end + --end, + stopAtEntry = true, + args = {}, + --runInTerminal = true, + --runInTerminal = false, + --console = 'integratedTerminal', + + --MIMode = 'gdb', + --miDebuggerServerAddress = 'localhost:1234', + --miDebuggerPath = 'gdb-oneapi', + --miDebuggerPath = '/usr/bin/gdb', + externalConsole = true, + --setupCommands = { + -- { + -- text = '-enable-pretty-printing', + -- description = 'enable pretty printing', + -- ignoreFailures = false + -- } + --}, + }, +} + +-- If you want to use this for Rust and C, add something like this: +dap.configurations.c = dap.configurations.cpp +dap.configurations.rust = dap.configurations.cpp + +-- javascript +--dap.adapters.node2 = { +-- type = 'executable', +-- command = 'node-debug2-adapter', +-- args = {}, +--} + +--dap.configurations.javascript = { +-- { +-- name = 'Launch', +-- type = 'node2', +-- request = 'attach', +-- program = '${file}', +-- cwd = vim.fn.getcwd(), +-- sourceMaps = true, +-- protocol = 'inspector', +-- console = 'integratedTerminal', +-- }, +--} + +dap.adapters.python = { + type = "executable", + command = vim.trim(vim.fn.system("which python")), + args = { "-m", "debugpy.adapter" }, +} + +dap.configurations.python = { + { + -- The first three options are required by nvim-dap + type = "python", -- the type here established the link to the adapter definition: `dap.adapters.python` + request = "launch", + name = "Launch file", + -- Options below are for debugpy, see https://github.com/microsoft/debugpy/wiki/Debug-configuration-settings for supported options + program = "${file}", -- This configuration will launch the current file if used. + stopOnEntry = true, + }, +} + +local dapui = require("dapui") +--local dap_ui_status_ok, dapui = pcall(require, "dapui") +--if not dap_ui_status_ok then +-- return +--end + +-- setup repl +--dap.repl.commands = vim.tbl_extend('force', dap.repl.commands, { +-- exit = { 'q', 'exit' }, +-- custom_commands = { +-- ['.run_to_cursor'] = dap.run_to_cursor, +-- ['.restart'] = dap.run_last +-- } +--}) + +-- Load dapui configuration only if it hasn't been loaded before +if not vim.g.loaded_dapui then + require("dapui").setup({ + mappings = { + expand = "<CR>", + open = "o", + remove = "D", + edit = "e", + repl = "r", + toggle = "t", + }, + controls = { + enabled = true, + }, + layouts = { + { + elements = { + -- Elements can be strings or table with id and size keys. + { id = "watches", size = 0.25 }, + { id = "scopes", size = 0.25 }, + { id = "breakpoints", size = 0.25 }, + { id = "stacks", size = 0.25 }, + }, + size = 50, -- 40 columns + position = "left", + }, + { + elements = { + { id = "console", size = 0.6 }, + { id = "repl", size = 0.4 }, + }, + size = 0.3, + position = "bottom", + }, + }, + render = { + max_value_lines = 3, + }, + floating = { + max_height = nil, -- These can be integers or a float between 0 and 1. + max_width = nil, -- Floats will be treated as percentage of your screen. + border = "single", -- Border style. Can be "single", "double" or "rounded" + mappings = { + close = { "q", "<Esc>" }, + }, + }, + --icons = { expanded = "-", collapsed = "$" }, + icons = { + expanded = "", + collapsed = "", + current_frame = "", + }, + }) + vim.g.loaded_dapui = true +end + +-- Signs +local sign = vim.fn.sign_define +sign("DapBreakpoint", { text = "●", texthl = "DapBreakpoint", linehl = "", numhl = "" }) +sign("DapBreakpointCondition", { text = "◆", texthl = "DapBreakpointCondition", linehl = "", numhl = "" }) -- +sign("DapBreakpointRejected", { text = "R", texthl = "DiagnosticError", numhl = "DiagnosticError" }) +sign("DapLogPoint", { text = "L", texthl = "DapLogPoint", linehl = "", numhl = "" }) +sign("DapStopped", { text = "", texthl = "DiagnosticSignHint", numbhl = "", linehl = "" }) + +--sign('DapBreakpoint', { text = '', texthl = 'DiagnosticSignError', numbhl = '', linehl = '' }) +--sign("DapLogPoint", { text = '.>', texthl = 'DiagnosticInfo', numhl = 'DiagnosticInfo' }) +--vim.fn.sign_define("DapBreakpointCondition", { text = '?>', texthl = 'DiagnosticInfo', numhl = 'DiagnosticInfo' }) +--vim.fn.sign_define("DapStopped", { text = '=>', texthl = 'DiagnosticWarn', numhl = 'DiagnosticWarn' }) +--vim.fn.sign_define("DapBreakpoint", { text = '<>', texthl = 'DiagnosticInfo', numhl = 'DiagnosticInfo' }) + +dap.listeners.after.event_initialized["dapui_config"] = function() + dapui.open() +end +dap.listeners.before.event_terminated["dapui_config"] = function() + dapui.close() +end +dap.listeners.before.event_exited["dapui_config"] = function() + dapui.close() +end +dap.listeners.before.disconnect["dapui_config"] = function() + dapui.close() +end + +require("nvim-dap-virtual-text").setup({ + enabled = true, + enabled_commands = true, + highlight_changed_variables = true, + highlight_new_as_changed = false, + show_stop_reason = true, + commented = true, + only_first_definition = true, + all_references = false, + filter_references_pattern = "<module", + virt_text_pos = "eol", + all_frames = false, + virt_text_win_col = nil, +}) diff --git a/common/config/nvim/lua/plugins/dashboard.lua b/common/config/nvim/lua/plugins/dashboard.lua new file mode 100644 index 0000000..f02242c --- /dev/null +++ b/common/config/nvim/lua/plugins/dashboard.lua @@ -0,0 +1,90 @@ +local db = require('dashboard') +local messages = require('plugins.messages') + +function GetRandomMessage() + -- Get a random index from the messages array + local randomIndex = math.random(1, #messages) + return messages[randomIndex] +end + +--vim.api.nvim_create_autocmd("VimEnter", { +-- callback = function() +-- -- disable line numbers +-- vim.opt_local.number = false +-- vim.opt_local.relativenumber = false +-- -- always start in insert mode +-- end, +--}) + +db.setup({ + theme = 'hyper', + config = { + mru = { limit = 10, label = '' }, + project = { limit = 10 }, + header = { + [[ ███╗ ██╗ ███████╗ ██████╗ ██╗ ██╗ ██╗ ███╗ ███╗]], + [[ ████╗ ██║ ██╔════╝██╔═══██╗ ██║ ██║ ██║ ████╗ ████║]], + [[ ██╔██╗ ██║ █████╗ ██║ ██║ ██║ ██║ ██║ ██╔████╔██║]], + [[ ██║╚██╗██║ ██╔══╝ ██║ ██║ ╚██╗ ██╔╝ ██║ ██║╚██╔╝██║]], + [[ ██║ ╚████║ ███████╗╚██████╔╝ ╚████╔╝ ██║ ██║ ╚═╝ ██║]], + [[ ╚═╝ ╚═══╝ ╚══════╝ ╚═════╝ ╚═══╝ ╚═╝ ╚═╝ ╚═╝]], + }, + disable_move = false, + shortcut = { + { desc = ' Plugins', group = 'Number', action = 'PackerStatus', key = 'p' }, + --{ desc = " Plugins", group = "@property", action = "PackerStatus", key = "p" }, + { + desc = ' Files', + group = 'Number', + --group = "Label", + action = 'Telescope find_files', + key = 'f', + }, + { + desc = ' Text', + group = 'Number', + --group = "Label", + action = 'enew', + key = 't', + }, + { + desc = ' Grep', + group = 'Number', + --group = "Label", + action = 'Telescope live_grep', + key = 'g', + }, + { + desc = ' Scheme', + group = 'Number', + --group = "Label", + action = 'Telescope colorscheme', + key = 's', + }, + { + desc = ' Config', + group = 'Number', + --group = "Label", + action = ':edit ~/.config/nvim/init.lua', + key = 'c', + }, + }, + footer = function() + return { '', GetRandomMessage() } + end, + }, + hide = { + statusline = false, + tabline = false, + winbar = false, + }, +}) + +--highlights +---- General +--DashboardHeader DashboardFooter +---- Hyper theme +--DashboardProjectTitle DashboardProjectTitleIcon DashboardProjectIcon +--DashboardMruTitle DashboardMruIcon DashboardFiles DashboardShotCutIcon +---- Doome theme +--DashboardDesc DashboardKey DashboardIcon DashboardShotCut diff --git a/common/config/nvim/lua/plugins/fidget.lua b/common/config/nvim/lua/plugins/fidget.lua new file mode 100644 index 0000000..d401c5f --- /dev/null +++ b/common/config/nvim/lua/plugins/fidget.lua @@ -0,0 +1,34 @@ +require("fidget").setup({ + --event = "LspAttach", + text = { + --spinner = "pipe", -- (Default) animation shown when tasks are ongoing + --spinner = "hamburger", -- animation shown when tasks are ongoing + --spinner = "dots_pulse", -- animation shown when tasks are ongoing + spinner = "dots", -- animation shown when tasks are ongoing + done = "✔", -- character shown when all tasks are complete + commenced = "Started", -- message shown when task starts + completed = "Completed", -- message shown when task completes + }, + fmt = { + task = function(task_name, message, percentage) + if task_name == "diagnostics" then + return false + end + return string.format( + "%s%s [%s]", + message, + percentage and string.format(" (%s%%)", percentage) or "", + task_name + ) + end, + }, + --sources = { -- Sources to configure + --["null-ls"] = { -- Name of source + --ignore = true, -- Ignore notifications from this source + --}, + --}, + debug = { + logging = false, -- whether to enable logging, for debugging + strict = false, -- whether to interpret LSP strictly + }, +}) diff --git a/common/config/nvim/lua/plugins/fzf.lua b/common/config/nvim/lua/plugins/fzf.lua new file mode 100644 index 0000000..5675e9f --- /dev/null +++ b/common/config/nvim/lua/plugins/fzf.lua @@ -0,0 +1,60 @@ +--vim.cmd([[ +-- let g:fzf_history_dir = '~/.local/share/fzf-history' +-- map <leader>z :FZF<CR> +-- map <leader>a :Files<CR> +-- map <leader>l :Lines<CR> +-- map <leader>L :BLines<CR> +-- map <leader>B :Buffers<CR> +-- map <leader>h :History:<CR> +-- nnoremap <leader>g :Rg<CR> +-- "nnoremap <leader>t :Tags<CR> +-- nnoremap <leader>m :Marks<CR> +-- " This is the default extra key bindings +-- let g:fzf_action = { +-- \ 'ctrl-t': 'tab split', +-- \ 'ctrl-x': 'split', +-- \ 'ctrl-y': 'vsplit' } +-- let g:fzf_tags_command = 'ctags -R' +-- " Border color +-- let g:fzf_layout = {'up':'~90%', 'window': { 'width': 0.8, 'height': 0.8,'yoffset':0.5,'xoffset': 0.5, 'highlight': 'Todo', 'border': 'sharp' } } +-- let $FZF_DEFAULT_OPTS = '--layout=reverse --info=inline' +-- let $FZF_DEFAULT_COMMAND="rg --files --hidden" +-- " Customize fzf colors to match your color scheme +-- let g:fzf_colors = +-- \ { 'fg': ['fg', 'Normal'], +-- \ 'bg': ['bg', 'Normal'], +-- \ 'hl': ['fg', 'Comment'], +-- \ 'fg+': ['fg', 'CursorLine', 'CursorColumn', 'Normal'], +-- \ 'bg+': ['bg', 'CursorLine', 'CursorColumn'], +-- \ 'hl+': ['fg', 'Statement'], +-- \ 'info': ['fg', 'PreProc'], +-- \ 'border': ['fg', 'Ignore'], +-- \ 'prompt': ['fg', 'Conditional'], +-- \ 'pointer': ['fg', 'Exception'], +-- \ 'marker': ['fg', 'Keyword'], +-- \ 'spinner': ['fg', 'Label'], +-- \ 'header': ['fg', 'Comment'] } +-- " Get Files +-- command! -bang -nargs=? -complete=dir Files +-- \ call fzf#vim#files(<q-args>, fzf#vim#with_preview({'options': ['--layout=reverse', '--info=inline']}), <bang>0) +-- " Get text in files with Rg +-- command! -bang -nargs=* Rg +-- \ call fzf#vim#grep( +-- \ 'rg --column --line-number --no-heading --color=always --smart-case '.shellescape(<q-args>), 1, +-- \ fzf#vim#with_preview(), <bang>0) +-- " Ripgrep advanced +-- function! RipgrepFzf(query, fullscreen) +-- let command_fmt = 'rg --column --line-number --no-heading --color=always --smart-case %s || true' +-- let initial_command = printf(command_fmt, shellescape(a:query)) +-- let reload_command = printf(command_fmt, '{q}') +-- let spec = {'options': ['--phony', '--query', a:query, '--bind', 'change:reload:'.reload_command]} +-- call fzf#vim#grep(initial_command, 1, fzf#vim#with_preview(spec), a:fullscreen) +-- endfunction +-- command! -nargs=* -bang RG call RipgrepFzf(<q-args>, <bang>0) +-- " Git grep +-- command! -bang -nargs=* GGrep +-- \ call fzf#vim#grep( +-- \ 'git grep --line-number '.shellescape(<q-args>), 0, +-- \ fzf#vim#with_preview({'dir': systemlist('git rev-parse --show-toplevel')[0]}), <bang>0) +-- command! -bang FM call fzf#run(fzf#wrap({'source': 'cat ~/.fzf-marks | sed "s/.*: \(.*\)$/\1/" | sed "s#~#${HOME}#"', 'sink': 'lcd'}, <bang>0)) +--]]) diff --git a/common/config/nvim/lua/plugins/gitsigns.lua b/common/config/nvim/lua/plugins/gitsigns.lua new file mode 100644 index 0000000..8fbdae1 --- /dev/null +++ b/common/config/nvim/lua/plugins/gitsigns.lua @@ -0,0 +1,47 @@ +require("gitsigns").setup({ + signs = { + --add = { + -- hl = "GitSignsAdd", + -- text = "▍", --│ + -- numhl = "GitSignsAddNr", + -- linehl = "GitSignsAddLn", + --}, + --change = { + -- hl = "GitSignsChange", + -- text = "▍", --│ + -- numhl = "GitSignsChangeNr", + -- linehl = "GitSignsChangeLn", + --}, + delete = { + hl = "GitSignsDelete", + text = "▁", --_━─ + numhl = "GitSignsDeleteNr", + linehl = "GitSignsDeleteLn", + }, + topdelete = { + hl = "GitSignsDelete", + text = "▔", --‾ + numhl = "GitSignsDeleteNr", + linehl = "GitSignsDeleteLn", + }, + changedelete = { + hl = "GitSignsDelete", + text = "~", + numhl = "GitSignsChangeNr", + linehl = "GitSignsChangeLn", + }, + }, + current_line_blame = true, + }) + +vim.api.nvim_command("highlight DiffAdd guibg=none guifg=#21c7a8") +vim.api.nvim_command("highlight DiffModified guibg=none guifg=#82aaff") +vim.api.nvim_command("highlight DiffDelete guibg=none guifg=#fc514e") +vim.api.nvim_command("highlight DiffText guibg=none guifg=#fc514e") +vim.cmd([[ +hi link GitSignsAdd DiffAdd +hi link GitSignsChange DiffModified +hi link GitSignsDelete DiffDelete +hi link GitSignsTopDelete DiffDelete +hi link GitSignsChangedDelete DiffDelete +]]) diff --git a/common/config/nvim/lua/plugins/goto-preview.lua b/common/config/nvim/lua/plugins/goto-preview.lua new file mode 100644 index 0000000..d4d2c67 --- /dev/null +++ b/common/config/nvim/lua/plugins/goto-preview.lua @@ -0,0 +1,18 @@ +require('goto-preview').setup { + width = 120; -- Width of the floating window + height = 15; -- Height of the floating window + border = {"↖", "─" ,"┐", "│", "┘", "─", "└", "│"}; -- Border characters of the floating window + default_mappings = false; -- Bind default mappings + debug = false; -- Print debug information + opacity = nil; -- 0-100 opacity level of the floating window where 100 is fully transparent. + resizing_mappings = false; -- Binds arrow keys to resizing the floating window. + post_open_hook = nil; -- A function taking two arguments, a buffer and a window to be ran as a hook. + references = { -- Configure the telescope UI for slowing the references cycling window. + telescope = require("telescope.themes").get_dropdown({ hide_preview = false }) + }; + -- These two configs can also be passed down to the goto-preview definition and implementation calls for one off "peak" functionality. + focus_on_open = true; -- Focus the floating window when opening it. + dismiss_on_move = false; -- Dismiss the floating window when moving the cursor. + force_close = true, -- passed into vim.api.nvim_win_close's second argument. See :h nvim_win_close + bufhidden = "wipe", -- the bufhidden option to set on the floating window. See :h bufhidden +} diff --git a/common/config/nvim/lua/plugins/hardtime.lua b/common/config/nvim/lua/plugins/hardtime.lua new file mode 100644 index 0000000..cb03468 --- /dev/null +++ b/common/config/nvim/lua/plugins/hardtime.lua @@ -0,0 +1,29 @@ +local hardtime = require('hardtime') + +hardtime.setup({ + -- hardtime config here + enabled = true, + restriction_mode = 'hint', + disabled_filetypes = { 'qf', 'netrw', 'NvimTree', 'NvimTree_1', 'lazy', 'mason', 'oil', 'dashboard' }, + disable_mouse = false, + disabled_keys = { + ['<Up>'] = {}, + ['<Down>'] = {}, + ['<Left>'] = {}, + ['<Right>'] = {}, + }, +}) + +-- Function to toggle the hardtime state and echo a message +local hardtime_enabled = true + +function ToggleHardtime() + hardtime.toggle() + hardtime_enabled = not hardtime_enabled + local message = hardtime_enabled and 'hardtime on' or 'hardtime off' + vim.cmd('echo "' .. message .. '"') +end + +return { + ToggleHardtime = ToggleHardtime, +} diff --git a/common/config/nvim/lua/plugins/harpoon.lua b/common/config/nvim/lua/plugins/harpoon.lua new file mode 100644 index 0000000..784ee0b --- /dev/null +++ b/common/config/nvim/lua/plugins/harpoon.lua @@ -0,0 +1,34 @@ +require("harpoon").setup({ + menu = { + width = vim.api.nvim_win_get_width(0) - 4, + }, + --keys = { + -- { "mt", function() require("harpoon.mark").toggle_file() end, desc = "Toggle File" }, + -- { "mm", function() require("harpoon.ui").toggle_quick_menu() end, desc = "Harpoon Menu" }, + -- { "mc", function() require("harpoon.cmd-ui").toggle_quick_menu() end, desc = "Command Menu" }, + -- --{ "<leader>1", function() require("harpoon.ui").nav_file(1) end, desc = "File 1" }, + -- --{ "<leader>2", function() require("harpoon.ui").nav_file(2) end, desc = "File 2" }, + -- --{ "<leader>3", function() require("harpoon.term").gotoTerminal(1) end, desc = "Terminal 1" }, + -- --{ "<leader>4", function() require("harpoon.term").gotoTerminal(2) end, desc = "Terminal 2" }, + -- --{ "<leader>5", function() require("harpoon.term").sendCommand(1,1) end, desc = "Command 1" }, + -- --{ "<leader>6", function() require("harpoon.term").sendCommand(1,2) end, desc = "Command 2" }, + --}, +}) +vim.api.nvim_set_keymap("n", "<leader>ma", ":lua require('harpoon.mark').add_file()<CR>", {}) +vim.api.nvim_set_keymap("n", "<leader>mt", ":lua require('harpoon.mark').toggle_file()<CR>", {}) +vim.api.nvim_set_keymap("n", "<leader>mq", ":lua require('harpoon.ui').toggle_quick_menu()<CR>", {}) +vim.api.nvim_set_keymap("n", "<leader>mh", ":lua require('harpoon.ui').nav_file(1)<CR>", {}) +vim.api.nvim_set_keymap("n", "<leader>mj", ":lua require('harpoon.ui').nav_file(2)<CR>", {}) +vim.api.nvim_set_keymap("n", "<leader>mk", ":lua require('harpoon.ui').nav_file(3)<CR>", {}) +vim.api.nvim_set_keymap("n", "<leader>ml", ":lua require('harpoon.ui').nav_file(4)<CR>", {}) + +--local mark = require("harpoon.mark") +--local ui = require("harpoon.ui") +-- +--vim.keymap.set("n", "<leader>a", mark.add_file) +--vim.keymap.set("n", "<C-e>", ui.toggle_quick_menu) +-- +--vim.keymap.set("n", "<C-h>", function() ui.nav_file(1) end) +--vim.keymap.set("n", "<C-t>", function() ui.nav_file(2) end) +--vim.keymap.set("n", "<C-n>", function() ui.nav_file(3) end) +--vim.keymap.set("n", "<C-s>", function() ui.nav_file(4) end) diff --git a/common/config/nvim/lua/plugins/heirline.lua b/common/config/nvim/lua/plugins/heirline.lua new file mode 100644 index 0000000..c41aff3 --- /dev/null +++ b/common/config/nvim/lua/plugins/heirline.lua @@ -0,0 +1,1290 @@ +local conditions = require('heirline.conditions') +local utils = require('heirline.utils') + +local colors = { + --bg = "#23232e", + bg = nil, + nobg = 'NONE', + white = '#f8f8f2', + black = '#000000', + darkgray = '#23232e', + gray = '#2d2b3a', + lightgray = '#d6d3ea', + pink = '#f92672', + green = '#50fa7b', + blue = '#39BAE6', + yellow = '#f1fa8c', + orange = '#ffb86c', + purple = '#BF40BF', + violet = '#7F00FF', + red = '#ff5555', + cyan = '#66d9eC', + diag = { + warn = utils.get_highlight('DiagnosticSignWarn').fg, + error = utils.get_highlight('DiagnosticSignError').fg, + hint = utils.get_highlight('DiagnosticSignHint').fg, + info = utils.get_highlight('DiagnosticSignInfo').fg, + }, + git = { + active = '#f34f29', + del = '#ff5555', + add = '#50fa7b', + change = '#ae81ff', + }, +} + +require('heirline').load_colors(colors) + +local Align = { provider = '%=', hl = { bg = colors.bg } } +local Space = { provider = ' ', hl = { bg = colors.bg } } +local Tab = { provider = ' ' } +local LeftSpace = { provider = '' } +local RightSpace = { provider = '' } + +local ViMode = { + init = function(self) + self.mode = vim.fn.mode(1) + --if not self.once then + -- vim.cmd("au ModeChanged *:*o redrawstatus") + --end + --self.once = true + end, + static = { + mode_names = { + n = ' NORMAL ', + no = 'PENDING ', + nov = ' N? ', + noV = ' N? ', + ['no\22'] = ' N? ', + niI = ' Ni ', + niR = ' Nr ', + niV = ' Nv ', + nt = 'TERMINAL', + v = ' VISUAL ', + vs = ' Vs ', + V = ' V·LINE ', + ['\22'] = 'V·BLOCK ', + ['\22s'] = 'V·BLOCK ', + s = ' SELECT ', + S = ' S·LINE ', + ['\19'] = 'S·BLOCK ', + i = ' INSERT ', + ix = 'insert x', + ic = 'insert c', + R = 'REPLACE ', + Rc = ' Rc ', + Rx = ' Rx ', + Rv = 'V·REPLACE ', + Rvc = ' Rv ', + Rvx = ' Rv ', + c = 'COMMAND ', + cv = ' VIM EX ', + ce = ' EX ', + r = ' PROMPT ', + rm = ' MORE ', + ['r?'] = 'CONFIRM ', + ['!'] = ' SHELL ', + t = 'TERMINAL', + }, + }, + provider = function(self) + return ' %2(' .. self.mode_names[self.mode] .. '%) ' + end, + hl = function(self) + return { fg = 'colors.black', bg = self.mode_color, bold = true } + end, + update = { + 'ModeChanged', + 'VimEnter', + pattern = '*:*', + callback = vim.schedule_wrap(function() + vim.cmd('redrawstatus') + end), + }, +} + +-- LSP +local LSPActive = { + condition = conditions.lsp_attached, + update = { 'LspAttach', 'LspDetach' }, + provider = function() + local buf_clients = vim.lsp.buf_get_clients() + local buf_client_names = {} + + -- add client + for _, client in pairs(buf_clients) do + if client.name ~= 'null-ls' then + table.insert(buf_client_names, client.name) + end + end + return '⚙️ ' .. table.concat(buf_client_names, '') + end, + hl = { fg = colors.lightgray, bold = false }, +} +local Navic = { + condition = function() + return require('nvim-navic').is_available() + end, + static = { + -- create a type highlight map + type_hl = { + File = 'Directory', + Module = '@include', + Namespace = '@namespace', + Package = '@include', + Class = '@structure', + Method = '@method', + Property = '@property', + Field = '@field', + Constructor = '@constructor', + Enum = '@field', + Interface = '@type', + Function = '@function', + Variable = '@variable', + Constant = '@constant', + String = '@string', + Number = '@number', + Boolean = '@boolean', + Array = '@field', + Object = '@type', + Key = '@keyword', + Null = '@comment', + EnumMember = '@field', + Struct = '@structure', + Event = '@keyword', + Operator = '@operator', + TypeParameter = '@type', + }, + -- bit operation dark magic, see below... + enc = function(line, col, winnr) + return bit.bor(bit.lshift(line, 16), bit.lshift(col, 6), winnr) + end, + -- line: 16 bit (65535); col: 10 bit (1023); winnr: 6 bit (63) + dec = function(c) + local line = bit.rshift(c, 16) + local col = bit.band(bit.rshift(c, 6), 1023) + local winnr = bit.band(c, 63) + return line, col, winnr + end, + }, + init = function(self) + local data = require('nvim-navic').get_data() or {} + local children = {} + -- create a child for each level + for i, d in ipairs(data) do + -- encode line and column numbers into a single integer + local pos = self.enc(d.scope.start.line, d.scope.start.character, self.winnr) + local child = { + { + provider = d.icon, + hl = self.type_hl[d.type], + }, + { + -- escape `%`s (elixir) and buggy default separators + provider = d.name:gsub('%%', '%%%%'):gsub('%s*->%s*', ''), + -- highlight icon only or location name as well + -- hl = self.type_hl[d.type], + + on_click = { + -- pass the encoded position through minwid + minwid = pos, + callback = function(_, minwid) + -- decode + local line, col, winnr = self.dec(minwid) + vim.api.nvim_win_set_cursor(vim.fn.win_getid(winnr), { line, col }) + end, + name = 'heirline_navic', + }, + }, + } + -- add a separator only if needed + if #data > 1 and i < #data then + table.insert(child, { + provider = ' > ', + hl = { fg = 'bright_fg' }, + }) + end + table.insert(children, child) + end + -- instantiate the new child, overwriting the previous one + self.child = self:new(children, 1) + end, + -- evaluate the children containing navic components + provider = function(self) + return self.child:eval() + end, + hl = { fg = 'gray' }, + update = 'CursorMoved', +} + +-- Diagnostics +local Diagnostics = { + condition = conditions.has_diagnostics, + static = { + error_icon = vim.fn.sign_getdefined('DiagnosticSignError')[1].text, + warn_icon = vim.fn.sign_getdefined('DiagnosticSignWarn')[1].text, + info_icon = vim.fn.sign_getdefined('DiagnosticSignInfo')[1].text, + hint_icon = vim.fn.sign_getdefined('DiagnosticSignHint')[1].text, + }, + init = function(self) + self.errors = #vim.diagnostic.get(0, { severity = vim.diagnostic.severity.ERROR }) + self.warnings = #vim.diagnostic.get(0, { severity = vim.diagnostic.severity.WARN }) + self.hints = #vim.diagnostic.get(0, { severity = vim.diagnostic.severity.HINT }) + self.info = #vim.diagnostic.get(0, { severity = vim.diagnostic.severity.INFO }) + end, + update = { 'DiagnosticChanged', 'BufEnter' }, + { + provider = function(self) + -- 0 is just another output, we can decide to print it or not! + return self.errors > 0 and (self.error_icon .. self.errors .. ' ') + end, + hl = { fg = colors.diag.error, bg = colors.bg }, + }, + { + provider = function(self) + return self.warnings > 0 and (self.warn_icon .. self.warnings .. ' ') + end, + hl = { fg = colors.diag.warn, bg = colors.bg }, + }, + { + provider = function(self) + return self.info > 0 and (self.info_icon .. self.info .. ' ') + end, + hl = { fg = colors.diag.info, bg = colors.bg }, + }, + { + provider = function(self) + return self.hints > 0 and (self.hint_icon .. self.hints) + end, + hl = { fg = colors.diag.hint, bg = colors.bg }, + }, + on_click = { + callback = function() + require('trouble').toggle({ mode = 'document_diagnostics' }) + -- or + -- vim.diagnostic.setqflist() + end, + name = 'heirline_diagnostics', + }, +} + +-- Git +-- For the ones who're not (too) afraid of changes! Uses gitsigns. +local Git = { + condition = conditions.is_git_repo, + init = function(self) + self.status_dict = vim.b.gitsigns_status_dict + self.has_changes = self.status_dict.added ~= 0 or self.status_dict.removed ~= 0 or self.status_dict.changed ~= 0 + end, + --{ + -- -- git branch name + -- provider = function(self) + -- --return ' ' .. self.status_dict.head + -- return ' ' .. self.status_dict.head + -- end, + -- --hl = { bold = true }, + -- hl = { fg = colors.git.active, bold = true, bg = colors.bg }, + --}, + -- You could handle delimiters, icons and counts similar to Diagnostics + { + -- git branch icon + provider = function() + return ' ' + end, + hl = { fg = colors.git.active, bg = colors.bg }, + }, + + { + -- git branch name + provider = function(self) + return self.status_dict.head + end, + hl = { fg = colors.white, bg = colors.bg }, + }, + + { + condition = function(self) + return self.has_changes + end, + --provider = "(" + provider = '', + }, + { + provider = function(self) + local count = self.status_dict.added or 0 + --return count > 0 and ("+" .. count) + return count > 0 and (' ' .. count) + end, + --hl = { fg = "git_add" }, + hl = { fg = colors.git.add, bg = colors.bg }, + }, + { + provider = function(self) + local count = self.status_dict.removed or 0 + --return count > 0 and ("-" .. count) + return count > 0 and (' ' .. count) + end, + --hl = { fg = "git_del" }, + hl = { fg = colors.git.del, bg = colors.bg }, + }, + { + provider = function(self) + local count = self.status_dict.changed or 0 + --return count > 0 and ("~" .. count) + return count > 0 and (' ' .. count) + end, + --hl = { fg = "git_change" }, + hl = { fg = colors.git.change, bg = colors.bg }, + }, + --{ + -- condition = function(self) + -- return self.has_changes + -- end, + -- provider = ")", + --}, + on_click = { + callback = function() + -- If you want to use Fugitive: + -- vim.cmd("G") + + -- If you prefer Lazygit + -- use vim.defer_fn() if the callback requires + -- opening of a floating window + -- (this also applies to telescope) + vim.defer_fn(function() + vim.cmd('Lazygit') + end, 100) + end, + name = 'heirline_git', + }, +} + +-- Debugger +-- Display informations from nvim-dap! +-- Note that we add spaces separately, so that only the icon characters will be clickable +--local DAPMessages = { +-- condition = function() +-- local session = require("dap").session() +-- return session ~= nil +-- end, +-- provider = function() +-- return " " .. require("dap").status() .. " " +-- end, +-- hl = "Debug", +-- { +-- provider = "", +-- on_click = { +-- callback = function() +-- require("dap").step_into() +-- end, +-- name = "heirline_dap_step_into", +-- }, +-- }, +-- { provider = " " }, +-- { +-- provider = "", +-- on_click = { +-- callback = function() +-- require("dap").step_out() +-- end, +-- name = "heirline_dap_step_out", +-- }, +-- }, +-- { provider = " " }, +-- { +-- provider = " ", +-- on_click = { +-- callback = function() +-- require("dap").step_over() +-- end, +-- name = "heirline_dap_step_over", +-- }, +-- }, +-- { provider = " " }, +-- { +-- provider = "ﰇ", +-- on_click = { +-- callback = function() +-- require("dap").run_last() +-- end, +-- name = "heirline_dap_run_last", +-- }, +-- }, +-- { provider = " " }, +-- { +-- provider = "", +-- on_click = { +-- callback = function() +-- require("dap").terminate() +-- require("dapui").close({}) +-- end, +-- name = "heirline_dap_close", +-- }, +-- }, +-- { provider = " " }, +-- -- icons: ﰇ +--} + +-- Tests +-- This requires the great ultest. +--local UltTest = { +-- condition = function() +-- return vim .api.nvim_call_function("ultest#is_test_file", {}) ~= 0 +-- end, +-- static = { +-- passed_icon = vim.fn.sign_getdefined("test_pass")[1].text, +-- failed_icon = vim.fn.sign_getdefined("test_fail")[1].text, +-- passed_hl = { fg = utils.get_highlight("UltestPass").fg }, +-- failed_hl = { fg = utils.get_highlight("UltestFail").fg }, +-- }, +-- init = function(self) +-- self.status = vim.api.nvim_call_function("ultest#status", {}) +-- end, +-- +-- -- again, if you'd like icons and numbers to be colored differently, +-- -- just split the component in two +-- { +-- provider = function(self) +-- return self.passed_icon .. self.status.passed .. " " +-- end, +-- hl = function(self) +-- return self.passed_hl +-- end, +-- }, +-- { +-- provider = function(self) +-- return self.failed_icon .. self.status.failed .. " " +-- end, +-- hl = function(self) +-- return self.failed_hl +-- end, +-- }, +-- { +-- provider = function(self) +-- return "of " .. self.status.tests - 1 +-- end, +-- }, +--} + +-- FileNameBlock: FileIcon, FileName and friends +local FileNameBlock = { + -- let's first set up some attributes needed by this component and it's children + init = function(self) + self.filename = vim.api.nvim_buf_get_name(0) + end, + --hl = { fg = utils.get_highlight("Statusline").fg, bold = true, bg = colors.bg }, + hl = { bg = colors.bg }, +} + +-- FileIcon, FileName, FileFlags and FileNameModifier +local FileIcon = { + init = function(self) + local filename = self.filename + local extension = vim.fn.fnamemodify(filename, ':e') + self.icon, self.icon_color = require('nvim-web-devicons').get_icon_color(filename, extension, { default = true }) + end, + provider = function(self) + return self.icon and (self.icon .. ' ') + end, + hl = function(self) + return { fg = self.icon_color, bg = colors.bg } + end, +} + +local FileName = { + provider = function(self) + -- first, trim the pattern relative to the current directory. For other + -- options, see :h filename-modifers + local filename = vim.fn.fnamemodify(self.filename, ':.') + if filename == '' then + return 'No Name' + end + -- now, if the filename would occupy more than 1/4th of the available + -- space, we trim the file path to its initials + -- See Flexible Components section below for dynamic truncation + if not conditions.width_percent_below(#filename, 0.25) then + filename = vim.fn.pathshorten(filename) + end + return filename + end, + --hl = { fg = utils.get_highlight("Statusline").fg, bold = false, bg = colors.bg }, + hl = { fg = colors.white, bold = false, bg = colors.bg }, +} + +local FileFlags = { + { + provider = function() + if vim.bo.modified then + return ' [+]' -- ±[+] + end + end, + hl = { fg = colors.green, bg = colors.bg }, + }, + { + provider = function() + if not vim.bo.modifiable or vim.bo.readonly then + return ' ' + end + end, + --hl = { fg = colors.orange }, + hl = { fg = colors.orange, bold = true, bg = colors.bg }, + }, +} + +local FileNameModifier = { + hl = function() + if vim.bo.modified then + return { fg = colors.green, bold = false, force = true } + end + end, +} + +-- FileType, FileEncoding and FileFormat +local FileType = { + provider = function() + return vim.bo.filetype + end, + hl = { fg = colors.white, bold = false, bg = colors.bg }, +} + +local FileEncoding = { + Space, + provider = function() + local enc = (vim.bo.fenc ~= '' and vim.bo.fenc) or vim.o.enc -- :h 'enc' + return enc:lower() + end, + --hl = { fg = utils.get_highlight("Statusline").fg, bold = true, bg = colors.bg }, + hl = { bg = colors.bg, bold = false }, +} + +local FileFormat = { + provider = function() + local fmt = vim.bo.fileformat + --return fmt ~= "unix" and fmt:upper() + return fmt ~= 'unix' and fmt:lower() + end, + hl = { fg = utils.get_highlight('Statusline').fg, bold = true, bg = colors.bg }, +} + +-- FileSize and FileLastModified +local FileSize = { + provider = function() + -- stackoverflow, compute human readable file size + local suffix = { 'b', 'k', 'M', 'G', 'T', 'P', 'E' } + local fsize = vim.fn.getfsize(vim.api.nvim_buf_get_name(0)) + fsize = (fsize < 0 and 0) or fsize + if fsize < 1024 then + return fsize .. suffix[1] + end + local i = math.floor((math.log(fsize) / math.log(1024))) + return string.format('%.2g%s', fsize / math.pow(1024, i), suffix[i + 1]) + end, + hl = { fg = utils.get_highlight('Statusline').fg, bold = true, bg = colors.bg }, +} + +local FileLastModified = { + -- did you know? Vim is full of functions! + provider = function() + local ftime = vim.fn.getftime(vim.api.nvim_buf_get_name(0)) + return (ftime > 0) and os.date('%c', ftime) + end, + hl = { fg = utils.get_highlight('Statusline').fg, bold = true, bg = colors.bg }, +} + +-- Spell +-- Add indicator when spell is set! +local Spell = { + condition = function() + return vim.wo.spell + end, + provider = ' 暈', + hl = { bold = true, fg = colors.yellow }, +} + +local HelpFileName = { + condition = function() + return vim.bo.filetype == 'help' + end, + provider = function() + local filename = vim.api.nvim_buf_get_name(0) + return vim.fn.fnamemodify(filename, ':t') + end, + hl = { fg = colors.blue }, +} + +local SearchCount = { + condition = function() + return vim.v.hlsearch ~= 0 and vim.o.cmdheight == 0 + end, + init = function(self) + local ok, search = pcall(vim.fn.searchcount) + if ok and search.total then + self.search = search + end + end, + provider = function(self) + local search = self.search + return string.format('[%d/%d]', search.current, math.min(search.total, search.maxcount)) + end, +} + +local MacroRec = { + condition = function() + return vim.fn.reg_recording() ~= '' and vim.o.cmdheight == 0 + end, + provider = ' ', + hl = { fg = 'orange', bold = true }, + utils.surround({ '[', ']' }, nil, { + provider = function() + return vim.fn.reg_recording() + end, + hl = { fg = 'green', bold = true }, + }), + update = { + 'RecordingEnter', + 'RecordingLeave', + }, +} + +local ShowCmd = { + condition = function() + return vim.o.cmdheight == 0 + end, + provider = ':%3.5(%S%)', +} + +local cursor_location = { + { provider = '%1(%4l:%-3(%c%)%) %*', hl = { fg = colors.black, bold = true } }, +} + +local Ruler = { cursor_location } + +--utils.make_flexible_component( +-- 3, +-- { Ruler, hl = { fg = utils.get_highlight("statusline").bg, force = true } }, +-- { provider = "%<" } +--), +--local cursor_location = { +-- { provider = "%7(%l:%c%) ", hl = { bold = true } }, +-- { +-- provider = " ", +-- hl = function(self) +-- local color = self:mode_color() +-- return { fg = color, bold = true } +-- end, +-- }, +--} + +local WordCount = { + condition = function() + return conditions.buffer_matches({ + filetype = { + 'markdown', + 'txt', + 'vimwiki', + }, + }) + end, + Space, + { + provider = function() + return 'W:' .. vim.fn.wordcount().words + end, + }, +} + +-- Working Directory +local WorkDir = { + init = function(self) + self.icon = (vim.fn.haslocaldir(0) == 1 and 'l' or 'g') .. ' ' .. ' ' + local cwd = vim.fn.getcwd(0) + self.cwd = vim.fn.fnamemodify(cwd, ':~') + end, + hl = { fg = 'colors.blue', bold = true }, + flexible = 1, + { + -- evaluates to the full-lenth path + provider = function(self) + local trail = self.cwd:sub(-1) == '/' and '' or '/' + return self.icon .. self.cwd .. trail .. ' ' + end, + }, + { + -- evaluates to the shortened path + provider = function(self) + local cwd = vim.fn.pathshorten(self.cwd) + local trail = self.cwd:sub(-1) == '/' and '' or '/' + return self.icon .. cwd .. trail .. ' ' + end, + }, + { + -- evaluates to "", hiding the component + provider = '', + }, +} + +-- Snippets Indicator +-- This requires ultisnips +--local Snippets = { +-- -- check that we are in insert or select mode +-- condition = function() +-- return vim.tbl_contains({'s', 'i'}, vim.fn.mode()) +-- end, +-- provider = function() +-- local forward = (vim.fn["UltiSnips#CanJumpForwards"]() == 1) and "" or "" +-- local backward = (vim.fn["UltiSnips#CanJumpBackwards"]() == 1) and " " or "" +-- return backward .. forward +-- end, +-- hl = { fg = "red", bold = true }, +--} + +-- let's add the children to our FileNameBlock component +FileNameBlock = utils.insert( + FileNameBlock, + FileIcon, + utils.insert(FileNameModifier, FileName), -- a new table where FileName is a child of FileNameModifier + unpack(FileFlags), -- A small optimisation, since their parent does nothing + { provider = '%<' } -- this means that the statusline is cut here when there's not enough space +) + +local FileInfoBlock = { + -- let's first set up some attributes needed by this component and it's children + init = function(self) + self.filename = vim.api.nvim_buf_get_name(0) + end, +} + +FileInfoBlock = utils.insert( + FileInfoBlock, + Space, + FileIcon, + FileType, + { provider = '%<' } -- this means that the statusline is cut here when there's not enough space +) + +LeftSpace = utils.surround({ '', '' }, function(self) + return self:mode_color() +end, { LeftSpace, hl = { fg = utils.get_highlight('statusline').bg, force = true } }) + +RightSpace = utils.surround({ '', '' }, function(self) + return self:mode_color() +end, { RightSpace, hl = { fg = utils.get_highlight('statusline').bg, force = true } }) + +LSPActive = utils.surround({ '', '' }, function(self) + return self:mode_color() +end, { Space, LSPActive, hl = { bg = colors.darkgray, force = true } }) + +FileInfoBlock = utils.surround({ '', '' }, function(self) + return self:mode_color() +end, { FileInfoBlock, Space, hl = { bg = colors.black, force = true } }) + +ViMode = utils.surround({ '', '' }, function(self) + return self:mode_color() +end, { ViMode, hl = { fg = colors.black, force = true } }) + +Ruler = utils.surround({ '', '' }, function(self) + return self:mode_color() +end, { Ruler, hl = { fg = colors.black, force = true } }) + +local left = { + { RightSpace, hl = { bg = colors.nobg, force = true } }, + { ViMode, hl = { bg = utils.get_highlight('statusline').bg, bold = false } }, + { LeftSpace, hl = { bg = colors.nobg, force = true } }, + { Space, hl = { bg = colors.nobg, force = true } }, + { FileNameBlock, hl = { bg = colors.nobg, force = true } }, + { Space, hl = { bg = colors.nobg, force = true } }, + { Git, hl = { bg = colors.nobg, force = true } }, +} + +local middle = { + { Align, hl = { bg = colors.nobg, force = true } }, + --{ Navic, hl = { bg = colors.nobg, force = true } }, + --{ DAPMessages, hl = { bg = colors.nobg, force = true } }, + { Align, hl = { bg = colors.nobg, force = true } }, +} + +local right = { + --{ Space, hl = { bg = colors.nobg, force = true } }, + { Diagnostics, hl = { bg = colors.nobg, force = true } }, + { Space, hl = { bg = colors.nobg, force = true } }, + { LSPActive, hl = { bg = colors.nobg, force = true } }, + { Space, hl = { bg = colors.nobg, force = true } }, + { FileInfoBlock, hl = { bg = colors.nobg, force = true } }, + { RightSpace, hl = { bg = colors.nobg, force = true } }, + { Ruler, hl = { fg = utils.get_highlight('statusline').bg, bold = false } }, + { LeftSpace, hl = { bg = colors.nobg, force = true } }, +} + +local sections = { left, middle, right } +local DefaultStatusline = { sections } + +local specialleft = { + { RightSpace, hl = { bg = colors.nobg, force = true } }, + { ViMode, hl = { bg = utils.get_highlight('statusline').bg, bold = false } }, + { LeftSpace, hl = { bg = colors.nobg, force = true } }, +} + +local specialmiddle = { + { Align, hl = { bg = colors.nobg, force = true } }, + --{ DAPMessages, hl = { bg = colors.nobg, force = true } }, + { Align, hl = { bg = colors.nobg, force = true } }, +} + +local specialright = { + { RightSpace, hl = { bg = colors.nobg, force = true } }, + { Ruler, hl = { fg = utils.get_highlight('statusline').bg, bold = false } }, + { LeftSpace, hl = { bg = colors.nobg, force = true } }, +} + +local specialsections = { specialleft, specialmiddle, specialright } + +local InactiveStatusline = { + condition = conditions.is_not_active, + --{ FileNameBlock, hl = { bg = colors.nobg, force = true } }, + --{ Align, hl = { bg = colors.nobg, force = true } }, + specialsections, +} + +local SpecialStatusline = { + condition = function() + return conditions.buffer_matches({ + buftype = { 'nofile', 'prompt', 'help', 'quickfix' }, + filetype = { '^git.*', 'fugitive', 'dashboard' }, + }) + end, + specialsections, +} + +--local InactiveStatusline = SpecialStatusline + +local TerminalStatusline = { + condition = function() + return conditions.buffer_matches({ buftype = { 'terminal' } }) + end, + specialsections, +} + +local StatusLine = { + static = { + --mode_colors = { + -- n = colors.blue, + -- i = colors.green, + -- v = colors.purple, + -- V = colors.purple, + -- ["\22"] = colors.purple, + -- c = colors.orange, + -- s = colors.purple, + -- S = colors.purple, + -- ["\19"] = colors.purple, + -- R = colors.red, + -- r = colors.red, + -- ["!"] = colors.orange, + -- t = colors.orange, + --}, + mode_colors = { + n = colors.blue, + no = colors.blue, + nov = colors.blue, + noV = colors.blue, + ['no\22'] = colors.blue, + niI = colors.blue, + niR = colors.blue, + niV = colors.blue, + nt = colors.blue, + v = colors.purple, + vs = colors.purple, + V = colors.purple, + ['\22'] = colors.purple, + ['\22s'] = colors.purple, + s = colors.purple, + S = colors.purple, + ['\19'] = colors.purple, + i = colors.green, + ix = colors.green, + ic = colors.green, + R = colors.red, + Rc = colors.red, + Rx = colors.red, + Rv = colors.red, + Rvc = colors.red, + Rvx = colors.red, + c = colors.orange, + cv = colors.orange, + ce = colors.orange, + r = colors.red, + rm = colors.red, + ['r?'] = colors.red, + ['!'] = colors.orange, + t = colors.orange, + }, + mode_color = function(self) + local mode = conditions.is_active() and vim.fn.mode() or 'n' + return self.mode_colors[mode] + end, + hl = function(self) + local color = self:mode_color() -- here! + return { bg = color } + end, + }, + fallthrough = false, + SpecialStatusline, + TerminalStatusline, + InactiveStatusline, + DefaultStatusline, +} + +-- +--- WinBar +-- +local WinbarFileNameBlock = { + -- let's first set up some attributes needed by this component and it's children + init = function(self) + self.filename = vim.api.nvim_buf_get_name(0) + end, + hl = { bg = colors.bg }, +} + +local WinbarFileName = { + provider = function(self) + -- first, trim the pattern relative to the current directory. For other + -- options, see :h filename-modifers + local filename = vim.fn.fnamemodify(self.filename, ':.') + if filename == '' then + return 'No Name' + end + -- now, if the filename would occupy more than 1/4th of the available + -- space, we trim the file path to its initials + -- See Flexible Components section below for dynamic truncation + if not conditions.width_percent_below(#filename, 0.25) then + filename = vim.fn.pathshorten(filename) + end + return filename + end, + --hl = { fg = utils.get_highlight("Statusline").fg, bold = false, bg = colors.bg }, + hl = { fg = colors.gray, bold = false, bg = colors.bg }, +} + +WinbarFileNameBlock = utils.insert( + WinbarFileNameBlock, + FileIcon, + utils.insert(WinbarFileName), -- a new table where FileName is a child of FileNameModifier + unpack(FileFlags), -- A small optimisation, since their parent does nothing + { provider = '%<' } -- this means that the statusline is cut here when there's not enough space +) + +vim.api.nvim_create_autocmd('User', { + pattern = 'HeirlineInitWinbar', + callback = function(args) + local buf = args.buf + local buftype = vim.tbl_contains({ 'prompt', 'nofile', 'help', 'quickfix' }, vim.bo[buf].buftype) + local filetype = vim.tbl_contains({ 'gitcommit', 'fugitive' }, vim.bo[buf].filetype) + if buftype or filetype then + vim.opt_local.winbar = nil + end + end, +}) + +On_click = { + -- get the window id of the window in which the component was evaluated + minwid = function() + return vim.api.nvim_get_current_win() + end, + callback = function(_, minwid) + -- winid is the window id of the window the component was clicked from + local winid = minwid + -- do something with the window id, e.g.: + local buf = vim.api.nvim_win_get_buf(winid) + -- ... + end, +} + +local CloseButton = { + condition = function(self) + return not vim.bo.modified + end, + -- a small performance improvement: + -- re register the component callback only on layout/buffer changes. + update = { 'WinNew', 'WinClosed', 'BufEnter' }, + { provider = ' ' }, + { + provider = '', + hl = { fg = 'gray' }, + On_click = { + minwid = function() + return vim.api.nvim_get_current_win() + end, + callback = function(_, minwid) + vim.api.nvim_win_close(minwid, true) + end, + name = 'heirline_winbar_close_button', + }, + }, +} + +local Center = { + fallthrough = false, + { + -- Hide the winbar for special buffers + condition = function() + return conditions.buffer_matches({ + buftype = { 'terminal', 'nofile', 'prompt', 'help', 'quickfix' }, + filetype = { 'dap-ui', 'NvimTree', '^git.*', 'fugitive', 'dashboard' }, + }) + end, + init = function() + vim.opt_local.winbar = nil + end, + }, + { + -- A special winbar for terminals + condition = function() + return conditions.buffer_matches({ buftype = { 'terminal' } }) + end, + FileType, + Space, + --TerminalName, + }, + { + -- An inactive winbar for regular files + condition = function() + return not conditions.is_active() + end, + --utils.surround({ "", "" }, colors.nobg, { FileIcon, { WinbarFileName, hl = { fg = colors.gray } }, FileFlags } ), + utils.surround({ '', '' }, colors.nobg, { WinbarFileNameBlock }), + }, + -- A winbar for regular files + utils.surround({ '', '' }, colors.nobg, { FileNameBlock }), +} + +--local WinBar = { Align, Center, Align } +local WinBar = { Space, Center } + +-- TabLine +--local TablineBufnr = { +-- provider = function(self) +-- return tostring(self.bufnr) .. "." +-- end, +-- hl = { fg = colors.white, bold = false }, +---- hl = "Comment", +--} + +-- we redefine the filename component, as we probably only want the tail and not the relative path +local TablineFileName = { + provider = function(self) + -- self.filename will be defined later, just keep looking at the example! + local filename = self.filename + filename = filename == '' and 'No Name' or vim.fn.fnamemodify(filename, ':t') + return filename + end, + hl = function(self) + return { fg = colors.white, bold = self.is_active or self.is_visible, italic = true } + end, +} + +local TablineFileFlags = { + { + provider = function(self) + if vim.bo[self.bufnr].modified then + return ' [+] ' + end + end, + hl = { fg = colors.green }, + }, + { + provider = function(self) + if not vim.bo[self.bufnr].modifiable or vim.bo[self.bufnr].readonly then + return ' ' + end + end, + hl = { fg = 'orange' }, + }, +} + +local TablineFileIcon = { + init = function(self) + local filename = self.filename + local extension = vim.fn.fnamemodify(filename, ':e') + self.icon, self.icon_color = require('nvim-web-devicons').get_icon_color(filename, extension, { default = true }) + end, + provider = function(self) + return self.icon and (' ' .. self.icon .. ' ') + end, + hl = function(self) + return { fg = self.icon_color } + end, +} + +-- Here the filename block finally comes together +local TablineFileNameBlock = { + init = function(self) + self.filename = vim.api.nvim_buf_get_name(self.bufnr) + end, + hl = function(self) + if self.is_active then + return 'TabLineSel' + -- why not? + --elseif not vim.api.nvim_buf_is_loaded(self.bufnr) then + --return { fg = "gray", bg = colors.bg } + else + return 'TabLineFill' + end + end, + on_click = { + callback = function(_, minwid, _, button) + if button == 'm' then -- close on mouse middle click + vim.api.nvim_buf_delete(minwid, { force = false }) + else + vim.api.nvim_win_set_buf(0, minwid) + end + end, + minwid = function(self) + return self.bufnr + end, + name = 'heirline_tabline_buffer_callback', + }, + --TablineBufnr, + TablineFileIcon, + TablineFileName, + TablineFileFlags, +} + +-- a nice "x" button to close the buffer +local TablineCloseButton = { + condition = function(self) + return not vim.api.nvim_buf_get_option(self.bufnr, 'modified') + end, + { provider = ' ' }, + { + provider = ' ', + --hl = { fg = "red", bg = colors.bg }, + hl = { fg = colors.red }, + on_click = { + callback = function(_, minwid) + vim.api.nvim_buf_delete(minwid, { force = false }) + end, + minwid = function(self) + return self.bufnr + end, + name = 'heirline_tabline_close_buffer_callback', + }, + }, +} + +-- The final touch! +local TablineBufferBlock = utils.surround({ '', '' }, function(self) + --local TablineBufferBlock = utils.surround({ "█", "█" }, function(self) + if self.is_active then + return utils.get_highlight('TabLineSel').bg + else + return utils.get_highlight('TabLineFill').bg + end +end, { Tab, TablineFileNameBlock, TablineCloseButton }) + +local BufferLine = utils.make_buflist( + TablineBufferBlock, + { provider = ' ', hl = { fg = colors.white } }, -- left truncation, optional (defaults to "<") + { provider = ' ', hl = { fg = colors.white } } -- right trunctation, also optional (defaults to ...... yep, ">") +-- by the way, open a lot of buffers and try clicking them ;) +) +-- TabList +local Tabpage = { + provider = function(self) + return '%' .. self.tabnr .. 'T ' .. self.tabnr .. ' %T' + end, + hl = function(self) + if not self.is_active then + return 'TabLineFill' + else + return 'TabLineSel' + end + end, +} + +local TabpageClose = { + provider = '%999X %X', + --hl = "TabLine", + hl = { fg = colors.red, bg = colors.bg }, +} + +local TabPages = { + -- only show this component if there's 2 or more tabpages + condition = function() + return #vim.api.nvim_list_tabpages() >= 2 + end, + { + provider = '%=', + }, + utils.make_tablist(Tabpage), + TabpageClose, +} + +-- TabLineOffset +local TabLineOffset = { + condition = function(self) + local win = vim.api.nvim_tabpage_list_wins(0)[1] + local bufnr = vim.api.nvim_win_get_buf(win) + self.winid = win + + if vim.api.nvim_buf_get_option(bufnr, 'filetype') == 'NvimTree' then + self.title = 'NvimTree' + return true + end + end, + provider = function(self) + local title = self.title + local width = vim.api.nvim_win_get_width(self.winid) + local pad = math.ceil((width - #title) / 2) + return string.rep(' ', pad) .. title .. string.rep(' ', pad) + end, + hl = { fg = colors.white, bg = '#333842', bold = true }, + + --hl = function(self) + -- if vim.api.nvim_get_current_win() == self.winid then + -- return 'TablineSel' + -- else + -- return 'TablineFill' + -- end + --end, +} + +local TabLine = { + TabLineOffset, + BufferLine, + TabPages, +} + +require('heirline').setup({ + statusline = StatusLine, + winbar = WinBar, + tabline = TabLine, + --statuscolumn = StatusColumn +}) + +-- Yep, with heirline we're driving manual! +vim.o.showtabline = 2 +vim.cmd([[au FileType * if index(['wipe', 'delete', 'unload'], &bufhidden) >= 0 | set nobuflisted | endif]]) + +local function get_bufs() + return vim.tbl_filter(function(bufnr) + return vim.api.nvim_buf_is_loaded(bufnr) and vim.bo[bufnr].buflisted + end, vim.api.nvim_list_bufs()) +end + +local function goto_buf(index) + local bufs = get_bufs() + if index > #bufs then + index = #bufs + end + vim.api.nvim_win_set_buf(0, bufs[index]) +end + +local function addKey(key, index) + vim.keymap.set('', '<A-' .. key .. '>', function() + goto_buf(index) + end, { noremap = true, silent = true }) +end + +for i = 1, 9 do + addKey(i, i) +end +addKey('0', 10) diff --git a/common/config/nvim/lua/plugins/indent-blankline.lua b/common/config/nvim/lua/plugins/indent-blankline.lua new file mode 100644 index 0000000..25a2da0 --- /dev/null +++ b/common/config/nvim/lua/plugins/indent-blankline.lua @@ -0,0 +1,24 @@ +--local highlight = { +-- "RainbowRed", +-- "RainbowYellow", +-- "RainbowBlue", +-- "RainbowOrange", +-- "RainbowGreen", +-- "RainbowViolet", +-- "RainbowCyan", +--} +-- +--local hooks = require("ibl.hooks") +---- create the highlight groups in the highlight setup hook, so they are reset +---- every time the colorscheme changes +--hooks.register(hooks.type.HIGHLIGHT_SETUP, function() +-- vim.api.nvim_set_hl(0, "RainbowRed", { fg = "#E06C75" }) +-- vim.api.nvim_set_hl(0, "RainbowYellow", { fg = "#E5C07B" }) +-- vim.api.nvim_set_hl(0, "RainbowBlue", { fg = "#61AFEF" }) +-- vim.api.nvim_set_hl(0, "RainbowOrange", { fg = "#D19A66" }) +-- vim.api.nvim_set_hl(0, "RainbowGreen", { fg = "#98C379" }) +-- vim.api.nvim_set_hl(0, "RainbowViolet", { fg = "#C678DD" }) +-- vim.api.nvim_set_hl(0, "RainbowCyan", { fg = "#56B6C2" }) +--end) + +require("ibl").setup({ indent = { highlight = highlight } }) diff --git a/common/config/nvim/lua/plugins/leetcode.lua b/common/config/nvim/lua/plugins/leetcode.lua new file mode 100644 index 0000000..50369e1 --- /dev/null +++ b/common/config/nvim/lua/plugins/leetcode.lua @@ -0,0 +1,68 @@ +---@alias lc.lang +---| "cpp" +---| "java" +---| "python" +---| "python3" +---| "c" +---| "csharp" +---| "javascript" +---| "typescript" +---| "php" +---| "swift" +---| "kotlin" +---| "dart" +---| "golang" +---| "ruby" +---| "scala" +---| "rust" +---| "racket" +---| "erlang" +---| "elixir" + +---@alias lc.sql_lang +---| "pythondata" +---| "mysql" +---| "mssql" +---| "oraclesql" + +---@alias lc.domain +---| "com" +---| "cn" + +---@class lc.UserConfig +local M = { + ---@type lc.domain + domain = 'com', -- For now "com" is the only one supported + + ---@type string + arg = 'leetcode.nvim', + + ---@type lc.lang + lang = 'cpp', + + ---@type lc.sql_lang + sql = 'mysql', + + ---@type string + directory = vim.fn.stdpath('data') .. '/leetcode/', + + ---@type boolean + logging = true, + + console = { + ---@type boolean + open_on_runcode = false, + + size = { + width = '75%', ---@type string | integer + height = '75%', ---@type string | integer + }, + dir = 'row', ---@type "col" | "row" + }, + + description = { + width = '40%', ---@type string | integer + }, +} + +return M diff --git a/common/config/nvim/lua/plugins/loclist.lua b/common/config/nvim/lua/plugins/loclist.lua new file mode 100644 index 0000000..9b72a94 --- /dev/null +++ b/common/config/nvim/lua/plugins/loclist.lua @@ -0,0 +1,18 @@ +local M = {} + +function M.loclist_toggle() + for _, info in ipairs(vim.fn.getwininfo()) do + if info.loclist == 1 then + vim.cmd('lclose') + return + end + end + + if next(vim.fn.getloclist(0)) == nil then + print('loc list empty') + return + end + vim.cmd('lopen') +end + +return M diff --git a/common/config/nvim/lua/plugins/lsp.lua b/common/config/nvim/lua/plugins/lsp.lua new file mode 100644 index 0000000..286e0d2 --- /dev/null +++ b/common/config/nvim/lua/plugins/lsp.lua @@ -0,0 +1,448 @@ +local lspconfig = require("lspconfig") +local mason_lspconfig = require("mason-lspconfig") +local null_ls = require("null-ls") +-- local lsp_lines = require('lsp_lines') +require("mason").setup() +require("mason-null-ls").setup({ handlers = {}, ensure_installed = nil, automatic_installation = true, + automatic_setup = true }) + +local keymap = vim.keymap +local cmd = vim.cmd + +local border = { { "┌", "FloatBorder" }, { "─", "FloatBorder" }, { "┐", "FloatBorder" }, { "│", "FloatBorder" }, + { "┘", "FloatBorder" }, { "─", "FloatBorder" }, { "└", "FloatBorder" }, { "│", "FloatBorder" } } + +-- Set up LSP servers if not done before +if not vim.g.lsp_setup_done then + -- Clear existing LSP clients + for _, bufnr in ipairs(vim.api.nvim_list_bufs()) do + local clients = require("user.mods").get_lsp_clients(bufnr) + + for _, client in ipairs(clients) do + client.stop() + end + end + + local signs = { Error = " ", Warn = "▲", Info = "", Hint = "⚑" } + -- + for type, icon in pairs(signs) do + local hl = "DiagnosticSign" .. type + vim.fn.sign_define(hl, { text = icon, texthl = hl, numhl = hl }) + end + + -- lsp_lines.setup() + + -- vim.keymap.set("n", "g?", function() + -- local lines_enabled = not vim.diagnostic.config().virtual_lines + -- vim.diagnostic.config( + -- { + -- virtual_lines = lines_enabled, + -- virtual_text = not lines_enabled + -- } + -- ) + -- end, { noremap = true, silent = true }) + + vim.diagnostic.config({ + underline = false, + signs = true, + virtual_text = true, -- virtual_lines = { only_current_line = true }, + virtual_lines = false, + float = { + show_header = true, + source = "if_many", -- border = 'rounded', + border = border, + focusable = true, + }, + update_in_insert = false, -- default to false + severity_sort = true, -- default to false + }) + + vim.lsp.handlers["textDocument/publishDiagnostics"] = vim.lsp.with(vim.lsp.diagnostic.on_publish_diagnostics, + { underline = false, virtual_text = false, signs = true, update_in_insert = false }) + + vim.lsp.handlers["textDocument/hover"] = vim.lsp.with(vim.lsp.handlers.hover, { border = "rounded" }) + vim.lsp.handlers["textDocument/signatureHelp"] = vim.lsp.with(vim.lsp.handlers.signature_help, { border = "rounded" }) + + -- Use an on_attach function to only map the following keys after the language server attaches to the current buffer + local on_attach = function(client, bufnr) + -- Enable completion triggered by <c-x><c-o> + vim.api.nvim_buf_set_option(bufnr, "omnifunc", "v:lua.vim.lsp.omnifunc") + local map = function(mode, l, r, opts) + opts = opts or {} + opts.silent = true + opts.noremap = true + opts.buffer = bufnr + keymap.set(mode, l, r, opts) + end + -- Mappings + map("n", "K", "<Cmd>lua vim.lsp.buf.hover()<CR>") + -- map("n", "gd", "<Cmd>lua vim.lsp.buf.definition()<CR>") + map("n", "gd", "<cmd>lua require('goto-preview').goto_preview_definition()<CR>") + -- map("n", "gi", "<Cmd>lua vim.lsp.buf.implementation()<CR>") + map("n", "gi", "<cmd>lua require('goto-preview').goto_preview_implementation()<CR>") + -- map("n", "gr", "<Cmd>lua vim.lsp.buf.references()<CR>") + map("n", "gr", "<cmd>lua require('goto-preview').goto_preview_references()<CR>") + map("n", "gD", "<Cmd>lua vim.lsp.buf.declaration()<CR>") -- most lsp servers don't implement textDocument/Declaration, so gD is useless for now. + map("n", "<leader>k", "<Cmd>lua vim.lsp.buf.signature_help()<CR>") + -- map("n", "gt", "<Cmd>lua vim.lsp.buf.type_definition()<CR>") + map("n", "gt", "<cmd>lua require('goto-preview').goto_preview_type_definition()<CR>") + map("n", "gn", "<Cmd>lua vim.lsp.buf.rename()<CR>") + map("n", "ga", "<Cmd>lua vim.lsp.buf.code_action()<CR>") + map("n", "gf", "<Cmd>lua vim.lsp.buf.format()<CR>") + map("n", "go", "<Cmd>lua vim.diagnostic.open_float()<CR>") + map("n", "<leader>go", + ":call utils#ToggleDiagnosticsOpenFloat()<CR> | :echom ('Toggle Diagnostics Float open/close...')<CR> | :sl! | echo ('')<CR>") + map("n", "gq", "<Cmd>lua vim.diagnostic.setloclist()<CR>") + map("n", "[d", "<Cmd>lua vim.diagnostic.goto_prev()<CR>") + map("n", "]d", "<Cmd>lua vim.diagnostic.goto_next()<CR>") + map("n", "gs", "<Cmd>lua vim.lsp.buf.document_symbol()<CR>") + map("n", "gw", "<Cmd>lua vim.lsp.buf.workspace_symbol()<CR>") + map("n", "<leader>wa", "<Cmd>lua vim.lsp.buf.add_workspace_folder()<CR>") + map("n", "<leader>wr", "<Cmd>lua vim.lsp.buf.remove_workspace_folder()<CR>") + map("n", "<leader>wl", function() + print(vim.inspect(vim.lsp.buf.list_workspace_folders())) + end) + + -- TODO: Use the nicer new API for autocommands + cmd("augroup lsp_aucmds") + if client.server_capabilities.documentHighlightProvider then + cmd("au CursorHold <buffer> lua vim.lsp.buf.document_highlight()") + cmd("au CursorMoved <buffer> lua vim.lsp.buf.clear_references()") + end + cmd("augroup END") + end + + -- Toggle diagnostics visibility + vim.g.diagnostics_visible = true + function _G.toggle_diagnostics() + if vim.g.diagnostics_visible then + vim.g.diagnostics_visible = false + vim.diagnostic.disable() + else + vim.g.diagnostics_visible = true + vim.diagnostic.enable() + end + end + + -- Open float for diagnostics automatically + vim.cmd([[ + augroup OpenFloat + " autocmd CursorHold,CursorHoldI * lua vim.diagnostic.open_float(nil, {focusable = false,}) + autocmd CursorHold * lua vim.diagnostic.open_float(nil, {focusable = false,}) + + augroup END + ]]) + + -- Suppress error messages from lang servers + vim.lsp.set_log_level("debug") + local capabilities = vim.lsp.protocol.make_client_capabilities() + capabilities = require("cmp_nvim_lsp").default_capabilities() + capabilities.textDocument.completion.completionItem.snippetSupport = true + capabilities.offsetEncoding = { "utf-8", "utf-16" } + + local function prefer_null_ls_fmt(client) + client.server_capabilities.documentHighlightProvider = true + client.server_capabilities.documentFormattingProvider = true + on_attach(client) + end + + --local cmp_nvim_lsp = require('cmp_nvim_lsp') + local servers = { + asm_lsp = {}, + bashls = {}, + clangd = { + on_attach = on_attach, + capabilites = capabilities, + cmd = { "clangd", "--offset-encoding=utf-16", "--cross-file-rename", "--header-insertion=never", + "--suggest-missing-includes" }, + init_options = { + clangdFileStatus = true, + }, + root_files = { + ".clangd", + ".clang-tidy", + ".clang-format", + "compile_commands.json", + "compile_flags.txt", + "configure.ac", -- AutoTools + }, + }, + cssls = { filetypes = { "css", "scss", "less", "sass" }, + root_dir = lspconfig.util.root_pattern("package.json", ".git") }, -- ghcide = {}, + html = {}, + jsonls = { prefer_null_ls = true, cmd = { "--stdio" } }, + intelephense = {}, + julials = { + on_new_config = function(new_config, _) + local julia = vim.fn.expand("~/.julia/environments/nvim-lspconfig/bin/julia") + if lspconfig.util.path.is_file(julia) then + new_config.cmd[1] = julia + end + end, + settings = { julia = { format = { indent = 2 } } }, + }, + pyright = { settings = { python = { formatting = { provider = "yapf" }, linting = { pytypeEnabled = true } } } }, + rust_analyzer = { + settings = { + ["rust-analyzer"] = { cargo = { allFeatures = true }, checkOnSave = { command = "clippy", + extraArgs = { "--no-deps" } } }, + }, + }, + dartls = { + cmd = { "dart", "language-server", "--protocol=lsp" }, + filetypes = { "dart" }, + init_options = { + closingLabels = true, + flutterOutline = true, + onlyAnalyzeProjectsWithOpenFiles = true, + outline = true, + suggestFromUnimportedLibraries = true, + }, -- root_dir = root_pattern("pubspec.yaml"), + settings = { dart = { completeFunctionCalls = true, showTodos = true } }, + on_attach = function(client, bufnr) end, + }, + lua_ls = { + on_attach = on_attach, + capabilities = capabilities, + debounce_text_changes = 500, + settings = { + Lua = { + runtime = { version = "LuaJIT", path = vim.split(package.path, ";") }, + diagnostics = { enable = true, globals = { "vim" } }, + workspace = { maxPreload = 2000, preloadFileSize = 50000, checkThirdParty = false }, + }, + }, + }, + sqlls = {}, + tsserver = { + capabilities = require("cmp_nvim_lsp").default_capabilities(vim.lsp.protocol.make_client_capabilities()), + on_attach = function(client) + client.server_capabilities.document_formatting = false + client.server_capabilities.document_range_formatting = false + end, + filetypes = { "javascript", "javascriptreact", "javascript.jsx", "typescript", "typescriptreact", "typescript.tsx" }, + }, + vimls = {}, + yamlls = {}, + } + + mason_lspconfig.setup({ + ensure_installed = servers, -- will be installed by mason + automatic_installation = true, + }) + + -- Your other configurations ... + -- require("lspconfig").dartls.setup({ capabilities = capabilities }) + -- local installed_lsp = mason_lspconfig.ensure_installed + -- local mason_lspconfig = require("mason-lspconfig").ensure_installed + + -- require("lspconfig").setup({ + -- function() + -- for _, lsp in ipairs(installed_lsp) do + -- if + -- lsp ~= "sqls" + -- --and lsp ~= "sumneko_lua" + -- --and lsp ~= "stylelint_lsp" + -- --and lsp ~= "rust_analyzer" + -- --and lsp ~= "sourcekit" + -- and lsp ~= "dartls" + -- then + -- lspconfig[lsp].setup({ + -- on_attach = on_attach, + -- capabilities = capabilities, + -- }) + -- end + -- end + -- end, + -- }) + + for server, config in pairs(servers) do + if config.prefer_null_ls then + if config.on_attach then + local old_on_attach = config.on_attach + config.on_attach = function(client, bufnr) + old_on_attach(client, bufnr) + prefer_null_ls_fmt(client) + end + else + config.on_attach = prefer_null_ls_fmt + end + elseif not config.on_attach then + config.on_attach = on_attach + end + + lspconfig[server].setup(config) + end + + -- null_ls setup + local builtins = null_ls.builtins + local augroup = vim.api.nvim_create_augroup("LspFormatting", {}) + + -- local eslint_opts = { + -- -- condition = function(utils) + -- -- return utils.root_has_file ".eslintrc.js" or utils.root_has_file ".eslintrc" or utils.root_has_file ".eslintrc.json" + -- -- end, + -- -- diagnostics_format = "#{m} [#{c}]", + -- prefer_local = true, + -- } + + -- null_ls.setup({ + local sources = { + -- Diagnostics + builtins.diagnostics.chktex, + -- null_ls.builtins.code_actions.eslint_d, + -- null_ls.builtins.diagnostics.eslint_d, + -- null_ls.builtins.formatting.eslint_d, + -- null_ls.builtins.diagnostics.cppcheck, + -- null_ls.builtins.diagnostics.proselint, + -- null_ls.builtins.diagnostics.pylint, + -- builtins.diagnostics.selene, + builtins.diagnostics.dotenv_linter, + builtins.diagnostics.shellcheck.with({ -- shell script diagnostics + diagnostic_config = { -- see :help vim.diagnostic.config() + underline = true, + virtual_text = false, + signs = true, + update_in_insert = false, + severity_sort = true, + }, + diagnostics_format = "[#{c}] #{m} (#{s})", -- this will run every time the source runs, + -- so you should prefer caching results if possible + }), + builtins.diagnostics.zsh.with({ filetypes = "zsh", "sh" }), + builtins.diagnostics.todo_comments, + builtins.diagnostics.teal, + -- null_ls.builtins.diagnostics.vale, + builtins.diagnostics.vint, + builtins.diagnostics.tidy, + builtins.diagnostics.php, + builtins.diagnostics.phpcs, + builtins.diagnostics.flake8, + builtins.diagnostics.eslint_d.with({ + condition = function(utils) + return utils.root_has_file(".eslintrc.json") + end, + }), + builtins.formatting.eslint_d, + -- null_ls.builtins.diagnostics.write_good.with { filetypes = { 'markdown', 'tex' } }, + + -- Formatting + builtins.formatting.shfmt.with({ filetypes = { "bash", "zsh", "sh" }, extra_args = { "-i", "2", "-ci" } }), + builtins.formatting.shellharden, + builtins.formatting.trim_whitespace.with({ filetypes = { "tmux", "teal", "zsh" } }), -- builtins.formatting.beautysh, + builtins.formatting.beautysh.with({ filetypes = "zsh" }), + builtins.formatting.clang_format.with({ + filetypes = { "c", "cpp", "cs", "java", "cuda", "proto" }, + extra_args = { + "--style", + "{BasedOnStyle: Google, IndentWidth: 4, BreakBeforeBinaryOperators: NonAssignment, AllowShortFunctionsOnASingleLine: None}", + }, + }), + --builtins.formatting.rustfmt, + builtins.formatting.sql_formatter, + -- null_ls.builtins.formatting.cmake_format, + builtins.formatting.isort, + builtins.formatting.htmlbeautifier, -- null_ls.builtins.formatting.prettier, + builtins.formatting.prettierd, + builtins.formatting.prettier.with({ + filetypes = { "javascript", "javascriptreact", "typescript", "typescriptreact", "json", "yaml", "markdown", "html", + "css", "scss", "less", "graphql", "vue", "svelte" }, + extra_args = { "--single-quote", "--tab-width 4", "--print-width 200" }, + }), + -- builtins.formatting.stylua, + -- builtins.formatting.lua_format, + builtins.formatting.stylua.with({ + filetypes = { "lua" }, + command = "stylua", + args = { "--quote_style", "AutoPreferSingle", "--indent-width", "2", "--column-width", "160", "--indent-type", + "Spaces", "-" }, + }), + -- builtins.formatting.dart_format, + builtins.formatting.dart_format.with({ filetypes = { "dart" } }), + builtins.formatting.trim_whitespace, + builtins.formatting.yapf, + -- null_ls.builtins.formatting.black + + -- Code Actions + builtins.code_actions.shellcheck, -- shell script code actions + -- builtins.code_actions.eslint_d.with(eslint_opts), + -- null_ls.builtins.code_actions.refactoring.with { filetypes = { 'javascript', 'typescript', 'lua', 'python', 'c', 'cpp' } }, + builtins.code_actions.gitsigns, + builtins.code_actions.gitrebase, -- Hover + builtins.hover.dictionary, + builtins.hover.printenv, + } + -- }) + -- Linters/Formatters ensure installed + -- for _, pkg_name in ipairs({ + -- "dart-debug-Adaptor", + -- "stylua", + -- "prettier", + -- "prettierd", + -- }) do + + -- Import the builtins table from the null-ls module and store it in the null_ls_sources variable + null_ls.setup({ + sources = sources, + update_in_insert = true, + on_attach = function(client, bufnr) + if client.supports_method("textDocument/formatting") then + vim.api.nvim_clear_autocmds({ group = augroup, buffer = bufnr }) + vim.api.nvim_create_autocmd("BufWritePre", { + group = augroup, + buffer = bufnr, + callback = function() + vim.lsp.buf.format() + end, + }) + end + end, + }) + + -- Install all the null-ls sources using Mason + local registry = require("mason-registry") + for _, source_name in ipairs(sources) do + local ok, pkg = pcall(registry.get_package, source_name) + if ok then + if not pkg:is_installed() then + pkg:install() + end + end + end + -- Loop through the null_ls_sources table and install the packages + -- Install all sources for null-ls + -- local null_ls_sources = require("null-ls").builtins + + -- for _, source_name in ipairs(null_ls_sources) do + -- local ok, pkg = pcall(mason.get_package, source_name) + -- if ok then + -- if not pkg:is_installed() then + -- pkg:install() + -- end + -- end + -- end + vim.api.nvim_create_user_command("NullLsToggle", function() + -- you can also create commands to disable or enable sources + require("null-ls").toggle({}) + end, {}) + + local null_ls_stop = function() + local null_ls_client + local clients = require("user.mods").get_lsp_clients(bufnr) + + for _, client in ipairs(clients) do + if client.name == "null-ls" then + null_ls_client = client + end + end + if not null_ls_client then + return + end + + null_ls_client.stop() + end + + vim.api.nvim_create_user_command("NullLsStop", null_ls_stop, {}) + + vim.g.lsp_setup_done = true +end diff --git a/common/config/nvim/lua/plugins/messages.lua b/common/config/nvim/lua/plugins/messages.lua new file mode 100644 index 0000000..8e46c09 --- /dev/null +++ b/common/config/nvim/lua/plugins/messages.lua @@ -0,0 +1,85 @@ +local M = { + 'Why do programmers prefer dark mode? Because light attracts bugs!', + 'Why did the AI break up with its computer? It found someone with better algorithms!', + "Why do Python programmers prefer snakes? Because they can't stand Java!", + 'Why did the developer go to the beach? To catch some rays and debug JavaScript!', + "Why was the HTML document lonely? It didn't have any <body> to share its content with!", + "Why did the CSS file break up with the HTML file? It couldn't stand the layout!", + 'Why do programmers always mix up Christmas and Halloween? Because Oct 31 == Dec 25!', + 'Why did the computer take up gardening? It wanted to improve its root system!', + 'Why do programmers prefer dark chocolate? It has better byte-size!', + "Why did the developer get mad at their computer? It couldn't understand their emotional code!", + 'Why was the JavaScript developer so good at relationships? They knew how to handle callbacks!', + 'Why did the coder go broke? They lost all their cache!', + 'Why did the SQL query go to therapy? It had too many inner joins!', + 'Why did the programmer plant a light bulb? They wanted to grow a power plant!', + 'Why did the computer keep its drink on the windowsill? It wanted a byte!', + "Why don't programmers like nature? It has too many bugs!", + 'Why did the developer go broke? They spent all their money on keyboard shortcuts!', + 'Why did the computer cross the road? To get to the other website!', + 'Why was the code cold? It left its Windows open!', + 'Why did the coder go to therapy? They had too many issues!', + 'Why was the function sad? It returned null!', + "Why did the programmer quit their job? They didn't get arrays!", + 'Why was the loop so fast? It was in a hurry!', + 'Why was the computer cold? It left its Windows open!', + "Why did the developer stay calm during the crisis? Because they knew how to 'handle' exceptions!", + "Why did the JavaScript developer always smile? Because they had 'callbacks' for everything!", + "Why did the programmer break up with their keyboard? It had too many 'commitment' issues!", + "Why don't Neovim users ever get lost in their text files? Because they always 'find' their way!", + "Why don't Neovim users need a GPS? Because they're experts at 'mapping' their routes!", + 'Why did the Neovim user become a musician? Because they can play the keyboard like a pro!', + "Why don't Neovim users ever lose track of time? Because they have a 'status line' to keep them informed!", + "Why did the Neovim user open a detective agency? Because they have an 'eye' for spotting code errors!", + 'Why did the developer bring a ladder to the coding competition? To take their code to the next level!', + "When your code is running slowly: 'It's not a bug; it's a feature that takes its time.'", + "Why did the programmer go to therapy? Because their code had too many 'issues'!", + "Why was the JavaScript developer sad? Because they didn't 'console' their feelings!", + "Why did the developer get locked out of their own codebase? They forgot the 'key'!", + 'Welcome to Neovim, where plugins multiply faster than rabbits!', + "How many programmers does it take to change a lightbulb? None, that's a hardware problem!", + "When you're debugging and can't find the issue: 'I swear, it was working yesterday!'", + "Why don't programmers trust stairs? Because they're always up to 'something'!", + "When you fix a bug without even trying: 'I guess I'm just that good.'", + 'Why was the computer cold? It left its Windows open!', + "Why do Java developers wear glasses? Because they don't C#!", + "Why did the programmer quit their job? They didn't get arrays!", + "When you write a one-liner that solves a complex problem: 'I am a genius, yes, I am.'", + "When you refactor your code and it breaks everything: 'I've made a huge mistake.'", + "When you accidentally close your editor with unsaved changes: 'Goodbye, cruel world.'", + "When you discover a bug on a Friday afternoon: 'Looks like we're working late again.'", + "When you realize your code from last year: 'Who wrote this junk? Oh, wait...'", + "When you write a comment and six months later can't understand it: 'I speak my own language.'", + "When you join a new project with zero documentation: 'Here be dragons.'", + "When you add a 'TODO' comment and hope someone else will deal with it: 'Not my problem.'", + "Remember, coding is not just about writing code; it's about solving problems.", + 'Stay curious and never stop learning. Technology is always evolving.', + "When debugging, don't guess; use systematic troubleshooting techniques.", + "Keep your code DRY (Don't Repeat Yourself) to make it more maintainable.", + 'Use meaningful variable and function names. Your code should read like a story.', + 'Always test your code thoroughly before deploying it. Automated tests are your friends.', + 'Spend time designing your code before jumping into implementation. Good architecture pays off.', + 'Learn to break down complex problems into smaller, manageable tasks.', + "Code with the future in mind. Write code that's easy to understand and maintain.", + 'Version control is your safety net. Use Git or other VCS systems religiously.', + 'Document your code and processes. It will save you and your team countless hours.', + "Don't optimize prematurely. Measure first, then optimize where it matters.", + "Read other people's code. It's a great way to learn different coding styles and techniques.", + 'Stay organized with your project structure. Consistency makes collaboration smoother.', + 'Take regular breaks to prevent burnout. Your productivity will thank you.', + 'Use comments sparingly but effectively. Explain why, not just what.', + 'Consider pair programming or code reviews to catch issues early and learn from others.', + 'Know when to ask for help. Programming is a team effort.', + "Programming is not just about the code; it's about the problem-solving mindset.", + 'Keep your development environment clean and well-maintained for consistent productivity.', + 'Learn from your mistakes and failures; they are valuable lessons in programming.', + 'When faced with a bug, isolate and reproduce it before attempting to fix it.', + "Why did the developer stay calm during the crisis? Because they knew how to 'handle' exceptions.", + "Why was the JavaScript developer always smiling? Because they had 'callbacks' for everything!", + "Why did the programmer break up with their keyboard? It had too many 'commitment' issues!", + "Margaret Hamilton coined the term 'software engineer.'", + 'Why did the function go to therapy? It had too many issues!', + "Why don't programmers like nature? It has too many bugs!", +} + +return M diff --git a/common/config/nvim/lua/plugins/modify-blend.lua b/common/config/nvim/lua/plugins/modify-blend.lua new file mode 100644 index 0000000..1b2c6d5 --- /dev/null +++ b/common/config/nvim/lua/plugins/modify-blend.lua @@ -0,0 +1,43 @@ +local ui = vim.api.nvim_list_uis()[1] + +local bufnr = vim.api.nvim_create_buf(true, true) +local win = vim.api.nvim_open_win(bufnr, true, { + relative = "editor", + --relative = "cursor", + width = ui.width, + height = ui.height, + anchor = "NE", + row = 10, + col = 10, + style = "minimal", + zindex = 50, +}) + +vim.api.nvim_win_set_option(win, "winblend", 1) + +local blend_start = 15 +local offset = 1 + +CANCEL = false +local timer = vim.loop.new_timer() +timer:start( + 0, + 50, + vim.schedule_wrap(function() + blend_start = blend_start + offset + + if blend_start > 90 then + offset = -1 + elseif blend_start < 10 then + offset = 1 + end + + if CANCEL or not vim.api.nvim_win_is_valid(win) then + timer:close() + timer:stop() + return + end + + vim.cmd([[highlight NormalFloat blend=]] .. tostring(blend_start)) + end) +) diff --git a/common/config/nvim/lua/plugins/navic.lua b/common/config/nvim/lua/plugins/navic.lua new file mode 100644 index 0000000..a95485d --- /dev/null +++ b/common/config/nvim/lua/plugins/navic.lua @@ -0,0 +1,50 @@ +local navic = require("nvim-navic") +--local on_attach = function(client, bufnr) +-- if client.server_capabilities.documentSymbolProvider then +-- navic.attach(client, bufnr) +-- end +--end + +--require("lspconfig").clangd.setup { +-- on_attach = on_attach +--} + +navic.setup { + icons = { + File = " ", + Module = " ", + Namespace = " ", + Package = " ", + Class = " ", + Method = " ", + Property = " ", + Field = " ", + Constructor = " ", + Enum = "練", + Interface = "練", + Function = " ", + Variable = " ", + Constant = " ", + String = " ", + Number = " ", + Boolean = "◩ ", + Array = " ", + Object = " ", + Key = " ", + Null = "ﳠ ", + EnumMember = " ", + Struct = " ", + Event = " ", + Operator = " ", + TypeParameter = " ", + }, + lsp = { + auto_attach = true, + --preference = nil, + }, + highlight = false, + separator = " > ", + depth_limit = 0, + depth_limit_indicator = "..", + safe_output = true +} diff --git a/common/config/nvim/lua/plugins/neodev.lua b/common/config/nvim/lua/plugins/neodev.lua new file mode 100644 index 0000000..f820422 --- /dev/null +++ b/common/config/nvim/lua/plugins/neodev.lua @@ -0,0 +1,29 @@ +require("neodev").setup({ + --library = { plugins = { "nvim-dap-ui" }, types = true }, + --library = { plugins = { "neotest" }, types = true }, + library = { + enabled = true, -- when not enabled, neodev will not change any settings to the LSP server + -- these settings will be used for your Neovim config directory + runtime = true, -- runtime path + types = true, -- full signature, docs and completion of vim.api, vim.treesitter, vim.lsp and others + --plugins = { "neotest" }, + --{ "nvim-dap-ui" }, + --plugins = true, -- installed opt or start plugins in packpath + -- you can also specify the list of plugins to make available as a workspace library + -- plugins = { "nvim-treesitter", "plenary.nvim", "telescope.nvim" }, + plugins = { "nvim-treesitter", "plenary.nvim", "telescope.nvim", "neotest", "nvim-dap-ui" }, + }, + setup_jsonls = true, -- configures jsonls to provide completion for project specific .luarc.json files + -- for your Neovim config directory, the config.library settings will be used as is + -- for plugin directories (root_dirs having a /lua directory), config.library.plugins will be disabled + -- for any other directory, config.library.enabled will be set to false + override = function(root_dir, options) + end, + -- With lspconfig, Neodev will automatically setup your lua-language-server + -- If you disable this, then you have to set {before_init=require("neodev.lsp").before_init} + -- in your lsp start options + lspconfig = true, + -- much faster, but needs a recent built of lua-language-server + -- needs lua-language-server >= 3.6.0 + pathStrict = true, +}) diff --git a/common/config/nvim/lua/plugins/neoscroll.lua b/common/config/nvim/lua/plugins/neoscroll.lua new file mode 100644 index 0000000..d122584 --- /dev/null +++ b/common/config/nvim/lua/plugins/neoscroll.lua @@ -0,0 +1,21 @@ +require("neoscroll").setup({ + easing_function = "quadratic", +}) + +local t = {} +-- Syntax: t[keys] = {function, {function arguments}} +-- Use the "sine" easing function +t["<C-u>"] = { "scroll", { "-vim.wo.scroll", "true", "20", [['cubic']] } } +t["<C-d>"] = { "scroll", { "vim.wo.scroll", "true", "20", [['cubic']] } } +-- Use the "circular" easing function +t["<C-b>"] = { "scroll", { "-vim.api.nvim_win_get_height(0)", "true", "50", [['cubic']] } } +t["<C-f>"] = { "scroll", { "vim.api.nvim_win_get_height(0)", "true", "50", [['cubic']] } } +-- Pass "nil" to disable the easing animation (constant scrolling speed) +t["<C-y>"] = { "scroll", { "-0.10", "false", "100", nil } } +t["<C-e>"] = { "scroll", { "0.10", "false", "100", nil } } +-- When no easing function is provided the default easing function (in this case "quadratic") will be used +t["zt"] = { "zt", { "10" } } +t["zz"] = { "zz", { "10" } } +t["zb"] = { "zb", { "10" } } + +require("neoscroll.config").set_mappings(t) diff --git a/common/config/nvim/lua/plugins/neotest.lua b/common/config/nvim/lua/plugins/neotest.lua new file mode 100644 index 0000000..aa73899 --- /dev/null +++ b/common/config/nvim/lua/plugins/neotest.lua @@ -0,0 +1,11 @@ +require("neotest").setup({ + adapters = { + require("neotest-python")({ + dap = { justMyCode = false }, + }), + require("neotest-plenary"), + require("neotest-vim-test")({ + ignore_file_types = { "python", "vim", "lua" }, + }), + }, +}) diff --git a/common/config/nvim/lua/plugins/notify.lua b/common/config/nvim/lua/plugins/notify.lua new file mode 100644 index 0000000..dcb496a --- /dev/null +++ b/common/config/nvim/lua/plugins/notify.lua @@ -0,0 +1,18 @@ +require('notify').setup({ + background_colour = '#000000', + icons = { + ERROR = '', + WARN = '', + INFO = '', + DEBUG = '', + TRACE = '✎', + }, +}) + +vim.api.nvim_command('hi default link NotifyERRORBody Normal') +vim.api.nvim_command('hi default link NotifyWARNBody Normal') +vim.api.nvim_command('hi default link NotifyINFOBody Normal') +vim.api.nvim_command('hi default link NotifyDEBUGBody Normal') +vim.api.nvim_command('hi default link NotifyTRACEBody Normal') +vim.api.nvim_command('hi default link NotifyLogTime Comment') +vim.api.nvim_command('hi default link NotifyLogTitle Special') diff --git a/common/config/nvim/lua/plugins/nvim-tree.lua b/common/config/nvim/lua/plugins/nvim-tree.lua new file mode 100644 index 0000000..e817c04 --- /dev/null +++ b/common/config/nvim/lua/plugins/nvim-tree.lua @@ -0,0 +1,423 @@ +----------------------------------------------------------- +-- Neovim File Tree Configuration +----------------------------------------------------------- + +--- To see mappings `g?` on nvim-tree +--- To see default mappings `:nvim-tree-default-mappings` + +-- Nvim-Tree.lua advises to do this at the start. +vim.g.loaded_netrw = 1 +vim.g.loaded_netrwPlugin = 1 + +local icons = { + webdev_colors = true, + git_placement = "signcolumn", + modified_placement = "after", + padding = " ", + show = { + file = true, + folder = true, + folder_arrow = true, + git = true, + modified = true, + }, + + glyphs = { + default = "", + symlink = "", + folder = { + arrow_open = "", + arrow_closed = "", + default = " ", + open = " ", + empty = " ", + empty_open = " ", + symlink = "", + symlink_open = "", + }, + + git = { + deleted = "", + unmerged = "", + untracked = "", + unstaged = "", + staged = "", + renamed = "➜", + ignored = "◌", + }, + }, + web_devicons = { + folder = { + enable = true, + color = true, + }, + }, +} + +local renderer = { + group_empty = true, -- default: true. Compact folders that only contain a single folder into one node in the file tree. + highlight_git = false, + full_name = false, + highlight_opened_files = "icon", -- "none" (default), "icon", "name" or "all" + highlight_modified = "icon", -- "none", "name" or "all". Nice and subtle, override the open icon + root_folder_label = ":~:s?$?/..?", + indent_width = 2, + indent_markers = { + enable = true, + inline_arrows = true, + icons = { + corner = "└", + edge = "│", + item = "│", + bottom = "─", + none = " ", + }, + }, + icons = icons, +} +local system_open = { cmd = "zathura" } + +local HEIGHT_RATIO = 0.8 +local WIDTH_RATIO = 0.15 + +local float = { + enable = false, + open_win_config = function() + local screen_w = vim.opt.columns:get() + local screen_h = vim.opt.lines:get() - vim.opt.cmdheight:get() + local window_w = screen_w * WIDTH_RATIO + local window_h = screen_h * HEIGHT_RATIO + local window_w_int = math.floor(window_w) + local window_h_int = math.floor(window_h) + local center_x = (screen_w - window_w) / 2 + local center_y = ((vim.opt.lines:get() - window_h) / 2) - vim.opt.cmdheight:get() + return { + border = "rounded", + relative = "editor", + row = center_y, + col = center_x, + width = window_w_int, + height = window_h_int, + } + end, +} + +local view = { + cursorline = true, + float = float, + --signcolumn = 'no', + --width = function() + -- return math.floor(vim.opt.columns:get() * WIDTH_RATIO) + --end, + width = { max = 38, min = 38 }, + side = "left", +} + +local api = require("nvim-tree.api") +local function on_attach(bufnr) + local function opts(desc) + return { desc = "nvim-tree: " .. desc, buffer = bufnr, noremap = true, silent = true, nowait = true } + end + + local mappings = { + ["<C-]>"] = { api.tree.change_root_to_node, "CD" }, + ["<C-e>"] = { api.node.open.replace_tree_buffer, "Open: In Place" }, + ["<C-k>"] = { api.node.show_info_popup, "Info" }, + ["<C-r>"] = { api.fs.rename_sub, "Rename: Omit Filename" }, + ["<C-t>"] = { api.node.open.tab, "Open: New Tab" }, + ["<C-v>"] = { api.node.open.vertical, "Open: Vertical Split" }, + ["<C-x>"] = { api.node.open.horizontal, "Open: Horizontal Split" }, + ["<BS>"] = { api.node.navigate.parent_close, "Close Directory" }, + -- ["<CR>"] = { api.node.open.edit, "Open" }, + ["<Tab>"] = { api.node.open.preview, "Open Preview" }, + [">"] = { api.node.navigate.sibling.next, "Next Sibling" }, + ["<"] = { api.node.navigate.sibling.prev, "Previous Sibling" }, + ["."] = { api.node.run.cmd, "Run Command" }, + ["-"] = { api.tree.change_root_to_parent, "Up" }, + ["a"] = { api.fs.create, "Create" }, + ["bmv"] = { api.marks.bulk.move, "Move Bookmarked" }, + ["B"] = { api.tree.toggle_no_buffer_filter, "Toggle No Buffer" }, + ["c"] = { api.fs.copy.node, "Copy" }, + -- ["C"] = { api.tree.toggle_git_clean_filter, "Toggle Git Clean" }, + ["[c"] = { api.node.navigate.git.prev, "Prev Git" }, + ["]c"] = { api.node.navigate.git.next, "Next Git" }, + ["d"] = { api.fs.remove, "Delete" }, + ["D"] = { api.fs.trash, "Trash" }, + ["E"] = { api.tree.expand_all, "Expand All" }, + ["e"] = { api.fs.rename_basename, "Rename: Basename" }, + ["]e"] = { api.node.navigate.diagnostics.next, "Next Diagnostic" }, + ["[e"] = { api.node.navigate.diagnostics.prev, "Prev Diagnostic" }, + ["F"] = { api.live_filter.clear, "Clean Filter" }, + ["f"] = { api.live_filter.start, "Filter" }, + ["g?"] = { api.tree.toggle_help, "Help" }, + ["gy"] = { api.fs.copy.absolute_path, "Copy Absolute Path" }, + ["H"] = { api.tree.toggle_hidden_filter, "Toggle Dotfiles" }, + ["I"] = { api.tree.toggle_gitignore_filter, "Toggle Git Ignore" }, + ["J"] = { api.node.navigate.sibling.last, "Last Sibling" }, + ["K"] = { api.node.navigate.sibling.first, "First Sibling" }, + ["m"] = { api.marks.toggle, "Toggle Bookmark" }, + -- ["o"] = { api.node.open.edit, "Open" }, + ["O"] = { api.node.open.no_window_picker, "Open: No Window Picker" }, + ["p"] = { api.fs.paste, "Paste" }, + ["P"] = { api.node.navigate.parent, "Parent Directory" }, + ["q"] = { api.tree.close, "Close" }, + ["r"] = { api.fs.rename, "Rename" }, + ["R"] = { api.tree.reload, "Refresh" }, + ["s"] = { api.node.run.system, "Run System" }, + ["S"] = { api.tree.search_node, "Search" }, + ["U"] = { api.tree.toggle_custom_filter, "Toggle Hidden" }, + ["W"] = { api.tree.collapse_all, "Collapse" }, + ["x"] = { api.fs.cut, "Cut" }, + ["y"] = { api.fs.copy.filename, "Copy Name" }, + ["Y"] = { api.fs.copy.relative_path, "Copy Relative Path" }, + ["<2-LeftMouse>"] = { api.node.open.edit, "Open" }, + ["<2-RightMouse>"] = { api.tree.change_root_to_node, "CD" }, + + -- Mappings migrated from view.mappings.list + ["l"] = { api.node.open.edit, "Open" }, + ["<CR>"] = { api.node.open.edit, "Open" }, + ["o"] = { api.node.open.edit, "Open" }, + ["h"] = { api.node.navigate.parent_close, "Close Directory" }, + ["v"] = { api.node.open.vertical, "Open: Vertical Split" }, + ["C"] = { api.tree.change_root_to_node, "CD" }, + } + for keys, mapping in pairs(mappings) do + vim.keymap.set("n", keys, mapping[1], opts(mapping[2])) + end +end +--api.events.subscribe(api.events.Event.FileCreated, function(file) +-- vim.cmd('edit' .. file.fname) +--end) + +require("nvim-tree").setup({ + --auto_reload_on_write = true, + --create_in_closed_folder = false, + --hijack_cursor = true, + --disable_netrw = true, + --hijack_netrw = true, + --hijack_unnamed_buffer_when_opening = false, + --ignore_buffer_on_setup = false, + update_focused_file = { + enable = true, + update_cwd = true, + update_root = true, + ignore_list = {}, + }, + root_dirs = {}, + --prefer_startup_root = true, + --hijack_directories = { + -- enable = false, + --}, + --respect_buf_cwd = false, + sync_root_with_cwd = true, + --reload_on_bufenter = false, + filesystem_watchers = { + enable = true, + debounce_delay = 50, + ignore_dirs = { "node_modules", ".config/nvm" }, + }, + view = view, + system_open = system_open, + renderer = renderer, + on_attach = on_attach, + notify = { + threshold = vim.log.levels.ERROR, + }, + log = { + enable = true, + truncate = true, + types = { + diagnostics = true, + git = true, + profile = true, + watcher = true, + }, + }, + git = { ignore = false }, + diagnostics = { + enable = true, + show_on_dirs = true, + icons = { + hint = "⚑", + info = "", + warning = "▲", + error = "", + }, + }, + trash = { + cmd = "gio trash", + require_confirm = true, + }, + modified = { + enable = true, + show_on_dirs = true, + show_on_open_dirs = true, + }, + --filters = { + -- dotfiles = false, + -- git_clean = false, + -- no_buffer = false, + -- custom = {}, + -- exclude = {}, + --}, + actions = { + use_system_clipboard = true, + change_dir = { + enable = true, + global = false, + restrict_above_cwd = false, + }, + remove_file = { + close_window = true, + }, + open_file = { + quit_on_open = true, + --eject = true, + resize_window = false, + window_picker = { + enable = true, + chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890", + exclude = { + filetype = { "notify", "packer", "qf", "diff", "fugitive", "fugitiveblame" }, + buftype = { "nofile", "terminal", "help" }, + }, + }, + }, + }, +}) + +local api = require("nvim-tree.api") +local event = api.events.Event +--api.events.subscribe(event.TreeOpen, function(_) +-- vim.cmd([[setlocal statuscolumn=\ ]]) +-- vim.cmd([[setlocal cursorlineopt=number]]) +-- vim.cmd([[setlocal fillchars+=vert:🮇]]) +-- vim.cmd([[setlocal fillchars+=horizup:🮇]]) +-- vim.cmd([[setlocal fillchars+=vertright:🮇]]) +--end) + +local function open_nvim_tree(data) + vim.cmd.cd(data.file:match("(.+)/[^/]*$")) + local directory = vim.fn.isdirectory(data.file) == 1 + if not directory then + return + end + require("nvim-tree.api").tree.open() +end +vim.api.nvim_create_autocmd({ "VimEnter" }, { callback = open_nvim_tree }) + +-- Change Root To Global Current Working Directory +local function change_root_to_global_cwd() + local api = require("nvim-tree.api") + local global_cwd = vim.fn.getcwd(-1, -1) + api.tree.change_root(global_cwd) +end + +local function copy_file_to(node) + local file_src = node["absolute_path"] + -- The args of input are {prompt}, {default}, {completion} + -- Read in the new file path using the existing file's path as the baseline. + local file_out = vim.fn.input("COPY TO: ", file_src, "file") + -- Create any parent dirs as required + local dir = vim.fn.fnamemodify(file_out, ":h") + vim.fn.system({ "mkdir", "-p", dir }) + -- Copy the file + vim.fn.system({ "cp", "-R", file_src, file_out }) +end + +local function edit_and_close(node) + api.node.open.edit(node, {}) + api.tree.close() +end + +--vim.api.nvim_create_augroup('NvimTreeRefresh', {}) +--vim.api.nvim_create_autocmd('BufEnter', { +-- pattern = 'NvimTree_1', +-- command = 'NvimTreeRefresh', +-- group = 'NvimTreeRefresh', +--}) + +vim.api.nvim_create_autocmd({ "CursorHold" }, { + pattern = "NvimTree*", + callback = function() + local def = vim.api.nvim_get_hl_by_name("Cursor", true) + vim.api.nvim_set_hl( + 0, + "Cursor", + vim.tbl_extend("force", def, { + blend = 100, + }) + ) + vim.opt.guicursor:append("a:Cursor/lCursor") + end, +}) + +vim.api.nvim_create_autocmd({ "BufLeave", "WinClosed", "WinLeave" }, { + pattern = "NvimTree*", + callback = function() + local def = vim.api.nvim_get_hl_by_name("Cursor", true) + vim.api.nvim_set_hl( + 0, + "Cursor", + vim.tbl_extend("force", def, { + blend = 0, + }) + ) + vim.opt.guicursor = "n-v-c-sm:block,i-ci-ve:ver25,r-cr-o:hor20" + end, +}) + +-- Highlight Groups +vim.api.nvim_command("highlight NvimTreeNormal guibg=NONE ctermbg=NONE") +vim.api.nvim_command("highlight NvimTreeNormalNC guibg=NONE ctermbg=NONE guifg=NONE") +vim.api.nvim_command("highlight NvimTreeNormalFloat guibg=NONE ctermbg=NONE") +vim.api.nvim_command("highlight NvimTreeEndOfBuffer guibg=NONE ctermbg=NONE") --(NonText) +vim.api.nvim_command("highlight NvimTreeCursorLine guibg=#50fa7b guifg=#000000") +vim.api.nvim_command("highlight NvimTreeSymlinkFolderName guifg=#f8f8f2 guibg=NONE ctermbg=NONE") +vim.api.nvim_command("highlight NvimTreeFolderName guifg=#f8f8f2 guibg=NONE ctermbg=NONE") +vim.api.nvim_command("highlight NvimTreeRootFolder guifg=#f8f8f2 guibg=NONE ctermbg=NONE") +vim.api.nvim_command("highlight NvimTreeEmptyFolderName guifg=#f8f8f2 guibg=NONE ctermbg=NONE") --(Directory) +vim.api.nvim_command("highlight NvimTreeOpenedFolderName guifg=#f8f8f2 guibg=NONE ctermbg=NONE") --(Directory) +vim.api.nvim_command("highlight NvimTreeOpenedFile guifg=#50fa7b guibg=NONE ctermbg=NONE") + +--vim.api.nvim_command("highlight NvimTreeSymlink ") +--vim.api.nvim_command("highlight NvimTreeSymlinkFolderName ") --(Directory) +--vim.api.nvim_command("highlight NvimTreeFolderName ") --(Directory) +--vim.api.nvim_command("highlight NvimTreeRootFolder ") +--vim.api.nvim_command("highlight NvimTreeFolderIcon ") +--vim.api.nvim_command("highlight NvimTreeOpenedFolderIcon ") --(NvimTreeFolderIcon) +--vim.api.nvim_command("highlight NvimTreeClosedFolderIcon ") --(NvimTreeFolderIcon) +--vim.api.nvim_command("highlight NvimTreeFileIcon ") +--vim.api.nvim_command("highlight NvimTreeEmptyFolderName ") --(Directory) +--vim.api.nvim_command("highlight NvimTreeOpenedFolderName ") --(Directory) +--vim.api.nvim_command("highlight NvimTreeExecFile ") +vim.api.nvim_command("highlight NvimTreeExecFile guifg=#ff882a guibg=none gui=NONE") +--vim.api.nvim_command("highlight NvimTreeOpenedFile ") +--vim.api.nvim_command("highlight NvimTreeModifiedFile ") +--vim.api.nvim_command("highlight NvimTreeSpecialFile ") +--vim.api.nvim_command("highlight NvimTreeImageFile ") +--vim.api.nvim_command("highlight NvimTreeIndentMarker ") +--vim.api.nvim_command("highlight NvimTreeLspDiagnosticsError ") --(DiagnosticError) +--vim.api.nvim_command("highlight NvimTreeLspDiagnosticsWarning ") --(DiagnosticWarn) +--vim.api.nvim_command("highlight NvimTreeLspDiagnosticsInformation ") --(DiagnosticInfo) +--vim.api.nvim_command("highlight NvimTreeLspDiagnosticsHint ") --(DiagnosticHint) +--vim.api.nvim_command("highlight NvimTreeGitDirty ") +--vim.api.nvim_command("highlight NvimTreeGitStaged ") +--vim.api.nvim_command("highlight NvimTreeGitMerge ") +--vim.api.nvim_command("highlight NvimTreeGitRenamed ") +--vim.api.nvim_command("highlight NvimTreeGitNew ") +--vim.api.nvim_command("highlight NvimTreeGitDeleted ") +--vim.api.nvim_command("highlight NvimTreeGitIgnored ") --(Comment) +--vim.api.nvim_command("highlight NvimTreeNormal ") +--vim.api.nvim_command("highlight NvimTreeEndOfBuffer ") --(NonText) +--vim.api.nvim_command("highlight NvimTreeCursorColumn ") --(CursorColumn) +--vim.api.nvim_command("highlight NvimTreeFileDirty ") --(NvimTreeGitDirty) +--vim.api.nvim_command("highlight NvimTreeFileStaged ") --(NvimTreeGitStaged) +--vim.api.nvim_command("highlight NvimTreeFileMerge ") --(NvimTreeGitMerge) +--vim.api.nvim_command("highlight NvimTreeFileRenamed ") --(NvimTreeGitRenamed) +--vim.api.nvim_command("highlight NvimTreeFileNew ") --(NvimTreeGitNew) +--vim.api.nvim_command("highlight NvimTreeFileDeleted ") --(NvimTreeGitDeleted) +--vim.api.nvim_command("highlight NvimTreeFileIgnored ") --(NvimTreeGitIgnored) +--vim.api.nvim_command("highlight NvimTreeLiveFilterPrefix ") +--vim.api.nvim_command("highlight NvimTreeLiveFilterValue ") +--vim.api.nvim_command("highlight NvimTreeBookmark ") diff --git a/common/config/nvim/lua/plugins/overseer.lua b/common/config/nvim/lua/plugins/overseer.lua new file mode 100644 index 0000000..6319d36 --- /dev/null +++ b/common/config/nvim/lua/plugins/overseer.lua @@ -0,0 +1 @@ +require('overseer').setup() diff --git a/common/config/nvim/lua/plugins/quickfix.lua b/common/config/nvim/lua/plugins/quickfix.lua new file mode 100644 index 0000000..4a76da0 --- /dev/null +++ b/common/config/nvim/lua/plugins/quickfix.lua @@ -0,0 +1,15 @@ +local M = {} + +M.close = function() + vim.cmd.cclose() +end + +M.open = function() + if vim.tbl_count(vim.fn.getqflist()) == 0 then + vim.notify('Nothing in quickfix list; not opening.', vim.log.levels.WARN) + else + vim.cmd.copen() + end +end + +return M diff --git a/common/config/nvim/lua/plugins/session.lua b/common/config/nvim/lua/plugins/session.lua new file mode 100644 index 0000000..0c84625 --- /dev/null +++ b/common/config/nvim/lua/plugins/session.lua @@ -0,0 +1,5 @@ +require('auto-session').setup({ + log_level = 'error', + auto_session_suppress_dirs = { '~/', '~/projects', '~/downloads', '/' }, +}) +require('session-lens').setup({}) diff --git a/common/config/nvim/lua/plugins/snippets.lua b/common/config/nvim/lua/plugins/snippets.lua new file mode 100644 index 0000000..7df6b2f --- /dev/null +++ b/common/config/nvim/lua/plugins/snippets.lua @@ -0,0 +1,68 @@ +local ls = require "luasnip" -- + +require("luasnip.loaders.from_lua").load({ paths = "~/.config/nvim/snippets/" }) +--local options = { +ls.config.set_config { + history = true, + updateevents = "TextChanged,TextChangedI", + -- Autosnippets: + enable_autosnippets = true, -- + region_check_events = "InsertEnter", + delete_check_events = "TextChanged", + update_events = "TextChanged,TextChangedI", + store_selection_keys = "<Tab>", + ext_opts = { -- + [require("luasnip.util.types").choiceNode] = { + active = { + virt_text = { { "«", "GruvboxOrange" } }, + }, + }, + }, +} + +--local keymap = vim.keymap +--local keymap = vim.api.nvim_set_keymap +local keymap = vim.keymap.set +--keymap('i', '<c-f>', 'luasnip#expand_or_jumpable() ? "<Plug>luasnip-expand-or-jump" : "<Tab>"', {expr = true, silent = true}) +keymap({ "i", "s"}, "<c-f>", function() + if ls.expand_or_jumpable() then + ls.expand() + end +end) + +keymap({ "i", "s"}, "<c-j>", function() + if ls.jumpable(1) then + ls.jump(1) + end +end) + +keymap({ "i", "s"}, "<c-k>", function() + if ls.jumpable(-1) then + ls.jump(-1) + end +end) + +keymap({ "i", "s"}, "<c-c>", function() + if ls.choice_active() then + ls.change_choice(1) + end +end) + +keymap({ "i", "s"}, "<a-c>", function() + if ls.choice_active() then + ls.change_choice(-1) + end +end) + +-- Character class Matching +-- %a letters (A-Z, a-z) +-- %c control characters (\n, \t, \r, ...) +-- %d digits (0-9) +-- %l lower-case letter (a-z) +-- %p punctuation characters (!, ?, &, ...) +-- %s space characters +-- %u upper-case letters +-- %w alphanumeric characters (A-Z, a-z, 0-9) +-- %x hexadecimal digits (\3, \4, ...) +-- %z the character with representation 0 +-- . Matches any character diff --git a/common/config/nvim/lua/plugins/sniprun.lua b/common/config/nvim/lua/plugins/sniprun.lua new file mode 100644 index 0000000..418e8cc --- /dev/null +++ b/common/config/nvim/lua/plugins/sniprun.lua @@ -0,0 +1,57 @@ +local status_ok, sniprun = pcall(require, 'sniprun') +if not status_ok then + return +end + +sniprun.setup({ + -- selected_interpreters = {}, --# use those instead of the default for the current filetype + -- repl_enable = { "Python3_original" }, --# enable REPL-like behavior for the given interpreters + -- repl_disable = {}, --# disable REPL-like behavior for the given interpreters + + -- interpreter_options = { --# intepreter-specific options, see docs / :SnipInfo <name> + -- GFM_original = { + -- use_on_filetypes = { "markdown.pandoc" }, --# the 'use_on_filetypes' configuration key is + -- --# available for every interpreter + -- }, + -- }, + + --# you can combo different display modes as desired + display = { + -- "Classic", --# display results in the command-line area + --'VirtualTextOk', --# display ok results as virtual text (multiline is shortened) + -- "VirtualTextErr", --# display error results as virtual text + -- "TempFloatingWindow", --# display results in a floating window + -- "LongTempFloatingWindow", --# same as above, but only long results. To use with VirtualText__ + 'Terminal', --# display results in a vertical split + -- "TerminalWithCode", --# display results and code history in a vertical split + -- "NvimNotify", --# display with the nvim-notify plugin + -- "Api" --# return output to a programming interface + }, + + display_options = { + terminal_width = 45, --# change the terminal display option width + notification_timeout = 5, --# timeout for nvim_notify output + }, + + --# You can use the same keys to customize whether a sniprun producing + --# no output should display nothing or '(no output)' + show_no_output = { + 'Classic', + 'TempFloatingWindow', --# implies LongTempFloatingWindow, which has no effect on its own + }, + + --# customize highlight groups (setting this overrides colorscheme) + -- snipruncolors = { + -- SniprunVirtualTextOk = { bg = "NONE", fg = "#66eeff", ctermbg = "Black", cterfg = "Cyan" }, + -- SniprunFloatingWinOk = { fg = "NONE", ctermfg = "Cyan" }, + -- SniprunVirtualTextErr = { bg = "#881515", fg = "#000000", ctermbg = "DarkRed", cterfg = "Black" }, + -- SniprunFloatingWinErr = { fg = "#881515", ctermfg = "DarkRed" }, + -- }, + + --# miscellaneous compatibility/adjustement settings + inline_messages = 0, --# inline_message (0/1) is a one-line way to display messages + --# to workaround sniprun not being able to display anything + + borders = 'single', --# display borders around floating windows + --# possible values are 'none', 'single', 'double', or 'shadow' +}) diff --git a/common/config/nvim/lua/plugins/statuscol.lua b/common/config/nvim/lua/plugins/statuscol.lua new file mode 100644 index 0000000..24a2308 --- /dev/null +++ b/common/config/nvim/lua/plugins/statuscol.lua @@ -0,0 +1,28 @@ +local status, statuscol = pcall(require, "statuscol") + +if not status then + vim.notify("statuscol not found") + return +end + +local builtin = require("statuscol.builtin") + +statuscol.setup({ + segments = { + { text = { builtin.lnumfunc }, click = "v:lua.ScLa" }, + { text = { "%s" }, click = "v:lua.ScSa" }, + { text = { builtin.foldfunc }, click = "v:lua.ScFa" }, + }, + ft_ignore = { + "NvimTree", + "packer", + "NeogitStatus", + "toggleterm", + "dapui_scopes", + "dapui_breakpoints", + "dapui_stacks", + "dapui_watches", + "dapui_console", + "dapui_repl", + }, +}) diff --git a/common/config/nvim/lua/plugins/surround.lua b/common/config/nvim/lua/plugins/surround.lua new file mode 100644 index 0000000..04def1b --- /dev/null +++ b/common/config/nvim/lua/plugins/surround.lua @@ -0,0 +1,22 @@ +require("nvim-surround").setup({ + keymaps = { + insert = false, + insert_line = false, + normal = false, + normal_cur = false, + normal_line = false, + normal_cur_line = false, + visual = "<S-s>", + visual_line = false, + delete = false, + change = false, + }, + aliases = { + ["a"] = false, + ["b"] = false, + ["B"] = false, + ["r"] = false, + ["q"] = false, + ["s"] = false, + }, +}) diff --git a/common/config/nvim/lua/plugins/telescope.lua b/common/config/nvim/lua/plugins/telescope.lua new file mode 100644 index 0000000..506be8b --- /dev/null +++ b/common/config/nvim/lua/plugins/telescope.lua @@ -0,0 +1,636 @@ +local M = {} + +-- Shorten function names +local actions = require('telescope.actions') +local fb_actions = require('telescope').extensions.file_browser.actions +--local builtin = require("telescope.builtin") +--local utils = require("telescope.utils") +--local layout_actions = require("telescope.actions.layout") +--local themes = require('telescope.themes') +local actions_set = require('telescope.actions.set') +local actions_state = require('telescope.actions.state') +local finders = require('telescope.finders') +local pickers = require('telescope.pickers') +local config = require('telescope.config').values + +require('telescope').setup({ + defaults = { + vimgrep_arguments = { + 'rg', + '--color=never', + '--no-heading', + '--with-filename', + '--line-number', + '--column', + '--smart-case', + '--hidden', + '--fixed-strings', + '--trim', + }, + prompt_prefix = ' ', + selection_caret = ' ', + entry_prefix = ' ', + path_display = { 'tail' }, + --path_display = { "truncate" }, + --path_display = { "smart" }, + file_ignore_patterns = { + 'packer_compiled.lua', + '~/.config/zsh/plugins', + 'zcompdump', + '%.DS_Store', + '%.git/', + '%.spl', + --"%.log", + '%[No Name%]', -- new files / sometimes folders (netrw) + '/$', -- ignore folders (netrw) + 'node_modules', + '%.png', + '%.zip', + '%.pxd', + --"^.vim/", + '^.local/', + '^.cache/', + '^downloads/', + '^music/', + --"^node_modules/", + --"^undodir/", + }, + mappings = { + i = { + ['<C-n>'] = actions.cycle_history_next, + ['<C-p>'] = actions.cycle_history_prev, + + ['<C-j>'] = actions.move_selection_next, + ['<C-k>'] = actions.move_selection_previous, + + --["<C-c>"] = actions.close, + ['<Esc>'] = actions.close, -- close w/ one esc + --["<Esc>"] = "close", -- close w/ one esc + ['<?>'] = actions.which_key, -- keys from pressing <C-/> + + ['<Down>'] = actions.move_selection_next, + ['<Up>'] = actions.move_selection_previous, + + ['<CR>'] = actions.select_default, + ['<C-x>'] = actions.select_horizontal, + ['<C-y>'] = actions.select_vertical, + ['<C-t>'] = actions.select_tab, + ['<C-c>'] = actions.delete_buffer, + + ['<C-u>'] = actions.preview_scrolling_up, + ['<C-d>'] = actions.preview_scrolling_down, + + ['<PageUp>'] = actions.results_scrolling_up, + ['<PageDown>'] = actions.results_scrolling_down, + + ['<Tab>'] = actions.toggle_selection + actions.move_selection_worse, + ['<S-Tab>'] = actions.toggle_selection + actions.move_selection_better, + ['<C-q>'] = actions.send_to_qflist + actions.open_qflist, + ['<M-q>'] = actions.send_selected_to_qflist + actions.open_qflist, + ['<C-l>'] = actions.complete_tag, + ['<C-_>'] = actions.which_key, -- keys from pressing <C-/> + --["<C-o>"] = function(prompt_bufnr) + -- local selection = require("telescope.actions.state").get_selected_entry() + -- local dir = vim.fn.fnamemodify(selection.path, ":p:h") + -- require("telescope.actions").close(prompt_bufnr) + -- -- Depending on what you want put `cd`, `lcd`, `tcd` + -- vim.cmd(string.format("silent lcd %s", dir)) + --end, + }, + n = { + --["cd"] = function(prompt_bufnr) + -- local selection = require("telescope.actions.state").get_selected_entry() + -- local dir = vim.fn.fnamemodify(selection.path, ":p:h") + -- require("telescope.actions").close(prompt_bufnr) + -- -- Depending on what you want put `cd`, `lcd`, `tcd` + -- vim.cmd(string.format("silent lcd %s", dir)) + --end, + ['<esc>'] = actions.close, + ['<q>'] = actions.close, + ['<CR>'] = actions.select_default, + ['<C-x>'] = actions.select_horizontal, + ['<C-y>'] = actions.select_vertical, + ['<C-t>'] = actions.select_tab, + ['<C-c>'] = actions.delete_buffer, + + ['<Tab>'] = actions.toggle_selection + actions.move_selection_worse, + ['<S-Tab>'] = actions.toggle_selection + actions.move_selection_better, + ['<C-q>'] = actions.send_to_qflist + actions.open_qflist, + ['<M-q>'] = actions.send_selected_to_qflist + actions.open_qflist, + + ['j'] = actions.move_selection_next, + ['k'] = actions.move_selection_previous, + ['H'] = actions.move_to_top, + ['M'] = actions.move_to_middle, + ['L'] = actions.move_to_bottom, + + ['<Down>'] = actions.move_selection_next, + ['<Up>'] = actions.move_selection_previous, + ['gg'] = actions.move_to_top, + ['G'] = actions.move_to_bottom, + + ['<C-u>'] = actions.preview_scrolling_up, + ['<C-d>'] = actions.preview_scrolling_down, + + ['<PageUp>'] = actions.results_scrolling_up, + ['<PageDown>'] = actions.results_scrolling_down, + ['cd'] = function(prompt_bufnr) + local selection = require('telescope.actions.state').get_selected_entry() + local dir = vim.fn.fnamemodify(selection.path, ':p:h') + require('telescope.actions').close(prompt_bufnr) + -- Depending on what you want put `cd`, `lcd`, `tcd` + vim.cmd(string.format('silent lcd %s', dir)) + end, + ['?'] = actions.which_key, + --["<C-o>"] = function(prompt_bufnr) + -- local selection = require("telescope.actions.state").get_selected_entry() + -- local dir = vim.fn.fnamemodify(selection.path, ":p:h") + -- require("telescope.actions").close(prompt_bufnr) + -- -- Depending on what you want put `cd`, `lcd`, `tcd` + -- vim.cmd(string.format("silent lcd %s", dir)) + --end, + }, + }, + }, + preview = { + filesize_limit = 3, + timeout = 250, + }, + selection_strategy = 'reset', + sorting_strategy = 'ascending', + scroll_strategy = 'limit', + color_devicons = true, + layout_strategy = 'horizontal', + layout_config = { + horizontal = { + height = 0.95, + preview_cutoff = 70, + width = 0.92, + preview_width = { 0.55, max = 50 }, + }, + bottom_pane = { + height = 12, + preview_cutoff = 70, + prompt_position = 'bottom', + }, + }, + find_files = { + --cwd = '%:p:h', + cwd = vim.fn.getcwd(), + prompt_prefix = ' ', + --hidden = true, + --no_ignore = false, + follow = true, + }, + --pickers = { + -- live_grep = { + -- disable_coordinates = true, + -- layout_config = { + -- horizontal = { + -- preview_width = 0.55, + -- }, + -- }, + -- }, + --}, + --pickers = { + -- live_grep = { + -- mappings = { + -- i = { + -- ["<C-f>"] = ts_select_dir_for_grep, + -- }, + -- n = { + -- ["<C-f>"] = ts_select_dir_for_grep, + -- }, + -- }, + -- }, + --}, + --pickers = { + --lsp_references = { + -- prompt_prefix='⬅️', + -- show_line=false, + -- trim_text=true, + -- include_declaration=false, + -- initial_mode = "normal", + --}, + --lsp_definitions = { + -- prompt_prefix='➡️', + -- show_line=false, + -- trim_text=true, + -- initial_mode = "normal", + --}, + --lsp_document_symbols = { + -- prompt_prefix='* ', + -- show_line = false, + --}, + --treesitter = { + -- prompt_prefix=' ', + -- show_line = false, + --}, + --keymaps = { prompt_prefix='? ' }, + --oldfiles = { prompt_prefix=' ' }, + --highlights = { prompt_prefix=' ' }, + --git_files = { + -- prompt_prefix=' ', + -- show_untracked = true, + -- path_display = { "tail" }, + --}, + --buffers = { + -- prompt_prefix=' ', + -- ignore_current_buffer = true, + -- initial_mode = "normal", + -- sort_mru = true, + --}, + --live_grep = { + -- cwd='%:p:h', + -- disable_coordinates=true, + -- prompt_title='Search in Folder', + -- prompt_prefix=' ', + --}, + --spell_suggest = { + -- initial_mode = "normal", + -- prompt_prefix = "暈", + -- theme = "cursor", + -- layout_config = { cursor = { width = 0.3 } } + --}, + --colorscheme = { + -- enable_preview = true, + -- prompt_prefix = '', + -- results_title = '', + -- layout_strategy = "bottom_pane", + --}, + --}, + + extensions = { + file_browser = { + theme = 'dropdown', + -- disables netrw and use telescope-file-browser in its place + hijack_netrw = false, + mappings = { + -- your custom insert mode mappings + ['i'] = { + ['<C-w>'] = function() + vim.cmd('normal vbd') + end, + ['<C-h>'] = fb_actions.goto_parent_dir, + }, + ['n'] = { + -- your custom normal mode mappings + ['N'] = fb_actions.create, + ['<C-h>'] = fb_actions.goto_parent_dir, + --["/"] = function() + -- vim.cmd("startinsert") + --end, + }, + }, + }, + }, +}) + +-------------------------------------------------------------------------------- + +-- Load extensions: +-- have to be loaded after telescope setup/config +require('telescope').load_extension('fzf') +require('telescope').load_extension('ui-select') +require('telescope').load_extension('file_browser') +require('telescope').load_extension('changed_files') +require('telescope').load_extension('media_files') +require('telescope').load_extension('notify') +require('telescope').load_extension('dap') +require('telescope').load_extension('session-lens') +require('telescope').load_extension('flutter') +require('telescope').load_extension('recent_files') +--require('telescope').load_extension('projects') + +--M.curbuf = function(opts) +-- opts = opts +-- or themes.get_dropdown({ +-- previewer = false, +-- shorten_path = false, +-- border = true, +-- }) +-- require("telescope.builtin").current_buffer_fuzzy_find(opts) +--end + +function M.find_configs() + -- Track dotfiles (bare git repository) + -- Inside shell config file: + -- alias config='git --git-dir=$HOME/.cfg --work-tree=$HOME' + -- cfg_files=$(config ls-tree --name-only -r HEAD) + -- export CFG_FILES="$cfg_files" + local tracked_files = {} + + for file in string.gmatch(os.getenv('CFG_FILES'), '[^\n]+') do + table.insert(tracked_files, os.getenv('HOME') .. '/' .. file) + end + + local history = os.getenv('HOME') .. '/.config/zsh/.zhistory' + table.insert(tracked_files, history) + + require('telescope.builtin').find_files({ + hidden = true, + no_ignore = false, + prompt_title = ' Find Configs', + results_title = 'Config Files', + path_display = { 'smart' }, + search_dirs = tracked_files, + layout_strategy = 'horizontal', + layout_config = { preview_width = 0.65, width = 0.75 }, + }) +end + +function M.find_scripts() + require('telescope.builtin').find_files({ + hidden = true, + no_ignore = true, + prompt_title = ' Find Scripts', + path_display = { 'smart' }, + search_dirs = { + '~/.scripts', + }, + layout_strategy = 'horizontal', + layout_config = { preview_width = 0.65, width = 0.75 }, + }) +end + +function M.find_projects() + local search_dir = '~/projects' + pickers + .new({}, { + prompt_title = 'Find Projects', + finder = finders.new_oneshot_job({ + 'find', + vim.fn.expand(search_dir), + '-type', + 'd', + '-maxdepth', + '1', + }), + previewer = require('telescope.previewers').vim_buffer_cat.new({}), + sorter = config.generic_sorter({}), + attach_mappings = function(prompt_bufnr, map) + actions_set.select:replace(function() + local entry = actions_state.get_selected_entry() + if entry ~= nil then + local dir = entry.value + actions.close(prompt_bufnr, false) + vim.fn.chdir(dir) + vim.cmd('e .') + vim.cmd("echon ''") + print('cwd: ' .. vim.fn.getcwd()) + end + end) + return true + end, + }) + :find() +end + +function M.grep_notes() + local opts = {} + opts.hidden = false + opts.search_dirs = { + '~/documents/notes/', + } + opts.prompt_prefix = ' ' + opts.prompt_title = ' Grep Notes' + opts.path_display = { 'smart' } + require('telescope.builtin').live_grep(opts) +end + +function M.find_notes() + require('telescope.builtin').find_files({ + hidden = true, + no_ignore = false, + prompt_title = ' Find Notes', + path_display = { 'smart' }, + search_dirs = { + '~/documents/notes/private/', + '~/documents/notes', + }, + layout_strategy = 'horizontal', + layout_config = { preview_width = 0.65, width = 0.75 }, + }) +end + +function M.find_private() + require('telescope.builtin').find_files({ + hidden = true, + no_ignore = false, + prompt_title = ' Find Notes', + path_display = { 'smart' }, + search_dirs = { + '~/notes/private', + '~/notes', + }, + layout_strategy = 'horizontal', + layout_config = { preview_width = 0.65, width = 0.75 }, + }) +end + +function M.find_books() + local search_dir = '~/documents/books' + vim.fn.jobstart('$HOME/.scripts/track-books.sh') + local recent_books_directory = vim.fn.stdpath('config') .. '/tmp/' + local recent_books_file = recent_books_directory .. 'recent_books.txt' + local search_cmd = 'find ' .. vim.fn.expand(search_dir) .. ' -type d -o -type f -maxdepth 1' + + local recent_books = vim.fn.readfile(recent_books_file) + local search_results = vim.fn.systemlist(search_cmd) + + local results = {} + + -- Section for Recent Books + table.insert(results, ' Recent Books') + for _, recent_book_path in ipairs(recent_books) do + local formatted_path = vim.fn.fnameescape(recent_book_path) + table.insert(results, formatted_path) + end + + -- Section for All Books + table.insert(results, ' All Books') + local directories = {} + local files = {} + + for _, search_result in ipairs(search_results) do + if vim.fn.isdirectory(search_result) == 1 then + table.insert(directories, search_result) + else + table.insert(files, search_result) + end + end + + table.sort(directories) + table.sort(files) + + for _, dir in ipairs(directories) do + table.insert(results, dir) + end + + for _, file in ipairs(files) do + table.insert(results, file) + end + + local picker = pickers.new({}, { + prompt_title = 'Find Books', + finder = finders.new_table({ + results = results, + }), + file_ignore_patterns = { + '%.git', + }, + previewer = require('telescope.previewers').vim_buffer_cat.new({}), + sorter = config.generic_sorter({}), + attach_mappings = function(prompt_bufnr, map) + actions_set.select:replace(function() + local entry = actions_state.get_selected_entry() + if entry ~= nil then + local path = entry.value + + actions.close(prompt_bufnr, false) + + -- Check if it's under "Recent Books" + if path == ' Recent Books' or path == ' All Books' then + vim.notify("Cannot select 'All Books'/'Recent Books', please select a book or directory.", vim.log.levels.WARN, { title = 'Find Books' }) + else + -- Determine whether it's a directory or a file + local is_directory = vim.fn.isdirectory(path) + if is_directory then + -- It's a directory, navigate to it in the current buffer + vim.cmd('e ' .. path) + else + -- It's a file, open it + vim.cmd('e ' .. path) + end + end + end + end) + return true + end, + }) + + picker:find() +end + +function M.grep_current_dir() + local buffer_dir = require('telescope.utils').buffer_dir() + local opts = { + prompt_title = 'Live Grep in ' .. buffer_dir, + cwd = buffer_dir, + } + require('telescope.builtin').live_grep(opts) +end + +-------------------------------------------------------------------------------- + +local dropdown = require('telescope.themes').get_dropdown({ + hidden = true, + no_ignore = true, + previewer = false, + prompt_title = '', + preview_title = '', + results_title = '', + layout_config = { + --anchor = "S", + prompt_position = 'top', + }, +}) + +-- File browser always relative to buffer +--local opts_file_browser = vim.tbl_extend('force', dropdown, { +-- path_display = { '%:p:h' }, +--}) + +-- Set current folder as prompt title +local with_title = function(opts, extra) + extra = extra or {} + local path = opts.cwd or opts.path or extra.cwd or extra.path or nil + local title = '' + local buf_path = vim.fn.expand('%:p:h') + local cwd = vim.fn.getcwd() + if path ~= nil and buf_path ~= cwd then + title = require('plenary.path'):new(buf_path):make_relative(cwd) + else + title = vim.fn.fnamemodify(cwd, ':t') + end + + return vim.tbl_extend('force', opts, { + prompt_title = title, + }, extra or {}) +end + +-- Find here +function M.findhere() + -- Open file browser if argument is a folder + local arg = vim.api.nvim_eval('argv(0)') + if arg and (vim.fn.isdirectory(arg) ~= 0 or arg == '') then + vim.defer_fn(function() + require('telescope.builtin').find_files(with_title(dropdown)) + -- require'telescope.builtin'.find_files(require('telescope.themes').get_dropdown({ + -- hidden = true, + -- results_title = '', + -- layout_config = { prompt_position = 'top' }, + -- })) + end, 10) + end +end + +-- Define the custom command findhere/startup +vim.cmd('command! Findhere lua require("plugins.telescope").findhere()') +--vim.cmd('command! Startup lua require("plugins.telescope").findhere()') +--vim.api.nvim_command('autocmd VimEnter * lua require("plugins/telescope").findhere()') + +-- Find dirs +function M.find_dirs() + local root_dir = vim.fn.input('Enter the root directory: ') + + -- Check if root_dir is empty + if root_dir == '' then + print('No directory entered. Aborting.') + return + end + + local entries = {} + + -- Use vim.fn.expand() to get an absolute path + local root_path = vim.fn.expand(root_dir) + + local subentries = vim.fn.readdir(root_path) + if subentries then + for _, subentry in ipairs(subentries) do + local absolute_path = root_path .. '/' .. subentry + table.insert(entries, subentry) + end + end + + pickers + .new({}, { + prompt_title = 'Change Directory or Open File', + finder = finders.new_table({ + results = entries, + }), + previewer = config.file_previewer({}), + sorter = config.generic_sorter({}), + attach_mappings = function(prompt_bufnr, map) + actions_set.select:replace(function() + local entry = actions_state.get_selected_entry() + if entry ~= nil then + local selected_entry = entry.value + actions.close(prompt_bufnr, false) + local selected_path = root_path .. '/' .. selected_entry + if vim.fn.isdirectory(selected_path) == 1 then + vim.fn.chdir(selected_path) + vim.cmd('e .') + print('cwd: ' .. vim.fn.getcwd()) + else + vim.cmd('e ' .. selected_path) + end + end + end) + return true + end, + }) + :find() +end + +return M diff --git a/common/config/nvim/lua/plugins/toggleterm.lua b/common/config/nvim/lua/plugins/toggleterm.lua new file mode 100644 index 0000000..e67bdec --- /dev/null +++ b/common/config/nvim/lua/plugins/toggleterm.lua @@ -0,0 +1,179 @@ +local status_ok, toggleterm = pcall(require, 'toggleterm') +if not status_ok then + return +end +toggleterm.setup({ + --open_mapping = [[<leader>tt]], + autochdir = true, + hide_numbers = true, + shade_filetypes = {}, + shade_terminals = false, + --shading_factor = 1, + start_in_insert = true, + insert_mappings = true, + terminal_mappings = true, + persist_size = true, + direction = 'float', + --direction = "vertical", + --direction = "horizontal", + close_on_exit = true, + shell = vim.o.shell, + highlights = { + -- highlights which map to a highlight group name and a table of it's values + -- NOTE: this is only a subset of values, any group placed here will be set for the terminal window split + --Normal = { + -- background = "#000000", + --}, + --Normal = { guibg = 'Black', guifg = 'White' }, + --FloatBorder = { guibg = 'Black', guifg = 'DarkGray' }, + --NormalFloat = { guibg = 'Black' }, + float_opts = { + --winblend = 3, + }, + }, + size = function(term) + if term.direction == 'horizontal' then + return 7 + elseif term.direction == 'vertical' then + return math.floor(vim.o.columns * 0.4) + end + end, + float_opts = { + width = 70, + height = 15, + border = 'curved', + highlights = { + border = 'Normal', + --background = 'Normal', + }, + --winblend = 0, + }, +}) +local mods = require('user.mods') +local float_handler = function(term) + if not mods.empty(vim.fn.mapcheck('jk', 't')) then + vim.keymap.del('t', 'jk', { buffer = term.bufnr }) + vim.keymap.del('t', '<esc>', { buffer = term.bufnr }) + end +end + +function _G.set_terminal_keymaps() + local opts = { noremap = true } + --local opts = {buffer = 0} + --vim.api.nvim_buf_set_keymap(0, "i", ";to", "[[<Esc>]]<cmd>Toggleterm", opts) + vim.api.nvim_buf_set_keymap(0, 't', '<C-c>', [[<Esc>]], opts) + vim.api.nvim_buf_set_keymap(0, 't', '<esc>', [[<C-\><C-n>]], opts) + vim.api.nvim_buf_set_keymap(0, 't', 'jk', [[<C-\><C-n>]], opts) + vim.api.nvim_buf_set_keymap(0, 't', '<C-h>', [[<C-\><C-n><C-W>h]], opts) + vim.api.nvim_buf_set_keymap(0, 't', '<C-j>', [[<C-\><C-n><C-W>j]], opts) + vim.api.nvim_buf_set_keymap(0, 't', '<C-k>', [[<C-\><C-n><C-W>k]], opts) + vim.api.nvim_buf_set_keymap(0, 't', '<C-l>', [[<C-\><C-n><C-W>l]], opts) +end + +-- if you only want these mappings for toggle term use term://*toggleterm#* instead +vim.cmd('autocmd! TermOpen term://* lua set_terminal_keymaps()') +local Terminal = require('toggleterm.terminal').Terminal + +local horizontal_term = Terminal:new({ hidden = true, direction = 'horizontal' }) +local vertical_term = Terminal:new({ hidden = true, direction = 'vertical' }) + +function Horizontal_term_toggle() + horizontal_term:toggle(8, 'horizontal') +end + +function Vertical_term_toggle() + horizontal_term:toggle(math.floor(vim.o.columns * 0.5), 'vertical') +end + +local lazygit = Terminal:new({ + cmd = 'lazygit', + count = 5, + id = 1000, + dir = 'git_dir', + direction = 'float', + on_open = float_handler, + hidden = true, + float_opts = { + border = { '╒', '═', '╕', '│', '╛', '═', '╘', '│' }, + width = 150, + height = 40, + }, + + ---- Function to run on opening the terminal + --on_open = function(term) + -- vim.api.nvim_buf_set_keymap(term.bufnr, 'n', 'q', '<cmd>close<CR>', + -- {noremap = true, silent = true}) + -- vim.api.nvim_buf_set_keymap(term.bufnr, 'n', '<esc>', '<cmd>close<CR>', + -- {noremap = true, silent = true}) + -- vim.api.nvim_buf_set_keymap(term.bufnr, 'n', '<C-\\>', '<cmd>close<CR>', + -- {noremap = true, silent = true}) + --end, + ---- Function to run on closing the terminal + --on_close = function(term) + -- vim.cmd("startinsert!") + --end +}) + +function Lazygit_toggle() + -- cwd is the root of project. if cwd is changed, change the git. + local cwd = vim.fn.getcwd() + if cwd ~= Cur_cwd then + Cur_cwd = cwd + lazygit:close() + lazygit = Terminal:new({ + cmd = "zsh --login -c 'lazygit'", + dir = 'git_dir', + direction = 'float', + hidden = true, + on_open = float_handler, + float_opts = { + border = { '╒', '═', '╕', '│', '╛', '═', '╘', '│' }, + width = 150, + height = 40, + }, + }) + end + lazygit:toggle() +end + +local node = Terminal:new({ cmd = 'node', hidden = true }) + +function _NODE_TOGGLE() + node:toggle() +end + +local ncdu = Terminal:new({ cmd = 'ncdu', hidden = true }) + +function _NCDU_TOGGLE() + ncdu:toggle() +end + +local htop = Terminal:new({ cmd = 'htop', hidden = true }) + +function _HTOP_TOGGLE() + htop:toggle() +end + +local python = Terminal:new({ cmd = 'python', hidden = true }) + +function _PYTHON_TOGGLE() + python:toggle() +end + +function Gh_dash() + Terminal:new({ + cmd = 'gh dash', + hidden = true, + direction = 'float', + on_open = float_handler, + float_opts = { + height = function() + return math.floor(vim.o.lines * 0.8) + end, + width = function() + return math.floor(vim.o.columns * 0.95) + end, + }, + }) + Gh_dash:toggle() +end diff --git a/common/config/nvim/lua/plugins/treesitter.lua b/common/config/nvim/lua/plugins/treesitter.lua new file mode 100644 index 0000000..7f481d3 --- /dev/null +++ b/common/config/nvim/lua/plugins/treesitter.lua @@ -0,0 +1,31 @@ +require'nvim-treesitter.configs'.setup { + -- A list of parser names, or "all" (the four listed parsers should always be installed) + + ensure_installed = { + "c", + "bash", + "lua", + "rust", + }, + --ensure_installed = "all", -- one of "all" or a list of languages + --ignore_install = { "" }, -- List of parsers to ignore installing + sync_install = false, + auto_install = true, + highlight = { + enable = false, + disable = {}, + }, + indent = { + enable = true, + disable = {}, + --disable = { "python", "css" } + }, + autotag = { + enable = true, + }, +} +--vim.opt.foldmethod = "expr" +--vim.opt.foldexpr = "nvim_treesitter#foldexpr()" + +--local parser_config = require "nvim-treesitter.parsers".get_parser_configs() +--parser_config.tsx.filetype_to_parsername = { "javascript", "typescript.tsx" } diff --git a/common/config/nvim/lua/plugins/trouble.lua b/common/config/nvim/lua/plugins/trouble.lua new file mode 100644 index 0000000..7d74730 --- /dev/null +++ b/common/config/nvim/lua/plugins/trouble.lua @@ -0,0 +1,47 @@ +require('trouble').setup({ + position = 'bottom', -- position of the list can be: bottom, top, left, right + height = 10, -- height of the trouble list when position is top or bottom + width = 50, -- width of the list when position is left or right + icons = true, -- use devicons for filenames + mode = 'document_diagnostics', -- "workspace_diagnostics", "document_diagnostics", "quickfix", "lsp_references", "loclist" + fold_open = '', -- icon used for open folds + fold_closed = '', -- icon used for closed folds + group = true, -- group results by file + padding = true, -- add an extra new line on top of the list + action_keys = { -- key mappings for actions in the trouble list + -- map to {} to remove a mapping, for example: + -- close = {}, + close = 'q', -- close the list + cancel = '<esc>', -- cancel the preview and get back to your last window / buffer / cursor + refresh = 'r', -- manually refresh + jump = { '<cr>', '<tab>' }, -- jump to the diagnostic or open / close folds + open_split = { '<c-x>' }, -- open buffer in new split + open_vsplit = { '<c-v>' }, -- open buffer in new vsplit + open_tab = { '<c-t>' }, -- open buffer in new tab + jump_close = { 'o' }, -- jump to the diagnostic and close the list + toggle_mode = 'm', -- toggle between "workspace" and "document" diagnostics mode + toggle_preview = 'P', -- toggle auto_preview + hover = 'K', -- opens a small popup with the full multiline message + preview = 'p', -- preview the diagnostic location + close_folds = { 'zM', 'zm' }, -- close all folds + open_folds = { 'zR', 'zr' }, -- open all folds + toggle_fold = { 'zA', 'za' }, -- toggle fold of current file + previous = 'k', -- previous item + next = 'j', -- next item + }, + indent_lines = true, -- add an indent guide below the fold icons + auto_open = false, -- automatically open the list when you have diagnostics + auto_close = false, -- automatically close the list when you have no diagnostics + auto_preview = true, -- automatically preview the location of the diagnostic. <esc> to close preview and go back to last window + auto_fold = false, -- automatically fold a file trouble list at creation + auto_jump = { 'lsp_definitions' }, -- for the given modes, automatically jump if there is only a single result + signs = { + -- icons / text used for a diagnostic + error = '', + warning = '▲', + information = '', + hint = '⚑', + other = '', + }, + use_diagnostic_signs = true, -- enabling this will use the signs defined in your lsp client +}) diff --git a/common/config/nvim/lua/plugins/vimtex.lua b/common/config/nvim/lua/plugins/vimtex.lua new file mode 100644 index 0000000..732e6ed --- /dev/null +++ b/common/config/nvim/lua/plugins/vimtex.lua @@ -0,0 +1,45 @@ +--ft = { "latex", "tex" }, +--if vim.loop.os_uname().sysname == "Linux" then +-- vim.g.vimtex_view_method = "zathura" +--end +--vim.g["vimtex_view_method"] = "zathura" -- main variant with xdotool (requires X11; not compatible with wayland) +--vim.g.vimtex_compiler_method = "pdflatex" +-- compilation configuration +vim.g["vimtex_compiler_method"] = "latexmk" +--vim.g["vimtex_compiler_method"] = "xelatex" +--vim.g["vimtex_compiler_method"] = "lualatex" +vim.g["vimtex_compiler_latexmk"] = { + callback = 1, + continuous = 1, + executable = "latexmk", + options = { + "-shell-escape", + "-verbose", + "-file-line-error", + "-synctex=1", + "-interaction=nonstopmode", + }, +} +vim.g["vimtex_view_enabled"] = 1 +vim.g["vimtex_view_zathura_check_libsynctex"] = 0 +--vim.g["vimtex_view_method"] = "zathura" -- main variant with xdotool (requires X11; not compatible with wayland) +if vim.loop.os_uname().sysname == "Linux" then + vim.g.vimtex_view_method = "zathura" +end +--vim.g.vimtex_view_method = "sioyek" +--vim.g["vimtex_view_method"] = "zathura_simple" -- for variant without xdotool to avoid errors in wayland +vim.g["vimtex_quickfix_mode"] = 0 -- suppress error reporting on save and build +vim.g["vimtex_mappings_enabled"] = 0 -- Ignore mappings +vim.g["vimtex_indent_enabled"] = 0 -- Auto Indent +vim.g["tex_flavor"] = "latex" -- how to read tex files +vim.g["tex_indent_items"] = 0 -- turn off enumerate indent +vim.g["tex_indent_brace"] = 0 -- turn off brace indent +--vim.g.vimtex_view_forward_search_on_start = 0 +--vim.g["vimtex_context_pdf_viewer"] = "zathura" -- external PDF viewer run from vimtex menu command +--vim.g["latex_view_general_viewer"] = "zathura" +vim.g["vimtex_log_ignore"] = { -- Error suppression: + "Underfull", + "Overfull", + "specifier changed to", + "Token not allowed in a PDF string", +} diff --git a/common/config/nvim/lua/plugins/web-devicons.lua b/common/config/nvim/lua/plugins/web-devicons.lua new file mode 100644 index 0000000..06f2d1c --- /dev/null +++ b/common/config/nvim/lua/plugins/web-devicons.lua @@ -0,0 +1,22 @@ +local devicons = require('nvim-web-devicons') + +-- Set devicons overrides early. +devicons.setup({ + override = { + js = { icon = '', color = '#f5c06f', name = 'Js' }, + jsx = { icon = '', color = '#689fb6', name = 'Jsx' }, + ts = { icon = '', color = '#4377c1', name = 'Ts' }, + tsx = { icon = '', color = '#4377c1', name = 'Tsx' }, + png = { icon = '', color = '#d4843e', name = 'Png' }, + webp = { icon = '', color = '#3498db', name = 'Webp' }, + jpg = { icon = '', color = '#16a085', name = 'Jpg' }, + svg = { icon = '', color = '#3affdb', name = 'Svg' }, + zsh = { + icon = '', + color = '#428850', + cterm_color = '65', + name = 'Zsh', + }, + }, + color_icons = true, +}) diff --git a/common/config/nvim/lua/plugins/which-key.lua b/common/config/nvim/lua/plugins/which-key.lua new file mode 100644 index 0000000..10c0c41 --- /dev/null +++ b/common/config/nvim/lua/plugins/which-key.lua @@ -0,0 +1,60 @@ +require("which-key").setup { + plugins = { + marks = true, -- shows a list of your marks on ' and ` + registers = true, -- shows your registers on " in NORMAL or <C-r> in INSERT mode + spelling = { + enabled = true, -- enabling this will show WhichKey when pressing z= to select spelling suggestions + suggestions = 9, -- how many suggestions should be shown in the list? + }, + -- the presets plugin, adds help for a bunch of default keybindings in Neovim + -- No actual key bindings are created + presets = { + operators = true, -- adds help for operators like d, y, ... and registers them for motion / text object completion + motions = true, -- adds help for motions + text_objects = true, -- help for text objects triggered after entering an operator + windows = true, -- default bindings on <c-w> + nav = true, -- misc bindings to work with windows + z = true, -- bindings for folds, spelling and others prefixed with z + g = true, -- bindings for prefixed with g + }, + }, + -- add operators that will trigger motion and text object completion + -- to enable all native operators, set the preset / operators plugin above + operators = { gc = "Comments" }, + key_labels = { + -- override the label used to display some keys. It doesn't effect WK in any other way. + -- For example: + -- ["<space>"] = "SPC", + -- ["<cr>"] = "RET", + -- ["<tab>"] = "TAB", + }, + icons = { + breadcrumb = "»", -- symbol used in the command line area that shows your active key combo + separator = "➜", -- symbol used between a key and it's label + group = "+", -- symbol prepended to a group + }, + window = { + border = "none", -- none, single, double, shadow + position = "bottom", -- bottom, top + margin = { 0, 0, 0, 0 }, -- extra window margin [top, right, bottom, left] + padding = { 1, 0, 1, 0 }, -- extra window padding [top, right, bottom, left] + }, + layout = { + height = { min = 1, max = 25 }, -- min and max height of the columns + width = { min = 20, max = 50 }, -- min and max width of the columns + spacing = 1, -- spacing between columns + align = "center", -- align columns left, center or right + }, + ignore_missing = false, -- enable this to hide mappings for which you didn't specify a label + hidden = { "<silent>", "<cmd>", "<Cmd>", "<CR>", "call", "lua", "^:", "^ " }, -- hide mapping boilerplate + show_help = true, -- show help message on the command line when the popup is visible + triggers = "auto", -- automatically setup triggers + -- triggers = {"<leader>"} -- or specify a list manually + + triggers_blacklist = { + -- list of mode / prefixes that should never be hooked by WhichKey + -- this is mostly relevant for key maps that start with a native binding + -- most people should not need to change this + n = { "o", "O" }, + }, +} diff --git a/common/config/nvim/lua/plugins/zen-mode.lua b/common/config/nvim/lua/plugins/zen-mode.lua new file mode 100644 index 0000000..7e52854 --- /dev/null +++ b/common/config/nvim/lua/plugins/zen-mode.lua @@ -0,0 +1,7 @@ +local status, zenMode = pcall(require, "zen-mode") +if (not status) then return end + +zenMode.setup { +} + +vim.keymap.set('n', '<C-w>o', '<cmd>ZenMode<cr>', { silent = true }) diff --git a/common/config/nvim/lua/user/keys.lua b/common/config/nvim/lua/user/keys.lua new file mode 100644 index 0000000..87d852b --- /dev/null +++ b/common/config/nvim/lua/user/keys.lua @@ -0,0 +1,472 @@ +local keymap = vim.keymap +local map = function(mode, l, r, opts) + opts = opts or {} + opts.silent = true + opts.noremap = true + keymap.set(mode, l, r, opts) +end +local term_opts = { noremap = true, silent = false } +local mods = require("user.mods") +local bufnr = vim.api.nvim_get_current_buf() + +-- Semi-colon as leader key +vim.g.mapleader = ";" + +-- "jk" and "kj" to exit insert-mode +map("i", "jk", "<esc>") + +-- Jump to next match on line using `.` instead of `;` NOTE: commented out in favour of "ggandor/flit.nvim" +--map("n", ".", ";") + +-- Repeat last command using `<Space>` instead of `.` NOTE: commented out in favour of "ggandor/flit.nvim" +--map("n", "<Space>", ".") + +-- Reload nvim config +map("n", "<leader><CR>", + "<cmd>luafile ~/.config/nvim/init.lua<CR> | :echom ('Nvim config loading...') | :sl! | echo ('')<CR>") + +--------------- Extended Operations --------------- +-- Conditional 'q' to quit on floating/quickfix/help windows otherwise still use it for macros +-- TODO: Have a list of if available on system/packages, example "Zen Mode" to not work on it (quit Zen Mode) +map("n", "q", function() + local config = vim.api.nvim_win_get_config(0) + if config.relative ~= "" then -- is_floating_window? + return ":silent! close!<CR>" + elseif vim.o.buftype == "quickfix" then + return ":quit<CR>" + elseif vim.o.buftype == "help" then + return ":close<CR>" + else + return "q" + end +end, { expr = true, replace_keycodes = true }) + +-- Edit new file +map("n", "<leader>;", [[:e <C-R>=expand("%:h")..'/'<CR>]], { noremap = true, silent = true, desc = "New file" }) + +-- Write as sudo +map("c", "W", "exe 'w !sudo tee >/dev/null %:p:S' | setl nomod", { silent = true, desc = "Write as Sudo" }) + +-- Combine buffers list with buffer name +map("n", "<Leader>b", ":buffers<CR>:buffer<Space>") + +-- Buffer confirmation +map("n", "<leader>y", ":BufferPick<CR>") + +-- Map buffer next, prev and delete to <leader>+(n/p/d) respectively and tab/s-tab +map("n", "<leader>n", ":bn<cr>") +map("n", "<leader>p", ":bp<cr>") +map("n", "<leader>d", ":bd<cr>") +map("n", "<TAB>", ":bnext<CR>") +map("n", "<S-TAB>", ":bprevious<CR>") + +-- Delete file of current buffer +map("n", "<leader>rm", "<CMD>call delete(expand('%')) | bdelete!<CR>") + +-- List marks +map("n", "<Leader>m", ":marks<CR>") + +-- Messages +map("n", "<Leader>M", ":messages<CR>") + +--- Clear messages or just refresh/redraw the screen +map("n", "<leader>i", "<cmd>lua require('notify').dismiss()<CR>") + +-- Unsets the 'last search pattern' register by hitting return +--map("n", "<CR>", "!silent :noh<CR><CR>") + +-- Toggle set number +map("n", "<leader>$", ":NumbersToggle<CR>") +map("n", "<leader>%", ":NumbersOnOff<CR>") + +-- Easier split navigations, just ctrl-j instead of ctrl-w then j +map("t", "<C-[>", "<C-\\><C-N>") +map("t", "<C-h>", "<C-\\><C-N><C-h>") +map("t", "<C-j>", "<C-\\><C-N><C-j>") +map("t", "<C-k>", "<C-\\><C-N><C-k>") +map("t", "<C-l>", "<C-\\><C-N><C-l>") + +-- Split window +map("n", "<leader>-", ":split<CR>") +map("n", "<leader>\\", ":vsplit<CR>") +map("n", "<leader>c", "<C-w>c") + +-- Resize Panes +--map('n', '<Leader>+', ':resize +5<CR>') +--map('n', '<Leader>-', ':resize -5<CR>') +map("n", "<Leader><", ":vertical resize +5<CR>") +map("n", "<Leader>>", ":vertical resize -5<CR>") +map("n", "<Leader>=", "<C-w>=") + +-- Map Alt+(h/j/k/l) in insert(include terminal/command) mode to move directional +map({ "i", "t", "c" }, "<A-h>", "<left>") +map({ "i", "t", "c" }, "<A-j>", "<down>") +map({ "i", "t", "c" }, "<A-k>", "<up>") +map({ "i", "t", "c" }, "<A-l>", "<right>") + +-- Create tab, edit and move between them +map("n", "<C-T>n", ":tabnew<CR>") +map("n", "<C-T>e", ":tabedit") +map("n", "<leader>[", ":tabprev<CR>") +map("n", "<leader>]", ":tabnext<CR>") + +-- "Zoom" a split window into a tab and/or close it +--map("n", "<Leader>,", ":tabnew %<CR>") +--map("n", "<Leader>.", ":tabclose<CR>") + +-- Vim TABs +map("n", "<leader>1", "1gt<CR>") +map("n", "<leader>2", "2gt<CR>") +map("n", "<leader>3", "3gt<CR>") +map("n", "<leader>4", "4gt<CR>") +map("n", "<leader>5", "5gt<CR>") +map("n", "<leader>6", "6gt<CR>") +map("n", "<leader>7", "7gt<CR>") +map("n", "<leader>8", "8gt<CR>") +map("n", "<leader>9", "9gt<CR>") +map("n", "<leader>0", "10gt<CR>") + +-- Hitting ESC when inside a terminal to get into normal mode +--map("t", "<Esc>", [[<C-\><C-N>]]) + +-- Move block (indentation) easily +--map("n", "<", "<<", term_opts) +--map("n", ">", ">>", term_opts) +--map("x", "<", "<gv", term_opts) +--map("x", ">", ">gv", term_opts) +map("v", "<", "<gv") +map("v", ">", ">gv") +map("n", "<", "<S-v><<esc>") +map("n", ">", "<S-v>><esc>") + +-- Set alt+(j/k) to switch lines of texts or simply move them +map("n", "<A-k>", ':let save_a=@a<Cr><Up>"add"ap<Up>:let @a=save_a<Cr>') +map("n", "<A-j>", ':let save_a=@a<Cr>"add"ap:let @a=save_a<Cr>') + +-- Toggle Diff +map("n", "<leader>df", "<Cmd>call utils#ToggleDiff()<CR>") + +-- Toggle Verbose +map("n", "<leader>uvt", "<Cmd>call utils#VerboseToggle()<CR>") + +-- Jump List +map("n", "<leader>j", "<Cmd>call utils#GotoJump()<CR>") + +-- Rename file +map("n", "<leader>rf", "<Cmd>call utils#RenameFile()<CR>") + +-- Map delete to Ctrl+l +map("i", "<C-l>", "<Del>") + +-- Clear screen +map("n", "<leader><C-l>", "<Cmd>!clear<CR>") + +-- Change file to an executable +map("n", "<Leader>x", + ":lua require('user.mods').Toggle_executable()<CR> | :echom ('Toggle executable')<CR> | :sl! | echo ('')<CR>") +-- map("n", "<leader>x", ":!chmod +x %<CR>") + +-- Paste without replace clipboard +map("v", "p", '"_dP') + +-- Swap two pieces of text, use x to cut in visual mode, then use Ctrl-x in +-- visual mode to select text to swap with +--map("v", "<C-X>", "<Esc>`.``gvP``P") + +-- Change Working Directory to current project +map("n", "<leader>cd", ":cd %:p:h<CR>:pwd<CR>") + +-- Open the current file in the default program (on Mac this should just be just `open`) +map("n", "<leader>o", ":!xdg-open %<cr><cr>") + +-- URL handling +if vim.fn.has("mac") == 1 then + map("", "gx", '<Cmd>call jobstart(["open", expand("<cfile>")], {"detach": v:true})<CR>', {}) +elseif vim.fn.has("unix") == 1 then + map("", "gx", '<Cmd>call jobstart(["xdg-open", expand("<cfile>")], {"detach": v:true})<CR>', {}) +elseif vim.fn.has("wsl") == 1 then + map("", "gx", '<Cmd>call jobstart(["wslview", expand("<cfile>")], {"detach": v:true})<CR>', {}) +else + map[""].gx = { '<Cmd>lua print("Error: gx is not supported on this OS!")<CR>' } +end + +-- Search and replace +map("v", "<leader>sr", 'y:%s/<C-r><C-r>"//g<Left><Left>c') + +-- Substitute globally and locally in the selected region. +map("n", "<leader>s", ":%s//g<Left><Left>") +map("v", "<leader>s", ":s//g<Left><Left>") + +-- Toggle completion +map("n", "<Leader>tc", ':lua require("user.mods").toggle_completion()<CR>') + +-- Disable default completion. +map("i", "<C-n>", "<Nop>") +map("i", "<C-p>", "<Nop>") + +-- Set line wrap +map("n", "<M-z>", function() + local wrap_status = vim.api.nvim_exec("set wrap ?", true) + + if wrap_status == "nowrap" then + vim.api.nvim_command("set wrap linebreak") + print("Wrap enabled") + else + vim.api.nvim_command("set wrap nowrap") + print("Wrap disabled") + end +end, { silent = true }) + +-- Toggle between folds +map("n", "<Space>", "&foldlevel ? 'zM' : 'zR'", { expr = true }) + +-- Use space to toggle fold +--map("n", "<Space>", "za") + +-- Make a copy of current file +--vim.cmd([[ +-- map <leader>s :up \| saveas! %:p:r-<C-R>=strftime("%y.%m.%d-%H:%M")<CR>-bak.<C-R>=expand("%:e")<CR> \| 3sleep \| e #<CR> +--]]) +map("n", "<leader>.b", ":!cp % %.backup<CR>") + +-- Toggle transparency +map("n", "<leader>tb", ":call utils#Toggle_transparent_background()<CR>") + +-- Toggle zoom +map("n", "<leader>z", ":call utils#ZoomToggle()<CR>") +map("n", "<C-w>z", "<C-w>|<C-w>_") + +-- Toggle statusline +map("n", "<leader>sl", ":call utils#ToggleHiddenAll()<CR>") + +-- Open last closed buffer +map("n", "<C-t>", ":call OpenLastClosed()<CR>") + +---------------- Plugin Operations ---------------- +-- Packer +map("n", "<leader>Pc", "<cmd>PackerCompile<cr>") +map("n", "<leader>Pi", "<cmd>PackerInstall<cr>") +map("n", "<leader>Ps", "<cmd>PackerSync<cr>") +map("n", "<leader>PS", "<cmd>PackerStatus<cr>") +map("n", "<leader>Pu", "<cmd>PackerUpdate<cr>") + +-- Tmux navigation (aserowy/tmux.nvim) +map("n", "<C-h>", "<CMD>NavigatorLeft<CR>") +map("n", "<C-l>", "<CMD>NavigatorRight<CR>") +map("n", "<C-k>", "<CMD>NavigatorUp<CR>") +map("n", "<C-j>", "<CMD>NavigatorDown<CR>") + +-- ToggleTerm +map({ "n", "t" }, "<leader>tt", "<cmd>ToggleTerm<CR>") +map({ "n", "t" }, "<leader>th", "<cmd>lua Horizontal_term_toggle()<CR>") +map({ "n", "t" }, "<leader>tv", "<cmd>lua Vertical_term_toggle()<CR>") + +-- LazyGit +map({ "n", "t" }, "<leader>gg", "<cmd>lua Lazygit_toggle()<CR>") + +map("n", "<leader>tg", "<cmd>lua Gh_dash()<CR>") + +-- Fugitive git bindings +map("n", "<leader>gs", vim.cmd.Git) +map("n", "<leader>ga", ":Git add %:p<CR><CR>") +--map("n", "<leader>gs", ":Gstatus<CR>") +map("n", "<leader>gc", ":Gcommit -v -q<CR>") +map("n", "<leader>gt", ":Gcommit -v -q %:p<CR>") +--map("n", "<leader>gd", ":Gdiff<CR>") +map("n", "<leader>ge", ":Gedit<CR>") +--map("n", "<leader>gr", ":Gread<Cj>") +map("n", "<leader>gw", ":Gwrite<CR><CR>") +map("n", "<leader>gl", ":silent! Glog<CR>:bot copen<CR>") +--map("n", "<leader>gp", ":Ggrep<Space>") +--map("n", "<Leader>gp", ":Git push<CR>") +--map("n", "<Leader>gb", ":Gblame<CR>") +map("n", "<leader>gm", ":Gmove<Space>") +--map("n", "<leader>gb", ":Git branch<Space>") +--map("n", "<leader>go", ":Git checkout<Space>") +--map("n", "<leader>gps", ":Dispatch! git push<CR>") +--map("n", "<leader>gpl", ":Dispatch! git pull<CR>") + +-- Telescope +map("n", "<leader>ff", ":cd %:p:h<CR>:pwd<CR><cmd>lua require('telescope.builtin').find_files()<cr>") -- find files with hidden option +map("n", "<leader>fF", ":cd %:p:h<CR>:pwd<CR><cmd>lua require('user.mods').findFilesInCwd()<CR>", + { noremap = true, silent = true, desc = "Find files in cwd" }) +map("n", "<leader>f.", function() + require("telescope.builtin").find_files({ hidden = true, no_ignore = true }) +end) -- find all files +map("n", "<leader>fg", "<cmd>lua require('telescope.builtin').live_grep()<cr>") +map("n", "<leader>fb", "<cmd>lua require('telescope.builtin').buffers()<cr>") +map("n", "<leader>fh", "<cmd>lua require('telescope.builtin').help_tags()<cr>") +map("n", "<leader>fc", "<cmd>lua require('telescope.builtin').commands()<cr>") +map("n", "<leader>cf", "<cmd>Telescope changed_files<cr>") +map("n", "<leader>fp", "<cmd>Telescope pickers<cr>") +map("n", "<leader>fd", "<cmd>lua require('telescope.builtin').diagnostics()<cr>") +map("n", "<leader>fk", "<cmd>lua require('telescope.builtin').keymaps()<cr>") +map("n", "<leader>fr", "<cmd>lua require('telescope.builtin').registers({})<CR>") -- registers picker +map("n", "<leader>fm", "<cmd>lua require('telescope').extensions.media_files.media_files({})<cr>") -- find media files +map("n", "<leader>fi", "<cmd>lua require('telescope').extensions.notify.notify({})<cr>") -- find notifications +map("n", "<Leader>fs", '<cmd>lua require("session-lens").search_session()<CR>') +map("n", "<leader>ffd", [[<Cmd>lua require'plugins.telescope'.find_dirs()<CR>]]) -- find dies +map("n", "<leader>ff.", [[<Cmd>lua require'plugins.telescope'.find_configs()<CR>]]) -- find configs +map("n", "<leader>ffs", [[<Cmd>lua require'plugins.telescope'.find_scripts()<CR>]]) -- find scripts +map("n", "<leader>ffw", [[<Cmd>lua require'plugins.telescope'.find_projects()<CR>]]) -- find projects +map("n", "<leader>ffb", [[<Cmd>lua require'plugins.telescope'.find_books()<CR>]]) -- find books +map("n", "<leader>ffn", [[<Cmd>lua require'plugins.telescope'.find_notes()<CR>]]) -- find notes +map("n", "<leader>fgn", [[<Cmd>lua require'plugins.telescope'.grep_notes()<CR>]]) -- search notes +map("n", "<Leader>frf", "<cmd>lua require('telescope').extensions.recent_files.pick()<CR>") +map("n", "<leader>ffc", "<cmd>lua require('telescope.builtin').current_buffer_fuzzy_find()<cr>") +map("n", "<Leader>f/", "<cmd>lua require('telescope').extensions.file_browser.file_browser()<CR>") +--map("n", "<leader>f/", "<cmd>lua require('plugins.telescope').curbuf()<cr>") -- find files with hidden option +-- Map a shortcut to open the picker. + +-- FZF +map("n", "<leader>fz", "<cmd>lua require('fzf-lua').files()<CR>") + +-- Nvim-tree +map("n", "<leader>e", "<cmd>Rooter<CR>:NvimTreeToggle<CR>", {}) + +-- Undotree +map("n", "<leader>u", vim.cmd.UndotreeToggle) + +-- Markdown-preview +map("n", "<leader>md", "<Plug>MarkdownPreviewToggle") +map("n", "<leader>mg", "<CMD>Glow<CR>") + +-- Autopairs +map("n", "<leader>ww", "<cmd>lua require('user.mods').Toggle_autopairs()<CR>") + +-- Zen-mode toggle +map("n", "<leader>zm", "<CMD>ZenMode<CR> | :echom ('Zen Mode')<CR> | :sl! | echo ('')<CR>") + +-- Vim-rooter +map("n", "<leader>ro", "<CMD>Rooter<CR> | :echom ('cd to root/project directory')<CR> | :sl! | echo ('')<CR>", term_opts) + +-- Trouble (UI to show diagnostics) +map("n", "<leader>t", ":cd %:p:h<CR>:pwd<CR><CMD>TroubleToggle<CR>") +map("n", "<leader>tw", ":cd %:p:h<CR>:pwd<CR><CMD>TroubleToggle workspace_diagnostics<CR>") +map("n", "<leader>td", ":cd %:p:h<CR>:pwd<CR><CMD>TroubleToggle document_diagnostics<CR>") +map("n", "<leader>tq", ":cd %:p:h<CR>:pwd<CR><CMD>TroubleToggle quickfix<CR>") +map("n", "<leader>tl", ":cd %:p:h<CR>:pwd<CR><CMD>TroubleToggle loclist<CR>") +map("n", "gR", "<CMD>TroubleToggle lsp_references<CR>") + +-- Null-ls +map("n", "<leader>ls", "<CMD>NullLsToggle<CR>") + +-- Replacer +map("n", "<Leader>qr", ':lua require("replacer").run()<CR>') + +-- Quickfix +map("n", "<leader>q", function() + if vim.fn.getqflist({ winid = 0 }).winid ~= 0 then + require("plugins.quickfix").close() + else + require("plugins.quickfix").open() + end +end, { desc = "Toggle quickfix window" }) + +-- Move to the next and previous item in the quickfixlist +map("n", "]c", "<Cmd>cnext<CR>") +map("n", "[c", "<Cmd>cprevious<CR>") + +-- Location list +map("n", "<leader>l", '<cmd>lua require("plugins.loclist").loclist_toggle()<CR>') + +-- Dap (debugging) +local dap_ok, dap = pcall(require, "dap") +local dap_ui_ok, ui = pcall(require, "dapui") + +if not (dap_ok and dap_ui_ok) then + require("notify")("nvim-dap or dap-ui not installed!", "warning") + return +end + +vim.fn.sign_define("DapBreakpoint", { text = "🐞" }) + +-- Start debugging session +map("n", "<leader>ds", function() + dap.continue() + ui.toggle({}) + vim.api.nvim_feedkeys(vim.api.nvim_replace_termcodes("<C-w>=", false, true, true), "n", false) -- Spaces buffers evenly +end) + +-- Set breakpoints, get variable values, step into/out of functions, etc. +map("n", "<leader>dC", dap.continue) +-- map("n", "<leader>dC", dap.close) +-- map("n", "<leader>dt", dap.terminate) +map("n", "<leader>dt", ui.toggle) +map("n", "<leader>dd", function() + dap.disconnect({ terminateDebuggee = true }) +end) +map("n", "<leader>dn", dap.step_over) +map("n", "<leader>di", dap.step_into) +map("n", "<leader>do", dap.step_out) +map("n", "<leader>db", dap.toggle_breakpoint) +map("n", "<leader>dB", function() + dap.clear_breakpoints() + require("notify")("Breakpoints cleared", "warn") +end) +map("n", "<leader>dl", require("dap.ui.widgets").hover) +map("n", "<leader>de", function() + require("dapui").float_element() +end, { desc = "Open Element" }) +map("n", "<leader>dq", function() + require("dapui").close() + require("dap").repl.close() + local session = require("dap").session() + if session then + require("dap").terminate() + end + require("nvim-dap-virtual-text").refresh() +end, { desc = "Terminate Debug" }) +map("n", "<leader>dc", function() + require("telescope").extensions.dap.commands() +end, { desc = "DAP-Telescope: Commands" }) +--vim.keymap.set("n", "<leader>B", ":lua require'dap'.set_breakpoint(vim.fn.input('Breakpoint condition: '))<CR>") +--vim.keymap.set("v", "<leader>B", ":lua require'dap'.set_breakpoint(vim.fn.input('Breakpoint condition: '))<CR>") +--vim.keymap.set("n", "<leader>lp", ":lua require'dap'.set_breakpoint(nil, nil, vim.fn.input('Log point message: '))<CR>") +--vim.keymap.set("n", "<leader>dr", ":lua require'dap'.repl.open()<CR>") + +-- Close debugger and clear breakpoints +--map("n", "<leader>de", function() +-- dap.clear_breakpoints() +-- ui.toggle({}) +-- dap.terminate() +-- vim.api.nvim_feedkeys(vim.api.nvim_replace_termcodes("<C-w>=", false, true, true), "n", false) +-- require("notify")("Debugger session ended", "warn") +--end) + +-- Toggle Dashboard +map("n", "<leader><Space>", '<CMD>lua require("user.mods").toggle_dashboard()<CR>') + +-- Lsp Lines toggle +map("", "<Leader>ll", require("lsp_lines").toggle, { desc = "Toggle lsp_lines" }) + +-- SnipRun +map({ "n", "v" }, "<leader>r", "<Plug>SnipRun<CR>") + +-- Codi +map("n", "<leader>co", '<CMD>lua require("user.mods").toggleCodi()<CR>') + +-- Scratch buffer +map("n", "<leader>ss", '<CMD>lua require("user.mods").Scratch("float")<CR>') +map("n", "<leader>sh", '<CMD>lua require("user.mods").Scratch("horizontal")<CR>') +map("n", "<leader>sv", '<CMD>lua require("user.mods").Scratch("vertical")<CR>') + +-- Hardtime +map("n", "<leader>H", '<CMD>lua require("plugins.hardtime").ToggleHardtime()<CR>') + +-- Code Run +map("n", "<leader>rr", '<CMD>lua require("user.mods").toggleCodeRunner()<CR>') + +-- Run executable file +map("n", "<leader>rx", + ":lua require('user.mods').RunCurrentFile()<CR>:echom 'Running executable file...'<CR>:sl!<CR>:echo ''<CR>") + +-- Close all floating windows +map({ "n", "t", "c" }, "<leader>w", "<CMD>CloseFloatingWindows<CR>") + +-- Vimtex +map("n", "<Leader>lc", ":VimtexCompile<cr>") +map("v", "<Leader>ls", ":VimtexCompileSelected<cr>") +map("n", "<Leader>li", ":VimtexInfo<cr>") +map("n", "<Leader>lt", ":VimtexTocToggle<cr>") +map("n", "<Leader>lv", ":VimtexView<cr>") diff --git a/common/config/nvim/lua/user/mods.lua b/common/config/nvim/lua/user/mods.lua new file mode 100644 index 0000000..c20c687 --- /dev/null +++ b/common/config/nvim/lua/user/mods.lua @@ -0,0 +1,1065 @@ +local M = {} + +--- Shorten Function Names +local fn = vim.fn +function M.executable(name) + if fn.executable(name) > 0 then + return true + end + + return false +end + +-------------------------------------------------- + +--- Check whether a feature exists in Nvim +--- @feat: string +--- the feature name, like `nvim-0.7` or `unix`. +--- return: bool +M.has = function(feat) + if fn.has(feat) == 1 then + return true + end + + return false +end + +-------------------------------------------------- + +-- Format on save +local format_augroup = vim.api.nvim_create_augroup("LspFormatting", {}) +require("null-ls").setup({ + -- you can reuse a shared lspconfig on_attach callback here + on_attach = function(client, bufnr) + if client.supports_method("textDocument/formatting") then + vim.api.nvim_clear_autocmds({ group = format_augroup, buffer = bufnr }) + vim.api.nvim_create_autocmd("BufWritePre", { + group = format_augroup, + buffer = bufnr, + callback = function() + -- on 0.8, you should use vim.lsp.buf.format({ bufnr = bufnr }) instead + --vim.lsp.buf.formatting_seq_sync() + vim.lsp.buf.format({ bufnr = bufnr }) + end, + }) + end + end, +}) + +vim.cmd([[autocmd BufWritePre <buffer> lua vim.lsp.buf.format()]]) +--vim.cmd [[autocmd BufWritePre * lua vim.lsp.buf.format()]] + +-------------------------------------------------- + +---Determine if a value of any type is empty +---@param item any +---@return boolean? +function M.empty(item) + if not item then + return true + end + local item_type = type(item) + if item_type == "string" then + return item == "" + end + if item_type == "number" then + return item <= 0 + end + if item_type == "table" then + return vim.tbl_isempty(item) + end + return item ~= nil +end + +-------------------------------------------------- + +--- Create a dir if it does not exist +function M.may_create_dir(dir) + local res = fn.isdirectory(dir) + + if res == 0 then + fn.mkdir(dir, "p") + end +end + +-------------------------------------------------- + +--- Toggle cmp completion +vim.g.cmp_toggle_flag = false -- initialize +local normal_buftype = function() + return vim.api.nvim_buf_get_option(0, "buftype") ~= "prompt" +end +M.toggle_completion = function() + local ok, cmp = pcall(require, "cmp") + if ok then + local next_cmp_toggle_flag = not vim.g.cmp_toggle_flag + if next_cmp_toggle_flag then + print("completion on") + else + print("completion off") + end + cmp.setup({ + enabled = function() + vim.g.cmp_toggle_flag = next_cmp_toggle_flag + if next_cmp_toggle_flag then + return normal_buftype + else + return next_cmp_toggle_flag + end + end, + }) + else + print("completion not available") + end +end + +-------------------------------------------------- + +--- Make sure using latest neovim version +function M.get_nvim_version() + local actual_ver = vim.version() + + local nvim_ver_str = string.format("%d.%d.%d", actual_ver.major, actual_ver.minor, actual_ver.patch) + return nvim_ver_str +end + +function M.add_pack(name) + local status, error = pcall(vim.cmd, "packadd " .. name) + + return status +end + +-------------------------------------------------- + +-- Define a global function to retrieve LSP clients based on Neovim version +function M.get_lsp_clients(bufnr) + local mods = require("user.mods") + --local expected_ver = '0.10.0' + local nvim_ver = mods.get_nvim_version() + + local version_major, version_minor = string.match(nvim_ver, "(%d+)%.(%d+)") + version_major = tonumber(version_major) + version_minor = tonumber(version_minor) + + if version_major > 0 or (version_major == 0 and version_minor >= 10) then + return vim.lsp.get_clients({ buffer = bufnr }) + else + return vim.lsp.buf_get_clients() + end +end + +-------------------------------------------------- + +--- Toggle autopairs on/off (requires "windwp/nvim-autopairs") +function M.Toggle_autopairs() + local ok, autopairs = pcall(require, "nvim-autopairs") + if ok then + if autopairs.state.disabled then + autopairs.enable() + print("autopairs on") + else + autopairs.disable() + print("autopairs off") + end + else + print("autopairs not available") + end +end + +-------------------------------------------------- + +--- Make vim-rooter message disappear after making it's changes +--vim.cmd([[ +--let timer = timer_start(1000, 'LogTrigger', {}) +--func! LogTrigger(timer) +-- silent! +--endfunc +--]]) +-- +--vim.cmd([[ +--function! ConfigureChDir() +-- echo ('') +--endfunction +--" Call after vim-rooter changes the root dir +--autocmd User RooterChDir :sleep! | call LogTrigger(timer) | call ConfigureChDir() +--]]) + +function M.findFilesInCwd() + vim.cmd("let g:rooter_manual_only = 1") -- Toggle the rooter plugin + require("plugins.telescope").findhere() + vim.defer_fn(function() + vim.cmd("let g:rooter_manual_only = 0") -- Change back to automatic rooter + end, 100) +end + +--function M.findFilesInCwd() +-- vim.cmd("let g:rooter_manual_only = 1") -- Toggle the rooter plugin +-- require("plugins.telescope").findhere() +-- --vim.cmd("let g:rooter_manual_only = 0") -- Change back to automatic rooter +--end + +-------------------------------------------------- + +-- Toggle the executable permission +function M.Toggle_executable() + local current_file = vim.fn.expand("%:p") + local executable = vim.fn.executable(current_file) == 1 + + if executable then + -- File is executable, unset the executable permission + vim.fn.system("chmod -x " .. current_file) + --print(current_file .. ' is no longer executable.') + print("No longer executable") + else + -- File is not executable, set the executable permission + vim.fn.system("chmod +x " .. current_file) + --print(current_file .. ' is now executable.') + print("Now executable") + end +end + +-------------------------------------------------- + +-- Set bare dotfiles repository git environment variables dynamically + +-- Set git enviornment variables +--function M.Set_git_env_vars() +-- local git_dir_job = vim.fn.jobstart({ "git", "rev-parse", "--git-dir" }) +-- local command_status = vim.fn.jobwait({ git_dir_job })[1] +-- if command_status > 0 then +-- vim.env.GIT_DIR = vim.fn.expand("$HOME/.cfg") +-- vim.env.GIT_WORK_TREE = vim.fn.expand("~") +-- else +-- vim.env.GIT_DIR = nil +-- vim.env.GIT_WORK_TREE = nil +-- end +-- -- Launch terminal emulator with Git environment variables set +-- --require("toggleterm").exec(string.format([[%s %s]], os.getenv("SHELL"), "-i")) +--end + +------ + +local prev_cwd = "" + +function M.Set_git_env_vars() + local cwd = vim.fn.getcwd() + if prev_cwd == "" then + -- First buffer being opened, set prev_cwd to cwd + prev_cwd = cwd + elseif cwd ~= prev_cwd then + -- Working directory has changed since last buffer was opened + prev_cwd = cwd + local git_dir_job = vim.fn.jobstart({ "git", "rev-parse", "--git-dir" }) + local command_status = vim.fn.jobwait({ git_dir_job })[1] + if command_status > 0 then + vim.env.GIT_DIR = vim.fn.expand("$HOME/.cfg") + vim.env.GIT_WORK_TREE = vim.fn.expand("~") + else + vim.env.GIT_DIR = nil + vim.env.GIT_WORK_TREE = nil + end + end +end + +vim.cmd([[augroup my_git_env_vars]]) +vim.cmd([[ autocmd!]]) +vim.cmd([[ autocmd BufEnter * lua require('user.mods').Set_git_env_vars()]]) +vim.cmd([[ autocmd VimEnter * lua require('user.mods').Set_git_env_vars()]]) +vim.cmd([[augroup END]]) + +-------------------------------------------------- + +--- Update Tmux Status Vi-mode +function M.update_tmux_status() + -- Check if the current buffer has a man filetype + if vim.bo.filetype == "man" then + return + end + local mode = vim.api.nvim_eval("mode()") + -- Determine the mode name based on the mode value + local mode_name + if mode == "n" then + mode_name = "-- NORMAL --" + elseif mode == "i" or mode == "ic" then + mode_name = "-- INSERT --" + else + mode_name = "-- NORMAL --" --'-- COMMAND --' + end + + -- Write the mode name to the file + local file = io.open(os.getenv("HOME") .. "/.vi-mode", "w") + file:write(mode_name) + file:close() + if nvim_running then + -- Neovim is running, update the mode file and refresh tmux + VI_MODE = "" -- Clear VI_MODE to show Neovim mode + vim.cmd("silent !tmux refresh-client -S") + end + ---- Force tmux to update the status + vim.cmd("silent !tmux refresh-client -S") +end + +vim.cmd([[ + augroup TmuxStatus + autocmd! + autocmd InsertLeave,InsertEnter * lua require("user.mods").update_tmux_status() + autocmd VimEnter * lua require("user.mods").update_tmux_status() + autocmd BufEnter * lua require("user.mods").update_tmux_status() + autocmd ModeChanged * lua require("user.mods").update_tmux_status() + autocmd WinEnter,WinLeave * lua require("user.mods").update_tmux_status() + augroup END +]]) + +-- Add autocmd for <esc> +-- Add autocmd to check when tmux switches panes/windows +--autocmd InsertLeave,InsertEnter * lua require("user.mods").update_tmux_status() +--autocmd BufEnter * lua require("user.mods").update_tmux_status() +--autocmd WinEnter,WinLeave * lua require("user.mods").update_tmux_status() + +--autocmd WinEnter,WinLeave * lua require("user.mods").update_tmux_status() +--autocmd VimResized * lua require("user.mods").update_tmux_status() +--autocmd FocusGained * lua require("user.mods").update_tmux_status() +--autocmd FocusLost * lua require("user.mods").update_tmux_status() +--autocmd CmdwinEnter,CmdwinLeave * lua require("user.mods").update_tmux_status() + +-------------------------------------------------- + +-- function OpenEmulatorList() +-- local emulatorsBuffer = vim.api.nvim_create_buf(false, true) +-- vim.api.nvim_buf_set_lines(emulatorsBuffer, 0, 0, true, {"Some text"}) +-- vim.api.nvim_open_win( +-- emulatorsBuffer, +-- false, +-- { +-- relative='win', row=3, col=3, width=12, height=3 +-- } +-- ) +-- end +-- +-- vim.api.nvim_create_user_command('OpenEmulators', OpenEmulatorList, {}) + +--local api = vim.api +--local fn = vim.fn +--local cmd = vim.cmd +-- +--local function bufremove(opts) +-- local target_buf_id = api.nvim_get_current_buf() +-- +-- -- Do nothing if buffer is in modified state. +-- if not opts.force and api.nvim_buf_get_option(target_buf_id, 'modified') then +-- return false +-- end +-- +-- -- Hide target buffer from all windows. +-- vim.tbl_map(function(win_id) +-- win_id = win_id or 0 +-- +-- local current_buf_id = api.nvim_win_get_buf(win_id) +-- +-- api.nvim_win_call(win_id, function() +-- -- Try using alternate buffer +-- local alt_buf_id = fn.bufnr('#') +-- if alt_buf_id ~= current_buf_id and fn.buflisted(alt_buf_id) == 1 then +-- api.nvim_win_set_buf(win_id, alt_buf_id) +-- return +-- end +-- +-- -- Try using previous buffer +-- cmd('bprevious') +-- if current_buf_id ~= api.nvim_win_get_buf(win_id) then +-- return +-- end +-- +-- -- Create new listed scratch buffer +-- local new_buf = api.nvim_create_buf(true, true) +-- api.nvim_win_set_buf(win_id, new_buf) +-- end) +-- +-- return true +-- end, fn.win_findbuf(target_buf_id)) +-- +-- cmd(string.format('bdelete%s %d', opts.force and '!' or '', target_buf_id)) +--end +-- +---- Assign bufremove to a global variable +--_G.bufremove = bufremove + +--vim.cmd([[ +-- augroup NvimTreeDelete +-- autocmd! +-- autocmd FileType NvimTree lua require('user.mods').enew_on_delete() +-- augroup END +--]]) +-- +--function M.enew_on_delete() +-- if vim.bo.buftype == 'nofile' then +-- vim.cmd('enew') +-- end +--end + +-- Update Neovim +--function M.Update_neovim() +-- -- Run the commands to download and extract the latest version +-- os.execute("curl -L -o nvim-linux64.tar.gz https://github.com/neovim/neovim/releases/latest/download/nvim-linux64.tar.gz") +-- os.execute("tar xzvf nvim-linux64.tar.gz") +-- -- Replace the existing Neovim installation with the new version +-- os.execute("rm -rf $HOME/.local/bin/nvim") +-- os.execute("mv nvim-linux64 $HOME/.local/bin/nvim") +-- +-- -- Clean up the downloaded file +-- os.execute("rm nvim-linux64.tar.gz") +-- +-- -- Print a message to indicate the update is complete +-- print("Neovim has been updated to the latest version.") +--end +-- +---- Bind a keymap to the update_neovim function (optional) +--vim.api.nvim_set_keymap('n', '<leader>u', '<cmd> lua require("user.mods").Update_neovim()<CR>', { noremap = true, silent = true }) + +-- Define a function to create a floating window and run the update process inside it +function M.Update_neovim() + -- Create a new floating window + local bufnr, winid = vim.api.nvim_create_buf(false, true) + vim.api.nvim_open_win(bufnr, true, { + relative = "editor", + width = 80, + height = 20, + row = 2, + col = 2, + style = "minimal", + border = "single", + }) + + -- Function to append a line to the buffer in the floating window + local function append_line(line) + vim.api.nvim_buf_set_option(bufnr, "modifiable", true) + vim.api.nvim_buf_set_lines(bufnr, -1, -1, false, { line }) + vim.api.nvim_buf_set_option(bufnr, "modifiable", false) + end + + -- Download the latest version of Neovim + append_line("Downloading the latest version of Neovim...") + os.execute( + "curl -L -o nvim-linux64.tar.gz https://github.com/neovim/neovim/releases/latest/download/nvim-linux64.tar.gz") + append_line("Download complete.") + + -- Extract the downloaded archive + append_line("Extracting the downloaded archive...") + os.execute("tar xzvf nvim-linux64.tar.gz") + append_line("Extraction complete.") + + -- Replace the existing Neovim installation with the new version + append_line("Replacing the existing Neovim installation...") + os.execute("rm -rf $HOME/nvim") + os.execute("mv nvim-linux64 $HOME/nvim") + append_line("Update complete.") + + -- Clean up the downloaded file + append_line("Cleaning up the downloaded file...") + os.execute("rm nvim-linux64.tar.gz") + append_line("Cleanup complete.") + + -- Close the floating window after a delay + vim.defer_fn(function() + vim.api.nvim_win_close(winid, true) + end, 5000) -- Adjust the delay as needed +end + +-- Bind a keymap to the update_neovim function (optional) +vim.api.nvim_set_keymap("n", "<leader>U", '<cmd> lua require("user.mods").Update_neovim()<CR>', + { noremap = true, silent = true }) + +-------------------------------------------------- + +-- Fix or suppress closing nvim error message (/src/unix/core.c:147: uv_close: Assertion `!uv__is_closing(handle)' failed.) +vim.api.nvim_create_autocmd({ "VimLeave" }, { + callback = function() + vim.fn.jobstart("!notify-send 2>/dev/null &", { detach = true }) + end, +}) + +-------------------------------------------------- + +-- Rooter +--vim.cmd([[autocmd BufEnter * lua vim.cmd('Rooter')]]) + +-------------------------------------------------- + +-- Nvim-tree +local modifiedBufs = function(bufs) -- nvim-tree is also there in modified buffers so this function filter it out + local t = 0 + for k, v in pairs(bufs) do + if v.name:match("NvimTree_", "NvimTree1") == nil then + t = t + 1 + end + end + return t +end + +-- Deleting current file opened behaviour +function M.DeleteCurrentBuffer() + local cbn = vim.api.nvim_get_current_buf() + local buffers = vim.fn.getbufinfo({ buflisted = true }) + local size = #buffers + local idx = 0 + + for n, e in ipairs(buffers) do + if e.bufnr == cbn then + idx = n + break -- Exit loop as soon as we find the buffer + end + end + + if idx == 0 then + return + end + + if idx == size then + vim.cmd("bprevious") + else + vim.cmd("bnext") + end + + vim.cmd("silent! bdelete " .. cbn) + + -- Open a new blank window + vim.cmd("silent! enew") -- Opens a new vertical split + -- OR + -- vim.cmd("new") -- Opens a new horizontal split + -- Delay before opening a new split + --vim.defer_fn(function() + -- vim.cmd("enew") -- Opens a new vertical split + --end, 100) -- Adjust the delay as needed (in milliseconds) + -- Delay before closing the nvim-tree window +end + +vim.cmd([[autocmd FileType NvimTree lua require("user.mods").DeleteCurrentBuffer()]]) + +-- On :bd nvim-tree should behave as if it wasn't opened +vim.api.nvim_create_autocmd("BufEnter", { + nested = true, + callback = function() + -- Only 1 window with nvim-tree left: we probably closed a file buffer + if #vim.api.nvim_list_wins() == 1 and require("nvim-tree.utils").is_nvim_tree_buf() then + local api = require("nvim-tree.api") + -- Required to let the close event complete. An error is thrown without this. + vim.defer_fn(function() + -- close nvim-tree: will go to the last buffer used before closing + api.tree.toggle({ find_file = true, focus = true }) + -- re-open nivm-tree + api.tree.toggle({ find_file = true, focus = true }) + -- nvim-tree is still the active window. Go to the previous window. + vim.cmd("wincmd p") + end, 0) + end + end, +}) + +-- Dismiss notifications when opening nvim-tree window +local function isNvimTreeOpen() + local win = vim.fn.win_findbuf(vim.fn.bufnr("NvimTree")) + return vim.fn.empty(win) == 0 +end + +function M.DisableNotify() + if isNvimTreeOpen() then + require("notify").dismiss() + end +end + +vim.cmd([[ + autocmd! WinEnter,WinLeave * lua require('user.mods').DisableNotify() +]]) + +-------------------------------------------------- + +-- Toggle Dashboard +function M.toggle_dashboard() + if vim.bo.filetype == "dashboard" then + vim.cmd("bdelete") + else + vim.cmd("Dashboard") + end +end + +-------------------------------------------------- + +-- Helper function to suppress errors +local function silent_execute(cmd) + vim.fn["serverlist"]() -- Required to prevent 'Press ENTER' prompt + local result = vim.fn.system(cmd .. " 2>/dev/null") + vim.fn["serverlist"]() + return result +end + +-------------------------------------------------- + +-- Toggle Codi +-- Define a global variable to track Codi's state +local is_codi_open = false + +function M.toggleCodi() + if is_codi_open then + -- Close Codi + vim.cmd("Codi!") + is_codi_open = false + print("Codi off") + else + -- Open Codi + vim.cmd("Codi") + is_codi_open = true + print("Codi on") + end +end + +-------------------------------------------------- + +---- Function to create or toggle a scratch buffer +-- Define global variables to store the scratch buffer and window +local scratch_buf = nil +local scratch_win = nil + +-- Other global variables +local scratch_date = os.date("%Y-%m-%d") +local scratch_dir = vim.fn.expand("~/notes/private") +local scratch_file = "scratch-" .. scratch_date .. ".md" + +-- Function to close and delete a buffer +function CloseAndDeleteBuffer(bufnr) + if bufnr and vim.api.nvim_buf_is_valid(bufnr) then + vim.api.nvim_command("silent! bwipe " .. bufnr) + end +end + +function M.Scratch(Split_direction) + -- Check if the directory exists, and create it if it doesn't + if vim.fn.isdirectory(scratch_dir) == 0 then + vim.fn.mkdir(scratch_dir, "p") + end + + -- Determine the window type based on Split_direction + local current_window_type = "float" + if Split_direction == "float" then + current_window_type = "float" + elseif Split_direction == "vertical" then + current_window_type = "vertical" + elseif Split_direction == "horizontal" then + current_window_type = "horizontal" + end + + local file_path = scratch_dir .. "/" .. scratch_file + + if scratch_win and vim.api.nvim_win_is_valid(scratch_win) then + -- Window exists, save buffer to file and close it + WriteScratchBufferToFile(scratch_buf, file_path) + vim.cmd(":w!") + vim.api.nvim_win_close(scratch_win, true) + CloseAndDeleteBuffer(scratch_buf) + scratch_win = nil + scratch_buf = nil + else + if scratch_buf and vim.api.nvim_buf_is_valid(scratch_buf) then + -- Buffer exists, reuse it and open a new window + OpenScratchWindow(scratch_buf, current_window_type) + else + -- Buffer doesn't exist, create it and load the file if it exists + scratch_buf = OpenScratchBuffer(file_path) + OpenScratchWindow(scratch_buf, current_window_type) + end + end +end + +-- Function to write buffer contents to a file +function WriteScratchBufferToFile(buf, file_path) + if buf and vim.api.nvim_buf_is_valid(buf) then + local lines = vim.api.nvim_buf_get_lines(buf, 0, -1, false) + local content = table.concat(lines, "\n") + local escaped_file_path = vim.fn.fnameescape(file_path) + + -- Write the buffer content to the file + local file = io.open(escaped_file_path, "w") + if file then + file:write(content) + file:close() + end + end +end + +-- Function to create or open the scratch buffer +function OpenScratchBuffer(file_path) + local buf = vim.api.nvim_create_buf(true, false) + + -- Set the file name for the buffer + local escaped_file_path = vim.fn.fnameescape(file_path) + vim.api.nvim_buf_set_name(buf, escaped_file_path) + + -- Check if the file exists and load it if it does + if vim.fn.filereadable(file_path) == 1 then + local file_contents = vim.fn.readfile(file_path) + vim.api.nvim_buf_set_lines(buf, 0, -1, true, file_contents) + else + -- Insert initial content + vim.api.nvim_buf_set_lines(buf, 0, -1, true, { + "# Quick Notes - " .. scratch_date, + "--------------------------", + "", + }) + + -- Save the initial content to the file + vim.cmd(":w") + end + + return buf +end + +-- Function to open the scratch buffer in a window +function OpenScratchWindow(buf, current_window_type) + if buf and vim.api.nvim_buf_is_valid(buf) then + if current_window_type == "float" then + local opts = { + relative = "win", + width = 120, + height = 10, + border = "single", + row = 20, + col = 20, + } + scratch_win = vim.api.nvim_open_win(buf, true, opts) + -- Go to the last line of the buffer + vim.api.nvim_win_set_cursor(scratch_win, { vim.api.nvim_buf_line_count(buf), 1 }) + elseif current_window_type == "vertical" then + vim.cmd("vsplit") + vim.api.nvim_win_set_buf(0, buf) + scratch_win = 0 + elseif current_window_type == "horizontal" then + vim.cmd("split") + vim.api.nvim_win_set_buf(0, buf) + scratch_win = 0 + end + end +end + +-------------------------------------------------- + +-- Intercept file open +local augroup = vim.api.nvim_create_augroup("user-autocmds", { clear = true }) +local intercept_file_open = true +vim.api.nvim_create_user_command("InterceptToggle", function() + intercept_file_open = not intercept_file_open + local intercept_state = "`Enabled`" + if not intercept_file_open then + intercept_state = "`Disabled`" + end + vim.notify("Intercept file open set to " .. intercept_state, vim.log.levels.INFO, { + title = "Intercept File Open", + ---@param win integer The window handle + on_open = function(win) + vim.api.nvim_buf_set_option(vim.api.nvim_win_get_buf(win), "filetype", "markdown") + end, + }) +end, { desc = "Toggles intercepting BufNew to open files in custom programs" }) + +-- NOTE: Add "BufReadPre" to the autocmd events to also intercept files given on the command line, e.g. +-- `nvim myfile.txt` +vim.api.nvim_create_autocmd({ "BufNew" }, { + group = augroup, + callback = function(args) + ---@type string + local path = args.match + ---@type integer + local bufnr = args.buf + + ---@type string? The file extension if detected + local extension = vim.fn.fnamemodify(path, ":e") + ---@type string? The filename if detected + local filename = vim.fn.fnamemodify(path, ":t") + + ---Open a given file path in a given program and remove the buffer for the file. + ---@param buf integer The buffer handle for the opening buffer + ---@param fpath string The file path given to the program + ---@param fname string The file name used in notifications + ---@param prog string The program to execute against the file path + local function open_in_prog(buf, fpath, fname, prog) + vim.notify(string.format("Opening `%s` in `%s`", fname, prog), vim.log.levels.INFO, { + title = "Open File in External Program", + ---@param win integer The window handle + on_open = function(win) + vim.api.nvim_buf_set_option(vim.api.nvim_win_get_buf(win), "filetype", "markdown") + end, + }) + local mods = require("user.mods") + local nvim_ver = mods.get_nvim_version() + + local version_major, version_minor = string.match(nvim_ver, "(%d+)%.(%d+)") + version_major = tonumber(version_major) + version_minor = tonumber(version_minor) + + if version_major > 0 or (version_major == 0 and version_minor >= 10) then + vim.system({ prog, fpath }, { detach = true }) + else + vim.fn.jobstart({ prog, fpath }, { detach = true }) + end + vim.api.nvim_buf_delete(buf, { force = true }) + end + + local extension_callbacks = { + ["pdf"] = function(buf, fpath, fname) + open_in_prog(buf, fpath, fname, "zathura") + end, + ["epub"] = function(buf, fpath, fname) + open_in_prog(buf, fpath, fname, "zathura") + end, + ["mobi"] = "pdf", + ["png"] = function(buf, fpath, fname) + open_in_prog(buf, fpath, fname, "vimiv") + end, + ["jpg"] = "png", + ["mp4"] = function(buf, fpath, fname) + open_in_prog(buf, fpath, fname, "vlc") + end, + ["gif"] = "mp4", + } + + ---Get the extension callback for a given extension. Will do a recursive lookup if an extension callback is actually + ---of type string to get the correct extension + ---@param ext string A file extension. Example: `png`. + ---@return fun(bufnr: integer, path: string, filename: string?) extension_callback The extension callback to invoke, expects a buffer handle, file path, and filename. + local function extension_lookup(ext) + local callback = extension_callbacks[ext] + if type(callback) == "string" then + callback = extension_lookup(callback) + end + return callback + end + + if extension ~= nil and not extension:match("^%s*$") and intercept_file_open then + local callback = extension_lookup(extension) + if type(callback) == "function" then + callback(bufnr, path, filename) + end + end + end, +}) + +-------------------------------------------------- + +-- Delete [No Name] buffers +vim.api.nvim_create_autocmd("BufHidden", { + desc = "Delete [No Name] buffers", + callback = function(event) + if event.file == "" and vim.bo[event.buf].buftype == "" and not vim.bo[event.buf].modified then + vim.schedule(function() + pcall(vim.api.nvim_buf_delete, event.buf, {}) + end) + end + end, +}) + +-------------------------------------------------- + +local codeRunnerEnabled = false + +function M.toggleCodeRunner() + codeRunnerEnabled = not codeRunnerEnabled + if codeRunnerEnabled then + print("Code Runner enabled") + M.RunCode() -- Execute when enabled + else + print("Code Runner disabled") + -- Close the terminal window when disabled + local buffers = vim.fn.getbufinfo() + + for _, buf in ipairs(buffers) do + local type = vim.api.nvim_buf_get_option(buf.bufnr, "buftype") + if type == "terminal" then + vim.api.nvim_command("silent! bdelete " .. buf.bufnr) + end + end + end +end + +local function substitute(cmd) + cmd = cmd:gsub("%%", vim.fn.expand("%")) + cmd = cmd:gsub("$fileBase", vim.fn.expand("%:r")) + cmd = cmd:gsub("$filePath", vim.fn.expand("%:p")) + cmd = cmd:gsub("$file", vim.fn.expand("%")) + cmd = cmd:gsub("$dir", vim.fn.expand("%:p:h")) + cmd = cmd:gsub("#", vim.fn.expand("#")) + cmd = cmd:gsub("$altFile", vim.fn.expand("#")) + + return cmd +end + +function M.RunCode() + if not codeRunnerEnabled then + print("Code Runner is currently disabled. Toggle it on to execute code.") + return + end + local file_extension = vim.fn.expand("%:e") + local selected_cmd = "" + local supported_filetypes = { + html = { + default = "%", + }, + c = { + default = "gcc % -o $fileBase && ./$fileBase", + debug = "gcc -g % -o $fileBase && ./$fileBase", + }, + cs = { + default = "dotnet run", + }, + cpp = { + default = "g++ % -o $fileBase && ./$fileBase", + debug = "g++ -g % -o ./$fileBase", + competitive = "g++ -std=c++17 -Wall -DAL -O2 % -o $fileBase && $fileBase<input.txt", + }, + py = { + default = "python %", + }, + go = { + default = "go run %", + }, + java = { + default = "java %", + }, + js = { + default = "node %", + debug = "node --inspect %", + }, + lua = { + default = "lua %", + }, + ts = { + default = "tsc % && node $fileBase", + }, + rs = { + default = "rustc % && $fileBase", + }, + php = { + default = "php %", + }, + r = { + default = "Rscript %", + }, + jl = { + default = "julia %", + }, + rb = { + default = "ruby %", + }, + pl = { + default = "perl %", + }, + } + + local term_cmd = "bot 10 new | term " + local choices = {} + + -- Add 'default' as the first option if available + if supported_filetypes[file_extension]["default"] then + table.insert(choices, "default") + end + + -- Add 'debug' as the second option if available + if supported_filetypes[file_extension]["debug"] then + table.insert(choices, "debug") + end + + -- Add other available options + for key, _ in pairs(supported_filetypes[file_extension]) do + if key ~= "default" and key ~= "debug" then + table.insert(choices, key) + end + end + if #choices == 0 then + vim.notify("It doesn't contain any command", vim.log.levels.WARN, { title = "Code Runner" }) + elseif #choices == 1 then + selected_cmd = supported_filetypes[file_extension][choices[1]] + vim.cmd(term_cmd .. substitute(selected_cmd)) + else + vim.ui.select(choices, { + prompt = "Choose a command: ", + layout_config = { + height = 10, + width = 40, + prompt_position = "top", + -- other options as required + }, + }, function(choice) + selected_cmd = supported_filetypes[file_extension][choice] + if selected_cmd then + vim.cmd(term_cmd .. substitute(selected_cmd)) + end + end) + end + + if not supported_filetypes[file_extension] then + vim.notify("The filetype isn't included in the list", vim.log.levels.WARN, { title = "Code Runner" }) + end +end + +-------------------------------------------------- + +-- Run executable file +local interpreters = { + python = "python", + lua = "lua", + bash = "bash", + zsh = "zsh", + perl = "perl", + ruby = "ruby", + node = "node", + rust = "rust", + php = "php", +} + +function M.RunCurrentFile() + local file_path = vim.fn.expand("%:p") + local file = io.open(file_path, "r") + + if not file then + print("Error: Unable to open the file") + return + end + + local shebang = file:read() + file:close() + + local interpreter = shebang:match("#!%s*(.-)$") + if not interpreter then + print("Error: No shebang line found in the file") + return + end + + -- Remove leading spaces and any arguments, extracting the interpreter name + interpreter = interpreter:gsub("^%s*([^%s]+).*", "%1") + + local cmd = interpreters[interpreter] + + if not cmd then + cmd = interpreter -- Set the command to the interpreter directly + end + + -- Run the file using the determined interpreter + vim.fn.jobstart(cmd .. " " .. file_path, { + cwd = vim.fn.expand("%:p:h"), + }) +end + +-------------------------------------------------- + +-- Close all floating windows +vim.api.nvim_create_user_command("CloseFloatingWindows", function(opts) + for _, window_id in ipairs(vim.api.nvim_list_wins()) do + -- If window is floating + if vim.api.nvim_win_get_config(window_id).relative ~= "" then + -- Force close if called with ! + vim.api.nvim_win_close(window_id, opts.bang) + end + end +end, { bang = true, nargs = 0 }) + +-------------------------------------------------- + +-- ... +return M diff --git a/common/config/nvim/lua/user/opts.lua b/common/config/nvim/lua/user/opts.lua new file mode 100644 index 0000000..cc8debc --- /dev/null +++ b/common/config/nvim/lua/user/opts.lua @@ -0,0 +1,351 @@ +--[[ opts.lua ]] + +-- Environment +--vim.opt.shell = "zsh" -- +vim.o.updatetime = 250 +vim.o.shell = '/bin/zsh' +vim.scriptencoding = 'utf-8' -- +vim.opt.encoding = 'utf-8' -- +vim.opt.fileencoding = 'utf-8' -- +vim.g.python3_host_prog = '/usr/bin/python3' -- +vim.g.loaded_python3_provider = 1 -- +vim.g.sh_noisk = 1 -- iskeyword word boundaries when editing a 'sh' file +vim.o.autochdir = true +--vim.o.writeany= true + +-- Clipboard +vim.opt.clipboard:append({ 'unnamedplus' }) -- Install xclip or this will slowdown startup + +-- Behaviour +vim.opt.backspace = { 'start', 'eol', 'indent' } -- Make backspace work as you would expect. +vim.opt.hidden = true -- Switch between buffers without having to save first. +vim.opt.splitbelow = true -- make split put the new buffer below the current buffer +vim.opt.splitright = true -- make vsplit put the new buffer on the right of the current buffer +vim.opt.scrolloff = 8 -- +vim.opt.sidescrolloff = 8 -- how many lines to scroll when using the scrollbar +vim.opt.autoread = true -- reload files if changed externally +vim.opt.display = 'lastline' -- Show as much as possible of the last line. +vim.opt.inccommand = 'split' -- +vim.opt.ttyfast = true -- Faster redrawing. +vim.opt.lazyredraw = false -- Only redraw when necessary +vim.opt.keywordprg = ':help' -- :help options +vim.opt.ruler = true -- +vim.opt.errorbells = false -- +vim.opt.list = true -- Show non-printable characters. +vim.opt.showmatch = true -- +vim.opt.matchtime = 3 -- +vim.opt.showbreak = '↪ ' -- +vim.opt.linebreak = true -- +vim.opt.exrc = true -- +--vim.opt.autochdir = true -- or use this to use <:e> to create a file in current directory +vim.opt.autoread = true -- if a file is changed outside of vim, automatically reload it without asking +--vim.opt.notimeout = true -- Timeout on keycodes and not mappings +vim.opt.ttimeout = true -- Makes terminal vim work sanely +vim.opt.ttimeoutlen = 10 -- +--vim.opt.timeoutlen = 100 -- time to wait for a mapped sequence to complete (in milliseconds) +--vim.cmd([[set diffopt = vertical = true]]) -- diffs are shown side-by-side not above/below + +-- Indent/tab +vim.opt.breakindent = true -- +vim.opt.autoindent = true -- Indent according to previous line. +vim.opt.copyindent = true -- Copy indent from the previous line +vim.opt.smarttab = false -- +vim.opt.tabstop = 2 -- +vim.opt.expandtab = true -- Indent according to previous line. +--vim.opt.expandtab = true -- Use spaces instead of tabs. +vim.opt.softtabstop = 2 -- Tab key indents by 2 spaces. +vim.opt.shiftwidth = 2 -- >> indents by 2 spaces. +vim.opt.shiftround = true -- >> indents to next multiple of 'shiftwidth'. +vim.opt.smartindent = true -- smart indent + +-- Column/statusline/Cl +vim.opt.number = true -- +vim.opt.title = true -- +--vim.opt.colorcolumn = "+1" -- +vim.opt.signcolumn = 'yes:1' -- always show the sign column +--vim.opt.signcolumn = "yes:" .. vim.o.numberwidth +--vim.opt.signcolumn = "number" +--vim.opt.signcolumn = "no" -- +vim.opt.laststatus = 3 -- " Always show statusline. +vim.opt.showmode = true -- Show current mode in command-line, example: -- INSERT -- mode +vim.opt.showcmd = true -- Show the command in the status bar +vim.opt.cmdheight = 1 -- +--vim.opt.cmdheight = 0 -- +vim.opt.report = 0 -- Always report changed lines. +--local autocmd = vim.api.nvim_create_autocmd +--autocmd("bufenter", { +-- pattern = "*", +-- callback = function() +-- if vim.bo.ft ~= "terminal" then +-- vim.opt.statusline = "%!v:lua.require'ui.statusline'.run()" +-- else +-- vim.opt.statusline = "%#normal# " +-- end +-- end, +--}) +---- With vertical splits, the statusline would still show up at the +---- bottom of the split. A quick fix is to just set the statusline +---- to empty whitespace (it can't be an empty string because then +---- it'll get replaced by the default stline). +--vim.opt.stl = " " + +-- Backup/undo/swap +local prefix = vim.env.XDG_CONFIG_HOME or vim.fn.expand('~/.config') +--vim.opt.undodir = os.getenv("HOME") .. "/.vim/undodir" +vim.opt.undodir = { prefix .. '/nvim/tmp/.undo//' } +vim.opt.directory = { prefix .. '/nvim/tmp/.swp//' } +vim.opt.backupdir = { prefix .. '/nvim/tmp/.backup//' } +vim.opt.undofile = true -- +vim.opt.swapfile = true -- +vim.opt.backup = true -- +--vim.opt.backupcopy = +-- Add timestamp as extension for backup files +vim.api.nvim_create_autocmd('BufWritePre', { + group = vim.api.nvim_create_augroup('timestamp_backupext', { clear = true }), + desc = 'Add timestamp to backup extension', + pattern = '*', + callback = function() + vim.opt.backupext = '-' .. vim.fn.strftime('%Y%m%d%H%M') + end, +}) + +-- Format +--vim.opt.textwidth = 80 -- +vim.opt.isfname:append('@-@') +vim.cmd([[let &t_Cs = "\e[4:3m"]]) -- Undercurl +vim.cmd([[let &t_Ce = "\e[4:0m"]]) -- +vim.opt.path:append({ '**' }) -- Finding files - Search down into subfolder +vim.cmd('set whichwrap+=<,>,[,],h,l') -- +vim.cmd([[set iskeyword+=-]]) -- +--vim.cmd([[set formatoptions-=cro]]) -- TODO: this doesn't seem to work +vim.opt.formatoptions = vim.opt.formatoptions + - 't' -- wrap with text width + + 'c' -- wrap comments + + 'r' -- insert comment after enter + - 'o' -- insert comment after o/O + - 'q' -- allow formatting of comments with gq + - 'a' -- format paragraphs + + 'n' -- recognized numbered lists + - '2' -- use indent of second line for paragraph + + 'l' -- long lines are not broken + + 'j' -- remove comment when joining lines +vim.opt.wrapscan = true -- " Searches wrap around end-of-file. +--vim.wo.number = true -- +--vim.opt.wrap = false -- No Wrap lines +--vim.opt.foldmethod = 'manual' -- +--vim.opt.foldmethod = "expr" -- +vim.opt.foldmethod = 'manual' +vim.opt.foldlevel = 3 +vim.opt.confirm = false +--vim.opt.shortmess:append("sI") +--vim.opt.shortmess = "a" +--vim.opt.shortmess = "sI" +--vim.o.shortmess = vim.o.shortmess:gsub('s', '') +vim.opt.shortmess = table.concat({ -- Use abbreviations and short messages in command menu line. + 'f', -- Use "(3 of 5)" instead of "(file 3 of 5)". + 'i', -- Use "[noeol]" instead of "[Incomplete last line]". + 'l', -- Use "999L, 888C" instead of "999 lines, 888 characters". + 'm', -- Use "[+]" instead of "[Modified]". + 'n', -- Use "[New]" instead of "[New File]". + 'r', -- Use "[RO]" instead of "[readonly]". + 'w', -- Use "[w]", "[a]" instead of "written", "appended". + 'x', -- Use "[dos]", "[unix]", "[mac]" instead of "[dos format]", "[unix format]", "[mac format]". + 'o', -- Overwrite message for writing a file with subsequent message. + 'O', -- Message for reading a file overwrites any previous message. + 's', -- Disable "search hit BOTTOM, continuing at TOP" such messages. + 't', -- Truncate file message at the start if it is too long. + 'T', -- Truncate other messages in the middle if they are too long. + 'I', -- Don't give the :intro message when starting. + 'c', -- Don't give ins-completion-menu messages. + 'F', -- Don't give the file info when editing a file. +}) +vim.opt.fillchars = { + horiz = '─', + horizup = '┴', + horizdown = '┬', + vert = '│', + vertleft = '┤', + vertright = '├', + verthoriz = '┼', + foldopen = '', + foldsep = '│', + foldclose = '', + fold = '─', + eob = ' ', + --diff = "┃", + diff = '░', + msgsep = '━', + --msgsep = "‾", +} +vim.opt.listchars = { tab = '▸ ', trail = '·' } -- +--vim.opt.fillchars:append({ eob = " " }) -- remove the ~ from end of buffer +vim.opt.modeline = true -- +vim.opt.modelines = 3 -- modelines (comments that set vim options on a per-file basis) +--vim.opt.modelineexpr = true +--vim.opt.nofoldenable = true -- turn folding off +--vim.opt.foldenable = false -- turn folding off +vim.o.showtabline = 2 + +-- Highlights +vim.opt.incsearch = true -- Highlight while searching with / or ?. +vim.opt.hlsearch = true -- Keep matches highlighted. +vim.opt.ignorecase = true -- ignore case in search patterns UNLESS /C or capital in search +vim.opt.smartcase = true -- smart case +vim.opt.synmaxcol = 200 -- Only highlight the first 200 columns. +--vim.opt.winblend = 30 +--vim.opt.winblend = 5 +vim.opt.wildoptions = 'pum' -- +--vim.opt.pumblend = 5 -- +vim.opt.pumblend = 12 -- +--vim.opt.pumblend=15 +vim.opt.pumheight = 10 -- pop up menu height + +-- Better Completion +vim.opt.complete = { '.', 'w', 'b', 'u', 't' } -- +--vim.opt.completeopt = { "longest,menuone,preview" } -- +vim.opt.completeopt = { 'menu', 'menuone', 'noselect' } +--vim.opt.completeopt = { "menuone", "noselect" } -- mostly just for cmp +--vim.opt.completeopt = { "menu", "menuone", "noselect" } -- + +-- Wildmenu completion -- +vim.opt.wildmenu = true -- +vim.opt.wildmode = { 'list:longest' } -- +vim.opt.wildignore:append({ '.hg', '.git', '.svn' }) -- Version control +vim.opt.wildignore:append({ '*.aux', '*.out', '*.toc' }) -- LaTeX intermediate files +vim.opt.wildignore:append({ '*.jpg', '*.bmp', '*.gif', '*.png', '*.jpeg' }) -- binary images +vim.opt.wildignore:append({ '*.o', '*.obj', '*.exe', '*.dll', '*.manifest' }) -- compiled object files +vim.opt.wildignore:append({ '*.spl' }) -- compiled spelling word lists +vim.opt.wildignore:append({ '*.sw?' }) -- Vim swap files +vim.opt.wildignore:append({ '*.DS_Store' }) -- OSX bullshit +vim.opt.wildignore:append({ '*.luac' }) -- Lua byte code +vim.opt.wildignore:append({ 'migrations' }) -- Django migrations +vim.opt.wildignore:append({ '*.pyc' }) -- Python byte code +vim.opt.wildignore:append({ '*.orig' }) -- Merge resolution files +vim.opt.wildignore:append({ '*/node_modules/*' }) -- + +-- Shada +vim.opt.shada = "!,'1000,f1,<1000,s100,:1000,/1000,h" + +-- Sessions +vim.opt.sessionoptions = 'blank,buffers,curdir,folds,help,tabpages,winsize,winpos,terminal' +--vim.opt.sessionoptions = "curdir,folds,help,options,tabpages,winsize,winpos,terminal,globals" -- +--vim.opt.sessionoptions = "buffers,curdir,folds,help,tabpages,winsize,winpos,terminal" +--vim.opt.sessionoptions:remove({ "blank", "buffers", "globals" }) + +-- Netrw file tree +vim.g.netrw_browse_split = 0 +vim.g.netrw_banner = 0 +vim.g.netrw_winsize = 25 + +-- " Load indent files, to automatically do language-dependent indenting. +--vim.cmd([[ +-- "filetype plugin indent on +--]]) +vim.cmd('filetype plugin on') +vim.cmd('filetype indent off') + +-- Let clipboard register be + +vim.cmd([[ + let g:clipbrdDefaultReg = '+' +]]) + +--vim.cmd([[ +-- "autocmd BufEnter * :syntax sync fromstart +-- "syntax enable +-- "set nocompatible +-- "autocmd FileType lua set comments=s1:---,m:--,ex:-- +--]]) + +-- Fast macros without lazyredraw +vim.cmd([[ + set re=0 + nnoremap @ <cmd>execute "noautocmd norm! " . v:count1 . "@" . getcharstr()<cr> + xnoremap @ :<C-U>execute "noautocmd '<,'>norm! " . v:count1 . "@" . getcharstr()<cr> +]]) + +-- Stop annoying auto commenting on new lines +vim.cmd([[ + augroup annoying + au! + au BufEnter * set fo-=c fo-=r fo-=o + augroup end +]]) + +-- Cursorline +vim.cmd([[ " Only show cursorline in the current window and in normal mode + augroup cline + au! + au WinLeave,InsertEnter * set nocursorline + au WinEnter,InsertLeave * set cursorline + augroup END +]]) +vim.opt.cursorline = true -- +vim.opt.guicursor = 'i:ver100,r:hor100' -- + +-- Trailing whitespace +vim.cmd([[ " Only show in insert mode + augroup trailing + au! + au InsertEnter * :set listchars-=trail:⌴ + au InsertLeave * :set listchars+=trail:⌴ + augroup END +]]) + +-- Line Return +vim.cmd([[ " Return to the same line when we reopen a file + augroup line_return + au! + au BufReadPost * + \ if line("'\"") > 0 && line("'\"") <= line("$") | + \ execute 'normal! g`"zvzz' | + \ endif + augroup END +]]) + +-- Enable mouse scrollback +vim.cmd([[ + set mouse=a + tnoremap <Esc> <C-\><C-n> + tnoremap <c-b> <c-\><c-n> + function! ClearTerminal() + set scrollback=1 + let &g:scrollback=1 + echo &scrollback + call feedkeys("\i") + call feedkeys("clear\<CR>") + call feedkeys("\<C-\>\<C-n>") + call feedkeys("\i") + sleep 100m + let &scrollback=s:scroll_value + endfunction +]]) + +-- Yank to clipboard in Termux +if vim.fn.has('termux') == 1 then + local Job = require('plenary.job') + vim.api.nvim_create_autocmd('TextYankPost', { + pattern = '*', + callback = function() + Job:new({ + command = 'termux-clipboard-set', + writer = vim.fn.getreg('@'), + }):start() + end, + }) +end + +function GetTermuxClipboard() + if vim.fn.has('termux') == 1 then + local sysclip = vim.fn.system('termux-clipboard-get') + if sysclip ~= '@' then + vim.fn.setreg('@', sysclip) + end + end + return '' +end + +if vim.fn.has('termux') == 1 then + vim.cmd('autocmd TextYankPost * call GetTermuxClipboard()') + vim.cmd('noremap <expr> p Paste("p")') + vim.cmd('noremap <expr> P Paste("P")') +end diff --git a/common/config/nvim/lua/user/pack.lua b/common/config/nvim/lua/user/pack.lua new file mode 100644 index 0000000..7ed86db --- /dev/null +++ b/common/config/nvim/lua/user/pack.lua @@ -0,0 +1,403 @@ +local fn = vim.fn + +-------------------------------------------------- + +-- Automatically install packer +local install_path = fn.stdpath("data") .. "/site/pack/packer/start/packer.nvim" +if fn.empty(fn.glob(install_path)) > 0 then + PACKER_BOOTSTRAP = fn.system({ + "git", + "clone", + "--depth", + "1", + "https://github.com/wbthomason/packer.nvim", + install_path, + }) + print("Installing packer, please close and reopen Neovim...") + vim.cmd([[packadd packer.nvim]]) +end + +-------------------------------------------------- + +-- Autocommand that reloads neovim whenever you save this file +vim.cmd([[ + augroup packer_user_config + autocmd! + autocmd BufWritePost pack.lua source <afile> | PackerSync + augroup end +]]) + +-------------------------------------------------- + +-- Use a protected call so don't error out on first use +local status_ok, packer = pcall(require, "packer") +if not status_ok then + return +end + +-------------------------------------------------- + +-- Have packer use a popup window and set a maximum number of jobs +packer.init({ + auto_reload_compiled = true, + --max_jobs = 90, + display = { + open_fn = function() + return require("packer.util").float({ border = "rounded" }) + end, + }, +}) + +-------------------------------------------------- + +-- Install plugins here +return packer.startup(function(use) + -- Defaults + use("wbthomason/packer.nvim") -- Have packer manage itself (package manager) + use("nvim-lua/plenary.nvim") -- Useful lua functions used by lots of plugins + use("lewis6991/impatient.nvim") -- Faster loading/startup times + + -- Tree-sitter + use({ "nvim-treesitter/nvim-treesitter", run = ":TSUpdate" }) -- For language parsing, examples: highlighting, folding, jumping, refactoring... + use("nvim-treesitter/nvim-treesitter-refactor") -- Refactor module for nvim-treesitter + + -- lsp + use("williamboman/mason.nvim") -- Package manager to install and manage LSP servers, DAP servers, linters and formatters + use("neovim/nvim-lspconfig") -- Collection of LSP configs + use("williamboman/mason-lspconfig.nvim") -- Bridges mason.nvim with nvim-lspconfig to help use them together + use({ + "https://git.sr.ht/~whynothugo/lsp_lines.nvim", + config = function() + require("lsp_lines").setup() + end, + }) + use("rmagatti/goto-preview") + + -- Debugger + use("mfussenegger/nvim-dap") -- Debug Adapter Protocol client implementation for Neovim + use("rcarriga/nvim-dap-ui") -- UI for nvim-dap + --use { "rcarriga/nvim-dap-ui", requires = {"mfussenegger/nvim-dap"} } + use("theHamsta/nvim-dap-virtual-text") + use("gabrielpoca/replacer.nvim") + use("jayp0521/mason-nvim-dap.nvim") + --use({ + -- "jayp0521/mason-nvim-dap.nvim", + -- config = function() + -- require("mason-nvim-dap").setup({ + -- automatic_installation = true, + -- ensure_installed = { "python", "cppdbg", "codelldb" }, + -- }) + -- end, + --}) + + -- Linters/Formatters + use("mhartington/formatter.nvim") + use("jay-babu/mason-null-ls.nvim") + --use({"jayp0521/mason-null-ls.nvim", + -- config = function() + -- require('mason-null-ls.nvim').setup({ + -- automatic_setup = true, + -- }) + -- end + --}) + use({ + "jose-elias-alvarez/null-ls.nvim", -- Provides LSP: linters, formatters, diagnostics, code actions and etc... + requires = { "jay-babu/mason-null-ls.nvim" }, + }) + + -- Completion + use("hrsh7th/nvim-cmp") -- Completion engine plugin + use("hrsh7th/cmp-nvim-lsp") -- Completion source for nvim-lsp + use("hrsh7th/cmp-buffer") -- Completion source for content of current buffer + use("hrsh7th/cmp-path") -- Completion source for paths + use("hrsh7th/cmp-cmdline") -- Completion source for command-line + use("petertriho/cmp-git") -- Completion source for git + use("tamago324/cmp-zsh") -- Completion source for zsh + use("f3fora/cmp-spell") -- Completion source for spell-checking + use("hrsh7th/cmp-calc") -- Completion source for math calculation + use("saadparwaiz1/cmp_luasnip") -- Completion source for snippets, specifically for luasnip + use("hrsh7th/cmp-nvim-lsp-signature-help") -- Completion source for displaying function signatures with the current parameter emphasized + use("rcarriga/cmp-dap") + + -- Snippets + use("L3MON4D3/LuaSnip") -- Snippet engine + use("rafamadriz/friendly-snippets") -- Collection of snippets to use + + -- Git + use("tpope/vim-fugitive") -- + --use("dinhhuy258/git.nvim") -- For git blame & browse + use("kdheepak/lazygit.nvim") -- Terminal UI for git commands + use("lewis6991/gitsigns.nvim") -- Git decorations + + -- File explorer/fuzzy finder + use("kyazdani42/nvim-tree.lua") -- File explorer + use("ibhagwan/fzf-lua") -- Fuzzy finder + use("ThePrimeagen/harpoon") + --use("nvim-telescope/telescope.nvim") -- Fuzzy finder with lots of features/extendabilities + use({ + "nvim-telescope/telescope.nvim", + branch = "0.1.x", + --config = function() + -- require('plugins.telescope').setup() + --end, + requires = { + "nvim-lua/plenary.nvim", + "nvim-telescope/telescope-live-grep-args.nvim", + "nvim-telescope/telescope-file-browser.nvim", + { "nvim-telescope/telescope-fzf-native.nvim", run = "make" }, + }, + }) + use({ "nvim-telescope/telescope-fzf-native.nvim", run = "make" }) -- Support fzf syntax/algorithm + use("nvim-telescope/telescope-ui-select.nvim") -- + use("nvim-telescope/telescope-project.nvim") -- + use("nvim-telescope/telescope-media-files.nvim") -- + use("nvim-telescope/telescope-file-browser.nvim") -- + use({ "nvim-telescope/telescope-symbols.nvim", after = "telescope.nvim" }) -- Search emoji(s) and other symbols + use("nvim-telescope/telescope-dap.nvim") + use("axkirillov/telescope-changed-files") -- + use("smartpde/telescope-recent-files") + use("rmagatti/auto-session") + use("rmagatti/session-lens") + + -- UX + use("folke/neodev.nvim") + use({ + "numToStr/Navigator.nvim", -- Navigate between Tmux and Nvim + config = function() + require("Navigator").setup() + end, + }) + use({ "tpope/vim-eunuch", cmd = { "Rename", "Delete", "Mkdir" } }) -- Handy unix commands inside Vim (Rename, Move etc.) + --use("tpope/vim-obsession") -- + use("tpope/vim-unimpaired") -- + --use("tpope/vim-surround") -- + use({ + "kylechui/nvim-surround", + tag = "*", -- Use for stability; omit to use `main` branch for the latest features + }) + --use("vimpostor/vim-tpipeline") -- + --use("nathom/filetype.nvim") -- + use("mbbill/undotree") + use({ + "myusuf3/numbers.vim", -- + vim.cmd("let g:numbers_exclude = ['dashboard']"), + }) + use("windwp/nvim-autopairs") -- + use("numToStr/Comment.nvim") -- + use("akinsho/toggleterm.nvim") -- + use("tweekmonster/startuptime.vim") -- + use("qpkorr/vim-bufkill") + use({ + "ggandor/leap.nvim", -- + config = function() + require("leap").add_default_mappings() + --require("leap").set_default_keymaps() + --vim.keymap.set('n', '-', '<Plug>(leap-forward)', {}) + --vim.keymap.set('n', '_', '<Plug>(leap-backward)', {}) + end, + }) + use({ + "ggandor/flit.nvim", -- + config = function() + require("flit").setup() + end, + }) + use("folke/which-key.nvim") -- + use("folke/zen-mode.nvim") -- + use("romainl/vim-cool") -- + use("antoinemadec/FixCursorHold.nvim") -- + use({ + "folke/trouble.nvim", + requires = "nvim-tree/nvim-web-devicons", + }) + use({ + "airblade/vim-rooter", -- + --vim.cmd("let g:rooter_change_directory_for_non_project_files = ''"), + --vim.cmd("let g:rooter_change_directory_for_non_project_files = 'current'") + }) + use({ "michaelb/sniprun", run = "bash ./install.sh" }) + use({ "stevearc/overseer.nvim" }) + --use("vim-test/vim-test") -- + --use({ + -- "rcarriga/vim-ultest", -- + -- requires = { "vim-test/vim-test" }, + -- run = ":UpdateRemotePlugins", + -- config = function() + -- require("plugins.ultest") + -- end, + --}) + --use({"rcarriga/neotest", + -- config = function() + -- require("neotest").setup() + --end, + --}) + use({ + "nvim-neotest/neotest", + requires = { + { + "nvim-neotest/neotest-python", + "nvim-neotest/neotest-plenary", + "nvim-neotest/neotest-vim-test", + }, + }, + }) + use("kawre/leetcode.nvim") + use("m4xshen/hardtime.nvim") + use({ + "luckasRanarison/nvim-devdocs", + config = function() + require("nvim-devdocs").setup() + end, + }) + + -- Colorschemes + use("bluz71/vim-nightfly-guicolors") + use("ayu-theme/ayu-vim") + use("joshdick/onedark.vim") + use("NTBBloodbath/doom-one.nvim") + use("nyngwang/nvimgelion") + use("projekt0n/github-nvim-theme") + use("folke/tokyonight.nvim") + use("ribru17/bamboo.nvim") + + -- UI + use("kyazdani42/nvim-web-devicons") -- + use("onsails/lspkind-nvim") -- + use({ "kevinhwang91/nvim-ufo", requires = "kevinhwang91/promise-async" }) -- Fold code + use("lukas-reineke/indent-blankline.nvim") + use({ + "luukvbaal/statuscol.nvim", + config = function() + local builtin = require("statuscol.builtin") + require("statuscol").setup({ + relculright = true, + segments = { + { text = { builtin.foldfunc }, click = "v:lua.ScFa" }, + { text = { "%s" }, click = "v:lua.ScSa" }, + { text = { builtin.lnumfunc, " " }, click = "v:lua.ScLa" }, + }, + }) + end, + }) + use({ + "glepnir/dashboard-nvim", + --event = 'VimEnter', + requires = { "nvim-tree/nvim-web-devicons" }, + }) + use("rcarriga/nvim-notify") -- Notification plugin + use("karb94/neoscroll.nvim") -- Faster/smooth scrolling + --use("MunifTanjim/prettier.nvim") -- Prettier plugin for Neovim's built-in LSP client + use({ + "norcalli/nvim-colorizer.lua", -- colorize hexa and rgb strings + cmd = { "ColorizerToggle", "ColorizerAttachToBuffer" }, + config = function() + require("colorizer").setup({ + --'*'; + user_default_options = { + RGB = true, + RRGGBB = true, + names = false, + RRGGBBAA = false, + css = false, + css_fn = true, + mode = "foreground", + }, + }) + end, + }) + use("MunifTanjim/nui.nvim") + use({ + "j-hui/fidget.nvim", + tag = "legacy", + }) -- UI to show nvim-lsp progress + use("metakirby5/codi.vim") + use({ + "simrat39/symbols-outline.nvim", -- + config = function() + require("symbols-outline").setup({ + auto_close = true, + }) + end, + }) + use({ + "kosayoda/nvim-lightbulb", -- + requires = "antoinemadec/FixCursorHold.nvim", + }) + use({ + "SmiteshP/nvim-navic", -- Statusline/Winbar component that uses LSP to show current code context + requires = "neovim/nvim-lspconfig", + }) + use({ + "rebelot/heirline.nvim", -- Statusline that is highly configurable + --requires = 'kyazdani42/nvim-web-devicons', + --event = 'VimEnter', + }) + use({ + "samodostal/image.nvim", + config = function() + require("image").setup({}) + end, + }) + -- Language specific tools + use("simrat39/rust-tools.nvim") -- Rust tooling ecosystem + use({ + "saecki/crates.nvim", -- + requires = { "nvim-lua/plenary.nvim" }, + config = function() + require("crates").setup() + end, + }) + use({ + "akinsho/flutter-tools.nvim", + requires = { + "nvim-lua/plenary.nvim", + "stevearc/dressing.nvim", -- optional for vim.ui.select + }, + config = function() + require("flutter-tools").setup({ + debugger = { + enabled = true, + run_via_dap = true, + }, + }) + end, + }) + use({ + "iamcco/markdown-preview.nvim", -- Markdown Preview + run = function() + vim.fn["mkdp#util#install"]() + end, + vim.cmd("let g:mkdp_auto_close = 0"), + }) + use({ + "ellisonleao/glow.nvim", -- Markdown Preview + config = function() + local glow_path + + -- Check if glow exists in ~/.local/bin + if vim.fn.executable("~/.local/bin/glow") == 1 then + glow_path = "~/.local/bin/glow" + else + -- Fallback to /usr/bin/glow + glow_path = "/usr/bin/glow" + end + + require("glow").setup({ + style = "dark", + glow_path = glow_path, + }) + end, + }) + use({ + "lervag/vimtex", + }) + use("micangl/cmp-vimtex") + + -------------------------------------------------- + + -- Automatically set up your configuration after cloning packer.nvim + -- Put this at the end after all plugins + if PACKER_BOOTSTRAP then + require("packer").sync() + end +end) diff --git a/common/config/nvim/lua/user/view.lua b/common/config/nvim/lua/user/view.lua new file mode 100644 index 0000000..837fce4 --- /dev/null +++ b/common/config/nvim/lua/user/view.lua @@ -0,0 +1,69 @@ +-- Colorscheme + +-- Colors +vim.opt.termguicolors = true + +-- Available colorschemes: +-- [[ nightfly ayu onedark doom-one nvimgelion github_dark tokyonight bamboo ]] + +require('tokyonight').setup({ + style = 'night', + transparent = true, + transparent_sidebar = true, + dim_inactive = false, + styles = { + sidebars = 'transparent', + floats = 'transparent', + }, +}) + +-- Define default color scheme +local default_colorscheme = 'tokyonight-night' +local fallback_colorscheme = 'desert' + +-- Attempt to set the default color scheme +local status_ok, _ = pcall(vim.cmd, 'colorscheme ' .. default_colorscheme) + +-- If the default color scheme is not found, use the fallback color scheme +if not status_ok then + vim.cmd('colorscheme ' .. fallback_colorscheme) +end + +vim.api.nvim_command('syntax on') +vim.api.nvim_command('highlight Normal guibg=NONE ctermbg=NONE') +vim.api.nvim_command('highlight NormalNC guibg=NONE') +vim.api.nvim_command('highlight NormalFloat guibg=NONE ctermbg=NONE') +vim.api.nvim_command('highlight Float guibg=NONE ctermbg=NONE') +vim.api.nvim_command('highlight NonText guibg=NONE ctermbg=NONE') +vim.api.nvim_command('highlight SignColumn guibg=NONE') +vim.api.nvim_command('highlight FoldColumn guibg=NONE') +vim.api.nvim_command('highlight CursorLineSign guibg=NONE ctermbg=NONE') +vim.api.nvim_command('highlight Title guibg=NONE gui=bold') +vim.api.nvim_command('highlight TabLine guibg=#333842 gui=bold') +vim.api.nvim_command('highlight TabLineSel guibg=#333842 gui=bold') +vim.api.nvim_command('highlight TabLineFill guibg=NONE gui=bold') +vim.api.nvim_command('highlight WinBar guibg=NONE ctermbg=NONE gui=bold') +vim.api.nvim_command('highlight WinBarNC guibg=NONE ctermbg=NONE') +vim.api.nvim_command('highlight LineNr guibg=NONE ctermbg=NONE') +vim.api.nvim_command('highlight WinSeparator guibg=NONE gui=bold ctermbg=NONE') +vim.api.nvim_command('highlight MsgSeparator guibg=NONE ctermbg=NONE') +vim.api.nvim_command('highlight EndOfBuffer guibg=NONE guifg=Normal') +vim.api.nvim_command('highlight Comment guibg=NONE ctermbg=NONE') +vim.api.nvim_command('highlight Winblend guibg=NONE ctermbg=NONE') +vim.api.nvim_command('highlight NormalFloat guibg=NONE ctermbg=NONE') +vim.api.nvim_command('highlight Pumblend guibg=NONE ctermbg=NONE') +vim.api.nvim_command('highlight WildMenu guibg=NONE ctermbg=NONE') +vim.api.nvim_command('highlight WarningMsg guibg=NONE ctermbg=NONE') +vim.api.nvim_command('highlight Pmenu guibg=NONE ctermbg=NONE') +vim.api.nvim_command('highlight PmenuSel guibg=NONE ctermbg=NONE') +vim.api.nvim_command('highlight PmenuThumb guibg=NONE ctermbg=NONE') +vim.api.nvim_command('highlight PmenuSbar guibg=NONE ctermbg=NONE') +vim.api.nvim_command('highlight PmenuExtra guibg=NONE ctermbg=NONE') +vim.api.nvim_command('highlight PmenuExtraSel guibg=NONE ctermbg=NONE') +vim.api.nvim_command('highlight MoreMsg guibg=NONE ctermbg=NONE') + +-- Set different window separator colorscheme +vim.cmd([[ +au WinEnter * setl winhl=WinSeparator:WinSeparatorA +au WinLeave * setl winhl=WinSeparator:WinSeparator +]]) diff --git a/common/config/nvim/snippets/boilerplate.lua b/common/config/nvim/snippets/boilerplate.lua new file mode 100644 index 0000000..04e973a --- /dev/null +++ b/common/config/nvim/snippets/boilerplate.lua @@ -0,0 +1,75 @@ +local ls = require("luasnip") --{{{ +local s = ls.s +local i = ls.i +local t = ls.t + +local d = ls.dynamic_node +local c = ls.choice_node +local f = ls.function_node +local sn = ls.snippet_node + +local fmt = require("luasnip.extras.fmt").fmt +local rep = require("luasnip.extras").rep + +local snippets, autosnippets = {}, {} --}}} + +local group = vim.api.nvim_create_augroup("Lua Snippets", { clear = true }) +local file_pattern = "*.lua" + +local function cs(trigger, nodes, opts) --{{{ + local snippet = s(trigger, nodes) + local target_table = snippets + + local pattern = file_pattern + local keymaps = {} + + if opts ~= nil then + -- check for custom pattern + if opts.pattern then + pattern = opts.pattern + end + + -- if opts is a string + if type(opts) == "string" then + if opts == "auto" then + target_table = autosnippets + else + table.insert(keymaps, { "i", opts }) + end + end + + -- if opts is a table + if opts ~= nil and type(opts) == "table" then + for _, keymap in ipairs(opts) do + if type(keymap) == "string" then + table.insert(keymaps, { "i", keymap }) + else + table.insert(keymaps, keymap) + end + end + end + + -- set autocmd for each keymap + if opts ~= "auto" then + for _, keymap in ipairs(keymaps) do + vim.api.nvim_create_autocmd("BufEnter", { + pattern = pattern, + group = group, + callback = function() + vim.keymap.set(keymap[1], keymap[2], function() + ls.snip_expand(snippet) + end, { noremap = true, silent = true, buffer = true }) + end, + }) + end + end + end + + table.insert(target_table, snippet) -- insert snippet into appropriate table +end --}}} + +-- Start Refactoring -- + +-- End Refactoring -- + +return snippets, autosnippets diff --git a/common/config/nvim/snippets/lua.lua b/common/config/nvim/snippets/lua.lua new file mode 100644 index 0000000..eb46b67 --- /dev/null +++ b/common/config/nvim/snippets/lua.lua @@ -0,0 +1,264 @@ + +local ls = require("luasnip") --{{{ +local s = ls.s --> snippet +local i = ls.i --> insert node +local t = ls.t --> text node + +local d = ls.dynamic_node +local c = ls.choice_node --> takes in a pos as first arg and a table of nodes +local f = ls.function_node +local sn = ls.snippet_node + +local fmt = require("luasnip.extras.fmt").fmt +local rep = require("luasnip.extras").rep + +local snippets, autosnippets = {}, {} --}}} + +local group = vim.api.nvim_create_augroup("Lua Snippets", { clear = true }) +local file_pattern = "*.lua" + +local function cs(trigger, nodes, opts) --{{{ + local snippet = s(trigger, nodes) + local target_table = snippets + + local pattern = file_pattern + local keymaps = {} + + if opts ~= nil then + -- check for custom pattern + if opts.pattern then + pattern = opts.pattern + end + + -- if opts is a string + if type(opts) == "string" then + if opts == "auto" then + target_table = autosnippets + else + table.insert(keymaps, { "i", opts }) + end + end + + -- if opts is a table + if opts ~= nil and type(opts) == "table" then + for _, keymap in ipairs(opts) do + if type(keymap) == "string" then + table.insert(keymaps, { "i", keymap }) + else + table.insert(keymaps, keymap) + end + end + end + + -- set autocmd for each keymap + if opts ~= "auto" then + for _, keymap in ipairs(keymaps) do + vim.api.nvim_create_autocmd("BufEnter", { + pattern = pattern, + group = group, + callback = function() + vim.keymap.set(keymap[1], keymap[2], function() + ls.snip_expand(snippet) + end, { noremap = true, silent = true, buffer = true }) + end, + }) + end + end + end + + table.insert(target_table, snippet) -- insert snippet into appropriate table +end --}}} + +-- Start Refactoring -- + +cs("CMD", { -- [CMD] multiline vim.cmd{{{ + t({ "vim.cmd[[", " " }), + i(1, ""), + t({ "", "]]" }), +}) --}}} +cs("cmd", fmt("vim.cmd[[{}]]", { i(1, "") })) -- single line vim.cmd +cs({ -- github import for packer{{{ + trig = "https://github%.com/([%w-%._]+)/([%w-%._]+)!", + regTrig = true, + hidden = true, +}, { + t([[use "]]), + f(function(_, snip) + return snip.captures[1] + end), + t("/"), + f(function(_, snip) + return snip.captures[2] + end), + t({ [["]], "" }), + i(1, ""), +}, "auto") --}}} + +cs( -- {regexSnippet} LuaSnippet{{{ + "regexSnippet", + fmt( + [=[ +cs( -- {} +{{ trig = "{}", regTrig = true, hidden = true }}, fmt([[ +{} +]], {{ + {} +}})) + ]=], + { + i(1, "Description"), + i(2, ""), + i(3, ""), + i(4, ""), + } + ), + { pattern = "*/snippets/*.lua", "<C-d>" } +) --}}} +cs( -- [luaSnippet] LuaSnippet{{{ + "luaSnippet", + fmt( + [=[ +cs("{}", fmt( -- {} +[[ +{} +]], {{ + {} + }}){}) + ]=], + { + i(1, ""), + i(2, "Description"), + i(3, ""), + i(4, ""), + c(5, { + t(""), + fmt([[, "{}"]], { i(1, "keymap") }), + fmt([[, {{ pattern = "{}", {} }}]], { i(1, "*/snippets/*.lua"), i(2, "keymap") }), + }), + } + ), + { pattern = "*/snippets/*.lua", "jcs" } +) --}}} + +cs( -- choice_node_snippet luaSnip choice node{{{ + "choice_node_snippet", + fmt( + [[ +c({}, {{ {} }}), +]], + { + i(1, ""), + i(2, ""), + } + ), + { pattern = "*/snippets/*.lua", "jcn" } +) --}}} + +cs( -- [function] Lua function snippet{{{ + "function", + fmt( + [[ +function {}({}) + {} +end +]], + { + i(1, ""), + i(2, ""), + i(3, ""), + } + ), + "jff" +) --}}} +cs( -- [local_function] Lua function snippet{{{ + "local_function", + fmt( + [[ +local function {}({}) + {} +end +]], + { + i(1, ""), + i(2, ""), + i(3, ""), + } + ), + "jlf" +) --}}} +cs( -- [local] Lua local variable snippet{{{ + "local", + fmt( + [[ +local {} = {} + ]], + { i(1, ""), i(2, "") } + ), + "jj" +) --}}} +-- Tutorial Snippets go here -- +local myFirstSnippet = s("myFirstSnippet", { + t("Hi! This is my first snippet in Luasnip "), + i(1, "placeholder"), + t({"", "this is another text node", ""}), + i(2, "put here"), +}) +table.insert(snippets, myFirstSnippet) + + + +local mySecondSnippet = s( + "mySecondSnippet", + fmt( + [[ + local {} = function({}) + {} {{ im in a curly braces }} + end {} + ]], + { + i(1, "myVar"), + c(2, { t(""), i(1, "myArg") }), + i(3, "-- TODO: something"), + i(4, "-- nice") + } + ) +) +table.insert(snippets, mySecondSnippet) + +local myFirstAutoSnippet = s("automatic", { t("This was auto triggered") }) +table.insert(autosnippets, myFirstAutoSnippet) + +local mySecondAutoSnippet = s({ trig = "digit(%d)(%d)", regTrig = true }, { + f(function(_, snip) + return snip.captures[1] .. " + " + end), + f(function(_, snip) + return snip.captures[2] + end), +}) +table.insert(autosnippets, mySecondAutoSnippet) + + + + + + + + +-- End Refactoring -- + +return snippets, autosnippets + + + + + + + + + + + + + + diff --git a/common/config/nvim/snippets/markdown.lua b/common/config/nvim/snippets/markdown.lua new file mode 100644 index 0000000..d0d1487 --- /dev/null +++ b/common/config/nvim/snippets/markdown.lua @@ -0,0 +1,58 @@ +local ls = require("luasnip") +local s = ls.s +local i = ls.i +local t = ls.t + +local d = ls.dynamic_node +local c = ls.choice_node +local f = ls.function_node +local sn = ls.snippet_node + +local fmt = require("luasnip.extras.fmt").fmt +local rep = require("luasnip.extras").rep + +-- -- + +local snippets = {} +local autosnippets = {} + +local autocmd = vim.api.nvim_create_autocmd +local augroup = vim.api.nvim_create_augroup +local map = vim.keymap.set +local opts = { noremap = true, silent = true, buffer = true } +local group = augroup("Markdown Snippets", { clear = true }) + +local function cs(trigger, nodes, keymap) --> cs stands for create snippet + local snippet = s(trigger, nodes) + table.insert(snippets, snippet) + + if keymap ~= nil then + local pattern = "*.md" + if type(keymap) == "table" then + pattern = keymap[1] + keymap = keymap[2] + end + autocmd("BufEnter", { + pattern = pattern, + group = group, + callback = function() + map({ "i" }, keymap, function() + ls.snip_expand(snippet) + end, opts) + end, + }) + end +end + +local function lp(package_name) -- Load Package Function + package.loaded[package_name] = nil + return require(package_name) +end + +-- Utility Functions -- + +-- Start Refactoring -- + +-- Start Refactoring -- + +return snippets, autosnippets |
