-
-
Notifications
You must be signed in to change notification settings - Fork 119
/
floating_text.lua
161 lines (119 loc) · 4.2 KB
/
floating_text.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
153
154
155
156
157
158
159
160
161
local vim = vim
local api = vim.api
local F = require("custom.functional")
local split = vim.split
local function split_lines(value)
if type(value) == type({}) then
return value
end
return split(value, '\n', true)
end
local function get_default_bufnr_and_namespace(bufnr, namespace)
if bufnr == nil then
bufnr = api.nvim_buf_get_number(0)
end
if namespace == nil then
namespace = -1
end
return bufnr, namespace
end
local M = {}
M._current_scratch = {}
-- Example: create a float with scratch buffer: >
-- let buf = nvim_create_buf(v:false, v:true)
-- call nvim_buf_set_lines(buf, 0, -1, v:true, ["test", "text"])
-- let opts = {'relative': 'cursor', 'width': 10, 'height': 2, 'col': 0,
-- \ 'row': 1, 'anchor': 'NW', 'style': 'minimal'}
-- let win = nvim_open_win(buf, 0, opts)
-- " optional: change highlight, otherwise Pmenu is used
-- call nvim_win_set_option(win, 'winhl', 'Normal:MyHighlight')
-- @param text str
-- @param bufnr number
-- @param namespace number
function M.create_floating_scratch(text, floating_options, bufnr, namespace)
bufnr, namespace = get_default_bufnr_and_namespace(bufnr, namespace)
M.close_floating_scratch(bufnr, namespace)
local buf = api.nvim_create_buf(false, true)
api.nvim_buf_set_lines(buf, 0, -1, true, split_lines(text))
local window_width = api.nvim_win_get_width(0)
local window_height = api.nvim_win_get_height(0)
local window_percentage = 0.2
if window_width > 140 then
window_percentage = 0.4
end
local floating_width = math.floor(window_width * window_percentage)
local floating_height = window_height - 2
-- TODO: Determine the opts that make this nice and easy.
local opts = {
relative="win",
width=floating_width,
height=floating_height,
anchor="NW",
style="minimal",
-- definitely needs work
col=window_width - floating_width - 1,
row=1, -- One row below the top row
}
local win = api.nvim_open_win(buf, false, opts)
api.nvim_win_set_option(win, 'winhl', 'Normal:MyHighlight')
api.nvim_win_set_option(win, 'wrap', false)
M.set_floating_scratch(bufnr, namespace, win)
if floating_options.border then
local border_win = M.create_window_border(opts)
M.set_floating_scratch(bufnr, namespace, border_win)
end
if not floating_options.no_scroll then
api.nvim_win_set_option(0, 'scrollbind', true)
api.nvim_win_set_option(win, 'scrollbind', true)
end
return win
end
function M.close_floating_scratch(bufnr, namespace)
bufnr, namespace = get_default_bufnr_and_namespace(bufnr, namespace)
if M._current_scratch[bufnr] then
if M._current_scratch[bufnr][namespace] then
for _, winnr in ipairs(M._current_scratch[bufnr][namespace]) do
api.nvim_win_close(winnr, false)
end
end
end
if M._current_scratch[bufnr] == nil then
M._current_scratch[bufnr] = {}
end
M._current_scratch[bufnr][namespace] = {}
end
function M.set_floating_scratch(bufnr, namespace, floating_win)
if M._current_scratch[bufnr] == nil then
M._current_scratch[bufnr] = {}
end
if M._current_scratch[bufnr][namespace] == nil then
M._current_scratch[bufnr][namespace] = {}
end
table.insert(M._current_scratch[bufnr][namespace], floating_win)
end
function M.create_window_border(original_window_options)
local win_height = original_window_options.height
local win_width = original_window_options.width
local row = original_window_options.row
local col = original_window_options.col
local relative = original_window_options.relative
local border_buf = vim.api.nvim_create_buf(false, true)
local border_lines = { '╔' .. string.rep('═', win_width) .. '╗' }
local middle_line = '║' .. string.rep(' ', win_width) .. '║'
for _=1, win_height do
table.insert(border_lines, middle_line)
end
table.insert(border_lines, '╚' .. string.rep('═', win_width) .. '╝')
local border_opts = {
style = "minimal",
relative = relative,
width = win_width + 2,
height = win_height + 2,
row = row - 1,
col = col - 1
}
vim.api.nvim_buf_set_lines(border_buf, 0, -1, false, border_lines)
local border_win = vim.api.nvim_open_win(border_buf, false, border_opts)
return border_win
end
return M