Ver código fonte

feat: Add an async logger using plenary (#1207)

Co-authored-by: rebuilt <memoryman51@hotmail.com>
kylo252 3 anos atrás
pai
commit
405423108f

+ 4 - 0
README.md

@@ -42,6 +42,10 @@ LVBRANCH=rolling bash <(curl -s https://raw.githubusercontent.com/lunarvim/lunar
 * If you want to keep launching LunarVim with the `nvim` command, add an alias entry to your shell's config file:  `alias nvim=lvim`.  To temporarily revert to the default `nvim` prefix it with a backslash `\nvim`.
 * Many options formerly available in `config.lua` have been renamed.  For details [look here](https://github.com/lunarvim/LunarVim/wiki/Breaking-changes-in-rolling)
 
+### Debugging LunarVim's configuration
+* To turn on debugging add these settings `lvim.log.level = debug` and use `<leader>Ll` to see the options of viewing the logfiles
+* You can also use install [lnav](https://github.com/tstack/lnav) and use it in a floating terminal. Make sure to set `lvim.builtin.terminal.active = true`.
+
 ### Fixing installation problems
 If your installation is stuck on `Ok to remove? [y/N]`, it means there are some leftovers, \
 you can run the script with `--overwrite` but be warned this will remove the following folders:

+ 2 - 0
lua/core/autopairs.lua

@@ -1,8 +1,10 @@
 -- if not package.loaded['nvim-autopairs'] then
 --   return
 -- end
+local Log = require "core.log"
 local status_ok, _ = pcall(require, "nvim-autopairs")
 if not status_ok then
+  Log:get_default().error "Failed to load autopairs"
   return
 end
 local npairs = require "nvim-autopairs"

+ 2 - 0
lua/core/compe.lua

@@ -1,4 +1,5 @@
 local M = {}
+local Log = require "core.log"
 M.config = function()
   lvim.builtin.compe = {
     enabled = true,
@@ -62,6 +63,7 @@ M.setup = function()
 
   local status_ok, compe = pcall(require, "compe")
   if not status_ok then
+    Log:get_default().error "Failed to load compe"
     return
   end
 

+ 2 - 0
lua/core/dap.lua

@@ -1,4 +1,5 @@
 local M = {}
+local Log = require "core.log"
 M.config = function()
   lvim.builtin.dap = {
     active = false,
@@ -14,6 +15,7 @@ end
 M.setup = function()
   local status_ok, dap = pcall(require, "dap")
   if not status_ok then
+    Log:get_default().error "Failed to load dap"
     return
   end
 

+ 2 - 0
lua/core/galaxyline.lua

@@ -1,8 +1,10 @@
 -- if not package.loaded['galaxyline'] then
 --   return
 -- end
+local Log = require "core.log"
 local status_ok, gl = pcall(require, "galaxyline")
 if not status_ok then
+  Log:get_default().error "Failed to load galaxyline"
   return
 end
 

+ 2 - 0
lua/core/gitsigns.lua

@@ -1,4 +1,5 @@
 local M = {}
+local Log = require "core.log"
 M.config = function()
   lvim.builtin.gitsigns = {
     signs = {
@@ -50,6 +51,7 @@ end
 M.setup = function()
   local status_ok, gitsigns = pcall(require, "gitsigns")
   if not status_ok then
+    Log:get_default().error "Failed to load gitsigns"
     return
   end
   gitsigns.setup(lvim.builtin.gitsigns)

+ 29 - 0
lua/core/log.lua

@@ -0,0 +1,29 @@
+local Log = {}
+
+--- Creates a log handle based on Plenary.log
+---@param opts these are passed verbatim to Plenary.log
+---@return log handle
+function Log:new(opts)
+  local status_ok, _ = pcall(require, "plenary.log")
+  if not status_ok then
+    return nil
+  end
+
+  local obj = require("plenary.log").new(opts)
+  local path = string.format("%s/%s.log", vim.api.nvim_call_function("stdpath", { "cache" }), opts.plugin)
+
+  obj.get_path = function()
+    return path
+  end
+
+  return obj
+end
+
+--- Creates or retrieves a log handle for the default logfile
+--- based on Plenary.log
+---@return log handle
+function Log:get_default()
+  return Log:new { plugin = "lunarvim", level = lvim.log.level }
+end
+
+return Log

+ 2 - 0
lua/core/nvimtree.lua

@@ -1,4 +1,5 @@
 local M = {}
+local Log = require "core.log"
 --
 M.config = function()
   lvim.builtin.nvimtree = {
@@ -49,6 +50,7 @@ end
 M.setup = function()
   local status_ok, nvim_tree_config = pcall(require, "nvim-tree.config")
   if not status_ok then
+    Log:get_default().error "Failed to load nvim-tree.config"
     return
   end
   local g = vim.g

+ 2 - 0
lua/core/telescope.lua

@@ -1,4 +1,5 @@
 local M = {}
+local Log = require "core.log"
 M.config = function()
   local status_ok, actions = pcall(require, "telescope.actions")
   if not status_ok then
@@ -79,6 +80,7 @@ end
 M.setup = function()
   local status_ok, telescope = pcall(require, "telescope")
   if not status_ok then
+    Log:get_default().error "Failed to load telescope"
     return
   end
   telescope.setup(lvim.builtin.telescope)

+ 45 - 3
lua/core/terminal.lua

@@ -1,8 +1,11 @@
 local M = {}
+local Log = require "core.log"
+local utils = require "utils"
+
 M.config = function()
   lvim.builtin["terminal"] = {
     -- size can be a number or function which is passed the current terminal
-    size = 5,
+    size = 20,
     -- open_mapping = [[<c-\>]],
     open_mapping = [[<c-t>]],
     hide_numbers = true, -- hide the number column in toggleterm buffers
@@ -11,7 +14,7 @@ M.config = function()
     shading_factor = 2, -- the degree by which to darken to terminal colour, default: 1 for dark backgrounds, 3 for light
     start_in_insert = true,
     insert_mappings = true, -- whether or not the open mapping applies in insert mode
-    persist_size = true,
+    persist_size = false,
     -- direction = 'vertical' | 'horizontal' | 'window' | 'float',
     direction = "float",
     close_on_exit = true, -- close the terminal window when the process exits
@@ -36,13 +39,16 @@ 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"}
-    execs = { { "lazygit", "gg", "LazyGit" } },
+    execs = {
+      { "lazygit", "gg", "LazyGit" },
+    },
   }
 end
 
 M.setup = function()
   local status_ok, terminal = pcall(require, "toggleterm")
   if not status_ok then
+    Log:get_default().error "Failed to load toggleterm"
     print(terminal)
     return
   end
@@ -88,4 +94,40 @@ M._exec_toggle = function(exec)
   exec_term:toggle()
 end
 
+local function get_log_path(name)
+  --handle custom paths not managed by Plenary.log
+  local logger = require "core.log"
+  local file
+  if name == "nvim" then
+    file = CACHE_PATH .. "/log"
+  else
+    file = logger:new({ plugin = name }):get_path()
+  end
+  if utils.is_file(file) then
+    return file
+  end
+end
+
+---Toggles a log viewer according to log.viewer.layout_config
+---@param name can be the name of any of the managed logs, e,g. "lunarvim" or the default ones {"nvim", "lsp", "packer.nvim"}
+M.toggle_log_view = function(name)
+  local logfile = get_log_path(name)
+  if not logfile then
+    return
+  end
+  local term_opts = vim.tbl_deep_extend("force", lvim.builtin.terminal, {
+    cmd = lvim.log.viewer.cmd .. " " .. logfile,
+    open_mapping = lvim.log.viewer.layout_config.open_mapping,
+    direction = lvim.log.viewer.layout_config.direction,
+    -- TODO: this might not be working as expected
+    size = lvim.log.viewer.layout_config.size,
+    float_opts = lvim.log.viewer.layout_config.float_opts,
+  })
+
+  local Terminal = require("toggleterm.terminal").Terminal
+  local log_view = Terminal:new(term_opts)
+  -- require("core.log"):get_default().debug("term", vim.inspect(term_opts))
+  log_view:toggle()
+end
+
 return M

+ 2 - 0
lua/core/treesitter.lua

@@ -1,4 +1,5 @@
 local M = {}
+local Log = require "core.log"
 M.config = function()
   lvim.builtin.treesitter = {
     ensure_installed = {}, -- one of "all", "maintained" (parsers with maintainers), or a list of languages
@@ -64,6 +65,7 @@ end
 M.setup = function()
   local status_ok, treesitter_configs = pcall(require, "nvim-treesitter.configs")
   if not status_ok then
+    Log:get_default().error "Failed to load nvim-treesitter.configs"
     return
   end
 

+ 19 - 1
lua/core/which-key.lua

@@ -1,4 +1,5 @@
 local M = {}
+local Log = require "core.log"
 M.config = function()
   lvim.builtin.which_key = {
     active = false,
@@ -173,8 +174,24 @@ M.config = function()
           "<cmd>lua require('core.info').toggle_popup(vim.bo.filetype)<cr>",
           "Toggle LunarVim Info",
         },
+        l = {
+          name = "+logs",
+          d = {
+            "<cmd>lua require('core.terminal').toggle_log_view('lunarvim')<cr>",
+            "view default log",
+          },
+          D = { "<cmd>edit ~/.cache/nvim/lunarvim.log<cr>", "Open the default logfile" },
+          n = { "<cmd>lua require('core.terminal').toggle_log_view('lsp')<cr>", "view lsp log" },
+          N = { "<cmd>edit ~/.cache/nvim/log<cr>", "Open the Neovim logfile" },
+          l = { "<cmd>lua require('core.terminal').toggle_log_view('nvim')<cr>", "view neovim log" },
+          L = { "<cmd>edit ~/.cache/nvim/lsp.log<cr>", "Open the LSP logfile" },
+          p = {
+            "<cmd>lua require('core.terminal').toggle_log_view('packer.nvim')<cr>",
+            "view packer log",
+          },
+          P = { "<cmd>edit ~/.cache/nvim/packer.nvim.log<cr>", "Open the Packer logfile" },
+        },
       },
-
       s = {
         name = "Search",
         b = { "<cmd>Telescope git_branches<cr>", "Checkout branch" },
@@ -206,6 +223,7 @@ M.setup = function()
   -- end
   local status_ok, which_key = pcall(require, "which-key")
   if not status_ok then
+    Log:get_default "Failed to load whichkey"
     return
   end
 

+ 16 - 1
lua/default-config.lua

@@ -34,6 +34,22 @@ lvim = {
     terminal = {},
   },
 
+  log = {
+    ---@usage can be { "trace", "debug", "info", "warn", "error", "fatal" },
+    level = "warn",
+    viewer = {
+      ---@usage this will fallback on "less +F" if not found
+      cmd = "lnav",
+      layout_config = {
+        ---@usage direction = 'vertical' | 'horizontal' | 'window' | 'float',
+        direction = "horizontal",
+        open_mapping = "",
+        size = 40,
+        float_opts = {},
+      },
+    },
+  },
+
   lsp = {
     completion = {
       item_kind = {
@@ -95,7 +111,6 @@ lvim = {
   },
 
   autocommands = {},
-  debug = false,
 }
 
 local schemas = nil

+ 4 - 0
lua/keymappings.lua

@@ -1,4 +1,5 @@
 local M = {}
+local Log = require "core.log"
 
 local generic_opts_any = { noremap = true, silent = true }
 
@@ -148,6 +149,9 @@ function M.config()
     lvim.keys.normal_mode["<A-Down>"] = lvim.keys.normal_mode["<C-Down>"]
     lvim.keys.normal_mode["<A-Left>"] = lvim.keys.normal_mode["<C-Left>"]
     lvim.keys.normal_mode["<A-Right>"] = lvim.keys.normal_mode["<C-Right>"]
+    if Log:get_default() then
+      Log:get_default().info "Activated mac keymappings"
+    end
   end
 end
 

+ 6 - 5
lua/lsp/init.lua

@@ -1,6 +1,5 @@
 local M = {}
-local u = require "utils"
-
+local Log = require "core.log"
 function M.config()
   vim.lsp.protocol.CompletionItemKind = lvim.lsp.completion.item_kind
 
@@ -93,9 +92,7 @@ function M.get_ls_capabilities(client_id)
 
   for k, v in pairs(client.resolved_capabilities) do
     if v == true then
-      -- print("got cap: ", vim.inspect(caps))
       table.insert(enabled_caps, k)
-      -- vim.list_extend(enabled_caps, cap)
     end
   end
 
@@ -105,19 +102,23 @@ end
 function M.common_on_init(client, bufnr)
   if lvim.lsp.on_init_callback then
     lvim.lsp.on_init_callback(client, bufnr)
+    Log:get_default().info "Called lsp.on_init_callback"
     return
   end
 
   local formatters = lvim.lang[vim.bo.filetype].formatters
   if not vim.tbl_isempty(formatters) and formatters[1]["exe"] ~= nil and formatters[1].exe ~= "" then
     client.resolved_capabilities.document_formatting = false
-    u.lvim_log(string.format("Overriding [%s] formatter with [%s]", client.name, formatters[1].exe))
+    Log:get_default().info(
+      string.format("Overriding language server [%s] with format provider [%s]", client.name, formatters[1].exe)
+    )
   end
 end
 
 function M.common_on_attach(client, bufnr)
   if lvim.lsp.on_attach_callback then
     lvim.lsp.on_attach_callback(client, bufnr)
+    Log:get_default().info "Called lsp.on_init_callback"
   end
   lsp_highlight_document(client)
   add_lsp_buffer_keybindings(bufnr)

+ 12 - 8
lua/lsp/null-ls.lua

@@ -1,5 +1,6 @@
 local M = {}
-local u = require "utils"
+local Log = require "core.log"
+
 local null_ls = require "null-ls"
 
 local nodejs_local_providers = { "prettier", "prettierd", "prettier_d_slim", "eslint_d", "eslint" }
@@ -54,20 +55,21 @@ local function validate_nodejs_provider(provider)
     --- use LSP to set root_dir
     local ts_client = require("utils").get_active_client_by_ft "typescript"
     if ts_client == nil then
-      u.lvim_log "Unable to determine root directory since tsserver didn't start correctly"
+      Log:get_default().error "Unable to determine root directory since tsserver didn't start correctly"
       return
     end
     root_dir = ts_client.config.root_dir
   end
   local local_nodejs_command = root_dir .. "/node_modules/.bin/" .. provider._opts.command
-  u.lvim_log(string.format("checking [%s] for local node module: [%s]", local_nodejs_command, vim.inspect(provider)))
+  Log:get_default().debug("checking for local node module: ", vim.inspect(provider))
+
   if vim.fn.executable(local_nodejs_command) == 1 then
     command_path = local_nodejs_command
   elseif vim.fn.executable(provider._opts.command) == 1 then
-    u.lvim_log(string.format("checking in global path instead for node module: [%s]", provider._opts.command))
+    Log:get_default().debug("checking in global path instead for node module", provider._opts.command)
     command_path = provider._opts.command
   else
-    u.lvim_log(string.format("Unable to find node module: [%s]", provider._opts.command))
+    Log:get_default().debug("Unable to find node module", provider._opts.command)
   end
   return command_path
 end
@@ -81,7 +83,7 @@ local function validate_provider_request(provider)
     return validate_nodejs_provider(provider)
   end
   if vim.fn.executable(provider._opts.command) ~= 1 then
-    u.lvim_log(string.format("Unable to find the path for: [%s]", vim.inspect(provider)))
+    Log:get_default().warn("Unable to find the path for", vim.inspect(provider))
     return
   end
   return provider._opts.command
@@ -90,6 +92,7 @@ end
 -- TODO: for linters and formatters with spaces and '-' replace with '_'
 function M.setup(filetype)
   for _, formatter in pairs(lvim.lang[filetype].formatters) do
+    Log:get_default().debug("validating format provider: ", formatter.exe)
     local builtin_formatter = null_ls.builtins.formatting[formatter.exe]
     if not vim.tbl_contains(M.requested_providers, builtin_formatter) then
       -- FIXME: why doesn't this work?
@@ -99,7 +102,7 @@ function M.setup(filetype)
       if resolved_path then
         builtin_formatter._opts.command = resolved_path
         table.insert(M.requested_providers, builtin_formatter)
-        u.lvim_log(string.format("Using format provider: [%s]", builtin_formatter.name))
+        Log:get_default().info("Using format provider", builtin_formatter.name)
       else
         -- mark it here to avoid re-doing the lookup again
         register_failed_request(filetype, formatter.exe, "formatters")
@@ -109,6 +112,7 @@ function M.setup(filetype)
 
   for _, linter in pairs(lvim.lang[filetype].linters) do
     local builtin_diagnoser = null_ls.builtins.diagnostics[linter.exe]
+    Log:get_default().debug("validating lint provider: ", linter.exe)
     -- special case: fallback to "eslint"
     -- https://github.com/jose-elias-alvarez/null-ls.nvim/blob/9b8458bd1648e84169a7e8638091ba15c2f20fc0/doc/BUILTINS.md#eslint
     -- if provider.exe
@@ -123,7 +127,7 @@ function M.setup(filetype)
       if resolved_path then
         builtin_diagnoser._opts.command = resolved_path
         table.insert(M.requested_providers, builtin_diagnoser)
-        u.lvim_log(string.format("Using linter provider: [%s]", builtin_diagnoser.name))
+        Log:get_default().info("Using linter provider", builtin_diagnoser.name)
       else
         -- mark it here to avoid re-doing the lookup again
         register_failed_request(filetype, linter.exe, "linters")

+ 2 - 0
lua/plugins.lua

@@ -135,6 +135,8 @@ return {
     config = function()
       local status_ok, nvim_comment = pcall(require, "nvim_comment")
       if not status_ok then
+        local Log = require "core.log"
+        Log:get_default().error "Failed to load nvim-comment"
         return
       end
       nvim_comment.setup()

+ 15 - 4
lua/utils/init.lua

@@ -1,4 +1,6 @@
 local utils = {}
+local Log = require "core.log"
+local uv = vim.loop
 
 -- recursive Print (structure, limit, separator)
 local function r_inspect_settings(structure, limit, separator)
@@ -68,6 +70,9 @@ function utils.toggle_autoformat()
         },
       },
     }
+    if Log:get_default() then
+      Log:get_default().info "Format on save active"
+    end
   end
 
   if not lvim.format_on_save then
@@ -76,6 +81,9 @@ function utils.toggle_autoformat()
         :autocmd! autoformat
       endif
     ]]
+    if Log:get_default() then
+      Log:get_default().info "Format on save off"
+    end
   end
 end
 
@@ -91,6 +99,7 @@ function utils.reload_lv_config()
   vim.cmd ":PackerInstall"
   require("keymappings").setup()
   -- vim.cmd ":PackerClean"
+  Log:get_default().info "Reloaded configuration"
 end
 
 function utils.check_lsp_client_active(name)
@@ -157,10 +166,12 @@ function utils.gsub_args(args)
   return args
 end
 
-function utils.lvim_log(msg)
-  if lvim.debug then
-    vim.notify(msg, vim.log.levels.DEBUG)
-  end
+--- Checks whether a given path exists and is a file.
+--@param filename (string) path to check
+--@returns (bool)
+function utils.is_file(filename)
+  local stat = uv.fs_stat(filename)
+  return stat and stat.type == "file" or false
 end
 
 return utils

+ 1 - 1
utils/installer/config.example.lua

@@ -9,7 +9,7 @@ an executable
 -- THESE ARE EXAMPLE CONFIGS FEEL FREE TO CHANGE TO WHATEVER YOU WANT
 
 -- general
-
+lvim.log.level = "warn"
 lvim.format_on_save = true
 lvim.lint_on_save = true
 lvim.colorscheme = "spacegray"