Merge pull request #37 from kyazdani42/refacto-and-fixes

Refacto and fixes
This commit is contained in:
Kiyan Yazdani 2020-06-09 19:02:45 +02:00 committed by GitHub
commit 20b816bd8e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 107 additions and 79 deletions

13
.luacheckrc Normal file
View File

@ -0,0 +1,13 @@
-- vim: ft=lua tw=80
-- Don't report unused self arguments of methods.
self = false
ignore = {
"631", -- max_line_length
}
-- Global objects defined by the C code
read_globals = {
"vim",
}

View File

@ -25,7 +25,7 @@ local function get_colors()
} }
end end
local function get_hl_groups() local function get_hl_groups()
local colors = get_colors() local colors = get_colors()
return { return {
@ -96,7 +96,7 @@ M.hl_groups = {
['ejs'] = 'HtmlIcon'; ['ejs'] = 'HtmlIcon';
} }
local function get_links() local function get_links()
return { return {
FolderName = 'Directory', FolderName = 'Directory',
Normal = 'Normal', Normal = 'Normal',

View File

@ -57,4 +57,21 @@ function M.get_bindings()
} }
end end
function M.window_options()
local opts = {}
if vim.g.lua_tree_side == 'right' then
opts.side = 'L'
opts.open_command = 'h'
opts.preview_command = 'l'
opts.split_command = 'nosplitright'
else
opts.side = 'H'
opts.open_command = 'l'
opts.preview_command = 'h'
opts.split_command = 'splitright'
end
return opts
end
return M return M

View File

@ -28,7 +28,7 @@ local function create_file(file)
end end
local function get_num_entries(iter) local function get_num_entries(iter)
i = 0 local i = 0
for _ in iter do for _ in iter do
i = i + 1 i = i + 1
end end
@ -37,7 +37,7 @@ end
function M.create(node) function M.create(node)
if node.name == '..' then return end if node.name == '..' then return end
local add_into local add_into
if node.entries ~= nil then if node.entries ~= nil then
add_into = node.absolute_path..'/' add_into = node.absolute_path..'/'

View File

@ -51,8 +51,8 @@ local function create_root(cwd)
return true return true
end end
function M.update_status(entries, cwd) function M.update_status(entries, _cwd)
local cwd = cwd:gsub(' ', '\\ ') local cwd = _cwd:gsub(' ', '\\ '):gsub('%[', '\\['):gsub('%(', '\\(')
local git_root, git_status = get_git_root(cwd) local git_root, git_status = get_git_root(cwd)
if not git_root then if not git_root then
if not create_root(cwd) then if not create_root(cwd) then

View File

@ -8,6 +8,8 @@ local pops = require'lib.populate'
local populate = pops.populate local populate = pops.populate
local refresh_entries = pops.refresh_entries local refresh_entries = pops.refresh_entries
local window_opts = config.window_options()
local M = {} local M = {}
M.Tree = { M.Tree = {
@ -16,12 +18,15 @@ M.Tree = {
cwd = nil, cwd = nil,
win_width = vim.g.lua_tree_width or 30, win_width = vim.g.lua_tree_width or 30,
loaded = false, loaded = false,
side = 'H',
bufnr = nil, bufnr = nil,
winnr = nil, winnr = nil,
buf_options = { buf_options = {
'sidescroll=5', 'noswapfile', 'splitbelow', 'sidescroll=5',
'noruler', 'noshowmode', 'noshowcmd' 'noswapfile',
'splitbelow',
'noruler',
'noshowmode',
'noshowcmd'
}, },
win_options = { win_options = {
relativenumber = false, relativenumber = false,
@ -36,10 +41,6 @@ M.Tree = {
} }
} }
if vim.g.lua_tree_side == 'right' then
M.Tree.side = 'L'
end
function M.init(with_open, with_render) function M.init(with_open, with_render)
M.Tree.cwd = luv.cwd() M.Tree.cwd = luv.cwd()
populate(M.Tree.entries, M.Tree.cwd, M.Tree) populate(M.Tree.entries, M.Tree.cwd, M.Tree)
@ -117,7 +118,7 @@ local function refresh_nodes(node)
end end
function M.refresh_tree() function M.refresh_tree()
local stat = luv.fs_stat(M.Tree.cwd) -- local stat = luv.fs_stat(M.Tree.cwd)
-- if stat.mtime.sec ~= M.Tree.last_modified then -- if stat.mtime.sec ~= M.Tree.last_modified then
refresh_nodes(M.Tree) refresh_nodes(M.Tree)
-- end -- end
@ -178,18 +179,10 @@ function M.set_index_and_redraw(fname)
end end
function M.open_file(mode, filename) function M.open_file(mode, filename)
if vim.g.lua_tree_side == 'right' then api.nvim_command('noautocmd wincmd '..window_opts.open_command)
api.nvim_command('noautocmd wincmd h')
else
api.nvim_command('noautocmd wincmd l')
end
if mode == 'preview' then if mode == 'preview' then
api.nvim_command(string.format("edit %s", filename)) api.nvim_command(string.format("edit %s", filename))
if vim.g.lua_tree_side == 'right' then api.nvim_command('noautocmd wincmd '..window_opts.preview_command)
api.nvim_command('noautocmd wincmd l')
else
api.nvim_command('noautocmd wincmd h')
end
else else
api.nvim_command(string.format("%s %s", mode, filename)) api.nvim_command(string.format("%s %s", mode, filename))
end end
@ -246,18 +239,13 @@ local function create_buf()
api.nvim_command('setlocal '..opt) api.nvim_command('setlocal '..opt)
end end
if M.Tree.side == 'L' then api.nvim_command('setlocal '..window_opts.split_command)
api.nvim_command('setlocal nosplitright')
else
api.nvim_command('setlocal splitright')
end
set_mappings() set_mappings()
end end
local function create_win() local function create_win()
api.nvim_command("vsplit") api.nvim_command("vsplit")
api.nvim_command("wincmd "..M.Tree.side) api.nvim_command("wincmd "..window_opts.side)
api.nvim_command("vertical resize "..M.Tree.win_width) api.nvim_command("vertical resize "..M.Tree.win_width)
M.Tree.winnr = api.nvim_get_current_win() M.Tree.winnr = api.nvim_get_current_win()

View File

@ -37,6 +37,11 @@ local function file_new(cwd, name)
} }
end end
-- TODO-INFO: sometimes fs_realpath returns nil
-- I expect this be a bug in glibc, because it fails to retrieve the path for some
-- links (for instance libr2.so in /usr/lib) and thus even with a C program realpath fails
-- when it has no real reason to. Maybe there is a reason, but errno is definitely wrong.
-- So we need to check for link_to ~= nil when adding new links to the main tree
local function link_new(cwd, name) local function link_new(cwd, name)
local absolute_path = cwd..'/'..name local absolute_path = cwd..'/'..name
local link_to = luv.fs_realpath(absolute_path) local link_to = luv.fs_realpath(absolute_path)
@ -114,9 +119,9 @@ function M.refresh_entries(entries, cwd)
end end
local all = { local all = {
{ entries = dirs, fn = dir_new }, { entries = dirs, fn = dir_new, check = function(_, abs) return luv.fs_access(abs, 'R') end },
{ entries = links, fn = link_new }, { entries = links, fn = link_new, check = function(name) return name ~= nil end },
{ entries = files, fn = file_new } { entries = files, fn = file_new, check = function() return true end }
} }
local prev = nil local prev = nil
@ -124,8 +129,11 @@ function M.refresh_entries(entries, cwd)
for _, name in ipairs(e.entries) do for _, name in ipairs(e.entries) do
if not named_entries[name] then if not named_entries[name] then
local n = e.fn(cwd, name) local n = e.fn(cwd, name)
if not e.check(n.link_to, n.absolute_path) then
goto continue
end
local idx = 1 idx = 1
if prev then if prev then
idx = entries_idx[prev] + 1 idx = entries_idx[prev] + 1
end end
@ -134,6 +142,7 @@ function M.refresh_entries(entries, cwd)
cached_entries[idx] = name cached_entries[idx] = name
end end
prev = name prev = name
::continue::
end end
end end
end end
@ -152,6 +161,7 @@ function M.populate(entries, cwd)
while true do while true do
local name, t = luv.fs_scandir_next(handle) local name, t = luv.fs_scandir_next(handle)
if not name then break end if not name then break end
if should_ignore(name) then goto continue end
if t == 'directory' then if t == 'directory' then
table.insert(dirs, name) table.insert(dirs, name)
@ -160,29 +170,29 @@ function M.populate(entries, cwd)
elseif t == 'link' then elseif t == 'link' then
table.insert(links, name) table.insert(links, name)
end end
::continue::
end end
-- Create Nodes -- -- Create Nodes --
for _, dirname in ipairs(dirs) do for _, dirname in ipairs(dirs) do
local dir = dir_new(cwd, dirname) local dir = dir_new(cwd, dirname)
if not should_ignore(dir.name) and luv.fs_access(dir.absolute_path, 'R') then if luv.fs_access(dir.absolute_path, 'R') then
table.insert(entries, dir) table.insert(entries, dir)
end end
end end
for _, linkname in ipairs(links) do for _, linkname in ipairs(links) do
local link = link_new(cwd, linkname) local link = link_new(cwd, linkname)
if not should_ignore(link.name) then if link.link_to ~= nil then
table.insert(entries, link) table.insert(entries, link)
end end
end end
for _, filename in ipairs(files) do for _, filename in ipairs(files) do
local file = file_new(cwd, filename) local file = file_new(cwd, filename)
if not should_ignore(file.name) then table.insert(entries, file)
table.insert(entries, file)
end
end end
if not icon_config.show_git_icon then if not icon_config.show_git_icon then

View File

@ -11,8 +11,8 @@ local namespace_id = api.nvim_create_namespace('LuaTreeHighlights')
local icon_state = config.get_icon_state() local icon_state = config.get_icon_state()
local get_folder_icon = function() return "" end local get_folder_icon = function() return "" end
local set_folder_hl = function(index, depth, git_icon_len) local set_folder_hl = function(line, depth, git_icon_len)
table.insert(hl, {'LuaTreeFolderName', index, depth+git_icon_len, -1}) table.insert(hl, {'LuaTreeFolderName', line, depth+git_icon_len, -1})
end end
if icon_state.show_folder_icon then if icon_state.show_folder_icon then
@ -23,9 +23,9 @@ if icon_state.show_folder_icon then
return icon_state.icons.folder_icons.default .. " " return icon_state.icons.folder_icons.default .. " "
end end
end end
set_folder_hl = function(index, depth, icon_len, name_len) set_folder_hl = function(line, depth, icon_len, name_len)
table.insert(hl, {'LuaTreeFolderName', index, depth+icon_len, depth+icon_len+name_len}) table.insert(hl, {'LuaTreeFolderName', line, depth+icon_len, depth+icon_len+name_len})
table.insert(hl, {'LuaTreeFolderIcon', index, depth, depth+icon_len}) table.insert(hl, {'LuaTreeFolderIcon', line, depth, depth+icon_len})
end end
end end
@ -33,8 +33,9 @@ local get_file_icon = function() return "" end
if icon_state.show_file_icon then if icon_state.show_file_icon then
local web_devicons = require'nvim-web-devicons' local web_devicons = require'nvim-web-devicons'
get_file_icon = function(fname, extension, index, depth) get_file_icon = function(fname, extension, line, depth)
local icon, hl_group = web_devicons.get_icon(fname, extension) local hl_group
local icon, _ = web_devicons.get_icon(fname, extension)
-- TODO: remove this hl_group and make this in nvim-web-devicons -- TODO: remove this hl_group and make this in nvim-web-devicons
if #extension == 0 then if #extension == 0 then
hl_group = colors.hl_groups[fname] hl_group = colors.hl_groups[fname]
@ -42,7 +43,7 @@ if icon_state.show_file_icon then
hl_group = colors.hl_groups[extension] hl_group = colors.hl_groups[extension]
end end
if hl_group and icon then if hl_group and icon then
table.insert(hl, { 'LuaTree'..hl_group, index, depth, depth + #icon }) table.insert(hl, { 'LuaTree'..hl_group, line, depth, depth + #icon })
return icon.." " return icon.." "
else else
return icon_state.icons.default and icon_state.icons.default.." " or "" return icon_state.icons.default and icon_state.icons.default.." " or ""
@ -52,10 +53,8 @@ if icon_state.show_file_icon then
end end
local get_git_icons = function() return "" end local get_git_icons = function() return "" end
local git_icon_state = {}
if icon_state.show_git_icon then if icon_state.show_git_icon then
local git_icon_state = {
git_icon_state = {
["M "] = { { icon = icon_state.icons.git_icons.staged, hl = "LuaTreeGitStaged" } }, ["M "] = { { icon = icon_state.icons.git_icons.staged, hl = "LuaTreeGitStaged" } },
[" M"] = { { icon = icon_state.icons.git_icons.unstaged, hl = "LuaTreeGitDirty" } }, [" M"] = { { icon = icon_state.icons.git_icons.unstaged, hl = "LuaTreeGitDirty" } },
["MM"] = { ["MM"] = {
@ -77,14 +76,14 @@ if icon_state.show_git_icon then
dirty = { { icon = icon_state.icons.git_icons.unstaged, hl = "LuaTreeGitDirty" } }, dirty = { { icon = icon_state.icons.git_icons.unstaged, hl = "LuaTreeGitDirty" } },
} }
get_git_icons = function(node, index, depth, icon_len) get_git_icons = function(node, line, depth, icon_len)
local git_status = node.git_status local git_status = node.git_status
if not git_status then return "" end if not git_status then return "" end
local icon = "" local icon = ""
local icons = git_icon_state[git_status] local icons = git_icon_state[git_status]
for _, v in ipairs(icons) do for _, v in ipairs(icons) do
table.insert(hl, { v.hl, index, depth+icon_len+#icon, depth+icon_len+#icon+#v.icon }) table.insert(hl, { v.hl, line, depth+icon_len+#icon, depth+icon_len+#icon+#v.icon })
icon = icon..v.icon.." " icon = icon..v.icon.." "
end end
@ -166,7 +165,7 @@ function M.draw(tree, reload)
update_draw_data(tree, 0) update_draw_data(tree, 0)
end end
api.nvim_buf_set_lines(tree.bufnr, 0, -1, false, lines) api.nvim_buf_set_lines(tree.bufnr, 0, -1, false, lines)
M.render_hl(tree.bufnr) M.render_hl(tree.bufnr)
if #lines > cursor[1] then if #lines > cursor[1] then
api.nvim_win_set_cursor(tree.winnr, cursor) api.nvim_win_set_cursor(tree.winnr, cursor)

View File

@ -1,34 +1,35 @@
local luv = vim.loop local luv = vim.loop
local tree = require'lib.tree' local lib = require'lib.lib'
local colors = require'lib.colors' local colors = require'lib.colors'
local renderer = require'lib.renderer' local renderer = require'lib.renderer'
local fs = require'lib.fs' local fs = require'lib.fs'
local utils = require'lib.utils'
local api = vim.api local api = vim.api
local M = {} local M = {}
function M.toggle() function M.toggle()
if tree.win_open() then if lib.win_open() then
tree.close() lib.close()
else else
tree.open() lib.open()
end end
end end
function M.close() function M.close()
if tree.win_open() then if lib.win_open() then
tree.close() lib.close()
end end
end end
function M.open() function M.open()
if not tree.win_open() then if not lib.win_open() then
tree.open() lib.open()
end end
end end
function M.on_keypress(mode) function M.on_keypress(mode)
local node = tree.get_node_at_cursor() local node = lib.get_node_at_cursor()
if not node then return end if not node then return end
if mode == 'create' then if mode == 'create' then
@ -41,13 +42,13 @@ function M.on_keypress(mode)
if mode == 'preview' then if mode == 'preview' then
if node.entries ~= nil or node.name == '..' then return end if node.entries ~= nil or node.name == '..' then return end
return tree.open_file(mode, node.absolute_path) return lib.open_file(mode, node.absolute_path)
end end
if node.name == ".." then if node.name == ".." then
return tree.change_dir("..") return lib.change_dir("..")
elseif mode == "cd" and node.entries ~= nil then elseif mode == "cd" and node.entries ~= nil then
return tree.change_dir(node.absolute_path) return lib.change_dir(node.absolute_path)
elseif mode == "cd" then elseif mode == "cd" then
return return
end end
@ -56,16 +57,16 @@ function M.on_keypress(mode)
local stat = luv.fs_stat(node.link_to) local stat = luv.fs_stat(node.link_to)
-- TODO: potentially CD here -- TODO: potentially CD here
if stat.type == 'directory' then return end if stat.type == 'directory' then return end
tree.open_file(mode, node.link_to) lib.open_file(mode, node.link_to)
elseif node.entries ~= nil then elseif node.entries ~= nil then
tree.unroll_dir(node) lib.unroll_dir(node)
else else
tree.open_file(mode, node.absolute_path) lib.open_file(mode, node.absolute_path)
end end
end end
function M.refresh() function M.refresh()
tree.refresh_tree() lib.refresh_tree()
end end
function M.on_enter() function M.on_enter()
@ -79,7 +80,7 @@ function M.on_enter()
end end
local should_open = vim.g.lua_tree_auto_open == 1 and (bufname == '' or is_dir) local should_open = vim.g.lua_tree_auto_open == 1 and (bufname == '' or is_dir)
colors.setup() colors.setup()
tree.init(should_open, should_open) lib.init(should_open, should_open)
end end
local function is_file_readable(fname) local function is_file_readable(fname)
@ -92,12 +93,12 @@ local function find_file()
local bufname = api.nvim_buf_get_name(api.nvim_get_current_buf()) local bufname = api.nvim_buf_get_name(api.nvim_get_current_buf())
if not is_file_readable(bufname) then return end if not is_file_readable(bufname) then return end
tree.set_index_and_redraw(bufname) lib.set_index_and_redraw(bufname)
end end
function M.on_leave() function M.on_leave()
vim.defer_fn(function() vim.defer_fn(function()
if #api.nvim_list_wins() == 1 and tree.win_open() then if #api.nvim_list_wins() == 1 and lib.win_open() then
api.nvim_command(':qa!') api.nvim_command(':qa!')
end end
end, 50) end, 50)
@ -105,18 +106,18 @@ end
local function update_root_dir() local function update_root_dir()
local bufname = api.nvim_buf_get_name(api.nvim_get_current_buf()) local bufname = api.nvim_buf_get_name(api.nvim_get_current_buf())
if not is_file_readable(bufname) or not tree.Tree.cwd then return end if not is_file_readable(bufname) or not lib.Tree.cwd then return end
-- this logic is a hack -- this logic is a hack
-- depending on vim-rooter or autochdir, it would not behave the same way when those two are not enabled -- depending on vim-rooter or autochdir, it would not behave the same way when those two are not enabled
-- until i implement multiple workspaces/project, it should stay like this -- until i implement multiple workspaces/project, it should stay like this
if bufname:match(tree.Tree.cwd:gsub('(%-)', '(%%-)'):gsub('(%.)', '(%%.)')) ~= nil then if bufname:match(utils.path_to_matching_str(lib.Tree.cwd)) then
return return
end end
local new_cwd = luv.cwd() local new_cwd = luv.cwd()
if tree.Tree.cwd == new_cwd then return end if lib.Tree.cwd == new_cwd then return end
tree.change_dir(new_cwd) lib.change_dir(new_cwd)
end end
function M.buf_enter() function M.buf_enter()
@ -128,11 +129,11 @@ end
function M.reset_highlight() function M.reset_highlight()
colors.setup() colors.setup()
renderer.render_hl(tree.Tree.bufnr) renderer.render_hl(lib.Tree.bufnr)
end end
function M.xdg_open() function M.xdg_open()
local node = tree.get_node_at_cursor() local node = lib.get_node_at_cursor()
-- TODO: this should open symlink targets -- TODO: this should open symlink targets
if not node or node.entries or node.link_to then return end if not node or node.entries or node.link_to then return end