kylo252 пре 3 година
родитељ
комит
57bebb5c51

+ 2 - 1
.gitignore

@@ -28,4 +28,5 @@ lua/lv-user-config/
 *.backup
 *.old
 
-.luarc.json
+.luarc.json
+.luacheckcache

+ 2 - 1
lua/lvim/core/lualine/components.lua

@@ -110,7 +110,8 @@ return {
       local supported_linters = linters.list_registered(buf_ft)
       vim.list_extend(buf_client_names, supported_linters)
 
-      return "[" .. table.concat(buf_client_names, ", ") .. "]"
+      local unique_client_names = vim.fn.uniq(buf_client_names)
+      return "[" .. table.concat(unique_client_names, ", ") .. "]"
     end,
     color = { gui = "bold" },
     cond = conditions.hide_in_width,

+ 6 - 3
lua/lvim/core/nvimtree.lua

@@ -148,7 +148,6 @@ function M.config()
       },
     },
   }
-  lvim.builtin.which_key.mappings["e"] = { "<cmd>NvimTreeToggle<CR>", "Explorer" }
 end
 
 function M.setup()
@@ -158,10 +157,14 @@ function M.setup()
     return
   end
 
-  for opt, val in pairs(lvim.builtin.nvimtree) do
-    vim.g["nvim_tree_" .. opt] = val
+  if lvim.builtin.nvimtree._setup_called then
+    Log:debug "ignoring repeated setup call for nvim-tree, see kyazdani42/nvim-tree.lua#1308"
+    return
   end
 
+  lvim.builtin.which_key.mappings["e"] = { "<cmd>NvimTreeToggle<CR>", "Explorer" }
+  lvim.builtin.nvimtree._setup_called = true
+
   -- Implicitly update nvim-tree when project module is active
   if lvim.builtin.project.active then
     lvim.builtin.nvimtree.setup.respect_buf_cwd = true

+ 8 - 8
lua/lvim/core/telescope.lua

@@ -70,14 +70,14 @@ function M.config()
       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 = {
+      find_files = {
+        hidden = true,
+      },
+      live_grep = {
+        --@usage don't include the filename in the search results
+        only_sort_text = true,
       },
     },
     extensions = {

+ 1 - 0
lua/lvim/core/which-key.lua

@@ -244,6 +244,7 @@ M.config = function()
         c = { "<cmd>Telescope colorscheme<cr>", "Colorscheme" },
         f = { "<cmd>Telescope find_files<cr>", "Find File" },
         h = { "<cmd>Telescope help_tags<cr>", "Find Help" },
+        H = { "<cmd>Telescope highlights<cr>", "Find highlight groups" },
         M = { "<cmd>Telescope man_pages<cr>", "Man Pages" },
         r = { "<cmd>Telescope oldfiles<cr>", "Open Recent File" },
         R = { "<cmd>Telescope registers<cr>", "Registers" },

+ 1 - 0
lua/lvim/lsp/config.lua

@@ -32,6 +32,7 @@ local skipped_servers = {
   "stylelint_lsp",
   "tailwindcss",
   "tflint",
+  "svlangserver",
   "verible",
   "vuels",
 }

+ 1 - 1
lua/lvim/lsp/utils.lua

@@ -176,7 +176,7 @@ function M.format(opts)
   end, clients)
 
   if #clients == 0 then
-    vim.notify "[LSP] Format request failed, no matching language servers."
+    vim.notify_once "[LSP] Format request failed, no matching language servers."
   end
 
   local timeout_ms = opts.timeout_ms or 1000

+ 13 - 3
lua/lvim/plugins.lua

@@ -246,9 +246,19 @@ local core_plugins = {
   },
 }
 
