diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index 255497d6..88a6b71e 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -2,4 +2,5 @@ github: christianchiarulli patreon: chrisatmachine - +ko_fi: chrisatmachine +custom: ["https://www.buymeacoffee.com/chrisatmachine", "https://www.paypal.com/paypalme/chrisatmachine", "https://strike.me/chrisatmachine"] diff --git a/.github/ISSUE_TEMPLATE/general-issue-form.yaml b/.github/ISSUE_TEMPLATE/general-issue-form.yaml index ea8c9cba..8faff6ae 100644 --- a/.github/ISSUE_TEMPLATE/general-issue-form.yaml +++ b/.github/ISSUE_TEMPLATE/general-issue-form.yaml @@ -33,7 +33,7 @@ body: - type: input id: nvim-version attributes: - label: Neovim version (>= 0.7.2) + label: Neovim version (>= 0.8.0) description: "Output of `nvim --version`" placeholder: | NVIM v0.8.0-dev+199-g2875d45e7 diff --git a/.github/ISSUE_TEMPLATE/lsp-issue-form.yaml b/.github/ISSUE_TEMPLATE/lsp-issue-form.yaml index e8079ffa..b3d4713b 100644 --- a/.github/ISSUE_TEMPLATE/lsp-issue-form.yaml +++ b/.github/ISSUE_TEMPLATE/lsp-issue-form.yaml @@ -27,7 +27,7 @@ body: - type: input id: nvim-version attributes: - label: Neovim version (>= 0.7) + label: Neovim version (>= 0.8.0) description: "Output of `nvim --version`" placeholder: | NVIM v0.8.0-dev+199-g2875d45e7 diff --git a/.github/workflows/close-inactive-bot.yml b/.github/workflows/close-inactive-bot.yml new file mode 100644 index 00000000..0ae33625 --- /dev/null +++ b/.github/workflows/close-inactive-bot.yml @@ -0,0 +1,22 @@ +name: Close inactive issues +on: + schedule: + - cron: '30 1 * * *' + +jobs: + close-issues: + runs-on: ubuntu-latest + permissions: + issues: write + pull-requests: write + steps: + - uses: actions/stale@v5 + with: + days-before-issue-stale: 30 + days-before-issue-close: 14 + stale-issue-label: 'stale' + stale-issue-message: 'This issue is stale because it has been open for 30 days with no activity.' + close-issue-message: 'This issue was closed because it has been inactive for 14 days since being marked as stale.' + days-before-pr-stale: -1 + days-before-pr-close: -1 + repo-token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/commitlint.yml b/.github/workflows/commitlint.yml index 1bae3a10..400b0bd0 100644 --- a/.github/workflows/commitlint.yml +++ b/.github/workflows/commitlint.yml @@ -10,10 +10,10 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} steps: - - uses: actions/checkout@v2.3.1 + - uses: actions/checkout@v3 with: fetch-depth: 0 - - uses: wagoid/commitlint-github-action@v4 + - uses: wagoid/commitlint-github-action@v5 with: configFile: .github/workflows/commitlint.config.js helpURL: https://github.com/LunarVim/LunarVim/blob/rolling/CONTRIBUTING.md#commit-messages diff --git a/.github/workflows/format.yaml b/.github/workflows/format.yaml index b63b89d7..64da97e6 100644 --- a/.github/workflows/format.yaml +++ b/.github/workflows/format.yaml @@ -15,20 +15,21 @@ jobs: name: "Formatting check with Stylua" runs-on: ubuntu-20.04 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Lint with stylua - uses: JohnnyMorganz/stylua-action@1.0.0 + uses: JohnnyMorganz/stylua-action@v1 with: token: ${{ secrets.GITHUB_TOKEN }} # CLI arguments + version: 0.15.1 args: --check . shfmt-check: name: "Formatting check with shfmt" runs-on: ubuntu-20.04 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Setup Go uses: actions/setup-go@v2 diff --git a/.github/workflows/install.yaml b/.github/workflows/install.yaml index e21607ab..5f72bcac 100644 --- a/.github/workflows/install.yaml +++ b/.github/workflows/install.yaml @@ -21,10 +21,10 @@ jobs: include: - runner: ubuntu-latest os: linux - neovim: v0.7.0 + neovim: v0.8.0 - runner: macos-latest os: osx - neovim: v0.7.0 + neovim: v0.8.0 - runner: ubuntu-22.04 os: linux neovim: nightly @@ -33,13 +33,13 @@ jobs: neovim: nightly runs-on: ${{ matrix.runner }} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Install neovim binary from release env: RELEASE_VER: ${{ matrix.neovim }} run: | - echo "$HOME/.local/bin" >> $GITHUB_PATH + echo "$HOME/.local/bin" >> "$GITHUB_PATH" bash ./utils/installer/install-neovim-from-release - name: Install LunarVim @@ -72,13 +72,13 @@ jobs: shell: pwsh steps: # it's not currently possbile to run tests on windows, see nvim-lua/plenary.nvim#255 - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Install neovim binary uses: rhysd/action-setup-vim@v1 with: neovim: true - version: v0.7.0 + version: v0.8.0 - name: Install LunarVim timeout-minutes: 4 diff --git a/.github/workflows/lint.yaml b/.github/workflows/lint.yaml index c238a5d1..f136d442 100644 --- a/.github/workflows/lint.yaml +++ b/.github/workflows/lint.yaml @@ -15,7 +15,7 @@ jobs: name: "Linting with luacheck" runs-on: ubuntu-20.04 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: leafo/gh-actions-lua@v8 - uses: leafo/gh-actions-luarocks@v4 @@ -30,7 +30,7 @@ jobs: name: Shellcheck runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Run ShellCheck uses: ludeeus/action-shellcheck@master with: diff --git a/.github/workflows/plugins.yml b/.github/workflows/plugins.yml index 3df32105..46c88c81 100644 --- a/.github/workflows/plugins.yml +++ b/.github/workflows/plugins.yml @@ -25,15 +25,13 @@ jobs: contents: write pull-requests: write steps: - - uses: actions/checkout@v2 - with: - ref: ${{ github.head_ref }} + - uses: actions/checkout@v3 - name: Install neovim binary uses: rhysd/action-setup-vim@v1 with: neovim: true - version: v0.7.0 + version: nightly - name: Install LunarVim timeout-minutes: 4 diff --git a/.gitignore b/.gitignore index c4b5cbc1..4a0cb4c8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,3 @@ -plugin/ dein tags* .netrwhist diff --git a/.luacheckrc b/.luacheckrc index 136e2326..53307087 100644 --- a/.luacheckrc +++ b/.luacheckrc @@ -1,8 +1,10 @@ +---@diagnostic disable -- vim: ft=lua tw=80 stds.nvim = { globals = { "lvim", + "reload", vim = { fields = { "g" } }, "TERMINAL", "USER", @@ -29,6 +31,7 @@ stds.nvim = { std = "lua51+nvim" files["tests/*_spec.lua"].std = "lua51+nvim+busted" +files["lua/lvim/impatient*"].ignore = {"121"} -- Don't report unused self arguments of methods. self = false diff --git a/.luarc.json b/.luarc.json new file mode 100644 index 00000000..a95ef0a2 --- /dev/null +++ b/.luarc.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://raw.githubusercontent.com/sumneko/vscode-lua/master/setting/schema.json", + "Lua.diagnostics.disable": [ + "redundant-parameter", + "param-type-mismatch", + "missing-parameter" + ], + "diagnostics.libraryFiles": "Disable" +} diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9df262b8..21ef9a8d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -10,7 +10,7 @@ One of the best ways to begin contributing in a meaningful way is by helping fin ## Getting Started -1. Follow the [Installation](https://www.lunarvim.org/01-installing.html) guide +1. Follow the [Installation](https://www.lunarvim.org/docs/installation) guide 2. Link your fork with the repository `git remote add upstream https://github.com/lunarvim/LunarVim.git`, or use `gh fork` 3. That's it! You can now `git fetch upstream` and `git rebase [-i] upstream/rolling` to update your branches with the latest contributions. diff --git a/README.md b/README.md index 8b8a9cdc..16ce0540 100644 --- a/README.md +++ b/README.md @@ -21,22 +21,31 @@ ## Showcase -![intro1](https://user-images.githubusercontent.com/59826753/159939936-3a9a8e94-05ea-48fa-8c46-69378276451b.png) -![info](https://user-images.githubusercontent.com/59826753/159939984-ac0190d7-a3fb-46c0-95ca-a6fec626bbac.png) +![intro1](https://user-images.githubusercontent.com/29136904/191624232-a7b13f11-cc9f-495e-879e-67ea0444c568.png) +![info](https://user-images.githubusercontent.com/29136904/191624942-3d75ef87-35cf-434d-850e-3e7cd5ce2ad0.png) -![demo1](https://user-images.githubusercontent.com/59826753/159940004-84975294-5703-4bf1-aa98-2cc97cb38d96.png) -![demo2](https://user-images.githubusercontent.com/59826753/159940040-375a0a28-4c81-4fdf-80f2-62853edf9b4f.png) +![demo1](https://user-images.githubusercontent.com/29136904/191625579-ce9efb1f-1e23-4a05-aebc-915a0f614d72.png) +![demo2](https://user-images.githubusercontent.com/29136904/191626018-2e9ee682-043c-4ce5-a5dd-c11b94759782.png) +![demo3](https://user-images.githubusercontent.com/29136904/191626246-ce0cc0c5-4b41-49e3-9cb7-4b1867ab0dcb.png) ## Install In One Command! -Make sure you have the release version of Neovim (0.7+). +Make sure you have the release version of Neovim (0.8+). -### Linux: +### Linux/MacOS: + +If you are running Neovim 0.8+ ```bash bash <(curl -s https://raw.githubusercontent.com/lunarvim/lunarvim/master/utils/installer/install.sh) ``` +If you are running Neovim 0.8+ + +```bash +export LV_BRANCH="rolling"; bash <(curl -s https://raw.githubusercontent.com/lunarvim/lunarvim/rolling/utils/installer/install.sh) +``` + To run the install script without any interaction you can pass the `-y` flag to automatically install all dependencies and have no prompts. This is particularly useful in automated installations. In the same way, you can use `--no-install-dependencies` to skip the dependency installation. @@ -62,7 +71,7 @@ Example: ```lua -- general lvim.format_on_save = true -lvim.colorscheme = "onedarker" +lvim.colorscheme = "tokyonight" lvim.leader = "space" -- add your own keymapping @@ -83,7 +92,7 @@ lvim.builtin.notify.active = true lvim.builtin.terminal.active = true -- Treesitter parsers change this to a table of the languages you want i.e. {"java", "python", javascript} -lvim.builtin.treesitter.ensure_installed = "maintained" +lvim.builtin.treesitter.ensure_installed = "all" lvim.builtin.treesitter.ignore_install = { "haskell" } -- Disable virtual text @@ -117,7 +126,7 @@ linters.setup { -- Additional Plugins lvim.plugins = { {"lunarvim/colorschemes"}, - {"folke/tokyonight.nvim"}, { + { "ray-x/lsp_signature.nvim", config = function() require"lsp_signature".on_attach() end, event = "BufRead" @@ -134,12 +143,6 @@ lvim.plugins = { - inside LunarVim `:PackerUpdate` -## Breaking changes - -- `lvim.lang.FOO` is no longer supported. Refer to for up-to-date instructions. -- `lvim.lsp.popup_border` has been deprecated in favor of `lvim.lsp.float.border` and `lvim.lsp.diagnostics.float.border`. -- `lvim.builtin.dashboard` has been replaced with `lvim.builtin.alpha`, see - ## Resources - [Documentation](https://www.lunarvim.org) diff --git a/ftplugin/lua.lua b/ftplugin/lua.lua new file mode 100644 index 00000000..138332e9 --- /dev/null +++ b/ftplugin/lua.lua @@ -0,0 +1,88 @@ +local fmt = string.format +-- luacheck: ignore +-- TODO: fix lint violations + +-- Iterator that splits a string o a given delimiter +local function split(str, delim) + delim = delim or "%s" + return string.gmatch(str, fmt("[^%s]+", delim)) +end + +-- Find the proper directory separator depending +-- on lua installation or OS. +local function dir_separator() + -- Look at package.config for directory separator string (it's the first line) + if package.config then + return string.match(package.config, "^[^\n]") + elseif vim.fn.has "win32" == 1 then + return "\\" + else + return "/" + end +end + +-- Search for lua traditional include paths. +-- This mimics how require internally works. +local function include_paths(fname, ext) + ext = ext or "lua" + local sep = dir_separator() + local paths = string.gsub(package.path, "%?", fname) + for path in split(paths, "%;") do + if vim.fn.filereadable(path) == 1 then + return path + end + end +end + +-- Search for nvim lua include paths +local function include_rtpaths(fname, ext) + ext = ext or "lua" + local sep = dir_separator() + local rtpaths = vim.api.nvim_list_runtime_paths() + local modfile, initfile = fmt("%s.%s", fname, ext), fmt("init.%s", ext) + for _, path in ipairs(rtpaths) do + -- Look on runtime path for 'lua/*.lua' files + local path1 = table.concat({ path, ext, modfile }, sep) + if vim.fn.filereadable(path1) == 1 then + return path1 + end + -- Look on runtime path for 'lua/*/init.lua' files + local path2 = table.concat({ path, ext, fname, initfile }, sep) + if vim.fn.filereadable(path2) == 1 then + return path2 + end + end +end + +-- Global function that searches the path for the required file +function find_required_path(module) + -- Look at package.config for directory separator string (it's the first line) + local sep = string.match(package.config, "^[^\n]") + -- Properly change '.' to separator (probably '/' on *nix and '\' on Windows) + local fname = vim.fn.substitute(module, "\\.", sep, "g") + local f + ---- First search for lua modules + f = include_paths(fname, "lua") + if f then + return f + end + -- This part is just for nvim modules + f = include_rtpaths(fname, "lua") + if f then + return f + end + ---- Now search for Fennel modules + f = include_paths(fname, "fnl") + if f then + return f + end + -- This part is just for nvim modules + f = include_rtpaths(fname, "fnl") + if f then + return f + end +end + +-- Set options to open require with gf +vim.opt_local.include = [=[\v<((do|load)file|require)\s*\(?['"]\zs[^'"]+\ze['"]]=] +vim.opt_local.includeexpr = "v:lua.find_required_path(v:fname)" diff --git a/init.lua b/init.lua index cd7c6598..75452843 100644 --- a/init.lua +++ b/init.lua @@ -1,5 +1,8 @@ -local init_path = debug.getinfo(1, "S").source:sub(2) -local base_dir = init_path:match("(.*[/\\])"):sub(1, -2) +local base_dir = vim.env.LUNARVIM_BASE_DIR + or (function() + local init_path = debug.getinfo(1, "S").source + return init_path:sub(2):match("(.*[/\\])"):sub(1, -2) + end)() if not vim.tbl_contains(vim.opt.rtp:get(), base_dir) then vim.opt.rtp:append(base_dir) @@ -10,8 +13,11 @@ require("lvim.bootstrap"):init(base_dir) require("lvim.config"):load() local plugins = require "lvim.plugins" + require("lvim.plugin-loader").load { plugins, lvim.plugins } +require("lvim.core.theme").setup() + local Log = require "lvim.core.log" Log:debug "Starting LunarVim" diff --git a/lua/lvim/bootstrap.lua b/lua/lvim/bootstrap.lua index f637c144..5d980498 100644 --- a/lua/lvim/bootstrap.lua +++ b/lua/lvim/bootstrap.lua @@ -1,7 +1,7 @@ local M = {} -if vim.fn.has "nvim-0.7" ~= 1 then - vim.notify("Please upgrade your Neovim base installation. Lunarvim requires v0.7+", vim.log.levels.WARN) +if vim.fn.has "nvim-0.8" ~= 1 then + vim.notify("Please upgrade your Neovim base installation. Lunarvim requires v0.8+", vim.log.levels.WARN) vim.wait(5000, function() return false end) @@ -19,15 +19,9 @@ function _G.join_paths(...) return result end ----Require a module in protected mode without relying on its cached value ----@param module string ----@return any -function _G.require_clean(module) - package.loaded[module] = nil - _G[module] = nil - local _, requested = pcall(require, module) - return requested -end +_G.require_clean = require("lvim.utils.modules").require_clean +_G.require_safe = require("lvim.utils.modules").require_safe +_G.reload = require("lvim.utils.modules").reload ---Get the full path to `$LUNARVIM_RUNTIME_DIR` ---@return string @@ -70,7 +64,7 @@ function M:init(base_dir) self.packer_install_dir = join_paths(self.runtime_dir, "site", "pack", "packer", "start", "packer.nvim") self.packer_cache_path = join_paths(self.config_dir, "plugin", "packer_compiled.lua") - ---@meta overridden to use LUNARVIM_CACHE_DIR instead, since a lot of plugins call this function interally + ---@meta overridden to use LUNARVIM_CACHE_DIR instead, since a lot of plugins call this function internally ---NOTE: changes to "data" are currently unstable, see #2507 vim.fn.stdpath = function(what) if what == "cache" then @@ -90,6 +84,7 @@ function M:init(base_dir) vim.opt.rtp:remove(join_paths(vim.call("stdpath", "data"), "site")) vim.opt.rtp:remove(join_paths(vim.call("stdpath", "data"), "site", "after")) vim.opt.rtp:prepend(join_paths(self.runtime_dir, "site")) + vim.opt.rtp:append(join_paths(self.runtime_dir, "lvim", "after")) vim.opt.rtp:append(join_paths(self.runtime_dir, "site", "after")) vim.opt.rtp:remove(vim.call("stdpath", "config")) @@ -120,10 +115,10 @@ end ---Update LunarVim ---pulls the latest changes from github and, resets the startup cache function M:update() - require_clean("lvim.utils.hooks").run_pre_update() - local ret = require_clean("lvim.utils.git").update_base_lvim() + reload("lvim.utils.hooks").run_pre_update() + local ret = reload("lvim.utils.git").update_base_lvim() if ret then - require_clean("lvim.utils.hooks").run_post_update() + reload("lvim.utils.hooks").run_post_update() end end diff --git a/lua/lvim/config/defaults.lua b/lua/lvim/config/defaults.lua index 7546644f..1bd57b94 100644 --- a/lua/lvim/config/defaults.lua +++ b/lua/lvim/config/defaults.lua @@ -1,6 +1,7 @@ return { leader = "space", - colorscheme = "onedarker", + reload_config_on_save = true, + colorscheme = "tokyonight", transparent_window = false, format_on_save = { ---@usage pattern string pattern used for the autocommand (Default: '*') @@ -13,6 +14,7 @@ return { keys = {}, use_icons = true, + icons = require "lvim.icons", builtin = {}, diff --git a/lua/lvim/config/init.lua b/lua/lvim/config/init.lua index c6765f56..59722673 100644 --- a/lua/lvim/config/init.lua +++ b/lua/lvim/config/init.lua @@ -111,45 +111,56 @@ end --- Override the configuration with a user provided one -- @param config_path The path to the configuration overrides function M:load(config_path) - local autocmds = require "lvim.core.autocmds" + local autocmds = reload "lvim.core.autocmds" config_path = config_path or self:get_user_config_path() local ok, err = pcall(dofile, config_path) if not ok then if utils.is_file(user_config_file) then Log:warn("Invalid configuration: " .. err) else - vim.notify_once(string.format("Unable to find configuration file [%s]", config_path), vim.log.levels.WARN) + vim.notify_once( + string.format("User-configuration not found. Creating an example configuration in %s", config_path) + ) + local example_config = join_paths(get_lvim_base_dir(), "utils", "installer", "config.example.lua") + vim.loop.fs_copyfile(example_config, config_path) end end + Log:set_level(lvim.log.level) + handle_deprecated_settings() autocmds.define_autocmds(lvim.autocommands) vim.g.mapleader = (lvim.leader == "space" and " ") or lvim.leader - require("lvim.keymappings").load(lvim.keys) + reload("lvim.keymappings").load(lvim.keys) if lvim.transparent_window then autocmds.enable_transparent_mode() end + + if lvim.reload_config_on_save then + autocmds.enable_reload_config_on_save() + end end --- Override the configuration with a user provided one -- @param config_path The path to the configuration overrides function M:reload() vim.schedule(function() - require_clean("lvim.utils.hooks").run_pre_reload() + reload("lvim.utils.hooks").run_pre_reload() M:load() - require("lvim.core.autocmds").configure_format_on_save() + reload("lvim.core.autocmds").configure_format_on_save() - local plugins = require "lvim.plugins" - local plugin_loader = require "lvim.plugin-loader" + local plugins = reload "lvim.plugins" + local plugin_loader = reload "lvim.plugin-loader" plugin_loader.reload { plugins, lvim.plugins } - require_clean("lvim.utils.hooks").run_post_reload() + reload("lvim.core.theme").setup() + reload("lvim.utils.hooks").run_post_reload() end) end diff --git a/lua/lvim/config/settings.lua b/lua/lvim/config/settings.lua index faa28641..4f61ed09 100644 --- a/lua/lvim/config/settings.lua +++ b/lua/lvim/config/settings.lua @@ -13,8 +13,7 @@ M.load_default_options = function() local default_options = { backup = false, -- creates a backup file clipboard = "unnamedplus", -- allows neovim to access the system clipboard - cmdheight = 2, -- more space in the neovim command line for displaying messages - colorcolumn = "99999", -- fixes indentline for now + cmdheight = 1, -- more space in the neovim command line for displaying messages completeopt = { "menuone", "noselect" }, conceallevel = 0, -- so that `` is visible in markdown files fileencoding = "utf-8", -- the encoding written to a file @@ -34,28 +33,31 @@ M.load_default_options = function() splitright = true, -- force all vertical splits to go to the right of current window swapfile = false, -- creates a swapfile termguicolors = true, -- set term gui colors (most terminals support this) - timeoutlen = 250, -- time to wait for a mapped sequence to complete (in milliseconds) + timeoutlen = 1000, -- time to wait for a mapped sequence to complete (in milliseconds) title = true, -- set the title of window to the value of the titlestring -- opt.titlestring = "%<%F%=%l/%L - nvim" -- what the title of the window will be set to undodir = undodir, -- set an undo directory undofile = true, -- enable persistent undo - updatetime = 300, -- faster completion + updatetime = 100, -- faster completion writebackup = false, -- if a file is being edited by another program (or was written to file while editing with another program), it is not allowed to be edited expandtab = true, -- convert tabs to spaces shiftwidth = 2, -- the number of spaces inserted for each indentation tabstop = 2, -- insert 2 spaces for a tab cursorline = true, -- highlight the current line number = true, -- set numbered lines - relativenumber = false, -- set relative numbered lines numberwidth = 4, -- set number column width to 2 {default 4} signcolumn = "yes", -- always show the sign column, otherwise it would shift the text each time wrap = false, -- display lines as one long line shadafile = join_paths(get_cache_dir(), "lvim.shada"), scrolloff = 8, -- minimal number of screen lines to keep above and below the cursor. sidescrolloff = 8, -- minimal number of screen lines to keep left and right of the cursor. + showcmd = false, + ruler = false, + laststatus = 3, } --- SETTINGS --- + vim.opt.spelllang:append "cjk" -- disable spellchecking for asian characters (VIM algorithm does not support it) vim.opt.shortmess:append "c" -- don't show redundant messages from ins-completion-menu vim.opt.shortmess:append "I" -- don't show the default intro message vim.opt.whichwrap:append "<,>,[,],h,l" diff --git a/lua/lvim/core/alpha.lua b/lua/lvim/core/alpha.lua index fd637818..58b787ed 100644 --- a/lua/lvim/core/alpha.lua +++ b/lua/lvim/core/alpha.lua @@ -65,7 +65,10 @@ local function configure_additional_autocmds() end function M.setup() - local alpha = require "alpha" + local status_ok, alpha = pcall(require, "alpha") + if not status_ok then + return + end local mode = lvim.builtin.alpha.mode local config = lvim.builtin.alpha[mode].config diff --git a/lua/lvim/core/alpha/dashboard.lua b/lua/lvim/core/alpha/dashboard.lua index d65980fb..5e73206f 100644 --- a/lua/lvim/core/alpha/dashboard.lua +++ b/lua/lvim/core/alpha/dashboard.lua @@ -1,32 +1,86 @@ local M = {} +local banner = { + " ⢀⣀⣤⣤⣤⣶⣶⣶⣶⣶⣶⣤⣤⣤⣀⡀ ", + " ⣀⣤⣶⣿⠿⠟⠛⠉⠉⠉⠁⠈⠉⠉⠉⠛⠛⠿⣿⣷⣦⣀ ", + " ⢀⣤⣾⡿⠛⠉ ⠉⠛⢿⣷⣤⡀ ", + " ⣴⣿⡿⠃ ⠙⠻⣿⣦ ", + " ⢀⣠⣤⣤⣤⣤⣤⣾⣿⣉⣀⡀ ⠙⢻⣷⡄ ", + "⣼⠋⠁ ⢠⣿⡟ ⠉⠉⠉⠛⠛⠶⠶⣤⣄⣀ ⣀⣀ ⢠⣤⣤⡄ ⢻⣿⣆ ", + "⢻⡄ ⢰⣿⡟ ⢠⣿⣿⣿⠉⠛⠲⣾⣿⣿⣷ ⢀⣾⣿⣿⠁ ⢻⣿⡆ ", + " ⠹⣦⡀ ⣿⣿⠁ ⢸⣿⣿⡇ ⠻⣿⣿⠟⠳⠶⣤⣀⣸⣿⣿⠇ ⣿⣷ ", + " ⠙⢷⣿⡇ ⣸⣿⣿⠃ ⢸⣿⣿⢷⣤⡀ ⢸⣿⡆ ", + " ⢸⣿⠇ ⣿⣿⣿ ⣿⣿⣷ ⢠⣿⣿⡏ ⠈⠙⠳⢦⣄ ⠈⣿⡇ ", + " ⢸⣿⡆ ⢸⣿⣿⡇ ⣿⣿⣿ ⢀⣿⣿⡟ ⠈⠙⠷⣤⣿⡇ ", + " ⠘⣿⡇ ⣼⣿⣿⠁ ⣿⣿⣿ ⣼⣿⣿⠃ ⢸⣿⠷⣄⡀ ", + " ⣿⣿ ⣿⣿⡿ ⣿⣿⣿⢸⣿⣿⠃ ⣾⡿ ⠈⠻⣆ ", + " ⠸⣿⣧ ⢸⣿⣿⣇⣀⣀⣀⣀⣀⣀⣸⣿⣿⣿⣿⠇ ⣼⣿⠇ ⠘⣧", + " ⠹⣿⣧ ⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠏ ⣼⣿⠏ ⣠⡿", + " ⠘⢿⣷⣄ ⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉⠉ ⢠⣼⡿⠛⠛⠛⠛⠛⠛⠉ ", + " ⠻⣿⣦⣄ ⣀⣴⣿⠟ ", + " ⠈⠛⢿⣶⣤⣀ ⣀⣤⣶⡿⠛⠁ ", + " ⠉⠻⢿⣿⣶⣤⣤⣀⣀⡀ ⢀⣀⣀⣠⣤⣶⣿⡿⠟⠋ ", + " ⠈⠉⠙⠛⠻⠿⠿⠿⠿⠿⠿⠟⠛⠋⠉⠁ ", +} + +M.banner_alt_1 = { + "⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", + "⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", + "⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣀⣤⣤⣶⣶⣶⣶⣶⣶⣶⣦⣤⣄⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", + "⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣴⣾⣿⠿⠛⠛⠉⠉⠉⠉⠉⠉⠉⠙⠛⠻⢿⣿⣶⣤⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", + "⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣴⣿⠿⠛⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠻⢿⣷⣤⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", + "⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣴⣿⠟⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⢿⣿⣦⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", + "⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡠⠒⠈⠉⠉⠉⠉⠉⣹⣿⠟⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⢿⣷⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", + "⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠸⡀⠀⠀⠀⠀⠀⠀⣰⣿⠏⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⢿⣿⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", + "⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠑⢄⠀⠀⠀⠀⢰⣿⠏⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⢿⣿⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", + "⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠑⢄⡀⠀⣿⡟⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⣿⣧⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", + "⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⢺⣿⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", + "⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⠉⠑⠢⢄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", + "⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⣿⡇⠀⠀⠀⠈⠑⠢⠄⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣿⠢⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", + "⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢿⣇⠀⠀⠀⠀⠀⠀⠀⠀⠉⠐⠢⠄⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢰⣿⡟⠀⠈⠑⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", + "⠀⠀⠀⠀⠀⠀⢀⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⣿⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠁⠒⠠⠤⣀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣾⣿⠁⠀⠀⢀⣼⣦⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", + "⠀⠀⠀⠀⠀⠀⢸⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠹⣷⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠁⠒⠂⠤⠤⠀⣀⡀⠀⠀⠀⣼⣿⠇⠀⠀⢀⣸⣿⡿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", + "⠀⠀⠀⠀⠀⠀⣿⡟⠀⠀⠀⠀⠀⠀⣤⡄⠀⠀⠀⣠⣤⠀⠀⢠⣭⣀⣤⣤⣤⡀⠀⠀⠀⢀⣤⣤⣤⣤⡀⠀⠀⠀⢠⣤⢀⣤⣤⣄⠀⠀⣿⣿⠀⠉⣹⣿⠏⠉⠉⢱⣶⣶⣶⡦⠀⠀⠀⢠⣶⣦⣴⣦⣠⣴⣦⡀⠀⠀⠀⠀", + "⠀⠀⠀⠀⠀⢠⣿⡇⠀⠀⠀⠀⠀⢠⣿⠇⠀⠀⠀⣿⡇⠀⠀⣿⡿⠉⠀⠈⣿⣧⠀⠀⠰⠿⠋⠀⠀⢹⣿⠀⠀⠀⣿⡿⠋⠀⠹⠿⠀⠀⢻⣿⡇⢠⣿⡟⠀⠀⠀⠈⠉⢹⣿⡇⠀⠀⠀⢸⣿⡏⢹⣿⡏⢹⣿⡇⠀⠀⠀⠀", + "⠀⠀⠀⠀⠀⢸⣿⠀⠀⠀⠀⠀⠀⢸⣿⠀⠀⠀⢰⣿⠃⠀⢠⣿⡇⠀⠀⠀⣿⡇⠀⠀⣠⣴⡶⠶⠶⣿⣿⠀⠀⢠⣿⡇⠀⠀⠀⠀⠀⠀⢸⣿⣇⣿⡿⠀⠀⠀⠀⠀⠀⣿⣿⠁⠀⠀⠀⣿⣿⠀⣾⣿⠀⣾⣿⠁⠀⠀⠀⠀", + "⠀⠀⠀⠀⠀⣿⣟⠀⠀⠀⠀⠀⠀⢻⣿⡀⠀⢀⣼⣿⠀⠀⢸⣿⠀⠀⠀⢰⣿⠇⠀⢰⣿⣇⠀⠀⣠⣿⡏⠀⠀⢸⣿⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⠁⠀⠀⠀⣀⣀⣠⣿⣿⣀⡀⠀⢠⣿⡟⢠⣿⡟⢀⣿⡿⠀⠀⠀⠀⠀", + "⠀⠀⠀⠀⠀⠛⠛⠛⠛⠛⠛⠁⠀⠈⠛⠿⠟⠋⠛⠃⠀⠀⠛⠛⠀⠀⠀⠘⠛⠀⠀⠀⠙⠿⠿⠛⠙⠛⠃⠀⠀⠚⠛⠀⠀⠀⠀⠀⠀⠀⠘⠿⠿⠃⠀⠀⠀⠀⠿⠿⠿⠿⠿⠿⠿⠀⠸⠿⠇⠸⠿⠇⠸⠿⠇⠀⠀⠀⠀⠀", + " ", +} + +M.banner_alt_2 = { + "⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿", + "⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠿⠟⠛⠛⠉⠉⠉⠉⠉⠉⠛⠛⠻⠿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿", + "⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠿⠛⠉⠀⣀⣤⣴⣶⣶⣾⣿⣿⣷⣶⣶⣦⣤⣀⠀⠉⠛⠿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿", + "⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠟⠁⢀⣴⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣦⡀⠈⠻⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿", + "⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠏⠀⣠⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣄⠀⠹⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿", + "⣿⣿⠿⠟⠛⠛⠛⠛⠛⠁⠀⠾⠿⠿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⡀⠈⢻⣿⣿⣿⣿⣿⣿⣿⣿", + "⣿⠁⣴⣾⣿⣿⣿⡟⠀⣰⣿⣶⣶⣶⣤⣤⣉⣉⠛⠛⠿⠿⣿⣿⡿⠿⠿⣿⣿⣿⣿⣿⣿⡟⠛⠛⢛⣿⣿⣿⣆⠀⢻⣿⣿⣿⣿⣿⣿⣿", + "⣿⡄⠻⣿⣿⣿⡟⠀⢠⣿⣿⣿⣿⣿⣿⣿⣿⡟⠀⠀⠀⣦⣤⡈⠀⠀⠀⠈⣿⣿⣿⣿⡿⠁⠀⠀⣾⣿⣿⣿⣿⡄⠀⢻⣿⣿⣿⣿⣿⣿", + "⣿⣿⣄⠙⠿⣿⠁⢀⣿⣿⣿⣿⣿⣿⣿⣿⣿⡇⠀⠀⢸⣿⣿⣿⣄⠀⠀⣠⣄⣉⠛⠻⠃⠀⠀⣼⣿⣿⣿⣿⣿⣿⡀⠈⣿⣿⣿⣿⣿⣿", + "⣿⣿⣿⣷⣦⡈⠀⢸⣿⣿⣿⣿⣿⣿⣿⣿⣿⠀⠀⠀⣼⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠆⠀⠀⡀⠛⠿⣿⣿⣿⣿⣿⡇⠀⢻⣿⣿⣿⣿⣿", + "⣿⣿⣿⣿⣿⡇⠀⣾⣿⣿⣿⣿⣿⣿⣿⣿⡟⠀⠀⢀⣿⣿⣿⣿⡇⠀⠀⠘⣿⣿⡟⠀⠀⢰⣿⣷⣦⣌⡙⠻⢿⣿⣷⠀⢸⣿⣿⣿⣿⣿", + "⣿⣿⣿⣿⣿⡇⠀⢿⣿⣿⣿⣿⣿⣿⣿⣿⡇⠀⠀⢸⣿⣿⣿⣿⣿⠀⠀⠀⣿⡿⠀⠀⢀⣿⣿⣿⣿⣿⣿⣷⣤⣈⠛⠀⢸⣿⣿⣿⣿⣿", + "⣿⣿⣿⣿⣿⣧⠀⢸⣿⣿⣿⣿⣿⣿⣿⣿⠁⠀⠀⣾⣿⣿⣿⣿⣿⠀⠀⠀⣿⠁⠀⠀⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⡇⠀⡈⠻⢿⣿⣿⣿", + "⣿⣿⣿⣿⣿⣿⡀⠈⣿⣿⣿⣿⣿⣿⣿⡿⠀⠀⢀⣿⣿⣿⣿⣿⣿⠀⠀⠀⠃⠀⠀⣼⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠁⢀⣿⣶⣄⠙⣿⣿", + "⣿⣿⣿⣿⣿⣿⣧⠀⠘⣿⣿⣿⣿⣿⣿⡇⠀⠀⠸⠿⠿⠿⠿⠿⠿⠇⠀⠀⠀⠀⣸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠃⠀⣼⣿⣿⣿⣦⠘⣿", + "⣿⣿⣿⣿⣿⣿⣿⣧⠀⠹⣿⣿⣿⣿⣿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢰⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠏⠀⣼⣿⣿⣿⡿⠟⢀⣿", + "⣿⣿⣿⣿⣿⣿⣿⣿⣧⡀⠈⢿⣿⣿⣿⣶⣶⣶⣶⣶⣶⣶⣶⣶⣶⣶⣶⣶⣶⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠁⢀⣤⣤⣤⣤⣤⣴⣶⣿⣿", + "⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣆⠀⠙⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠋⠀⣰⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿", + "⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣦⡀⠈⠻⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠟⠁⢀⣴⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿", + "⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣶⣤⣀⠀⠉⠛⠻⠿⠿⢿⣿⣿⡿⠿⠿⠟⠛⠉⠀⣀⣤⣶⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿", + "⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣶⣦⣤⣤⣀⣀⣀⣀⣀⣀⣤⣤⣴⣶⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿", + "⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿", +} + +if vim.o.lines < 36 then + banner = vim.list_slice(banner, 16, 22) +end + function M.get_sections() local header = { type = "text", - val = { - "⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", - "⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", - "⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣀⣤⣤⣶⣶⣶⣶⣶⣶⣶⣦⣤⣄⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", - "⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣴⣾⣿⠿⠛⠛⠉⠉⠉⠉⠉⠉⠉⠙⠛⠻⢿⣿⣶⣤⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", - "⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣴⣿⠿⠛⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠻⢿⣷⣤⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", - "⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣴⣿⠟⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⢿⣿⣦⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", - "⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡠⠒⠈⠉⠉⠉⠉⠉⣹⣿⠟⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⢿⣷⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", - "⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠸⡀⠀⠀⠀⠀⠀⠀⣰⣿⠏⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⢿⣿⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", - "⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠑⢄⠀⠀⠀⠀⢰⣿⠏⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⢿⣿⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", - "⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠑⢄⡀⠀⣿⡟⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⣿⣧⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", - "⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⢺⣿⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", - "⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⠉⠑⠢⢄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", - "⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⣿⡇⠀⠀⠀⠈⠑⠢⠄⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣿⠢⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", - "⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢿⣇⠀⠀⠀⠀⠀⠀⠀⠀⠉⠐⠢⠄⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢰⣿⡟⠀⠈⠑⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", - "⠀⠀⠀⠀⠀⠀⢀⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⣿⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠁⠒⠠⠤⣀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣾⣿⠁⠀⠀⢀⣼⣦⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", - "⠀⠀⠀⠀⠀⠀⢸⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠹⣷⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠁⠒⠂⠤⠤⠀⣀⡀⠀⠀⠀⣼⣿⠇⠀⠀⢀⣸⣿⡿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀", - "⠀⠀⠀⠀⠀⠀⣿⡟⠀⠀⠀⠀⠀⠀⣤⡄⠀⠀⠀⣠⣤⠀⠀⢠⣭⣀⣤⣤⣤⡀⠀⠀⠀⢀⣤⣤⣤⣤⡀⠀⠀⠀⢠⣤⢀⣤⣤⣄⠀⠀⣿⣿⠀⠉⣹⣿⠏⠉⠉⢱⣶⣶⣶⡦⠀⠀⠀⢠⣶⣦⣴⣦⣠⣴⣦⡀⠀⠀⠀⠀", - "⠀⠀⠀⠀⠀⢠⣿⡇⠀⠀⠀⠀⠀⢠⣿⠇⠀⠀⠀⣿⡇⠀⠀⣿⡿⠉⠀⠈⣿⣧⠀⠀⠰⠿⠋⠀⠀⢹⣿⠀⠀⠀⣿⡿⠋⠀⠹⠿⠀⠀⢻⣿⡇⢠⣿⡟⠀⠀⠀⠈⠉⢹⣿⡇⠀⠀⠀⢸⣿⡏⢹⣿⡏⢹⣿⡇⠀⠀⠀⠀", - "⠀⠀⠀⠀⠀⢸⣿⠀⠀⠀⠀⠀⠀⢸⣿⠀⠀⠀⢰⣿⠃⠀⢠⣿⡇⠀⠀⠀⣿⡇⠀⠀⣠⣴⡶⠶⠶⣿⣿⠀⠀⢠⣿⡇⠀⠀⠀⠀⠀⠀⢸⣿⣇⣿⡿⠀⠀⠀⠀⠀⠀⣿⣿⠁⠀⠀⠀⣿⣿⠀⣾⣿⠀⣾⣿⠁⠀⠀⠀⠀", - "⠀⠀⠀⠀⠀⣿⣟⠀⠀⠀⠀⠀⠀⢻⣿⡀⠀⢀⣼⣿⠀⠀⢸⣿⠀⠀⠀⢰⣿⠇⠀⢰⣿⣇⠀⠀⣠⣿⡏⠀⠀⢸⣿⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⠁⠀⠀⠀⣀⣀⣠⣿⣿⣀⡀⠀⢠⣿⡟⢠⣿⡟⢀⣿⡿⠀⠀⠀⠀⠀", - "⠀⠀⠀⠀⠀⠛⠛⠛⠛⠛⠛⠁⠀⠈⠛⠿⠟⠋⠛⠃⠀⠀⠛⠛⠀⠀⠀⠘⠛⠀⠀⠀⠙⠿⠿⠛⠙⠛⠃⠀⠀⠚⠛⠀⠀⠀⠀⠀⠀⠀⠘⠿⠿⠃⠀⠀⠀⠀⠿⠿⠿⠿⠿⠿⠿⠀⠸⠿⠇⠸⠿⠇⠸⠿⠇⠀⠀⠀⠀⠀", - " ", - }, + val = banner, opts = { position = "center", hl = "Label", @@ -48,21 +102,30 @@ function M.get_sections() hl = "Number", }, } + local buttons = {} - local buttons = { - entries = { - { "SPC f", " Find File", "Telescope find_files" }, - { "SPC n", " New File", "ene!" }, - { "SPC P", " Recent Projects ", "Telescope projects" }, - { "SPC s r", " Recently Used Files", "Telescope oldfiles" }, - { "SPC s t", " Find Word", "Telescope live_grep" }, - { - "SPC L c", - " Configuration", - "edit " .. require("lvim.config"):get_user_config_path() .. " ", + local status_ok, dashboard = pcall(require, "alpha.themes.dashboard") + if status_ok then + local function button(sc, txt, keybind, keybind_opts) + local b = dashboard.button(sc, txt, keybind, keybind_opts) + b.opts.hl_shortcut = "Macro" + return b + end + buttons = { + val = { + button("f", lvim.icons.ui.FindFile .. " Find File", "Telescope find_files"), + button("n", lvim.icons.ui.NewFile .. " New File", "ene!"), + button("p", lvim.icons.ui.Project .. " Projects ", "Telescope projects"), + button("r", lvim.icons.ui.History .. " Recent files", ":Telescope oldfiles "), + button("t", lvim.icons.ui.FindText .. " Find Text", "Telescope live_grep"), + button( + "c", + lvim.icons.ui.Gear .. " Configuration", + "edit " .. require("lvim.config"):get_user_config_path() .. " " + ), }, - }, - } + } + end return { header = header, diff --git a/lua/lvim/core/alpha/startify.lua b/lua/lvim/core/alpha/startify.lua index 2ea541f5..b1e83d1d 100644 --- a/lua/lvim/core/alpha/startify.lua +++ b/lua/lvim/core/alpha/startify.lua @@ -19,7 +19,7 @@ function M.get_sections() local top_buttons = { entries = { - { "e", " New File", "ene!" }, + { "e", lvim.icons.ui.NewFile .. " New File", "ene!" }, }, val = {}, } diff --git a/lua/lvim/core/autocmds.lua b/lua/lvim/core/autocmds.lua index f5c63588..ae10d552 100644 --- a/lua/lvim/core/autocmds.lua +++ b/lua/lvim/core/autocmds.lua @@ -3,13 +3,25 @@ local Log = require "lvim.core.log" --- Load the default set of autogroups and autocommands. function M.load_defaults() - local user_config_file = require("lvim.config"):get_user_config_path() - - if vim.loop.os_uname().version:match "Windows" then - -- autocmds require forward slashes even on windows - user_config_file = user_config_file:gsub("\\", "/") - end - + vim.api.nvim_create_autocmd({ "FileType" }, { + pattern = { + "Jaq", + "qf", + "help", + "man", + "lspinfo", + "spectre_panel", + "lir", + "DressingSelect", + "tsplayground", + }, + callback = function() + vim.cmd [[ + nnoremap q :close + set nobuflisted + ]] + end, + }) local definitions = { { "TextYankPost", @@ -18,19 +30,16 @@ function M.load_defaults() pattern = "*", desc = "Highlight text on yank", callback = function() - require("vim.highlight").on_yank { higroup = "Search", timeout = 200 } + require("vim.highlight").on_yank { higroup = "Search", timeout = 100 } end, }, }, { - "BufWritePost", + "FileType", { - group = "_general_settings", - pattern = user_config_file, - desc = "Trigger LvimReload on saving " .. vim.fn.expand "%:~", - callback = function() - require("lvim.config"):reload() - end, + group = "_hide_dap_repl", + pattern = "dap-repl", + command = "set nobuflisted", }, }, { @@ -73,6 +82,31 @@ function M.load_defaults() command = "tabdo wincmd =", }, }, + { + "FileType", + { + group = "_filetype_settings", + pattern = "alpha", + callback = function() + vim.cmd [[ + nnoremap q :qa + nnoremap :qa + set nobuflisted + ]] + end, + }, + }, + { + "FileType", + { + group = "_filetype_settings", + pattern = "lir", + callback = function() + vim.opt_local.number = false + vim.opt_local.relativenumber = false + end, + }, + }, } M.define_autocmds(definitions) @@ -129,6 +163,23 @@ function M.toggle_format_on_save() end end +function M.enable_reload_config_on_save() + local user_config_file = require("lvim.config"):get_user_config_path() + + if vim.loop.os_uname().version:match "Windows" then + -- autocmds require forward slashes even on windows + user_config_file = user_config_file:gsub("\\", "/") + end + vim.api.nvim_create_autocmd("BufWritePost", { + group = "_general_settings", + pattern = user_config_file, + desc = "Trigger LvimReload on saving config.lua", + callback = function() + require("lvim.config"):reload() + end, + }) +end + function M.enable_transparent_mode() vim.api.nvim_create_autocmd("ColorScheme", { pattern = "*", diff --git a/lua/lvim/core/autopairs.lua b/lua/lvim/core/autopairs.lua index 469a38a4..5daffba5 100644 --- a/lua/lvim/core/autopairs.lua +++ b/lua/lvim/core/autopairs.lua @@ -47,7 +47,10 @@ function M.config() end M.setup = function() - local autopairs = require "nvim-autopairs" + local status_ok, autopairs = pcall(require, "nvim-autopairs") + if not status_ok then + return + end local Rule = require "nvim-autopairs.rule" autopairs.setup { diff --git a/lua/lvim/core/breadcrumbs.lua b/lua/lvim/core/breadcrumbs.lua new file mode 100644 index 00000000..ab5aa86d --- /dev/null +++ b/lua/lvim/core/breadcrumbs.lua @@ -0,0 +1,226 @@ +local M = {} + +-- local Log = require "lvim.core.log" + +local icons = lvim.icons.kind + +M.config = function() + lvim.builtin.breadcrumbs = { + active = true, + on_config_done = nil, + winbar_filetype_exclude = { + "help", + "startify", + "dashboard", + "packer", + "neo-tree", + "neogitstatus", + "NvimTree", + "Trouble", + "alpha", + "lir", + "Outline", + "spectre_panel", + "toggleterm", + "DressingSelect", + "Jaq", + "harpoon", + "dap-repl", + "dap-terminal", + "dapui_console", + "lab", + "Markdown", + "notify", + "noice", + "", + }, + options = { + icons = { + Array = icons.Array .. " ", + Boolean = icons.Boolean, + Class = icons.Class .. " ", + Color = icons.Color .. " ", + Constant = icons.Constant .. " ", + Constructor = icons.Constructor .. " ", + Enum = icons.Enum .. " ", + EnumMember = icons.EnumMember .. " ", + Event = icons.Event .. " ", + Field = icons.Field .. " ", + File = icons.File .. " ", + Folder = icons.Folder .. " ", + Function = icons.Function .. " ", + Interface = icons.Interface .. " ", + Key = icons.Key .. " ", + Keyword = icons.Keyword .. " ", + Method = icons.Method .. " ", + Module = icons.Module .. " ", + Namespace = icons.Namespace .. " ", + Null = icons.Null .. " ", + Number = icons.Number .. " ", + Object = icons.Object .. " ", + Operator = icons.Operator .. " ", + Package = icons.Package .. " ", + Property = icons.Property .. " ", + Reference = icons.Reference .. " ", + Snippet = icons.Snippet .. " ", + String = icons.String .. " ", + Struct = icons.Struct .. " ", + Text = icons.Text .. " ", + TypeParameter = icons.TypeParameter .. " ", + Unit = icons.Unit .. " ", + Value = icons.Value .. " ", + Variable = icons.Variable .. " ", + }, + highlight = true, + separator = " " .. ">" .. " ", + depth_limit = 0, + depth_limit_indicator = "..", + }, + } +end + +M.setup = function() + local status_ok, navic = pcall(require, "nvim-navic") + if not status_ok then + return + end + + M.create_winbar() + navic.setup(lvim.builtin.breadcrumbs.options) + + if lvim.builtin.breadcrumbs.on_config_done then + lvim.builtin.breadcrumbs.on_config_done() + end +end + +M.get_filename = function() + local filename = vim.fn.expand "%:t" + local extension = vim.fn.expand "%:e" + local f = require "lvim.utils.functions" + + if not f.isempty(filename) then + local file_icon, file_icon_color = + require("nvim-web-devicons").get_icon_color(filename, extension, { default = true }) + + local hl_group = "FileIconColor" .. extension + + vim.api.nvim_set_hl(0, hl_group, { fg = file_icon_color }) + if f.isempty(file_icon) then + file_icon = lvim.icons.kind.File + end + + local buf_ft = vim.bo.filetype + + if buf_ft == "dapui_breakpoints" then + file_icon = lvim.icons.ui.Bug + end + + if buf_ft == "dapui_stacks" then + file_icon = lvim.icons.ui.Stacks + end + + if buf_ft == "dapui_scopes" then + file_icon = lvim.icons.ui.Scopes + end + + if buf_ft == "dapui_watches" then + file_icon = lvim.icons.ui.Watches + end + + -- if buf_ft == "dapui_console" then + -- file_icon = lvim.icons.ui.DebugConsole + -- end + + local navic_text = vim.api.nvim_get_hl_by_name("Normal", true) + vim.api.nvim_set_hl(0, "Winbar", { fg = navic_text.foreground }) + + return " " .. "%#" .. hl_group .. "#" .. file_icon .. "%*" .. " " .. "%#Winbar#" .. filename .. "%*" + end +end + +local get_gps = function() + local status_gps_ok, gps = pcall(require, "nvim-navic") + if not status_gps_ok then + return "" + end + + local status_ok, gps_location = pcall(gps.get_location, {}) + if not status_ok then + return "" + end + + if not gps.is_available() or gps_location == "error" then + return "" + end + + if not require("lvim.utils.functions").isempty(gps_location) then + -- TODO: replace with chevron + return ">" .. " " .. gps_location + else + return "" + end +end + +local excludes = function() + return vim.tbl_contains(lvim.builtin.breadcrumbs.winbar_filetype_exclude or {}, vim.bo.filetype) +end + +M.get_winbar = function() + if excludes() then + return + end + local f = require "lvim.utils.functions" + local value = M.get_filename() + + local gps_added = false + if not f.isempty(value) then + local gps_value = get_gps() + value = value .. " " .. gps_value + if not f.isempty(gps_value) then + gps_added = true + end + end + + if not f.isempty(value) and f.get_buf_option "mod" then + -- TODO: replace with circle + local mod = "%#LspCodeLens#" .. lvim.icons.ui.Circle .. "%*" + if gps_added then + value = value .. " " .. mod + else + value = value .. mod + end + end + + local num_tabs = #vim.api.nvim_list_tabpages() + + if num_tabs > 1 and not f.isempty(value) then + local tabpage_number = tostring(vim.api.nvim_tabpage_get_number(0)) + value = value .. "%=" .. tabpage_number .. "/" .. tostring(num_tabs) + end + + local status_ok, _ = pcall(vim.api.nvim_set_option_value, "winbar", value, { scope = "local" }) + if not status_ok then + return + end +end + +M.create_winbar = function() + vim.api.nvim_create_augroup("_winbar", {}) + if vim.fn.has "nvim-0.8" == 1 then + vim.api.nvim_create_autocmd( + { "CursorMoved", "CursorHold", "BufWinEnter", "BufFilePost", "InsertEnter", "BufWritePost", "TabClosed" }, + { + group = "_winbar", + callback = function() + local status_ok, _ = pcall(vim.api.nvim_buf_get_var, 0, "lsp_floating_window") + if not status_ok then + -- TODO: + require("lvim.core.breadcrumbs").get_winbar() + end + end, + } + ) + end +end + +return M diff --git a/lua/lvim/core/bufferline.lua b/lua/lvim/core/bufferline.lua index 36e5ff54..b8143813 100644 --- a/lua/lvim/core/bufferline.lua +++ b/lua/lvim/core/bufferline.lua @@ -6,7 +6,11 @@ end local function diagnostics_indicator(num, _, diagnostics, _) local result = {} - local symbols = { error = "", warning = "", info = "" } + local symbols = { + error = lvim.icons.diagnostics.Error, + warning = lvim.icons.diagnostics.Warning, + info = lvim.icons.diagnostics.Information, + } if not lvim.use_icons then return "(" .. num .. ")" end @@ -59,14 +63,14 @@ M.config = function() left_mouse_command = "buffer %d", -- can be a string | function, see "Mouse actions" middle_mouse_command = nil, -- can be a string | function, see "Mouse actions" indicator = { - icon = "▎", -- this should be omitted if indicator style is not 'icon' + icon = lvim.icons.ui.BoldLineLeft, -- this should be omitted if indicator style is not 'icon' style = "icon", -- can also be 'underline'|'none', }, - buffer_close_icon = "", - modified_icon = "●", - close_icon = "", - left_trunc_marker = "", - right_trunc_marker = "", + buffer_close_icon = lvim.icons.ui.Close, + modified_icon = lvim.icons.ui.Circle, + close_icon = lvim.icons.ui.BoldClose, + left_trunc_marker = lvim.icons.ui.ArrowCircleLeft, + right_trunc_marker = lvim.icons.ui.ArrowCircleRight, --- name_formatter can be used to change the buffer's label in the bufferline. --- Please note some names can/will break the --- bufferline so use this at your discretion knowing that it has @@ -140,7 +144,13 @@ end M.setup = function() require("lvim.keymappings").load(lvim.builtin.bufferline.keymap) - require("bufferline").setup { + + local status_ok, bufferline = pcall(require, "bufferline") + if not status_ok then + return + end + + bufferline.setup { options = lvim.builtin.bufferline.options, highlights = lvim.builtin.bufferline.highlights, } diff --git a/lua/lvim/core/builtins/init.lua b/lua/lvim/core/builtins/init.lua index 5cad2a00..0060c460 100644 --- a/lua/lvim/core/builtins/init.lua +++ b/lua/lvim/core/builtins/init.lua @@ -1,6 +1,7 @@ local M = {} local builtins = { + "lvim.core.theme", "lvim.core.which-key", "lvim.core.gitsigns", "lvim.core.cmp", @@ -9,6 +10,10 @@ local builtins = { "lvim.core.telescope", "lvim.core.treesitter", "lvim.core.nvimtree", + "lvim.core.lir", + "lvim.core.illuminate", + "lvim.core.indentlines", + "lvim.core.breadcrumbs", "lvim.core.project", "lvim.core.bufferline", "lvim.core.autopairs", @@ -21,7 +26,8 @@ local builtins = { function M.config(config) for _, builtin_path in ipairs(builtins) do - local builtin = require(builtin_path) + local builtin = reload(builtin_path) + builtin.config(config) end end diff --git a/lua/lvim/core/cmp.lua b/lua/lvim/core/cmp.lua index 408691a6..4ebc4d43 100644 --- a/lua/lvim/core/cmp.lua +++ b/lua/lvim/core/cmp.lua @@ -19,6 +19,7 @@ end local function feedkeys(key, mode) vim.api.nvim_feedkeys(T(key), mode, true) end + M.methods.feedkeys = feedkeys ---when inside a snippet, seeks to the nearest luasnip field if possible, and checks if it is jumpable @@ -113,6 +114,7 @@ local function jumpable(dir) return luasnip.in_snippet() and seek_luasnip_cursor_node() and luasnip.jumpable(1) end end + M.methods.jumpable = jumpable M.config = function() @@ -135,39 +137,13 @@ M.config = function() keyword_length = 1, }, experimental = { - ghost_text = true, + ghost_text = false, native_menu = false, }, formatting = { fields = { "kind", "abbr", "menu" }, max_width = 0, - 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 = " ", - }, + kind_icons = lvim.icons.kind, source_names = { nvim_lsp = "(LSP)", emoji = "(Emoji)", @@ -178,6 +154,8 @@ M.config = function() luasnip = "(Snippet)", buffer = "(Buffer)", tmux = "(TMUX)", + copilot = "(Copilot)", + treesitter = "(TreeSitter)", }, duplicates = { buffer = 1, @@ -189,10 +167,40 @@ M.config = function() format = function(entry, vim_item) local max_width = lvim.builtin.cmp.formatting.max_width if max_width ~= 0 and #vim_item.abbr > max_width then - vim_item.abbr = string.sub(vim_item.abbr, 1, max_width - 1) .. "…" + vim_item.abbr = string.sub(vim_item.abbr, 1, max_width - 1) .. lvim.icons.ui.Ellipsis end if lvim.use_icons then vim_item.kind = lvim.builtin.cmp.formatting.kind_icons[vim_item.kind] + + -- TODO: not sure why I can't put this anywhere else + vim.api.nvim_set_hl(0, "CmpItemKindCopilot", { fg = "#6CC644" }) + if entry.source.name == "copilot" then + vim_item.kind = lvim.icons.git.Octoface + vim_item.kind_hl_group = "CmpItemKindCopilot" + end + + vim.api.nvim_set_hl(0, "CmpItemKindTabnine", { fg = "#CA42F0" }) + if entry.source.name == "cmp_tabnine" then + vim_item.kind = lvim.icons.misc.Robot + vim_item.kind_hl_group = "CmpItemKindTabnine" + end + + vim.api.nvim_set_hl(0, "CmpItemKindCrate", { fg = "#F64D00" }) + if entry.source.name == "crates" then + vim_item.kind = lvim.icons.misc.Package + vim_item.kind_hl_group = "CmpItemKindCrate" + end + + if entry.source.name == "lab.quick_data" then + vim_item.kind = lvim.icons.misc.CircuitBoard + vim_item.kind_hl_group = "CmpItemKindConstant" + end + + vim.api.nvim_set_hl(0, "CmpItemKindEmoji", { fg = "#FDE030" }) + if entry.source.name == "emoji" then + vim_item.kind = lvim.icons.misc.Smiley + vim_item.kind_hl_group = "CmpItemKindEmoji" + end end vim_item.menu = lvim.builtin.cmp.formatting.source_names[entry.source.name] vim_item.dup = lvim.builtin.cmp.formatting.duplicates[entry.source.name] @@ -210,7 +218,50 @@ M.config = function() documentation = cmp.config.window.bordered(), }, sources = { - { name = "nvim_lsp" }, + { + name = "copilot", + -- keyword_length = 0, + max_item_count = 3, + trigger_characters = { + { + ".", + ":", + "(", + "'", + '"', + "[", + ",", + "#", + "*", + "@", + "|", + "=", + "-", + "{", + "/", + "\\", + "+", + "?", + " ", + -- "\t", + -- "\n", + }, + }, + }, + { + name = "nvim_lsp", + entry_filter = function(entry, ctx) + local kind = require("cmp.types").lsp.CompletionItemKind[entry:get_kind()] + if kind == "Snippet" and ctx.prev_context.filetype == "java" then + return false + end + if kind == "Text" then + return false + end + return true + end, + }, + { name = "path" }, { name = "luasnip" }, { name = "cmp_tabnine" }, @@ -223,8 +274,8 @@ M.config = function() { name = "tmux" }, }, mapping = cmp.mapping.preset.insert { - [""] = cmp.mapping.select_prev_item(), - [""] = cmp.mapping.select_next_item(), + [""] = cmp.mapping(cmp.mapping.select_prev_item(), { "i", "c" }), + [""] = cmp.mapping(cmp.mapping.select_next_item(), { "i", "c" }), [""] = cmp.mapping(cmp.mapping.select_next_item { behavior = cmp.SelectBehavior.Select }, { "i" }), [""] = cmp.mapping(cmp.mapping.select_prev_item { behavior = cmp.SelectBehavior.Select }, { "i" }), [""] = cmp.mapping.scroll_docs(-4), @@ -247,7 +298,8 @@ M.config = function() elseif jumpable(1) then luasnip.jump(1) elseif has_words_before() then - cmp.complete() + -- cmp.complete() + fallback() else fallback() end @@ -283,11 +335,38 @@ M.config = function() fallback() -- if not exited early, always fallback end), }, + cmdline = { + enable = true, + options = { + { + type = ":", + sources = { + { name = "path" }, + }, + }, + { + type = { "/", "?" }, + sources = { + { name = "buffer" }, + }, + }, + }, + }, } end function M.setup() - require("cmp").setup(lvim.builtin.cmp) + local cmp = require "cmp" + cmp.setup(lvim.builtin.cmp) + + if lvim.builtin.cmp.cmdline.enable then + for _, option in ipairs(lvim.builtin.cmp.cmdline.options) do + cmp.setup.cmdline(option.type, { + mapping = cmp.mapping.preset.cmdline(), + sources = option.sources, + }) + end + end end return M diff --git a/lua/lvim/core/comment.lua b/lua/lvim/core/comment.lua index d07739c6..501d01b6 100644 --- a/lua/lvim/core/comment.lua +++ b/lua/lvim/core/comment.lua @@ -1,27 +1,10 @@ local M = {} function M.config() - local pre_hook = nil - if lvim.builtin.treesitter.context_commentstring.enable then - pre_hook = function(ctx) - local U = require "Comment.utils" - - -- Determine whether to use linewise or blockwise commentstring - local type = ctx.ctype == U.ctype.linewise and "__default" or "__multiline" - - -- Determine the location where to calculate commentstring from - local location = nil - if ctx.ctype == U.ctype.blockwise then - location = require("ts_context_commentstring.utils").get_cursor_location() - elseif ctx.cmotion == U.cmotion.v or ctx.cmotion == U.cmotion.V then - location = require("ts_context_commentstring.utils").get_visual_start_location() - end - - return require("ts_context_commentstring.internal").calculate_commentstring { - key = type, - location = location, - } - end + local pre_hook + local loaded, ts_comment = pcall(require, "ts_context_commentstring.integrations.comment_nvim") + if loaded and ts_comment then + pre_hook = ts_comment.create_pre_hook() end lvim.builtin.comment = { active = true, @@ -30,6 +13,11 @@ function M.config() ---@type boolean padding = true, + ---Whether cursor should stay at the + ---same position. Only works in NORMAL + ---mode mappings + sticky = true, + ---Lines to be ignored while comment/uncomment. ---Could be a regex string or a function that returns a regex string. ---Example: Use '^$' to ignore empty lines @@ -45,9 +33,6 @@ function M.config() ---Extra mapping ---Includes `gco`, `gcO`, `gcA` extra = true, - ---Extended mapping - ---Includes `g>`, `g<`, `g>[count]{motion}` and `g<[count]{motion}` - extended = false, }, ---LHS of line and block comment toggle mapping in NORMAL/VISUAL mode @@ -68,6 +53,17 @@ function M.config() block = "gb", }, + ---LHS of extra mappings + ---@type table + extra = { + ---Add comment on the line above + above = "gcO", + ---Add comment on the line below + below = "gco", + ---Add comment at the end of line + eol = "gcA", + }, + ---Pre-hook, called before commenting the line ---@type function|nil pre_hook = pre_hook, diff --git a/lua/lvim/core/dap.lua b/lua/lvim/core/dap.lua index 727e238f..cff50f64 100644 --- a/lua/lvim/core/dap.lua +++ b/lua/lvim/core/dap.lua @@ -2,31 +2,37 @@ local M = {} M.config = function() lvim.builtin.dap = { - active = false, + active = true, on_config_done = nil, breakpoint = { - text = "", - texthl = "LspDiagnosticsSignError", + text = lvim.icons.ui.Bug, + texthl = "DiagnosticSignError", linehl = "", numhl = "", }, breakpoint_rejected = { - text = "", - texthl = "LspDiagnosticsSignHint", + text = lvim.icons.ui.Bug, + texthl = "DiagnosticSignError", linehl = "", numhl = "", }, stopped = { - text = "", - texthl = "LspDiagnosticsSignInformation", - linehl = "DiagnosticUnderlineInfo", - numhl = "LspDiagnosticsSignInformation", + text = lvim.icons.ui.BoldArrowRight, + texthl = "DiagnosticSignWarn", + linehl = "Visual", + numhl = "DiagnosticSignWarn", + }, + ui = { + auto_open = true, }, } end M.setup = function() - local dap = require "dap" + local status_ok, dap = pcall(require, "dap") + if not status_ok then + return + end if lvim.use_icons then vim.fn.sign_define("DapBreakpoint", lvim.builtin.dap.breakpoint) @@ -34,8 +40,6 @@ M.setup = function() vim.fn.sign_define("DapStopped", lvim.builtin.dap.stopped) end - dap.defaults.fallback.terminal_win_cmd = "50vsplit new" - lvim.builtin.which_key.mappings["d"] = { name = "Debug", t = { "lua require'dap'.toggle_breakpoint()", "Toggle Breakpoint" }, @@ -51,6 +55,7 @@ M.setup = function() r = { "lua require'dap'.repl.toggle()", "Toggle Repl" }, s = { "lua require'dap'.continue()", "Start" }, q = { "lua require'dap'.close()", "Quit" }, + U = { "lua require'dapui'.toggle()", "Toggle UI" }, } if lvim.builtin.dap.on_config_done then @@ -58,21 +63,65 @@ M.setup = function() end end --- TODO put this up there ^^^ call in ftplugin +M.setup_ui = function() + local status_ok, dap = pcall(require, "dap") + if not status_ok then + return + end + local dapui = require "dapui" + dapui.setup { + expand_lines = true, + icons = { expanded = "", collapsed = "", circular = "" }, + mappings = { + -- Use a table to apply multiple mappings + expand = { "", "<2-LeftMouse>" }, + open = "o", + remove = "d", + edit = "e", + repl = "r", + toggle = "t", + }, + layouts = { + { + elements = { + { id = "scopes", size = 0.33 }, + { id = "breakpoints", size = 0.17 }, + { id = "stacks", size = 0.25 }, + { id = "watches", size = 0.25 }, + }, + size = 0.33, + position = "right", + }, + { + elements = { + { id = "repl", size = 0.45 }, + { id = "console", size = 0.55 }, + }, + size = 0.27, + position = "bottom", + }, + }, + floating = { + max_height = 0.9, + max_width = 0.5, -- Floats will be treated as percentage of your screen. + border = vim.g.border_chars, -- Border style. Can be 'single', 'double' or 'rounded' + mappings = { + close = { "q", "" }, + }, + }, + } --- 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 + if lvim.builtin.dap.ui.auto_open then + dap.listeners.after.event_initialized["dapui_config"] = function() + dapui.open() + end + -- dap.listeners.before.event_terminated["dapui_config"] = function() + -- dapui.close() + -- end + -- dap.listeners.before.event_exited["dapui_config"] = function() + -- dapui.close() + -- end + end +end return M diff --git a/lua/lvim/core/gitsigns.lua b/lua/lvim/core/gitsigns.lua index 0365fc69..cc727c8b 100644 --- a/lua/lvim/core/gitsigns.lua +++ b/lua/lvim/core/gitsigns.lua @@ -8,31 +8,31 @@ M.config = function() signs = { add = { hl = "GitSignsAdd", - text = "▎", + text = lvim.icons.ui.BoldLineLeft, numhl = "GitSignsAddNr", linehl = "GitSignsAddLn", }, change = { hl = "GitSignsChange", - text = "▎", + text = lvim.icons.ui.BoldLineLeft, numhl = "GitSignsChangeNr", linehl = "GitSignsChangeLn", }, delete = { hl = "GitSignsDelete", - text = "契", + text = lvim.icons.ui.Triangle, numhl = "GitSignsDeleteNr", linehl = "GitSignsDeleteLn", }, topdelete = { hl = "GitSignsDelete", - text = "契", + text = lvim.icons.ui.Triangle, numhl = "GitSignsDeleteNr", linehl = "GitSignsDeleteLn", }, changedelete = { hl = "GitSignsChange", - text = "▎", + text = lvim.icons.ui.BoldLineLeft, numhl = "GitSignsChangeNr", linehl = "GitSignsChangeLn", }, @@ -79,7 +79,7 @@ M.config = function() end M.setup = function() - local gitsigns = require "gitsigns" + local gitsigns = reload "gitsigns" gitsigns.setup(lvim.builtin.gitsigns.opts) if lvim.builtin.gitsigns.on_config_done then diff --git a/lua/lvim/core/illuminate.lua b/lua/lvim/core/illuminate.lua new file mode 100644 index 00000000..a3ca6711 --- /dev/null +++ b/lua/lvim/core/illuminate.lua @@ -0,0 +1,68 @@ +local M = {} + +M.config = function() + lvim.builtin.illuminate = { + active = true, + on_config_done = nil, + options = { + -- providers: provider used to get references in the buffer, ordered by priority + providers = { + "lsp", + "treesitter", + "regex", + }, + -- delay: delay in milliseconds + delay = 120, + -- filetypes_denylist: filetypes to not illuminate, this overrides filetypes_allowlist + filetypes_denylist = { + "dirvish", + "fugitive", + "alpha", + "NvimTree", + "packer", + "neogitstatus", + "Trouble", + "lir", + "Outline", + "spectre_panel", + "toggleterm", + "DressingSelect", + "TelescopePrompt", + }, + -- filetypes_allowlist: filetypes to illuminate, this is overridden by filetypes_denylist + filetypes_allowlist = {}, + -- modes_denylist: modes to not illuminate, this overrides modes_allowlist + modes_denylist = {}, + -- modes_allowlist: modes to illuminate, this is overridden by modes_denylist + modes_allowlist = {}, + -- providers_regex_syntax_denylist: syntax to not illuminate, this overrides providers_regex_syntax_allowlist + -- Only applies to the 'regex' provider + -- Use :echom synIDattr(synIDtrans(synID(line('.'), col('.'), 1)), 'name') + providers_regex_syntax_denylist = {}, + -- providers_regex_syntax_allowlist: syntax to illuminate, this is overridden by providers_regex_syntax_denylist + -- Only applies to the 'regex' provider + -- Use :echom synIDattr(synIDtrans(synID(line('.'), col('.'), 1)), 'name') + providers_regex_syntax_allowlist = {}, + -- under_cursor: whether or not to illuminate under the cursor + under_cursor = true, + }, + } +end + +M.setup = function() + local status_ok, illuminate = pcall(reload, "illuminate") + if not status_ok then + return + end + + local config_ok, _ = pcall(illuminate.configure, lvim.builtin.illuminate.options) + if not config_ok then + return + end + + if lvim.builtin.illuminate.on_config_done then + lvim.builtin.illuminate.on_config_done() + end +end + +return M diff --git a/lua/lvim/core/indentlines.lua b/lua/lvim/core/indentlines.lua new file mode 100644 index 00000000..dc4a72ba --- /dev/null +++ b/lua/lvim/core/indentlines.lua @@ -0,0 +1,42 @@ +local M = {} + +M.config = function() + lvim.builtin.indentlines = { + active = true, + on_config_done = nil, + options = { + enabled = true, + buftype_exclude = { "terminal", "nofile" }, + filetype_exclude = { + "help", + "startify", + "dashboard", + "packer", + "neogitstatus", + "NvimTree", + "Trouble", + "text", + }, + char = lvim.icons.ui.LineLeft, + show_trailing_blankline_indent = false, + show_first_indent_level = true, + use_treesitter = true, + show_current_context = true, + }, + } +end + +M.setup = function() + local status_ok, indent_blankline = pcall(reload, "indent_blankline") + if not status_ok then + return + end + + indent_blankline.setup(lvim.builtin.indentlines.options) + + if lvim.builtin.indentlines.on_config_done then + lvim.builtin.indentlines.on_config_done() + end +end + +return M diff --git a/lua/lvim/core/info.lua b/lua/lvim/core/info.lua index da9ddbe6..c413f0f1 100644 --- a/lua/lvim/core/info.lua +++ b/lua/lvim/core/info.lua @@ -25,8 +25,8 @@ local function make_formatters_info(ft) "Formatters info", fmt( "* Active: %s%s", - table.concat(registered_formatters, "  , "), - vim.tbl_count(registered_formatters) > 0 and "  " or "" + table.concat(registered_formatters, " " .. lvim.icons.ui.BoxChecked .. " , "), + vim.tbl_count(registered_formatters) > 0 and " " .. lvim.icons.ui.BoxChecked .. " " or "" ), fmt("* Supported: %s", str_list(supported_formatters)), } @@ -41,8 +41,8 @@ local function make_code_actions_info(ft) "Code actions info", fmt( "* Active: %s%s", - table.concat(registered_actions, "  , "), - vim.tbl_count(registered_actions) > 0 and "  " or "" + table.concat(registered_actions, " " .. lvim.icons.ui.BoxChecked .. " , "), + vim.tbl_count(registered_actions) > 0 and " " .. lvim.icons.ui.BoxChecked .. " " or "" ), } @@ -57,8 +57,8 @@ local function make_linters_info(ft) "Linters info", fmt( "* Active: %s%s", - table.concat(registered_linters, "  , "), - vim.tbl_count(registered_linters) > 0 and "  " or "" + table.concat(registered_linters, " " .. lvim.icons.ui.BoxChecked .. " , "), + vim.tbl_count(registered_linters) > 0 and " " .. lvim.icons.ui.BoxChecked .. " " or "" ), fmt("* Supported: %s", str_list(supported_linters)), } @@ -202,7 +202,7 @@ function M.toggle_popup(ft) vim.fn.matchadd("LvimInfoIdentifier", " " .. ft .. "$") vim.fn.matchadd("string", "true") vim.fn.matchadd("string", "active") - vim.fn.matchadd("string", "") + vim.fn.matchadd("string", lvim.icons.ui.BoxChecked) vim.fn.matchadd("boolean", "inactive") vim.fn.matchadd("error", "false") tbl_set_highlight(require("lvim.lsp.null-ls.formatters").list_registered(ft), "LvimInfoIdentifier") diff --git a/lua/lvim/core/lir.lua b/lua/lvim/core/lir.lua new file mode 100644 index 00000000..68445664 --- /dev/null +++ b/lua/lvim/core/lir.lua @@ -0,0 +1,118 @@ +local M = {} + +M.config = function() + lvim.builtin.lir = { + active = true, + on_config_done = nil, + icon = "", + } + + local status_ok, _ = pcall(require, "lir") + if not status_ok then + return + end + + local actions = require "lir.actions" + local mark_actions = require "lir.mark.actions" + local clipboard_actions = require "lir.clipboard.actions" + + lvim.builtin.lir = vim.tbl_extend("force", lvim.builtin.lir, { + show_hidden_files = false, + devicons_enable = true, + mappings = { + ["l"] = actions.edit, + [""] = actions.edit, + [""] = actions.split, + ["v"] = actions.vsplit, + [""] = actions.tabedit, + + ["h"] = actions.up, + ["q"] = actions.quit, + + ["A"] = actions.mkdir, + ["a"] = actions.newfile, + ["r"] = actions.rename, + ["@"] = actions.cd, + ["Y"] = actions.yank_path, + ["i"] = actions.toggle_show_hidden, + ["d"] = actions.delete, + + ["J"] = function() + mark_actions.toggle_mark() + vim.cmd "normal! j" + end, + ["c"] = clipboard_actions.copy, + ["x"] = clipboard_actions.cut, + ["p"] = clipboard_actions.paste, + }, + float = { + winblend = 0, + curdir_window = { + enable = false, + highlight_dirname = true, + }, + + -- -- You can define a function that returns a table to be passed as the third + -- -- argument of nvim_open_win(). + win_opts = function() + local width = math.floor(vim.o.columns * 0.7) + local height = math.floor(vim.o.lines * 0.7) + return { + border = "rounded", + width = width, + height = height, + -- row = 1, + -- col = math.floor((vim.o.columns - width) / 2), + } + end, + }, + hide_cursor = false, + on_init = function() + -- use visual mode + vim.api.nvim_buf_set_keymap( + 0, + "x", + "J", + ':lua require"lir.mark.actions".toggle_mark("v")', + { noremap = true, silent = true } + ) + + -- echo cwd + -- vim.api.nvim_echo({ { vim.fn.expand "%:p", "Normal" } }, false, {}) + end, + }) +end + +function M.icon_setup() + local function get_hl_by_name(name) + local ret = vim.api.nvim_get_hl_by_name(name.group, true) + return string.format("#%06x", ret[name.property]) + end + + local found, icon_hl = pcall(get_hl_by_name, { group = "NvimTreeFolderIcon", property = "foreground" }) + if not found then + icon_hl = "#42A5F5" + end + + reload("nvim-web-devicons").set_icon { + lir_folder_icon = { + icon = lvim.builtin.lir.icon, + color = icon_hl, + name = "LirFolderNode", + }, + } +end + +function M.setup() + local status_ok, lir = pcall(reload, "lir") + if not status_ok then + return + end + lir.setup(lvim.builtin.lir) + + if lvim.builtin.lir.on_config_done then + lvim.builtin.lir.on_config_done(lir) + end +end + +return M diff --git a/lua/lvim/core/log.lua b/lua/lvim/core/log.lua index 48891139..d88a659b 100644 --- a/lua/lvim/core/log.lua +++ b/lua/lvim/core/log.lua @@ -12,26 +12,23 @@ vim.tbl_add_reverse_lookup(Log.levels) local notify_opts = {} function Log:set_level(level) - local logger_ok, _ = xpcall(function() - local log_level = Log.levels[level:upper()] - local structlog = require "structlog" - if structlog then - local logger = structlog.get_logger "lvim" - for _, s in ipairs(logger.sinks) do - s.level = log_level - end + local logger_ok, logger = pcall(function() + return require("structlog").get_logger "lvim" + end) + local log_level = Log.levels[level:upper()] + if logger_ok and logger and log_level then + for _, s in ipairs(logger.sinks) do + s.level = log_level end - end, debug.traceback) - if not logger_ok then - Log:debug("Unable to set logger's level: " .. debug.traceback()) + else + vim.notify_once("Unable to set logger's level to " .. level) end local packer_ok, _ = xpcall(function() - package.loaded["packer.log"] = nil - require("packer.log").new { level = lvim.log.level } + require("packer.log").cfg { log = { level = level } } end, debug.traceback) if not packer_ok then - Log:debug("Unable to set packer's log level: " .. debug.traceback()) + vim.notify_once("Unable to set packer's log level to " .. level) end end @@ -91,7 +88,7 @@ function Log:init() vim_log_level = vim_log_level + 1 end - logger:log(vim_log_level, msg) + self:info(vim_log_level, msg) end end @@ -145,8 +142,9 @@ function Log:configure_notifications(notif_handle) end --- Adds a log entry using Plenary.log +---@param level integer [same as vim.log.levels] ---@param msg any ----@param level string [same as vim.log.log_levels] +---@param event any function Log:add_entry(level, msg, event) local logger = self:get_logger() if not logger then @@ -158,11 +156,15 @@ end ---Retrieves the handle of the logger object ---@return table|nil logger handle if found function Log:get_logger() - if self.__handle then - return self.__handle + local logger_ok, logger = pcall(function() + return require("structlog").get_logger "lvim" + end) + if logger_ok and logger then + return logger end - local logger = self:init() + logger = self:init() + if not logger then return end diff --git a/lua/lvim/core/lualine/components.lua b/lua/lvim/core/lualine/components.lua index c88bf82b..e4148e20 100644 --- a/lua/lvim/core/lualine/components.lua +++ b/lua/lvim/core/lualine/components.lua @@ -12,10 +12,35 @@ local function diff_source() end end +local statusline_hl = vim.api.nvim_get_hl_by_name("StatusLine", true) +local cursorline_hl = vim.api.nvim_get_hl_by_name("CursorLine", true) +local normal_hl = vim.api.nvim_get_hl_by_name("Normal", true) + +vim.api.nvim_set_hl(0, "SLCopilot", { fg = "#6CC644", bg = statusline_hl.background }) +vim.api.nvim_set_hl(0, "SLGitIcon", { fg = "#E8AB53", bg = cursorline_hl.background }) +vim.api.nvim_set_hl(0, "SLBranchName", { fg = normal_hl.foreground, bg = cursorline_hl.background }) +vim.api.nvim_set_hl(0, "SLProgress", { fg = "#ECBE7B", bg = statusline_hl.background }) + +local location_color = nil +local branch = lvim.icons.git.Branch +local separator = lvim.icons.ui.LineMiddle + +if lvim.colorscheme == "tokyonight" then + location_color = "SLBranchName" + branch = "%#SLGitIcon#" .. lvim.icons.git.Branch .. "%*" .. "%#SLBranchName#" + + local status_ok, tnc = pcall(require, "tokyonight.colors") + if status_ok then + local tncolors = tnc.setup { transform = true } + vim.api.nvim_set_hl(0, "SLSeparator", { fg = cursorline_hl.background, bg = tncolors.black }) + separator = "%#SLSeparator#" .. lvim.icons.ui.LineMiddle .. "%*" + end +end + return { mode = { function() - return " " + return " " .. lvim.icons.ui.Target .. " " end, padding = { left = 0, right = 0 }, color = {}, @@ -23,9 +48,8 @@ return { }, branch = { "b:gitsigns_head", - icon = " ", + icon = branch, color = { gui = "bold" }, - cond = conditions.hide_in_width, }, filename = { "filename", @@ -35,7 +59,12 @@ return { diff = { "diff", source = diff_source, - symbols = { added = "  ", modified = " ", removed = " " }, + symbols = { + added = lvim.icons.git.LineAdded .. " ", + modified = lvim.icons.git.LineModified .. " ", + removed = lvim.icons.git.LineRemoved .. " ", + }, + padding = { left = 2, right = 1 }, diff_color = { added = { fg = colors.green }, modified = { fg = colors.yellow }, @@ -49,7 +78,9 @@ return { if vim.bo.filetype == "python" then local venv = os.getenv "CONDA_DEFAULT_ENV" or os.getenv "VIRTUAL_ENV" if venv then - return string.format("  (%s)", utils.env_cleanup(venv)) + local icons = require "nvim-web-devicons" + local py_icon, _ = icons.get_icon ".py" + return string.format(" " .. py_icon .. " (%s)", utils.env_cleanup(venv)) end end return "" @@ -60,12 +91,17 @@ return { diagnostics = { "diagnostics", sources = { "nvim_diagnostic" }, - symbols = { error = " ", warn = " ", info = " ", hint = " " }, - cond = conditions.hide_in_width, + symbols = { + error = lvim.icons.diagnostics.BoldError .. " ", + warn = lvim.icons.diagnostics.BoldWarning .. " ", + info = lvim.icons.diagnostics.BoldInformation .. " ", + hint = lvim.icons.diagnostics.BoldHint .. " ", + }, + -- cond = conditions.hide_in_width, }, treesitter = { function() - return "" + return lvim.icons.ui.Tree end, color = function() local buf = vim.api.nvim_get_current_buf() @@ -87,12 +123,17 @@ return { end local buf_ft = vim.bo.filetype local buf_client_names = {} + local copilot_active = false -- add client for _, client in pairs(buf_clients) do - if client.name ~= "null-ls" then + if client.name ~= "null-ls" and client.name ~= "copilot" then table.insert(buf_client_names, client.name) end + + if client.name == "copilot" then + copilot_active = true + end end -- add formatter @@ -106,26 +147,35 @@ return { vim.list_extend(buf_client_names, supported_linters) local unique_client_names = vim.fn.uniq(buf_client_names) - return "[" .. table.concat(unique_client_names, ", ") .. "]" + + local language_servers = "[" .. table.concat(unique_client_names, ", ") .. "]" + + if copilot_active then + language_servers = language_servers .. "%#SLCopilot#" .. " " .. lvim.icons.git.Octoface .. "%*" + end + + return language_servers end, + separator = separator, color = { gui = "bold" }, cond = conditions.hide_in_width, }, - location = { "location", cond = conditions.hide_in_width, color = {} }, - progress = { "progress", cond = conditions.hide_in_width, color = {} }, + location = { "location", color = location_color }, + progress = { + "progress", + fmt = function() + return "%P/%L" + end, + color = {}, + }, + spaces = { function() - if not vim.api.nvim_buf_get_option(0, "expandtab") then - return "Tab size: " .. vim.api.nvim_buf_get_option(0, "tabstop") .. " " - end - local size = vim.api.nvim_buf_get_option(0, "shiftwidth") - if size == 0 then - size = vim.api.nvim_buf_get_option(0, "tabstop") - end - return "Spaces: " .. size .. " " + local shiftwidth = vim.api.nvim_buf_get_option(0, "shiftwidth") + return lvim.icons.ui.Tab .. " " .. shiftwidth end, - cond = conditions.hide_in_width, - color = {}, + separator = separator, + padding = 1, }, encoding = { "o:encoding", @@ -133,7 +183,7 @@ return { color = {}, cond = conditions.hide_in_width, }, - filetype = { "filetype", cond = conditions.hide_in_width }, + filetype = { "filetype", cond = nil, padding = { left = 1, right = 1 } }, scrollbar = { function() local current_line = vim.fn.line "." @@ -144,7 +194,7 @@ return { return chars[index] end, padding = { left = 0, right = 0 }, - color = { fg = colors.yellow, bg = colors.bg }, + color = "SLProgress", cond = nil, }, } diff --git a/lua/lvim/core/lualine/conditions.lua b/lua/lvim/core/lualine/conditions.lua index 6e120b26..42d52a83 100644 --- a/lua/lvim/core/lualine/conditions.lua +++ b/lua/lvim/core/lualine/conditions.lua @@ -1,11 +1,11 @@ -local window_width_limit = 70 +local window_width_limit = 100 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 + return vim.o.columns > window_width_limit end, -- check_git_workspace = function() -- local filepath = vim.fn.expand "%:p:h" diff --git a/lua/lvim/core/lualine/init.lua b/lua/lvim/core/lualine/init.lua index e041e8a8..0ee35c04 100644 --- a/lua/lvim/core/lualine/init.lua +++ b/lua/lvim/core/lualine/init.lua @@ -9,7 +9,7 @@ M.config = function() section_separators = nil, theme = nil, disabled_filetypes = nil, - globalstatus = false, + globalstatus = true, }, sections = { lualine_a = nil, @@ -34,16 +34,19 @@ M.config = function() end M.setup = function() - -- avoid running in headless mode since it's harder to detect failures if #vim.api.nvim_list_uis() == 0 then local Log = require "lvim.core.log" Log:debug "headless mode detected, skipping running setup for lualine" return end + local status_ok, lualine = pcall(require, "lualine") + if not status_ok then + return + end + require("lvim.core.lualine.styles").update() - local lualine = require "lualine" lualine.setup(lvim.builtin.lualine) if lvim.builtin.lualine.on_config_done then diff --git a/lua/lvim/core/lualine/styles.lua b/lua/lvim/core/lualine/styles.lua index 8991d9d9..81dbbabb 100644 --- a/lua/lvim/core/lualine/styles.lua +++ b/lua/lvim/core/lualine/styles.lua @@ -11,6 +11,7 @@ styles.none = { style = "none", options = { theme = "auto", + globalstatus = true, icons_enabled = lvim.use_icons, component_separators = { left = "", right = "" }, section_separators = { left = "", right = "" }, @@ -40,9 +41,16 @@ styles.default = { style = "default", options = { theme = "auto", + globalstatus = true, icons_enabled = lvim.use_icons, - component_separators = { left = "", right = "" }, - section_separators = { left = "", right = "" }, + component_separators = { + left = lvim.icons.ui.DividerRight, + right = lvim.icons.ui.DividerLeft, + }, + section_separators = { + left = lvim.icons.ui.BoldDividerRight, + right = lvim.icons.ui.BoldDividerLeft, + }, disabled_filetypes = {}, }, sections = { @@ -69,10 +77,11 @@ styles.lvim = { style = "lvim", options = { theme = "auto", + globalstatus = true, icons_enabled = lvim.use_icons, component_separators = { left = "", right = "" }, section_separators = { left = "", right = "" }, - disabled_filetypes = { "alpha", "NvimTree", "Outline" }, + disabled_filetypes = { "alpha" }, }, sections = { lualine_a = { @@ -80,7 +89,6 @@ styles.lvim = { }, lualine_b = { components.branch, - components.filename, }, lualine_c = { components.diff, @@ -88,27 +96,39 @@ styles.lvim = { }, lualine_x = { components.diagnostics, - components.treesitter, components.lsp, + components.spaces, components.filetype, }, - lualine_y = {}, + lualine_y = { components.location }, lualine_z = { - components.scrollbar, + components.progress, }, }, inactive_sections = { lualine_a = { - "filename", + components.mode, + }, + lualine_b = { + components.branch, + }, + lualine_c = { + components.diff, + components.python_env, + }, + lualine_x = { + components.diagnostics, + components.lsp, + components.spaces, + components.filetype, + }, + lualine_y = { components.location }, + lualine_z = { + components.progress, }, - lualine_b = {}, - lualine_c = {}, - lualine_x = {}, - lualine_y = {}, - lualine_z = {}, }, tabline = {}, - extensions = { "nvim-tree" }, + extensions = {}, } function M.get_style(style) @@ -132,6 +152,14 @@ function M.update() local style = M.get_style(lvim.builtin.lualine.style) lvim.builtin.lualine = vim.tbl_deep_extend("keep", lvim.builtin.lualine, style) + + local color_template = vim.g.colors_name or lvim.colorscheme + local theme_supported, template = pcall(function() + require("lualine.utils.loader").load_theme(color_template) + end) + if theme_supported and template then + lvim.builtin.lualine.options.theme = color_template + end end return M diff --git a/lua/lvim/core/mason.lua b/lua/lvim/core/mason.lua index 39be4f42..19dee633 100644 --- a/lua/lvim/core/mason.lua +++ b/lua/lvim/core/mason.lua @@ -3,6 +3,7 @@ local M = {} function M.config() lvim.builtin.mason = { ui = { + border = "rounded", keymaps = { toggle_package_expand = "", install_package = "i", @@ -30,7 +31,7 @@ function M.config() end function M.setup() - local status_ok, mason = pcall(require, "mason") + local status_ok, mason = pcall(reload, "mason") if not status_ok then return end diff --git a/lua/lvim/core/notify.lua b/lua/lvim/core/notify.lua index 2db4c4d5..b08c45a6 100644 --- a/lua/lvim/core/notify.lua +++ b/lua/lvim/core/notify.lua @@ -3,7 +3,7 @@ local M = {} local Log = require "lvim.core.log" local defaults = { - active = false, + active = true, on_config_done = nil, opts = { ---@usage Animation style one of { "fade", "slide", "fade_in_slide_out", "static" } @@ -29,11 +29,11 @@ local defaults = { ---@usage Icons for the different levels icons = { - ERROR = "", - WARN = "", - INFO = "", - DEBUG = "", - TRACE = "✎", + ERROR = lvim.icons.diagnostics.Error, + WARN = lvim.icons.diagnostics.Warning, + INFO = lvim.icons.diagnostics.Information, + DEBUG = lvim.icons.diagnostics.Debug, + TRACE = lvim.icons.diagnostics.Trace, }, }, } @@ -43,7 +43,7 @@ function M.config() defaults.opts.icons = { ERROR = "[ERROR]", WARN = "[WARNING]", - INFO = "[INFo]", + INFO = "[INFO]", DEBUG = "[DEBUG]", TRACE = "[TRACE]", } @@ -58,7 +58,11 @@ function M.setup() end local opts = lvim.builtin.notify and lvim.builtin.notify.opts or defaults - local notify = require "notify" + + local status_ok, notify = pcall(require, "notify") + if not status_ok then + return + end notify.setup(opts) vim.notify = notify diff --git a/lua/lvim/core/nvimtree.lua b/lua/lvim/core/nvimtree.lua index 15e80e85..199279a6 100644 --- a/lua/lvim/core/nvimtree.lua +++ b/lua/lvim/core/nvimtree.lua @@ -6,34 +6,24 @@ function M.config() active = true, on_config_done = nil, setup = { - disable_netrw = true, - hijack_netrw = true, - open_on_setup = false, - open_on_setup_file = false, - sort_by = "name", - ignore_buffer_on_setup = false, ignore_ft_on_setup = { "startify", "dashboard", "alpha", }, - auto_reload_on_write = true, - hijack_unnamed_buffer_when_opening = false, + auto_reload_on_write = false, hijack_directories = { - enable = true, - auto_open = true, + enable = false, }, - open_on_tab = false, - hijack_cursor = false, - update_cwd = false, + update_cwd = true, diagnostics = { enable = lvim.use_icons, show_on_dirs = false, icons = { - hint = "", - info = "", - warning = "", - error = "", + hint = lvim.icons.diagnostics.BoldHint, + info = lvim.icons.diagnostics.BoldInformation, + warning = lvim.icons.diagnostics.BoldWarning, + error = lvim.icons.diagnostics.BoldError, }, }, update_focused_file = { @@ -52,10 +42,8 @@ function M.config() }, view = { width = 30, - height = 30, hide_root_folder = false, side = "left", - preserve_window_proportions = false, mappings = { custom_only = false, list = {}, @@ -83,27 +71,28 @@ function M.config() folder_arrow = lvim.use_icons, }, glyphs = { - default = "", - symlink = "", + default = lvim.icons.ui.Text, + symlink = lvim.icons.ui.FileSymlink, git = { - unstaged = "", - staged = "S", - unmerged = "", - renamed = "➜", - deleted = "", - untracked = "U", - ignored = "◌", + deleted = lvim.icons.git.FileDeleted, + ignored = lvim.icons.git.FileIgnored, + renamed = lvim.icons.git.FileRenamed, + staged = lvim.icons.git.FileStaged, + unmerged = lvim.icons.git.FileUnmerged, + unstaged = lvim.icons.git.FileUnstaged, + untracked = lvim.icons.git.FileUntracked, }, folder = { - default = "", - open = "", - empty = "", - empty_open = "", - symlink = "", + default = lvim.icons.ui.Folder, + empty = lvim.icons.ui.EmptyFolder, + empty_open = lvim.icons.ui.EmptyFolderOpen, + open = lvim.icons.ui.FolderOpen, + symlink = lvim.icons.ui.FolderSymlink, }, }, }, highlight_git = true, + group_empty = false, root_folder_modifier = ":t", }, filters = { @@ -158,6 +147,24 @@ function M.setup() return end + local status_ok_1, utils = pcall(require, "nvim-tree.utils") + if not status_ok_1 then + return + end + + local function notify_level() + return function(msg) + vim.schedule(function() + vim.api.nvim_echo({ { msg, "WarningMsg" } }, false, {}) + end) + end + end + + utils.notify.warn = notify_level(vim.log.levels.WARN) + utils.notify.error = notify_level(vim.log.levels.ERROR) + utils.notify.info = notify_level(vim.log.levels.INFO) + utils.notify.debug = notify_level(vim.log.levels.DEBUG) + if lvim.builtin.nvimtree._setup_called then Log:debug "ignoring repeated setup call for nvim-tree, see kyazdani42/nvim-tree.lua#1308" return diff --git a/lua/lvim/core/project.lua b/lua/lvim/core/project.lua index e33d8720..c3734a16 100644 --- a/lua/lvim/core/project.lua +++ b/lua/lvim/core/project.lua @@ -22,7 +22,7 @@ function M.config() detection_methods = { "pattern" }, ---@usage patterns used to detect root dir, when **"pattern"** is in detection_methods - patterns = { ".git", "_darcs", ".hg", ".bzr", ".svn", "Makefile", "package.json" }, + patterns = { ".git", "_darcs", ".hg", ".bzr", ".svn", "Makefile", "package.json", "pom.xml" }, ---@ Show hidden files in telescope when searching for files in a project show_hidden = false, diff --git a/lua/lvim/core/telescope.lua b/lua/lvim/core/telescope.lua index f556913b..77bf552d 100644 --- a/lua/lvim/core/telescope.lua +++ b/lua/lvim/core/telescope.lua @@ -1,5 +1,63 @@ local M = {} +local function get_pickers(actions) + return { + find_files = { + theme = "dropdown", + hidden = true, + previewer = false, + }, + live_grep = { + --@usage don't include the filename in the search results + only_sort_text = true, + theme = "dropdown", + }, + grep_string = { + only_sort_text = true, + theme = "dropdown", + }, + buffers = { + theme = "dropdown", + previewer = false, + initial_mode = "normal", + mappings = { + i = { + [""] = actions.delete_buffer, + }, + n = { + ["dd"] = actions.delete_buffer, + }, + }, + }, + planets = { + show_pluto = true, + show_moon = true, + }, + git_files = { + theme = "dropdown", + hidden = true, + previewer = false, + show_untracked = true, + }, + lsp_references = { + theme = "dropdown", + initial_mode = "normal", + }, + lsp_definitions = { + theme = "dropdown", + initial_mode = "normal", + }, + lsp_declarations = { + theme = "dropdown", + initial_mode = "normal", + }, + lsp_implementations = { + theme = "dropdown", + initial_mode = "normal", + }, + } +end + function M.config() -- Define this minimal config so that it's available if telescope is not yet available. @@ -15,8 +73,8 @@ function M.config() end lvim.builtin.telescope = vim.tbl_extend("force", lvim.builtin.telescope, { defaults = { - prompt_prefix = " ", - selection_caret = " ", + prompt_prefix = lvim.icons.ui.Telescope .. " ", + selection_caret = lvim.icons.ui.Forward .. " ", entry_prefix = " ", initial_mode = "insert", selection_strategy = "reset", @@ -47,6 +105,7 @@ function M.config() "--hidden", "--glob=!.git/", }, + ---@usage Mappings are fully customizable. Many familiar mapping patterns are setup as defaults. mappings = { i = { [""] = actions.move_selection_next, @@ -63,23 +122,16 @@ function M.config() [""] = actions.smart_send_to_qflist + actions.open_qflist, }, }, + pickers = get_pickers(actions), file_ignore_patterns = {}, - path_display = { shorten = 5 }, + path_display = { "smart" }, winblend = 0, border = {}, borderchars = { "─", "│", "─", "│", "╭", "╮", "╯", "╰" }, color_devicons = true, set_env = { ["COLORTERM"] = "truecolor" }, -- default = nil, }, - pickers = { - find_files = { - hidden = true, - }, - live_grep = { - --@usage don't include the filename in the search results - only_sort_text = true, - }, - }, + pickers = get_pickers(actions), extensions = { fzf = { fuzzy = true, -- false will only do exact matching @@ -94,7 +146,6 @@ end function M.setup() local previewers = require "telescope.previewers" local sorters = require "telescope.sorters" - local actions = require "telescope.actions" lvim.builtin.telescope = vim.tbl_extend("keep", { file_previewer = previewers.vim_buffer_cat.new, @@ -102,23 +153,6 @@ function M.setup() qflist_previewer = previewers.vim_buffer_qflist.new, file_sorter = sorters.get_fuzzy_file, generic_sorter = sorters.get_generic_fuzzy_sorter, - ---@usage Mappings are fully customizable. Many familiar mapping patterns are setup as defaults. - mappings = { - i = { - [""] = actions.move_selection_next, - [""] = actions.move_selection_previous, - [""] = actions.close, - [""] = actions.cycle_history_next, - [""] = actions.cycle_history_prev, - [""] = actions.smart_send_to_qflist + actions.open_qflist, - [""] = actions.select_default + actions.center, - }, - n = { - [""] = actions.move_selection_next, - [""] = actions.move_selection_previous, - [""] = actions.smart_send_to_qflist + actions.open_qflist, - }, - }, }, lvim.builtin.telescope) local telescope = require "telescope" diff --git a/lua/lvim/core/telescope/custom-finders.lua b/lua/lvim/core/telescope/custom-finders.lua index 69428a44..9ab06326 100644 --- a/lua/lvim/core/telescope/custom-finders.lua +++ b/lua/lvim/core/telescope/custom-finders.lua @@ -88,11 +88,12 @@ end -- Smartly opens either git_files or find_files, depending on whether the working directory is -- contained in a Git repo. -function M.find_project_files() - local ok = pcall(builtin.git_files) +function M.find_project_files(opts) + opts = opts or {} + local ok = pcall(builtin.git_files, opts) if not ok then - builtin.find_files() + builtin.find_files(opts) end end diff --git a/lua/lvim/core/terminal.lua b/lua/lvim/core/terminal.lua index 6f543d06..006452e1 100644 --- a/lua/lvim/core/terminal.lua +++ b/lua/lvim/core/terminal.lua @@ -3,11 +3,11 @@ local Log = require "lvim.core.log" M.config = function() lvim.builtin["terminal"] = { + active = true, on_config_done = nil, -- size can be a number or function which is passed the current terminal size = 20, - -- open_mapping = [[]], - open_mapping = [[]], + open_mapping = [[]], hide_numbers = true, -- hide the number column in toggleterm buffers shade_filetypes = {}, shade_terminals = true, @@ -39,8 +39,11 @@ M.config = function() -- { exec, keymap, name} -- lvim.builtin.terminal.execs = {{}} to overwrite -- lvim.builtin.terminal.execs[#lvim.builtin.terminal.execs+1] = {"gdb", "tg", "GNU Debugger"} + -- TODO: pls add mappings in which key and refactor this execs = { - { "lazygit", "gg", "LazyGit", "float" }, + { vim.o.shell, "", "Horizontal Terminal", "horizontal", 10 }, + { vim.o.shell, "", "Vertical Terminal", "vertical", 60 }, + { vim.o.shell, "", "Float Terminal", "float", nil }, }, } end @@ -57,7 +60,7 @@ M.setup = function() -- NOTE: unable to consistently bind id/count <= 9, see #2146 count = i + 100, direction = exec[4] or lvim.builtin.terminal.direction, - size = lvim.builtin.terminal.size, + size = exec[5] or lvim.builtin.terminal.size, } M.add_exec(opts) @@ -76,14 +79,14 @@ M.add_exec = function(opts) end vim.keymap.set({ "n", "t" }, opts.keymap, function() - M._exec_toggle { cmd = opts.cmd, count = opts.count, direction = opts.direction } + M._exec_toggle { cmd = opts.cmd, count = opts.count, direction = opts.direction, size = opts.size } end, { desc = opts.label, noremap = true, silent = true }) end M._exec_toggle = function(opts) local Terminal = require("toggleterm.terminal").Terminal local term = Terminal:new { cmd = opts.cmd, count = opts.count, direction = opts.direction } - term:toggle(lvim.builtin.terminal.size, opts.direction) + term:toggle(opts.size, opts.direction) end ---Toggles a log viewer according to log.viewer.layout_config @@ -109,4 +112,24 @@ M.toggle_log_view = function(logfile) log_view:toggle() end +M.lazygit_toggle = function() + local Terminal = require("toggleterm.terminal").Terminal + local lazygit = Terminal:new { + cmd = "lazygit", + hidden = true, + direction = "float", + float_opts = { + border = "none", + width = 100000, + height = 100000, + }, + on_open = function(_) + vim.cmd "startinsert!" + end, + on_close = function(_) end, + count = 99, + } + lazygit:toggle() +end + return M diff --git a/lua/lvim/core/theme.lua b/lua/lvim/core/theme.lua new file mode 100644 index 00000000..0f960d3d --- /dev/null +++ b/lua/lvim/core/theme.lua @@ -0,0 +1,113 @@ +local Log = require "lvim.core.log" + +local M = {} + +M.config = function() + lvim.builtin.theme = { + name = "tokyonight", + options = { + on_highlights = function(hl, c) + hl.IndentBlanklineContextChar = { + fg = c.dark5, + } + hl.TSConstructor = { + fg = c.blue1, + } + hl.TSTagDelimiter = { + fg = c.dark5, + } + -- local prompt = "#2d3149" + -- hl.TelescopeNormal = { + -- bg = c.bg_dark, + -- fg = c.fg_dark, + -- } + -- hl.TelescopeBorder = { + -- bg = c.bg_dark, + -- fg = c.bg_dark, + -- } + -- hl.TelescopePromptNormal = { + -- bg = prompt, + -- } + -- hl.TelescopePromptBorder = { + -- bg = prompt, + -- fg = prompt, + -- } + -- hl.TelescopePromptTitle = { + -- bg = prompt, + -- fg = prompt, + -- } + -- hl.TelescopePreviewTitle = { + -- bg = c.bg_dark, + -- fg = c.bg_dark, + -- } + -- hl.TelescopeResultsTitle = { + -- bg = c.bg_dark, + -- fg = c.bg_dark, + -- } + end, + style = "night", -- The theme comes in three styles, `storm`, a darker variant `night` and `day` + transparent = lvim.transparent_window, -- Enable this to disable setting the background color + terminal_colors = true, -- Configure the colors used when opening a `:terminal` in Neovim + styles = { + -- Style to be applied to different syntax groups + -- Value is any valid attr-list value for `:help nvim_set_hl` + comments = { italic = true }, + keywords = { italic = true }, + functions = {}, + variables = {}, + -- Background styles. Can be "dark", "transparent" or "normal" + sidebars = "dark", -- style for sidebars, see below + floats = "dark", -- style for floating windows + }, + -- Set a darker background on sidebar-like windows. For example: `["qf", "vista_kind", "terminal", "packer"]` + sidebars = { + "qf", + "vista_kind", + "terminal", + "packer", + "spectre_panel", + "NeogitStatus", + "help", + }, + day_brightness = 0.3, -- Adjusts the brightness of the colors of the **Day** style. Number between 0 and 1, from dull to vibrant colors + hide_inactive_statusline = false, -- Enabling this option, will hide inactive statuslines and replace them with a thin border instead. Should work with the standard **StatusLine** and **LuaLine**. + dim_inactive = false, -- dims inactive windows + lualine_bold = false, -- When `true`, section headers in the lualine theme will be bold + use_background = true, -- can be light/dark/auto. When auto, background will be set to vim.o.background + }, + } + local status_ok, theme = pcall(require, "tokyonight") + if not status_ok then + return + end + + theme.setup(lvim.builtin.theme.options) +end + +M.setup = function() + -- avoid running in headless mode since it's harder to detect failures + if #vim.api.nvim_list_uis() == 0 then + Log:debug "headless mode detected, skipping running setup for lualine" + return + end + + local status_ok, theme = pcall(require, "tokyonight") + if status_ok and theme then + theme.setup(lvim.builtin.theme.options) + end + + -- ref: https://github.com/neovim/neovim/issues/18201#issuecomment-1104754564 + local colors = vim.api.nvim_get_runtime_file(("colors/%s.*"):format(lvim.colorscheme), false) + if #colors == 0 then + Log:warn(string.format("Could not find '%s' colorscheme", lvim.colorscheme)) + lvim.colorscheme = "tokyonight" + end + + vim.g.colors_name = lvim.colorscheme + vim.cmd("colorscheme " .. lvim.colorscheme) + + require("lvim.core.lualine").setup() + require("lvim.core.lir").icon_setup() +end + +return M diff --git a/lua/lvim/core/which-key.lua b/lua/lvim/core/which-key.lua index 2301943f..55e3aae0 100644 --- a/lua/lvim/core/which-key.lua +++ b/lua/lvim/core/which-key.lua @@ -6,8 +6,8 @@ M.config = function() 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 in INSERT mode + marks = false, -- shows a list of your marks on ' and ` + registers = false, -- shows your registers on " in NORMAL or in INSERT mode -- the presets plugin, adds help for a bunch of default keybindings in Neovim -- No actual key bindings are created presets = { @@ -15,16 +15,16 @@ M.config = function() motions = false, -- adds help for motions text_objects = false, -- help for text objects triggered after entering an operator windows = false, -- default bindings on - 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 + nav = false, -- misc bindings to work with windows + z = false, -- bindings for folds, spelling and others prefixed with z + g = false, -- 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 + breadcrumb = lvim.icons.ui.DoubleChevronRight, -- symbol used in the command line area that shows your active key combo + separator = lvim.icons.ui.BoldArrowRight, -- symbol used between a key and it's label + group = lvim.icons.ui.Plus, -- symbol prepended to a group }, popup_mappings = { scroll_down = "", -- binding to scroll down inside the popup @@ -130,8 +130,9 @@ M.config = function() -- " Debugging g = { name = "Git", - j = { "lua require 'gitsigns'.next_hunk()", "Next Hunk" }, - k = { "lua require 'gitsigns'.prev_hunk()", "Prev Hunk" }, + g = { "lua require 'lvim.core.terminal'.lazygit_toggle()", "Lazygit" }, + j = { "lua require 'gitsigns'.next_hunk({navigation_message = false})", "Next Hunk" }, + k = { "lua require 'gitsigns'.prev_hunk({navigation_message = false})", "Prev Hunk" }, l = { "lua require 'gitsigns'.blame_line()", "Blame" }, p = { "lua require 'gitsigns'.preview_hunk()", "Preview Hunk" }, r = { "lua require 'gitsigns'.reset_hunk()", "Reset Hunk" }, @@ -170,12 +171,6 @@ M.config = function() "Prev Diagnostic", }, l = { vim.lsp.codelens.run, "CodeLens Action" }, - p = { - name = "Peek", - d = { "lua require('lvim.lsp.peek').Peek('definition')", "Definition" }, - t = { "lua require('lvim.lsp.peek').Peek('typeDefinition')", "Type Definition" }, - i = { "lua require('lvim.lsp.peek').Peek('implementation')", "Implementation" }, - }, q = { vim.diagnostic.setloclist, "Quickfix" }, r = { vim.lsp.buf.rename, "Rename" }, s = { "Telescope lsp_document_symbols", "Document Symbols" }, diff --git a/lua/lvim/icons.lua b/lua/lvim/icons.lua new file mode 100644 index 00000000..d0f0cf69 --- /dev/null +++ b/lua/lvim/icons.lua @@ -0,0 +1,154 @@ +return { + kind = { + Array = "", + Boolean = "蘒", + Class = "", + Color = "", + Constant = "", + Constructor = "", + Enum = "", + EnumMember = "", + Event = "", + Field = "", + File = "", + Folder = "", + Function = "", + Interface = "", + Key = "", + Keyword = "", + Method = "", + Module = "", + Namespace = "", + Null = "ﳠ", + Number = "", + Object = "", + Operator = "", + Package = "", + Property = "", + Reference = "", + Snippet = "", + String = "", + Struct = "", + Text = "", + TypeParameter = "", + Unit = "", + Value = "", + Variable = "", + }, + git = { + LineAdded = "", + LineModified = "", + LineRemoved = "", + FileDeleted = "", + FileIgnored = "◌", + FileRenamed = "➜", + FileStaged = "S", + FileUnmerged = "", + FileUnstaged = "", + FileUntracked = "U", + Diff = "", + Repo = "", + Octoface = "", + Branch = "", + }, + ui = { + ArrowCircleDown = "", + ArrowCircleLeft = "", + ArrowCircleRight = "", + ArrowCircleUp = "", + BoldArrowDown = "", + BoldArrowLeft = "", + BoldArrowRight = "", + BoldArrowUp = "", + BoldClose = "", + BoldDividerLeft = "", + BoldDividerRight = "", + BoldLineLeft = "▎", + BookMark = "", + BoxChecked = "", + Bug = "", + Stacks = " ", + Scopes = "", + Watches = "", + DebugConsole = " ", + Calendar = "", + Check = "", + ChevronRight = ">", + ChevronShortDown = "", + ChevronShortLeft = "", + ChevronShortRight = "", + ChevronShortUp = "", + Circle = "", + Close = "", + CloudDownload = "", + Code = "", + Comment = "", + Dashboard = "", + DividerLeft = "", + DividerRight = "", + DoubleChevronRight = "»", + Ellipsis = "…", + EmptyFolder = "", + EmptyFolderOpen = "", + File = "", + FileSymlink = "", + Files = "", + FindFile = "", + FindText = "", + Fire = "", + Folder = "", + FolderOpen = "", + FolderSymlink = "", + Forward = "", + Gear = "", + History = "", + Lightbulb = "", + LineLeft = "▏", + LineMiddle = "│", + List = "", + Lock = "", + NewFile = "", + Note = "", + Package = "", + Pencil = "", + Plus = "", + Project = "", + Search = "", + SignIn = "", + SignOut = "", + Tab = "", + Table = "", + Target = "", + Telescope = "", + Text = "", + Tree = "", + Triangle = "契", + TriangleShortArrowDown = "", + TriangleShortArrowLeft = "", + TriangleShortArrowRight = "", + TriangleShortArrowUp = "", + }, + diagnostics = { + BoldError = "", + Error = "", + BoldWarning = "", + Warning = "", + BoldInformation = "", + Information = "", + BoldQuestion = "", + Question = "", + BoldHint = "", + Hint = "", + Debug = "", + Trace = "✎", + }, + misc = { + Robot = "ﮧ", + Squirrel = "", + Tag = "", + Watch = "", + Smiley = "ﲃ", + Package = "", + CircuitBoard = "", + }, +} diff --git a/lua/lvim/impatient.lua b/lua/lvim/impatient.lua index fe26b940..beb3862a 100644 --- a/lua/lvim/impatient.lua +++ b/lua/lvim/impatient.lua @@ -1,5 +1,4 @@ -- modified version from https://github.com/lewis6991/impatient.nvim - local vim = vim local api = vim.api local uv = vim.loop @@ -7,66 +6,96 @@ local _loadfile = loadfile local get_runtime = api.nvim__get_runtime local fs_stat = uv.fs_stat local mpack = vim.mpack +local loadlib = package.loadlib -local appdir = os.getenv "APPDIR" +local std_cache = vim.fn.stdpath "cache" -local M = { +local sep +if jit.os == "Windows" then + sep = "\\" +else + sep = "/" +end + +local std_dirs = { + [""] = os.getenv "APPDIR", + [""] = os.getenv "VIMRUNTIME", + [""] = vim.fn.stdpath "data", + [""] = vim.fn.stdpath "config", + [""] = get_lvim_base_dir(), + [""] = get_runtime_dir(), + [""] = get_config_dir(), +} + +local function modpath_mangle(modpath) + for name, dir in pairs(std_dirs) do + modpath = modpath:gsub(dir, name) + end + return modpath +end + +local function modpath_unmangle(modpath) + for name, dir in pairs(std_dirs) do + modpath = modpath:gsub(name, dir) + end + return modpath +end + +-- Overridable by user +local default_config = { + chunks = { + enable = true, + path = std_cache .. sep .. "luacache_chunks", + }, + modpaths = { + enable = true, + path = std_cache .. sep .. "luacache_modpaths", + }, +} + +-- State used internally +local default_state = { chunks = { cache = {}, profile = nil, dirty = false, - path = vim.fn.stdpath "cache" .. "/luacache_chunks", + get = function(self, path) + return self.cache[modpath_mangle(path)] + end, + set = function(self, path, chunk) + self.cache[modpath_mangle(path)] = chunk + end, }, modpaths = { cache = {}, profile = nil, dirty = false, - path = vim.fn.stdpath "cache" .. "/luacache_modpaths", + get = function(self, mod) + if self.cache[mod] then + return modpath_unmangle(self.cache[mod]) + end + end, + set = function(self, mod, path) + self.cache[mod] = modpath_mangle(path) + end, }, log = {}, } +---@diagnostic disable-next-line: undefined-field +local M = vim.tbl_deep_extend("keep", _G.__luacache_config or {}, default_config, default_state) _G.__luacache = M -if not get_runtime then - -- nvim 0.5 compat - get_runtime = function(paths, all, _) - local r = {} - for _, path in ipairs(paths) do - local found = api.nvim_get_runtime_file(path, all) - for i = 1, #found do - r[#r + 1] = found[i] - end - end - return r - end -end - local function log(...) M.log[#M.log + 1] = table.concat({ string.format(...) }, " ") end -function M.print_log() +local function print_log() for _, l in ipairs(M.log) do print(l) end end -function M.enable_profile() - local P = require "lvim.impatient.profile" - - M.chunks.profile = {} - M.modpaths.profile = {} - - P.setup(M.modpaths.profile) - - M.print_profile = function() - P.print_profile(M) - end - - vim.cmd [[command! LuaCacheProfile lua _G.__luacache.print_profile()]] -end - local function hash(modpath) local stat = fs_stat(modpath) if stat then @@ -75,20 +104,6 @@ local function hash(modpath) error("Could not hash " .. modpath) end -local function modpath_mangle(modpath) - if appdir then - modpath = modpath:gsub(appdir, "/$APPDIR") - end - return modpath -end - -local function modpath_unmangle(modpath) - if appdir then - modpath = modpath:gsub("/$APPDIR", appdir) - end - return modpath -end - local function profile(m, entry, name, loader) if m.profile then local mp = m.profile @@ -107,18 +122,41 @@ local function mprofile(mod, name, loader) end local function cprofile(path, name, loader) + if M.chunks.profile then + path = modpath_mangle(path) + end profile(M.chunks, path, name, loader) end -local function get_runtime_file(basename, paths) +function M.enable_profile() + local P = require "lvim.impatient.profile" + + M.chunks.profile = {} + M.modpaths.profile = {} + + loadlib = function(path, fun) + cprofile(path, "load_start") + local f, err = package.loadlib(path, fun) + cprofile(path, "load_end", "standard") + return f, err + end + + P.setup(M.modpaths.profile) + + api.nvim_create_user_command("LuaCacheProfile", function() + P.print_profile(M, std_dirs) + end, {}) +end + +local function get_runtime_file_from_parent(basename, paths) -- Look in the cache to see if we have already loaded a parent module. -- If we have then try looking in the parents directory first. - local parents = vim.split(basename, "/") + local parents = vim.split(basename, sep) for i = #parents, 1, -1 do - local parent = table.concat(vim.list_slice(parents, 1, i), "/") - local ppath = M.modpaths.cache[parent] + local parent = table.concat(vim.list_slice(parents, 1, i), sep) + local ppath = M.modpaths:get(parent) if ppath then - if ppath:sub(-9) == "/init.lua" then + if ppath:sub(-9) == (sep .. "init.lua") then ppath = ppath:sub(1, -10) -- a/b/init.lua -> a/b else ppath = ppath:sub(1, -5) -- a/b.lua -> a/b @@ -126,38 +164,71 @@ local function get_runtime_file(basename, paths) for _, path in ipairs(paths) do -- path should be of form 'a/b/c.lua' or 'a/b/c/init.lua' - local modpath = ppath .. "/" .. path:sub(#("lua/" .. parent) + 2) + local modpath = ppath .. sep .. path:sub(#("lua" .. sep .. parent) + 2) if fs_stat(modpath) then return modpath, "cache(p)" end end end end +end - -- What Neovim does by default; slowest - local modpath = get_runtime(paths, false, { is_lua = true })[1] - return modpath, "standard" +local rtp = vim.split(vim.o.rtp, ",") + +-- Make sure modpath is in rtp and that modpath is in paths. +local function validate_modpath(modpath, paths) + local match = false + for _, p in ipairs(paths) do + if vim.endswith(modpath, p) then + match = true + break + end + end + if not match then + return false + end + for _, dir in ipairs(rtp) do + if vim.startswith(modpath, dir) then + return fs_stat(modpath) ~= nil + end + end + return false end local function get_runtime_file_cached(basename, paths) + local modpath, loader local mp = M.modpaths - if mp.cache[basename] then - local modpath = mp.cache[basename] - if fs_stat(modpath) then - mprofile(basename, "resolve_end", "cache") - return modpath + if mp.enable then + local modpath_cached = mp:get(basename) + if modpath_cached then + modpath, loader = modpath_cached, "cache" + else + modpath, loader = get_runtime_file_from_parent(basename, paths) + end + + if modpath and not validate_modpath(modpath, paths) then + modpath = nil + + -- Invalidate + mp.cache[basename] = nil + mp.dirty = true end - mp.cache[basename] = nil - mp.dirty = true end - local modpath, loader = get_runtime_file(basename, paths) + if not modpath then + -- What Neovim does by default; slowest + modpath, loader = get_runtime(paths, false, { is_lua = true })[1], "standard" + end + if modpath then mprofile(basename, "resolve_end", loader) - log("Creating cache for module %s", basename) - mp.cache[basename] = modpath_mangle(modpath) - mp.dirty = true + if mp.enable and loader ~= "cache" then + log("Creating cache for module %s", basename) + mp:set(basename, modpath) + mp.dirty = true + end end + return modpath end @@ -168,8 +239,12 @@ local function extract_basename(pats) for _, pat in ipairs(pats) do for i, npat in ipairs { -- Ordered by most specific - "lua/(.*)/init%.lua", - "lua/(.*)%.lua", + "lua" + .. sep + .. "(.*)" + .. sep + .. "init%.lua", + "lua" .. sep .. "(.*)%.lua", } do local m = pat:match(npat) if i == 2 and m and m:sub(-4) == "init" then @@ -211,8 +286,8 @@ end -- Copied from neovim/src/nvim/lua/vim.lua with two lines changed local function load_package(name) - local basename = name:gsub("%.", "/") - local paths = { "lua/" .. basename .. ".lua", "lua/" .. basename .. "/init.lua" } + local basename = name:gsub("%.", sep) + local paths = { "lua" .. sep .. basename .. ".lua", "lua" .. sep .. basename .. sep .. "init.lua" } -- Original line: -- local found = vim.api.nvim__get_runtime(paths, false, {is_lua=true}) @@ -239,7 +314,7 @@ local function load_package(name) -- So "foo-bar.baz" should result in "luaopen_bar_baz" local dash = name:find("-", 1, true) local modname = dash and name:sub(dash + 1) or name - local f, err = package.loadlib(found[1], "luaopen_" .. modname:gsub("%.", "_")) + local f, err = loadlib(found[1], "luaopen_" .. modname:gsub("%.", "_")) return f or error(err) end return nil @@ -248,14 +323,16 @@ end local function load_from_cache(path) local mc = M.chunks - if not mc.cache[path] then + local cache = mc:get(path) + + if not cache then return nil, string.format("No cache for path %s", path) end - local mhash, codes = unpack(mc.cache[path]) + local mhash, codes = unpack(cache) - if mhash ~= hash(modpath_unmangle(path)) then - mc.cache[path] = nil + if mhash ~= hash(path) then + mc:set(path) mc.dirty = true return nil, string.format("Stale cache for path %s", path) end @@ -263,7 +340,7 @@ local function load_from_cache(path) local chunk = loadstring(codes) if not chunk then - mc.cache[path] = nil + mc:set(path) mc.dirty = true return nil, string.format("Cache error for path %s", path) end @@ -274,19 +351,23 @@ end local function loadfile_cached(path) cprofile(path, "load_start") - local chunk, err = load_from_cache(path) - if chunk and not err then - log("Loaded cache for path %s", path) - cprofile(path, "load_end", "cache") - return chunk + local chunk, err + + if M.chunks.enable then + chunk, err = load_from_cache(path) + if chunk and not err then + log("Loaded cache for path %s", path) + cprofile(path, "load_end", "cache") + return chunk + end + log(err) end - log(err) chunk, err = _loadfile(path) - if not err then + if not err and M.chunks.enable then log("Creating cache for path %s", path) - M.chunks.cache[modpath_mangle(path)] = { hash(path), string.dump(chunk) } + M.chunks:set(path, { hash(path), string.dump(chunk) }) M.chunks.dirty = true end @@ -296,9 +377,12 @@ end function M.save_cache() local function _save_cache(t) + if not t.enable then + return + end if t.dirty then log("Updating chunk cache file: %s", t.path) - local f = io.open(t.path, "w+b") + local f = assert(io.open(t.path, "w+b")) f:write(mpack.encode(t.cache)) f:flush() t.dirty = false @@ -308,7 +392,7 @@ function M.save_cache() _save_cache(M.modpaths) end -function M.clear_cache() +local function clear_cache() local function _clear_cache(t) t.cache = {} os.remove(t.path) @@ -319,9 +403,12 @@ end local function init_cache() local function _init_cache(t) + if not t.enable then + return + end if fs_stat(t.path) then log("Loading cache file %s", t.path) - local f = io.open(t.path, "rb") + local f = assert(io.open(t.path, "rb")) local ok ok, t.cache = pcall(function() return mpack.decode(f:read "*a") @@ -336,6 +423,10 @@ local function init_cache() end end + if not uv.fs_stat(std_cache) then + vim.fn.mkdir(std_cache, "p") + end + _init_cache(M.chunks) _init_cache(M.modpaths) end @@ -343,20 +434,42 @@ end local function setup() init_cache() + -- Usual package loaders + -- 1. package.preload + -- 2. vim._load_package + -- 3. package.path + -- 4. package.cpath + -- 5. all-in-one + -- Override default functions + for i, loader in ipairs(package.loaders) do + if loader == vim._load_package then + package.loaders[i] = load_package + break + end + end vim._load_package = load_package + vim.api.nvim__get_runtime = get_runtime_cached - -- luacheck: ignore 121 loadfile = loadfile_cached - vim.cmd [[ - augroup impatient - autocmd VimEnter,VimLeave * lua _G.__luacache.save_cache() - augroup END + local augroup = api.nvim_create_augroup("impatient", {}) - command! LuaCacheClear lua _G.__luacache.clear_cache() - command! LuaCacheLog lua _G.__luacache.print_log() - ]] + api.nvim_create_user_command("LuaCacheClear", clear_cache, {}) + api.nvim_create_user_command("LuaCacheLog", print_log, {}) + + api.nvim_create_autocmd({ "VimEnter", "VimLeave" }, { + group = augroup, + callback = M.save_cache, + }) + + api.nvim_create_autocmd("OptionSet", { + group = augroup, + pattern = "runtimepath", + callback = function() + rtp = vim.split(vim.o.rtp, ",") + end, + }) end setup() diff --git a/lua/lvim/impatient/profile.lua b/lua/lvim/impatient/profile.lua index 0ab04d65..2eafbbf2 100644 --- a/lua/lvim/impatient/profile.lua +++ b/lua/lvim/impatient/profile.lua @@ -1,12 +1,13 @@ local M = {} -local api, uv = vim.api, vim.loop +local sep +if jit.os == "Windows" then + sep = "\\" +else + sep = "/" +end -local std_data = vim.fn.stdpath "data" -local std_config = vim.fn.stdpath "config" -local vimruntime = os.getenv "VIMRUNTIME" -local lvim_runtime = get_runtime_dir() -local lvim_config = get_config_dir() +local api, uv = vim.api, vim.loop local function load_buffer(title, lines) local bufnr = api.nvim_create_buf(false, false) @@ -19,19 +20,6 @@ local function load_buffer(title, lines) api.nvim_set_current_buf(bufnr) end -local function mod_path(path) - if not path then - return "?" - end - path = path:gsub(std_data .. "/site/pack/packer/", "/") - path = path:gsub(std_data .. "/", "/") - path = path:gsub(std_config .. "/", "/") - path = path:gsub(vimruntime .. "/", "/") - path = path:gsub(lvim_runtime .. "/", "/") - path = path:gsub(lvim_config .. "/", "/") - return path -end - local function time_tostr(x) if x == 0 then return "?" @@ -51,7 +39,7 @@ local function mem_tostr(x) return string.format("%1.1f%s", x, unit) end -function M.print_profile(I) +function M.print_profile(I, std_dirs) local mod_profile = I.modpaths.profile local chunk_profile = I.chunks.profile @@ -67,42 +55,50 @@ function M.print_profile(I) for path, m in pairs(chunk_profile) do m.load = m.load_end - m.load_start m.load = m.load / 1000000 - m.path = mod_path(path) + m.path = path or "?" end local module_content_width = 0 + local unloaded = {} + for module, m in pairs(mod_profile) do - m.resolve = 0 - if m.resolve_end then - m.resolve = m.resolve_end - m.resolve_start - m.resolve = m.resolve / 1000000 - end + local module_dot = module:gsub(sep, ".") + m.module = module_dot - m.module = module:gsub("/", ".") - m.loader = m.loader or m.loader_guess - - local path = I.modpaths.cache[module] - local path_prof = chunk_profile[path] - m.path = mod_path(path) - - if path_prof then - chunk_profile[path] = nil - m.load = path_prof.load - m.ploader = path_prof.loader + if not package.loaded[module_dot] and not package.loaded[module] then + unloaded[#unloaded + 1] = m else - m.load = 0 - m.ploader = "NA" + m.resolve = 0 + if m.resolve_start and m.resolve_end then + m.resolve = m.resolve_end - m.resolve_start + m.resolve = m.resolve / 1000000 + end + + m.loader = m.loader or m.loader_guess + + local path = I.modpaths.cache[module] + local path_prof = chunk_profile[path] + m.path = path or "?" + + if path_prof then + chunk_profile[path] = nil + m.load = path_prof.load + m.ploader = path_prof.loader + else + m.load = 0 + m.ploader = "NA" + end + + total_resolve = total_resolve + m.resolve + total_load = total_load + m.load + + if #module > module_content_width then + module_content_width = #module + end + + modules[#modules + 1] = m end - - total_resolve = total_resolve + m.resolve - total_load = total_load + m.load - - if #module > module_content_width then - module_content_width = #module - end - - modules[#modules + 1] = m end table.sort(modules, function(a, b) @@ -181,6 +177,12 @@ function M.print_profile(I) end add "" + add "Standard directories:" + for alias, path in pairs(std_dirs) do + add(" %-12s -> %s", alias, path) + end + add "" + add("%s─%s┬%s─%s┐", tcwl, lcwl, tcwl, lcwl) add(title1_fmt, "Resolve", "Load") add("%s┬%s┼%s┬%s┼%s┬%s", tcwl, lcwl, tcwl, lcwl, mcwl, n) @@ -207,7 +209,17 @@ function M.print_profile(I) add(f3, p.load, p.loader, p.path) end add("%s┴%s┴%s", tcwl, lcwl, n) + end + + if #unloaded > 0 then add "" + add(n) + add "Modules which were unable to loaded" + add(n) + for _, p in ipairs(unloaded) do + lines[#lines + 1] = p.module + end + add(n) end load_buffer("Impatient Profile Report", lines) @@ -216,13 +228,12 @@ end M.setup = function(profile) local _require = require - -- luacheck: ignore 121 require = function(mod) - local basename = mod:gsub("%.", "/") + local basename = mod:gsub("%.", sep) if not profile[basename] then profile[basename] = {} profile[basename].resolve_start = uv.hrtime() - profile[basename].loader_guess = "C" + profile[basename].loader_guess = "" end return _require(mod) end @@ -232,7 +243,7 @@ M.setup = function(profile) for i = 1, #pl do local l = pl[i] pl[i] = function(mod) - local basename = mod:gsub("%.", "/") + local basename = mod:gsub("%.", sep) profile[basename].loader_guess = i == 1 and "preloader" or "loader #" .. i return l(mod) end diff --git a/lua/lvim/keymappings.lua b/lua/lvim/keymappings.lua index 82113398..d0d46fd7 100644 --- a/lua/lvim/keymappings.lua +++ b/lua/lvim/keymappings.lua @@ -31,12 +31,6 @@ local mode_adapters = { local defaults = { insert_mode = { - -- 'jk' for quitting insert mode - ["jk"] = "", - -- 'kj' for quitting insert mode - ["kj"] = "", - -- 'jj' for quitting insert mode - ["jj"] = "", -- Move current line / block with Alt-j/k ala vscode. [""] = ":m .+1==gi", -- Move current line / block with Alt-j/k ala vscode. @@ -89,10 +83,6 @@ local defaults = { }, visual_block_mode = { - -- Move selected line / block of text in visual mode - ["K"] = ":move '<-2gv-gv", - ["J"] = ":move '>+1gv-gv", - -- Move current line / block with Alt-j/k ala vscode. [""] = ":m '>+1gv-gv", [""] = ":m '<-2gv-gv", diff --git a/lua/lvim/lsp/config.lua b/lua/lvim/lsp/config.lua index 96a1b823..358e83f8 100644 --- a/lua/lvim/lsp/config.lua +++ b/lua/lvim/lsp/config.lua @@ -10,6 +10,7 @@ local skipped_servers = { "eslint", "eslintls", "golangci_lint_ls", + "gradle_ls", "graphql", "jedi_language_server", "ltex", @@ -18,10 +19,12 @@ local skipped_servers = { "psalm", "pylsp", "quick_lint_js", - "rome", "reason_ls", + "rome", + "ruby_ls", "scry", "solang", + "solc", "solidity_ls", "sorbet", "sourcekit", @@ -30,8 +33,8 @@ local skipped_servers = { "sqlls", "sqls", "stylelint_lsp", - "tflint", "svlangserver", + "tflint", "verible", "vuels", } @@ -46,10 +49,10 @@ return { signs = { active = true, values = { - { name = "DiagnosticSignError", text = "" }, - { name = "DiagnosticSignWarn", text = "" }, - { name = "DiagnosticSignHint", text = "" }, - { name = "DiagnosticSignInfo", text = "" }, + { name = "DiagnosticSignError", text = lvim.icons.diagnostics.Error }, + { name = "DiagnosticSignWarn", text = lvim.icons.diagnostics.Warning }, + { name = "DiagnosticSignHint", text = lvim.icons.diagnostics.Hint }, + { name = "DiagnosticSignInfo", text = lvim.icons.diagnostics.Info }, }, }, virtual_text = true, @@ -72,18 +75,13 @@ return { end, }, }, - document_highlight = true, + document_highlight = false, code_lens_refresh = true, float = { focusable = true, style = "minimal", border = "rounded", }, - peek = { - max_height = 15, - max_width = 30, - context = 10, - }, on_attach_callback = nil, on_init_callback = nil, automatic_configuration = { @@ -100,12 +98,6 @@ return { ["gr"] = { vim.lsp.buf.references, "Goto references" }, ["gI"] = { vim.lsp.buf.implementation, "Goto Implementation" }, ["gs"] = { vim.lsp.buf.signature_help, "show signature help" }, - ["gp"] = { - function() - require("lvim.lsp.peek").Peek "definition" - end, - "Peek definition", - }, ["gl"] = { function() local config = lvim.lsp.diagnostics.float @@ -143,7 +135,9 @@ return { }, }, null_ls = { - setup = {}, + setup = { + debug = false, + }, config = {}, }, ---@deprecated use lvim.lsp.automatic_configuration.skipped_servers instead diff --git a/lua/lvim/lsp/init.lua b/lua/lvim/lsp/init.lua index 0b361972..c8a2b22f 100644 --- a/lua/lvim/lsp/init.lua +++ b/lua/lvim/lsp/init.lua @@ -25,6 +25,11 @@ local function add_lsp_buffer_keybindings(bufnr) end function M.common_capabilities() + local status_ok, cmp_nvim_lsp = pcall(require, "cmp_nvim_lsp") + if status_ok then + return cmp_nvim_lsp.default_capabilities() + end + local capabilities = vim.lsp.protocol.make_client_capabilities() capabilities.textDocument.completion.completionItem.snippetSupport = true capabilities.textDocument.completion.completionItem.resolveSupport = { @@ -35,11 +40,6 @@ function M.common_capabilities() }, } - local status_ok, cmp_nvim_lsp = pcall(require, "cmp_nvim_lsp") - if status_ok then - capabilities = cmp_nvim_lsp.update_capabilities(capabilities) - end - return capabilities end @@ -74,6 +74,7 @@ function M.common_on_attach(client, bufnr) end add_lsp_buffer_keybindings(bufnr) add_lsp_buffer_options(bufnr) + lu.setup_document_symbols(client, bufnr) end function M.get_common_opts() diff --git a/lua/lvim/lsp/peek.lua b/lua/lvim/lsp/peek.lua deleted file mode 100644 index 65c67e92..00000000 --- a/lua/lvim/lsp/peek.lua +++ /dev/null @@ -1,157 +0,0 @@ -local M = { - floating_buf = nil, - floating_win = nil, - prev_result = nil, -} - -local function create_floating_file(location, opts) - vim.validate { - location = { location, "t" }, - opts = { opts, "t", true }, - } - - -- Set some defaults - opts = opts or {} - local close_events = opts.close_events or { "CursorMoved", "CursorMovedI", "BufHidden", "InsertCharPre" } - - -- location may be LocationLink or Location - local uri = location.targetUri or location.uri - if uri == nil then - return - end - local bufnr = vim.uri_to_bufnr(uri) - if not vim.api.nvim_buf_is_loaded(bufnr) then - vim.fn.bufload(bufnr) - end - - local range = location.targetRange or location.range - - local contents = vim.api.nvim_buf_get_lines( - bufnr, - range.start.line, - math.min( - range["end"].line + 1 + (opts.context or lvim.lsp.peek.max_height), - range.start.line + (opts.max_height or lvim.lsp.peek.max_height) - ), - false - ) - if next(contents) == nil then - vim.notify("peek: Unable to get contents of the file!", vim.log.levels.WARN) - return - end - local width, height = vim.lsp.util._make_floating_popup_size(contents, opts) - local if_nil = vim.F.if_nil - opts = vim.lsp.util.make_floating_popup_options( - if_nil(width, lvim.lsp.peek.max_width), - if_nil(height, lvim.lsp.peek.max_height), - opts - ) - -- Don't make it minimal as it is meant to be fully featured - opts["style"] = nil - - vim.api.nvim_buf_set_option(bufnr, "bufhidden", "wipe") - - local winnr = vim.api.nvim_open_win(bufnr, false, opts) - vim.api.nvim_win_set_option(winnr, "winblend", 0) - - vim.api.nvim_win_set_cursor(winnr, { range.start.line + 1, range.start.character }) - vim.api.nvim_buf_set_var(bufnr, "lsp_floating_window", winnr) - - -- Set some autocmds to close the window - vim.api.nvim_command( - string.format("autocmd %s ++once lua pcall(vim.api.nvim_win_close, %d, true)", unpack(close_events), winnr) - ) - - return bufnr, winnr -end - -local function preview_location_callback(result) - if result == nil or vim.tbl_isempty(result) then - return nil - end - - local opts = { - border = "rounded", - context = lvim.lsp.peek.context, - } - - if vim.tbl_islist(result) then - M.prev_result = result[1] - M.floating_buf, M.floating_win = create_floating_file(result[1], opts) - else - M.prev_result = result - M.floating_buf, M.floating_win = create_floating_file(result, opts) - end -end - -local function preview_location_callback_new_signature(_, result) - return preview_location_callback(result) -end - -function M.open_file() - -- Get the file currently open in the floating window - local filepath = vim.fn.expand "%:." - - if not filepath then - vim.notify("peek: Unable to open the file!", vim.log.levels.ERROR) - return - end - - -- Close the floating window - pcall(vim.api.nvim_win_close, M.floating_win, true) - - -- Edit the file - vim.cmd("edit " .. filepath) - - local winnr = vim.api.nvim_get_current_win() - - -- Set the cursor at the right position - M.set_cursor_to_prev_pos(winnr) -end - -function M.set_cursor_to_prev_pos(winnr) - -- Get position of the thing to peek at - local location = M.prev_result - local range = location.targetRange or location.range - local cursor_pos = { range.start.line + 1, range.start.character } - - -- Set the winnr to the floating window if none was passed in - winnr = winnr or M.floating_win - -- Set the cursor at the correct position in the floating window - vim.api.nvim_win_set_cursor(winnr, cursor_pos) -end - -function M.Peek(what) - -- If a window already exists, focus it at the right position! - if vim.tbl_contains(vim.api.nvim_list_wins(), M.floating_win) then - local success_1, _ = pcall(vim.api.nvim_set_current_win, M.floating_win) - if not success_1 then - vim.notify("peek: You cannot edit the current file in a preview!", vim.log.levels.ERROR) - return - end - - -- Set the cursor at the correct position in the floating window - M.set_cursor_to_prev_pos() - - vim.api.nvim_buf_set_keymap( - M.floating_buf, - "n", - "", - ":lua require('lvim.lsp.peek').open_file()", - { noremap = true, silent = true } - ) - else - -- Make a new request and then create the new window in the callback - local params = vim.lsp.util.make_position_params() - local preview_callback = preview_location_callback_new_signature - local success, _ = pcall(vim.lsp.buf_request, 0, "textDocument/" .. what, params, preview_callback) - if not success then - vim.notify( - 'peek: Error calling LSP method "textDocument/' .. what .. '". The current language lsp might not support it.', - vim.log.levels.ERROR - ) - end - end -end - -return M diff --git a/lua/lvim/lsp/providers/sumneko_lua.lua b/lua/lvim/lsp/providers/sumneko_lua.lua index 6cd78157..2caa23b6 100644 --- a/lua/lvim/lsp/providers/sumneko_lua.lua +++ b/lua/lvim/lsp/providers/sumneko_lua.lua @@ -1,32 +1,59 @@ -local dev_opts = { +local default_workspace = { library = { - vimruntime = true, -- runtime path - types = true, -- full signature, docs and completion of vim.api, vim.treesitter, vim.lsp and others - -- plugins = true, -- installed opt or start plugins in packpath - -- you can also specify the list of plugins to make available as a workspace library - plugins = { "plenary.nvim" }, + vim.fn.expand "$VIMRUNTIME", + get_lvim_base_dir(), + require("neodev.config").types(), }, - override = nil, -- function(root_dir, options) end, + + maxPreload = 5000, + preloadFileSize = 10000, } -local lua_dev_loaded, lua_dev = pcall(require, "lua-dev") -if lua_dev_loaded then - lua_dev.setup(dev_opts) +local add_packages_to_workspace = function(packages, config) + -- config.settings.Lua = config.settings.Lua or { workspace = default_workspace } + local runtimedirs = vim.api.nvim__get_runtime({ "lua" }, true, { is_lua = true }) + local workspace = config.settings.Lua.workspace + for _, v in pairs(runtimedirs) do + for _, pack in ipairs(packages) do + if v:match(pack) and not vim.tbl_contains(workspace.library, v) then + table.insert(workspace.library, v) + end + end + end end +local lspconfig = require "lspconfig" + +local make_on_new_config = function(on_new_config, _) + return lspconfig.util.add_hook_before(on_new_config, function(new_config, _) + local server_name = new_config.name + + if server_name ~= "sumneko_lua" then + return + end + local plugins = { "plenary.nvim", "telescope.nvim", "nvim-treesitter", "LuaSnip" } + add_packages_to_workspace(plugins, new_config) + end) +end + +lspconfig.util.default_config = vim.tbl_extend("force", lspconfig.util.default_config, { + on_new_config = make_on_new_config(lspconfig.util.default_config.on_new_config), +}) + local opts = { settings = { Lua = { - diagnostics = { - globals = { "vim", "lvim", "packer_plugins" }, - }, - workspace = { - library = { - [require("lvim.utils").join_paths(get_runtime_dir(), "lvim", "lua")] = true, + telemetry = { enable = false }, + runtime = { + version = "LuaJIT", + special = { + reload = "require", }, - maxPreload = 100000, - preloadFileSize = 10000, }, + diagnostics = { + globals = { "vim", "lvim", "packer_plugins", "reload" }, + }, + workspace = default_workspace, }, }, } diff --git a/lua/lvim/lsp/utils.lua b/lua/lvim/lsp/utils.lua index b92ef11c..44e4f5f7 100644 --- a/lua/lvim/lsp/utils.lua +++ b/lua/lvim/lsp/utils.lua @@ -1,6 +1,7 @@ local M = {} local tbl = require "lvim.utils.table" +local Log = require "lvim.core.log" function M.is_client_active(name) local clients = vim.lsp.get_active_clients() @@ -22,25 +23,14 @@ function M.get_active_clients_by_ft(filetype) end function M.get_client_capabilities(client_id) - local client - if not client_id then - local buf_clients = vim.lsp.buf_get_clients() - for _, buf_client in pairs(buf_clients) do - if buf_client.name ~= "null-ls" then - client = buf_client - break - end - end - else - client = vim.lsp.get_client_by_id(tonumber(client_id)) - end + local client = vim.lsp.get_client_by_id(tonumber(client_id)) if not client then - error "Unable to determine client_id" + Log:warn("Unable to determine client from client_id: " .. client_id) return end local enabled_caps = {} - for capability, status in pairs(client.server_capabilities or client.resolved_capabilities) do + for capability, status in pairs(client.server_capabilities) do if status == true then table.insert(enabled_caps, capability) end @@ -82,30 +72,55 @@ function M.get_all_supported_filetypes() end function M.setup_document_highlight(client, bufnr) + if lvim.builtin.illuminate.active then + Log:debug "skipping setup for document_highlight, illuminate already active" + return + end local status_ok, highlight_supported = pcall(function() return client.supports_method "textDocument/documentHighlight" end) if not status_ok or not highlight_supported then return end - local augroup_exist, _ = pcall(vim.api.nvim_get_autocmds, { - group = "lsp_document_highlight", + local group = "lsp_document_highlight" + local hl_events = { "CursorHold", "CursorHoldI" } + + local ok, hl_autocmds = pcall(vim.api.nvim_get_autocmds, { + group = group, + buffer = bufnr, + event = hl_events, }) - if not augroup_exist then - vim.api.nvim_create_augroup("lsp_document_highlight", {}) + + if ok and #hl_autocmds > 0 then + return end - vim.api.nvim_create_autocmd({ "CursorHold", "CursorHoldI" }, { - group = "lsp_document_highlight", + + vim.api.nvim_create_augroup(group, { clear = false }) + vim.api.nvim_create_autocmd(hl_events, { + group = group, buffer = bufnr, callback = vim.lsp.buf.document_highlight, }) vim.api.nvim_create_autocmd("CursorMoved", { - group = "lsp_document_highlight", + group = group, buffer = bufnr, callback = vim.lsp.buf.clear_references, }) end +function M.setup_document_symbols(client, bufnr) + vim.g.navic_silence = false -- can be set to true to suppress error + local symbols_supported = client.supports_method "textDocument/documentSymbol" + if not symbols_supported then + Log:debug("skipping setup for document_symbols, method not supported by " .. client.name) + return + end + local status_ok, navic = pcall(require, "nvim-navic") + if status_ok then + navic.attach(client, bufnr) + end +end + function M.setup_codelens_refresh(client, bufnr) local status_ok, codelens_supported = pcall(function() return client.supports_method "textDocument/codeLens" @@ -113,14 +128,20 @@ function M.setup_codelens_refresh(client, bufnr) if not status_ok or not codelens_supported then return end - local augroup_exist, _ = pcall(vim.api.nvim_get_autocmds, { - group = "lsp_code_lens_refresh", + local group = "lsp_code_lens_refresh" + local cl_events = { "BufEnter", "InsertLeave" } + local ok, cl_autocmds = pcall(vim.api.nvim_get_autocmds, { + group = group, + buffer = bufnr, + event = cl_events, }) - if not augroup_exist then - vim.api.nvim_create_augroup("lsp_code_lens_refresh", {}) + + if ok and #cl_autocmds > 0 then + return end - vim.api.nvim_create_autocmd({ "BufEnter", "InsertLeave" }, { - group = "lsp_code_lens_refresh", + vim.api.nvim_create_augroup(group, { clear = false }) + vim.api.nvim_create_autocmd(cl_events, { + group = group, buffer = bufnr, callback = vim.lsp.codelens.refresh, }) @@ -135,9 +156,9 @@ function M.format_filter(client) local n = require "null-ls" local s = require "null-ls.sources" local method = n.methods.FORMATTING - local avalable_formatters = s.get_available(filetype, method) + local available_formatters = s.get_available(filetype, method) - if #avalable_formatters > 0 then + if #available_formatters > 0 then return client.name == "null-ls" elseif client.supports_method "textDocument/formatting" then return true @@ -146,47 +167,13 @@ function M.format_filter(client) end end ----Provide vim.lsp.buf.format for nvim <0.8 ----@param opts table +---Simple wrapper for vim.lsp.buf.format() to provide defaults +---@param opts table|nil function M.format(opts) opts = opts or {} opts.filter = opts.filter or M.format_filter - if vim.lsp.buf.format then - return vim.lsp.buf.format(opts) - end - - local bufnr = opts.bufnr or vim.api.nvim_get_current_buf() - - ---@type table|nil - local clients = vim.lsp.get_active_clients { - id = opts.id, - bufnr = bufnr, - name = opts.name, - } - - if opts.filter then - clients = vim.tbl_filter(opts.filter, clients) - end - - clients = vim.tbl_filter(function(client) - return client.supports_method "textDocument/formatting" - end, clients) - - if #clients == 0 then - vim.notify_once "[LSP] Format request failed, no matching language servers." - end - - local timeout_ms = opts.timeout_ms or 1000 - for _, client in pairs(clients) do - local params = vim.lsp.util.make_formatting_params(opts.formatting_options) - local result, err = client.request_sync("textDocument/formatting", params, timeout_ms, bufnr) - if result and result.result then - vim.lsp.util.apply_text_edits(result.result, bufnr, client.offset_encoding) - elseif err then - vim.notify(string.format("[LSP][%s] %s", client.name, err), vim.log.levels.WARN) - end - end + return vim.lsp.buf.format(opts) end return M diff --git a/lua/lvim/plugin-loader.lua b/lua/lvim/plugin-loader.lua index c10fe75e..f6cb4651 100644 --- a/lua/lvim/plugin-loader.lua +++ b/lua/lvim/plugin-loader.lua @@ -16,14 +16,19 @@ function plugin_loader.init(opts) local install_path = opts.install_path or join_paths(vim.fn.stdpath "data", "site", "pack", "packer", "start", "packer.nvim") + local max_jobs = 100 + if vim.fn.has "mac" == 1 then + max_jobs = 50 + end + local init_opts = { package_root = opts.package_root or join_paths(vim.fn.stdpath "data", "site", "pack"), compile_path = compile_path, snapshot_path = snapshot_path, - max_jobs = 40, + max_jobs = max_jobs, log = { level = "warn" }, git = { - clone_timeout = 300, + clone_timeout = 120, }, display = { open_fn = function() @@ -106,10 +111,8 @@ function plugin_loader.load(configurations) end end end) - -- colorscheme must get called after plugins are loaded or it will break new installs. - vim.g.colors_name = lvim.colorscheme - vim.cmd("colorscheme " .. lvim.colorscheme) end, debug.traceback) + if not status_ok then Log:warn "problems detected while loading plugins' configurations" Log:trace(debug.traceback()) diff --git a/lua/lvim/plugins.lua b/lua/lvim/plugins.lua index bfe76bb8..db84d878 100644 --- a/lua/lvim/plugins.lua +++ b/lua/lvim/plugins.lua @@ -1,3 +1,4 @@ +-- local require = require("lvim.utils.require").require local core_plugins = { -- Packer can manage itself as an optional plugin { "wbthomason/packer.nvim" }, @@ -6,7 +7,6 @@ local core_plugins = { { "jose-elias-alvarez/null-ls.nvim", }, - { "antoinemadec/FixCursorHold.nvim" }, -- Needed while issue https://github.com/neovim/neovim/issues/12587 is still open { "williamboman/mason-lspconfig.nvim" }, { "williamboman/mason.nvim", @@ -15,17 +15,7 @@ local core_plugins = { end, }, { - "lunarvim/onedarker.nvim", - branch = "freeze", - config = function() - pcall(function() - if lvim and lvim.colorscheme == "onedarker" then - require("onedarker").setup() - lvim.builtin.lualine.options.theme = "onedarker" - end - end) - end, - disable = lvim.colorscheme ~= "onedarker", + "folke/tokyonight.nvim", }, { "rcarriga/nvim-notify", @@ -102,8 +92,8 @@ local core_plugins = { "hrsh7th/cmp-path", }, { - "folke/lua-dev.nvim", - module = "lua-dev", + "folke/neodev.nvim", + module = "neodev", }, -- Autopairs @@ -139,7 +129,15 @@ local core_plugins = { end, disable = not lvim.builtin.nvimtree.active, }, - + -- Lir + { + "christianchiarulli/lir.nvim", + config = function() + require("lvim.core.lir").setup() + end, + requires = { "kyazdani42/nvim-web-devicons" }, + disable = not lvim.builtin.lir.active, + }, { "lewis6991/gitsigns.nvim", @@ -196,6 +194,15 @@ local core_plugins = { disable = not lvim.builtin.lualine.active, }, + -- breadcrumbs + { + "SmiteshP/nvim-navic", + config = function() + require("lvim.core.breadcrumbs").setup() + end, + disable = not lvim.builtin.breadcrumbs.active, + }, + { "akinsho/bufferline.nvim", config = function() @@ -216,12 +223,12 @@ local core_plugins = { disable = not lvim.builtin.dap.active, }, - -- Debugger management + -- Debugger user interface { - "Pocco81/dap-buddy.nvim", - branch = "dev", - -- event = "BufWinEnter", - -- event = "BufRead", + "rcarriga/nvim-dap-ui", + config = function() + require("lvim.core.dap").setup_ui() + end, disable = not lvim.builtin.dap.active, }, @@ -249,6 +256,36 @@ local core_plugins = { { "b0o/schemastore.nvim", }, + + { + "RRethy/vim-illuminate", + config = function() + require("lvim.core.illuminate").setup() + end, + disable = not lvim.builtin.illuminate.active, + }, + + { + "lukas-reineke/indent-blankline.nvim", + config = function() + require("lvim.core.indentlines").setup() + end, + disable = not lvim.builtin.indentlines.active, + }, + + { + "lunarvim/onedarker.nvim", + branch = "freeze", + config = function() + pcall(function() + if lvim and lvim.colorscheme == "onedarker" then + require("onedarker").setup() + lvim.builtin.lualine.options.theme = "onedarker" + end + end) + end, + disable = lvim.colorscheme ~= "onedarker", + }, } local default_snapshot_path = join_paths(get_lvim_base_dir(), "snapshots", "default.json") @@ -260,8 +297,8 @@ local get_default_sha1 = function(spec) return default_sha1[short_name] and default_sha1[short_name].commit end -for _, spec in ipairs(core_plugins) do - if not vim.env.LVIM_DEV_MODE then +if not vim.env.LVIM_DEV_MODE then + for _, spec in ipairs(core_plugins) do -- Manually lock the commit hash since Packer's snapshots are unreliable in headless mode spec["commit"] = get_default_sha1(spec) end diff --git a/lua/lvim/utils/functions.lua b/lua/lvim/utils/functions.lua index de46bc8a..1cb8ec8e 100644 --- a/lua/lvim/utils/functions.lua +++ b/lua/lvim/utils/functions.lua @@ -16,4 +16,17 @@ function M.smart_quit() end end +function M.isempty(s) + return s == nil or s == "" +end + +function M.get_buf_option(opt) + local status_ok, buf_option = pcall(vim.api.nvim_buf_get_option, 0, opt) + if not status_ok then + return nil + else + return buf_option + end +end + return M diff --git a/lua/lvim/utils/git.lua b/lua/lvim/utils/git.lua index 99c178f3..c1bdca1b 100644 --- a/lua/lvim/utils/git.lua +++ b/lua/lvim/utils/git.lua @@ -1,6 +1,7 @@ local M = {} local Log = require "lvim.core.log" +local fmt = string.format local if_nil = vim.F.if_nil local function git_cmd(opts) @@ -39,13 +40,20 @@ local function safe_deep_fetch() Log:error(vim.inspect(error)) return end - -- git fetch --unshallow will cause an error on a a complete clone + -- git fetch --unshallow will cause an error on a complete clone local fetch_mode = result[1] == "true" and "--unshallow" or "--all" ret = git_cmd { args = { "fetch", fetch_mode } } if ret ~= 0 then - Log:error("Git fetch failed! Please pull the changes manually in " .. get_lvim_base_dir()) + Log:error(fmt "Git fetch %s failed! Please pull the changes manually in %s", fetch_mode, get_lvim_base_dir()) return end + if fetch_mode == "--unshallow" then + ret = git_cmd { args = { "remote", "set-branches", "origin", "*" } } + if ret ~= 0 then + Log:error(fmt "Git fetch %s failed! Please pull the changes manually in %s", fetch_mode, get_lvim_base_dir()) + return + end + end return true end @@ -53,6 +61,11 @@ end function M.update_base_lvim() Log:info "Checking for updates" + if not vim.loop.fs_access(get_lvim_base_dir(), "w") then + Log:warn(fmt("Lunarvim update aborted! cannot write to %s", get_lvim_base_dir())) + return + end + if not safe_deep_fetch() then return end diff --git a/lua/lvim/utils/hooks.lua b/lua/lvim/utils/hooks.lua index f15f6729..bf0dac60 100644 --- a/lua/lvim/utils/hooks.lua +++ b/lua/lvim/utils/hooks.lua @@ -19,7 +19,7 @@ function M.run_on_packer_complete() pcall(vim.cmd, "colorscheme " .. lvim.colorscheme) if M._reload_triggered then - Log:info "Reloaded configuration" + Log:debug "Reloaded configuration" M._reload_triggered = nil end end @@ -34,10 +34,7 @@ end ---It also forces regenerating any template ftplugin files ---Tip: Useful for clearing any outdated settings function M.reset_cache() - local impatient = _G.__luacache - if impatient then - impatient.clear_cache() - end + vim.cmd [[LuaCacheClear]] local lvim_modules = {} for module, _ in pairs(package.loaded) do if module:match "lvim.core" or module:match "lvim.lsp" then @@ -52,8 +49,8 @@ end function M.run_post_update() Log:debug "Starting post-update hook" - if vim.fn.has "nvim-0.7" ~= 1 then - local compat_tag = "1.1.3" + if vim.fn.has "nvim-0.8" ~= 1 then + local compat_tag = "1.1.4" vim.notify( "Please upgrade your Neovim base installation. Newer version of Lunarvim requires v0.7+", vim.log.levels.WARN @@ -61,9 +58,9 @@ function M.run_post_update() vim.wait(1000, function() return false end) - local ret = require_clean("lvim.utils.git").switch_lvim_branch(compat_tag) + local ret = reload("lvim.utils.git").switch_lvim_branch(compat_tag) if ret then - vim.notify("Reverted to the last known compatibile version: " .. compat_tag, vim.log.levels.WARN) + vim.notify("Reverted to the last known compatible version: " .. compat_tag, vim.log.levels.WARN) end return end diff --git a/lua/lvim/utils/modules.lua b/lua/lvim/utils/modules.lua new file mode 100644 index 00000000..d5674483 --- /dev/null +++ b/lua/lvim/utils/modules.lua @@ -0,0 +1,98 @@ +local M = {} + +local Log = require "lvim.core.log" +-- revisit this +-- function prequire(package) +-- local status, lib = pcall(require, package) +-- if status then +-- return lib +-- else +-- vim.notify("Failed to require '" .. package .. "' from " .. debug.getinfo(2).source) +-- return nil +-- end +-- end + +local function _assign(old, new, k) + local otype = type(old[k]) + local ntype = type(new[k]) + -- print("hi") + if (otype == "thread" or otype == "userdata") or (ntype == "thread" or ntype == "userdata") then + vim.notify(string.format("warning: old or new attr %s type be thread or userdata", k)) + end + old[k] = new[k] +end + +local function _replace(old, new, repeat_tbl) + if repeat_tbl[old] then + return + end + repeat_tbl[old] = true + + local dellist = {} + for k, _ in pairs(old) do + if not new[k] then + table.insert(dellist, k) + end + end + for _, v in ipairs(dellist) do + old[v] = nil + end + + for k, _ in pairs(new) do + if not old[k] then + old[k] = new[k] + else + if type(old[k]) ~= type(new[k]) then + Log:debug( + string.format("Reloader: mismatch between old [%s] and new [%s] type for [%s]", type(old[k]), type(new[k]), k) + ) + _assign(old, new, k) + else + if type(old[k]) == "table" then + _replace(old[k], new[k], repeat_tbl) + else + _assign(old, new, k) + end + end + end + end +end + +M.require_clean = function(m) + package.loaded[m] = nil + _G[m] = nil + local _, module = pcall(require, m) + return module +end + +M.require_safe = function(mod) + local status_ok, module = pcall(require, mod) + if not status_ok then + local trace = debug.getinfo(2, "SL") + local shorter_src = trace.short_src + local lineinfo = shorter_src .. ":" .. (trace.currentline or trace.linedefined) + local msg = string.format("%s : skipped loading [%s]", lineinfo, mod) + Log:debug(msg) + end + return module +end + +M.reload = function(mod) + if not package.loaded[mod] then + return M.require_safe(mod) + end + + local old = package.loaded[mod] + package.loaded[mod] = nil + local new = M.require_safe(mod) + + if type(old) == "table" and type(new) == "table" then + local repeat_tbl = {} + _replace(old, new, repeat_tbl) + end + + package.loaded[mod] = old + return old +end + +return M diff --git a/snapshots/default.json b/snapshots/default.json index b57c4fba..f0a6d293 100644 --- a/snapshots/default.json +++ b/snapshots/default.json @@ -1,84 +1,90 @@ { "Comment.nvim": { - "commit": "30d23aa" - }, - "FixCursorHold.nvim": { - "commit": "5aa5ff1" + "commit": "ad7ffa8" }, "LuaSnip": { - "commit": "6e506ce" + "commit": "663d544" }, "alpha-nvim": { "commit": "0bb6fc0" }, "bufferline.nvim": { - "commit": "ffa1d00" + "commit": "0606cee" }, "cmp-buffer": { "commit": "3022dbc" }, "cmp-nvim-lsp": { - "commit": "affe808" + "commit": "2a84710" }, "cmp-path": { - "commit": "447c87c" + "commit": "91ff86c" }, "cmp_luasnip": { "commit": "a9de941" }, - "dap-buddy.nvim": { - "commit": "3679132" - }, "friendly-snippets": { - "commit": "22a9975" + "commit": "fd16b4d" }, "gitsigns.nvim": { - "commit": "d7e0bcb" + "commit": "2c6f96d" }, - "lua-dev.nvim": { - "commit": "fd7a18e" + "indent-blankline.nvim": { + "commit": "db7cbcb" + }, + "lir.nvim": { + "commit": "7d8c6c4" }, "lualine.nvim": { - "commit": "a52f078" + "commit": "edca2b0" }, "mason-lspconfig.nvim": { - "commit": "1534b61" + "commit": "bf8ac12" }, "mason.nvim": { - "commit": "b56ea0b" + "commit": "45b9a4d" + }, + "neodev.nvim": { + "commit": "08d8455" }, "nlsp-settings.nvim": { - "commit": "e1fcc6e" + "commit": "8500c4e" }, "null-ls.nvim": { - "commit": "bf02782" + "commit": "643c67a" }, "nvim-autopairs": { - "commit": "5fe2441" + "commit": "4fc96c8" }, "nvim-cmp": { - "commit": "913eb85" + "commit": "3347dd3" }, "nvim-dap": { - "commit": "d9b315a" + "commit": "e71da68" + }, + "nvim-dap-ui": { + "commit": "1cd4764" }, "nvim-lspconfig": { - "commit": "f8b3c24" + "commit": "35a731b" + }, + "nvim-navic": { + "commit": "132b273" }, "nvim-notify": { - "commit": "7076ce8" + "commit": "af935fd" }, "nvim-tree.lua": { - "commit": "fb8735e" + "commit": "c446527" }, "nvim-treesitter": { - "commit": "2eaf188" + "commit": "1da61c9" }, "nvim-ts-context-commentstring": { - "commit": "4d3a68c" + "commit": "2941f00" }, "nvim-web-devicons": { - "commit": "2d02a56" + "commit": "a8cf88c" }, "onedarker.nvim": { "commit": "b00dd21" @@ -87,16 +93,16 @@ "commit": "6afb674" }, "plenary.nvim": { - "commit": "4b66054" + "commit": "4b7e520" }, "popup.nvim": { "commit": "b7404d3" }, "project.nvim": { - "commit": "090bb11" + "commit": "628de7e" }, "schemastore.nvim": { - "commit": "92efc7c" + "commit": "03f4f94" }, "structlog.nvim": { "commit": "232a8e2" @@ -108,9 +114,15 @@ "commit": "0b1c41a" }, "toggleterm.nvim": { - "commit": "5e393e5" + "commit": "2a787c4" + }, + "tokyonight.nvim": { + "commit": "e6307e1" + }, + "vim-illuminate": { + "commit": "0603e75" }, "which-key.nvim": { - "commit": "d5f0c63" + "commit": "6885b66" } } diff --git a/tests/minimal_lsp.lua b/tests/minimal_lsp.lua index 09224f94..01e814be 100644 --- a/tests/minimal_lsp.lua +++ b/tests/minimal_lsp.lua @@ -71,7 +71,7 @@ _G.load_config = function() vim.keymap.set("n", "]d", vim.diagnostic.goto_next, opts) vim.keymap.set("n", "q", vim.diagnostic.setloclist, opts) vim.keymap.set("n", "li", "LspInfo", opts) - vim.keymap.set("n", "lI", "MasonCR>", opts) + vim.keymap.set("n", "lI", "Mason", opts) end -- Add the server that troubles you here, e.g. "clangd", "pyright", "tsserver" diff --git a/tests/specs/plugins_load_spec.lua b/tests/specs/plugins_load_spec.lua index 283d5547..5cf1c2f5 100644 --- a/tests/specs/plugins_load_spec.lua +++ b/tests/specs/plugins_load_spec.lua @@ -59,7 +59,7 @@ a.describe("plugin-loader", function() _G.completed = false _G.verify_sha = function() if _G.locked_sha ~= get_current_sha(plugin.path) then - error "unmached results!" + error "unmatched results!" else _G.completed = true end diff --git a/utils/bin/lvim.ps1 b/utils/bin/lvim.ps1 index 32723c18..3ec8125c 100644 --- a/utils/bin/lvim.ps1 +++ b/utils/bin/lvim.ps1 @@ -10,4 +10,4 @@ $env:LUNARVIM_CONFIG_DIR = $env:LUNARVIM_CONFIG_DIR ?? "$env:XDG_CONFIG_HOME\lvi $env:LUNARVIM_CACHE_DIR = $env:LUNARVIM_CACHE_DIR ?? "$env:XDG_CACHE_HOME\lvim" $env:LUNARVIM_BASE_DIR = $env:LUNARVIM_BASE_DIR ?? "$env:LUNARVIM_RUNTIME_DIR\lvim" -nvim -u "$env:LUNARVIM_RUNTIME_DIR\lvim\init.lua" @args +nvim -u "$env:LUNARVIM_BASE_DIR\init.lua" @args diff --git a/utils/bin/lvim.template b/utils/bin/lvim.template index 1b18977d..c17d25be 100644 --- a/utils/bin/lvim.template +++ b/utils/bin/lvim.template @@ -1,7 +1,9 @@ -#!/bin/sh +#!/usr/bin/env bash export LUNARVIM_RUNTIME_DIR="${LUNARVIM_RUNTIME_DIR:-RUNTIME_DIR_VAR}" export LUNARVIM_CONFIG_DIR="${LUNARVIM_CONFIG_DIR:-CONFIG_DIR_VAR}" export LUNARVIM_CACHE_DIR="${LUNARVIM_CACHE_DIR:-CACHE_DIR_VAR}" -exec nvim -u "$LUNARVIM_RUNTIME_DIR/lvim/init.lua" "$@" +export LUNARVIM_BASE_DIR="${LUNARVIM_BASE_DIR:-BASE_DIR_VAR}" + +exec -a lvim nvim -u "$LUNARVIM_BASE_DIR/init.lua" "$@" diff --git a/utils/ci/verify_plugins.lua b/utils/ci/verify_plugins.lua index 3cc5dd82..cecb01db 100644 --- a/utils/ci/verify_plugins.lua +++ b/utils/ci/verify_plugins.lua @@ -33,8 +33,7 @@ end local get_install_path = function(spec) local prefix = is_optional(spec) and packer_config.opt_dir or packer_config.start_dir local path = join_paths(prefix, get_short_name(spec)) - assert(is_directory(path)) - return path + return is_directory(path) and path end local function call_proc(process, opts, cb) @@ -92,11 +91,12 @@ end local function verify_core_plugins(verbose) for _, spec in pairs(core_plugins) do - if not spec.disable then + local path = get_install_path(spec) + if not spec.disable and path then table.insert(collection, { name = get_short_name(spec), commit = get_default_sha1(spec), - path = get_install_path(spec), + path = path, }) end end diff --git a/utils/desktop/16x16/lvim.svg b/utils/desktop/16x16/lvim.svg new file mode 100644 index 00000000..6898fd0d --- /dev/null +++ b/utils/desktop/16x16/lvim.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/utils/desktop/22x22/lvim.svg b/utils/desktop/22x22/lvim.svg new file mode 100644 index 00000000..06f24f5b --- /dev/null +++ b/utils/desktop/22x22/lvim.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/utils/desktop/24x24/lvim.svg b/utils/desktop/24x24/lvim.svg new file mode 100644 index 00000000..456298df --- /dev/null +++ b/utils/desktop/24x24/lvim.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/utils/desktop/32x32/lvim.svg b/utils/desktop/32x32/lvim.svg new file mode 100644 index 00000000..13e53c24 --- /dev/null +++ b/utils/desktop/32x32/lvim.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/utils/desktop/48x48/lvim.svg b/utils/desktop/48x48/lvim.svg new file mode 100644 index 00000000..35baac28 --- /dev/null +++ b/utils/desktop/48x48/lvim.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/utils/desktop/64x64/lvim.svg b/utils/desktop/64x64/lvim.svg new file mode 100644 index 00000000..fd2a964e --- /dev/null +++ b/utils/desktop/64x64/lvim.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/utils/desktop/lvim.desktop b/utils/desktop/lvim.desktop index f570cfae..cb4cb476 100644 --- a/utils/desktop/lvim.desktop +++ b/utils/desktop/lvim.desktop @@ -7,7 +7,7 @@ Exec=lvim %F Terminal=true Type=Application Keywords=Text;editor; -Icon=nvim +Icon=lvim Categories=Utility;TextEditor; StartupNotify=false MimeType=text/english;text/plain;text/x-makefile;text/x-c++hdr;text/x-c++src;text/x-chdr;text/x-csrc;text/x-java;text/x-moc;text/x-pascal;text/x-tcl;text/x-tex;application/x-shellscript;text/x-c;text/x-c++; diff --git a/utils/installer/config.example.lua b/utils/installer/config.example.lua index 26a50edc..ee599d1b 100644 --- a/utils/installer/config.example.lua +++ b/utils/installer/config.example.lua @@ -10,8 +10,8 @@ an executable -- general lvim.log.level = "warn" -lvim.format_on_save = true -lvim.colorscheme = "onedarker" +lvim.format_on_save = false +lvim.colorscheme = "tokyonight" -- to disable icons and use a minimalist setup, uncomment the following -- lvim.use_icons = false @@ -44,6 +44,10 @@ lvim.keys.normal_mode[""] = ":w" -- }, -- } +-- Change theme settings +-- lvim.builtin.theme.options.dim_inactive = true +-- lvim.builtin.theme.options.style = "storm" + -- Use which-key to add extra bindings with the leader-key prefix -- lvim.builtin.which_key.mappings["P"] = { "Telescope projects", "Projects" } -- lvim.builtin.which_key.mappings["t"] = { @@ -82,13 +86,13 @@ lvim.builtin.treesitter.ensure_installed = { } lvim.builtin.treesitter.ignore_install = { "haskell" } -lvim.builtin.treesitter.highlight.enabled = true +lvim.builtin.treesitter.highlight.enable = true -- generic LSP settings -- -- make sure server will always be installed even if the server is in skipped_servers list -- lvim.lsp.installer.setup.ensure_installed = { --- "sumeko_lua", +-- "sumneko_lua", -- "jsonls", -- } -- -- change UI setting of `LspInstallInfo` @@ -161,7 +165,6 @@ lvim.builtin.treesitter.highlight.enabled = true -- Additional Plugins -- lvim.plugins = { --- {"folke/tokyonight.nvim"}, -- { -- "folke/trouble.nvim", -- cmd = "TroubleToggle", diff --git a/utils/installer/config_win.example.lua b/utils/installer/config_win.example.lua index 872e6270..40cc34e8 100644 --- a/utils/installer/config_win.example.lua +++ b/utils/installer/config_win.example.lua @@ -28,7 +28,7 @@ vim.g.clipboard = { -- general lvim.log.level = "warn" lvim.format_on_save = true -lvim.colorscheme = "onedarker" +lvim.colorscheme = "tokyonight" -- to disable icons and use a minimalist setup, uncomment the following -- lvim.use_icons = false @@ -61,6 +61,10 @@ lvim.keys.normal_mode[""] = ":w" -- }, -- } +-- Change theme settings +-- lvim.builtin.theme.options.dim_inactive = true +-- lvim.builtin.theme.options.style = "storm" + -- Use which-key to add extra bindings with the leader-key prefix -- lvim.builtin.which_key.mappings["P"] = { "Telescope projects", "Projects" } -- lvim.builtin.which_key.mappings["t"] = { @@ -97,13 +101,13 @@ lvim.builtin.treesitter.ensure_installed = { } lvim.builtin.treesitter.ignore_install = { "haskell" } -lvim.builtin.treesitter.highlight.enabled = true +lvim.builtin.treesitter.highlight.enable = true -- generic LSP settings -- -- make sure server will always be installed even if the server is in skipped_servers list -- lvim.lsp.installer.setup.ensure_installed = { --- "sumeko_lua", +-- "sumneko_lua", -- "jsonls", -- } -- -- change UI setting of `LspInstallInfo` @@ -176,7 +180,6 @@ lvim.builtin.treesitter.highlight.enabled = true -- Additional Plugins -- lvim.plugins = { --- {"folke/tokyonight.nvim"}, -- { -- "folke/trouble.nvim", -- cmd = "TroubleToggle", diff --git a/utils/installer/install.sh b/utils/installer/install.sh index 620d46f5..87f60fd4 100755 --- a/utils/installer/install.sh +++ b/utils/installer/install.sh @@ -2,20 +2,20 @@ set -eo pipefail #Set branch to master unless specified by the user -declare LV_BRANCH="${LV_BRANCH:-"master"}" -declare -r LV_REMOTE="${LV_REMOTE:-lunarvim/lunarvim.git}" -declare -r INSTALL_PREFIX="${INSTALL_PREFIX:-"$HOME/.local"}" +declare -x LV_BRANCH="${LV_BRANCH:-"master"}" +declare -xr LV_REMOTE="${LV_REMOTE:-lunarvim/lunarvim.git}" +declare -xr INSTALL_PREFIX="${INSTALL_PREFIX:-"$HOME/.local"}" -declare -r XDG_DATA_HOME="${XDG_DATA_HOME:-"$HOME/.local/share"}" -declare -r XDG_CACHE_HOME="${XDG_CACHE_HOME:-"$HOME/.cache"}" -declare -r XDG_CONFIG_HOME="${XDG_CONFIG_HOME:-"$HOME/.config"}" +declare -xr XDG_DATA_HOME="${XDG_DATA_HOME:-"$HOME/.local/share"}" +declare -xr XDG_CACHE_HOME="${XDG_CACHE_HOME:-"$HOME/.cache"}" +declare -xr XDG_CONFIG_HOME="${XDG_CONFIG_HOME:-"$HOME/.config"}" -declare -r LUNARVIM_RUNTIME_DIR="${LUNARVIM_RUNTIME_DIR:-"$XDG_DATA_HOME/lunarvim"}" -declare -r LUNARVIM_CONFIG_DIR="${LUNARVIM_CONFIG_DIR:-"$XDG_CONFIG_HOME/lvim"}" -declare -r LUNARVIM_CACHE_DIR="${LUNARVIM_CACHE_DIR:-"$XDG_CACHE_HOME/lvim"}" -declare -r LUNARVIM_BASE_DIR="${LUNARVIM_BASE_DIR:-"$LUNARVIM_RUNTIME_DIR/lvim"}" +declare -xr LUNARVIM_RUNTIME_DIR="${LUNARVIM_RUNTIME_DIR:-"$XDG_DATA_HOME/lunarvim"}" +declare -xr LUNARVIM_CONFIG_DIR="${LUNARVIM_CONFIG_DIR:-"$XDG_CONFIG_HOME/lvim"}" +declare -xr LUNARVIM_CACHE_DIR="${LUNARVIM_CACHE_DIR:-"$XDG_CACHE_HOME/lvim"}" +declare -xr LUNARVIM_BASE_DIR="${LUNARVIM_BASE_DIR:-"$LUNARVIM_RUNTIME_DIR/lvim"}" -declare -r LUNARVIM_LOG_LEVEL="${LUNARVIM_LOG_LEVEL:-warn}" +declare -xr LUNARVIM_LOG_LEVEL="${LUNARVIM_LOG_LEVEL:-warn}" declare BASEDIR BASEDIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &>/dev/null && pwd)" @@ -51,7 +51,7 @@ function usage() { echo " -l, --local Install local copy of LunarVim" echo " -y, --yes Disable confirmation prompts (answer yes to all questions)" echo " --overwrite Overwrite previous LunarVim configuration (a backup is always performed first)" - echo " --[no]-install-dependencies Whether to automatically install external dependencies (will prompt by default)" + echo " --[no-]install-dependencies Whether to automatically install external dependencies (will prompt by default)" } function parse_arguments() { @@ -201,11 +201,11 @@ function print_missing_dep_msg() { } function check_neovim_min_version() { - local verify_version_cmd='if !has("nvim-0.7") | cquit | else | quit | endif' + local verify_version_cmd='if !has("nvim-0.8") | cquit | else | quit | endif' # exit with an error if min_version not found if ! nvim --headless -u NONE -c "$verify_version_cmd"; then - echo "[ERROR]: LunarVim requires at least Neovim v0.7 or higher" + echo "[ERROR]: LunarVim requires at least Neovim v0.8 or higher" exit 1 fi } @@ -395,7 +395,7 @@ function backup_old_config() { function clone_lvim() { msg "Cloning LunarVim configuration" if ! git clone --branch "$LV_BRANCH" \ - --depth 1 "https://github.com/${LV_REMOTE}" "$LUNARVIM_BASE_DIR"; then + "https://github.com/${LV_REMOTE}" "$LUNARVIM_BASE_DIR"; then echo "Failed to clone repository. Installation failed." exit 1 fi @@ -439,12 +439,14 @@ function setup_lvim() { setup_shim - cp "$LUNARVIM_BASE_DIR/utils/installer/config.example.lua" "$LUNARVIM_CONFIG_DIR/config.lua" + create_desktop_file + + [ ! -f "$LUNARVIM_CONFIG_DIR/config.lua" ] \ + && cp "$LUNARVIM_BASE_DIR/utils/installer/config.example.lua" "$LUNARVIM_CONFIG_DIR/config.lua" echo "Preparing Packer setup" "$INSTALL_PREFIX/bin/lvim" --headless \ - -c "lua require('lvim.core.log'):set_level([[$LUNARVIM_LOG_LEVEL]])" \ -c 'autocmd User PackerComplete quitall' \ -c 'PackerSync' @@ -453,6 +455,21 @@ function setup_lvim() { verify_core_plugins } +function create_desktop_file() { + OS="$(uname -s)" + # TODO: Any other OSes that use desktop files? + ([ "$OS" != "Linux" ] || ! command -v xdg-desktop-menu &>/dev/null) && return + echo "Creating desktop file" + + for d in "$LUNARVIM_BASE_DIR"/utils/desktop/*/; do + size_folder=$(basename "$d") + mkdir -p "$XDG_DATA_HOME/icons/hicolor/$size_folder/apps/" + cp "$LUNARVIM_BASE_DIR/utils/desktop/$size_folder/lvim.svg" "$XDG_DATA_HOME/icons/hicolor/$size_folder/apps" + done + + xdg-desktop-menu install --novendor "$LUNARVIM_BASE_DIR/utils/desktop/lvim.desktop" +} + function print_logo() { cat <<'EOF' diff --git a/utils/installer/install_bin.sh b/utils/installer/install_bin.sh index c6ad5181..920f2fd5 100755 --- a/utils/installer/install_bin.sh +++ b/utils/installer/install_bin.sh @@ -26,7 +26,8 @@ function setup_shim() { sed -e s"#RUNTIME_DIR_VAR#\"${LUNARVIM_RUNTIME_DIR}\"#"g \ -e s"#CONFIG_DIR_VAR#\"${LUNARVIM_CONFIG_DIR}\"#"g \ - -e s"#CACHE_DIR_VAR#\"${LUNARVIM_CACHE_DIR}\"#"g "$src" \ + -e s"#CACHE_DIR_VAR#\"${LUNARVIM_CACHE_DIR}\"#"g \ + -e s"#BASE_DIR_VAR#\"${LUNARVIM_BASE_DIR}\"#"g "$src" \ | tee "$dst" >/dev/null chmod u+x "$dst" diff --git a/utils/installer/uninstall.sh b/utils/installer/uninstall.sh index 8fc8e693..597bbf85 100755 --- a/utils/installer/uninstall.sh +++ b/utils/installer/uninstall.sh @@ -60,12 +60,23 @@ function remove_lvim_bin() { rm -f "$lvim_bin" } +function remove_desktop_file() { + OS="$(uname -s)" + # TODO: Any other OSes that use desktop files? + ([ "$OS" != "Linux" ] || ! command -v xdg-desktop-menu &>/dev/null) && return + echo "Removing desktop file..." + + find "$XDG_DATA_HOME/icons/hicolor" -name "lvim.svg" -type f -delete + xdg-desktop-menu uninstall lvim.desktop +} + function main() { parse_arguments "$@" echo "Removing LunarVim binary..." remove_lvim_bin echo "Removing LunarVim directories..." remove_lvim_dirs + remove_desktop_file echo "Uninstalled LunarVim!" }