Skip to content

Commit edb76cc

Browse files
authored
feat: allow pos="center", row=0, line=0 (#227)
1 parent ce8f7fa commit edb76cc

File tree

3 files changed

+60
-42
lines changed

3 files changed

+60
-42
lines changed

POPUP.md

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ stablization and any required features are merged into Neovim, we can upstream
1010
this and expose the API in vimL to create better compatibility.
1111

1212
## Notices
13+
- **2021-09-19:** we now follow Vim's convention of the first line/column of the screen being indexed 1, so that 0 can be used for centering.
1314
- **2021-08-19:** we now follow Vim's default to `noautocmd` on popup creation. This can be overriden with `vim_options.noautocmd=false`
1415

1516
## List of Neovim Features Required:

lua/plenary/popup/init.lua

+43-38
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,43 @@ function popup.create(what, vim_options)
9898
local win_opts = {}
9999
win_opts.relative = "editor"
100100

101+
-- Feels like maxheight, minheight, maxwidth, minwidth will all be related
102+
--
103+
-- maxheight Maximum height of the contents, excluding border and padding.
104+
-- minheight Minimum height of the contents, excluding border and padding.
105+
-- maxwidth Maximum width of the contents, excluding border, padding and scrollbar.
106+
-- minwidth Minimum width of the contents, excluding border, padding and scrollbar.
107+
local width = vim_options.width or 1
108+
local height
109+
if type(what) == "number" then
110+
height = vim.api.nvim_buf_line_count(what)
111+
else
112+
for _, v in ipairs(what) do
113+
width = math.max(width, #v)
114+
end
115+
height = #what
116+
end
117+
win_opts.width = utils.bounded(width, vim_options.minwidth, vim_options.maxwidth)
118+
win_opts.height = utils.bounded(height, vim_options.minheight, vim_options.maxheight)
119+
120+
-- pos
121+
--
122+
-- Using "topleft", "topright", "botleft", "botright" defines what corner of the popup "line"
123+
-- and "col" are used for. When not set "topleft" behaviour is used.
124+
-- Alternatively "center" can be used to position the popup in the center of the Neovim window,
125+
-- in which case "line" and "col" are ignored.
126+
if vim_options.pos then
127+
if vim_options.pos == "center" then
128+
vim_options.line = 0
129+
vim_options.col = 0
130+
win_opts.anchor = "NW"
131+
else
132+
win_opts.anchor = popup._pos_map[vim_options.pos]
133+
end
134+
else
135+
win_opts.anchor = "NW" -- This is the default, but makes `posinvert` easier to implement
136+
end
137+
101138
local cursor_relative_pos = function(pos_str, dim)
102139
assert(string.find(pos_str, "^cursor"), "Invalid value for " .. dim)
103140
win_opts.relative = "cursor"
@@ -110,37 +147,24 @@ function popup.create(what, vim_options)
110147
return line
111148
end
112149

113-
if vim_options.line then
150+
if vim_options.line and vim_options.line ~= 0 then
114151
if type(vim_options.line) == "string" then
115152
win_opts.row = cursor_relative_pos(vim_options.line, "row")
116153
else
117-
win_opts.row = vim_options.line
154+
win_opts.row = vim_options.line - 1
118155
end
119156
else
120-
-- TODO: It says it needs to be "vertically cenetered"?...
121-
-- wut is that.
122-
win_opts.row = 0
157+
win_opts.row = math.floor((vim.o.lines - win_opts.height) / 2)
123158
end
124159

125-
if vim_options.col then
160+
if vim_options.col and vim_options.col ~= 0 then
126161
if type(vim_options.col) == "string" then
127162
win_opts.col = cursor_relative_pos(vim_options.col, "col")
128163
else
129-
win_opts.col = vim_options.col
164+
win_opts.col = vim_options.col - 1
130165
end
131166
else
132-
-- TODO: It says it needs to be "horizontally cenetered"?...
133-
win_opts.col = 0
134-
end
135-
136-
if vim_options.pos then
137-
if vim_options.pos == "center" then
138-
-- TODO: Do centering..
139-
else
140-
win_opts.anchor = popup._pos_map[vim_options.pos]
141-
end
142-
else
143-
win_opts.anchor = "NW" -- This is the default, but makes `posinvert` easier to implement
167+
win_opts.col = math.floor((vim.o.columns - win_opts.width) / 2)
144168
end
145169

146170
-- , fixed When FALSE (the default), and:
@@ -153,25 +177,6 @@ function popup.create(what, vim_options)
153177

154178
win_opts.style = "minimal"
155179

156-
-- Feels like maxheight, minheight, maxwidth, minwidth will all be related
157-
--
158-
-- maxheight Maximum height of the contents, excluding border and padding.
159-
-- minheight Minimum height of the contents, excluding border and padding.
160-
-- maxwidth Maximum width of the contents, excluding border, padding and scrollbar.
161-
-- minwidth Minimum width of the contents, excluding border, padding and scrollbar.
162-
local width = vim_options.width or 1
163-
local height
164-
if type(what) == "number" then
165-
height = vim.api.nvim_buf_line_count(what)
166-
else
167-
for _, v in ipairs(what) do
168-
width = math.max(width, #v)
169-
end
170-
height = #what
171-
end
172-
win_opts.width = utils.bounded(width, vim_options.minwidth, vim_options.maxwidth)
173-
win_opts.height = utils.bounded(height, vim_options.minheight, vim_options.maxheight)
174-
175180
-- posinvert, When FALSE the value of "pos" is always used. When
176181
-- , TRUE (the default) and the popup does not fit
177182
-- , vertically and there is more space on the other side

tests/plenary/strings_spec.lua

+16-4
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,14 @@ describe("strings", function()
5050
{ args = { "abcde", 6, nil, 1 }, expected = { single = "abcde", double = "abcde" } },
5151
{ args = { "abcde", 5, nil, 1 }, expected = { single = "abcde", double = "abcde" } },
5252
{ args = { "abcde", 4, nil, 1 }, expected = { single = "abc…", double = "ab…" } },
53-
{ args = { "アイウエオ", 11, nil, 1 }, expected = { single = "アイウエオ", double = "アイウエオ" } },
54-
{ args = { "アイウエオ", 10, nil, 1 }, expected = { single = "アイウエオ", double = "アイウエオ" } },
53+
{
54+
args = { "アイウエオ", 11, nil, 1 },
55+
expected = { single = "アイウエオ", double = "アイウエオ" },
56+
},
57+
{
58+
args = { "アイウエオ", 10, nil, 1 },
59+
expected = { single = "アイウエオ", double = "アイウエオ" },
60+
},
5561
{ args = { "アイウエオ", 9, nil, 1 }, expected = { single = "アイウエ…", double = "アイウ…" } },
5662
{ args = { "アイウエオ", 8, nil, 1 }, expected = { single = "アイウ…", double = "アイウ…" } },
5763
{ args = { "├─┤", 7, nil, 1 }, expected = { single = "├─┤", double = "├─┤" } },
@@ -64,8 +70,14 @@ describe("strings", function()
6470
{ args = { "abcde", 6, nil, -1 }, expected = { single = "abcde", double = "abcde" } },
6571
{ args = { "abcde", 5, nil, -1 }, expected = { single = "abcde", double = "abcde" } },
6672
{ args = { "abcde", 4, nil, -1 }, expected = { single = "…cde", double = "…de" } },
67-
{ args = { "アイウエオ", 11, nil, -1 }, expected = { single = "アイウエオ", double = "アイウエオ" } },
68-
{ args = { "アイウエオ", 10, nil, -1 }, expected = { single = "アイウエオ", double = "アイウエオ" } },
73+
{
74+
args = { "アイウエオ", 11, nil, 1 },
75+
expected = { single = "アイウエオ", double = "アイウエオ" },
76+
},
77+
{
78+
args = { "アイウエオ", 10, nil, 1 },
79+
expected = { single = "アイウエオ", double = "アイウエオ" },
80+
},
6981
{ args = { "アイウエオ", 9, nil, -1 }, expected = { single = "…イウエオ", double = "…ウエオ" } },
7082
{ args = { "アイウエオ", 8, nil, -1 }, expected = { single = "…ウエオ", double = "…ウエオ" } },
7183
{ args = { "├─┤", 7, nil, -1 }, expected = { single = "├─┤", double = "├─┤" } },

0 commit comments

Comments
 (0)