From c09c07c473a72852bef246b79851174d23b77eed Mon Sep 17 00:00:00 2001 From: Alexander Courtis Date: Sun, 6 Mar 2022 14:59:15 +1100 Subject: [PATCH 1/7] add file logging infrastructure --- lua/nvim-tree.lua | 9 +++++++++ lua/nvim-tree/log.lua | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) create mode 100644 lua/nvim-tree/log.lua diff --git a/lua/nvim-tree.lua b/lua/nvim-tree.lua index 9a41ac1713b..479b4a3b15e 100644 --- a/lua/nvim-tree.lua +++ b/lua/nvim-tree.lua @@ -2,6 +2,7 @@ local luv = vim.loop local api = vim.api local lib = require'nvim-tree.lib' +local log = require'nvim-tree.log' local colors = require'nvim-tree.colors' local renderer = require'nvim-tree.renderer' local view = require'nvim-tree.view' @@ -388,6 +389,13 @@ local DEFAULT_OPTS = { } } }, + log = { + enable = false, + types = { + all = false, + git = false, + }, + } } local function merge_options(conf) @@ -413,6 +421,7 @@ function M.setup(conf) manage_netrw(opts.disable_netrw, opts.hijack_netrw) + require'nvim-tree.log'.setup(opts) require'nvim-tree.actions'.setup(opts) require'nvim-tree.colors'.setup() require'nvim-tree.diagnostics'.setup(opts) diff --git a/lua/nvim-tree/log.lua b/lua/nvim-tree/log.lua new file mode 100644 index 00000000000..d51a884d336 --- /dev/null +++ b/lua/nvim-tree/log.lua @@ -0,0 +1,39 @@ +local M = { + config = nil, + path = nil, +} + +--- Write to log +--- @param typ as per config log.types +--- @param fmt for string.format +--- @param ... arguments for string.format +function M.raw(typ, fmt, ...) + if not M.path or not M.config.types[typ] and not M.config.types.all then + return + end + + local line = string.format(fmt, ...) + local file = io.open(M.path, "a") + io.output(file) + io.write(line) + io.close(file) +end + +-- Write to log with time and typ prefixed and a trailing newline +function M.line(typ, fmt, ...) + if not M.path or not M.config.types[typ] and not M.config.types.all then + return + end + + M.raw(typ, string.format("[%s] [%s] %s\n", os.date("%H:%M:%S"), typ, fmt), ...) +end + +function M.setup(opts) + M.config = opts.log + if M.config and M.config.enable and M.config.types then + M.path = string.format("%s/nvim-tree-%s-%s.log", vim.env.HOME, os.date("%H:%M:%S"), vim.env.USER) + end +end + +return M + From 0a59351004c58afb84c5d524165e3c5a89eab1fd Mon Sep 17 00:00:00 2001 From: Alexander Courtis Date: Sun, 6 Mar 2022 15:00:56 +1100 Subject: [PATCH 2/7] log git runner operations --- lua/nvim-tree/git/runner.lua | 57 ++++++++++++++++++++++++++++-------- lua/nvim-tree/log.lua | 5 ++-- 2 files changed, 47 insertions(+), 15 deletions(-) diff --git a/lua/nvim-tree/git/runner.lua b/lua/nvim-tree/git/runner.lua index aeb200635a9..5fbb5a63ae0 100644 --- a/lua/nvim-tree/git/runner.lua +++ b/lua/nvim-tree/git/runner.lua @@ -1,4 +1,5 @@ local uv = vim.loop +local log = require'nvim-tree.log' local utils = require'nvim-tree.utils' local Runner = {} @@ -40,30 +41,39 @@ function Runner:_handle_incoming_data(prev_output, incoming) return nil end -function Runner:_getopts(stdout_handle) +function Runner:_getopts(stdout_handle, stderr_handle) local untracked = self.list_untracked and '-u' or nil local ignored = (self.list_untracked and self.list_ignored) and '--ignored=matching' or '--ignored=no' return { args = {"--no-optional-locks", "status", "--porcelain=v1", ignored, untracked}, cwd = self.project_root, - stdio = { nil, stdout_handle, nil }, + stdio = { nil, stdout_handle, stderr_handle, }, } end +function Runner:_log_raw_output(output) + if output and type(output) == "string" then + log.raw("git", "%s", output) + end +end + function Runner:_run_git_job() local handle, pid local stdout = uv.new_pipe(false) + local stderr = uv.new_pipe(false) local timer = uv.new_timer() - local function on_finish() - self._done = true - if timer:is_closing() or stdout:is_closing() or (handle and handle:is_closing()) then + local function on_finish(rc) + self.rc = rc or 0 + if timer:is_closing() or stdout:is_closing() or stderr:is_closing() or (handle and handle:is_closing()) then return end timer:stop() timer:close() stdout:read_stop() + stderr:read_stop() stdout:close() + stderr:close() if handle then handle:close() end @@ -71,25 +81,37 @@ function Runner:_run_git_job() pcall(uv.kill, pid) end + local opts = self:_getopts(stdout, stderr) + log.line("git", "running job with timeout %dms", self.timeout) + log.line("git", "git %s", table.concat(opts.args, " ")) + handle, pid = uv.spawn( "git", - self:_getopts(stdout), - vim.schedule_wrap(function() on_finish() end) + opts, + vim.schedule_wrap(function(rc) on_finish(rc) end) ) - timer:start(self.timeout, 0, vim.schedule_wrap(function() on_finish() end)) + timer:start(self.timeout, 0, vim.schedule_wrap(function(rc) + on_finish(-1) + end)) local output_leftover = '' - local function manage_output(err, data) - if err then return end + local function manage_stdout(rc, data) + if rc then return end + self:_log_raw_output(data) output_leftover = self:_handle_incoming_data(output_leftover, data) end - uv.read_start(stdout, vim.schedule_wrap(manage_output)) + local function manage_stderr(rc, data) + self:_log_raw_output(data) + end + + uv.read_start(stdout, vim.schedule_wrap(manage_stdout)) + uv.read_start(stderr, vim.schedule_wrap(manage_stderr)) end function Runner:_wait() - while not vim.wait(30, function() return self._done end, 30) do end + while not vim.wait(30, function() return self.rc ~= nil end, 30) do end end -- This module runs a git process, which will be killed if it takes more than timeout which defaults to 400ms @@ -100,11 +122,20 @@ function Runner.run(opts) list_ignored = opts.list_ignored, timeout = opts.timeout or 400, output = {}, - _done = false + rc = nil, -- -1 indicates timeout }, Runner) self:_run_git_job() self:_wait() + + if (self.rc == -1) then + log.line("git", "job timed out") + elseif (self.rc ~= 0) then + log.line("git", "job failed with return code %d", self.rc) + else + log.line("git", "job success") + end + return self.output end diff --git a/lua/nvim-tree/log.lua b/lua/nvim-tree/log.lua index d51a884d336..be1106b4892 100644 --- a/lua/nvim-tree/log.lua +++ b/lua/nvim-tree/log.lua @@ -3,7 +3,7 @@ local M = { path = nil, } ---- Write to log +--- Write to log file --- @param typ as per config log.types --- @param fmt for string.format --- @param ... arguments for string.format @@ -19,7 +19,8 @@ function M.raw(typ, fmt, ...) io.close(file) end --- Write to log with time and typ prefixed and a trailing newline +-- Write to log file +-- time and typ are prefixed and a trailing newline is added function M.line(typ, fmt, ...) if not M.path or not M.config.types[typ] and not M.config.types.all then return From 7a03c79288e72e07abf1ed195af73d686167d854 Mon Sep 17 00:00:00 2001 From: Alexander Courtis Date: Sun, 6 Mar 2022 15:32:07 +1100 Subject: [PATCH 3/7] log configuration and mappings --- lua/nvim-tree.lua | 5 +++++ lua/nvim-tree/actions/init.lua | 4 ++++ lua/nvim-tree/log.lua | 2 +- 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/lua/nvim-tree.lua b/lua/nvim-tree.lua index 479b4a3b15e..b52c0329e2d 100644 --- a/lua/nvim-tree.lua +++ b/lua/nvim-tree.lua @@ -393,6 +393,7 @@ local DEFAULT_OPTS = { enable = false, types = { all = false, + config = false, git = false, }, } @@ -422,6 +423,10 @@ function M.setup(conf) manage_netrw(opts.disable_netrw, opts.hijack_netrw) require'nvim-tree.log'.setup(opts) + + log.line("config", "default config + user") + log.raw("config", "%s\n", vim.inspect(opts)) + require'nvim-tree.actions'.setup(opts) require'nvim-tree.colors'.setup() require'nvim-tree.diagnostics'.setup(opts) diff --git a/lua/nvim-tree/actions/init.lua b/lua/nvim-tree/actions/init.lua index 9726178f34b..0362a2758dd 100644 --- a/lua/nvim-tree/actions/init.lua +++ b/lua/nvim-tree/actions/init.lua @@ -1,6 +1,7 @@ local a = vim.api local lib = require'nvim-tree.lib' +local log = require'nvim-tree.log' local view = require'nvim-tree.view' local util = require'nvim-tree.utils' local nvim_tree_callback = require'nvim-tree.config'.nvim_tree_callback @@ -225,6 +226,9 @@ function M.setup(opts) else M.mappings = merge_mappings(options.list) end + + log.line("config", "active mappings") + log.raw("config", "%s\n", vim.inspect(M.mappings)) end return M diff --git a/lua/nvim-tree/log.lua b/lua/nvim-tree/log.lua index be1106b4892..5313fe92626 100644 --- a/lua/nvim-tree/log.lua +++ b/lua/nvim-tree/log.lua @@ -4,7 +4,7 @@ local M = { } --- Write to log file ---- @param typ as per config log.types +--- @param typ as per log.types config --- @param fmt for string.format --- @param ... arguments for string.format function M.raw(typ, fmt, ...) From dfdd071354b646c8892b4c375d568d136e1c45d7 Mon Sep 17 00:00:00 2001 From: Alexander Courtis Date: Sun, 6 Mar 2022 15:51:36 +1100 Subject: [PATCH 4/7] document file logging infrastructure --- README.md | 15 ++++++++++++++- doc/nvim-tree-lua.txt | 32 +++++++++++++++++++++++++++++++- 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 49937ce7b9e..b329bc652a8 100644 --- a/README.md +++ b/README.md @@ -181,7 +181,15 @@ require'nvim-tree'.setup { } } } - } + }, + log = { + enable = false, + types = { + all = false, + config = false, + git = false, + }, + }, } ``` @@ -302,6 +310,11 @@ You can toggle the help UI by pressing `g?`. 3. `toggle` has a second parameter which allows to toggle without focusing the explorer (`require"nvim-tree.toggle(false, false)`). 4. You can allow nvim-tree to behave like vinegar (see `:help nvim-tree-vinegar`). +## Diagnostic Logging + +You may enable diagnostic logging and a file `nvim-tree-HH:MM:SS-username.log` will be created in your home directory, containing logs from that nvim session. See `:help nvim-tree.log`. + +The files may become large and numerous, so it is advised to turn on logging to diagnose an issue or while reporting a bug, then turn it off. ## Screenshots diff --git a/doc/nvim-tree-lua.txt b/doc/nvim-tree-lua.txt index 5ac6a81645d..edfd169315e 100644 --- a/doc/nvim-tree-lua.txt +++ b/doc/nvim-tree-lua.txt @@ -148,7 +148,15 @@ function. } } }, - } + }, + log = { + enable = false, + types = { + all = false, + config = false, + git = false, + }, + }, } < @@ -447,6 +455,28 @@ Here is a list of the options available in the setup call: `buftype = { "nofile", "terminal", "help", }` `}` +*nvim-tree.log* +|log|: configuration for diagnostic logging + + - |log.enable|: enable logging to a file `nvim-tree-HH:MM:SS-username.log` + in your home directory. + type: `boolean` + default: `false` + + - |log.types|: specify which information to log + + - |log.types.all|: everything + type: `boolean` + default: `false` + + - |log.types.config|: options and mappings, at startup + type: `boolean` + default: `false` + + - |log.types.git|: git processing + type: `boolean` + default: `false` + ============================================================================== OPTIONS *nvim-tree-options* From 098fab9765240a6925217b47afb903cff35cde8c Mon Sep 17 00:00:00 2001 From: Alexander Courtis Date: Sun, 6 Mar 2022 16:08:56 +1100 Subject: [PATCH 5/7] style fixes --- lua/nvim-tree/git/runner.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lua/nvim-tree/git/runner.lua b/lua/nvim-tree/git/runner.lua index 5fbb5a63ae0..d0535539192 100644 --- a/lua/nvim-tree/git/runner.lua +++ b/lua/nvim-tree/git/runner.lua @@ -91,7 +91,7 @@ function Runner:_run_git_job() vim.schedule_wrap(function(rc) on_finish(rc) end) ) - timer:start(self.timeout, 0, vim.schedule_wrap(function(rc) + timer:start(self.timeout, 0, vim.schedule_wrap(function() on_finish(-1) end)) @@ -102,7 +102,7 @@ function Runner:_run_git_job() output_leftover = self:_handle_incoming_data(output_leftover, data) end - local function manage_stderr(rc, data) + local function manage_stderr(_, data) self:_log_raw_output(data) end From cf0e6cc4720323fef386db4271a85af76cf458ef Mon Sep 17 00:00:00 2001 From: Alexander Courtis Date: Mon, 7 Mar 2022 11:24:44 +1100 Subject: [PATCH 6/7] stylua fixes --- lua/nvim-tree.lua | 2 +- lua/nvim-tree/git/runner.lua | 12 +++++++----- lua/nvim-tree/log.lua | 6 +++--- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/lua/nvim-tree.lua b/lua/nvim-tree.lua index ff47ce7027d..cefc4a87a41 100644 --- a/lua/nvim-tree.lua +++ b/lua/nvim-tree.lua @@ -398,7 +398,7 @@ local DEFAULT_OPTS = { config = false, git = false, }, - } + }, } local function merge_options(conf) diff --git a/lua/nvim-tree/git/runner.lua b/lua/nvim-tree/git/runner.lua index b72ea1dbd5b..370828f92ea 100644 --- a/lua/nvim-tree/git/runner.lua +++ b/lua/nvim-tree/git/runner.lua @@ -47,7 +47,7 @@ function Runner:_getopts(stdout_handle, stderr_handle) return { args = { "--no-optional-locks", "status", "--porcelain=v1", ignored, untracked }, cwd = self.project_root, - stdio = { nil, stdout_handle, stderr_handle, }, + stdio = { nil, stdout_handle, stderr_handle }, } end @@ -119,9 +119,11 @@ function Runner:_run_git_job() end function Runner:_wait() - while not vim.wait(30, function() + local function is_done() return self.rc ~= nil - end, 30) do end + end + while not vim.wait(30, is_done) do + end end -- This module runs a git process, which will be killed if it takes more than timeout which defaults to 400ms @@ -138,9 +140,9 @@ function Runner.run(opts) self:_run_git_job() self:_wait() - if (self.rc == -1) then + if self.rc == -1 then log.line("git", "job timed out") - elseif (self.rc ~= 0) then + elseif self.rc ~= 0 then log.line("git", "job failed with return code %d", self.rc) else log.line("git", "job success") diff --git a/lua/nvim-tree/log.lua b/lua/nvim-tree/log.lua index 5313fe92626..b9ae16d836c 100644 --- a/lua/nvim-tree/log.lua +++ b/lua/nvim-tree/log.lua @@ -26,15 +26,15 @@ function M.line(typ, fmt, ...) return end - M.raw(typ, string.format("[%s] [%s] %s\n", os.date("%H:%M:%S"), typ, fmt), ...) + M.raw(typ, string.format("[%s] [%s] %s\n", os.date "%H:%M:%S", typ, fmt), ...) end function M.setup(opts) M.config = opts.log if M.config and M.config.enable and M.config.types then - M.path = string.format("%s/nvim-tree-%s-%s.log", vim.env.HOME, os.date("%H:%M:%S"), vim.env.USER) + M.path = string.format("%s/nvim-tree-%s-%s.log", vim.fn.stdpath "cache", os.date "%H:%M:%S", vim.env.USER) + print("nvim-tree.lua logging to " .. M.path) end end return M - From 7159020bb6e87840c06ffe14a5cfdb75694361fa Mon Sep 17 00:00:00 2001 From: Alexander Courtis Date: Mon, 7 Mar 2022 14:21:18 +1100 Subject: [PATCH 7/7] document log file locations --- README.md | 2 +- doc/nvim-tree-lua.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 9a177a71e9e..47106ec69bd 100644 --- a/README.md +++ b/README.md @@ -317,7 +317,7 @@ You can toggle the help UI by pressing `g?`. ## Diagnostic Logging -You may enable diagnostic logging and a file `nvim-tree-HH:MM:SS-username.log` will be created in your home directory, containing logs from that nvim session. See `:help nvim-tree.log`. +You may enable diagnostic logging and a file `nvim-tree-HH:MM:SS-username.log` will be created in `$XDG_CACHE_HOME/nvim`, usually `~/.cache/nvim`, containing logs from that nvim session. See `:help nvim-tree.log`. The files may become large and numerous, so it is advised to turn on logging to diagnose an issue or while reporting a bug, then turn it off. diff --git a/doc/nvim-tree-lua.txt b/doc/nvim-tree-lua.txt index 82714040041..5555eb3b813 100644 --- a/doc/nvim-tree-lua.txt +++ b/doc/nvim-tree-lua.txt @@ -463,7 +463,7 @@ Here is a list of the options available in the setup call: |log|: configuration for diagnostic logging - |log.enable|: enable logging to a file `nvim-tree-HH:MM:SS-username.log` - in your home directory. + in $XDG_CACHE_HOME/nvim type: `boolean` default: `false`