-
Notifications
You must be signed in to change notification settings - Fork 4
Popupmenu


This file explains how the ui/cmdline.lua file works.
You can change how the pop-up menu looks by listening to the ext_popupmenu
events. You will typically use something like this,
---@type integer Namespace for the UI(s).
local namespace = vim.api.nvim_create_namespace("ui");
vim.ui_attach(namespace, {
ext_popupmenu = true
}, function (event, ...)
--- {event}, Event name
--- {...}, Arguments this event produces.
--- Do stuff...
end);
Tip
You can handle these events without using vim.schedule()
!
The pop-up menu receives the following events,
-
popupmenu_show
Triggered when the pop-up menu should be shown. -
popupmenu_select
Triggered when the selected item changes in the pop-up menu.
- popupmenu_hide
Triggered when the pop-up menu should be hidden.
The completion menu text is shown differently based on the current mode
.
This is used in command
mode and is created by popup.__strip_renderer() function.
It creates a single line by iterating over the lines and applying the highlights to the regions covered by each item.
The rendering process is similar to the command-line
so I won't be explaining it in detail here. It's a simple for loop that adds the completion text to a string and creates regions of highlights for that screen.
The text is then sent to nvim_buf_set_lines()
and the highlights are iterated over and the values are passed to nvim_buf_set_extmark()
.
This is used in other modes and is created by popup.__completion_renderer() function.
The rendering process here is a single for loop that adds a new line to the buffer(via nvim_buf_set_lines(buffer, -1, -1, false, { ... })
and an extmark for that line.
When using multi line pop-up menu, the menu gets placed based on the amount of free space around the cursor.
To get the cursor position on the screen we use vim.fn.screenpos()
. The returned value is a table which has a property named curscol
. This tells use which column the cursor is in.
It also has the row
property which tells us which row in the terminal the cursor is on.
ββββββββββββββββββββββββββ¬ββββββββ
β y = Screen row β β
β x = Screen column y β
β β β
β β β
βββββββββββββxββββββββββββββwββ¬βββ€
β w = Menu width ββββββ β
β h = Menu height hβββββ β
β ββββββ β
β ββββββ β
β β β
ββββββββββββββββββββββββββ΄ββββββββ
A simple condition is used to check which side to open the menu on. It looks like this,
-- Floating window's anchor based on
-- where it should be opened.
--
-- SE | SW
-- ---+---
-- NE | NW
---@type "NE" | "NW" | "SE" | "SW"
local anchor;
if y + h >= vim.o.lines then
-- Above
anchor = "S";
else
-- Below
anchor = "N";
end
if x + w >= vim.o.columns then
-- Left
anchor = anchor .. "E";
else
-- Right
anchor = anchor .. "W";
end