1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
|
local M = {}
local ns = nil
local log_buf = nil
local log_ns = nil
function M.init(hobs_ns)
ns = hobs_ns
log_ns = vim.api.nvim_create_namespace("hobs.nvim.log")
vim.api.nvim_set_hl(log_ns, "HobLogTimestamp", { fg = "grey", bold = true })
vim.api.nvim_set_hl(log_ns, "HobLogTagStarted", { fg = "#4ade80", bold = true })
vim.api.nvim_set_hl(log_ns, "HobLogTagFinished", { fg = "#60a5fa", bold = true })
vim.api.nvim_set_hl(log_ns, "HobLogTagFailed", { fg = "#f87171", bold = true })
vim.api.nvim_set_hl(log_ns, "HobLogTagError", { fg = "#fb923c", bold = true })
vim.api.nvim_set_hl(log_ns, "HobLogSed", { fg = "#a78bfa" })
vim.api.nvim_set_hl(log_ns, "HobLogSeparator", { fg = "#71717a" })
end
local function get_log_buf()
if log_buf and vim.api.nvim_buf_is_valid(log_buf) then
return log_buf
end
log_buf = vim.api.nvim_create_buf(false, true)
vim.api.nvim_buf_set_name(log_buf, "hobs://log")
vim.bo[log_buf].buftype = "nofile"
vim.bo[log_buf].bufhidden = "hide"
vim.bo[log_buf].swapfile = false
vim.bo[log_buf].filetype = "log"
vim.bo[log_buf].modifiable = false
return log_buf
end
local function append_to_log(lines, hl_group)
local buf = get_log_buf()
local base_row = vim.api.nvim_buf_line_count(buf)
vim.bo[buf].modifiable = true
vim.api.nvim_buf_set_lines(buf, -1, -1, false, lines)
vim.bo[buf].modifiable = false
if hl_group then
local end_row = vim.api.nvim_buf_line_count(buf) - 1
for row = base_row, end_row do
vim.api.nvim_buf_add_highlight(buf, log_ns, hl_group, row, 0, -1)
end
end
end
local function timestamp()
return os.date("%Y-%m-%d %H:%M:%S")
end
local function log_entry(tag, msg, hl_group)
local lines = vim.split(msg, "\n", { plain = true })
local prefix = string.format("[%s] %s:", timestamp(), tag)
lines[1] = prefix .. " " .. lines[1]
for i = 2, #lines do
lines[i] = "" .. lines[i]
end
if hl_group and #lines == 1 then
local buf = get_log_buf()
local base_row = vim.api.nvim_buf_line_count(buf)
vim.bo[buf].modifiable = true
vim.api.nvim_buf_set_lines(buf, -1, -1, false, lines)
local tag_end_col = #prefix
vim.api.nvim_buf_add_highlight(buf, log_ns, "HobLogTimestamp", base_row, 0, tag_end_col)
vim.api.nvim_buf_add_highlight(buf, log_ns, hl_group, base_row, tag_end_col, -1)
vim.bo[buf].modifiable = false
else
append_to_log(lines)
end
end
function M.log_info(msg, hl_group)
append_to_log({ string.format("[%s] INFO: %s", timestamp(), msg) }, hl_group)
end
function M.log_error(msg)
log_entry("ERROR", msg, "HobLogTagError")
end
function M.log_hob_started(id, filename, prompt)
local filename_short = vim.fn.fnamemodify(filename, ":t")
local msg = string.format("Hob %d started | %s | %s", id, filename_short, prompt)
log_entry("HOB", msg, "HobLogTagStarted")
end
function M.log_hob_working(id, status)
log_entry("HOB", string.format("Hob %d: %s", id, status))
end
function M.log_hob_sed(id, script)
local buf = get_log_buf()
vim.bo[buf].modifiable = true
local base_row = vim.api.nvim_buf_line_count(buf)
local separator_line = string.format("===== Hob %d sed script =====", id)
vim.api.nvim_buf_set_lines(buf, -1, -1, false, { separator_line })
vim.api.nvim_buf_add_highlight(buf, log_ns, "HobLogSeparator", base_row, 0, -1)
local sed_lines = vim.split(script, "\n", { plain = true })
if #sed_lines > 0 then
vim.api.nvim_buf_set_lines(buf, -1, -1, false, sed_lines)
for i = 1, #sed_lines do
vim.api.nvim_buf_add_highlight(buf, log_ns, "HobLogSed", base_row + i - 1, 0, -1)
end
end
local end_sep_row = vim.api.nvim_buf_line_count(buf) - 1
vim.api.nvim_buf_set_lines(buf, -1, -1, false, { "===== end sed script =====" })
vim.api.nvim_buf_add_highlight(buf, log_ns, "HobLogSeparator", end_sep_row, 0, -1)
vim.bo[buf].modifiable = false
end
function M.log_hob_finished(id)
log_entry("HOB", string.format("Hob %d finished and applied edit", id), "HobLogTagFinished")
end
function M.log_hob_failed(id, reason)
log_entry("HOB", string.format("Hob %d failed: %s", id, reason or "unknown error"), "HobLogTagFailed")
end
function M.log_hob_edit_failed(id, reason)
log_entry("HOB", string.format("Hob %d edit failed: %s", id, reason or "unknown error"), "HobLogTagFailed")
end
function M.open()
local buf = get_log_buf()
if not buf or not vim.api.nvim_buf_is_valid(buf) then
return
end
local win = vim.api.nvim_get_current_win()
local win_height = vim.api.nvim_win_get_height(win)
vim.cmd("botright split")
vim.api.nvim_win_set_buf(0, buf)
local log_height = math.min(15, math.ceil(win_height * 0.4))
vim.api.nvim_win_set_height(0, log_height)
vim.api.nvim_win_set_hl_ns(0, log_ns)
local lines_count = vim.api.nvim_buf_line_count(buf)
if lines_count > 0 then
local col = vim.fn.min({ vim.api.nvim_win_get_width(0) - 1, vim.fn.strwidth(vim.api.nvim_get_current_line()) })
vim.api.nvim_win_set_cursor(0, { lines_count, col })
end
vim.cmd("startinsert")
end
function M.reset()
if log_buf and vim.api.nvim_buf_is_valid(log_buf) then
vim.api.nvim_buf_delete(log_buf, { force = true })
log_buf = nil
end
end
return M
|