diff --git a/lua/lf/config.lua b/lua/lf/config.lua index 6dc2420..c587fec 100644 --- a/lua/lf/config.lua +++ b/lua/lf/config.lua @@ -1,43 +1,6 @@ local fn = vim.fn 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> 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 = {} ---@type LfConfig @@ -54,8 +17,10 @@ local opts = { dir = "", direction = "float", border = "double", - height = 0.80, - width = 0.85, + -- col = fn.float2nr(fn.round(0.12 * o.columns)), + -- 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, focus_on_open = true, mappings = true, @@ -67,13 +32,13 @@ local opts = { -- Layout configurations layout_mapping = "", 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.600, height = 0.600}, {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 function Config:override(cfg) 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) end return self @@ -137,3 +102,41 @@ return setmetatable(Config, { __newindex = function(_self, _key, _val) 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> 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` diff --git a/lua/lf/main.lua b/lua/lf/main.lua index f762e83..eeb77b3 100644 --- a/lua/lf/main.lua +++ b/lua/lf/main.lua @@ -97,8 +97,10 @@ function Lf:__create_term() highlights = self.cfg.highlights, float_opts = { border = self.cfg.border, - width = math.floor(o.columns * self.cfg.width), - height = math.floor(o.lines * self.cfg.height), + width = self.cfg.width, + height = self.cfg.height, + row = self.cfg.row, + col = self.cfg.col, winblend = self.cfg.winblend, }, }) @@ -163,11 +165,15 @@ function Lf:__set_cmd_wrapper() self.tmp_lastdir = 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" "$@" self.term.cmd = ([[%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.dir + self.term.cmd, self.tmp_id, self.tmp_lastdir, self.tmp_sel, open_on ) return self end @@ -179,30 +185,6 @@ function Lf:__on_open(term) self.bufnr = term.bufnr 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") -- Wrap needs to be set, otherwise the window isn't aligned on resize diff --git a/lua/lf/utils.lua b/lua/lf/utils.lua index 8beeaca..54af8dc 100644 --- a/lua/lf/utils.lua +++ b/lua/lf/utils.lua @@ -113,40 +113,6 @@ function M.tern(cond, is_if, is_else, simple) 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 ---@return uv_fs_t|string ---@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 col = vim.split(signcolumn, ":") if #col == 2 then - -- Can't cast integer to number? - ---@diagnostic disable-next-line:cast-local-type width = width + tonumber(col[2]) end - ---@diagnostic disable-next-line:return-type-mismatch return signcolumn:match("no") and o.columns or o.columns - width end @@ -207,29 +170,27 @@ end ---@return table function M.get_view(opts, bufnr, signcolumn) 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)) - height = fn.float2nr(M.round(height * M.height())) - local col = fn.float2nr(M.round((M.width(bufnr, signcolumn) - width) / 2)) - local row = fn.float2nr(M.round((M.height() - height) / 2)) + local width = opts.width + and fn.float2nr(fn.round(opts.width * o.columns)) + or M.width(bufnr, signcolumn) + 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 { col = col, row = row, - relative = "editor", - style = "minimal", width = width, height = height, + relative = "editor", + style = "minimal", } end @@ -237,13 +198,7 @@ end ---@return string|nil function M.git_dir() ---@diagnostic disable-next-line: missing-parameter - local gitdir = fn.system( - ("git -C %s rev-parse --show-toplevel"):format( - fn.expand( - "%:p:h" - ) - ) - ) + local gitdir = fn.system(("git -C %s rev-parse --show-toplevel"):format(fn.expand("%:p:h"))) if gitdir:match("^fatal:.*") then M.info("Failed to get git directory") @@ -260,14 +215,10 @@ function M.tmux(disable) end if disable then fn.system([[tmux set status off]]) - fn.system( - [[tmux list-panes -F '\#F' | grep -q Z || tmux resize-pane -Z]] - ) + fn.system([[tmux list-panes -F '\#F' | grep -q Z || tmux resize-pane -Z]]) else fn.system([[tmux set status on]]) - fn.system( - [[tmux list-panes -F '\#F' | grep -q Z && tmux resize-pane -Z]] - ) + fn.system([[tmux list-panes -F '\#F' | grep -q Z && tmux resize-pane -Z]]) end end