Skip to content

Commit

Permalink
feat: improved smart move. Added filetype exclusions and only move ou…
Browse files Browse the repository at this point in the history
…t when overlap > 30%. Fixes #130
  • Loading branch information
folke committed Oct 26, 2022
1 parent deda89a commit c63267d
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 10 deletions.
5 changes: 5 additions & 0 deletions lua/noice/config/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,11 @@ M.defaults = {
health = {
checker = true, -- Disable if you don't want health checks to run
},
smart_move = {
-- noice tries to move out of the way of existing floating windows.
-- add any filetypes here, that shouldn't trigger smart move.
excluded_filetypes = { "cmp_menu", "cmp_docs", "notify" },
},
throttle = 1000 / 30, -- how frequently does Noice need to check for ui updates? This has no effect when in blocking mode.
---@type NoiceConfigViews
views = {}, ---@see section on views
Expand Down
31 changes: 23 additions & 8 deletions lua/noice/util/nui.lua
Original file line number Diff line number Diff line change
Expand Up @@ -44,16 +44,31 @@ function M.bounds(win)
end

function M.overlap(win1, win2)
local b1 = M.bounds(win1)
local b2 = M.bounds(win2)
local bb1 = M.bounds(win1)
local bb2 = M.bounds(win2)

if b2.xmin > b1.xmax or b1.xmin > b2.xmax then
return false
end
if b2.ymin > b1.ymax or b1.ymin > b2.ymax then
return false
-- # determine the coordinates of the intersection rectangle
local x_left = math.max(bb1["xmin"], bb2["xmin"])
local y_top = math.max(bb1["ymin"], bb2["ymin"])
local x_right = math.min(bb1["xmax"], bb2["xmax"])
local y_bottom = math.min(bb1["ymax"], bb2["ymax"])

if x_right < x_left or y_bottom < y_top then
return 0.0
end
return true

-- # The intersection of two axis-aligned bounding boxes is always an
-- # axis-aligned bounding box
local intersection_area = math.max(x_right - x_left, 1) * math.max(y_bottom - y_top, 1)

-- # compute the area of both AABBs
local bb1_area = (bb1["xmax"] - bb1["xmin"]) * (bb1["ymax"] - bb1["ymin"])
local bb2_area = (bb2["xmax"] - bb2["xmin"]) * (bb2["ymax"] - bb2["ymin"])

-- # compute the intersection over union by taking the intersection
-- # area and dividing it by the sum of prediction + ground-truth
-- # areas - the interesection area
return intersection_area / (bb1_area + bb2_area - intersection_area)
end

---@param opts? NuiPopupOptions
Expand Down
30 changes: 28 additions & 2 deletions lua/noice/view/nui.lua
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ local require = require("noice.util.lazy")
local View = require("noice.view")
local Util = require("noice.util")
local Scrollbar = require("noice.view.scrollbar")
local Config = require("noice.config")

---@class NuiView: NoiceView
---@field _nui? NuiPopup|NuiSplit
Expand Down Expand Up @@ -36,6 +37,7 @@ function NuiView:update_options()
self._opts = vim.tbl_deep_extend("force", {}, {
buf_options = {
buftype = "nofile",
filetype = "noice",
},
win_options = {
foldenable = false,
Expand Down Expand Up @@ -71,17 +73,41 @@ function NuiView:smart_move()
if not (self._opts.type == "popup" and self._opts.relative and self._opts.relative.type == "editor") then
return
end
if not (self._nui.winid and vim.api.nvim_win_is_valid(self._nui.winid)) then
return
end
if not (self._nui.border.winid and vim.api.nvim_win_is_valid(self._nui.border.winid)) then
return
end

local nui_win = self._nui.border._.type == "complex" and self._nui.border.winid or self._nui.winid

local wins = vim.tbl_filter(function(win)
local ft = vim.bo[vim.api.nvim_win_get_buf(win)].filetype
return win ~= self._nui.winid
and ft ~= "noice"
and not vim.tbl_contains(Config.options.smart_move.excluded_filetypes, ft)
and not (self._nui.border and self._nui.border.winid == win)
and vim.api.nvim_win_is_valid(win)
and vim.bo[vim.api.nvim_win_get_buf(win)].filetype ~= "noice"
and vim.api.nvim_win_get_config(win).relative == "editor"
and Util.nui.overlap(self._nui.winid, win)
and Util.nui.overlap(nui_win, win) > 0.3
end, vim.api.nvim_list_wins())

if #wins > 0 then
-- local info = vim.tbl_map(function(win)
-- local buf = vim.api.nvim_win_get_buf(win)
-- return {
-- win = win,
-- buftype = vim.bo[buf].buftype,
-- ft = vim.bo[buf].filetype,
-- syntax = vim.bo[buf].syntax,
-- text = table.concat(vim.api.nvim_buf_get_lines(buf, 0, -1, false), "\n"),
-- name = vim.api.nvim_buf_get_name(buf),
-- -- config = vim.api.nvim_win_get_config(win),
-- area = Util.nui.overlap(nui_win, win),
-- }
-- end, wins)
-- dumpp(info)
local layout = self:get_layout()
layout.position.row = 2
self._nui:update_layout(layout)
Expand Down

0 comments on commit c63267d

Please sign in to comment.