Skip to content

Commit

Permalink
feat(win)!: support additional border styles (#1668)
Browse files Browse the repository at this point in the history
Refactor win class code:

- Support both neovim and fzf border styles for
  `winopts.border|winopts.preview.border`, styles inlcude:
  ```
  # `nvim_open_win` styles
  none single double rounded solid shadow
  # fzf-lua styles (some are aliases)
  empty bold block solidblock thicc thiccc thicccc
  # fzf borders
  border noborder border-none border-rounded border-sharp
  border-bold border-double border-block border-thinblock
  border-horizontal border-top border-bottom
  ```
- Improve `treesitter-context` attach
- Refactor (normalize) layout generation code
- Refactor scrollbar code
- Refactor preview border: remove dedicated border window
  and use `nvim_open_win` title options instead (neovim >= 0.9)
- Fix scroll position caching with entries that have no line|col
- Fix fullscreen with `winopts.relative=cursor`

Other changes:
- Require Neovim 0.7 and remove backward compat code
- Default profile set to `default-title` on neovim >= 0.9
- Modify profiles `borderless|borderless-full` to use the new
  border options
  • Loading branch information
ibhagwan committed Jan 5, 2025
1 parent 60428a8 commit 6d846f1
Show file tree
Hide file tree
Showing 16 changed files with 392 additions and 580 deletions.
2 changes: 1 addition & 1 deletion OPTIONS.md
Original file line number Diff line number Diff line change
Expand Up @@ -382,7 +382,7 @@ Scrollbar style in the builtin previewer, set to `false` to disable, possible va

#### globals.winopts.preview.scrolloff

Type: `number`, Default: `-2`
Type: `number`, Default: `-1`

Float style scrollbar offset from the right edge of the preview window.

Expand Down
32 changes: 16 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

# fzf :heart: lua

![Neovim version](https://img.shields.io/badge/Neovim-0.5-57A143?style=flat-square&logo=neovim)
![Neovim version](https://img.shields.io/badge/Neovim-0.7-57A143?style=flat-square&logo=neovim)

[Quickstart](#quickstart)[Installation](#installation)[Usage](#usage)[Commands](#commands)[Customization](#customization)[Wiki](https://github.com/ibhagwan/fzf-lua/wiki)

Expand Down Expand Up @@ -55,7 +55,7 @@ Using [lazy.nvim](https://github.com/folke/lazy.nvim)

### Dependencies

- [`neovim`](https://github.com/neovim/neovim/releases) version > `0.5.0`
- [`neovim`](https://github.com/neovim/neovim/releases) version > `0.7.0`
- [`fzf`](https://github.com/junegunn/fzf) version > `0.25`
or [`skim`](https://github.com/skim-rs/skim) binary installed
- [nvim-web-devicons](https://github.com/nvim-tree/nvim-web-devicons)
Expand Down Expand Up @@ -406,9 +406,8 @@ winopts = {
width = 0.80, -- window width
row = 0.35, -- window row position (0=top, 1=bottom)
col = 0.50, -- window col position (0=left, 1=right)
-- border argument passthrough to nvim_open_win(), also used
-- 'none', 'single', 'double', 'thicc' (+cc) or 'rounded' (default)
border = { '', '', '', '', '', '', '', '' },
-- border argument passthrough to nvim_open_win()
border = "rounded",
-- Backdrop opacity, 0 is fully opaque, 100 is fully transparent (i.e. disabled)
backdrop = 60,
-- title = "Title",
Expand All @@ -425,34 +424,35 @@ winopts = {
preview = {
-- default = 'bat', -- override the default previewer?
-- default uses the 'builtin' previewer
border = 'border', -- border|noborder, applies only to
border = "border", -- preview border: accepts both `nvim_open_win`
-- and fzf values (e.g. "border-top", "none")
-- native fzf previewers (bat/cat/git/etc)
wrap = 'nowrap', -- wrap|nowrap
hidden = 'nohidden', -- hidden|nohidden
vertical = 'down:45%', -- up|down:size
horizontal = 'right:60%', -- right|left:size
layout = 'flex', -- horizontal|vertical|flex
wrap = "nowrap", -- wrap|nowrap
hidden = "nohidden", -- hidden|nohidden
vertical = "down:45%", -- up|down:size
horizontal = "right:60%", -- right|left:size
layout = "flex", -- horizontal|vertical|flex
flip_columns = 100, -- #cols to switch to horizontal on flex
-- Only used with the builtin previewer:
title = true, -- preview border title (file/buf)?
title_pos = "center", -- left|center|right, title alignment
scrollbar = 'float', -- `false` or string:'float|border'
scrollbar = "float", -- `false` or string:'float|border'
-- float: in-window floating border
-- border: in-border "block" marker
scrolloff = '-2', -- float scrollbar offset from right
scrolloff = -1, -- float scrollbar offset from right
-- applies only when scrollbar = 'float'
delay = 20, -- delay(ms) displaying the preview
-- prevents lag on fast scrolling
winopts = { -- builtin previewer window options
number = true,
relativenumber = false,
cursorline = true,
cursorlineopt = 'both',
cursorlineopt = "both",
cursorcolumn = false,
signcolumn = 'no',
signcolumn = "no",
list = false,
foldenable = false,
foldmethod = 'manual',
foldmethod = "manual",
},
},
on_create = function()
Expand Down
4 changes: 2 additions & 2 deletions doc/fzf-lua-opts.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
*fzf-lua-opts.txt* For Neovim >= 0.8.0 Last change: 2024 December 18
*fzf-lua-opts.txt* For Neovim >= 0.8.0 Last change: 2024 December 27

==============================================================================
Table of Contents *fzf-lua-opts-table-of-contents*
Expand Down Expand Up @@ -504,7 +504,7 @@ values are `float|border`.

globals.winopts.preview.scrolloff*fzf-lua-opts-globals.winopts.preview.scrolloff*

Type: `number`, Default: `-2`
Type: `number`, Default: `-1`

Float style scrollbar offset from the right edge of the preview window.

Expand Down
25 changes: 24 additions & 1 deletion lua/fzf-lua/core.lua
Original file line number Diff line number Diff line change
Expand Up @@ -464,12 +464,35 @@ M.fzf = function(contents, opts)
return selected
end

-- Best approximation of neovim border types to fzf border types
local function translate_border(border)
local neovim2fzf = {
none = "noborder",
single = "border-sharp",
double = "border-double",
rounded = "border-rounded",
solid = "noborder",
empty = "border-block",
shadow = "border-thinblock",
bold = "border-bold",
block = "border-block",
solidblock = "border-block",
thicc = "border-bold",
thiccc = "border-block",
thicccc = "border-block",
}
border = type(border) == "string" and (neovim2fzf[border] or border) or "rounded"
return border
end

---@param o table
---@return string
M.preview_window = function(o, fzf_win)
local layout
local prefix = string.format("%s:%s:%s",
o.winopts.preview.hidden, o.winopts.preview.border, o.winopts.preview.wrap)
o.winopts.preview.hidden,
translate_border(o.winopts.preview.border),
o.winopts.preview.wrap)
if utils.has(o, "fzf", { 0, 31 })
and o.winopts.preview.layout == "flex"
and tonumber(o.winopts.preview.flip_columns) > 0
Expand Down
26 changes: 2 additions & 24 deletions lua/fzf-lua/defaults.lua
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ M.defaults = {
title = true,
title_pos = "center",
scrollbar = "border",
scrolloff = "-2",
scrolloff = -1,
-- default preview delay, fzf native previewers has a 100ms delay:
-- https://github.com/junegunn/fzf/issues/2417#issuecomment-809886535
delay = 20,
Expand Down Expand Up @@ -600,6 +600,7 @@ M.defaults.buffers = {
color_icons = true,
sort_lastused = true,
show_unloaded = true,
show_unlisted = false,
ignore_current_buffer = false,
no_action_set_cursor = true,
cwd_only = false,
Expand Down Expand Up @@ -1252,27 +1253,4 @@ M.defaults.__HLS = {
}
}

M.defaults.__WINOPTS = {
borderchars = {
["none"] = { "", "", "", "", "", "", "", "" },
["empty"] = { " ", " ", " ", " ", " ", " ", " ", " " },
["single"] = { "", "", "", "", "", "", "", "" },
["double"] = { "", "", "", "", "", "", "", "" },
["rounded"] = { "", "", "", "", "", "", "", "" },
["thicc"] = { "", "", "", "", "", "", "", "" },
["thiccc"] = { "", "", "", "", "", "", "", "" },
["thicccc"] = { "", "", "", "", "", "", "", "" },
},
-- border chars reverse lookup for ambiwidth="double"
border2string = {
[" "] = "empty",
[""] = "single",
[""] = "double",
[""] = "rounded",
[""] = "double",
[""] = "double",
[""] = "double",
},
}

return M
2 changes: 1 addition & 1 deletion lua/fzf-lua/devicons.lua
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ end
function NvimWebDevicons:load(do_not_lazy_load)
-- limit devicons support to nvim >=0.8, although official support is >=0.7
-- running setup on 0.7 errs with "W18: Invalid character in group name"
if not self._package_loaded and utils.__HAS_NVIM_07
if not self._package_loaded
-- do not trigger lazy loading
and (not do_not_lazy_load or package.loaded[self._package_name])
then
Expand Down
52 changes: 17 additions & 35 deletions lua/fzf-lua/fzf.lua
Original file line number Diff line number Diff line change
Expand Up @@ -221,26 +221,24 @@ function M.raw_fzf(contents, fzf_cli_args, opts)
-- sending `feedkeys|startinsert` after the term job is started, this approach
-- seems more consistent as it triggers when entering terminal normal mode "nt"
-- NOTE: "ModeChanged" was added with neovim 0.7
if utils.__HAS_NVIM_07 then
vim.api.nvim_create_autocmd("ModeChanged", {
once = true,
buffer = 0,
callback = function(e)
if e.match:match(":nt") then
vim.defer_fn(function()
-- Prevents inserting "i" when spamming `ctrl-g` in `grep_lgrep`
-- Also verify we're not already in TERMINAL mode, could happen
-- if the user has an autocmd for TermOpen with `startinsert`
if vim.api.nvim_buf_is_valid(e.buf)
and vim.api.nvim_get_mode().mode ~= "t"
then
vim.cmd("startinsert")
end
end, 0)
end
vim.api.nvim_create_autocmd("ModeChanged", {
once = true,
buffer = 0,
callback = function(e)
if e.match:match(":nt") then
vim.defer_fn(function()
-- Prevents inserting "i" when spamming `ctrl-g` in `grep_lgrep`
-- Also verify we're not already in TERMINAL mode, could happen
-- if the user has an autocmd for TermOpen with `startinsert`
if vim.api.nvim_buf_is_valid(e.buf)
and vim.api.nvim_get_mode().mode ~= "t"
then
vim.cmd("startinsert")
end
end, 0)
end
})
end
end
})
end

if opts.debug then
Expand Down Expand Up @@ -318,22 +316,6 @@ function M.raw_fzf(contents, fzf_cli_args, opts)
-- fzf-tmux spawns outside neovim, don't set filetype/insert mode
if not opts.is_fzf_tmux then
vim.bo.filetype = "fzf"

-- https://github.com/neovim/neovim/pull/15878
-- Since patch-8.2.3461 which was released with 0.6 neovim distinguishes between
-- Normal mode and Terminal-Normal mode. However, this seems to have also introduced
-- a bug with `startinsert`: When fzf-lua reuses interfaces (e.g. called from "builtin"
-- or grep<->live_grep toggle) the current mode will be "t" which is Terminal (INSERT)
-- mode but our interface is still opened in NORMAL mode, either `startinsert` is not
-- working (as it's technically already in INSERT) or creating a new terminal buffer
-- within the same window starts in NORMAL mode while returning the wrong `nvim_get_mode`
if not utils.__HAS_NVIM_07 then
if utils.__HAS_NVIM_06 and vim.api.nvim_get_mode().mode == "t" then
utils.feed_keys_termcodes("i")
else
vim.cmd [[startinsert]]
end
end
end

if not utils.__IS_WINDOWS
Expand Down
20 changes: 4 additions & 16 deletions lua/fzf-lua/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -127,26 +127,12 @@ function M.setup_highlights(override)
hl_def.default = false
end
end
if utils.__HAS_NVIM_07 then
vim.api.nvim_set_hl(0, hl_name, hl_def)
else
if hl_def.link then
vim.cmd(string.format("hi! %s link %s %s",
hl_def.default and "default" or "",
hl_name, hl_def.link))
else
vim.cmd(string.format("hi! %s %s %s%s%s",
hl_def.default and "default" or "", hl_name,
hl_def.fg and string.format(" guifg=%s", hl_def.fg) or "",
hl_def.bg and string.format(" guibg=%s", hl_def.bg) or "",
hl_def.bold and " gui=bold" or ""))
end
end
vim.api.nvim_set_hl(0, hl_name, hl_def)
end

-- linking to a cleared hl is bugged in neovim 0.8.x
-- resulting in a pink background for hls linked to `Normal`
if vim.fn.has("nvim-0.9") == 0 and vim.fn.has("nvim-0.8") == 1 then
if not utils.__HAS_NVIM_09 and utils.__HAS_NVIM_08 then
for _, a in ipairs(highlights) do
local hl_name, opt_name = a[1], a[2]
if utils.is_hl_cleared(hl_name) then
Expand Down Expand Up @@ -192,6 +178,8 @@ end

function M.setup(opts, do_not_reset_defaults)
opts = type(opts) == "table" and opts or {}
-- Default to picker info in win title (vs fzf prompt) if neovim version >= 0.9
opts[1] = opts[1] == nil and utils.__HAS_NVIM_09 and "default-title" or opts[1]
if opts[1] then
-- Did the user supply profile(s) to load?
opts = vim.tbl_deep_extend("keep", opts, load_profiles(opts[1]))
Expand Down
Loading

0 comments on commit 6d846f1

Please sign in to comment.