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 | 
