feat: support preview from floating window (#403)
* implement floating window * reset width on closing window * use gap from new config parameter * use minimal style for preview in floating * lower z-index * add configuration of preview position in floating window * fix in verions earlier than nvim 0.10 * close preview on opening floating window Close the any existing preview because otherwise strange errors happen when the preview is open and the floating window is opened at the same time. * reset formatting changes * remove empty line * change z-index of preview window to floating window z-index * add configurations to oil.txt * formatting * add auto configuration * update oil doc * refactor: move logic into layout.lua and eliminate flicker * fix: floating preview window title is file name * doc: clarify default_file_explorer * refactor: don't need a preview_gap option * refactor: only find preview win in current tabpage --------- Co-authored-by: Steven Arcangeli <stevearc@stevearc.com>
This commit is contained in:
parent
0883b109a7
commit
59b3dab6f7
6 changed files with 162 additions and 47 deletions
|
|
@ -127,7 +127,7 @@ You can open a directory with `:edit <path>` or `:Oil <path>`. To open oil in a
|
|||
```lua
|
||||
require("oil").setup({
|
||||
-- Oil will take over directory buffers (e.g. `vim .` or `:e src/`)
|
||||
-- Set to false if you still want to use netrw.
|
||||
-- Set to false if you want some other plugin (e.g. netrw) to open when you edit directories.
|
||||
default_file_explorer = true,
|
||||
-- Id is automatically added at the beginning, and name at the end
|
||||
-- See :help oil-columns
|
||||
|
|
@ -248,6 +248,8 @@ require("oil").setup({
|
|||
win_options = {
|
||||
winblend = 0,
|
||||
},
|
||||
-- preview_split: Split direction: "auto", "left", "right", "above", "below".
|
||||
preview_split = "auto",
|
||||
-- This is the config that will be passed to nvim_open_win.
|
||||
-- Change values here to customize the layout
|
||||
override = function(conf)
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ CONFIG *oil-confi
|
|||
>lua
|
||||
require("oil").setup({
|
||||
-- Oil will take over directory buffers (e.g. `vim .` or `:e src/`)
|
||||
-- Set to false if you still want to use netrw.
|
||||
-- Set to false if you want some other plugin (e.g. netrw) to open when you edit directories.
|
||||
default_file_explorer = true,
|
||||
-- Id is automatically added at the beginning, and name at the end
|
||||
-- See :help oil-columns
|
||||
|
|
@ -138,6 +138,8 @@ CONFIG *oil-confi
|
|||
win_options = {
|
||||
winblend = 0,
|
||||
},
|
||||
-- preview_split: Split direction: "auto", "left", "right", "above", "below".
|
||||
preview_split = "auto",
|
||||
-- This is the config that will be passed to nvim_open_win.
|
||||
-- Change values here to customize the layout
|
||||
override = function(conf)
|
||||
|
|
|
|||
|
|
@ -80,6 +80,11 @@ M.preview = {
|
|||
local cur_id = vim.w[winid].oil_entry_id
|
||||
if entry.id == cur_id then
|
||||
vim.api.nvim_win_close(winid, true)
|
||||
if util.is_floating_win() then
|
||||
local layout = require("oil.layout")
|
||||
local win_opts = layout.get_fullscreen_win_opts()
|
||||
vim.api.nvim_win_set_config(0, win_opts)
|
||||
end
|
||||
return
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
local default_config = {
|
||||
-- Oil will take over directory buffers (e.g. `vim .` or `:e src/`)
|
||||
-- Set to false if you still want to use netrw.
|
||||
-- Set to false if you want some other plugin (e.g. netrw) to open when you edit directories.
|
||||
default_file_explorer = true,
|
||||
-- Id is automatically added at the beginning, and name at the end
|
||||
-- See :help oil-columns
|
||||
|
|
@ -123,6 +123,8 @@ local default_config = {
|
|||
win_options = {
|
||||
winblend = 0,
|
||||
},
|
||||
-- preview_split: Split direction: "auto", "left", "right", "above", "below".
|
||||
preview_split = "auto",
|
||||
-- This is the config that will be passed to nvim_open_win.
|
||||
-- Change values here to customize the layout
|
||||
override = function(conf)
|
||||
|
|
|
|||
109
lua/oil/init.lua
109
lua/oil/init.lua
|
|
@ -244,6 +244,7 @@ M.open_float = function(dir)
|
|||
local layout = require("oil.layout")
|
||||
local util = require("oil.util")
|
||||
local view = require("oil.view")
|
||||
|
||||
local parent_url, basename = M.get_url_for_path(dir)
|
||||
if not parent_url then
|
||||
return
|
||||
|
|
@ -254,31 +255,7 @@ M.open_float = function(dir)
|
|||
|
||||
local bufnr = vim.api.nvim_create_buf(false, true)
|
||||
vim.bo[bufnr].bufhidden = "wipe"
|
||||
local total_width = vim.o.columns
|
||||
local total_height = layout.get_editor_height()
|
||||
local width = total_width - 2 * config.float.padding
|
||||
if config.float.border ~= "none" then
|
||||
width = width - 2 -- The border consumes 1 col on each side
|
||||
end
|
||||
if config.float.max_width > 0 then
|
||||
width = math.min(width, config.float.max_width)
|
||||
end
|
||||
local height = total_height - 2 * config.float.padding
|
||||
if config.float.max_height > 0 then
|
||||
height = math.min(height, config.float.max_height)
|
||||
end
|
||||
local row = math.floor((total_height - height) / 2)
|
||||
local col = math.floor((total_width - width) / 2) - 1 -- adjust for border width
|
||||
local win_opts = {
|
||||
relative = "editor",
|
||||
width = width,
|
||||
height = height,
|
||||
row = row,
|
||||
col = col,
|
||||
border = config.float.border,
|
||||
zindex = 45,
|
||||
}
|
||||
win_opts = config.float.override(win_opts) or win_opts
|
||||
local win_opts = layout.get_fullscreen_win_opts()
|
||||
|
||||
local original_winid = vim.api.nvim_get_current_win()
|
||||
local winid = vim.api.nvim_open_win(bufnr, true, win_opts)
|
||||
|
|
@ -332,12 +309,13 @@ M.open_float = function(dir)
|
|||
if not vim.api.nvim_win_is_valid(winid) or vim.api.nvim_win_get_buf(winid) ~= winbuf then
|
||||
return
|
||||
end
|
||||
local cur_win_opts = vim.api.nvim_win_get_config(winid)
|
||||
vim.api.nvim_win_set_config(winid, {
|
||||
relative = "editor",
|
||||
row = win_opts.row,
|
||||
col = win_opts.col,
|
||||
width = win_opts.width,
|
||||
height = win_opts.height,
|
||||
row = cur_win_opts.row,
|
||||
col = cur_win_opts.col,
|
||||
width = cur_win_opts.width,
|
||||
height = cur_win_opts.height,
|
||||
title = get_title(),
|
||||
})
|
||||
end,
|
||||
|
|
@ -444,6 +422,8 @@ end
|
|||
--- split "aboveleft"|"belowright"|"topleft"|"botright" Split modifier
|
||||
M.open_preview = function(opts, callback)
|
||||
opts = opts or {}
|
||||
local config = require("oil.config")
|
||||
local layout = require("oil.layout")
|
||||
local util = require("oil.util")
|
||||
|
||||
local function finish(err)
|
||||
|
|
@ -465,18 +445,59 @@ M.open_preview = function(opts, callback)
|
|||
opts.split = vim.o.splitright and "belowright" or "aboveleft"
|
||||
end
|
||||
end
|
||||
if util.is_floating_win() then
|
||||
return finish("oil preview doesn't work in a floating window")
|
||||
end
|
||||
|
||||
local preview_win = util.get_preview_win()
|
||||
local prev_win = vim.api.nvim_get_current_win()
|
||||
local bufnr = vim.api.nvim_get_current_buf()
|
||||
|
||||
local entry = M.get_cursor_entry()
|
||||
if not entry then
|
||||
return finish("Could not find entry under cursor")
|
||||
end
|
||||
local entry_title = entry.name
|
||||
if entry.type == "directory" then
|
||||
entry_title = entry_title .. "/"
|
||||
end
|
||||
|
||||
local preview_win = util.get_preview_win()
|
||||
local prev_win = vim.api.nvim_get_current_win()
|
||||
local bufnr = vim.api.nvim_get_current_buf()
|
||||
if util.is_floating_win() then
|
||||
if preview_win == nil then
|
||||
local root_win_opts, preview_win_opts =
|
||||
layout.split_window(0, config.float.preview_split, config.float.padding)
|
||||
|
||||
local win_opts_oil = {
|
||||
relative = "editor",
|
||||
width = root_win_opts.width,
|
||||
height = root_win_opts.height,
|
||||
row = root_win_opts.row,
|
||||
col = root_win_opts.col,
|
||||
border = config.float.border,
|
||||
zindex = 45,
|
||||
}
|
||||
vim.api.nvim_win_set_config(0, win_opts_oil)
|
||||
local win_opts = {
|
||||
relative = "editor",
|
||||
width = preview_win_opts.width,
|
||||
height = preview_win_opts.height,
|
||||
row = preview_win_opts.row,
|
||||
col = preview_win_opts.col,
|
||||
border = config.float.border,
|
||||
zindex = 45,
|
||||
focusable = false,
|
||||
noautocmd = true,
|
||||
style = "minimal",
|
||||
}
|
||||
|
||||
if vim.fn.has("nvim-0.9") == 1 then
|
||||
win_opts.title = entry_title
|
||||
end
|
||||
|
||||
preview_win = vim.api.nvim_open_win(bufnr, true, win_opts)
|
||||
vim.api.nvim_set_option_value("previewwindow", true, { scope = "local", win = preview_win })
|
||||
vim.api.nvim_set_current_win(prev_win)
|
||||
elseif vim.fn.has("nvim-0.9") == 1 then
|
||||
vim.api.nvim_win_set_config(preview_win, { title = entry_title })
|
||||
end
|
||||
end
|
||||
|
||||
local cmd = preview_win and "buffer" or "sbuffer"
|
||||
local mods = {
|
||||
|
|
@ -485,7 +506,6 @@ M.open_preview = function(opts, callback)
|
|||
split = opts.split,
|
||||
}
|
||||
|
||||
local is_visual_mode = util.is_visual_mode()
|
||||
-- HACK Switching windows takes us out of visual mode.
|
||||
-- Switching with nvim_set_current_win causes the previous visual selection (as used by `gv`) to
|
||||
-- not get set properly. So we have to switch windows this way instead.
|
||||
|
|
@ -494,15 +514,16 @@ M.open_preview = function(opts, callback)
|
|||
vim.cmd.wincmd({ args = { "w" }, count = winnr })
|
||||
end
|
||||
|
||||
if preview_win then
|
||||
if is_visual_mode then
|
||||
hack_set_win(preview_win)
|
||||
else
|
||||
vim.api.nvim_set_current_win(preview_win)
|
||||
end
|
||||
end
|
||||
|
||||
util.get_edit_path(bufnr, entry, function(normalized_url)
|
||||
local is_visual_mode = util.is_visual_mode()
|
||||
if preview_win then
|
||||
if is_visual_mode then
|
||||
hack_set_win(preview_win)
|
||||
else
|
||||
vim.api.nvim_set_current_win(preview_win)
|
||||
end
|
||||
end
|
||||
|
||||
local filebufnr = vim.fn.bufadd(normalized_url)
|
||||
local entry_is_file = not vim.endswith(normalized_url, "/")
|
||||
|
||||
|
|
|
|||
|
|
@ -93,6 +93,89 @@ M.calculate_height = function(desired_height, opts)
|
|||
)
|
||||
end
|
||||
|
||||
---@class (exact) conform.WinLayout
|
||||
---@field width integer
|
||||
---@field height integer
|
||||
---@field row integer
|
||||
---@field col integer
|
||||
|
||||
---@return vim.api.keyset.win_config
|
||||
M.get_fullscreen_win_opts = function()
|
||||
local config = require("oil.config")
|
||||
|
||||
local total_width = M.get_editor_width()
|
||||
local total_height = M.get_editor_height()
|
||||
local width = total_width - 2 * config.float.padding
|
||||
if config.float.border ~= "none" then
|
||||
width = width - 2 -- The border consumes 1 col on each side
|
||||
end
|
||||
if config.float.max_width > 0 then
|
||||
width = math.min(width, config.float.max_width)
|
||||
end
|
||||
local height = total_height - 2 * config.float.padding
|
||||
if config.float.max_height > 0 then
|
||||
height = math.min(height, config.float.max_height)
|
||||
end
|
||||
local row = math.floor((total_height - height) / 2)
|
||||
local col = math.floor((total_width - width) / 2) - 1 -- adjust for border width
|
||||
|
||||
local win_opts = {
|
||||
relative = "editor",
|
||||
width = width,
|
||||
height = height,
|
||||
row = row,
|
||||
col = col,
|
||||
border = config.float.border,
|
||||
zindex = 45,
|
||||
}
|
||||
return config.float.override(win_opts) or win_opts
|
||||
end
|
||||
|
||||
---@param winid integer
|
||||
---@param direction "above"|"below"|"left"|"right"|"auto"
|
||||
---@param gap integer
|
||||
---@return conform.WinLayout root_dim New dimensions of the original window
|
||||
---@return conform.WinLayout new_dim New dimensions of the new window
|
||||
M.split_window = function(winid, direction, gap)
|
||||
if direction == "auto" then
|
||||
direction = vim.o.splitright and "right" or "left"
|
||||
end
|
||||
|
||||
local float_config = vim.api.nvim_win_get_config(winid)
|
||||
local dim_root = {
|
||||
width = float_config.width,
|
||||
height = float_config.height,
|
||||
col = float_config.col,
|
||||
row = float_config.row,
|
||||
}
|
||||
if vim.fn.has("nvim-0.10") == 0 then
|
||||
-- read https://github.com/neovim/neovim/issues/24430 for more infos.
|
||||
dim_root.col = float_config.col[vim.val_idx]
|
||||
dim_root.row = float_config.row[vim.val_idx]
|
||||
end
|
||||
local dim_new = vim.deepcopy(dim_root)
|
||||
|
||||
if direction == "left" or direction == "right" then
|
||||
dim_new.width = math.floor(float_config.width / 2) - math.ceil(gap / 2)
|
||||
dim_root.width = dim_new.width
|
||||
else
|
||||
dim_new.height = math.floor(float_config.height / 2) - math.ceil(gap / 2)
|
||||
dim_root.height = dim_new.height
|
||||
end
|
||||
|
||||
if direction == "left" then
|
||||
dim_root.col = dim_root.col + dim_root.width + gap
|
||||
elseif direction == "right" then
|
||||
dim_new.col = dim_new.col + dim_new.width + gap
|
||||
elseif direction == "above" then
|
||||
dim_root.row = dim_root.row + dim_root.height + gap
|
||||
elseif direction == "below" then
|
||||
dim_new.row = dim_new.row + dim_new.height + gap
|
||||
end
|
||||
|
||||
return dim_root, dim_new
|
||||
end
|
||||
|
||||
M.calculate_dims = function(desired_width, desired_height, opts)
|
||||
local width = M.calculate_width(desired_width, opts)
|
||||
local height = M.calculate_height(desired_height, opts)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue