chore: allow global setup to work with command
This commit is contained in:
parent
313c9508b4
commit
251b24ff2c
52
README.md
52
README.md
|
@ -8,10 +8,8 @@ It is very similar to [`lf.vim`](https://github.com/ptzz/lf.vim), except for tha
|
|||
### Setup/Configuration
|
||||
|
||||
```lua
|
||||
local M = {}
|
||||
|
||||
-- Defaults
|
||||
local lf = require("lf").setup({
|
||||
require("lf").setup({
|
||||
default_cmd = "lf", -- default `lf` command
|
||||
default_action = "edit", -- default action when `Lf` opens a file
|
||||
default_actions = { -- default action keybindings
|
||||
|
@ -27,17 +25,43 @@ local lf = require("lf").setup({
|
|||
border = "double", -- border kind: single double shadow curved
|
||||
height = 0.80, -- height of the *floating* window
|
||||
width = 0.85, -- width of the *floating* window
|
||||
mappings = true, -- whether terminal buffer mapping is enabled
|
||||
})
|
||||
|
||||
function M.start_lf()
|
||||
lf:start()
|
||||
end
|
||||
vim.api.nvim_set_keymap("n", "<mapping>", "<cmd>lua require('lf').start()", { noremap = true })
|
||||
```
|
||||
|
||||
vim.api.nvim_set_keymap("n", "<mapping>", "<cmd>lua require('file').start_lf()", { noremap = true })
|
||||
-- or
|
||||
vim.api.nvim_set_keymap("n", "<mapping>", "<cmd>lua require('lf').setup():start()", { noremap = true })
|
||||
Another option is to use `vim.keymap.set`, which requires `nvim` 0.7.0 or higher. This doesn't require local
|
||||
variables and would allow customization of the program.
|
||||
|
||||
return M
|
||||
```lua
|
||||
vim.keymap.set(
|
||||
"n",
|
||||
"<mapping>",
|
||||
function()
|
||||
require("lf").start(
|
||||
nil, -- this is the path to open Lf (nil means CWD)
|
||||
{
|
||||
default_cmd = "lf", -- default `lf` command
|
||||
default_action = "edit", -- default action when `Lf` opens a file
|
||||
default_actions = { -- default action keybindings
|
||||
["<C-t>"] = "tabedit",
|
||||
["<C-x>"] = "split",
|
||||
["<C-v>"] = "vsplit",
|
||||
["<C-o>"] = "tab drop",
|
||||
},
|
||||
|
||||
winblend = 10, -- psuedotransparency level
|
||||
dir = "", -- directory where `lf` starts ('gwd' is git-working-directory)
|
||||
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
|
||||
mappings = true, -- whether terminal buffer mapping is enabled
|
||||
})
|
||||
end,
|
||||
{ noremap = true }
|
||||
)
|
||||
```
|
||||
|
||||
There is a command that does basically the exact same thing `:Lf`. This command takes one optional argument,
|
||||
|
@ -53,6 +77,14 @@ For the moment, these bindings are hijacked on the startup of `Lf`, and when the
|
|||
that your default action has changed. When you go to open a file as you normally would, this command is ran instead
|
||||
of your `default_action`.
|
||||
|
||||
### Neovim 0.7.0
|
||||
If you do not have the nightly version of `nvim`, then the `mappings` field can be set to false.
|
||||
Otherwise, a notification will be display saying that you are not allowed to use these.
|
||||
|
||||
```lua
|
||||
require("lf").setup({ mappings = false }):start()
|
||||
```
|
||||
|
||||
### Replacing Netrw
|
||||
The only configurable environment variable is `g:lf_replace_netrw`, which can be set to `1` to replace `netrw`
|
||||
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
local M = {}
|
||||
local loaded = false
|
||||
|
||||
local function has_feature(cfg)
|
||||
if not vim.keymap or not vim.keymap.set then
|
||||
local function print_err()
|
||||
require("lf.utils").notify(
|
||||
"lf.nvim mappings require Neovim 0.7.0 or higher", "error"
|
||||
)
|
||||
end
|
||||
|
||||
print_err()
|
||||
cfg.mappings = false
|
||||
-- Lf["__on_open"] = print_err
|
||||
end
|
||||
end
|
||||
|
||||
function M.setup(cfg)
|
||||
if loaded then
|
||||
return
|
||||
end
|
||||
|
||||
has_feature(cfg)
|
||||
M._cfg = cfg or {}
|
||||
loaded = true
|
||||
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
|
||||
function M.start(path, cfg)
|
||||
require("lf.main").Lf:new(cfg or M._cfg):start(path)
|
||||
end
|
||||
|
||||
return M
|
|
@ -8,32 +8,76 @@
|
|||
--- @field border string border kind: single double shadow curved
|
||||
--- @field height number height of the *floating* window
|
||||
--- @field width number width of the *floating* window
|
||||
local Config = {
|
||||
default_cmd = "lf",
|
||||
default_action = "edit",
|
||||
default_actions = {
|
||||
["<C-t>"] = "tabedit",
|
||||
["<C-x>"] = "split",
|
||||
["<C-v>"] = "vsplit",
|
||||
["<C-o>"] = "tab drop",
|
||||
},
|
||||
--- @field mappings boolean whether terminal buffer mappings should be set
|
||||
local Config = {}
|
||||
|
||||
winblend = 10,
|
||||
dir = "",
|
||||
direction = "float",
|
||||
border = "double",
|
||||
height = 0.80,
|
||||
width = 0.85,
|
||||
}
|
||||
-- A local function that runs each time allows for a global `.setup()` to work
|
||||
|
||||
--- Initialize the default configuration
|
||||
local function init()
|
||||
local lf = require("lf")
|
||||
vim.validate({ config = { lf._config, "table", true } })
|
||||
|
||||
local opts = {
|
||||
default_cmd = "lf",
|
||||
default_action = "edit",
|
||||
default_actions = {
|
||||
["<C-t>"] = "tabedit",
|
||||
["<C-x>"] = "split",
|
||||
["<C-v>"] = "vsplit",
|
||||
["<C-o>"] = "tab drop",
|
||||
},
|
||||
|
||||
winblend = 10,
|
||||
dir = "",
|
||||
direction = "float",
|
||||
border = "double",
|
||||
height = 0.80,
|
||||
width = 0.85,
|
||||
mappings = true,
|
||||
}
|
||||
|
||||
Config = vim.tbl_deep_extend("keep", lf._config or {}, opts)
|
||||
lf._config = nil
|
||||
end
|
||||
|
||||
init()
|
||||
|
||||
local notify = require("lf.utils").notify
|
||||
|
||||
---Verify that configuration options that are numbers are numbers or can be converted to numbers
|
||||
---@param field string `Config` field to check
|
||||
function Config:__check_number(field)
|
||||
if type(field) == "string" then
|
||||
local res = tonumber(field)
|
||||
if res == nil then
|
||||
notify(("invalid option for winblend: %s"):format(field))
|
||||
return self.winblend
|
||||
else
|
||||
return res
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
---Set a configuration passed as a function argument (not through `setup`)
|
||||
---@param cfg table configuration options
|
||||
---@return Config
|
||||
function Config:set(cfg)
|
||||
if cfg and type(cfg) ~= "table" then
|
||||
if cfg and type(cfg) == "table" then
|
||||
|
||||
cfg.winblend = self:__check_number(cfg.winblend)
|
||||
cfg.height = self:__check_number(cfg.height)
|
||||
cfg.width = self:__check_number(cfg.width)
|
||||
|
||||
self = vim.tbl_deep_extend("force", self, cfg or {})
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
---Get the entire configuration if empty, else get the given key
|
||||
---@param key string option to get
|
||||
---@return Config
|
||||
function Config:get(key)
|
||||
if key then
|
||||
return self[key]
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
-- TODO: Cleanup set/new/start functions
|
||||
|
||||
return {
|
||||
setup = function(config)
|
||||
return require("lf.action").Lf:new(config)
|
||||
end,
|
||||
}
|
|
@ -24,10 +24,9 @@ local g = vim.g
|
|||
local map = utils.map
|
||||
|
||||
---Error for this program
|
||||
ERROR = nil
|
||||
---Global running status
|
||||
---I'm unsure of a way to keep an `Lf` variable constant through more than 1 `setup` calls
|
||||
g.__lf_running = false
|
||||
M.error = nil
|
||||
---Is `Lf` configured?
|
||||
M.loaded = nil
|
||||
|
||||
local Config = require("lf.config")
|
||||
|
||||
|
@ -35,12 +34,9 @@ local Config = require("lf.config")
|
|||
local Terminal = require("toggleterm.terminal").Terminal
|
||||
|
||||
--- @class Lf
|
||||
--- @field cmd string
|
||||
--- @field direction string the layout style for the terminal
|
||||
--- @field id number
|
||||
--- @field window number
|
||||
--- @field job_id number
|
||||
--- @field highlights table<string, table<string, string>>
|
||||
--- @field cfg Config Configuration options
|
||||
--- @field cwd string Current working directory
|
||||
--- @field term Terminal Toggle terminal
|
||||
local Lf = {}
|
||||
|
||||
local function setup_term()
|
||||
|
@ -72,49 +68,64 @@ end
|
|||
---@param config 'table'
|
||||
---@return Lf
|
||||
function Lf:new(config)
|
||||
local cfg = Config:set(config):get()
|
||||
self.__index = self
|
||||
|
||||
self.cfg = cfg
|
||||
if config then
|
||||
self.cfg = Config:set(config):get()
|
||||
else
|
||||
self.cfg = Config
|
||||
end
|
||||
|
||||
self.bufnr = nil
|
||||
|
||||
-- TODO: use or del
|
||||
self.cwd = uv.cwd()
|
||||
|
||||
setup_term()
|
||||
self:__create_term()
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
---Create the toggle terminal
|
||||
function Lf:__create_term()
|
||||
self.term = Terminal:new(
|
||||
{
|
||||
cmd = cfg.default_cmd,
|
||||
dir = cfg.dir,
|
||||
direction = cfg.direction,
|
||||
winblend = cfg.winblend,
|
||||
cmd = self.cfg.default_cmd,
|
||||
dir = self.cfg.dir,
|
||||
direction = self.cfg.direction,
|
||||
winblend = self.cfg.winblend,
|
||||
close_on_exit = true,
|
||||
|
||||
float_opts = {
|
||||
border = cfg.border,
|
||||
width = math.floor(vim.o.columns * cfg.width),
|
||||
height = math.floor(vim.o.lines * cfg.height),
|
||||
winblend = cfg.winblend,
|
||||
border = self.cfg.border,
|
||||
width = math.floor(vim.o.columns * self.cfg.width),
|
||||
height = math.floor(vim.o.lines * self.cfg.height),
|
||||
winblend = self.cfg.winblend,
|
||||
highlights = { border = "Normal", background = "Normal" },
|
||||
},
|
||||
|
||||
-- on_open = cfg.on_open,
|
||||
-- on_close = nil,
|
||||
}
|
||||
)
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
---Start the underlying terminal
|
||||
---@param path string path where lf starts (reads from config if none, else CWD)
|
||||
function Lf:start(path)
|
||||
self:__open_in(path or self.cfg.dir)
|
||||
if ERROR ~= nil then
|
||||
notify(ERROR, "error")
|
||||
if M.error ~= nil then
|
||||
notify(M.error, "error")
|
||||
return
|
||||
end
|
||||
self:__wrapper()
|
||||
|
||||
self.term.on_open = function(term)
|
||||
self:__on_open(term)
|
||||
if self.cfg.mappings then
|
||||
self.term.on_open = function(term)
|
||||
self:__on_open(term)
|
||||
end
|
||||
else
|
||||
self.term.on_open = function(_)
|
||||
self.bufnr = api.nvim_get_current_buf()
|
||||
end
|
||||
end
|
||||
|
||||
self.term.on_exit = function(term, _, _, _)
|
||||
|
@ -123,17 +134,16 @@ function Lf:start(path)
|
|||
|
||||
-- NOTE: Maybe pcall here?
|
||||
self.term:toggle()
|
||||
g.__lf_running = true
|
||||
end
|
||||
|
||||
function M.print_active()
|
||||
p(active)
|
||||
end
|
||||
|
||||
---Toggle `Lf` on and off
|
||||
---@param path string
|
||||
function Lf:toggle(path)
|
||||
print(g.__lf_running)
|
||||
if g.__lf_running then
|
||||
self.term:close()
|
||||
g.__lf_running = false
|
||||
else
|
||||
self:start(path)
|
||||
end
|
||||
-- TODO:
|
||||
end
|
||||
|
||||
---@private
|
||||
|
@ -148,16 +158,18 @@ function Lf:__open_in(path)
|
|||
dir = require("lf.utils").git_dir()
|
||||
end
|
||||
|
||||
if dir then
|
||||
if dir ~= "" then
|
||||
return fn.expand(dir)
|
||||
else
|
||||
return self.cwd
|
||||
-- `uv` lib doesn't switch directories
|
||||
-- Expanding the filename works instead
|
||||
return fn.expand("%:p")
|
||||
end
|
||||
end)(path)
|
||||
)
|
||||
|
||||
if not path:exists() then
|
||||
ERROR = ("directory doesn't exist: %s"):format(path)
|
||||
M.error = ("directory doesn't exist: %s"):format(path)
|
||||
return
|
||||
end
|
||||
|
||||
|
@ -189,6 +201,9 @@ end
|
|||
---On open closure to run in the `Terminal`
|
||||
---@param term Terminal
|
||||
function Lf:__on_open(term)
|
||||
-- api.nvim_command("setlocal filetype=lf")
|
||||
M.loaded = true
|
||||
self.bufnr = api.nvim_get_current_buf()
|
||||
for key, mapping in pairs(self.cfg.default_actions) do
|
||||
map(
|
||||
"t", key, function()
|
||||
|
@ -206,9 +221,16 @@ end
|
|||
function Lf:__callback(term)
|
||||
if (self.cfg.default_action == "cd" or self.cfg.default_action == "lcd") and
|
||||
uv.fs_stat(self.lastdir_tmp) then
|
||||
local f = io.open(self.lastdir_tmp)
|
||||
local last_dir = f:read()
|
||||
f:close()
|
||||
|
||||
local with = require("plenary.context_manager").with
|
||||
local open = require("plenary.context_manager").open
|
||||
|
||||
-- Since plenary is already being used, this is used instead of `io`
|
||||
local last_dir = with(
|
||||
open(self.lastdir_tmp), function(r)
|
||||
return r:read()
|
||||
end
|
||||
)
|
||||
|
||||
if last_dir ~= uv.cwd() then
|
||||
api.nvim_exec(("%s %s"):format(self.cfg.default_action, last_dir), true)
|
|
@ -58,6 +58,11 @@ M.git_dir = function()
|
|||
return vim.trim(gitdir)
|
||||
end
|
||||
|
||||
---Create a neovim keybinding
|
||||
---@param mode string vim mode in a single letter
|
||||
---@param lhs string keys that are bound
|
||||
---@param rhs string string or lua function that is mapped to the keys
|
||||
---@param opts table options set for the mapping
|
||||
M.map = function(mode, lhs, rhs, opts)
|
||||
opts = opts or {}
|
||||
opts.noremap = opts.noremap == nil and true or opts.noremap
|
||||
|
|
|
@ -1,16 +1,15 @@
|
|||
command! -nargs=* -complete=file Lf lua require('lf').setup():start(<f-args>)
|
||||
command! -nargs=* -complete=file Lf lua require('lf').start(<f-args>)
|
||||
|
||||
" TODO: Finish this command
|
||||
" command! -nargs=* -complete=file LfToggle lua require('lf').setup():toggle(<f-args>)
|
||||
|
||||
" TODO: Make sure that this works
|
||||
if exists('g:lf_replace_netrw') && g:lf_replace_netrw
|
||||
augroup ReplaceNetrwWithLf
|
||||
autocmd VimEnter * silent! autocmd! FileExplorer
|
||||
autocmd BufEnter * let s:buf_path = expand("%")
|
||||
\ | if isdirectory(s:buf_path)
|
||||
\ | bdelete!
|
||||
\ | call timer_start(100, {->v:lua.require'lf'.setup():start(s:buf_path)})
|
||||
\ | call timer_start(100, {->v:lua.require'lf'.start(s:buf_path)})
|
||||
\ | endif
|
||||
augroup END
|
||||
endif
|
||||
|
|
Reference in New Issue