summaryrefslogtreecommitdiff
path: root/lua/lvim/core
diff options
context:
space:
mode:
Diffstat (limited to 'lua/lvim/core')
-rw-r--r--lua/lvim/core/autocmds.lua129
-rw-r--r--lua/lvim/core/autopairs.lua81
-rw-r--r--lua/lvim/core/bufferline.lua25
-rw-r--r--lua/lvim/core/builtins/init.lua28
-rw-r--r--lua/lvim/core/cmp.lua265
-rw-r--r--lua/lvim/core/commands.lua25
-rw-r--r--lua/lvim/core/comment.lua31
-rw-r--r--lua/lvim/core/dap.lua76
-rw-r--r--lua/lvim/core/dashboard.lua112
-rw-r--r--lua/lvim/core/gitsigns.lua64
-rw-r--r--lua/lvim/core/info.lua174
-rw-r--r--lua/lvim/core/log.lua60
-rw-r--r--lua/lvim/core/lualine/colors.lua16
-rw-r--r--lua/lvim/core/lualine/components.lua154
-rw-r--r--lua/lvim/core/lualine/conditions.lua17
-rw-r--r--lua/lvim/core/lualine/init.lua47
-rw-r--r--lua/lvim/core/lualine/styles.lua137
-rw-r--r--lua/lvim/core/lualine/utils.lua27
-rw-r--r--lua/lvim/core/nvimtree.lua141
-rw-r--r--lua/lvim/core/project.lua51
-rw-r--r--lua/lvim/core/telescope.lua193
-rw-r--r--lua/lvim/core/terminal.lua114
-rw-r--r--lua/lvim/core/treesitter.lua81
-rw-r--r--lua/lvim/core/which-key.lua270
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