-for _, entry in ipairs(core_plugins) do
-  if not os.getenv "LVIM_DEV_MODE" then
-    entry["lock"] = true
+local default_snapshot_path = join_paths(get_lvim_base_dir(), "snapshots", "default.json")
+local content = vim.fn.readfile(default_snapshot_path)
+local default_sha1 = vim.fn.json_decode(content)
+
+local get_default_sha1 = function(spec)
+  local short_name, _ = require("packer.util").get_plugin_short_name(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
+    -- Manually lock the commit hash since Packer's snapshots are unreliable in headless mode
+    spec["commit"] = get_default_sha1(spec)
   end
 end
 

+ 20 - 20
snapshots/default.json

@@ -1,15 +1,15 @@
 {
   "Comment.nvim": {
-    "commit": "bdf9ca6"
+    "commit": "3c69bab"
   },
   "FixCursorHold.nvim": {
     "commit": "1bfb32e"
   },
   "LuaSnip": {
-    "commit": "52f4aed"
+    "commit": "79b2019"
   },
   "alpha-nvim": {
-    "commit": "4781fcf"
+    "commit": "ef27a59"
   },
   "bufferline.nvim": {
     "commit": "c78b3ec"
@@ -30,10 +30,10 @@
     "commit": "bbda2b0"
   },
   "friendly-snippets": {
-    "commit": "974d792"
+    "commit": "d27a83a"
   },
   "gitsigns.nvim": {
-    "commit": "27aeb2e"
+    "commit": "c18e016"
   },
   "lua-dev.nvim": {
     "commit": "54149d1"
@@ -42,34 +42,34 @@
     "commit": "3362b28"
   },
   "nlsp-settings.nvim": {
-    "commit": "f27faa4"
+    "commit": "62d72bc"
   },
   "null-ls.nvim": {
-    "commit": "474372a"
+    "commit": "ff40739"
   },
   "nvim-autopairs": {
-    "commit": "b9cc0a2"
+    "commit": "fa6876f"
   },
   "nvim-cmp": {
-    "commit": "033a817"
+    "commit": "df6734a"
   },
   "nvim-dap": {
-    "commit": "688cb52"
+    "commit": "014ebd5"
   },
   "nvim-lsp-installer": {
-    "commit": "ce70a78"
+    "commit": "2408a0f"
   },
   "nvim-lspconfig": {
-    "commit": "eb03999"
+    "commit": "10c3934"
   },
   "nvim-notify": {
-    "commit": "8252aae"
+    "commit": "8960269"
   },
   "nvim-tree.lua": {
-    "commit": "1caca62"
+    "commit": "bdb6d4a"
   },
   "nvim-treesitter": {
-    "commit": "178f24e"
+    "commit": "518e275"
   },
   "nvim-ts-context-commentstring": {
     "commit": "8834375"
@@ -84,7 +84,7 @@
     "commit": "00ec5ad"
   },
   "plenary.nvim": {
-    "commit": "54b2e3d"
+    "commit": "968a4b9"
   },
   "popup.nvim": {
     "commit": "b7404d3"
@@ -93,19 +93,19 @@
     "commit": "541115e"
   },
   "schemastore.nvim": {
-    "commit": "3a15757"
+    "commit": "a32911d"
   },
   "structlog.nvim": {
     "commit": "232a8e2"
   },
   "telescope-fzf-native.nvim": {
-    "commit": "f0dba7d"
+    "commit": "6a33ece"
   },
   "telescope.nvim": {
-    "commit": "e6b69b1"
+    "commit": "d96eaa9"
   },
   "toggleterm.nvim": {
-    "commit": "5bf839a"
+    "commit": "aaeed9e"
   },
   "which-key.nvim": {
     "commit": "f03a259"

+ 2 - 1
tests/specs/plugins_load_spec.lua

@@ -38,7 +38,8 @@ a.describe("plugin-loader", function()
       assert.truthy(package.loaded[plugin])
     end
   end)
-  a.it("should be able to rollback plugins without errors", function()
+
+  pending("should be able to rollback plugins without errors", function()
     local plugin = { name = "onedarker.nvim" }
     plugin.path = vim.tbl_filter(function(package)
       return package:match(plugin.name)

+ 18 - 17
utils/ci/generate_new_lockfile.lua

@@ -1,18 +1,18 @@
 local sp = os.getenv "SNAPSHOT_PATH"
 
 local function call_proc(process, opts, cb)
-  local std_output = ""
-  local error_output = ""
-
-  local function onread(_, is_stderr)
-    return function(err, data)
-      if data then
-        if is_stderr then
-          error_output = (error_output or "") .. err
-        else
-          std_output = (std_output or "") .. data
-        end
-      end
+  local output, error_output = "", ""
+  local handle_stdout = function(err, chunk)
+    assert(not err, err)
+    if chunk then
+      output = output .. chunk
+    end
+  end
+
+  local handle_stderr = function(err, chunk)
+    assert(not err, err)
+    if chunk then
+      error_output = error_output .. chunk
     end
   end
 
@@ -26,7 +26,7 @@ local function call_proc(process, opts, cb)
 
   handle = uv.spawn(
     process,
-    { args = opts.args, cwd = uv.cwd(), stdio = stdio },
+    { args = opts.args, cwd = opts.cwd or uv.cwd(), stdio = stdio },
     vim.schedule_wrap(function(code)
       if code ~= 0 then
         stdout:read_stop()
@@ -42,13 +42,13 @@ local function call_proc(process, opts, cb)
         end
         check:stop()
         handle:close()
-        cb(code, std_output, error_output)
+        cb(code, output, error_output)
       end)
     end)
   )
 
-  uv.read_start(stdout, onread(handle, false))
-  uv.read_start(stderr, onread(handle, true))
+  uv.read_start(stdout, handle_stdout)
+  uv.read_start(stderr, handle_stderr)
 
   return handle
 end
@@ -91,11 +91,12 @@ local function write_lockfile(verbose)
     end
 
     local handle = call_proc("git", { args = { "ls-remote", entry.url, "HEAD" } }, on_done)
+    assert(handle)
     table.insert(active_jobs, handle)
   end
 
   print("active: " .. #active_jobs)
-  print("parsers: " .. #default_plugins)
+  print("plugins: " .. #default_plugins)
 
   vim.wait(#active_jobs * 60 * 1000, function()
     return completed == #active_jobs

+ 134 - 0
utils/ci/verify_plugins.lua

@@ -0,0 +1,134 @@
+local completed = 0
+local collection = {}
+local active_jobs = {}
+
+local fmt = string.format
+local core_plugins = require "lvim.plugins"
+
+local default_snapshot_path = join_paths(get_lvim_base_dir(), "snapshots", "default.json")
+local fd = io.open(default_snapshot_path, "rb")
+local content
+if fd then
+  content = fd:read "*a"
+end
+local default_sha1 = vim.json.decode(content)
+
+local get_short_name = function(spec)
+  return spec[1]:match "/(%S*)"
+end
+
+local get_default_sha1 = function(spec)
+  local short_name, _ = get_short_name(spec)
+  assert(default_sha1[short_name])
+  return default_sha1[short_name].commit
+end
+
+local is_directory = require("lvim.utils").is_directory
+-- see packer.init()
+local packdir = join_paths(get_runtime_dir(), "site", "pack", "packer")
+local packer_config = { opt_dir = join_paths(packdir, "opt"), start_dir = join_paths(packdir, "start") }
+local is_optional = function(spec)
+  return spec.opt or spec.event or spec.cmd or spec.module
+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
+end
+
+local function call_proc(process, opts, cb)
+  local output, error_output = "", ""
+  local handle_stdout = function(err, chunk)
+    assert(not err, err)
+    if chunk then
+      output = output .. chunk
+    end
+  end
+
+  local handle_stderr = function(err, chunk)
+    assert(not err, err)
+    if chunk then
+      error_output = error_output .. chunk
+    end
+  end
+
+  local uv = vim.loop
+  local handle
+
+  local stdout = uv.new_pipe(false)
+  local stderr = uv.new_pipe(false)
+
+  local stdio = { nil, stdout, stderr }
+
+  handle = uv.spawn(
+    process,
+    { args = opts.args, cwd = opts.cwd or uv.cwd(), stdio = stdio },
+    vim.schedule_wrap(function(code)
+      if code ~= 0 then
+        stdout:read_stop()
+        stderr:read_stop()
+      end
+
+      local check = uv.new_check()
+      check:start(function()
+        for _, pipe in ipairs(stdio) do
+          if pipe and not pipe:is_closing() then
+            return
+          end
+        end
+        check:stop()
+        handle:close()
+        cb(code, output, error_output)
+      end)
+    end)
+  )
+
+  uv.read_start(stdout, handle_stdout)
+  uv.read_start(stderr, handle_stderr)
+
+  return handle
+end
+
+local function verify_core_plugins(verbose)
+  for _, spec in pairs(core_plugins) do
+    if not spec.disable then
+      table.insert(collection, {
+        name = get_short_name(spec),
+        commit = get_default_sha1(spec),
+        path = get_install_path(spec),
+      })
+    end
+  end
+
+  for _, entry in pairs(collection) do
+    local on_done = function(code, result, errors)
+      completed = completed + 1
+      if code ~= 0 then
+        io.write(errors .. "\n")
+        -- os.exit(code)
+      else
+        if verbose then
+          io.write(fmt("verified [%s]\n", entry.name))
+        end
+      end
+      local current_commit = result:gsub("\n", ""):gsub([[']], [[]])
+      -- just in case there are some extra qutoes or it's a longer commit hash
+      if current_commit ~= entry.commit then
+        io.write(fmt("mismatch at [%s]: expected [%s], got [%s]\n", entry.name, entry.commit, current_commit))
+        os.exit(1)
+      end
+    end
+
+    local handle = call_proc("git", { args = { "log", "--pretty='%h'", "-1" }, cwd = entry.path }, on_done)
+    assert(handle)
+    table.insert(active_jobs, handle)
+  end
+
+  vim.wait(#active_jobs * 60 * 1000, function()
+    return completed == #active_jobs
+  end)
+end
+
+verify_core_plugins()
+vim.cmd "q"

+ 5 - 0
utils/ci/verify_plugins.sh

@@ -0,0 +1,5 @@
+#!/usr/bin/env bash
+set -e
+
+lvim --headless \
+  -c "luafile ./utils/ci/verify_plugins.lua"

+ 12 - 1
utils/installer/install.sh

@@ -160,7 +160,7 @@ function detect_platform() {
       elif [ -f "/etc/fedora-release" ] || [ -f "/etc/redhat-release" ]; then
         RECOMMEND_INSTALL="sudo dnf install -y"
       elif [ -f "/etc/gentoo-release" ]; then
-        RECOMMEND_INSTALL="emerge install -y"
+        RECOMMEND_INSTALL="emerge -tv"
       else # assume debian based
         RECOMMEND_INSTALL="sudo apt install -y"
       fi
@@ -206,6 +206,15 @@ function check_neovim_min_version() {
   fi
 }
 
+function verify_core_plugins() {
+  msg "Verifying core plugins"
+  if ! bash "$LUNARVIM_BASE_DIR/utils/ci/verify_plugins.sh"; then
+    echo "[ERROR]: Unable to verify plugins, makde sure to manually run ':PackerSync' when starting lvim for the first time."
+    exit 1
+  fi
+  echo "Verification complete!"
+}
+
 function validate_lunarvim_files() {
   local verify_version_cmd='if v:errmsg != "" | cquit | else | quit | endif'
   if ! "$INSTALL_PREFIX/bin/lvim" --headless -c 'LvimUpdate' -c "$verify_version_cmd" &>/dev/null; then
@@ -418,6 +427,8 @@ function setup_lvim() {
     -c 'PackerSync'
 
   echo "Packer setup complete"
+
+  verify_core_plugins
 }
 
 function print_logo() {