snailed
/
taolf
Archived
2
0
Fork 0

chore: allow global setup to work with command

This commit is contained in:
Lucas Burns 2022-04-10 19:42:15 -05:00
parent 313c9508b4
commit 251b24ff2c
No known key found for this signature in database
GPG Key ID: C011CBEF6628B679
7 changed files with 211 additions and 80 deletions

View File

@ -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`

36
lua/lf.lua Normal file
View File

@ -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

View File

@ -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]

View File

@ -1,7 +0,0 @@
-- TODO: Cleanup set/new/start functions
return {
setup = function(config)
return require("lf.action").Lf:new(config)
end,
}

View File

@ -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)

View File

@ -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

View File

@ -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