Skip to content

Commit 19075f4

Browse files
authored
File logging (#1053)
* add file logging infrastructure * log git runner operations * log configuration and mappings * document file logging infrastructure * style fixes * stylua fixes * document log file locations
1 parent 0816064 commit 19075f4

File tree

6 files changed

+148
-17
lines changed

6 files changed

+148
-17
lines changed

README.md

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,15 @@ require'nvim-tree'.setup {
186186
}
187187
}
188188
}
189-
}
189+
},
190+
log = {
191+
enable = false,
192+
types = {
193+
all = false,
194+
config = false,
195+
git = false,
196+
},
197+
},
190198
}
191199
```
192200

@@ -307,6 +315,11 @@ You can toggle the help UI by pressing `g?`.
307315
3. `toggle` has a second parameter which allows to toggle without focusing the explorer (`require"nvim-tree.toggle(false, false)`).
308316
4. You can allow nvim-tree to behave like vinegar (see `:help nvim-tree-vinegar`).
309317

318+
## Diagnostic Logging
319+
320+
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`.
321+
322+
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.
310323

311324
## Screenshots
312325

doc/nvim-tree-lua.txt

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,15 @@ function.
152152
}
153153
}
154154
},
155-
}
155+
},
156+
log = {
157+
enable = false,
158+
types = {
159+
all = false,
160+
config = false,
161+
git = false,
162+
},
163+
},
156164
}
157165
<
158166

@@ -451,6 +459,28 @@ Here is a list of the options available in the setup call:
451459
`buftype = { "nofile", "terminal", "help", }`
452460
`}`
453461

462+
*nvim-tree.log*
463+
|log|: configuration for diagnostic logging
464+
465+
- |log.enable|: enable logging to a file `nvim-tree-HH:MM:SS-username.log`
466+
in $XDG_CACHE_HOME/nvim
467+
type: `boolean`
468+
default: `false`
469+
470+
- |log.types|: specify which information to log
471+
472+
- |log.types.all|: everything
473+
type: `boolean`
474+
default: `false`
475+
476+
- |log.types.config|: options and mappings, at startup
477+
type: `boolean`
478+
default: `false`
479+
480+
- |log.types.git|: git processing
481+
type: `boolean`
482+
default: `false`
483+
454484
==============================================================================
455485
OPTIONS *nvim-tree-options*
456486

lua/nvim-tree.lua

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ local luv = vim.loop
22
local api = vim.api
33

44
local lib = require "nvim-tree.lib"
5+
local log = require "nvim-tree.log"
56
local colors = require "nvim-tree.colors"
67
local renderer = require "nvim-tree.renderer"
78
local view = require "nvim-tree.view"
@@ -390,6 +391,14 @@ local DEFAULT_OPTS = {
390391
},
391392
},
392393
},
394+
log = {
395+
enable = false,
396+
types = {
397+
all = false,
398+
config = false,
399+
git = false,
400+
},
401+
},
393402
}
394403

395404
local function merge_options(conf)
@@ -415,6 +424,11 @@ function M.setup(conf)
415424

416425
manage_netrw(opts.disable_netrw, opts.hijack_netrw)
417426

427+
require("nvim-tree.log").setup(opts)
428+
429+
log.line("config", "default config + user")
430+
log.raw("config", "%s\n", vim.inspect(opts))
431+
418432
require("nvim-tree.actions").setup(opts)
419433
require("nvim-tree.colors").setup()
420434
require("nvim-tree.diagnostics").setup(opts)

lua/nvim-tree/actions/init.lua

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
local a = vim.api
22

33
local lib = require "nvim-tree.lib"
4+
local log = require "nvim-tree.log"
45
local view = require "nvim-tree.view"
56
local util = require "nvim-tree.utils"
67
local nvim_tree_callback = require("nvim-tree.config").nvim_tree_callback
@@ -231,6 +232,9 @@ function M.setup(opts)
231232
else
232233
M.mappings = merge_mappings(options.list)
233234
end
235+
236+
log.line("config", "active mappings")
237+
log.raw("config", "%s\n", vim.inspect(M.mappings))
234238
end
235239

236240
return M

lua/nvim-tree/git/runner.lua

Lines changed: 45 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
local uv = vim.loop
2+
local log = require "nvim-tree.log"
23
local utils = require "nvim-tree.utils"
34

45
local Runner = {}
@@ -40,68 +41,88 @@ function Runner:_handle_incoming_data(prev_output, incoming)
4041
return nil
4142
end
4243

43-
function Runner:_getopts(stdout_handle)
44+
function Runner:_getopts(stdout_handle, stderr_handle)
4445
local untracked = self.list_untracked and "-u" or nil
4546
local ignored = (self.list_untracked and self.list_ignored) and "--ignored=matching" or "--ignored=no"
4647
return {
4748
args = { "--no-optional-locks", "status", "--porcelain=v1", ignored, untracked },
4849
cwd = self.project_root,
49-
stdio = { nil, stdout_handle, nil },
50+
stdio = { nil, stdout_handle, stderr_handle },
5051
}
5152
end
5253

54+
function Runner:_log_raw_output(output)
55+
if output and type(output) == "string" then
56+
log.raw("git", "%s", output)
57+
end
58+
end
59+
5360
function Runner:_run_git_job()
5461
local handle, pid
5562
local stdout = uv.new_pipe(false)
63+
local stderr = uv.new_pipe(false)
5664
local timer = uv.new_timer()
5765

58-
local function on_finish()
59-
self._done = true
60-
if timer:is_closing() or stdout:is_closing() or (handle and handle:is_closing()) then
66+
local function on_finish(rc)
67+
self.rc = rc or 0
68+
if timer:is_closing() or stdout:is_closing() or stderr:is_closing() or (handle and handle:is_closing()) then
6169
return
6270
end
6371
timer:stop()
6472
timer:close()
6573
stdout:read_stop()
74+
stderr:read_stop()
6675
stdout:close()
76+
stderr:close()
6777
if handle then
6878
handle:close()
6979
end
7080

7181
pcall(uv.kill, pid)
7282
end
7383

84+
local opts = self:_getopts(stdout, stderr)
85+
log.line("git", "running job with timeout %dms", self.timeout)
86+
log.line("git", "git %s", table.concat(opts.args, " "))
87+
7488
handle, pid = uv.spawn(
7589
"git",
76-
self:_getopts(stdout),
77-
vim.schedule_wrap(function()
78-
on_finish()
90+
opts,
91+
vim.schedule_wrap(function(rc)
92+
on_finish(rc)
7993
end)
8094
)
8195

8296
timer:start(
8397
self.timeout,
8498
0,
8599
vim.schedule_wrap(function()
86-
on_finish()
100+
on_finish(-1)
87101
end)
88102
)
89103

90104
local output_leftover = ""
91-
local function manage_output(err, data)
105+
local function manage_stdout(err, data)
92106
if err then
93107
return
94108
end
109+
self:_log_raw_output(data)
95110
output_leftover = self:_handle_incoming_data(output_leftover, data)
96111
end
97112

98-
uv.read_start(stdout, vim.schedule_wrap(manage_output))
113+
local function manage_stderr(_, data)
114+
self:_log_raw_output(data)
115+
end
116+
117+
uv.read_start(stdout, vim.schedule_wrap(manage_stdout))
118+
uv.read_start(stderr, vim.schedule_wrap(manage_stderr))
99119
end
100120

101121
function Runner:_wait()
102-
while not vim.wait(30, function()
103-
return self._done
104-
end, 30) do
122+
local function is_done()
123+
return self.rc ~= nil
124+
end
125+
while not vim.wait(30, is_done) do
105126
end
106127
end
107128

@@ -113,11 +134,20 @@ function Runner.run(opts)
113134
list_ignored = opts.list_ignored,
114135
timeout = opts.timeout or 400,
115136
output = {},
116-
_done = false,
137+
rc = nil, -- -1 indicates timeout
117138
}, Runner)
118139

119140
self:_run_git_job()
120141
self:_wait()
142+
143+
if self.rc == -1 then
144+
log.line("git", "job timed out")
145+
elseif self.rc ~= 0 then
146+
log.line("git", "job failed with return code %d", self.rc)
147+
else
148+
log.line("git", "job success")
149+
end
150+
121151
return self.output
122152
end
123153

lua/nvim-tree/log.lua

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
local M = {
2+
config = nil,
3+
path = nil,
4+
}
5+
6+
--- Write to log file
7+
--- @param typ as per log.types config
8+
--- @param fmt for string.format
9+
--- @param ... arguments for string.format
10+
function M.raw(typ, fmt, ...)
11+
if not M.path or not M.config.types[typ] and not M.config.types.all then
12+
return
13+
end
14+
15+
local line = string.format(fmt, ...)
16+
local file = io.open(M.path, "a")
17+
io.output(file)
18+
io.write(line)
19+
io.close(file)
20+
end
21+
22+
-- Write to log file
23+
-- time and typ are prefixed and a trailing newline is added
24+
function M.line(typ, fmt, ...)
25+
if not M.path or not M.config.types[typ] and not M.config.types.all then
26+
return
27+
end
28+
29+
M.raw(typ, string.format("[%s] [%s] %s\n", os.date "%H:%M:%S", typ, fmt), ...)
30+
end
31+
32+
function M.setup(opts)
33+
M.config = opts.log
34+
if M.config and M.config.enable and M.config.types then
35+
M.path = string.format("%s/nvim-tree-%s-%s.log", vim.fn.stdpath "cache", os.date "%H:%M:%S", vim.env.USER)
36+
print("nvim-tree.lua logging to " .. M.path)
37+
end
38+
end
39+
40+
return M

0 commit comments

Comments
 (0)