diff options
author | kylo252 <[email protected]> | 2021-10-10 21:07:41 +0200 |
---|---|---|
committer | GitHub <[email protected]> | 2021-10-10 21:07:41 +0200 |
commit | 52b74557415eb757ad4b7481b0aec8a3f98dd58d (patch) | |
tree | 9a05ec71a46c99fbdf8df0043be652b528c7c04e /lua/lvim/core | |
parent | e2c85df440564a62fd804555747b1652a6844a5e (diff) |
feat: add an independent lvim namespace (#1699)
Diffstat (limited to 'lua/lvim/core')
-rw-r--r-- | lua/lvim/core/autocmds.lua | 129 | ||||
-rw-r--r-- | lua/lvim/core/autopairs.lua | 81 | ||||
-rw-r--r-- | lua/lvim/core/bufferline.lua | 25 | ||||
-rw-r--r-- | lua/lvim/core/builtins/init.lua | 28 | ||||
-rw-r--r-- | lua/lvim/core/cmp.lua | 265 | ||||
-rw-r--r-- | lua/lvim/core/commands.lua | 25 | ||||
-rw-r--r-- | lua/lvim/core/comment.lua | 31 | ||||
-rw-r--r-- | lua/lvim/core/dap.lua | 76 | ||||
-rw-r--r-- | lua/lvim/core/dashboard.lua | 112 | ||||
-rw-r--r-- | lua/lvim/core/gitsigns.lua | 64 | ||||
-rw-r--r-- | lua/lvim/core/info.lua | 174 | ||||
-rw-r--r-- | lua/lvim/core/log.lua | 60 | ||||
-rw-r--r-- | lua/lvim/core/lualine/colors.lua | 16 | ||||
-rw-r--r-- | lua/lvim/core/lualine/components.lua | 154 | ||||
-rw-r--r-- | lua/lvim/core/lualine/conditions.lua | 17 | ||||
-rw-r--r-- | lua/lvim/core/lualine/init.lua | 47 | ||||
-rw-r--r-- | lua/lvim/core/lualine/styles.lua | 137 | ||||
-rw-r--r-- | lua/lvim/core/lualine/utils.lua | 27 | ||||
-rw-r--r-- | lua/lvim/core/nvimtree.lua | 141 | ||||
-rw-r--r-- | lua/lvim/core/project.lua | 51 | ||||
-rw-r--r-- | lua/lvim/core/telescope.lua | 193 | ||||
-rw-r--r-- | lua/lvim/core/terminal.lua | 114 | ||||
-rw-r--r-- | lua/lvim/core/treesitter.lua | 81 | ||||
-rw-r--r-- | lua/lvim/core/which-key.lua | 270 |
24 files changed, 2318 insertions, 0 deletions
diff --git a/lua/lvim/core/autocmds.lua b/lua/lvim/core/autocmds.lua new file mode 100644 index 00000000..4f29f0e1 --- /dev/null +++ b/lua/lvim/core/autocmds.lua @@ -0,0 +1,129 @@ +local autocommands = {} +local user_config_file = require("lvim.config"):get_user_config_path() + +lvim.autocommands = { + _general_settings = { + { + "Filetype", + "*", + "lua require('lvim.utils.ft').do_filetype(vim.fn.expand(\"<amatch>\"))", + }, + { + "FileType", + "qf", + "nnoremap <silent> <buffer> q :q<CR>", + }, + { + "FileType", + "lsp-installer", + "nnoremap <silent> <buffer> q :q<CR>", + }, + { + "TextYankPost", + "*", + "lua require('vim.highlight').on_yank({higroup = 'Search', timeout = 200})", + }, + { + "BufWinEnter", + "*", + "setlocal formatoptions-=c formatoptions-=r formatoptions-=o", + }, + { + "BufWinEnter", + "dashboard", + "setlocal cursorline signcolumn=yes cursorcolumn number", + }, + { + "BufRead", + "*", + "setlocal formatoptions-=c formatoptions-=r formatoptions-=o", + }, + { + "BufNewFile", + "*", + "setlocal formatoptions-=c formatoptions-=r formatoptions-=o", + }, + { "BufWritePost", user_config_file, "lua require('lvim.config'):reload()" }, + { + "FileType", + "qf", + "set nobuflisted", + }, + -- { "VimLeavePre", "*", "set title set titleold=" }, + }, + _filetypechanges = { + { "BufWinEnter", ".tf", "setlocal filetype=terraform" }, + { "BufRead", "*.tf", "setlocal filetype=terraform" }, + { "BufNewFile", "*.tf", "setlocal filetype=terraform" }, + { "BufWinEnter", ".zsh", "setlocal filetype=sh" }, + { "BufRead", "*.zsh", "setlocal filetype=sh" }, + { "BufNewFile", "*.zsh", "setlocal filetype=sh" }, + }, + -- _solidity = { + -- {'BufWinEnter', '.sol', 'setlocal filetype=solidity'}, {'BufRead', '*.sol', 'setlocal filetype=solidity'}, + -- {'BufNewFile', '*.sol', 'setlocal filetype=solidity'} + -- }, + -- _gemini = { + -- {'BufWinEnter', '.gmi', 'setlocal filetype=markdown'}, {'BufRead', '*.gmi', 'setlocal filetype=markdown'}, + -- {'BufNewFile', '*.gmi', 'setlocal filetype=markdown'} + -- }, + _git = { + { "FileType", "gitcommit", "setlocal wrap" }, + { "FileType", "gitcommit", "setlocal spell" }, + }, + _markdown = { + { "FileType", "markdown", "setlocal wrap" }, + { "FileType", "markdown", "setlocal spell" }, + }, + _buffer_bindings = { + { "FileType", "floaterm", "nnoremap <silent> <buffer> q :q<CR>" }, + }, + _auto_resize = { + -- will cause split windows to be resized evenly if main window is resized + { "VimResized", "*", "wincmd =" }, + }, + _packer_compile = { + -- will run PackerCompile after writing plugins.lua + { "BufWritePost", "plugins.lua", "PackerCompile" }, + }, + _general_lsp = { + { "FileType", "lspinfo", "nnoremap <silent> <buffer> q :q<CR>" }, + }, + + -- _fterm_lazygit = { + -- -- will cause esc key to exit lazy git + -- {"TermEnter", "*", "call LazyGitNativation()"} + -- }, + -- _mode_switching = { + -- -- will switch between absolute and relative line numbers depending on mode + -- {'InsertEnter', '*', 'if &relativenumber | let g:ms_relativenumberoff = 1 | setlocal number norelativenumber | endif'}, + -- {'InsertLeave', '*', 'if exists("g:ms_relativenumberoff") | setlocal relativenumber | endif'}, + -- {'InsertEnter', '*', 'if &cursorline | let g:ms_cursorlineoff = 1 | setlocal nocursorline | endif'}, + -- {'InsertLeave', '*', 'if exists("g:ms_cursorlineoff") | setlocal cursorline | endif'}, + -- }, + custom_groups = {}, +} + +function autocommands.define_augroups(definitions) -- {{{1 + -- Create autocommand groups based on the passed definitions + -- + -- The key will be the name of the group, and each definition + -- within the group should have: + -- 1. Trigger + -- 2. Pattern + -- 3. Text + -- just like how they would normally be defined from Vim itself + for group_name, definition in pairs(definitions) do + vim.cmd("augroup " .. group_name) + vim.cmd "autocmd!" + + for _, def in pairs(definition) do + local command = table.concat(vim.tbl_flatten { "autocmd", def }, " ") + vim.cmd(command) + end + + vim.cmd "augroup END" + end +end + +return autocommands diff --git a/lua/lvim/core/autopairs.lua b/lua/lvim/core/autopairs.lua new file mode 100644 index 00000000..eb080fb1 --- /dev/null +++ b/lua/lvim/core/autopairs.lua @@ -0,0 +1,81 @@ +local M = {} + +function M.config() + lvim.builtin.autopairs = { + active = true, + on_config_done = nil, + ---@usage auto insert after select function or method item + map_complete = true, + ---@usage -- modifies the function or method delimiter by filetypes + map_char = { + all = "(", + tex = "{", + }, + ---@usage check treesitter + check_ts = true, + ts_config = { + lua = { "string" }, + javascript = { "template_string" }, + java = false, + }, + } +end + +M.setup = function() + local autopairs = require "nvim-autopairs" + local Rule = require "nvim-autopairs.rule" + local cond = require "nvim-autopairs.conds" + + autopairs.setup { + check_ts = lvim.builtin.autopairs.check_ts, + ts_config = lvim.builtin.autopairs.ts_config, + } + + -- vim.g.completion_confirm_key = "" + + autopairs.add_rule(Rule("$$", "$$", "tex")) + autopairs.add_rules { + Rule("$", "$", { "tex", "latex" }) -- don't add a pair if the next character is % + :with_pair(cond.not_after_regex_check "%%") -- don't add a pair if the previous character is xxx + :with_pair(cond.not_before_regex_check("xxx", 3)) -- don't move right when repeat character + :with_move(cond.none()) -- don't delete if the next character is xx + :with_del(cond.not_after_regex_check "xx") -- disable add newline when press <cr> + :with_cr(cond.none()), + } + autopairs.add_rules { + Rule("$$", "$$", "tex"):with_pair(function(opts) + print(vim.inspect(opts)) + if opts.line == "aa $$" then + -- don't add pair on that line + return false + end + end), + } + + if package.loaded["cmp"] then + require("nvim-autopairs.completion.cmp").setup { + map_cr = false, + map_complete = lvim.builtin.autopairs.map_complete, + map_char = lvim.builtin.autopairs.map_char, + } + -- we map CR explicitly in cmp.lua but we still need to setup the autopairs CR keymap + vim.api.nvim_set_keymap("i", "<CR>", "v:lua.MPairs.autopairs_cr()", { expr = true, noremap = true }) + end + + require("nvim-treesitter.configs").setup { autopairs = { enable = true } } + + local ts_conds = require "nvim-autopairs.ts-conds" + + -- TODO: can these rules be safely added from "config.lua" ? + -- press % => %% is only inside comment or string + autopairs.add_rules { + Rule("%", "%", "lua"):with_pair(ts_conds.is_ts_node { "string", "comment" }), + Rule("$", "$", "lua"):with_pair(ts_conds.is_not_ts_node { "function" }), + } + + if lvim.builtin.autopairs.on_config_done then + lvim.builtin.autopairs.on_config_done(autopairs) + end +end + +return M diff --git a/lua/lvim/core/bufferline.lua b/lua/lvim/core/bufferline.lua new file mode 100644 index 00000000..ae6542d1 --- /dev/null +++ b/lua/lvim/core/bufferline.lua @@ -0,0 +1,25 @@ +local M = {} + +M.config = function() + lvim.builtin.bufferline = { + active = true, + on_config_done = nil, + keymap = { + normal_mode = { + ["<S-l>"] = ":BufferNext<CR>", + ["<S-h>"] = ":BufferPrevious<CR>", + }, + }, + } +end + +M.setup = function() + local keymap = require "lvim.keymappings" + keymap.append_to_defaults(lvim.builtin.bufferline.keymap) + + if lvim.builtin.bufferline.on_config_done then + lvim.builtin.bufferline.on_config_done() + end +end + +return M diff --git a/lua/lvim/core/builtins/init.lua b/lua/lvim/core/builtins/init.lua new file mode 100644 index 00000000..8f83072e --- /dev/null +++ b/lua/lvim/core/builtins/init.lua @@ -0,0 +1,28 @@ +local M = {} + +local builtins = { + "lvim.keymappings", + "lvim.core.which-key", + "lvim.core.gitsigns", + "lvim.core.cmp", + "lvim.core.dashboard", + "lvim.core.dap", + "lvim.core.terminal", + "lvim.core.telescope", + "lvim.core.treesitter", + "lvim.core.nvimtree", + "lvim.core.project", + "lvim.core.bufferline", + "lvim.core.autopairs", + "lvim.core.comment", + "lvim.core.lualine", +} + +function M.config(config) + for _, builtin_path in ipairs(builtins) do + local builtin = require(builtin_path) + builtin.config(config) + end +end + +return M diff --git a/lua/lvim/core/cmp.lua b/lua/lvim/core/cmp.lua new file mode 100644 index 00000000..ad06a360 --- /dev/null +++ b/lua/lvim/core/cmp.lua @@ -0,0 +1,265 @@ +local M = {} + +local check_backspace = function() + local col = vim.fn.col "." - 1 + return col == 0 or vim.fn.getline("."):sub(col, col):match "%s" +end + +local function T(str) + return vim.api.nvim_replace_termcodes(str, true, true, true) +end + +local is_emmet_active = function() + local clients = vim.lsp.buf_get_clients() + + for _, client in pairs(clients) do + if client.name == "emmet_ls" then + return true + end + end + return false +end + +M.config = function() + local status_cmp_ok, cmp = pcall(require, "cmp") + if not status_cmp_ok then + return + end + local status_luasnip_ok, luasnip = pcall(require, "luasnip") + if not status_luasnip_ok then + return + end + local win_get_cursor = vim.api.nvim_win_get_cursor + local get_current_buf = vim.api.nvim_get_current_buf + + local function inside_snippet() + -- for outdated versions of luasnip + if not luasnip.session.current_nodes then + return false + end + + local node = luasnip.session.current_nodes[get_current_buf()] + if not node then + return false + end + + local snip_begin_pos, snip_end_pos = node.parent.snippet.mark:pos_begin_end() + local pos = win_get_cursor(0) + pos[1] = pos[1] - 1 -- LuaSnip is 0-based not 1-based like nvim for rows + return pos[1] >= snip_begin_pos[1] and pos[1] <= snip_end_pos[1] + end + + ---sets the current buffer's luasnip to the one nearest the cursor + ---@return boolean true if a node is found, false otherwise + local function seek_luasnip_cursor_node() + -- for outdated versions of luasnip + if not luasnip.session.current_nodes then + return false + end + + local pos = win_get_cursor(0) + pos[1] = pos[1] - 1 + local node = luasnip.session.current_nodes[get_current_buf()] + if not node then + return false + end + + local snippet = node.parent.snippet + local exit_node = snippet.insert_nodes[0] + + -- exit early if we're past the exit node + if exit_node then + local exit_pos_end = exit_node.mark:pos_end() + if (pos[1] > exit_pos_end[1]) or (pos[1] == exit_pos_end[1] and pos[2] > exit_pos_end[2]) then + snippet:remove_from_jumplist() + luasnip.session.current_nodes[get_current_buf()] = nil + + return false + end + end + + node = snippet.inner_first:jump_into(1, true) + while node ~= nil and node.next ~= nil and node ~= snippet do + local n_next = node.next + local next_pos = n_next and n_next.mark:pos_begin() + local candidate = n_next ~= snippet and next_pos and (pos[1] < next_pos[1]) + or (pos[1] == next_pos[1] and pos[2] < next_pos[2]) + + -- Past unmarked exit node, exit early + if n_next == nil or n_next == snippet.next then + snippet:remove_from_jumplist() + luasnip.session.current_nodes[get_current_buf()] = nil + + return false + end + + if candidate then + luasnip.session.current_nodes[get_current_buf()] = node + return true + end + + local ok + ok, node = pcall(node.jump_from, node, 1, true) -- no_move until last stop + if not ok then + snippet:remove_from_jumplist() + luasnip.session.current_nodes[get_current_buf()] = nil + + return false + end + end + + -- No candidate, but have an exit node + if exit_node then + -- to jump to the exit node, seek to snippet + luasnip.session.current_nodes[get_current_buf()] = snippet + return true + end + + -- No exit node, exit from snippet + snippet:remove_from_jumplist() + luasnip.session.current_nodes[get_current_buf()] = nil + return false + end + + lvim.builtin.cmp = { + confirm_opts = { + behavior = cmp.ConfirmBehavior.Replace, + select = false, + }, + experimental = { + ghost_text = true, + native_menu = false, + }, + formatting = { + kind_icons = { + Class = " ", + Color = " ", + Constant = "ﲀ ", + Constructor = " ", + Enum = "練", + EnumMember = " ", + Event = " ", + Field = " ", + File = "", + Folder = " ", + Function = " ", + Interface = "ﰮ ", + Keyword = " ", + Method = " ", + Module = " ", + Operator = "", + Property = " ", + Reference = " ", + Snippet = " ", + Struct = " ", + Text = " ", + TypeParameter = " ", + Unit = "塞", + Value = " ", + Variable = " ", + }, + source_names = { + nvim_lsp = "(LSP)", + emoji = "(Emoji)", + path = "(Path)", + calc = "(Calc)", + cmp_tabnine = "(Tabnine)", + vsnip = "(Snippet)", + luasnip = "(Snippet)", + buffer = "(Buffer)", + }, + duplicates = { + buffer = 1, + path = 1, + nvim_lsp = 0, + luasnip = 1, + }, + duplicates_default = 0, + format = function(entry, vim_item) + vim_item.kind = lvim.builtin.cmp.formatting.kind_icons[vim_item.kind] + vim_item.menu = lvim.builtin.cmp.formatting.source_names[entry.source.name] + vim_item.dup = lvim.builtin.cmp.formatting.duplicates[entry.source.name] + or lvim.builtin.cmp.formatting.duplicates_default + return vim_item + end, + }, + snippet = { + expand = function(args) + require("luasnip").lsp_expand(args.body) + end, + }, + documentation = { + border = { "╭", "─", "╮", "│", "╯", "─", "╰", "│" }, + }, + sources = { + { name = "nvim_lsp" }, + { name = "path" }, + { name = "luasnip" }, + { name = "cmp_tabnine" }, + { name = "nvim_lua" }, + { name = "buffer" }, + { name = "calc" }, + { name = "emoji" }, + { name = "treesitter" }, + { name = "crates" }, + }, + mapping = { + ["<C-d>"] = cmp.mapping.scroll_docs(-4), + ["<C-f>"] = cmp.mapping.scroll_docs(4), + -- TODO: potentially fix emmet nonsense + ["<Tab>"] = cmp.mapping(function() + if cmp.visible() then + cmp.select_next_item() + elseif luasnip.expandable() then + luasnip.expand() + elseif inside_snippet() and seek_luasnip_cursor_node() and luasnip.jumpable() then + luasnip.jump(1) + elseif check_backspace() then + vim.fn.feedkeys(T "<Tab>", "n") + elseif is_emmet_active() then + return vim.fn["cmp#complete"]() + else + vim.fn.feedkeys(T "<Tab>", "n") + end + end, { + "i", + "s", + }), + ["<S-Tab>"] = cmp.mapping(function(fallback) + if cmp.visible() then + cmp.select_prev_item() + elseif inside_snippet() and luasnip.jumpable(-1) then + luasnip.jump(-1) + else + fallback() + end + end, { + "i", + "s", + }), + + ["<C-Space>"] = cmp.mapping.complete(), + ["<C-e>"] = cmp.mapping.close(), + ["<CR>"] = cmp.mapping(function(fallback) + if cmp.visible() and cmp.confirm(lvim.builtin.cmp.confirm_opts) then + return + end + + if inside_snippet() and seek_luasnip_cursor_node() and luasnip.jumpable() then + if not luasnip.jump(1) then + fallback() + end + else + fallback() + end + end), + }, + } +end + +M.setup = function() + require("luasnip/loaders/from_vscode").lazy_load() + require("cmp").setup(lvim.builtin.cmp) +end + +return M diff --git a/lua/lvim/core/commands.lua b/lua/lvim/core/commands.lua new file mode 100644 index 00000000..b750f12b --- /dev/null +++ b/lua/lvim/core/commands.lua @@ -0,0 +1,25 @@ +local M = {} + +M.defaults = { + [[ + function! QuickFixToggle() + if empty(filter(getwininfo(), 'v:val.quickfix')) + copen + else + cclose + endif + endfunction + ]], + -- :LvimInfo + [[ command! LvimInfo lua require('lvim.core.info').toggle_popup(vim.bo.filetype) ]], + [[ command! LvimCacheReset lua require('lvim.utils.hooks').reset_cache() ]], + [[ command! LvimUpdate lua require('lvim.bootstrap').update() ]], +} + +M.load = function(commands) + for _, command in ipairs(commands) do + vim.cmd(command) + end +end + +return M diff --git a/lua/lvim/core/comment.lua b/lua/lvim/core/comment.lua new file mode 100644 index 00000000..b98410ab --- /dev/null +++ b/lua/lvim/core/comment.lua @@ -0,0 +1,31 @@ +local M = {} + +function M.config() + lvim.builtin.comment = { + active = true, + on_config_done = nil, + -- Linters prefer comment and line to have a space in between markers + marker_padding = true, + -- should comment out empty or whitespace only lines + comment_empty = false, + -- Should key mappings be created + create_mappings = true, + -- Normal mode mapping left hand side + line_mapping = "gcc", + -- Visual/Operator mapping left hand side + operator_mapping = "gc", + -- Hook function to call before commenting takes place + hook = nil, + } +end + +function M.setup() + local nvim_comment = require "nvim_comment" + + nvim_comment.setup(lvim.builtin.comment) + if lvim.builtin.comment.on_config_done then + lvim.builtin.comment.on_config_done(nvim_comment) + end +end + +return M diff --git a/lua/lvim/core/dap.lua b/lua/lvim/core/dap.lua new file mode 100644 index 00000000..d9b59641 --- /dev/null +++ b/lua/lvim/core/dap.lua @@ -0,0 +1,76 @@ +local M = {} + +M.config = function() + lvim.builtin.dap = { + active = false, + on_config_done = nil, + breakpoint = { + text = "", + texthl = "LspDiagnosticsSignError", + linehl = "", + numhl = "", + }, + breakpoint_rejected = { + text = "", + texthl = "LspDiagnosticsSignHint", + linehl = "", + numhl = "", + }, + stopped = { + text = "", + texthl = "LspDiagnosticsSignInformation", + linehl = "DiagnosticUnderlineInfo", + numhl = "LspDiagnosticsSignInformation", + }, + } +end + +M.setup = function() + local dap = require "dap" + + vim.fn.sign_define("DapBreakpoint", lvim.builtin.dap.breakpoint) + vim.fn.sign_define("DapBreakpointRejected", lvim.builtin.dap.breakpoint_rejected) + vim.fn.sign_define("DapStopped", lvim.builtin.dap.stopped) + + dap.defaults.fallback.terminal_win_cmd = "50vsplit new" + + lvim.builtin.which_key.mappings["d"] = { + name = "Debug", + t = { "<cmd>lua require'dap'.toggle_breakpoint()<cr>", "Toggle Breakpoint" }, + b = { "<cmd>lua require'dap'.step_back()<cr>", "Step Back" }, + c = { "<cmd>lua require'dap'.continue()<cr>", "Continue" }, + C = { "<cmd>lua require'dap'.run_to_cursor()<cr>", "Run To Cursor" }, + d = { "<cmd>lua require'dap'.disconnect()<cr>", "Disconnect" }, + g = { "<cmd>lua require'dap'.session()<cr>", "Get Session" }, + i = { "<cmd>lua require'dap'.step_into()<cr>", "Step Into" }, + o = { "<cmd>lua require'dap'.step_over()<cr>", "Step Over" }, + u = { "<cmd>lua require'dap'.step_out()<cr>", "Step Out" }, + p = { "<cmd>lua require'dap'.pause.toggle()<cr>", "Pause" }, + r = { "<cmd>lua require'dap'.repl.toggle()<cr>", "Toggle Repl" }, + s = { "<cmd>lua require'dap'.continue()<cr>", "Start" }, + q = { "<cmd>lua require'dap'.close()<cr>", "Quit" }, + } + + if lvim.builtin.dap.on_config_done then + lvim.builtin.dap.on_config_done(dap) + end +end + +-- TODO put this up there ^^^ call in ftplugin + +-- M.dap = function() +-- if lvim.plugin.dap.active then +-- local dap_install = require "dap-install" +-- dap_install.config("python_dbg", {}) +-- end +-- end +-- +-- M.dap = function() +-- -- gem install readapt ruby-debug-ide +-- if lvim.plugin.dap.active then +-- local dap_install = require "dap-install" +-- dap_install.config("ruby_vsc_dbg", {}) +-- end +-- end + +return M diff --git a/lua/lvim/core/dashboard.lua b/lua/lvim/core/dashboard.lua new file mode 100644 index 00000000..38d9d226 --- /dev/null +++ b/lua/lvim/core/dashboard.lua @@ -0,0 +1,112 @@ +local M = {} +local utils = require "lvim.utils" + +M.config = function(config) + lvim.builtin.dashboard = { + active = false, + on_config_done = nil, + search_handler = "telescope", + disable_at_vim_enter = 0, + session_directory = utils.join_paths(get_cache_dir(), "sessions"), + custom_header = { + "⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣀⣀⣀⣀⣀⣀⣀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", + "⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣤⣶⣾⠿⠿⠟⠛⠛⠛⠛⠿⠿⣿⣷⣤⣄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", + " ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣠⣾⡿⠋⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠙⠿⣷⣤⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", + "⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣤⡿⠛⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠛⢿⣦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", + "⠀⠀⠀⠀⠀⠀⠀⠀⠀⡠⠒⠂⠉⠉⠉⠉⢩⣿⡿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠹⣷⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", + "⠀⠀⠀⠀⠀⠀⠀⠀⠸⡀⠀⠀⠀⠀⠀⢰⣿⠋⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⣿⣧⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", + "⠀⠀⠀⠀⠀⠀⠀⠀⠀⠑⠠⡀⠀⠀⢀⣾⠋⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⣿⡆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", + "⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠢⢀⣸⡟⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢹⣇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", + "⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⡧⢄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", + "⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⡇⠀⠈⠁⠒⠤⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", + "⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣇⠀⠀⠀⠀⠀⠀⠉⠢⠤⠀⢀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣸⡟⠈⠑⠄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", + "⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢿⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠑⠒⠤⣀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⣿⡇⠀⠀⢀⣣⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", + "⠀⣿⡟⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠸⣷⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠀⠀⠒⠢⠤⠄⣀⣀⠀⠀⠀⢠⣿⡟⠀⠀⠀⣺⣿⡿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", + "⠀⣿⠇⠀⠀⠀⠀⠀⣤⡄⠀⠀⢠⣤⡄⠀⢨⣭⣠⣤⣤⣤⡀⠀⠀⢀⣤⣤⣤⣤⡄⠀⠀⠀⣤⣄⣤⣤⣤⠀⠀⣿⣯⠉⠉⣿⡟⠀⠈⢩⣭⣤⣤⠀⠀⠀⠀⣠⣤⣤⣤⣄⣤⣤", + "⢠⣿⠀⠀⠀⠀⠀⠀⣿⠃⠀⠀⣸⣿⠁⠀⣿⣿⠉⠀⠈⣿⡇⠀⠀⠛⠋⠀⠀⢹⣿⠀⠀⠀⣿⠏⠀⠸⠿⠃⠀⣿⣿⠀⣰⡟⠀⠀⠀⠀⠀⢸⣿⠀⠀⠀⠀⣿⡟⢸⣿⡇⢀⣿", + "⣸⡇⠀⠀⠀⠀⠀⢸⣿⠀⠀⠀⣿⡟⠀⢠⣿⡇⠀⠀⢰⣿⡇⠀⣰⣾⠟⠛⠛⣻⡇⠀⠀⢸⡿⠀⠀⠀⠀⠀⠀⢻⣿⢰⣿⠀⠀⠀⠀⠀⠀⣾⡇⠀⠀⠀⢸⣿⠇⢸⣿⠀⢸⡏", + "⣿⣧⣤⣤⣤⡄⠀⠘⣿⣤⣤⡤⣿⠇⠀⢸⣿⠁⠀⠀⣼⣿⠀⠀⢿⣿⣤⣤⠔⣿⠃⠀⠀⣾⡇⠀⠀⠀⠀⠀⠀⢸⣿⣿⠋⠀⠀⠀⢠⣤⣤⣿⣥⣤⡄⠀⣼⣿⠀⣸⡏⠀⣿⠃", + "⠉⠉⠉⠉⠉⠁⠀⠀⠈⠉⠉⠀⠉⠀⠀⠈⠉⠀⠀⠀⠉⠉⠀⠀⠀⠉⠉⠁⠈⠉⠀⠀⠀⠉⠀⠀⠀⠀⠀⠀⠀⠈⠉⠉⠀⠀⠀⠀⠈⠉⠉⠉⠉⠉⠁⠀⠉⠁⠀⠉⠁⠀⠉⠀", + }, + + custom_section = { + a = { + description = { " Find File " }, + command = "Telescope find_files", + }, + b = { + description = { " Recent Projects " }, + command = "Telescope projects", + }, + c = { + description = { " Recently Used Files" }, + command = "Telescope oldfiles", + }, + d = { + description = { " Find Word " }, + command = "Telescope live_grep", + }, + e = { + description = { " Configuration " }, + command = ":e " .. config.user_config_file, + }, + }, + + footer = { "lunarvim.org" }, + } +end + +M.setup = function() + vim.g.dashboard_disable_at_vimenter = lvim.builtin.dashboard.disable_at_vim_enter + + vim.g.dashboard_custom_header = lvim.builtin.dashboard.custom_header + + vim.g.dashboard_default_executive = lvim.builtin.dashboard.search_handler + + vim.g.dashboard_custom_section = lvim.builtin.dashboard.custom_section + + lvim.builtin.which_key.mappings[";"] = { "<cmd>Dashboard<CR>", "Dashboard" } + + vim.g.dashboard_session_directory = lvim.builtin.dashboard.session_directory + + local lvim_site = "lunarvim.org" + local lvim_version = get_version "short" + local num_plugins_loaded = #vim.fn.globpath(get_runtime_dir() .. "/site/pack/packer/start", "*", 0, 1) + + local footer = { + "LunarVim loaded " .. num_plugins_loaded .. " plugins ", + "", + lvim_site, + } + + if lvim_version then + table.insert(footer, 2, "") + table.insert(footer, 3, "v" .. lvim_version) + end + + local text = require "lvim.interface.text" + vim.g.dashboard_custom_footer = text.align_center({ width = 0 }, footer, 0.49) -- Use 0.49 as counts for 2 characters + + require("lvim.core.autocmds").define_augroups { + _dashboard = { + -- seems to be nobuflisted that makes my stuff disappear will do more testing + { + "FileType", + "dashboard", + "setlocal nocursorline noswapfile synmaxcol& signcolumn=no norelativenumber nocursorcolumn nospell nolist nonumber bufhidden=wipe colorcolumn= foldcolumn=0 matchpairs= ", + }, + { + "FileType", + "dashboard", + "set showtabline=0 | autocmd BufLeave <buffer> set showtabline=" .. vim.opt.showtabline._value, + }, + { "FileType", "dashboard", "nnoremap <silent> <buffer> q :q<CR>" }, + }, + } + + if lvim.builtin.dashboard.on_config_done then + lvim.builtin.dashboard.on_config_done() + end +end + +return M diff --git a/lua/lvim/core/gitsigns.lua b/lua/lvim/core/gitsigns.lua new file mode 100644 index 00000000..cc6387dc --- /dev/null +++ b/lua/lvim/core/gitsigns.lua @@ -0,0 +1,64 @@ +local M = {} + +M.config = function() + lvim.builtin.gitsigns = { + active = true, + on_config_done = nil, + opts = { + 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 = "GitSignsChange", + text = "▎", + numhl = "GitSignsChangeNr", + linehl = "GitSignsChangeLn", + }, + }, + numhl = false, + linehl = false, + keymaps = { + -- Default keymap options + noremap = true, + buffer = true, + }, + watch_gitdir = { interval = 1000 }, + sign_priority = 6, + update_debounce = 200, + status_formatter = nil, -- Use default + }, + } +end + +M.setup = function() + local gitsigns = require "gitsigns" + + gitsigns.setup(lvim.builtin.gitsigns.opts) + if lvim.builtin.gitsigns.on_config_done then + lvim.builtin.gitsigns.on_config_done(gitsigns) + end +end + +return M diff --git a/lua/lvim/core/info.lua b/lua/lvim/core/info.lua new file mode 100644 index 00000000..7fdb665b --- /dev/null +++ b/lua/lvim/core/info.lua @@ -0,0 +1,174 @@ +local M = { + banner = { + "", + [[ __ _ ___ ]], + [[ / / __ ______ ____ _____| | / (_)___ ___ ]], + [[ / / / / / / __ \/ __ `/ ___/ | / / / __ `__ \]], + [[ / /___/ /_/ / / / / /_/ / / | |/ / / / / / / /]], + [[/_____/\__,_/_/ /_/\__,_/_/ |___/_/_/ /_/ /_/ ]], + }, +} + +local fmt = string.format +local text = require "lvim.interface.text" +local lsp_utils = require "lvim.lsp.utils" +local user_config_file = require("lvim.config"):get_user_config_path() + +local function str_list(list) + return fmt("[ %s ]", table.concat(list, ", ")) +end + +local function get_formatter_suggestion_msg(ft) + local null_formatters = require "lvim.lsp.null-ls.formatters" + local supported_formatters = null_formatters.list_available(ft) + local section = { + " HINT ", + "", + fmt("* List of supported formatters: %s", str_list(supported_formatters)), + } + + if not vim.tbl_isempty(supported_formatters) then + vim.list_extend(section, { + "* Configured formatter needs to be installed and executable.", + fmt("* Enable installed formatter(s) with following config in %s", user_config_file), + "", + fmt(" lvim.lang.%s.formatters = { { exe = '%s' } }", ft, table.concat(supported_formatters, "│")), + }) + end + + return section +end + +local function get_linter_suggestion_msg(ft) + local null_linters = require "lvim.lsp.null-ls.linters" + local supported_linters = null_linters.list_available(ft) + local section = { + " HINT ", + "", + fmt("* List of supported linters: %s", str_list(supported_linters)), + } + + if not vim.tbl_isempty(supported_linters) then + vim.list_extend(section, { + "* Configured linter needs to be installed and executable.", + fmt("* Enable installed linter(s) with following config in %s", user_config_file), + "", + fmt(" lvim.lang.%s.linters = { { exe = '%s' } }", ft, table.concat(supported_linters, "│")), + }) + end + + return section +end + +local function tbl_set_highlight(terms, highlight_group) + for _, v in pairs(terms) do + vim.cmd('let m=matchadd("' .. highlight_group .. '", "' .. v .. "[ ,│']\")") + end +end + +local function make_client_info(client) + local client_enabled_caps = lsp_utils.get_client_capabilities(client.id) + local name = client.name + local id = client.id + local document_formatting = client.resolved_capabilities.document_formatting + local client_info = { + fmt("* Name: %s", name), + fmt("* Id: %s", tostring(id)), + fmt("* Supports formatting: %s", tostring(document_formatting)), + } + if not vim.tbl_isempty(client_enabled_caps) then + local caps_text = "* Capabilities list: " + local caps_text_len = caps_text:len() + local enabled_caps = text.format_table(client_enabled_caps, 3, " | ") + enabled_caps = text.shift_right(enabled_caps, caps_text_len) + enabled_caps[1] = fmt("%s%s", caps_text, enabled_caps[1]:sub(caps_text_len + 1)) + vim.list_extend(client_info, enabled_caps) + end + + return client_info +end + +function M.toggle_popup(ft) + local clients = lsp_utils.get_active_clients_by_ft(ft) + local client_names = {} + + local header = { + fmt("Detected filetype: %s", ft), + fmt("Treesitter active: %s", tostring(next(vim.treesitter.highlighter.active) ~= nil)), + } + + local lsp_info = { + "Language Server Protocol (LSP) info", + fmt "* Associated server(s):", + } + + for _, client in pairs(clients) do + vim.list_extend(lsp_info, make_client_info(client)) + table.insert(client_names, client.name) + end + + local null_formatters = require "lvim.lsp.null-ls.formatters" + local null_linters = require "lvim.lsp.null-ls.linters" + local registered_formatters = null_formatters.list_supported_names(ft) + local registered_linters = null_linters.list_supported_names(ft) + local registered_providers = {} + vim.list_extend(registered_providers, registered_formatters) + vim.list_extend(registered_providers, registered_linters) + local registered_count = vim.tbl_count(registered_providers) + local null_ls_info = { + "Formatters and linters", + fmt( + "* Configured providers: %s%s", + table.concat(registered_providers, " , "), + registered_count > 0 and " " or "" + ), + } + + local content_provider = function(popup) + local content = {} + + for _, section in ipairs { + M.banner, + { "" }, + { "" }, + header, + { "" }, + lsp_info, + { "" }, + null_ls_info, + { "" }, + { "" }, + get_formatter_suggestion_msg(ft), + { "" }, + { "" }, + get_linter_suggestion_msg(ft), + } do + vim.list_extend(content, section) + end + + return text.align_left(popup, content, 0.5) + end + + local function set_syntax_hl() + vim.cmd [[highlight LvimInfoIdentifier gui=bold]] + vim.cmd [[highlight link LvimInfoHeader Type]] + vim.cmd [[let m=matchadd("LvimInfoHeader", "Language Server Protocol (LSP) info")]] + vim.cmd [[let m=matchadd("LvimInfoHeader", "Formatters and linters")]] + vim.cmd('let m=matchadd("LvimInfoIdentifier", " ' .. ft .. '$")') + vim.cmd 'let m=matchadd("string", "true")' + vim.cmd 'let m=matchadd("error", "false")' + tbl_set_highlight(registered_providers, "LvimInfoIdentifier") + -- tbl_set_highlight(require("lvim.lsp.null-ls.formatters").list_available(ft), "LvimInfoIdentifier") + -- tbl_set_highlight(require("lvim.lsp.null-ls.linters").list_available(ft), "LvimInfoIdentifier") + end + + local Popup = require("lvim.interface.popup"):new { + win_opts = { number = false }, + buf_opts = { modifiable = false, filetype = "lspinfo" }, + } + Popup:display(content_provider) + set_syntax_hl() + + return Popup +end +return M diff --git a/lua/lvim/core/log.lua b/lua/lvim/core/log.lua new file mode 100644 index 00000000..fca1fcb4 --- /dev/null +++ b/lua/lvim/core/log.lua @@ -0,0 +1,60 @@ +local Log = {} + +--- Adds a log entry using Plenary.log +---@param msg any +---@param level string [same as vim.log.log_levels] +function Log:add_entry(msg, level) + assert(type(level) == "string") + if self.__handle then + -- plenary uses lower-case log levels + self.__handle[level:lower()](msg) + return + end + local status_ok, plenary = pcall(require, "plenary") + if status_ok then + local default_opts = { plugin = "lunarvim", level = lvim.log.level } + local handle = plenary.log.new(default_opts) + handle[level:lower()](msg) + self.__handle = handle + end + -- don't do anything if plenary is not available +end + +---Retrieves the path of the logfile +---@return string path of the logfile +function Log:get_path() + return string.format("%s/%s.log", vim.fn.stdpath "cache", "lunarvim") +end + +---Add a log entry at TRACE level +---@param msg any +function Log:trace(msg) + self:add_entry(msg, "TRACE") +end + +---Add a log entry at DEBUG level +---@param msg any +function Log:debug(msg) + self:add_entry(msg, "DEBUG") +end + +---Add a log entry at INFO level +---@param msg any +function Log:info(msg) + self:add_entry(msg, "INFO") +end + +---Add a log entry at WARN level +---@param msg any +function Log:warn(msg) + self:add_entry(msg, "WARN") +end + +---Add a log entry at ERROR level +---@param msg any +function Log:error(msg) + self:add_entry(msg, "ERROR") +end + +setmetatable({}, Log) +return Log diff --git a/lua/lvim/core/lualine/colors.lua b/lua/lvim/core/lualine/colors.lua new file mode 100644 index 00000000..4984cd1f --- /dev/null +++ b/lua/lvim/core/lualine/colors.lua @@ -0,0 +1,16 @@ +local colors = { + bg = "#202328", + fg = "#bbc2cf", + yellow = "#ECBE7B", + cyan = "#008080", + darkblue = "#081633", + green = "#98be65", + orange = "#FF8800", + violet = "#a9a1e1", + magenta = "#c678dd", + purple = "#c678dd", + blue = "#51afef", + red = "#ec5f67", +} + +return colors diff --git a/lua/lvim/core/lualine/components.lua b/lua/lvim/core/lualine/components.lua new file mode 100644 index 00000000..5c0fb84b --- /dev/null +++ b/lua/lvim/core/lualine/components.lua @@ -0,0 +1,154 @@ +local conditions = require "lvim.core.lualine.conditions" +local colors = require "lvim.core.lualine.colors" + +local function diff_source() + local gitsigns = vim.b.gitsigns_status_dict + if gitsigns then + return { + added = gitsigns.added, + modified = gitsigns.changed, + removed = gitsigns.removed, + } + end +end + +return { + mode = { + function() + return " " + end, + padding = { left = 0, right = 0 }, + color = {}, + cond = nil, + }, + branch = { + "b:gitsigns_head", + icon = " ", + color = { gui = "bold" }, + cond = conditions.hide_in_width, + }, + filename = { + "filename", + color = {}, + cond = nil, + }, + diff = { + "diff", + source = diff_source, + symbols = { added = " ", modified = "柳", removed = " " }, + diff_color = { + added = { fg = colors.green }, + modified = { fg = colors.yellow }, + removed = { fg = colors.red }, + }, + color = {}, + cond = nil, + }, + python_env = { + function() + local utils = require "lvim.core.lualine.utils" + if vim.bo.filetype == "python" then + local venv = os.getenv "CONDA_DEFAULT_ENV" + if venv then + return string.format(" (%s)", utils.env_cleanup(venv)) + end + venv = os.getenv "VIRTUAL_ENV" + if venv then + return string.format(" (%s)", utils.env_cleanup(venv)) + end + return "" + end + return "" + end, + color = { fg = colors.green }, + cond = conditions.hide_in_width, + }, + diagnostics = { + "diagnostics", + sources = { "nvim_lsp" }, + symbols = { error = " ", warn = " ", info = " ", hint = " " }, + color = {}, + cond = conditions.hide_in_width, + }, + treesitter = { + function() + local b = vim.api.nvim_get_current_buf() + if next(vim.treesitter.highlighter.active[b]) then + return " " + end + return "" + end, + color = { fg = colors.green }, + cond = conditions.hide_in_width, + }, + lsp = { + function(msg) + msg = msg or "LS Inactive" + local buf_clients = vim.lsp.buf_get_clients() + if next(buf_clients) == nil then + -- TODO: clean up this if statement + if type(msg) == "boolean" or #msg == 0 then + return "LS Inactive" + end + return msg + end + local buf_ft = vim.bo.filetype + 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 + + -- add formatter + local formatters = require "lvim.lsp.null-ls.formatters" + local supported_formatters = formatters.list_supported_names(buf_ft) + vim.list_extend(buf_client_names, supported_formatters) + + -- add linter + local linters = require "lvim.lsp.null-ls.linters" + local supported_linters = linters.list_supported_names(buf_ft) + vim.list_extend(buf_client_names, supported_linters) + + return table.concat(buf_client_names, ", ") + end, + icon = " ", + color = { gui = "bold" }, + cond = conditions.hide_in_width, + }, + location = { "location", cond = conditions.hide_in_width, color = {} }, + progress = { "progress", cond = conditions.hide_in_width, color = {} }, + spaces = { + function() + local label = "Spaces: " + if not vim.api.nvim_buf_get_option(0, "expandtab") then + label = "Tab size: " + end + return label .. vim.api.nvim_buf_get_option(0, "shiftwidth") .. " " + end, + cond = conditions.hide_in_width, + color = {}, + }, + encoding = { + "o:encoding", + fmt = string.upper, + color = {}, + cond = conditions.hide_in_width, + }, + filetype = { "filetype", cond = conditions.hide_in_width, color = {} }, + scrollbar = { + function() + local current_line = vim.fn.line "." + local total_lines = vim.fn.line "$" + local chars = { "__", "▁▁", "▂▂", "▃▃", "▄▄", "▅▅", "▆▆", "▇▇", "██" } + local line_ratio = current_line / total_lines + local index = math.ceil(line_ratio * #chars) + return chars[index] + end, + padding = { left = 0, right = 0 }, + color = { fg = colors.yellow, bg = colors.bg }, + cond = nil, + }, +} diff --git a/lua/lvim/core/lualine/conditions.lua b/lua/lvim/core/lualine/conditions.lua new file mode 100644 index 00000000..3ee4fbb8 --- /dev/null +++ b/lua/lvim/core/lualine/conditions.lua @@ -0,0 +1,17 @@ +local window_width_limit = 80 + +local conditions = { + buffer_not_empty = function() + return vim.fn.empty(vim.fn.expand "%:t") ~= 1 + end, + hide_in_width = function() + return vim.fn.winwidth(0) > window_width_limit + end, + -- check_git_workspace = function() + -- local filepath = vim.fn.expand "%:p:h" + -- local gitdir = vim.fn.finddir(".git", filepath .. ";") + -- return gitdir and #gitdir > 0 and #gitdir < #filepath + -- end, +} + +return conditions diff --git a/lua/lvim/core/lualine/init.lua b/lua/lvim/core/lualine/init.lua new file mode 100644 index 00000000..c5d024c2 --- /dev/null +++ b/lua/lvim/core/lualine/init.lua @@ -0,0 +1,47 @@ +local M = {} +M.config = function() + lvim.builtin.lualine = { + active = true, + style = "lvim", + options = { + icons_enabled = nil, + component_separators = nil, + section_separators = nil, + theme = nil, + disabled_filetypes = nil, + }, + sections = { + lualine_a = nil, + lualine_b = nil, + lualine_c = nil, + lualine_x = nil, + lualine_y = nil, + lualine_z = nil, + }, + inactive_sections = { + lualine_a = nil, + lualine_b = nil, + lualine_c = nil, + lualine_x = nil, + lualine_y = nil, + lualine_z = nil, + }, + tabline = nil, + extensions = nil, + on_config_done = nil, + } +end + +M.setup = function() + require("lvim.core.lualine.styles").update() + require("lvim.core.lualine.utils").validate_theme() + + local lualine = require "lualine" + lualine.setup(lvim.builtin.lualine) + + if lvim.builtin.lualine.on_config_done then + lvim.builtin.lualine.on_config_done(lualine) + end +end + +return M diff --git a/lua/lvim/core/lualine/styles.lua b/lua/lvim/core/lualine/styles.lua new file mode 100644 index 00000000..0843aead --- /dev/null +++ b/lua/lvim/core/lualine/styles.lua @@ -0,0 +1,137 @@ +local M = {} +local components = require "lvim.core.lualine.components" + +local styles = { + lvim = nil, + default = nil, + none = nil, +} + +styles.none = { + style = "none", + options = { + icons_enabled = true, + component_separators = { left = "", right = "" }, + section_separators = { left = "", right = "" }, + disabled_filetypes = {}, + }, + sections = { + lualine_a = {}, + lualine_b = {}, + lualine_c = {}, + lualine_x = {}, + lualine_y = {}, + lualine_z = {}, + }, + inactive_sections = { + lualine_a = {}, + lualine_b = {}, + lualine_c = {}, + lualine_x = {}, + lualine_y = {}, + lualine_z = {}, + }, + tabline = {}, + extensions = {}, +} + +styles.default = { + style = "default", + options = { + icons_enabled = true, + component_separators = { left = "", right = "" }, + section_separators = { left = "", right = "" }, + disabled_filetypes = {}, + }, + sections = { + lualine_a = { "mode" }, + lualine_b = { "branch" }, + lualine_c = { "filename" }, + lualine_x = { "encoding", "fileformat", "filetype" }, + lualine_y = { "progress" }, + lualine_z = { "location" }, + }, + inactive_sections = { + lualine_a = {}, + lualine_b = {}, + lualine_c = { "filename" }, + lualine_x = { "location" }, + lualine_y = {}, + lualine_z = {}, + }, + tabline = {}, + extensions = {}, +} + +styles.lvim = { + style = "lvim", + options = { + icons_enabled = true, + component_separators = { left = "", right = "" }, + section_separators = { left = "", right = "" }, + disabled_filetypes = { "dashboard", "NvimTree", "Outline" }, + }, + sections = { + lualine_a = { + components.mode, + }, + lualine_b = { + components.branch, + components.filename, + }, + lualine_c = { + components.diff, + components.python_env, + }, + lualine_x = { + components.diagnostics, + components.treesitter, + components.lsp, + components.filetype, + }, + lualine_y = {}, + lualine_z = { + components.scrollbar, + }, + }, + inactive_sections = { + lualine_a = { + "filename", + }, + lualine_b = {}, + lualine_c = {}, + lualine_x = {}, + lualine_y = {}, + lualine_z = {}, + }, + tabline = {}, + extensions = { "nvim-tree" }, +} + +function M.get_style(style) + local style_keys = vim.tbl_keys(styles) + if not vim.tbl_contains(style_keys, style) then + local Log = require "lvim.core.log" + Log:error( + "Invalid lualine style", + string.format('"%s"', style), + "options are: ", + string.format('"%s"', table.concat(style_keys, '", "')) + ) + Log:debug '"lvim" style is applied.' + style = "lvim" + end + + return vim.deepcopy(styles[style]) +end + +function M.update() + local style = M.get_style(lvim.builtin.lualine.style) + if lvim.builtin.lualine.options.theme == nil then + lvim.builtin.lualine.options.theme = lvim.colorscheme + end + + lvim.builtin.lualine = vim.tbl_deep_extend("keep", lvim.builtin.lualine, style) +end + +return M diff --git a/lua/lvim/core/lualine/utils.lua b/lua/lvim/core/lualine/utils.lua new file mode 100644 index 00000000..cf80a99e --- /dev/null +++ b/lua/lvim/core/lualine/utils.lua @@ -0,0 +1,27 @@ +local M = {} + +function M.validate_theme() + local theme = lvim.builtin.lualine.options.theme + if type(theme) == "table" then + return + end + + local lualine_loader = require "lualine.utils.loader" + local ok = pcall(lualine_loader.load_theme, theme) + if not ok then + lvim.builtin.lualine.options.theme = "auto" + end +end + +function M.env_cleanup(venv) + if string.find(venv, "/") then + local final_venv = venv + for w in venv:gmatch "([^/]+)" do + final_venv = w + end + venv = final_venv + end + return venv +end + +return M diff --git a/lua/lvim/core/nvimtree.lua b/lua/lvim/core/nvimtree.lua new file mode 100644 index 00000000..d9e6fb5d --- /dev/null +++ b/lua/lvim/core/nvimtree.lua @@ -0,0 +1,141 @@ +local M = {} +local Log = require "lvim.core.log" + +function M.config() + lvim.builtin.nvimtree = { + active = true, + on_config_done = nil, + setup = { + open_on_setup = false, + auto_close = true, + open_on_tab = false, + update_focused_file = { + enable = true, + }, + diagnostics = { + enable = true, + icons = { + hint = "", + info = "", + warning = "", + error = "", + }, + }, + view = { + width = 30, + side = "left", + auto_resize = false, + mappings = { + custom_only = false, + }, + }, + }, + show_icons = { + git = 1, + folders = 1, + files = 1, + folder_arrows = 1, + tree_width = 30, + }, + ignore = { ".git", "node_modules", ".cache" }, + quit_on_open = 0, + hide_dotfiles = 1, + git_hl = 1, + root_folder_modifier = ":t", + allow_resize = 1, + auto_ignore_ft = { "startify", "dashboard" }, + icons = { + default = "", + symlink = "", + git = { + unstaged = "", + staged = "S", + unmerged = "", + renamed = "➜", + deleted = "", + untracked = "U", + ignored = "◌", + }, + folder = { + default = "", + open = "", + empty = "", + empty_open = "", + symlink = "", + }, + }, + } +end + +function M.setup() + local status_ok, nvim_tree_config = pcall(require, "nvim-tree.config") + if not status_ok then + Log:error "Failed to load nvim-tree.config" + return + end + local g = vim.g + + for opt, val in pairs(lvim.builtin.nvimtree) do + g["nvim_tree_" .. opt] = val + end + + -- Implicitly update nvim-tree when project module is active + if lvim.builtin.project.active then + lvim.builtin.nvimtree.respect_buf_cwd = 1 + lvim.builtin.nvimtree.setup.update_cwd = true + lvim.builtin.nvimtree.setup.disable_netrw = false + lvim.builtin.nvimtree.setup.hijack_netrw = false + vim.g.netrw_banner = false + end + + local tree_cb = nvim_tree_config.nvim_tree_callback + + if not lvim.builtin.nvimtree.setup.view.mappings.list then + lvim.builtin.nvimtree.setup.view.mappings.list = { + { key = { "l", "<CR>", "o" }, cb = tree_cb "edit" }, + { key = "h", cb = tree_cb "close_node" }, + { key = "v", cb = tree_cb "vsplit" }, + } + end + + lvim.builtin.which_key.mappings["e"] = { "<cmd>NvimTreeToggle<CR>", "Explorer" } + + local tree_view = require "nvim-tree.view" + + -- Add nvim_tree open callback + local open = tree_view.open + tree_view.open = function() + M.on_open() + open() + end + + vim.cmd "au WinClosed * lua require('lvim.core.nvimtree').on_close()" + + if lvim.builtin.nvimtree.on_config_done then + lvim.builtin.nvimtree.on_config_done(nvim_tree_config) + end + require("nvim-tree").setup(lvim.builtin.nvimtree.setup) +end + +function M.on_open() + if package.loaded["bufferline.state"] and lvim.builtin.nvimtree.setup.view.side == "left" then + require("bufferline.state").set_offset(lvim.builtin.nvimtree.setup.view.width + 1, "") + end +end + +function M.on_close() + local buf = tonumber(vim.fn.expand "<abuf>") + local ft = vim.api.nvim_buf_get_option(buf, "filetype") + if ft == "NvimTree" and package.loaded["bufferline.state"] then + require("bufferline.state").set_offset(0) + end +end + +function M.change_tree_dir(dir) + local lib_status_ok, lib = pcall(require, "nvim-tree.lib") + if lib_status_ok then + lib.change_dir(dir) + end +end + +return M diff --git a/lua/lvim/core/project.lua b/lua/lvim/core/project.lua new file mode 100644 index 00000000..e7527440 --- /dev/null +++ b/lua/lvim/core/project.lua @@ -0,0 +1,51 @@ +local M = {} + +function M.config() + lvim.builtin.project = { + ---@usage set to false to disable project.nvim. + --- This is on by default since it's currently the expected behavior. + active = true, + + on_config_done = nil, + + ---@usage set to true to disable setting the current-woriking directory + --- Manual mode doesn't automatically change your root directory, so you have + --- the option to manually do so using `:ProjectRoot` command. + manual_mode = false, + + ---@usage Methods of detecting the root directory + --- Allowed values: **"lsp"** uses the native neovim lsp + --- **"pattern"** uses vim-rooter like glob pattern matching. Here + --- order matters: if one is not detected, the other is used as fallback. You + --- can also delete or rearangne the detection methods. + detection_methods = { "lsp", "pattern" }, + + ---@usage patterns used to detect root dir, when **"pattern"** is in detection_methods + patterns = { ".git", "_darcs", ".hg", ".bzr", ".svn", "Makefile", "package.json" }, + + ---@ Show hidden files in telescope when searching for files in a project + show_hidden = false, + + ---@usage When set to false, you will get a message when project.nvim changes your directory. + -- When set to false, you will get a message when project.nvim changes your directory. + silent_chdir = true, + + ---@usage list of lsp client names to ignore when using **lsp** detection. eg: { "efm", ... } + ignore_lsp = {}, + + ---@type string + ---@usage path to store the project history for use in telescope + datapath = get_cache_dir(), + } +end + +function M.setup() + local project = require "project_nvim" + + project.setup(lvim.builtin.project) + if lvim.builtin.project.on_config_done then + lvim.builtin.project.on_config_done(project) + end +end + +return M diff --git a/lua/lvim/core/telescope.lua b/lua/lvim/core/telescope.lua new file mode 100644 index 00000000..35f6b4a2 --- /dev/null +++ b/lua/lvim/core/telescope.lua @@ -0,0 +1,193 @@ +local M = {} + +function M.config() + -- Define this minimal config so that it's available if telescope is not yet available. + lvim.builtin.telescope = { + ---@usage disable telescope completely [not recommeded] + active = true, + on_config_done = nil, + } + + local status_ok, actions = pcall(require, "telescope.actions") + if not status_ok then + return + end + + lvim.builtin.telescope = vim.tbl_extend("force", lvim.builtin.telescope, { + defaults = { + prompt_prefix = " ", + selection_caret = " ", + entry_prefix = " ", + initial_mode = "insert", + selection_strategy = "reset", + sorting_strategy = "descending", + layout_strategy = "horizontal", + layout_config = { + width = 0.75, + preview_cutoff = 120, + horizontal = { mirror = false }, + vertical = { mirror = false }, + }, + file_sorter = require("telescope.sorters").get_fzy_sorter, + file_ignore_patterns = {}, + generic_sorter = require("telescope.sorters").get_generic_fuzzy_sorter, + path_display = { shorten = 5 }, + winblend = 0, + border = {}, + borderchars = { "─", "│", "─", "│", "╭", "╮", "╯", "╰" }, + color_devicons = true, + use_less = true, + set_env = { ["COLORTERM"] = "truecolor" }, -- default = nil, + file_previewer = require("telescope.previewers").vim_buffer_cat.new, + grep_previewer = require("telescope.previewers").vim_buffer_vimgrep.new, + qflist_previewer = require("telescope.previewers").vim_buffer_qflist.new, + + -- Developer configurations: Not meant for general override + -- buffer_previewer_maker = require("telescope.previewers").buffer_previewer_maker, + mappings = { + i = { + ["<C-n>"] = actions.move_selection_next, + ["<C-p>"] = actions.move_selection_previous, + ["<C-c>"] = actions.close, + ["<C-j>"] = actions.cycle_history_next, + ["<C-k>"] = actions.cycle_history_prev, + ["<C-q>"] = actions.smart_send_to_qflist + actions.open_qflist, + ["<CR>"] = actions.select_default + actions.center, + -- To disable a keymap, put [map] = false + -- So, to not map "<C-n>", just put + -- ["<c-t>"] = trouble.open_with_trouble, + -- ["<c-x>"] = false, + -- ["<esc>"] = actions.close, + -- Otherwise, just set the mapping to the function that you want it to be. + -- ["<C-i>"] = actions.select_horizontal, + -- Add up multiple actions + -- You can perform as many actions in a row as you like + -- ["<CR>"] = actions.select_default + actions.center + my_cool_custom_action, + }, + n = { + ["<C-n>"] = actions.move_selection_next, + ["<C-p>"] = actions.move_selection_previous, + ["<C-q>"] = actions.smart_send_to_qflist + actions.open_qflist, + -- ["<c-t>"] = trouble.open_with_trouble, + -- ["<C-i>"] = my_cool_custom_action, + }, + }, + }, + extensions = { + fzy_native = { + override_generic_sorter = false, + override_file_sorter = true, + }, + }, + }) +end + +function M.find_lunarvim_files(opts) + opts = opts or {} + local themes = require "telescope.themes" + local theme_opts = themes.get_ivy { + sorting_strategy = "ascending", + layout_strategy = "bottom_pane", + prompt_prefix = ">> ", + prompt_title = "~ LunarVim files ~", + cwd = get_runtime_dir(), + search_dirs = { get_runtime_dir() .. "/lvim", lvim.lsp.templates_dir }, + } + opts = vim.tbl_deep_extend("force", theme_opts, opts) + require("telescope.builtin").find_files(opts) +end + +function M.grep_lunarvim_files(opts) + opts = opts or {} + local themes = require "telescope.themes" + local theme_opts = themes.get_ivy { + sorting_strategy = "ascending", + layout_strategy = "bottom_pane", + prompt_prefix = ">> ", + prompt_title = "~ search LunarVim ~", + cwd = get_runtime_dir(), + search_dirs = { get_runtime_dir() .. "/lvim", lvim.lsp.templates_dir }, + } + opts = vim.tbl_deep_extend("force", theme_opts, opts) + require("telescope.builtin").live_grep(opts) +end + +function M.view_lunarvim_changelog() + local finders = require "telescope.finders" + local make_entry = require "telescope.make_entry" + local pickers = require "telescope.pickers" + local previewers = require "telescope.previewers" + local actions = require "telescope.actions" + local opts = {} + + local conf = require("telescope.config").values + opts.entry_maker = make_entry.gen_from_git_commits(opts) + + pickers.new(opts, { + prompt_title = "LunarVim changelog", + + finder = finders.new_oneshot_job( + vim.tbl_flatten { + "git", + "log", + "--pretty=oneline", + "--abbrev-commit", + "--", + ".", + }, + opts + ), + previewer = { + previewers.git_commit_diff_to_parent.new(opts), + previewers.git_commit_diff_to_head.new(opts), + previewers.git_commit_diff_as_was.new(opts), + previewers.git_commit_message.new(opts), + }, + + --TODO: consider opening a diff view when pressing enter + attach_mappings = function(_, map) + map("i", "<enter>", actions._close) + map("n", "<enter>", actions._close) + map("i", "<esc>", actions._close) + map("n", "<esc>", actions._close) + map("n", "q", actions._close) + return true + end, + sorter = conf.file_sorter(opts), + }):find() +end + +function M.code_actions() + local opts = { + winblend = 15, + layout_config = { + prompt_position = "top", + width = 80, + height = 12, + }, + borderchars = { + prompt = { "─", "│", " ", "│", "╭", "╮", "│", "│" }, + results = { "─", "│", "─", "│", "├", "┤", "╯", "╰" }, + preview = { "─", "│", "─", "│", "╭", "╮", "╯", "╰" }, + }, + border = {}, + previewer = false, + shorten_path = false, + } + require("telescope.builtin").lsp_code_actions(require("telescope.themes").get_dropdown(opts)) +end + +function M.setup() + local telescope = require "telescope" + + telescope.setup(lvim.builtin.telescope) + if lvim.builtin.project.active then + telescope.load_extension "projects" + end + + if lvim.builtin.telescope.on_config_done then + lvim.builtin.telescope.on_config_done(telescope) + end +end + +return M diff --git a/lua/lvim/core/terminal.lua b/lua/lvim/core/terminal.lua new file mode 100644 index 00000000..aa6989ec --- /dev/null +++ b/lua/lvim/core/terminal.lua @@ -0,0 +1,114 @@ +local M = {} +local Log = require "lvim.core.log" + +M.config = function() + lvim.builtin["terminal"] = { + on_config_done = nil, + -- size can be a number or function which is passed the current terminal + size = 20, + -- open_mapping = [[<c-\>]], + open_mapping = [[<c-t>]], + hide_numbers = true, -- hide the number column in toggleterm buffers + shade_filetypes = {}, + shade_terminals = true, + shading_factor = 2, -- the degree by which to darken to terminal colour, default: 1 for dark backgrounds, 3 for light + start_in_insert = true, + insert_mappings = true, -- whether or not the open mapping applies in insert mode + persist_size = false, + -- direction = 'vertical' | 'horizontal' | 'window' | 'float', + direction = "float", + close_on_exit = true, -- close the terminal window when the process exits + shell = vim.o.shell, -- change the default shell + -- This field is only relevant if direction is set to 'float' + float_opts = { + -- The border key is *almost* the same as 'nvim_win_open' + -- see :h nvim_win_open for details on borders however + -- the 'curved' border is a custom border type + -- not natively supported but implemented in this plugin. + -- border = 'single' | 'double' | 'shadow' | 'curved' | ... other options supported by win open + border = "curved", + -- width = <value>, + -- height = <value>, + winblend = 0, + highlights = { + border = "Normal", + background = "Normal", + }, + }, + -- Add executables on the config.lua + -- { exec, keymap, name} + -- lvim.builtin.terminal.execs = {{}} to overwrite + -- lvim.builtin.terminal.execs[#lvim.builtin.terminal.execs+1] = {"gdb", "tg", "GNU Debugger"} + execs = { + { "lazygit", "gg", "LazyGit" }, + }, + } +end + +M.setup = function() + local terminal = require "toggleterm" + for _, exec in pairs(lvim.builtin.terminal.execs) do + require("lvim.core.terminal").add_exec(exec[1], exec[2], exec[3]) + end + terminal.setup(lvim.builtin.terminal) + + if lvim.builtin.terminal.on_config_done then + lvim.builtin.terminal.on_config_done(terminal) + end +end + +M.add_exec = function(exec, keymap, name) + vim.api.nvim_set_keymap( + "n", + "<leader>" .. keymap, + "<cmd>lua require('lvim.core.terminal')._exec_toggle('" .. exec .. "')<CR>", + { noremap = true, silent = true } + ) + lvim.builtin.which_key.mappings[keymap] = name +end + +M._split = function(inputstr, sep) + if sep == nil then + sep = "%s" + end + local t = {} + for str in string.gmatch(inputstr, "([^" .. sep .. "]+)") do + table.insert(t, str) + end + return t +end + +M._exec_toggle = function(exec) + local binary = M._split(exec)[1] + if vim.fn.executable(binary) ~= 1 then + Log:error("Unable to run executable " .. binary .. ". Please make sure it is installed properly.") + return + end + local Terminal = require("toggleterm.terminal").Terminal + local exec_term = Terminal:new { cmd = exec, hidden = true } + exec_term:toggle() +end + +---Toggles a log viewer according to log.viewer.layout_config +---@param logfile string the fullpath to the logfile +M.toggle_log_view = function(logfile) + local log_viewer = lvim.log.viewer.cmd + if vim.fn.executable(log_viewer) ~= 1 then + log_viewer = "less +F" + end + log_viewer = log_viewer .. " " .. logfile + local term_opts = vim.tbl_deep_extend("force", lvim.builtin.terminal, { + cmd = log_viewer, + open_mapping = lvim.log.viewer.layout_config.open_mapping, + direction = lvim.log.viewer.layout_config.direction, + -- TODO: this might not be working as expected + size = lvim.log.viewer.layout_config.size, + float_opts = lvim.log.viewer.layout_config.float_opts, + }) + + local Terminal = require("toggleterm.terminal").Terminal + local log_view = Terminal:new(term_opts) + log_view:toggle() +end + +return M diff --git a/lua/lvim/core/treesitter.lua b/lua/lvim/core/treesitter.lua new file mode 100644 index 00000000..ce99deba --- /dev/null +++ b/lua/lvim/core/treesitter.lua @@ -0,0 +1,81 @@ +local M = {} +local Log = require "lvim.core.log" + +M.config = function() + lvim.builtin.treesitter = { + on_config_done = nil, + ensure_installed = {}, -- one of "all", "maintained" (parsers with maintainers), or a list of languages + ignore_install = {}, + matchup = { + enable = false, -- mandatory, false will disable the whole extension + -- disable = { "c", "ruby" }, -- optional, list of language that will be disabled + }, + highlight = { + enable = true, -- false will disable the whole extension + additional_vim_regex_highlighting = true, + disable = { "latex" }, + }, + context_commentstring = { + enable = false, + config = { css = "// %s" }, + }, + -- indent = {enable = true, disable = {"python", "html", "javascript"}}, + -- TODO seems to be broken + indent = { enable = true, disable = { "yaml" } }, + autotag = { enable = false }, + textobjects = { + swap = { + enable = false, + -- swap_next = textobj_swap_keymaps, + }, + -- move = textobj_move_keymaps, + select = { + enable = false, + -- keymaps = textobj_sel_keymaps, + }, + }, + textsubjects = { + enable = false, + keymaps = { ["."] = "textsubjects-smart", [";"] = "textsubjects-big" }, + }, + playground = { + enable = false, + disable = {}, + updatetime = 25, -- Debounced time for highlighting nodes in the playground from source code + persist_queries = false, -- Whether the query persists across vim sessions + keybindings = { + toggle_query_editor = "o", + toggle_hl_groups = "i", + toggle_injected_languages = "t", + toggle_anonymous_nodes = "a", + toggle_language_display = "I", + focus_language = "f", + unfocus_language = "F", + update = "R", + goto_node = "<cr>", + show_help = "?", + }, + }, + rainbow = { + enable = false, + extended_mode = true, -- Highlight also non-parentheses delimiters, boolean or table: lang -> boolean + max_file_lines = 1000, -- Do not enable for files with more than 1000 lines, int + }, + } +end + +M.setup = function() + local status_ok, treesitter_configs = pcall(require, "nvim-treesitter.configs") + if not status_ok then + Log:get_default().error "Failed to load nvim-treesitter.configs" + return + end + + treesitter_configs.setup(lvim.builtin.treesitter) + + if lvim.builtin.treesitter.on_config_done then + lvim.builtin.treesitter.on_config_done(treesitter_configs) + end +end + +return M diff --git a/lua/lvim/core/which-key.lua b/lua/lvim/core/which-key.lua new file mode 100644 index 00000000..15f63273 --- /dev/null +++ b/lua/lvim/core/which-key.lua @@ -0,0 +1,270 @@ +local M = {} + +M.config = function() + lvim.builtin.which_key = { + ---@usage disable which-key completely [not recommeded] + active = true, + on_config_done = nil, + setup = { + plugins = { + marks = true, -- shows a list of your marks on ' and ` + registers = true, -- shows your registers on " in NORMAL or <C-r> in INSERT mode + -- the presets plugin, adds help for a bunch of default keybindings in Neovim + -- No actual key bindings are created + presets = { + operators = false, -- adds help for operators like d, y, ... + motions = false, -- adds help for motions + text_objects = false, -- help for text objects triggered after entering an operator + windows = true, -- default bindings on <c-w> + nav = true, -- misc bindings to work with windows + z = true, -- bindings for folds, spelling and others prefixed with z + g = true, -- bindings for prefixed with g + }, + spelling = { enabled = true, suggestions = 20 }, -- use which-key for spelling hints + }, + icons = { + breadcrumb = "»", -- symbol used in the command line area that shows your active key combo + separator = "➜", -- symbol used between a key and it's label + group = "+", -- symbol prepended to a group + }, + window = { + border = "single", -- none, single, double, shadow + position = "bottom", -- bottom, top + margin = { 1, 0, 1, 0 }, -- extra window margin [top, right, bottom, left] + padding = { 2, 2, 2, 2 }, -- extra window padding [top, right, bottom, left] + }, + layout = { + height = { min = 4, max = 25 }, -- min and max height of the columns + width = { min = 20, max = 50 }, -- min and max width of the columns + spacing = 3, -- spacing between columns + }, + hidden = { "<silent>", "<cmd>", "<Cmd>", "<CR>", "call", "lua", "^:", "^ " }, -- hide mapping boilerplate + show_help = true, -- show help message on the command line when the popup is visible + }, + + opts = { + mode = "n", -- NORMAL mode + prefix = "<leader>", + buffer = nil, -- Global mappings. Specify a buffer number for buffer local mappings + silent = true, -- use `silent` when creating keymaps + noremap = true, -- use `noremap` when creating keymaps + nowait = true, -- use `nowait` when creating keymaps + }, + vopts = { + mode = "v", -- VISUAL mode + prefix = "<leader>", + buffer = nil, -- Global mappings. Specify a buffer number for buffer local mappings + silent = true, -- use `silent` when creating keymaps + noremap = true, -- use `noremap` when creating keymaps + nowait = true, -- use `nowait` when creating keymaps + }, + -- NOTE: Prefer using : over <cmd> as the latter avoids going back in normal-mode. + -- see https://neovim.io/doc/user/map.html#:map-cmd + vmappings = { + ["/"] = { ":CommentToggle<CR>", "Comment" }, + }, + mappings = { + ["w"] = { "<cmd>w!<CR>", "Save" }, + ["q"] = { "<cmd>q!<CR>", "Quit" }, + ["/"] = { "<cmd>CommentToggle<CR>", "Comment" }, + ["c"] = { "<cmd>BufferClose!<CR>", "Close Buffer" }, + ["f"] = { "<cmd>Telescope find_files<CR>", "Find File" }, + ["h"] = { "<cmd>nohlsearch<CR>", "No Highlight" }, + b = { + name = "Buffers", + j = { "<cmd>BufferPick<cr>", "Jump" }, + f = { "<cmd>Telescope buffers<cr>", "Find" }, + b = { "<cmd>b#<cr>", "Previous" }, + w = { "<cmd>BufferWipeout<cr>", "Wipeout" }, + e = { + "<cmd>BufferCloseAllButCurrent<cr>", + "Close all but current", + }, + h = { "<cmd>BufferCloseBuffersLeft<cr>", "Close all to the left" }, + l = { + "<cmd>BufferCloseBuffersRight<cr>", + "Close all to the right", + }, + D = { + "<cmd>BufferOrderByDirectory<cr>", + "Sort by directory", + }, + L = { + "<cmd>BufferOrderByLanguage<cr>", + "Sort by language", + }, + }, + p = { + name = "Packer", + c = { "<cmd>PackerCompile<cr>", "Compile" }, + i = { "<cmd>PackerInstall<cr>", "Install" }, + r = { "<cmd>lua require('lvim.utils').reload_lv_config()<cr>", "Reload" }, + s = { "<cmd>PackerSync<cr>", "Sync" }, + S = { "<cmd>PackerStatus<cr>", "Status" }, + u = { "<cmd>PackerUpdate<cr>", "Update" }, + }, + + -- " Available Debug Adapters: + -- " https://microsoft.github.io/debug-adapter-protocol/implementors/adapters/ + -- " Adapter configuration and installation instructions: + -- " https://github.com/mfussenegger/nvim-dap/wiki/Debug-Adapter-installation + -- " Debug Adapter protocol: + -- " https://microsoft.github.io/debug-adapter-protocol/ + -- " Debugging + g = { + name = "Git", + j = { "<cmd>lua require 'gitsigns'.next_hunk()<cr>", "Next Hunk" }, + k = { "<cmd>lua require 'gitsigns'.prev_hunk()<cr>", "Prev Hunk" }, + l = { "<cmd>lua require 'gitsigns'.blame_line()<cr>", "Blame" }, + p = { "<cmd>lua require 'gitsigns'.preview_hunk()<cr>", "Preview Hunk" }, + r = { "<cmd>lua require 'gitsigns'.reset_hunk()<cr>", "Reset Hunk" }, + R = { "<cmd>lua require 'gitsigns'.reset_buffer()<cr>", "Reset Buffer" }, + s = { "<cmd>lua require 'gitsigns'.stage_hunk()<cr>", "Stage Hunk" }, + u = { + "<cmd>lua require 'gitsigns'.undo_stage_hunk()<cr>", + "Undo Stage Hunk", + }, + o = { "<cmd>Telescope git_status<cr>", "Open changed file" }, + b = { "<cmd>Telescope git_branches<cr>", "Checkout branch" }, + c = { "<cmd>Telescope git_commits<cr>", "Checkout commit" }, + C = { + "<cmd>Telescope git_bcommits<cr>", + "Checkout commit(for current file)", + }, + d = { + "<cmd>Gitsigns diffthis HEAD<cr>", + "Git Diff", + }, + }, + + l = { + name = "LSP", + a = { "<cmd>lua require('core.telescope').code_actions()<cr>", "Code Action" }, + d = { + "<cmd>Telescope lsp_document_diagnostics<cr>", + "Document Diagnostics", + }, + w = { + "<cmd>Telescope lsp_workspace_diagnostics<cr>", + "Workspace Diagnostics", + }, + f = { "<cmd>lua vim.lsp.buf.formatting()<cr>", "Format" }, + i = { "<cmd>LspInfo<cr>", "Info" }, + I = { "<cmd>LspInstallInfo<cr>", "Installer Info" }, + j = { + "<cmd>lua vim.lsp.diagnostic.goto_next({popup_opts = {border = lvim.lsp.popup_border}})<cr>", + "Next Diagnostic", + }, + k = { + "<cmd>lua vim.lsp.diagnostic.goto_prev({popup_opts = {border = lvim.lsp.popup_border}})<cr>", + "Prev Diagnostic", + }, + l = { "<cmd>lua vim.lsp.codelens.run()<cr>", "CodeLens Action" }, + p = { + name = "Peek", + d = { "<cmd>lua require('lvim.lsp.peek').Peek('definition')<cr>", "Definition" }, + t = { "<cmd>lua require('lvim.lsp.peek').Peek('typeDefinition')<cr>", "Type Definition" }, + i = { "<cmd>lua require('lvim.lsp.peek').Peek('implementation')<cr>", "Implementation" }, + }, + q = { "<cmd>lua vim.lsp.diagnostic.set_loclist()<cr>", "Quickfix" }, + r = { "<cmd>lua vim.lsp.buf.rename()<cr>", "Rename" }, + s = { "<cmd>Telescope lsp_document_symbols<cr>", "Document Symbols" }, + S = { + "<cmd>Telescope lsp_dynamic_workspace_symbols<cr>", + "Workspace Symbols", + }, + }, + L = { + name = "+LunarVim", + c = { + "<cmd>edit" .. get_config_dir() .. "/config.lua<cr>", + "Edit config.lua", + }, + f = { + "<cmd>lua require('lvim.core.telescope').find_lunarvim_files()<cr>", + "Find LunarVim files", + }, + g = { + "<cmd>lua require('lvim.core.telescope').grep_lunarvim_files()<cr>", + "Grep LunarVim files", + }, + k = { "<cmd>lua require('lvim.keymappings').print()<cr>", "View LunarVim's default keymappings" }, + i = { + "<cmd>lua require('lvim.core.info').toggle_popup(vim.bo.filetype)<cr>", + "Toggle LunarVim Info", + }, + I = { + "<cmd>lua require('lvim.core.telescope').view_lunarvim_changelog()<cr>", + "View LunarVim's changelog", + }, + l = { + name = "+logs", + d = { + "<cmd>lua require('lvim.core.terminal').toggle_log_view(require('lvim.core.log').get_path())<cr>", + "view default log", + }, + D = { + "<cmd>lua vim.fn.execute('edit ' .. require('lvim.core.log').get_path())<cr>", + "Open the default logfile", + }, + l = { "<cmd>lua require('lvim.core.terminal').toggle_log_view(vim.lsp.get_log_path())<cr>", "view lsp log" }, + L = { "<cmd>lua vim.fn.execute('edit ' .. vim.lsp.get_log_path())<cr>", "Open the LSP logfile" }, + n = { + "<cmd>lua require('lvim.core.terminal').toggle_log_view(os.getenv('NVIM_LOG_FILE'))<cr>", + "view neovim log", + }, + N = { "<cmd>edit $NVIM_LOG_FILE<cr>", "Open the Neovim logfile" }, + p = { + "<cmd>lua require('lvim.core.terminal').toggle_log_view('packer.nvim')<cr>", + "view packer log", + }, + P = { "<cmd>exe 'edit '.stdpath('cache').'/packer.nvim.log'<cr>", "Open the Packer logfile" }, + }, + r = { "<cmd>lua require('lvim.utils').reload_lv_config()<cr>", "Reload configurations" }, + u = { "<cmd>LvimUpdate<cr>", "Update LunarVim" }, + }, + s = { + name = "Search", + b = { "<cmd>Telescope git_branches<cr>", "Checkout branch" }, + c = { "<cmd>Telescope colorscheme<cr>", "Colorscheme" }, + f = { "<cmd>Telescope find_files<cr>", "Find File" }, + h = { "<cmd>Telescope help_tags<cr>", "Find Help" }, + M = { "<cmd>Telescope man_pages<cr>", "Man Pages" }, + r = { "<cmd>Telescope oldfiles<cr>", "Open Recent File" }, + R = { "<cmd>Telescope registers<cr>", "Registers" }, + t = { "<cmd>Telescope live_grep<cr>", "Text" }, + k = { "<cmd>Telescope keymaps<cr>", "Keymaps" }, + C = { "<cmd>Telescope commands<cr>", "Commands" }, + p = { + "<cmd>lua require('telescope.builtin.internal').colorscheme({enable_preview = true})<cr>", + "Colorscheme with Preview", + }, + }, + T = { + name = "Treesitter", + i = { ":TSConfigInfo<cr>", "Info" }, + }, + }, + } +end + +M.setup = function() + local which_key = require "which-key" + + which_key.setup(lvim.builtin.which_key.setup) + + local opts = lvim.builtin.which_key.opts + local vopts = lvim.builtin.which_key.vopts + + local mappings = lvim.builtin.which_key.mappings + local vmappings = lvim.builtin.which_key.vmappings + + which_key.register(mappings, opts) + which_key.register(vmappings, vopts) + + if lvim.builtin.which_key.on_config_done then + lvim.builtin.which_key.on_config_done(which_key) + end +end + +return M |