diff options
Diffstat (limited to '.config/nvim')
43 files changed, 5637 insertions, 0 deletions
diff --git a/.config/nvim/.gitignore b/.config/nvim/.gitignore new file mode 100644 index 0000000..e890cff --- /dev/null +++ b/.config/nvim/.gitignore @@ -0,0 +1,3 @@ +plugin/packer_compiled.lua +startup.log +tmp diff --git a/.config/nvim/README.md b/.config/nvim/README.md new file mode 100644 index 0000000..630b8e5 --- /dev/null +++ b/.config/nvim/README.md @@ -0,0 +1 @@ +## Neovim diff --git a/.config/nvim/autoload/utils.vim b/.config/nvim/autoload/utils.vim new file mode 100644 index 0000000..b4356ba --- /dev/null +++ b/.config/nvim/autoload/utils.vim @@ -0,0 +1,118 @@ +" 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! 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 + + +"------------------------------------------------- diff --git a/.config/nvim/init.lua b/.config/nvim/init.lua new file mode 100644 index 0000000..04c63b0 --- /dev/null +++ b/.config/nvim/init.lua @@ -0,0 +1,156 @@ +--[[ + ███╗ ██╗███████╗ ██████╗ ██╗ ██╗██╗███╗ ███╗ + ████╗ ██║██╔════╝██╔═══██╗██║ ██║██║████╗ ████║ + ██╔██╗ ██║█████╗ ██║ ██║██║ ██║██║██╔████╔██║ + ██║╚██╗██║██╔══╝ ██║ ██║╚██╗ ██╔╝██║██║╚██╔╝██║ + ██║ ╚████║███████╗╚██████╔╝ ╚████╔╝ ██║██║ ╚═╝ ██║ + ╚═╝ ╚═══╝╚══════╝ ╚═════╝ ╚═══╝ ╚═╝╚═╝ ╚═╝ + " ------------------------------------------------ + Author: srdusr + Email: graytrevor98@gmail.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 +-- 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.deps", -- Plugins + --"user.scripts", + "plugins.colorscheme", + "plugins.treesitter", + "plugins.telescope", + "plugins.nvim-tree", + "plugins.quickfix", + "plugins.cmp", + "plugins.luasnip", + "plugins.colorizer", + "plugins.prettier", + --"plugins.git", + "plugins.gitsigns", + "plugins.neoscroll", + --"plugins.null-ls", + "plugins.lsp", + "plugins.goto-preview", + "plugins.autopairs", + "plugins.navic", + "plugins.zen-mode", + "plugins.fidget", + "plugins.web-devicons", + "plugins.heirline", + "plugins.toggleterm", + "plugins.trouble", + "plugins.dashboard", + --"plugins.dap", + --"plugins.modify-blend", + --"plugins.floatterm", +} + + +-- Refresh module cache +for k, v in pairs(modules) do + package.loaded[v] = nil + require(v) +end + + +-- Check if we have the latest stable version of nvim +local mods = require("user.mods") +local expected_ver = "0.9.0" +local nvim_ver = mods.get_nvim_version() + +if nvim_ver ~= expected_ver then + local msg = string.format("Unsupported nvim version: expect %s, but got %s instead!", expected_ver, nvim_ver) +vim.api.nvim_err_writeln(msg) + return +end + + +-- Snippets +vim.g.snippets = "luasnip" + +-- Notifications +vim.notify = require("notify") -- Requires plugin "rcarriga/nvim-notify" + +-- 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 diff --git a/.config/nvim/lua/plugins/autopairs.lua b/.config/nvim/lua/plugins/autopairs.lua new file mode 100644 index 0000000..90c6d35 --- /dev/null +++ b/.config/nvim/lua/plugins/autopairs.lua @@ -0,0 +1,42 @@ +local status_ok, npairs = pcall(require, "nvim-autopairs") +if not status_ok then + return +end + +npairs.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 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/.config/nvim/lua/plugins/cmp-gh-source.lua b/.config/nvim/lua/plugins/cmp-gh-source.lua new file mode 100644 index 0000000..05bba55 --- /dev/null +++ b/.config/nvim/lua/plugins/cmp-gh-source.lua @@ -0,0 +1,72 @@ +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/.config/nvim/lua/plugins/cmp.lua b/.config/nvim/lua/plugins/cmp.lua new file mode 100644 index 0000000..edf57de --- /dev/null +++ b/.config/nvim/lua/plugins/cmp.lua @@ -0,0 +1,332 @@ + +-- 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 }, + }) +}) + + diff --git a/.config/nvim/lua/plugins/colorizer.lua b/.config/nvim/lua/plugins/colorizer.lua new file mode 100644 index 0000000..14d25e2 --- /dev/null +++ b/.config/nvim/lua/plugins/colorizer.lua @@ -0,0 +1,6 @@ +local status, colorizer = pcall(require, "colorizer") +if (not status) then return end + +colorizer.setup({ + '*'; +}) diff --git a/.config/nvim/lua/plugins/colorscheme.lua b/.config/nvim/lua/plugins/colorscheme.lua new file mode 100644 index 0000000..1ad9ce8 --- /dev/null +++ b/.config/nvim/lua/plugins/colorscheme.lua @@ -0,0 +1,73 @@ +-- Colorscheme +-- Available colorschemes: +-- [[ nightfly ayu onedark doom-one nvimgelion ]] +local colorscheme = "nvimgelion" +local status_ok, _ = pcall(vim.cmd, "colorscheme " .. colorscheme) +if not status_ok then + vim.notify("colorscheme " .. colorscheme .. " not found!") + return +end + +vim.api.nvim_command("syntax on") +vim.api.nvim_command("highlight Normal guibg=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 TabLine guibg=#333842 gui=bold") +vim.api.nvim_command("highlight Title guibg=none 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 gui=bold") +vim.api.nvim_command("highlight NormalFloat guibg=none") +vim.api.nvim_command("highlight LineNr guibg=none") +vim.api.nvim_command("highlight CursorLineSign guibg=none ctermbg=NONE") +--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") +vim.api.nvim_command("highlight WinSeparator guibg=none gui=bold") +vim.api.nvim_command("highlight MsgSeparator guibg=none") +vim.api.nvim_command("highlight PmenuSel guibg=none") +vim.api.nvim_command("highlight winblend guibg=none") + +-- Set different window separator colorscheme +vim.cmd [[ +au WinEnter * setl winhl=WinSeparator:WinSeparatorA +au WinLeave * setl winhl=WinSeparator:WinSeparator +]] + +require("notify").setup({ + background_colour = "#000000", +}) + +-- 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 +--]]) diff --git a/.config/nvim/lua/plugins/dap.lua b/.config/nvim/lua/plugins/dap.lua new file mode 100644 index 0000000..3d7059a --- /dev/null +++ b/.config/nvim/lua/plugins/dap.lua @@ -0,0 +1,114 @@ +local dap = require('dap') +dap.adapters.lldb = { + type = 'executable', + --command = '/usr/bin/lldb-vscode', -- adjust as needed, must be absolute path + --command = '/usr/bin/vscode-lldb', -- adjust as needed, must be absolute path + command = 'codelldb', + --command = 'lldb', + --command = codelldb_root, + name = 'lldb' +} + +-- cpp (c,c++,rust) +dap.configurations.cpp = { + { + name = 'Launch', + type = 'lldb', + request = 'launch', + --program = function() + -- return vim.fn.input('Path to executable: ', vim.fn.getcwd() .. '/', 'file') + --end, + terminal = 'integrated', + console = 'integratedTerminal', + program = function() + return vim.fn.input('program: ', vim.loop.cwd() .. '/', 'file') + end, + cwd = "${workspaceFolder}", + stopOnEntry = false, + args = {}, + }, +} + +-- 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') + +-- 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 + } +}) + +-- setup dapui +dapui.setup({ + mappings = { + expand = "<CR>", + open = "o", + remove = "D", + edit = "e", + repl = "r", + toggle = "t", + }, + layouts = { + { elements = { "scopes", "breakpoints", "stacks" }, size = 0.33, position = "right" }, + { elements = { "repl", "watches" }, size = 0.27, position = "bottom" }, + }, + icons = { expanded = "-", collapsed = "$" }, + controls = { enabled = false }, + floating = { border = "rounded", mappings = { close = { "q", "<esc>", "<c-o>" } } }, +}) + +-- signs +vim.fn.sign_define("DapStopped", { text = '=>', texthl = 'DiagnosticWarn', numhl = 'DiagnosticWarn' }) +vim.fn.sign_define("DapBreakpoint", { text = '<>', texthl = 'DiagnosticInfo', numhl = 'DiagnosticInfo' }) +vim.fn.sign_define("DapBreakpointRejected", { text = '!>', texthl = 'DiagnosticError', numhl = 'DiagnosticError' }) +vim.fn.sign_define("DapBreakpointCondition", { text = '?>', texthl = 'DiagnosticInfo', numhl = 'DiagnosticInfo' }) +vim.fn.sign_define("DapLogPoint", { text = '.>', texthl = 'DiagnosticInfo', numhl = 'DiagnosticInfo' }) + +-- options +dap.defaults.fallback.focus_terminal = false +dap.defaults.fallback.terminal_win_cmd = '10split new' + diff --git a/.config/nvim/lua/plugins/dashboard.lua b/.config/nvim/lua/plugins/dashboard.lua new file mode 100644 index 0000000..b288f46 --- /dev/null +++ b/.config/nvim/lua/plugins/dashboard.lua @@ -0,0 +1,75 @@ +local db = require("dashboard") +--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 = { + 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", + }, + }, + }, + hide = { + statusline = false, + tabline = false, + winbar = false, + }, + -- preview = { +-- command, -- preview command +-- file_path, -- preview file path +-- file_height, -- preview file height +-- file_width, -- preview file width +-- }, +-- footer = {} --your footer +}) + diff --git a/.config/nvim/lua/plugins/fidget.lua b/.config/nvim/lua/plugins/fidget.lua new file mode 100644 index 0000000..0f56a6b --- /dev/null +++ b/.config/nvim/lua/plugins/fidget.lua @@ -0,0 +1,33 @@ +require("fidget").setup({ + 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/.config/nvim/lua/plugins/git.lua b/.config/nvim/lua/plugins/git.lua new file mode 100644 index 0000000..963f7f9 --- /dev/null +++ b/.config/nvim/lua/plugins/git.lua @@ -0,0 +1,11 @@ +local status, git = pcall(require, "git") +if (not status) then return end + +git.setup({ + keymaps = { + -- Open blame window + blame = "<Leader>gb", + -- Open file/folder in git repository + browse = "<Leader>go", + } +}) diff --git a/.config/nvim/lua/plugins/gitsigns.lua b/.config/nvim/lua/plugins/gitsigns.lua new file mode 100644 index 0000000..c7b0726 --- /dev/null +++ b/.config/nvim/lua/plugins/gitsigns.lua @@ -0,0 +1,48 @@ +require("gitsigns").setup({ + keymaps = {}, + 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/.config/nvim/lua/plugins/goto-preview.lua b/.config/nvim/lua/plugins/goto-preview.lua new file mode 100644 index 0000000..d4d2c67 --- /dev/null +++ b/.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/.config/nvim/lua/plugins/heirline.lua b/.config/nvim/lua/plugins/heirline.lua new file mode 100644 index 0000000..dc415d5 --- /dev/null +++ b/.config/nvim/lua/plugins/heirline.lua @@ -0,0 +1,1125 @@ +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 = { + del = "#e95678", + add = "#a6e22e", + 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 = "N·OPERATOR PENDING ", + nov = "N?", + noV = "N?", + ["no\22"] = "N? ", + niI = "Ni", + niR = "Nr", + niV = "Nv", + nt = "Nt", + 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 = "darkgray", bg = self.mode_color, bold = true } end, + update = { + "ModeChanged", + }, +} + +-- 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 = require("nvim-navic").is_available, + 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 = colors.white }, + 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, + --hl = { fg = "orange" }, + hl = { fg = colors.orange, bg = colors.bg }, + { + -- git branch name + provider = function(self) + return " " .. self.status_dict.head + end, + --hl = { bold = true }, + hl = { bold = true, bg = colors.bg }, + }, + -- You could handle delimiters, icons and counts similar to Diagnostics + { + 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! +local DAPMessages = { + -- display the dap messages only on the debugged file + condition = function() + local session = require("dap").session() + if session then + local filename = vim.api.nvim_buf_get_name(0) + if session.config then + local progname = session.config.program + return filename == progname + end + end + return false + end, + provider = function() + return " " .. require("dap").status() + end, + hl = { fg = utils.get_highlight("Debug").fg }, + -- Debugger on_click: step-over, step-into, next, previous, stop buttons + -- coming soon! +} + +-- 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 help_file_name = { + 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 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.gray, force = true } }) + +Ruler = utils.surround({ "", "" }, colors.gray, { Ruler, hl = { fg = colors.gray, force = true } }) + +local left = { + { ViMode, hl = { fg = utils.get_highlight("statusline").bg, force = true } }, + { LeftSpace, 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 = utils.get_highlight("statusline").bg, 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, force = true } }, +} + +local sections = { left, middle, right } +local DefaultStatusline = { sections } + +local InactiveStatusline = { + condition = conditions.is_not_active, + { FileNameBlock, hl = { bg = colors.nobg, force = true } }, + { Align, hl = { bg = colors.nobg, force = true } }, +} + +local SpecialStatusline = { + condition = function() + return conditions.buffer_matches({ + buftype = { "nofile", "prompt", "help", "quickfix" }, + filetype = { "^git.*", "fugitive", "dashboard", }, + }) + end, + { ViMode, hl = { fg = utils.get_highlight("statusline").bg, force = true } }, + { LeftSpace, hl = { bg = colors.nobg, force = true } }, + { Space, hl = { bg = colors.nobg, force = true } }, + { Align, hl = { bg = colors.nobg, force = true } }, + { RightSpace, hl = { bg = colors.nobg, force = true } }, + { Ruler, hl = { fg = utils.get_highlight("statusline").bg, force = true } }, +} + +local TerminalStatusline = { + condition = function() + return conditions.buffer_matches({ buftype = { "terminal" } }) + end, + + -- Quickly add a condition to the ViMode to only show it when buffer is active! + --{ condition = conditions.is_active, ViMode, Space }, + { ViMode, hl = { fg = utils.get_highlight("statusline").bg, force = true } }, + { LeftSpace, hl = { bg = colors.nobg, force = true } }, + { FileNameBlock, hl = { bg = colors.nobg, force = true } }, + { Space, hl = { bg = colors.nobg, force = true } }, + { Align, hl = { bg = colors.nobg, force = true } }, + { RightSpace, hl = { bg = colors.nobg, force = true } }, + { Ruler, hl = { fg = utils.get_highlight("statusline").bg, force = true } }, +} + +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_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 = { "nofile", "prompt", "help", "quickfix" }, + filetype = { "^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 = 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.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/.config/nvim/lua/plugins/lsp.lua b/.config/nvim/lua/plugins/lsp.lua new file mode 100644 index 0000000..6c40c9c --- /dev/null +++ b/.config/nvim/lua/plugins/lsp.lua @@ -0,0 +1,327 @@ +require('mason').setup() +local lspconfig = require 'lspconfig' +local null_ls = require 'null-ls' + +local keymap = vim.keymap +local cmd = vim.cmd + +local border = { + { '🭽', 'FloatBorder' }, + { '▔', 'FloatBorder' }, + { '🭾', 'FloatBorder' }, + { '▕', 'FloatBorder' }, + { '🭿', 'FloatBorder' }, + { '▁', 'FloatBorder' }, + { '🭼', 'FloatBorder' }, + { '▏', 'FloatBorder' }, +} + +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 + +vim.diagnostic.config({ + underline = false, + signs = true, + virtual_text = false, + virtual_lines = { only_current_line = true }, + float = { + show_header = true, + source = 'if_many', + --border = 'rounded', + border = border, + focusable = true, + }, + update_in_insert = false, -- default to false + severity_sort = false, -- 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.formatting()<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", "[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-16" } + +local function prefer_null_ls_fmt(client) + client.server_capabilities.documentHighlightProvider = false + client.server_capabilities.documentFormattingProvider = false + on_attach(client) +end + +local servers = { + asm_lsp = {}, + bashls = {}, + clangd = {}, + 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' }, + }, + }, + }, + }, + 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 = {}, +} + + + +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 { + 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, + builtins.diagnostics.todo_comments, + builtins.diagnostics.teal, + -- null_ls.builtins.diagnostics.vale, + builtins.diagnostics.vint, + builtins.diagnostics.tidy, + builtins.diagnostics.php, + builtins.diagnostics.phpcs, + -- 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.clang_format, + 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.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" }, + }), + --null_ls.builtins.formatting.prettierd, + builtins.formatting.rustfmt, + builtins.formatting.stylua, + 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, + }, + 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, +} diff --git a/.config/nvim/lua/plugins/lspsaga.lua b/.config/nvim/lua/plugins/lspsaga.lua new file mode 100644 index 0000000..4161ce9 --- /dev/null +++ b/.config/nvim/lua/plugins/lspsaga.lua @@ -0,0 +1,46 @@ +return function() + local saga = require "lspsaga" + + saga.init_lsp_saga { + use_saga_diagnostic_sign = false, + finder_action_keys = { + vsplit = "v", + split = "s", + quit = { "q", "<ESC>" }, + }, + code_action_icon = "💡", + code_action_prompt = { + enable = false, + sign = false, + virtual_text = false, + }, + } + + require("as.highlights").highlight("LspSagaLightbulb", { guifg = "NONE", guibg = "NONE" }) + +-- as.vnoremap("<leader>ca", ":<c-u>lua require('lspsaga.codeaction').range_code_action()<CR>") +-- as.inoremap("<c-k>", "<cmd>lua require('lspsaga.signaturehelp').signature_help()<CR>") +-- as.nnoremap("K", "<cmd>lua require('lspsaga.hover').render_hover_doc()<CR>") +-- -- scroll down hover doc +-- as.nnoremap("<C-f>", "<cmd>lua require('lspsaga.action').smart_scroll_with_saga(1)<CR>") +-- -- scroll up hover doc +-- as.nnoremap("<C-b>", "<cmd>lua require('lspsaga.action').smart_scroll_with_saga(-1)<CR>") + + require("which-key").register { + ["<leader>rn"] = { require("lspsaga.rename").rename, "lsp: rename" }, + ["<leader>ca"] = { require("lspsaga.codeaction").code_action, "lsp: code action" }, + ["gp"] = { require("lspsaga.provider").preview_definition, "lsp: preview definition" }, + ["gh"] = { require("lspsaga.provider").lsp_finder, "lsp: finder" }, + -- jump diagnostic + ["]c"] = { require("lspsaga.diagnostic").lsp_jump_diagnostic_prev, "lsp: previous diagnostic" }, + ["[c"] = { require("lspsaga.diagnostic").lsp_jump_diagnostic_next, "lsp: next diagnostic" }, + } + + -- augroup("LspSagaCursorCommands", { + -- { + -- events = { "CursorHold" }, + -- targets = { "*" }, + -- command = "lua require('lspsaga.diagnostic').show_cursor_diagnostics()", + -- }, + -- }) +end diff --git a/.config/nvim/lua/plugins/luasnip.lua b/.config/nvim/lua/plugins/luasnip.lua new file mode 100644 index 0000000..4cceed1 --- /dev/null +++ b/.config/nvim/lua/plugins/luasnip.lua @@ -0,0 +1,64 @@ +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, -- + 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/.config/nvim/lua/plugins/modify-blend.lua b/.config/nvim/lua/plugins/modify-blend.lua new file mode 100644 index 0000000..1b2c6d5 --- /dev/null +++ b/.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/.config/nvim/lua/plugins/navic.lua b/.config/nvim/lua/plugins/navic.lua new file mode 100644 index 0000000..a58240a --- /dev/null +++ b/.config/nvim/lua/plugins/navic.lua @@ -0,0 +1,46 @@ +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 = " ", + }, + highlight = false, + separator = " > ", + depth_limit = 0, + depth_limit_indicator = "..", + safe_output = true +} diff --git a/.config/nvim/lua/plugins/neoscroll.lua b/.config/nvim/lua/plugins/neoscroll.lua new file mode 100644 index 0000000..d122584 --- /dev/null +++ b/.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/.config/nvim/lua/plugins/null-ls.lua b/.config/nvim/lua/plugins/null-ls.lua new file mode 100644 index 0000000..0ab0af8 --- /dev/null +++ b/.config/nvim/lua/plugins/null-ls.lua @@ -0,0 +1,173 @@ +--[[null-ls.]] +-- +-- null-language-server i.e. a sort of language server which does not provide any services such as formatting and diagnostics you expect from a language server. Instead it will need to install corresponding external “sources” and then hook these sources into the neovim lsp client through null-ls. +-- +local null_ls = require "null-ls" +local builtins = null_ls.builtins + +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, +} + +local sources = { + builtins.formatting.stylua, + 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.clang_format, + builtins.formatting.rustfmt, + builtins.formatting.sql_formatter, + builtins.formatting.prettierd.with({ + filetypes = { "javascript", "javascriptreact", "typescript", "typescriptreact", "json", "yaml", "markdown", "html", "css", "scss", "less", "graphql", "vue", "svelte" }, + }), + builtins.formatting.prettier.with({ + -- markdown, html/js formatting + 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.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.eslint_d.with(eslint_opts), + builtins.diagnostics.todo_comments, + builtins.diagnostics.vint, + + builtins.code_actions.shellcheck, -- shell script code actions + builtins.code_actions.eslint_d.with(eslint_opts), + builtins.code_actions.gitsigns, + builtins.code_actions.gitrebase, + builtins.hover.dictionary, + builtins.hover.printenv, +} + +local M = {} + +M.setup = function(on_attach) + local augroup = vim.api.nvim_create_augroup("LspFormatting", {}) + + null_ls.setup({ + sources = sources, + debug = false, + on_attach = function(client, bufnr) + -- Format on save + + 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, + }) +end + +return M + +--require("null-ls").setup({ +-- --debug = true, +-- disabled_filetypes = { "PKGBUILD" }, +-- timeout_ms = 5000, +-- async = true, +-- debounce = 150, +-- --log = { +-- -- enable = true, +-- -- level = 'warn', +-- -- use_console = 'async', +-- --}, +-- update_in_insert = false, +-- --fallback_severity = vim.diagnostic.severity.ERROR, +-- --log_level = "warn", +-- --on_attach = nil, +-- --on_init = nil, +-- --on_exit = nil, +-- sources = { +-- --require("null-ls").builtins.formatting.shfmt, -- shell script formatting +-- require("null-ls").builtins.diagnostics.dotenv_linter, +-- --require("null-ls").builtins.diagnostics.editorconfig_checker, +-- require("null-ls").builtins.formatting.shfmt.with({ +-- filetypes = { "bash", "zsh", "sh" }, +-- extra_args = { "-i", "2", "-ci" }, +-- }), +-- require("null-ls").builtins.formatting.prettier, -- markdown formatting +-- --require("null-ls").builtins.diagnostics.shellcheck, -- shell script diagnostics +-- require("null-ls").builtins.diagnostics.shellcheck.with({ +-- 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 +-- }), +---- require("null-ls").builtins.formatting.stylua, -- lua formatting +---- require("null-ls").builtins.formatting.black, +---- require("null-ls").builtins.formatting.prettierd, +---- require("null-ls").builtins.diagnostics.cspell.with { +---- filetypes = { "python", "rust", "typescript" }, +---- }, +---- --require("null-ls").builtins.diagnostics.luacheck, +---- --require("null-ls").builtins.diagnostics.eslint, +---- --require("null-ls").builtins.diagnostics.eslint_d, +---- require("null-ls").builtins.diagnostics.mdl, +---- require("null-ls").builtins.diagnostics.vint, +---- require("null-ls").builtins.completion.spell, +---- require("null-ls").builtins.formatting.clang_format, +---- require("null-ls").builtins.formatting.rustfmt, +---- require("null-ls").builtins.formatting.sql_formatter, +---- --require("null-ls").builtins.formatting.google_java_format, +---- require("null-ls").builtins.diagnostics.cppcheck, +-- require("null-ls").builtins.formatting.shellharden, +---- --require("null-ls").builtins.code_actions.eslint_d, +-- require("null-ls").builtins.code_actions.shellcheck, -- shell script code actions +-- require("null-ls").builtins.formatting.clang_format, +-- require("null-ls").builtins.formatting.rustfmt, +-- --require("null-ls").builtins.formatting.beautysh, +-- require("null-ls").builtins.formatting.sql_formatter, +-- require("null-ls").builtins.diagnostics.todo_comments, +-- --require("null-ls").builtins.diagnostics.zsh, +-- require("null-ls").builtins.hover.dictionary, +-- require("null-ls").builtins.hover.printenv, +-- }, +-- -- default_timeout = 5000, +-- -- diagnostics_format = '[#{c}] #{m} (#{s})', +-- -- fallback_severity = vim.diagnostic.severity.ERROR, +-- -- log = { +-- -- enable = true, +-- -- level = 'warn', +-- -- use_console = 'async', +-- -- }, +-- --on_attach = nil, +-- --on_init = nil, +-- --on_exit = nil, +-- --update_in_insert = false, +-- --update_in_leave = false, +--}) diff --git a/.config/nvim/lua/plugins/nvim-tree.lua b/.config/nvim/lua/plugins/nvim-tree.lua new file mode 100644 index 0000000..a1731ff --- /dev/null +++ b/.config/nvim/lua/plugins/nvim-tree.lua @@ -0,0 +1,134 @@ +local status_ok, nvim_tree = pcall(require, "nvim-tree") +if not status_ok then + return +end + +local config_status_ok, nvim_tree_config = pcall(require, "nvim-tree.config") +if not config_status_ok then + return +end + +local tree_cb = nvim_tree_config.nvim_tree_callback + +-- To see mappings `g?` on nvim-tree +-- To see default mappings `:nvim-tree-default-mappings` + +nvim_tree.setup({ + update_focused_file = { + enable = true, + update_cwd = true, + }, + git = { + enable = true, + ignore = false, + timeout = 500, +}, + renderer = { + root_folder_modifier = ":t", + indent_markers = { + enable = true, + }, + icons = { + glyphs = { + default = "", + symlink = "", + folder = { + arrow_open = "", + arrow_closed = "", + default = "", + open = "", + empty = "", + empty_open = "", + symlink = "", + symlink_open = "", + }, + git = { + unstaged = "", + staged = "S", + unmerged = "", + renamed = "➜", + untracked = "U", + deleted = "", + ignored = "◌", + }, + }, + }, + }, + diagnostics = { + enable = true, + show_on_dirs = true, + icons = { + hint = "", + info = "", + warning = "", + error = "", + }, + }, + view = { + width = 30, + --height = 30, + side = "left", + --mappings = { + -- list = { + -- { key = { "l", "<CR>", "o" }, cb = tree_cb("edit") }, + -- { key = "h", cb = tree_cb("close_node") }, + -- { key = "v", cb = tree_cb("vsplit") }, + -- { key = "u", action = "dir_up" }, + -- }, + --}, + }, +}) + +-- Highlight Groups +vim.api.nvim_command("highlight NvimTreeNormal guibg=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 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 NvimTreeWindowPicker ") +--vim.api.nvim_command("highlight NvimTreeNormal ") +--vim.api.nvim_command("highlight NvimTreeEndOfBuffer ") --(NonText) +--vim.api.nvim_command("highlight NvimTreeCursorLine ") --(CursorLine) +--vim.api.nvim_command("highlight NvimTreeCursorLineNr ") --(CursorLineNr) +--vim.api.nvim_command("highlight NvimTreeLineNr ") --(LineNr) +--vim.api.nvim_command("highlight NvimTreeWinSeparator ") --(WinSeparator) +--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/.config/nvim/lua/plugins/prettier.lua b/.config/nvim/lua/plugins/prettier.lua new file mode 100644 index 0000000..05d4665 --- /dev/null +++ b/.config/nvim/lua/plugins/prettier.lua @@ -0,0 +1,19 @@ +local status, prettier = pcall(require, "prettier") +if (not status) then return end + +prettier.setup { + bin = 'prettierd', + filetypes = { + "c", + "lua", + "vim", + --"css", + --"javascript", + --"javascriptreact", + --"typescript", + --"typescriptreact", + --"json", + --"scss", + "less" + } +} diff --git a/.config/nvim/lua/plugins/quickfix.lua b/.config/nvim/lua/plugins/quickfix.lua new file mode 100644 index 0000000..4ea2374 --- /dev/null +++ b/.config/nvim/lua/plugins/quickfix.lua @@ -0,0 +1,18 @@ +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/.config/nvim/lua/plugins/scripts/lsp-ext.lua b/.config/nvim/lua/plugins/scripts/lsp-ext.lua new file mode 100644 index 0000000..c4378c6 --- /dev/null +++ b/.config/nvim/lua/plugins/scripts/lsp-ext.lua @@ -0,0 +1,48 @@ +-- +-- lsp-ext.lua + + +M = {} + +function M.preview_location(location, context, before_context) + -- location may be LocationLink or Location (more useful for the former) + context = context or 15 + before_context = before_context or 0 + local uri = location.targetUri or location.uri + if uri == nil then + return + end + local bufnr = vim.uri_to_bufnr(uri) + if not vim.api.nvim_buf_is_loaded(bufnr) then + vim.fn.bufload(bufnr) + end + local range = location.targetRange or location.range + local contents = + vim.api.nvim_buf_get_lines(bufnr, range.start.line - before_context, range["end"].line + 1 + context, false) + local filetype = vim.api.nvim_buf_get_option(bufnr, "filetype") + return vim.lsp.util.open_floating_preview(contents, filetype) +end + +function M.preview_location_callback(_, method, result) + local context = 15 + if result == nil or vim.tbl_isempty(result) then + print("No location found: " .. method) + return nil + end + if vim.tbl_islist(result) then + M.floating_buf, M.floating_win = M.preview_location(result[1], context) + else + M.floating_buf, M.floating_win = M.preview_location(result, context) + end +end + +function M.peek_definition() + if vim.tbl_contains(vim.api.nvim_list_wins(), M.floating_win) then + vim.api.nvim_set_current_win(M.floating_win) + else + local params = vim.lsp.util.make_position_params() + return vim.lsp.buf_request(0, "textDocument/definition", params, M.preview_location_callback) + end +end + +return M diff --git a/.config/nvim/lua/plugins/scripts/setcolors.lua b/.config/nvim/lua/plugins/scripts/setcolors.lua new file mode 100644 index 0000000..605bc84 --- /dev/null +++ b/.config/nvim/lua/plugins/scripts/setcolors.lua @@ -0,0 +1,121 @@ +vim.cmd([[ +" Change the color scheme from a list of color scheme names. +" Version 2010-09-12 from http://vim.wikia.com/wiki/VimTip341 +" Press key: +" F8 next scheme +" Shift-F8 previous scheme +" Alt-F8 random scheme +" Set the list of color schemes used by the above (default is 'all'): +" :SetColors all (all $VIMRUNTIME/colors/*.vim) +" :SetColors my (names built into script) +" :SetColors blue ayu ron (these schemes) +" :SetColors (display current scheme names) +" Set the current color scheme based on time of day: +" :SetColors now +if v:version < 700 || exists('loaded_setcolors') || &cp + finish +endif + +let loaded_setcolors = 1 +let s:mycolors = ['everblush', 'ayu', 'gruvbox', 'molokai', 'onedark', 'srcery'] " colorscheme names that we use to set color + +" Set list of color scheme names that we will use, except +" argument 'now' actually changes the current color scheme. +function! s:SetColors(args) + if len(a:args) == 0 + echo 'Current color scheme names:' + let i = 0 + while i < len(s:mycolors) + echo ' '.join(map(s:mycolors[i : i+4], 'printf("%-14s", v:val)')) + let i += 5 + endwhile + elseif a:args == 'all' + let paths = split(globpath(&runtimepath, 'colors/*.vim'), "\n") + let s:mycolors = uniq(sort(map(paths, 'fnamemodify(v:val, ":t:r")'))) + echo 'List of colors set from all installed color schemes' + elseif a:args == 'my' + let c1 = 'default srcery everblush' + let c2 = 'gruvbox onedark' + let c3 = 'ayu molokai' + let s:mycolors = split(c1.' '.c2.' '.c3) + echo 'List of colors set from built-in names' + elseif a:args == 'now' + call s:HourColor() + else + let s:mycolors = split(a:args) + echo 'List of colors set from argument (space-separated names)' + endif +endfunction + +command! -nargs=* SetColors call s:SetColors('<args>') + +" Set next/previous/random (how = 1/-1/0) color from our list of colors. +" The 'random' index is actually set from the current time in seconds. +" Global (no 's:') so can easily call from command line. +function! NextColor(how) + call s:NextColor(a:how, 1) +endfunction + +" Helper function for NextColor(), allows echoing of the color name to be +" disabled. +function! s:NextColor(how, echo_color) + if len(s:mycolors) == 0 + call s:SetColors('all') + endif + if exists('g:colors_name') + let current = index(s:mycolors, g:colors_name) + else + let current = -1 + endif + let missing = [] + let how = a:how + for i in range(len(s:mycolors)) + if how == 0 + let current = localtime() % len(s:mycolors) + let how = 1 " in case random color does not exist + else + let current += how + if !(0 <= current && current < len(s:mycolors)) + let current = (how>0 ? 0 : len(s:mycolors)-1) + endif + endif + try + execute 'colorscheme '.s:mycolors[current] + break + catch /E185:/ + call add(missing, s:mycolors[current]) + endtry + endfor + redraw + if len(missing) > 0 + echo 'Error: colorscheme not found:' join(missing) + endif + if (a:echo_color) + echo g:colors_name + endif +endfunction + +nnoremap <leader>cn :call NextColor(1)<CR> +nnoremap <leader>cp :call NextColor(-1)<CR> +nnoremap <leader>cc :call NextColor(0)<CR> + +" Set color scheme according to current time of day. +function! s:HourColor() + let hr = str2nr(strftime('%H')) + if hr <= 3 + let i = 0 + elseif hr <= 7 + let i = 1 + elseif hr <= 14 + let i = 2 + elseif hr <= 18 + let i = 3 + else + let i = 4 + endif + let nowcolors = 'srcery onedark molokai' + execute 'colorscheme '.split(nowcolors)[i] + redraw + echo g:colors_name +endfunction +]]) diff --git a/.config/nvim/lua/plugins/scripts/toggleLsp.lua b/.config/nvim/lua/plugins/scripts/toggleLsp.lua new file mode 100644 index 0000000..28af698 --- /dev/null +++ b/.config/nvim/lua/plugins/scripts/toggleLsp.lua @@ -0,0 +1,40 @@ +local M = {} + +local check_function = function(bufnr, _) + local ok, result = pcall(vim.api.nvim_buf_get_var, bufnr, 'lsp_enabled') + -- No buffer local variable set, so just enable by default + if not ok then + return true + end + + return result +end + +vim.lsp.handlers["textDocument/publishDiagnostics"] = + vim.lsp.with(vim.lsp.diagnostic.on_publish_diagnostics, { + underline = check_function, + virtual_text = check_function, + signs = check_function + }) + +function M.Enable() + vim.b.lsp_enabled = true +end + +function M.Disable() + vim.b.lsp_enabled = false +end + +function M.Toggle() + if vim.b.lsp_enabled == false then + M.Enable() + else + M.Disable() + end +end + +vim.cmd [[ + command! -nargs=* ToggleLsp lua require'lsp.toggle'.Toggle() +]] + +return M diff --git a/.config/nvim/lua/plugins/telescope.lua b/.config/nvim/lua/plugins/telescope.lua new file mode 100644 index 0000000..1299b2f --- /dev/null +++ b/.config/nvim/lua/plugins/telescope.lua @@ -0,0 +1,373 @@ +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 themes = require("telescope.themes") +local utils = require("telescope.utils") +local action_state = require("telescope.actions.state") +local layout_actions = require("telescope.actions.layout") + + +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", + "%.DS_Store", + "%.git/", + "%.spl", + "%.log", + "%[No Name%]", -- new files / sometimes folders (netrw) + "/$", -- ignore folders (netrw) + "node_modules", + "%.png", + "%.zip", + "%.pxd", + "^.vim/", + "^.local/", + "^.cache/", + "^downloads/", + --"^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-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 = { + ["<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, + + ["<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, + + ["?"] = 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", + }, + }, + pickers = { + live_grep = { + disable_coordinates = true, + layout_config = { + horizontal = { + preview_width = 0.55, + }, + }, + }, + }, + --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, + --}, + --find_files = { + -- cwd='%:p:h', + -- prompt_prefix=' ', + -- hidden = true, + -- follow = true, + --}, + --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 = true, + 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').extensions.notify.notify() +require('telescope').load_extension('notify') + +function M.find_configs() + require("telescope.builtin").find_files { + hidden = true, + no_ignore = false, + prompt_title = " Find Configs", + results_title = "Config Files", + path_display = { "smart" }, + search_dirs = { + "~/.config/nvim", + "~/.config/zsh", + "~/.config/tmux", + "~/.config/X11", + "~/.config/alacritty", + "~/.config/kitty", + "~/.config/wezterm", + "~/.config/bspwm", + "~/.config/sxhkd", + "~/.config/picom", + "~/.bashrc", + }, + -- cwd = "~/.config/nvim/", + file_ignore_patterns = { + "~/.config/nvim/startup.log", + "packer_compiled.lua", + "resurrect", + "tmux/plugins", + --"^~/.config/tmux/plugins", + "%.txt", + ".git", + }, + 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 = { + "~/.local/bin/scripts", + }, + layout_strategy = "horizontal", + layout_config = { preview_width = 0.65, width = 0.75 }, + } +end + +function M.find_projects() + require("telescope.builtin").find_files { + hidden = true, + no_ignore = true, + prompt_title = " Find Projects", + path_display = { "smart" }, + search_dirs = { + "~/projects", + }, + layout_strategy = "horizontal", + layout_config = { preview_width = 0.65, width = 0.75 }, + } +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 = false, + prompt_title = " Find Notes", + path_display = { "smart" }, + search_dirs = { + "~/documents/notes/private/", + "~/documents/notes", + }, + --cwd = "~documents/notes", + layout_strategy = "horizontal", + layout_config = { preview_width = 0.65, width = 0.75 }, + } +end + +function M.file_explorer() + require("telescope.builtin").file_browser({ + prompt_title = "File Browser", + cwd = "~", + layout_strategy = "horizontal", + }) +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 + +return M diff --git a/.config/nvim/lua/plugins/toggleterm.lua b/.config/nvim/lua/plugins/toggleterm.lua new file mode 100644 index 0000000..f787f46 --- /dev/null +++ b/.config/nvim/lua/plugins/toggleterm.lua @@ -0,0 +1,155 @@ +local status_ok, toggleterm = pcall(require, "toggleterm") +if not status_ok then + return +end +toggleterm.setup({ + --size = function(term) + -- if term.direction == "horizontal" then + -- return 12 + -- elseif term.direction == "vertical" then + -- return vim.o.columns * 0.3 + -- end + --end, + --size = 20, + open_mapping = [[<leader>tt]], + --autochdir = true, + hide_numbers = true, + shade_filetypes = {}, + shade_terminals = false, + shading_factor = 1, + start_in_insert = true, + insert_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", + }, + --float_opts = { + -- border = as.style.current.border, + -- winblend = 3, + --}, + size = function(term) + if term.direction == 'horizontal' then + return 15 + elseif term.direction == 'vertical' then + return math.floor(vim.o.columns * 0.4) + end + end, + }, + float_opts = { + width = 70, + height = 15, + winblend = 3, + border = "curved", + --winblend = 0, + highlights = { + border = "Normal", + background = "Normal", + }, + }, +}) +local mods = require("user.mods") +local float_handler = function(term) + + if not mods.empty(vim.fn.mapcheck('jj', 't')) then + vim.keymap.del('t', 'jj', { 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, "t", "<esc>", [[<C-\><C-n>]], opts) + vim.api.nvim_buf_set_keymap(0, "t", "jj", [[<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 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 + diff --git a/.config/nvim/lua/plugins/treesitter.lua b/.config/nvim/lua/plugins/treesitter.lua new file mode 100644 index 0000000..7f481d3 --- /dev/null +++ b/.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/.config/nvim/lua/plugins/trouble.lua b/.config/nvim/lua/plugins/trouble.lua new file mode 100644 index 0000000..d4f50dc --- /dev/null +++ b/.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 = "workspace_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 = "", + hint = "", + information = "", + other = "" + }, + use_diagnostic_signs = false -- enabling this will use the signs defined in your lsp client +} diff --git a/.config/nvim/lua/plugins/web-devicons.lua b/.config/nvim/lua/plugins/web-devicons.lua new file mode 100644 index 0000000..2f68275 --- /dev/null +++ b/.config/nvim/lua/plugins/web-devicons.lua @@ -0,0 +1,17 @@ +--local status, icons = pcall(require, "nvim-web-devicons") +--if (not status) then return end +--icons.setup { +require'nvim-web-devicons'.setup { + override = { + zsh = { + icon = "", + color = "#428850", + cterm_color = "65", + name = "Zsh" + }; + color_icons = true; + }, + -- globally enable default icons (default to false) + -- will get overriden by `get_icons` option + --default = true +} diff --git a/.config/nvim/lua/plugins/zen-mode.lua b/.config/nvim/lua/plugins/zen-mode.lua new file mode 100644 index 0000000..7e52854 --- /dev/null +++ b/.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/.config/nvim/lua/user/func.lua b/.config/nvim/lua/user/func.lua new file mode 100644 index 0000000..c36d9e2 --- /dev/null +++ b/.config/nvim/lua/user/func.lua @@ -0,0 +1,138 @@ +--vim.cmd([[ +-- function RandomColorScheme() +-- let mycolors = split(globpath(&rtp,"**/colors/*.vim"),"\n") +-- exe 'so ' . mycolors[localtime() % len(mycolors)] +-- unlet mycolors +-- endfunction +-- +-- call RandomColorScheme() +-- +-- :command NewColor call RandomColorScheme() +--]]) + +--vim.cmd([[ +-- function RandomColorSchemeMyPicks() +-- let mypicks = ["pyte", "fokus", "github", "peachpuff", "morning", "simple256", "xcode", "gruvbox"] +-- let mypick = mypicks[localtime() % len(mypicks)] +-- echom mypick +-- execute 'colo' mypick +-- endfunction +-- +-- command NewColor call RandomColorSchemeMyPicks() +-- +-- let s:use_gui = exists('g:neovide') || has('gui_running') || (has('termguicolors') && &termguicolors) +-- if (s:use_gui) +-- call RandomColorSchemeMyPicks() +-- endif +--]]) + +--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)) +--]]) +-- +--vim.cmd([[ +-- " Enable mouse scrollback +-- 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 +--]]) +-- +--vim.cmd([[ +-- " :Rename {newname} +-- function! 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 +-- map <leader>re :call RenameFile()<cr> +--]]) + +--vim.cmd([[ +-- " Markdown Settings +-- autocmd BufNewFile,BufReadPost *.md set filetype=markdown +-- let g:markdown_fenced_languages = ['html', 'python', 'bash=sh', 'sql', 'pug'] +-- let g:markdown_minlines = 100 +-- let g:instant_markdown_autostart = 0 +--]]) +-- +--vim.cmd([[ +-- " 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 +--]]) diff --git a/.config/nvim/lua/user/keys.lua b/.config/nvim/lua/user/keys.lua new file mode 100644 index 0000000..c0592da --- /dev/null +++ b/.config/nvim/lua/user/keys.lua @@ -0,0 +1,382 @@ +--[[ key.lua ]] +------------- Shorten Function Names -------------- +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 } + +--------------- Standard Operations --------------- +-- Semi-colon as leader key +vim.g.mapleader = ";" + +-- 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>", ".") + +-- "jj" to exit insert-mode +map("i", "jj", "<esc>") + +-- 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 +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 }) + +-- 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 +map("n", "<leader>n", ":bn<cr>") +map("n", "<leader>p", ":bp<cr>") +map("n", "<leader>d", ":bd<cr>") + +-- List marks +map("n", "<Leader>m", ":marks<CR>") + +-- Messages +map("n", "<Leader>M", ":messages<CR>") + +-- Clear messages + +-- Clear messages or just refresh/redraw the screen +map("n", "<leader>u", ":echo '' | redraw<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("n", "<C-J>", "<C-W><C-J>") +--map("n", "<C-K>", "<C-W><C-K>") +--map("n", "<C-L>", "<C-W><C-L>") +--map("n", "<C-H>", "<C-W><C-H>") + +-- Split window +map("n", "<leader>h", ":split<CR>") +map("n", "<leader>v", ":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 mode to move directional +map("i", "<A-h>", "<left>") +map("i", "<A-j>", "<down>") +map("i", "<A-k>", "<up>") +map("i", "<A-l>", "<right>") + +-- Map Alt+(h/j/k/l) in command mode to move directional +vim.api.nvim_set_keymap('c', '<A-h>', '<Left>', { noremap = true }) +vim.api.nvim_set_keymap('c', '<A-j>', '<Down>', { noremap = true }) +vim.api.nvim_set_keymap('c', '<A-k>', '<Up>', { noremap = true }) +vim.api.nvim_set_keymap('c', '<A-l>', '<Right>', { noremap = true }) + +-- 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>") + +-- Move to the next and previous item in the quickfixlist +--map("n", "]c", "<Cmd>cnext<CR>") +--map("n", "[c", "<Cmd>cprevious<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) + +-- 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>') + +-- Search and replace +map("v", "<leader>sr", 'y:%s/<C-r><C-r>"//g<Left><Left>c') + +-- Toggle Diff +map("n", "<leader>dt", "<Cmd>call utils#ToggleDiff()<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", ":!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 + +-- 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 +--utils.map("n", "<F2>", "&foldlevel ? 'zM' : 'zR'", { expr = true }) + +-- Use space to toggle fold +--utils.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> +]]) + +-- 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', '<S-h>', ':call 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", "<leader>tt", "<cmd>ToggleTerm<cr>") + +-- LazyGit +map({ "n", "t" }, "<leader>gg", "<cmd>lua Lazygit_toggle()<CR>") + +-- Fugitive git bindings +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>") +-- map["<C-\\>"] = { "<cmd>ToggleTerm<cr>", desc = "Toggle terminal" } +-- map["<leader>tn"] = { function() toggle_term_cmd "node" end, desc = "ToggleTerm node" } +-- map["<leader>tu"] = { function() toggle_term_cmd "ncdu" end, desc = "ToggleTerm NCDU" } +-- map["<leader>tt"] = { function() toggle_term_cmd "htop" end, desc = "ToggleTerm htop" } +-- map["<leader>tp"] = { function() toggle_term_cmd "python" end, desc = "ToggleTerm python" } +-- map["<leader>tl"] = { function() toggle_term_cmd "lazygit" end, desc = "ToggleTerm lazygit" } +-- map["<leader>tf"] = { "<cmd>ToggleTerm direction=float<cr>", desc = "ToggleTerm float" } +-- map["<leader>th"] = { "<cmd>ToggleTerm size=10 direction=horizontal<cr>", desc = "ToggleTerm horizontal split" } +-- map["<leader>tv"] = { "<cmd>ToggleTerm size=80 direction=vertical<cr>", desc = "ToggleTerm vertical split" } +--end + +-- Telescope +map("n", "<leader>ff", function() require("telescope.builtin").find_files { hidden = true, no_ignore = true } end) -- find all files +map("n", "<leader>fF", "<cmd>lua require('telescope.builtin').find_files()<cr>") -- find files with hidden option +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>ffc", "<cmd>lua require('telescope.builtin').current_buffer_fuzzy_find()<cr>") +map("n", "<leader>cf", "<cmd>Telescope changed_files<cr>") +map("n", "<leader>fp", "<cmd>Telescope pickers<cr>") +map("n", "<leader>fr", "<cmd>lua require('telescope.builtin').registers({})<CR>") -- registers picker +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>fn", [[<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>f.", [[<Cmd>lua require'plugins.telescope'.find_configs()<CR>]]) -- find configs +map("n", "<leader>fs", [[<Cmd>lua require'plugins.telescope'.find_scripts()<CR>]]) -- find scripts +map("n", "<leader>fw", [[<Cmd>lua require'plugins.telescope'.find_projects()<CR>]]) -- find projects +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 + +-- FZF +map("n", "<leader>fz", "<cmd>lua require('fzf-lua').files()<CR>") + +-- Nvim-tree +map("n", "<leader>f", ":NvimTreeToggle<CR>", {}) + +-- 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", "<CMD>TroubleToggle<CR>") +map("n", "<leader>tw", "<CMD>TroubleToggle workspace_diagnostics<CR>") +map("n", "<leader>td", "<CMD>TroubleToggle document_diagnostics<CR>") +map("n", "<leader>tq", "<CMD>TroubleToggle quickfix<CR>") +map("n", "<leader>tl", "<CMD>TroubleToggle loclist<CR>") +map("n", "gR", "<CMD>TroubleToggle lsp_references<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() + --require("quickfix").open() + end +end, { desc = "Toggle quickfix window" }) + +-- 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>dl", require("dap.ui.widgets").hover) +map("n", "<leader>dc", dap.continue) +map("n", "<leader>db", dap.toggle_breakpoint) +map("n", "<leader>dn", dap.step_over) +map("n", "<leader>di", dap.step_into) +map("n", "<leader>do", dap.step_out) +map("n", "<leader>dC", function() + dap.clear_breakpoints() + require("notify")("Breakpoints cleared", "warn") +end) + +-- 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) + +-- Dashboard +map("n", "<leader><Space>", "<CMD>Dashboard<CR>") + +-- Lsp Lines toggle +map("", "<Leader>l", require("lsp_lines").toggle, { desc = "Toggle lsp_lines" }) diff --git a/.config/nvim/lua/user/mods.lua b/.config/nvim/lua/user/mods.lua new file mode 100644 index 0000000..e523eb7 --- /dev/null +++ b/.config/nvim/lua/user/mods.lua @@ -0,0 +1,218 @@ +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 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 = augroup, buffer = bufnr }) + vim.api.nvim_create_autocmd("BufWritePre", { + group = augroup, + buffer = bufnr, + callback = function() + -- on 0.8, you should use vim.lsp.buf.format({ bufnr = bufnr }) instead + vim.lsp.buf.formatting_seq_sync() + end, + }) + end + end, +}) + + +-------------------------------------------------- + +---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 + +-------------------------------------------------- + +--- 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() +--]]) + + +-------------------------------------------------- + +-- 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]] + +-------------------------------------------------- + +vim.cmd [[autocmd BufWritePre <buffer> lua vim.lsp.buf.format()]] +--vim.cmd [[autocmd BufWritePre * lua vim.lsp.buf.format()]] + +-------------------------------------------------- + + +return M diff --git a/.config/nvim/lua/user/opts.lua b/.config/nvim/lua/user/opts.lua new file mode 100644 index 0000000..aa4d0c2 --- /dev/null +++ b/.config/nvim/lua/user/opts.lua @@ -0,0 +1,277 @@ +--[[ opts.lua ]] + +-- " Load indent files, to automatically do language-dependent indenting. +--vim.cmd([[ +-- "filetype plugin indent on +--]]) + +-- 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 +]] + +-- 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 + +-- Colors +vim.opt.termguicolors = true + +-- Behaviour +vim.opt.clipboard:append({ "unnamedplus" }) -- Install xclip or this will slowdown startup +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 = true -- 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 = { prefix .. "/nvim/tmp/.undo//" } +vim.opt.backupdir = { prefix .. "/nvim/tmp/.backup//" } +vim.opt.directory = { prefix .. "/nvim/tmp/.swp//" } +vim.opt.backup = false -- +vim.opt.undofile = false -- +vim.opt.swapfile = true -- +-- 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.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.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" }) + +vim.opt.clipboard:append({ "unnamedplus" }) -- Install xclip or this will slowdown startup +-- 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 +]]) diff --git a/.config/nvim/lua/user/pack.lua b/.config/nvim/lua/user/pack.lua new file mode 100644 index 0000000..951e9f7 --- /dev/null +++ b/.config/nvim/lua/user/pack.lua @@ -0,0 +1,268 @@ +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 we 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("williamboman/mason-lspconfig.nvim") -- Bridges mason.nvim with nvim-lspconfig to help use them together + use("neovim/nvim-lspconfig") -- Collection of LSP configs + 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("gabrielpoca/replacer.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 + + -- 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-fzf-native.nvim", run = "make" }) -- Support fzf syntax/algorithm + use("nvim-telescope/telescope-ui-select.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("axkirillov/telescope-changed-files") -- + + -- UX + use({ + 'numToStr/Navigator.nvim', -- Navigate between Tmux and Nvim + config = function() + require('Navigator').setup() + end, + }) + use({ "tpope/vim-eunuch", cmd = { "Rename", "Delete" } }) -- Handy unix commands inside Vim (Rename, Move etc.) + --use("tpope/vim-surround") -- + --use("tpope/vim-obsession") -- + --use("tpope/vim-unimpaired") -- + --use("vimpostor/vim-tpipeline") -- + --use("nathom/filetype.nvim") -- + 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({ + "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") -- + --use("vim-test/vim-test") -- + --use({ + -- "rcarriga/vim-ultest", -- + -- requires = { "vim-test/vim-test" }, + -- run = ":UpdateRemotePlugins", + -- config = function() + -- require("plugins.ultest") + -- end, + --}) + + -- Colorschemes + use("bluz71/vim-nightfly-guicolors") + use("ayu-theme/ayu-vim") + use("joshdick/onedark.vim") + use("NTBBloodbath/doom-one.nvim") + use("nyngwang/nvimgelion") + + -- UI + use("kyazdani42/nvim-web-devicons") -- + use("onsails/lspkind-nvim") -- + --use({ + -- 'goolord/alpha-nvim', + -- requires = { 'nvim-tree/nvim-web-devicons' }, + -- config = function () + -- require'alpha'.setup(require'alpha.themes.startify'.config) + -- 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") -- + use( "j-hui/fidget.nvim") -- UI to show nvim-lsp progress + 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', + }) + + -- 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({ + "iamcco/markdown-preview.nvim", -- Markdown Preview + run = function() vim.fn["mkdp#util#install"]() end, + }) + use({ + "ellisonleao/glow.nvim", -- Markdown Preview + config = function() + require("glow").setup({ + style = "dark", + }) + end + }) + +-------------------------------------------------- + + -- 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/.config/nvim/snippets/boilerplate.lua b/.config/nvim/snippets/boilerplate.lua new file mode 100644 index 0000000..04e973a --- /dev/null +++ b/.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/.config/nvim/snippets/lua.lua b/.config/nvim/snippets/lua.lua new file mode 100644 index 0000000..523d2f4 --- /dev/null +++ b/.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, "") } + ), + "jk" +) --}}} +-- 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/.config/nvim/snippets/markdown.lua b/.config/nvim/snippets/markdown.lua new file mode 100644 index 0000000..d0d1487 --- /dev/null +++ b/.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 |
