-
Notifications
You must be signed in to change notification settings - Fork 175
/
preview.lua
152 lines (129 loc) · 3.44 KB
/
preview.lua
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
local Config = require("trouble.config")
local Render = require("trouble.view.render")
local Util = require("trouble.util")
local M = {}
M.preview = nil ---@type {item:trouble.Item, win:number, buf: number, close:fun()}?
function M.is_open()
return M.preview ~= nil
end
function M.is_win(win)
return M.preview and M.preview.win == win
end
function M.item()
return M.preview and M.preview.item
end
function M.close()
local preview = M.preview
M.preview = nil
if not preview then
return
end
Render.reset(preview.buf)
preview.close()
end
--- Create a preview buffer for an item.
--- If the item has a loaded buffer, use that,
--- otherwise create a new buffer.
---@param item trouble.Item
---@param opts? {scratch?:boolean}
function M.create(item, opts)
opts = opts or {}
local buf = item.buf or vim.fn.bufnr(item.filename)
if item.filename and vim.fn.isdirectory(item.filename) == 1 then
return
end
-- create a scratch preview buffer when needed
if not (buf and vim.api.nvim_buf_is_loaded(buf)) then
if opts.scratch then
buf = vim.api.nvim_create_buf(false, true)
vim.bo[buf].bufhidden = "wipe"
vim.bo[buf].buftype = "nofile"
local lines = Util.get_lines({ path = item.filename, buf = item.buf })
if not lines then
return
end
vim.api.nvim_buf_set_lines(buf, 0, -1, false, lines)
local ft = item:get_ft(buf)
if ft then
local lang = vim.treesitter.language.get_lang(ft)
if not pcall(vim.treesitter.start, buf, lang) then
vim.bo[buf].syntax = ft
end
end
else
vim.fn.bufload(buf)
end
end
-- make sure we highlight at least one character
local end_pos = { item.end_pos[1], item.end_pos[2] }
if end_pos[1] == item.pos[1] and end_pos[2] == item.pos[2] then
end_pos[2] = end_pos[2] + 1
end
-- highlight the line
Util.set_extmark(buf, Render.ns, item.pos[1] - 1, 0, {
end_row = end_pos[1],
hl_group = "CursorLine",
hl_eol = true,
strict = false,
})
-- highlight the range
Util.set_extmark(buf, Render.ns, item.pos[1] - 1, item.pos[2], {
end_row = end_pos[1] - 1,
end_col = end_pos[2],
hl_group = "TroublePreview",
strict = false,
})
return buf
end
---@param view trouble.View
---@param item trouble.Item
function M.open(view, item)
if M.item() == item then
return
end
if M.preview then
M.close()
end
local buf = M.create(item)
if not buf then
return
end
M.preview = M.preview_win(buf, view)
M.preview.buf = buf
M.preview.item = item
-- no autocmds should be triggered. So LSP's etc won't try to attach in the preview
Util.noautocmd(function()
vim.api.nvim_win_set_cursor(M.preview.win, item.pos)
vim.api.nvim_win_call(M.preview.win, function()
vim.cmd("norm! zzzv")
end)
end)
return item
end
---@param buf number
---@param view trouble.View
function M.preview_win(buf, view)
if view.opts.preview.type == "main" then
local main = view:main()
if not main then
Util.debug("No main window")
return
end
view.preview_win.opts.win = main.win
else
view.preview_win.opts.win = view.win.win
end
view.preview_win:open()
Util.noautocmd(function()
view.preview_win:set_buf(buf)
view.preview_win:set_options("win")
vim.w[view.preview_win.win].trouble_preview = true
end)
return {
win = view.preview_win.win,
close = function()
view.preview_win:close()
end,
}
end
return M