fix: make lf faster selecting file; fix layouts
This commit is contained in:
parent
aa72337c44
commit
c30426d2fb
|
@ -1,43 +1,6 @@
|
||||||
local fn = vim.fn
|
local fn = vim.fn
|
||||||
local o = vim.o
|
local o = vim.o
|
||||||
|
|
||||||
---@alias LfGenericBorder {[1]:string,[2]:string,[3]:string,[4]:string,[5]:string,[6]:string,[7]:string,[8]:string}
|
|
||||||
---@alias LfBorder "'none'"|"'single'"|"'double'"|"'rounded'"|"'solid'"|"'shadow'"|LfGenericBorder
|
|
||||||
|
|
||||||
---@class LfViews
|
|
||||||
---@field relative "'editor'"|"'win'"|"'cursor'"|"'mouse'"
|
|
||||||
---@field win number For `relative='win'`
|
|
||||||
---@field anchor "'NW'"|"'NE'"|"'SW'"|"'SE'" Which corner of float to place `(row, col)`
|
|
||||||
---@field width number
|
|
||||||
---@field height number
|
|
||||||
---@field bufpos {row: number, col: number}
|
|
||||||
---@field row number|float
|
|
||||||
---@field col number|float
|
|
||||||
---@field focusable boolean
|
|
||||||
---@field zindex number
|
|
||||||
---@field style "'minimal'"
|
|
||||||
---@field border LfBorder Border kind
|
|
||||||
---@field title string|{[1]: string, [2]: string}[] Can be a string or an array of tuples
|
|
||||||
---@field title_pos "'left'"|"'center'"|"'right'"
|
|
||||||
---@field noautocmd boolean
|
|
||||||
|
|
||||||
---@class LfConfig
|
|
||||||
---@field default_cmd string Default `lf` command
|
|
||||||
---@field default_action string Default action when `Lf` opens a file
|
|
||||||
---@field default_actions { [string]: string } Default action keybindings
|
|
||||||
---@field winblend number Psuedotransparency level
|
|
||||||
---@field dir "'gwd'"|"''"|nil|string Directory where `lf` starts ('gwd' is git-working-directory, ""/nil is CWD)
|
|
||||||
---@field direction "'vertical'"|"'horizontal'"|"'tab'"|"'float'" Window type
|
|
||||||
---@field border LfBorder Border kind
|
|
||||||
---@field height number Height of the *floating* window
|
|
||||||
---@field width number Width of the *floating* window
|
|
||||||
---@field escape_quit boolean Whether escape should be mapped to quit
|
|
||||||
---@field focus_on_open boolean Whether Lf should open focused on current file
|
|
||||||
---@field mappings boolean Whether terminal buffer mappings should be set
|
|
||||||
---@field tmux boolean Whether `tmux` statusline should be changed by this plugin
|
|
||||||
---@field highlights table<string, table<string, string>> Highlight table passed to `toggleterm`
|
|
||||||
---@field layout_mapping string Keybinding to rotate through the window layouts
|
|
||||||
---@field views LfViews[] Table of layouts to be applied to `nvim_win_set_config`
|
|
||||||
local Config = {}
|
local Config = {}
|
||||||
|
|
||||||
---@type LfConfig
|
---@type LfConfig
|
||||||
|
@ -54,8 +17,10 @@ local opts = {
|
||||||
dir = "",
|
dir = "",
|
||||||
direction = "float",
|
direction = "float",
|
||||||
border = "double",
|
border = "double",
|
||||||
height = 0.80,
|
-- col = fn.float2nr(fn.round(0.12 * o.columns)),
|
||||||
width = 0.85,
|
-- row = fn.float2nr(fn.round(0.12 * o.lines)),
|
||||||
|
width = fn.float2nr(fn.round(0.75 * o.columns)),
|
||||||
|
height = fn.float2nr(fn.round(0.75 * o.lines)),
|
||||||
escape_quit = false,
|
escape_quit = false,
|
||||||
focus_on_open = true,
|
focus_on_open = true,
|
||||||
mappings = true,
|
mappings = true,
|
||||||
|
@ -67,13 +32,13 @@ local opts = {
|
||||||
-- Layout configurations
|
-- Layout configurations
|
||||||
layout_mapping = "<A-u>",
|
layout_mapping = "<A-u>",
|
||||||
views = {
|
views = {
|
||||||
{width = 0.600, height = 0.600},
|
|
||||||
{
|
|
||||||
width = 1.0 * fn.float2nr(fn.round(0.7 * o.columns)) / o.columns,
|
|
||||||
height = 1.0 * fn.float2nr(fn.round(0.7 * o.lines)) / o.lines,
|
|
||||||
},
|
|
||||||
{width = 0.800, height = 0.800},
|
{width = 0.800, height = 0.800},
|
||||||
|
{width = 0.600, height = 0.600},
|
||||||
{width = 0.950, height = 0.950},
|
{width = 0.950, height = 0.950},
|
||||||
|
{width = 0.500, height = 0.500, col = 0, row = 0},
|
||||||
|
{width = 0.500, height = 0.500, col = 0, row = 0.5},
|
||||||
|
{width = 0.500, height = 0.500, col = 0.5, row = 0},
|
||||||
|
{width = 0.500, height = 0.500, col = 0.5, row = 0.5},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,7 +89,7 @@ init()
|
||||||
---@return LfConfig
|
---@return LfConfig
|
||||||
function Config:override(cfg)
|
function Config:override(cfg)
|
||||||
if type(cfg) == "table" then
|
if type(cfg) == "table" then
|
||||||
self = vim.tbl_deep_extend("keep", cfg or {}, self) --[[@as LfConfig]]
|
self = vim.tbl_deep_extend("force", self, cfg) --[[@as LfConfig]]
|
||||||
self = validate(self)
|
self = validate(self)
|
||||||
end
|
end
|
||||||
return self
|
return self
|
||||||
|
@ -137,3 +102,41 @@ return setmetatable(Config, {
|
||||||
__newindex = function(_self, _key, _val)
|
__newindex = function(_self, _key, _val)
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
---@alias LfGenericBorder {[1]:string,[2]:string,[3]:string,[4]:string,[5]:string,[6]:string,[7]:string,[8]:string}
|
||||||
|
---@alias LfBorder "'none'"|"'single'"|"'double'"|"'rounded'"|"'solid'"|"'shadow'"|LfGenericBorder
|
||||||
|
|
||||||
|
---@class LfViews
|
||||||
|
---@field relative "'editor'"|"'win'"|"'cursor'"|"'mouse'"
|
||||||
|
---@field win number For `relative='win'`
|
||||||
|
---@field anchor "'NW'"|"'NE'"|"'SW'"|"'SE'" Which corner of float to place `(row, col)`
|
||||||
|
---@field width number
|
||||||
|
---@field height number
|
||||||
|
---@field bufpos {row: number, col: number}
|
||||||
|
---@field row number|float
|
||||||
|
---@field col number|float
|
||||||
|
---@field focusable boolean
|
||||||
|
---@field zindex number
|
||||||
|
---@field style "'minimal'"
|
||||||
|
---@field border LfBorder Border kind
|
||||||
|
---@field title string|{[1]: string, [2]: string}[] Can be a string or an array of tuples
|
||||||
|
---@field title_pos "'left'"|"'center'"|"'right'"
|
||||||
|
---@field noautocmd boolean
|
||||||
|
|
||||||
|
---@class LfConfig
|
||||||
|
---@field default_cmd string Default `lf` command
|
||||||
|
---@field default_action string Default action when `Lf` opens a file
|
||||||
|
---@field default_actions { [string]: string } Default action keybindings
|
||||||
|
---@field winblend number Psuedotransparency level
|
||||||
|
---@field dir "'gwd'"|"''"|nil|string Directory where `lf` starts ('gwd' is git-working-directory, ""/nil is CWD)
|
||||||
|
---@field direction "'vertical'"|"'horizontal'"|"'tab'"|"'float'" Window type
|
||||||
|
---@field border LfBorder Border kind
|
||||||
|
---@field height number Height of the *floating* window
|
||||||
|
---@field width number Width of the *floating* window
|
||||||
|
---@field escape_quit boolean Whether escape should be mapped to quit
|
||||||
|
---@field focus_on_open boolean Whether Lf should open focused on current file
|
||||||
|
---@field mappings boolean Whether terminal buffer mappings should be set
|
||||||
|
---@field tmux boolean Whether `tmux` statusline should be changed by this plugin
|
||||||
|
---@field highlights table<string, table<string, string>> Highlight table passed to `toggleterm`
|
||||||
|
---@field layout_mapping string Keybinding to rotate through the window layouts
|
||||||
|
---@field views LfViews[] Table of layouts to be applied to `nvim_win_set_config`
|
||||||
|
|
|
@ -97,8 +97,10 @@ function Lf:__create_term()
|
||||||
highlights = self.cfg.highlights,
|
highlights = self.cfg.highlights,
|
||||||
float_opts = {
|
float_opts = {
|
||||||
border = self.cfg.border,
|
border = self.cfg.border,
|
||||||
width = math.floor(o.columns * self.cfg.width),
|
width = self.cfg.width,
|
||||||
height = math.floor(o.lines * self.cfg.height),
|
height = self.cfg.height,
|
||||||
|
row = self.cfg.row,
|
||||||
|
col = self.cfg.col,
|
||||||
winblend = self.cfg.winblend,
|
winblend = self.cfg.winblend,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
@ -163,11 +165,15 @@ function Lf:__set_cmd_wrapper()
|
||||||
self.tmp_lastdir = os.tmpname()
|
self.tmp_lastdir = os.tmpname()
|
||||||
self.tmp_id = os.tmpname()
|
self.tmp_id = os.tmpname()
|
||||||
|
|
||||||
|
local open_on = self.term.dir
|
||||||
|
if self.cfg.focus_on_open and fs.dirname(self.curfile) == self.term.dir then
|
||||||
|
open_on = self.curfile
|
||||||
|
end
|
||||||
|
|
||||||
-- command lf -command '$printf $id > '"$fid"'' -last-dir-path="$tmp" "$@"
|
-- command lf -command '$printf $id > '"$fid"'' -last-dir-path="$tmp" "$@"
|
||||||
self.term.cmd =
|
self.term.cmd =
|
||||||
([[%s -command='$printf $id > %s' -last-dir-path='%s' -selection-path='%s' %s]]):format(
|
([[%s -command='$printf $id > %s' -last-dir-path='%s' -selection-path='%s' %s]]):format(
|
||||||
self.term.cmd, self.tmp_id, self.tmp_lastdir, self.tmp_sel,
|
self.term.cmd, self.tmp_id, self.tmp_lastdir, self.tmp_sel, open_on
|
||||||
self.term.dir
|
|
||||||
)
|
)
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
@ -179,30 +185,6 @@ function Lf:__on_open(term)
|
||||||
self.bufnr = term.bufnr
|
self.bufnr = term.bufnr
|
||||||
self.winid = term.window
|
self.winid = term.window
|
||||||
|
|
||||||
-- TODO: The delay here needs to be fixed.
|
|
||||||
-- I need to find a way to block this outer function's caller
|
|
||||||
vim.defer_fn(function()
|
|
||||||
if self.cfg.focus_on_open then
|
|
||||||
if self.term.dir == fs.dirname(self.curfile) then
|
|
||||||
if not fn.filereadable(self.tmp_id) then
|
|
||||||
utils.err(("Lf's id file is not readable: %s"):format(self.tmp_id))
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
local res = utils.read_file(self.tmp_id)
|
|
||||||
self.id = tonumber(res)
|
|
||||||
|
|
||||||
if self.id ~= nil then
|
|
||||||
fn.system({
|
|
||||||
"lf",
|
|
||||||
"-remote",
|
|
||||||
("send %s select %s"):format(self.id, fs.basename(self.curfile)),
|
|
||||||
})
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end, 70)
|
|
||||||
|
|
||||||
cmd("silent! doautocmd User LfTermEnter")
|
cmd("silent! doautocmd User LfTermEnter")
|
||||||
|
|
||||||
-- Wrap needs to be set, otherwise the window isn't aligned on resize
|
-- Wrap needs to be set, otherwise the window isn't aligned on resize
|
||||||
|
|
|
@ -113,40 +113,6 @@ function M.tern(cond, is_if, is_else, simple)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
---## if else nil
|
|
||||||
---Similar to `vim.F.nil` except that:
|
|
||||||
--- - a default value can be given
|
|
||||||
--- - `if cond == nil then want else default`
|
|
||||||
---@generic T, V
|
|
||||||
---@param cond any Value to check if `nil`
|
|
||||||
---@param is_nil T Value to return if `cond` is `nil`
|
|
||||||
---@param is_not_nil V Value to return if `cond` is not `nil`
|
|
||||||
---@return T | V
|
|
||||||
function M.ife_nil(cond, is_nil, is_not_nil)
|
|
||||||
return M.tern(cond == nil, is_nil, is_not_nil)
|
|
||||||
end
|
|
||||||
|
|
||||||
---## if nil then
|
|
||||||
---Return a default value if `val` is nil
|
|
||||||
--- - `if val == nil then default else val`
|
|
||||||
--- - `ifn_then`
|
|
||||||
---@generic T, V
|
|
||||||
---@param val T value to check if `nil`
|
|
||||||
---@param default V default value to return if `val` is `nil`
|
|
||||||
---@return T | V
|
|
||||||
function M.unwrap_or(val, default)
|
|
||||||
if type(val) ~= "table" then
|
|
||||||
return M.ife_nil(val, default, val)
|
|
||||||
end
|
|
||||||
val = vim.deepcopy(val or {})
|
|
||||||
for k, v in pairs(default) do
|
|
||||||
if val[k] == nil then
|
|
||||||
val[k] = v
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return val
|
|
||||||
end
|
|
||||||
|
|
||||||
---@param path string
|
---@param path string
|
||||||
---@return uv_fs_t|string
|
---@return uv_fs_t|string
|
||||||
---@return uv.aliases.fs_stat_table?
|
---@return uv.aliases.fs_stat_table?
|
||||||
|
@ -192,11 +158,8 @@ function M.width(bufnr, signcolumn)
|
||||||
local width = #tostring(api.nvim_buf_line_count(bufnr))
|
local width = #tostring(api.nvim_buf_line_count(bufnr))
|
||||||
local col = vim.split(signcolumn, ":")
|
local col = vim.split(signcolumn, ":")
|
||||||
if #col == 2 then
|
if #col == 2 then
|
||||||
-- Can't cast integer to number?
|
|
||||||
---@diagnostic disable-next-line:cast-local-type
|
|
||||||
width = width + tonumber(col[2])
|
width = width + tonumber(col[2])
|
||||||
end
|
end
|
||||||
---@diagnostic disable-next-line:return-type-mismatch
|
|
||||||
return signcolumn:match("no") and o.columns or o.columns - width
|
return signcolumn:match("no") and o.columns or o.columns - width
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -207,29 +170,27 @@ end
|
||||||
---@return table
|
---@return table
|
||||||
function M.get_view(opts, bufnr, signcolumn)
|
function M.get_view(opts, bufnr, signcolumn)
|
||||||
opts = opts or {}
|
opts = opts or {}
|
||||||
local width = opts.width or math.ceil(
|
|
||||||
math.min(
|
|
||||||
M.width(bufnr, signcolumn),
|
|
||||||
math.max(80, M.width(bufnr, signcolumn) - 20)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
local height = opts.height
|
|
||||||
or math.ceil(
|
|
||||||
math.min(M.height(), math.max(20, M.height() - 10))
|
|
||||||
)
|
|
||||||
|
|
||||||
width = fn.float2nr(width * M.width(bufnr, signcolumn))
|
local width = opts.width
|
||||||
height = fn.float2nr(M.round(height * M.height()))
|
and fn.float2nr(fn.round(opts.width * o.columns))
|
||||||
local col = fn.float2nr(M.round((M.width(bufnr, signcolumn) - width) / 2))
|
or M.width(bufnr, signcolumn)
|
||||||
local row = fn.float2nr(M.round((M.height() - height) / 2))
|
local height = opts.height
|
||||||
|
and fn.float2nr(fn.round(opts.height * o.lines))
|
||||||
|
or M.height()
|
||||||
|
local col = opts.col
|
||||||
|
and fn.float2nr(fn.round(opts.col * o.columns))
|
||||||
|
or math.ceil(o.columns - width) * 0.5 - 1
|
||||||
|
local row = opts.row
|
||||||
|
and fn.float2nr(fn.round(opts.row * o.lines))
|
||||||
|
or math.ceil(o.lines - height) * 0.5 - 1
|
||||||
|
|
||||||
return {
|
return {
|
||||||
col = col,
|
col = col,
|
||||||
row = row,
|
row = row,
|
||||||
relative = "editor",
|
|
||||||
style = "minimal",
|
|
||||||
width = width,
|
width = width,
|
||||||
height = height,
|
height = height,
|
||||||
|
relative = "editor",
|
||||||
|
style = "minimal",
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -237,13 +198,7 @@ end
|
||||||
---@return string|nil
|
---@return string|nil
|
||||||
function M.git_dir()
|
function M.git_dir()
|
||||||
---@diagnostic disable-next-line: missing-parameter
|
---@diagnostic disable-next-line: missing-parameter
|
||||||
local gitdir = fn.system(
|
local gitdir = fn.system(("git -C %s rev-parse --show-toplevel"):format(fn.expand("%:p:h")))
|
||||||
("git -C %s rev-parse --show-toplevel"):format(
|
|
||||||
fn.expand(
|
|
||||||
"%:p:h"
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
if gitdir:match("^fatal:.*") then
|
if gitdir:match("^fatal:.*") then
|
||||||
M.info("Failed to get git directory")
|
M.info("Failed to get git directory")
|
||||||
|
@ -260,14 +215,10 @@ function M.tmux(disable)
|
||||||
end
|
end
|
||||||
if disable then
|
if disable then
|
||||||
fn.system([[tmux set status off]])
|
fn.system([[tmux set status off]])
|
||||||
fn.system(
|
fn.system([[tmux list-panes -F '\#F' | grep -q Z || tmux resize-pane -Z]])
|
||||||
[[tmux list-panes -F '\#F' | grep -q Z || tmux resize-pane -Z]]
|
|
||||||
)
|
|
||||||
else
|
else
|
||||||
fn.system([[tmux set status on]])
|
fn.system([[tmux set status on]])
|
||||||
fn.system(
|
fn.system([[tmux list-panes -F '\#F' | grep -q Z && tmux resize-pane -Z]])
|
||||||
[[tmux list-panes -F '\#F' | grep -q Z && tmux resize-pane -Z]]
|
|
||||||
)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Reference in New Issue