diff --git a/README.md b/README.md index 46e2a6e..52e7839 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ This is a neovim plugin for the [`lf`](https://github.com/gokcehan/lf) file manager. It is very similar to [`lf.vim`](https://github.com/ptzz/lf.vim), except for that this is written in Lua. -**NOTE**: This plugin uses [`toggleterm.nvim`](https://github.com/akinsho/toggleterm.nvim) and [`plenary.nvim`](https://github.com/nvim-lua/plenary.nvim) +**NOTE**: This plugin uses [`toggleterm.nvim`](https://github.com/akinsho/toggleterm.nvim). ### Installation ```lua @@ -15,24 +15,32 @@ use({ vim.g.lf_netrw = 1 require("lf").setup({ - escape_quit = false, - border = "rounded", - -- highlights = {FloatBorder = {guifg = require("kimbox.palette").colors.magenta}} + escape_quit = false, + border = "rounded", }) - vim.keymap.set("n", "", ":Lf") + vim.keymap.set("n", "", "Lf") + + vim.api.nvim_create_autocmd({ + event = "User", + pattern = "LfTermEnter", + callback = function(a) + vim.api.nvim_buf_set_keymap(a.buf, "t", "q", "q", {nowait = true}) + end, + }) end, - requires = {"plenary.nvim", "toggleterm.nvim"} + requires = {"toggleterm.nvim"} }) ``` ### Setup/Configuration ```lua +local fn = vim.fn + -- Defaults require("lf").setup({ - default_cmd = "lf", -- default `lf` command - default_action = "edit", -- default action when `Lf` opens a file + default_action = "drop", -- default action when `Lf` opens a file default_actions = { -- default action keybindings [""] = "tabedit", [""] = "split", @@ -43,37 +51,34 @@ require("lf").setup({ winblend = 10, -- psuedotransparency level dir = "", -- directory where `lf` starts ('gwd' is git-working-directory, ""/nil is CWD) direction = "float", -- window type: float horizontal vertical - border = "double", -- border kind: single double shadow curved - height = 0.80, -- height of the *floating* window - width = 0.85, -- width of the *floating* window + border = "rounded", -- border kind: single double shadow curved + height = fn.float2nr(fn.round(0.75 * o.lines)), -- height of the *floating* window + width = fn.float2nr(fn.round(0.75 * o.columns)), -- width of the *floating* window escape_quit = true, -- map escape to the quit command (so it doesn't go into a meta normal mode) - focus_on_open = false, -- focus the current file when opening Lf (experimental) + focus_on_open = true, -- focus the current file when opening Lf (experimental) mappings = true, -- whether terminal buffer mapping is enabled tmux = false, -- tmux statusline can be disabled on opening of Lf highlights = { -- highlights passed to toggleterm - Normal = { guibg = }, - NormalFloat = { link = 'Normal' }, - FloatBorder = { - guifg = , - guibg = - } + Normal = {link = "Normal"}, + NormalFloat = {link = 'Normal'}, + FloatBorder = {guifg = "", guibg = ""}, }, -- Layout configurations - layout_mapping = "", -- resize window with this key - + layout_mapping = "", -- resize window with this key views = { -- window dimensions to rotate through - { 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.950, height = 0.950 }, - } + {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}, }) -vim.keymap.set("n", "", "lua require('lf').start()", {noremap = true}) +-- Equivalent +vim.keymap.set("n", "", "lua require('lf').start()", {noremap = true}) +vim.keymap.set("n", "", "Lf", {noremap = true}) ``` Another option is to use `vim.keymap.set`, which requires `nvim` 0.7.0 or higher. This doesn't require local @@ -156,8 +161,8 @@ The mappings that are listed in the `setup` call above are the default bindings. * `` = `tabedit` * `` = `split` * `` = `vsplit` -* `` = `tab drop` (`` is also suggested) -* `` = resize the floating window +* `` = `tab drop` (`` is also suggested) +* `` = resize the floating window ### Notes The `autocmd` `LfTermEnter` is fired when the terminal buffer first opens diff --git a/doc/lf.txt b/doc/lf.txt index e315fcb..aa178b5 100644 --- a/doc/lf.txt +++ b/doc/lf.txt @@ -1,12 +1,14 @@ *lf.txt* File Manager +*lf.nvim* Version: 0.2 -Author : Lucas Burns +Author : Lucas Burns +Homepage: License: BSD3 ================================================================================ - TABLE OF CONTENTS *lf-table-of-contents* + Introduction |lf-introduction| Requirements |lf-requirements| Installation |lf-installation| @@ -14,65 +16,131 @@ Usage |lf-usage| Configuration |lf-configuration| ================================================================================ - INTRODUCTION *lf-introduction* -*lf.nvim* is a plugin written in Lua that allows you to use the -*lf* file manager inside of Neovim. +`lf.nvim` is a plugin written in Lua that allows you to use the +`lf` file manager inside of Neovim. -There is a similar plugin *lf.vim* which +There is a similar plugin `lf.vim` which basically does the same thing, except that is is written in Vimscript. Since this plugin uses the Neovim window API, Vim is not supported. ================================================================================ - REQUIREMENTS *lf-requirements* -1. *Lf* (https://github.com/gokechan/lf) -2. *toggleterm.nvim* (https://github.com/akinsho/toggleterm.nvim) -3. *plenary.nvim* (https://github.com/nvim-lua/plenary.nvim) +1. `lf` (https://github.com/gokechan/lf) +2. `toggleterm.nvim` (https://github.com/akinsho/toggleterm.nvim) ================================================================================ - INSTALLATION *lf-installation* Requires lf to be installed. The installation instructions for lf can be found here . -A sample installation is given. -NOTE: Replacing |netrw| will not work correctly if the plugin is lazily loaded. -> - use( - { - "lmburns/lf.nvim", - config = function() - vim.g.lf_netrw = 1 +See: |lf-configuration| - require("lf").setup( - { - escape_quit = false, - border = "rounded", - highlights = {FloatBorder = {guifg = require("kimbox.palette").colors.magenta}} - } - ) +Example ~ + NOTE: Replacing |netrw| will not work correctly if the plugin is lazily loaded. +>lua + use({ + "lmburns/lf.nvim", + config = function() + -- This feature will not work if the plugin is lazy-loaded + vim.g.lf_netrw = 1 - vim.keymap.set("n", "", ":Lf") - end, - requires = {"plenary.nvim", "toggleterm.nvim"} - } - ) + require("lf").setup({ + escape_quit = false, + border = "rounded", + }) + + vim.keymap.set("n", "", "Lf") + + vim.api.nvim_create_autocmd({ + event = "User", + pattern = "LfTermEnter", + callback = function(a) + vim.api.nvim_buf_set_keymap(a.buf, "t", "q", "q", {nowait = true}) + end, + }) + end, + requires = {"toggleterm.nvim"} + }) < ================================================================================ - USAGE *lf-usage* -The file manager can be opened with the |:Lf| command. +The file manager can be opened with the |:Lf| command or the Lua function >lua + require("lf").start() +<. + +Argument scheme ~ + +- Opens in current directory with rounded borders >lua + require('lf').start({border = "rounded"}) + -- equivalent + require('lf').start(nil, {border = "rounded"}) +< +- Opens in `~/.config` with either `.setup()` or default options >lua + require('lf').start("~/.config") + -- equivalent + require('lf').start("~/.config", nil) + -- same but rounded borders + require('lf').start("~/.config", {border = "rounded"} +< +- Opens in current directory with either `.setup()` or default options >lua + require('lf').start(nil, nil) + -- equivalent + require('lf').start() +< ================================================================================ - CONFIGURATION *lf-configuration* +Defaults ~ +>lua + require("lf").setup({ + default_action = "drop", -- default action when `Lf` opens a file + default_actions = { -- default action keybindings + [""] = "tabedit", + [""] = "split", + [""] = "vsplit", + [""] = "tab drop", + }, + + winblend = 10, -- psuedotransparency level + dir = "", -- directory where `lf` starts (`'gwd'` is git-working-directory, ""/nil is CWD) + direction = "float", -- window type: float horizontal vertical + border = "rounded", -- border kind: single double shadow curved + height = fn.float2nr(fn.round(0.75 * o.lines)), -- height of the floating window + width = fn.float2nr(fn.round(0.75 * o.columns)), -- width of the floating window + escape_quit = true, -- map escape to the quit command (so it doesn't go into a meta normal mode) + focus_on_open = true, -- focus the current file when opening Lf (experimental) + mappings = true, -- whether terminal buffer mapping is enabled + tmux = false, -- tmux statusline can be disabled on opening of Lf + highlights = { -- highlights passed to toggleterm + Normal = {link = "Normal"}, + NormalFloat = {link = 'Normal'}, + FloatBorder = {guifg = "", guibg = ""}, + }, + + -- Layout configurations + layout_mapping = "", -- resize window with this key + views = { -- window dimensions to rotate through + {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}, + }) + + -- Equivalent + vim.keymap.set("n", "", "lua require('lf').start()", {noremap = true}) + vim.keymap.set("n", "", "Lf", {noremap = true}) +< + ================================================================================ vim:tw=80:sw=0:ts=2:sts=2:et:ft=help:norl: diff --git a/lua/lf.lua b/lua/lf.lua index c020ce5..cd3b47c 100644 --- a/lua/lf.lua +++ b/lua/lf.lua @@ -4,7 +4,7 @@ local loaded = false local utils = require("lf.utils") ---Check Neovim version before setting mappings ----@param cfg LfConfig +---@param cfg Lf.Config local function has_feature(cfg) if not vim.keymap or not vim.keymap.set then utils.err("lf.nvim mappings require Neovim 0.7.0 or higher", true) @@ -13,7 +13,7 @@ local function has_feature(cfg) end ---Setup the Lf plugin ----@param cfg LfConfig +---@param cfg Lf.Config function M.setup(cfg) if loaded then return @@ -26,8 +26,13 @@ end ---Start the file manager ---`nil` can be used as the first parameter to change options and open in CWD ----@param path string optional path to start in ----@param cfg LfConfig +---@param path? string optional path to start in +---@param cfg? Lf.Config alternative configuration options +---@overload fun(cfg: Lf.Config) Only a config +---@overload fun(path: string) Only a path +---@overload fun(path: string, cfg: Lf.Config) Path and config are both valid +---@overload fun(path: nil, cfg: Lf.Config) Explicit nil to provide a config +---@overload fun() Empty function M.start(path, cfg) local path_t = type(path) local Lf = require("lf.main") diff --git a/lua/lf/config.lua b/lua/lf/config.lua index 8b2a77b..60cf511 100644 --- a/lua/lf/config.lua +++ b/lua/lf/config.lua @@ -3,7 +3,7 @@ local o = vim.o local Config = {} ----@type LfConfig +---@type Lf.Config local opts = { default_cmd = "lf", default_action = "drop", @@ -17,8 +17,8 @@ local opts = { dir = "", direction = "float", border = "double", - width = fn.float2nr(fn.round(0.75 * o.columns)), height = fn.float2nr(fn.round(0.75 * o.lines)), + width = fn.float2nr(fn.round(0.75 * o.columns)), escape_quit = false, focus_on_open = true, mappings = true, @@ -27,6 +27,11 @@ local opts = { Normal = {link = "Normal"}, FloatBorder = {link = "FloatBorder"}, }, + count = nil, + env = { + clear = false, + vars = {}, -- NOTE: this doesn't work for now + }, -- Layout configurations layout_mapping = "", views = { @@ -41,8 +46,8 @@ local opts = { } ---Validate configuration values ----@param cfg LfConfig existing configuration options ----@return LfConfig +---@param cfg Lf.Config existing configuration options +---@return Lf.Config local function validate(cfg) vim.validate({ default_cmd = {cfg.default_cmd, "s", false}, @@ -75,7 +80,7 @@ end local function init() local lf = require("lf") -- Keep options from the `lf.setup()` call - Config = vim.tbl_deep_extend("keep", lf.__conf or {}, opts) --[[@as LfConfig]] + Config = vim.tbl_deep_extend("keep", lf.__conf or {}, opts) --[[@as Lf.Config]] Config = validate(Config) lf.__conf = nil end @@ -83,11 +88,11 @@ end init() ---Set a configuration passed as a function argument (not through `setup`) ----@param cfg? LfConfig configuration options ----@return LfConfig +---@param cfg? Lf.Config configuration options +---@return Lf.Config function Config:override(cfg) if type(cfg) == "table" then - self = vim.tbl_deep_extend("force", self, cfg) --[[@as LfConfig]] + self = vim.tbl_deep_extend("force", self, cfg) --[[@as Lf.Config]] self = validate(self) end return self @@ -101,40 +106,48 @@ return setmetatable(Config, { 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 +---@alias Lf.border.generic {[1]:string,[2]:string,[3]:string,[4]:string,[5]:string,[6]:string,[7]:string,[8]:string} +---@alias Lf.border "'none'"|"'single'"|"'double'"|"'rounded'"|"'solid'"|"'shadow'"|Lf.border.generic +---@alias Lf.direction "'vertical'"|"'horizontal'"|"'tab'"|"'float'" +---@alias Lf.directory "'gwd'"|"''"|nil|string ----@class LfViews +---@class Lf.views ---@field relative "'editor'"|"'win'"|"'cursor'"|"'mouse'" ----@field win number For `relative='win'` +---@field win integer 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 row integer|float +---@field col integer|float ---@field focusable boolean ---@field zindex number ---@field style "'minimal'" ----@field border LfBorder Border kind +---@field border Lf.border 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 +---@class Lf.env +---@field clear boolean Should environment variables be cleared? +---@field vars table Hash of variables to be set on startup + +---@class Lf.Config ---@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 default_actions table 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 dir Lf.directory Directory where `lf` starts ('gwd' is git-working-directory, ""/nil is CWD) +---@field direction Lf.direction Window layout +---@field border Lf.border Border kind +---@field width integer Width of the *floating* window +---@field height integer Height 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 env Lf.env Environment variables ---@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` +---@field views Lf.views[] Table of layouts to be applied to `nvim_win_set_config` +---@field count? integer A number that triggers that specific terminal diff --git a/lua/lf/main.lua b/lua/lf/main.lua index d776776..9ad14d3 100644 --- a/lua/lf/main.lua +++ b/lua/lf/main.lua @@ -22,7 +22,7 @@ local Config = require("lf.config") local Terminal = require("toggleterm.terminal").Terminal ---@class Lf ----@field cfg LfConfig Configuration options +---@field cfg Lf.Config Configuration options ---@field term Terminal toggleterm terminal ---@field view_idx number Current index of configuration `views` ---@field winid? number `Terminal` window id @@ -62,8 +62,7 @@ end ---Setup a new instance of `Lf` ---Configuration has not been fully parsed by the end of this function ---A `Terminal` becomes attached and is able to be toggled ---- ----@param config? LfConfig +---@param config? Lf.Config ---@return Lf function Lf:new(config) if config then @@ -94,15 +93,14 @@ function Lf:__create_term() winblend = self.cfg.winblend, close_on_exit = true, hidden = false, - persist_size = false, - persist_mode = true, + clear_env = self.cfg.env.clear, highlights = self.cfg.highlights, + display_name = "Lf", + count = self.cfg.count, float_opts = { border = self.cfg.border, width = self.cfg.width, height = self.cfg.height, - row = self.cfg.row, - col = self.cfg.col, winblend = self.cfg.winblend, }, }) @@ -130,7 +128,6 @@ end ---@private ---Set the directory for `Lf` to open in ---- ---@param path? string ---@return Lf? function Lf:__open_in(path) @@ -160,7 +157,6 @@ end ---@private ---Wrap the default command to write the selected files to a temporary file ---- ---@return Lf function Lf:__set_cmd_wrapper() self.tmp_sel = os.tmpname() diff --git a/plugin/lf.lua b/plugin/lf.lua index c94650c..97f4d82 100644 --- a/plugin/lf.lua +++ b/plugin/lf.lua @@ -1,17 +1,18 @@ -local M = {} - -if _G.loaded_lf == 1 then +if vim.g.loaded_lf == 1 then return end +vim.g.loaded_lf = 1 + +local M = {} + local uv = vim.loop local api = vim.api local fn = vim.fn local cmd = vim.cmd -_G.loaded_lf = 1 - api.nvim_create_user_command("Lf", function(tbl) + ---@diagnostic disable-next-line: missing-parameter require("lf").start(tbl.args) end, {nargs = "*", complete = "file"})