remove old code

This commit is contained in:
kiyan42 2020-11-01 13:15:14 +01:00
parent c2403bc5cd
commit c7cfeb39bf
9 changed files with 0 additions and 1613 deletions

View File

@ -1,84 +0,0 @@
local api = vim.api
local config = require'lib.config'
local M = {}
local function get_color_from_hl(hl_name, fallback)
local id = vim.api.nvim_get_hl_id_by_name(hl_name)
if not id then return fallback end
local hl = vim.api.nvim_get_hl_by_id(id, true)
if not hl or not hl.foreground then return fallback end
return hl.foreground
end
local function get_colors()
return {
red = vim.g.terminal_color_1 or get_color_from_hl('Keyword', 'Red'),
green = vim.g.terminal_color_2 or get_color_from_hl('Character', 'Green'),
yellow = vim.g.terminal_color_3 or get_color_from_hl('PreProc', 'Yellow'),
blue = vim.g.terminal_color_4 or get_color_from_hl('Include', 'Blue'),
purple = vim.g.terminal_color_5 or get_color_from_hl('Define', 'Purple'),
cyan = vim.g.terminal_color_6 or get_color_from_hl('Conditional', 'Cyan'),
dark_red = vim.g.terminal_color_9 or get_color_from_hl('Keyword', 'DarkRed'),
orange = vim.g.terminal_color_11 or get_color_from_hl('Number', 'Orange'),
}
end
local function get_hl_groups()
local colors = get_colors()
return {
IndentMarker = { fg = '#8094b4' },
Symlink = { gui = 'bold', fg = colors.cyan },
FolderIcon = { fg = '#8094b4' },
RootFolder = { fg = colors.purple },
ExecFile = { gui = 'bold', fg = colors.green },
SpecialFile = { gui = 'bold,underline', fg = colors.yellow },
ImageFile = { gui = 'bold', fg = colors.purple },
GitDirty = { fg = colors.dark_red },
GitDeleted = { fg = colors.dark_red },
GitStaged = { fg = colors.green },
GitMerge = { fg = colors.orange },
GitRenamed = { fg = colors.purple },
GitNew = { fg = colors.yellow }
}
end
local function get_links()
return {
FolderName = 'Directory',
Normal = 'Normal',
EndOfBuffer = 'EndOfBuffer',
CursorLine = 'CursorLine',
VertSplit = 'VertSplit',
CursorColumn = 'CursorColumn',
FileDirty = 'LuaTreeGitDirty',
FileNew = 'LuaTreeGitNew',
FileRenamed = 'LuaTreeGitRenamed',
FileMerge = 'LuaTreeGitMerge',
FileStaged = 'LuaTreeGitStaged',
FileDeleted = 'LuaTreeGitDeleted',
}
end
function M.setup()
if config.get_icon_state().show_file_icon then
require'nvim-web-devicons'.setup()
end
local higlight_groups = get_hl_groups()
for k, d in pairs(higlight_groups) do
local gui = d.gui or 'NONE'
api.nvim_command('hi def LuaTree'..k..' gui='..gui..' guifg='..d.fg)
end
local links = get_links()
for k, d in pairs(links) do
api.nvim_command('hi def link LuaTree'..k..' '..d)
end
end
return M

View File

@ -1,92 +0,0 @@
local M = {}
function M.get_icon_state()
local show_icons = vim.g.lua_tree_show_icons or { git = 1, folders = 1, files = 1 }
local icons = {
default = "",
symlink = "",
git_icons = {
unstaged = "",
staged = "",
unmerged = "",
renamed = "",
untracked = "",
deleted = ""
},
folder_icons = {
default = "",
open = ""
}
}
local user_icons = vim.g.lua_tree_icons
if user_icons then
if user_icons.default then
icons.default = user_icons.default
icons.symlink = user_icons.default
end
if user_icons.symlink then
icons.symlink = user_icons.symlink
end
for key, val in pairs(user_icons.git or {}) do
if icons.git_icons[key] then
icons.git_icons[key] = val
end
end
for key, val in pairs(user_icons.folder or {}) do
if icons.folder_icons[key] then
icons.folder_icons[key] = val
end
end
end
return {
show_file_icon = show_icons.files == 1 and vim.g.nvim_web_devicons == 1,
show_folder_icon = show_icons.folders == 1,
show_git_icon = show_icons.git == 1,
icons = icons
}
end
function M.get_bindings()
local keybindings = vim.g.lua_tree_bindings or {}
return {
edit = keybindings.edit or {'<CR>', 'o'},
edit_vsplit = keybindings.edit_vsplit or '<C-v>',
edit_split = keybindings.edit_split or '<C-x>',
edit_tab = keybindings.edit_tab or '<C-t>',
preview = keybindings.preview or '<Tab>',
toggle_ignored = keybindings.toggle_ignored or 'I',
toggle_dotfiles = keybindings.toggle_dotfiles or 'H',
refresh = keybindings.refresh or 'R',
cd = keybindings.cd or '<C-]>',
create = keybindings.create or 'a',
remove = keybindings.remove or 'd',
rename = keybindings.rename or 'r',
cut = keybindings.cut or 'x',
copy = keybindings.copy or 'c',
paste = keybindings.paste or 'p',
prev_git_item = keybindings.prev_git_item or '[c',
next_git_item = keybindings.next_git_item or ']c',
}
end
function M.window_options()
local opts = {}
opts.winhl = 'EndOfBuffer:LuaTreeEndOfBuffer,Normal:LuaTreeNormal,CursorLine:LuaTreeCursorLine,VertSplit:LuaTreeVertSplit'
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

View File

@ -1,295 +0,0 @@
local api = vim.api
local luv = vim.loop
local open_mode = luv.constants.O_CREAT + luv.constants.O_WRONLY + luv.constants.O_TRUNC
local M = {}
local clipboard = {
move = {},
copy = {}
}
local function clear_prompt()
vim.api.nvim_command('normal :esc<CR>')
end
local function refresh_tree()
vim.api.nvim_command(":LuaTreeRefresh")
end
local function create_file(file)
luv.fs_open(file, "w", open_mode, vim.schedule_wrap(function(err, fd)
if err then
api.nvim_err_writeln('Could not create file '..file)
else
-- FIXME: i don't know why but libuv keeps creating file with executable permissions
-- this is why we need to chmod to default file permissions
luv.fs_chmod(file, 420)
luv.fs_close(fd)
api.nvim_out_write('File '..file..' was properly created\n')
refresh_tree()
end
end))
end
local function get_num_entries(iter)
local i = 0
for _ in iter do
i = i + 1
end
return i
end
function M.create(node)
if node.name == '..' then return end
local add_into
if node.entries ~= nil then
add_into = node.absolute_path..'/'
else
add_into = node.absolute_path:sub(0, -(#node.name + 1))
end
local ans = vim.fn.input('Create file '..add_into)
clear_prompt()
if not ans or #ans == 0 then return end
if not ans:match('/') then
return create_file(add_into..ans)
end
-- create a foler for each element until / and create a file when element is not ending with /
-- if element is ending with / and it's the last element, we need to manually refresh
local relpath = ''
local idx = 0
local num_entries = get_num_entries(ans:gmatch('[^/]+/?'))
for path in ans:gmatch('[^/]+/?') do
idx = idx + 1
relpath = relpath..path
if relpath:match('.*/$') then
local success = luv.fs_mkdir(add_into..relpath, 493)
if not success then
api.nvim_err_writeln('Could not create folder '..add_into..relpath)
return
end
if idx == num_entries then
api.nvim_out_write('Folder '..add_into..relpath..' was properly created\n')
refresh_tree()
end
else
create_file(add_into..relpath)
end
end
end
local function clear_buffer(absolute_path)
for _, buf in pairs(api.nvim_list_bufs()) do
if api.nvim_buf_get_name(buf) == absolute_path then
api.nvim_command(':bd! '..buf)
end
end
end
local function remove_dir(cwd)
local handle = luv.fs_scandir(cwd)
if type(handle) == 'string' then
return api.nvim_err_writeln(handle)
end
while true do
local name, t = luv.fs_scandir_next(handle)
if not name then break end
local new_cwd = cwd..'/'..name
if t == 'directory' then
local success = remove_dir(new_cwd)
if not success then return false end
else
local success = luv.fs_unlink(new_cwd)
if not success then return false end
clear_buffer(new_cwd)
end
end
return luv.fs_rmdir(cwd)
end
local function do_copy(source, destination)
local source_stats = luv.fs_stat(source)
if source_stats and source_stats.type == 'file' then
return luv.fs_copyfile(source, destination)
end
local handle = luv.fs_scandir(source)
if type(handle) == 'string' then
return false, handle
end
luv.fs_mkdir(destination, source_stats.mode)
while true do
local name, _ = luv.fs_scandir_next(handle)
if not name then break end
local new_name = source..'/'..name
local new_destination = destination..'/'..name
local success, msg = do_copy(new_name, new_destination)
if not success then return success, msg end
end
return true
end
local function do_single_paste(source, dest, action_type, action_fn)
local dest_stats = luv.fs_stat(dest)
local should_process = true
local should_rename = false
if dest_stats then
ans = vim.fn.input(dest..' already exists, overwrite ? y/n/r(ename): ')
clear_prompt()
should_process = ans:match('^y')
should_rename = ans:match('^r')
end
if should_rename then
new_dest = vim.fn.input('New name: ', dest)
return do_single_paste(source, new_dest, action_type, action_fn)
end
if should_process then
local success, errmsg = action_fn(source, dest)
if not success then
api.nvim_err_writeln('Could not '..action_type..' '..source..' - '..errmsg)
end
end
end
local function do_paste(node, action_type, action_fn)
if node.name == '..' then return end
local clip = clipboard[action_type]
if #clip == 0 then return end
local destination = node.absolute_path
local stats = luv.fs_stat(destination)
local is_dir = stats and stats.type == 'directory'
if not is_dir then
destination = vim.fn.fnamemodify(destination, ':p:h')
elseif not node.open then
destination = vim.fn.fnamemodify(destination, ':p:h:h')
end
local msg = #clip..' entries'
if #clip == 1 then
msg = clip[1].absolute_path
end
local ans = vim.fn.input(action_type..' '..msg..' to '..destination..'? y/n: ')
clear_prompt()
if not ans:match('^y') then
return api.nvim_out_write('Canceled.\n')
end
for _, entry in ipairs(clip) do
local dest = destination..'/'..entry.name
do_single_paste(entry.absolute_path, dest, action_type, action_fn)
end
clipboard[action_type] = {}
return refresh_tree()
end
local function add_to_clipboard(node, clip)
if node.name == '..' then return end
for idx, entry in ipairs(clip) do
if entry.absolute_path == node.absolute_path then
table.remove(clip, idx)
return api.nvim_out_write(node.absolute_path..' removed to clipboard.\n')
end
end
table.insert(clip, node)
api.nvim_out_write(node.absolute_path..' added to clipboard.\n')
end
function M.remove(node)
if node.name == '..' then return end
local ans = vim.fn.input("Remove " ..node.name.. " ? y/n: ")
clear_prompt()
if ans:match('^y') then
if node.entries ~= nil then
local success = remove_dir(node.absolute_path)
if not success then
return api.nvim_err_writeln('Could not remove '..node.name)
end
api.nvim_out_write(node.name..' has been removed\n')
else
local success = luv.fs_unlink(node.absolute_path)
if not success then
return api.nvim_err_writeln('Could not remove '..node.name)
end
api.nvim_out_write(node.name..' has been removed\n')
clear_buffer(node.absolute_path)
end
refresh_tree()
end
end
function M.rename(node)
if node.name == '..' then return end
local new_name = vim.fn.input("Rename " ..node.name.. " to ", node.absolute_path)
clear_prompt()
if not new_name or #new_name == 0 then return end
local success = luv.fs_rename(node.absolute_path, new_name) --, vim.schedule_wrap(rename_callback(node, ans)))
if not success then
return api.nvim_err_writeln('Could not rename '..node.absolute_path..' to '..new_name)
end
api.nvim_out_write(node.absolute_path..''..new_name..'\n')
for _, buf in pairs(api.nvim_list_bufs()) do
if api.nvim_buf_get_name(buf) == node.absolute_path then
api.nvim_buf_set_name(buf, new_name)
end
end
refresh_tree()
end
function M.copy(node)
add_to_clipboard(node, clipboard.copy)
end
function M.cut(node)
add_to_clipboard(node, clipboard.move)
end
function M.paste(node)
if clipboard.move[1] ~= nil then
return do_paste(node, 'move', luv.fs_rename)
end
return do_paste(node, 'copy', do_copy)
end
function M.print_clipboard()
local content = {}
if #clipboard.move > 0 then
table.insert(content, 'Cut')
for _, item in pairs(clipboard.move) do
table.insert(content, ' * '..item.absolute_path)
end
end
if #clipboard.copy > 0 then
table.insert(content, 'Copy')
for _, item in pairs(clipboard.copy) do
table.insert(content, ' * '..item.absolute_path)
end
end
return api.nvim_out_write(table.concat(content, '\n')..'\n')
end
return M

View File

@ -1,92 +0,0 @@
local utils = require'lib.utils'
local M = {}
local roots = {}
local not_git = 'not a git repo'
local function update_root_status(root)
local status = vim.fn.systemlist('cd "'..root..'" && git status --porcelain=v1 -u')
roots[root] = {}
for _, v in pairs(status) do
local head = v:sub(0, 2)
local body = v:sub(4, -1)
if body:match('%->') ~= nil then
body = body:gsub('^.* %-> ', '')
end
roots[root][body] = head
end
end
function M.reload_roots()
for root, status in pairs(roots) do
if status ~= not_git then
update_root_status(root)
end
end
end
local function get_git_root(path)
if roots[path] then
return path, roots[path]
end
for name, status in pairs(roots) do
if status ~= not_git then
if path:match(utils.path_to_matching_str(name)) then
return name, status
end
end
end
end
local function create_root(cwd)
local git_root = vim.fn.system('cd "'..cwd..'" && git rev-parse --show-toplevel')
if not git_root or #git_root == 0 or git_root:match('fatal') then
roots[cwd] = not_git
return false
end
update_root_status(git_root:sub(0, -2))
return true
end
function M.update_status(entries, cwd)
local git_root, git_status = get_git_root(cwd)
if not git_root then
if not create_root(cwd) then
return
end
git_root, git_status = get_git_root(cwd)
elseif git_status == not_git then
return
end
local matching_cwd = utils.path_to_matching_str(git_root..'/')
for _, node in pairs(entries) do
local relpath = node.absolute_path:gsub(matching_cwd, '')
if node.entries ~= nil then
relpath = relpath..'/'
node.git_status = nil
end
local status = git_status[relpath]
if status then
node.git_status = status
elseif node.entries ~= nil then
local matcher = '^'..utils.path_to_matching_str(relpath)
for key, entry_status in pairs(git_status) do
if key:match(matcher) then
node.git_status = entry_status
break
end
end
else
node.git_status = nil
end
end
end
return M

View File

@ -1,329 +0,0 @@
local api = vim.api
local luv = vim.loop
local renderer = require'lib.renderer'
local config = require'lib.config'
local git = require'lib.git'
local pops = require'lib.populate'
local populate = pops.populate
local refresh_entries = pops.refresh_entries
local window_opts = config.window_options()
local M = {}
M.Tree = {
entries = {},
buf_name = 'LuaTree',
cwd = nil,
win_width = vim.g.lua_tree_width or 30,
win_width_allow_resize = vim.g.lua_tree_width_allow_resize,
loaded = false,
bufnr = nil,
winnr = function()
for _, i in ipairs(api.nvim_list_wins()) do
if api.nvim_buf_get_name(api.nvim_win_get_buf(i)):match('.*/'..M.Tree.buf_name..'$') then
return i
end
end
end,
options = {
'noswapfile',
'norelativenumber',
'nonumber',
'nolist',
'winfixwidth',
'winfixheight',
'nofoldenable',
'nospell',
'foldmethod=manual',
'foldcolumn=0'
}
}
function M.init(with_open, with_render)
M.Tree.cwd = luv.cwd()
populate(M.Tree.entries, M.Tree.cwd, M.Tree)
local stat = luv.fs_stat(M.Tree.cwd)
M.Tree.last_modified = stat.mtime.sec
if with_open then
M.open()
end
if with_render then
renderer.draw(M.Tree, true)
M.Tree.loaded = true
end
end
local function get_node_at_line(line)
local index = 2
local function iter(entries)
for _, node in ipairs(entries) do
if index == line then
return node
end
index = index + 1
if node.open == true then
local child = iter(node.entries)
if child ~= nil then return child end
end
end
end
return iter
end
function M.get_node_at_cursor()
local cursor = api.nvim_win_get_cursor(M.Tree.winnr())
local line = cursor[1]
if line == 1 and M.Tree.cwd ~= "/" then
return { name = ".." }
end
if M.Tree.cwd == "/" then
line = line + 1
end
return get_node_at_line(line)(M.Tree.entries)
end
function M.unroll_dir(node)
node.open = not node.open
if #node.entries > 0 then
renderer.draw(M.Tree, true)
else
populate(node.entries, node.absolute_path)
renderer.draw(M.Tree, true)
end
end
local function refresh_git(node)
git.update_status(node.entries, node.absolute_path or node.cwd)
for _, entry in pairs(node.entries) do
if entry.entries ~= nil then
refresh_git(entry)
end
end
end
-- TODO update only entries where directory has changed
local function refresh_nodes(node)
refresh_entries(node.entries, node.absolute_path or node.cwd)
for _, entry in ipairs(node.entries) do
if entry.entries and entry.open then
refresh_nodes(entry)
end
end
end
function M.refresh_tree()
-- local stat = luv.fs_stat(M.Tree.cwd)
-- if stat.mtime.sec ~= M.Tree.last_modified then
refresh_nodes(M.Tree)
-- end
if config.get_icon_state().show_git_icon or vim.g.lua_tree_git_hl then
git.reload_roots()
refresh_git(M.Tree)
end
if M.win_open() then
renderer.draw(M.Tree, true)
else
M.Tree.loaded = false
end
end
function M.set_index_and_redraw(fname)
local i
if M.Tree.cwd == '/' then
i = 0
else
i = 1
end
local reload = false
local function iter(entries)
for _, entry in ipairs(entries) do
i = i + 1
if entry.absolute_path == fname then
return i
end
if fname:match(entry.match_path..'/') ~= nil then
if #entry.entries == 0 then
reload = true
populate(entry.entries, entry.absolute_path)
end
if entry.open == false then
reload = true
entry.open = true
end
if iter(entry.entries) ~= nil then
return i
end
elseif entry.open == true then
iter(entry.entries)
end
end
end
local index = iter(M.Tree.entries)
if not M.win_open() then
M.Tree.loaded = false
return
end
renderer.draw(M.Tree, reload)
if index then
api.nvim_win_set_cursor(M.Tree.winnr(), {index, 0})
end
end
local function check_and_open_split()
if #api.nvim_list_wins() == 1 then
api.nvim_command("vnew")
end
end
function M.open_file(mode, filename)
api.nvim_command('noautocmd wincmd '..window_opts.open_command)
if mode == 'preview' then
check_and_open_split()
api.nvim_command(string.format("edit %s", filename))
api.nvim_command('noautocmd wincmd '..window_opts.preview_command)
else
if mode == 'edit' then
check_and_open_split()
end
api.nvim_command(string.format("%s %s", mode, filename))
end
if not M.Tree.win_width_allow_resize then
local cur_win = api.nvim_get_current_win()
M.win_focus()
api.nvim_command('vertical resize '..M.Tree.win_width)
M.win_focus(cur_win)
end
if vim.g.lua_tree_quit_on_open then
M.close()
end
end
function M.change_dir(foldername)
api.nvim_command('cd '..foldername)
M.Tree.entries = {}
M.init(false, M.Tree.bufnr ~= nil)
end
local function set_mapping(buf, key, fn)
api.nvim_buf_set_keymap(buf, 'n', key, ':lua require"tree".'..fn..'<cr>', {
nowait = true, noremap = true, silent = true
})
end
local function set_mappings()
if vim.g.lua_tree_disable_keybindings == 1 then
return
end
local buf = M.Tree.bufnr
local bindings = config.get_bindings()
local mappings = {
['<2-LeftMouse>'] = 'on_keypress("edit")';
['<2-RightMouse>'] = 'on_keypress("cd")';
[bindings.cd] = 'on_keypress("cd")';
[bindings.edit] = 'on_keypress("edit")';
[bindings.edit_vsplit] = 'on_keypress("vsplit")';
[bindings.edit_split] = 'on_keypress("split")';
[bindings.edit_tab] = 'on_keypress("tabnew")';
[bindings.toggle_ignored] = 'on_keypress("toggle_ignored")';
[bindings.toggle_dotfiles] = 'on_keypress("toggle_dotfiles")';
[bindings.refresh] = 'on_keypress("refresh")';
[bindings.create] = 'on_keypress("create")';
[bindings.remove] = 'on_keypress("remove")';
[bindings.rename] = 'on_keypress("rename")';
[bindings.preview] = 'on_keypress("preview")';
[bindings.cut] = 'on_keypress("cut")';
[bindings.copy] = 'on_keypress("copy")';
[bindings.paste] = 'on_keypress("paste")';
[bindings.prev_git_item] = 'on_keypress("prev_git_item")';
[bindings.next_git_item] = 'on_keypress("next_git_item")';
gx = "xdg_open()";
}
for k,v in pairs(mappings) do
if type(k) == 'table' then
for _, key in pairs(k) do
set_mapping(buf, key, v)
end
else
set_mapping(buf, k, v)
end
end
end
local function create_buf()
local options = {
bufhidden = 'wipe';
buftype = 'nofile';
modifiable = false;
}
M.Tree.bufnr = api.nvim_create_buf(false, true)
api.nvim_buf_set_name(M.Tree.bufnr, M.Tree.buf_name)
for opt, val in pairs(options) do
api.nvim_buf_set_option(M.Tree.bufnr, opt, val)
end
set_mappings()
end
local function create_win()
api.nvim_command("vsplit")
api.nvim_command("wincmd "..window_opts.side)
api.nvim_command("vertical resize "..M.Tree.win_width)
end
function M.close()
if #api.nvim_list_wins() == 1 then
return vim.cmd ':q!'
end
api.nvim_win_close(M.Tree.winnr(), true)
M.Tree.bufnr = nil
end
function M.open()
create_buf()
create_win()
api.nvim_win_set_buf(M.Tree.winnr(), M.Tree.bufnr)
for _, opt in pairs(M.Tree.options) do
api.nvim_command('setlocal '..opt)
end
renderer.draw(M.Tree, not M.Tree.loaded)
M.Tree.loaded = true
api.nvim_buf_set_option(M.Tree.bufnr, 'filetype', M.Tree.buf_name)
api.nvim_command('setlocal '..window_opts.split_command)
end
function M.win_open()
return M.Tree.winnr() ~= nil
end
function M.win_focus(winnr)
local wnr = winnr or M.Tree.winnr()
api.nvim_set_current_win(wnr)
end
function M.toggle_ignored()
pops.show_ignored = not pops.show_ignored
return M.refresh_tree()
end
function M.toggle_dotfiles()
pops.show_dotfiles = not pops.show_dotfiles
return M.refresh_tree()
end
return M

View File

@ -1,209 +0,0 @@
local config = require'lib.config'
local git = require'lib.git'
local icon_config = config.get_icon_state()
local api = vim.api
local luv = vim.loop
local M = {
show_ignored = false,
show_dotfiles = vim.g.lua_tree_hide_dotfiles ~= 1,
}
local path_to_matching_str = require'lib.utils'.path_to_matching_str
local function dir_new(cwd, name)
local absolute_path = cwd..'/'..name
local stat = luv.fs_stat(absolute_path)
return {
name = name,
absolute_path = absolute_path,
-- TODO: last modified could also involve atime and ctime
last_modified = stat.mtime.sec,
match_name = path_to_matching_str(name),
match_path = path_to_matching_str(absolute_path),
open = false,
entries = {}
}
end
local function file_new(cwd, name)
local absolute_path = cwd..'/'..name
local is_exec = luv.fs_access(absolute_path, 'X')
return {
name = name,
absolute_path = absolute_path,
executable = is_exec,
extension = vim.fn.fnamemodify(name, ':e') or "",
match_name = path_to_matching_str(name),
match_path = path_to_matching_str(absolute_path),
}
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 absolute_path = cwd..'/'..name
local link_to = luv.fs_realpath(absolute_path)
return {
name = name,
absolute_path = absolute_path,
link_to = link_to,
match_name = path_to_matching_str(name),
match_path = path_to_matching_str(absolute_path),
}
end
local function gen_ignore_check()
local ignore_list = {}
if vim.g.lua_tree_ignore and #vim.g.lua_tree_ignore > 0 then
for _, entry in pairs(vim.g.lua_tree_ignore) do
ignore_list[entry] = true
end
end
return function(path)
local ignore_path = not M.show_ignored and ignore_list[path] == true
local ignore_dotfiles = not M.show_dotfiles and path:sub(1, 1) == '.'
return ignore_path or ignore_dotfiles
end
end
local should_ignore = gen_ignore_check()
function M.refresh_entries(entries, cwd)
local handle = luv.fs_scandir(cwd)
if type(handle) == 'string' then
api.nvim_err_writeln(handle)
return
end
local named_entries = {}
local cached_entries = {}
local entries_idx = {}
for i, node in ipairs(entries) do
cached_entries[i] = node.name
entries_idx[node.name] = i
named_entries[node.name] = node
end
local dirs = {}
local links = {}
local files = {}
local new_entries = {}
while true do
local name, t = luv.fs_scandir_next(handle)
if not name then break end
if not should_ignore(name) then
if t == 'directory' then
table.insert(dirs, name)
new_entries[name] = true
elseif t == 'file' then
table.insert(files, name)
new_entries[name] = true
elseif t == 'link' then
table.insert(links, name)
new_entries[name] = true
end
end
end
local idx = 1
for _, name in ipairs(cached_entries) do
if not new_entries[name] then
table.remove(entries, idx, idx + 1)
else
idx = idx + 1
end
end
local all = {
{ entries = dirs, fn = dir_new, check = function(_, abs) return luv.fs_access(abs, 'R') end },
{ entries = links, fn = link_new, check = function(name) return name ~= nil end },
{ entries = files, fn = file_new, check = function() return true end }
}
local prev = nil
local change_prev
for _, e in ipairs(all) do
for _, name in ipairs(e.entries) do
change_prev = true
if not named_entries[name] then
local n = e.fn(cwd, name)
if e.check(n.link_to, n.absolute_path) then
idx = 1
if prev then
idx = entries_idx[prev] + 1
end
table.insert(entries, idx, n)
entries_idx[name] = idx
cached_entries[idx] = name
else
change_prev = false
end
end
if change_prev then prev = name end
end
end
end
function M.populate(entries, cwd)
local handle = luv.fs_scandir(cwd)
if type(handle) == 'string' then
api.nvim_err_writeln(handle)
return
end
local dirs = {}
local links = {}
local files = {}
while true do
local name, t = luv.fs_scandir_next(handle)
if not name then break end
if not should_ignore(name) then
if t == 'directory' then
table.insert(dirs, name)
elseif t == 'file' then
table.insert(files, name)
elseif t == 'link' then
table.insert(links, name)
end
end
end
-- Create Nodes --
for _, dirname in ipairs(dirs) do
local dir = dir_new(cwd, dirname)
if luv.fs_access(dir.absolute_path, 'R') then
table.insert(entries, dir)
end
end
for _, linkname in ipairs(links) do
local link = link_new(cwd, linkname)
if link.link_to ~= nil then
table.insert(entries, link)
end
end
for _, filename in ipairs(files) do
local file = file_new(cwd, filename)
table.insert(entries, file)
end
if (not icon_config.show_git_icon) and vim.g.lua_tree_git_hl ~= 1 then
return
end
git.update_status(entries, cwd)
end
return M

View File

@ -1,297 +0,0 @@
local colors = require'lib.colors'
local config = require'lib.config'
local utils = require'lib.utils'
local api = vim.api
local lines = {}
local hl = {}
local index = 0
local namespace_id = api.nvim_create_namespace('LuaTreeHighlights')
local icon_state = config.get_icon_state()
local get_folder_icon = function() return "" end
local set_folder_hl = function(line, depth, git_icon_len, _, hl_group)
table.insert(hl, {hl_group, line, depth+git_icon_len, -1})
end
if icon_state.show_folder_icon then
get_folder_icon = function(open)
if open then
return icon_state.icons.folder_icons.open .. " "
else
return icon_state.icons.folder_icons.default .. " "
end
end
set_folder_hl = function(line, depth, icon_len, name_len, hl_group)
table.insert(hl, {hl_group, line, depth+icon_len, depth+icon_len+name_len})
table.insert(hl, {'LuaTreeFolderIcon', line, depth, depth+icon_len})
end
end
local get_file_icon = function() return icon_state.icons.default end
if icon_state.show_file_icon then
local web_devicons = require'nvim-web-devicons'
get_file_icon = function(fname, extension, line, depth)
local icon, hl_group = web_devicons.get_icon(fname, extension)
if icon then
if hl_group then
table.insert(hl, { hl_group, line, depth, depth + #icon })
end
return icon.." "
else
return #icon_state.icons.default > 0 and icon_state.icons.default.." " or ""
end
end
end
local get_symlink_icon = function() return icon_state.icons.symlink end
if icon_state.show_file_icon then
get_symlink_icon = function()
return #icon_state.icons.symlink > 0 and icon_state.icons.symlink.." " or ""
end
end
local get_special_icon = function() return icon_state.icons.default end
if icon_state.show_file_icon then
get_special_icon = function()
return #icon_state.icons.default > 0 and icon_state.icons.default.." " or ""
end
end
local get_git_icons = function() return "" end
local get_git_hl = function() return end
if vim.g.lua_tree_git_hl == 1 then
local git_hl = {
["M "] = { { hl = "LuaTreeFileStaged" } },
[" M"] = { { hl = "LuaTreeFileDirty" } },
["MM"] = {
{ hl = "LuaTreeFileStaged" },
{ hl = "LuaTreeFileDirty" }
},
["A "] = {
{ hl = "LuaTreeFileStaged" },
{ hl = "LuaTreeFileNew" }
},
["AD"] = {
{ hl = "LuaTreeFileStaged" },
{ hl = "LuaTreeFileDeleted" }
},
["AM"] = {
{ hl = "LuaTreeFileStaged" },
{ hl = "LuaTreeFileNew" },
{ hl = "LuaTreeFileDirty" }
},
["??"] = { { hl = "LuaTreeFileNew" } },
["R "] = { { hl = "LuaTreeFileRenamed" } },
["UU"] = { { hl = "LuaTreeFileMerge" } },
[" D"] = { { hl = "LuaTreeFileDeleted" } },
["D "] = {
{ hl = "LuaTreeFileDeleted" },
{ hl = "LuaTreeFileStaged" }
},
dirty = { { hl = "LuaTreeFileDirty" } },
}
get_git_hl = function(node)
local git_status = node.git_status
if not git_status then return end
local icons = git_hl[git_status]
if icons == nil then
utils.echo_warning('Unrecognized git state "'..git_status..'". Please open up an issue on https://github.com/kyazdani42/nvim-tree.lua/issues with this message.')
icons = git_hl.dirty
end
-- TODO: how would we determine hl color when multiple git status are active ?
return icons[1].hl
-- return icons[#icons].hl
end
end
if icon_state.show_git_icon then
local git_icon_state = {
["M "] = { { icon = icon_state.icons.git_icons.staged, hl = "LuaTreeGitStaged" } },
[" M"] = { { icon = icon_state.icons.git_icons.unstaged, hl = "LuaTreeGitDirty" } },
["MM"] = {
{ icon = icon_state.icons.git_icons.staged, hl = "LuaTreeGitStaged" },
{ icon = icon_state.icons.git_icons.unstaged, hl = "LuaTreeGitDirty" }
},
["A "] = {
{ icon = icon_state.icons.git_icons.staged, hl = "LuaTreeGitStaged" },
{ icon = icon_state.icons.git_icons.untracked, hl = "LuaTreeGitNew" }
},
["AM"] = {
{ icon = icon_state.icons.git_icons.staged, hl = "LuaTreeGitStaged" },
{ icon = icon_state.icons.git_icons.untracked, hl = "LuaTreeGitNew" },
{ icon = icon_state.icons.git_icons.unstaged, hl = "LuaTreeGitDirty" }
},
["??"] = { { icon = icon_state.icons.git_icons.untracked, hl = "LuaTreeGitNew" } },
["R "] = { { icon = icon_state.icons.git_icons.renamed, hl = "LuaTreeGitRenamed" } },
["UU"] = { { icon = icon_state.icons.git_icons.unmerged, hl = "LuaTreeGitMerge" } },
[" D"] = { { icon = icon_state.icons.git_icons.deleted, hl = "LuaTreeGitDeleted" } },
dirty = { { icon = icon_state.icons.git_icons.unstaged, hl = "LuaTreeGitDirty" } },
}
get_git_icons = function(node, line, depth, icon_len)
local git_status = node.git_status
if not git_status then return "" end
local icon = ""
local icons = git_icon_state[git_status]
if not icons then
if vim.g.lua_tree_git_hl ~= 1 then
utils.echo_warning('Unrecognized git state "'..git_status..'". Please open up an issue on https://github.com/kyazdani42/nvim-tree.lua/issues with this message.')
end
icons = git_icon_state.dirty
end
for _, v in ipairs(icons) do
table.insert(hl, { v.hl, line, depth+icon_len+#icon, depth+icon_len+#icon+#v.icon })
icon = icon..v.icon.." "
end
return icon
end
end
local get_padding = function(depth)
return string.rep(' ', depth)
end
if vim.g.lua_tree_indent_markers == 1 then
get_padding = function(depth, idx, tree, _, markers)
local padding = ""
if depth ~= 0 then
local rdepth = depth/2
markers[rdepth] = idx ~= #tree.entries
for i=1,rdepth do
if idx == #tree.entries and i == rdepth then
padding = padding..''
elseif markers[i] then
padding = padding..''
else
padding = padding..' '
end
end
end
return padding
end
end
local picture = {
jpg = true,
jpeg = true,
png = true,
gif = true,
}
local special = {
["Cargo.toml"] = true,
Makefile = true,
["README.md"] = true,
["readme.md"] = true,
}
local root_folder_modifier = vim.g.lua_tree_root_folder_modifier or ':~'
local function update_draw_data(tree, depth, markers)
if tree.cwd and tree.cwd ~= '/' then
local root_name = vim.fn.fnamemodify(tree.cwd, root_folder_modifier):gsub('/$', '').."/.."
table.insert(lines, root_name)
table.insert(hl, {'LuaTreeRootFolder', index, 0, string.len(root_name)})
index = 1
end
for idx, node in ipairs(tree.entries) do
local padding = get_padding(depth, idx, tree, node, markers)
local offset = string.len(padding)
if depth > 0 then
table.insert(hl, { 'LuaTreeIndentMarker', index, 0, offset })
end
local git_hl = get_git_hl(node)
if node.entries then
local icon = get_folder_icon(node.open)
local git_icon = get_git_icons(node, index, offset, #icon+1) or ""
-- INFO: this is mandatory in order to keep gui attributes (bold/italics)
set_folder_hl(index, offset, #icon, #node.name+#git_icon, 'LuaTreeFolderName')
if git_hl then
set_folder_hl(index, offset, #icon, #node.name+#git_icon, git_hl)
end
index = index + 1
if node.open then
table.insert(lines, padding..icon..git_icon..node.name)
update_draw_data(node, depth + 2, markers)
else
table.insert(lines, padding..icon..git_icon..node.name)
end
elseif node.link_to then
local icon = get_symlink_icon()
local link_hl = git_hl or 'LuaTreeSymlink'
table.insert(hl, { link_hl, index, offset, -1 })
table.insert(lines, padding..icon..node.name..""..node.link_to)
index = index + 1
else
local icon
local git_icons
if special[node.name] then
icon = get_special_icon()
git_icons = get_git_icons(node, index, offset, 0)
table.insert(hl, {'LuaTreeSpecialFile', index, offset+#git_icons, -1})
else
icon = get_file_icon(node.name, node.extension, index, offset)
git_icons = get_git_icons(node, index, offset, #icon)
end
table.insert(lines, padding..icon..git_icons..node.name)
if node.executable then
table.insert(hl, {'LuaTreeExecFile', index, offset+#icon+#git_icons, -1 })
elseif picture[node.extension] then
table.insert(hl, {'LuaTreeImageFile', index, offset+#icon+#git_icons, -1 })
end
if git_hl then
table.insert(hl, {git_hl, index, offset+#icon+#git_icons, -1 })
end
index = index + 1
end
end
end
local M = {}
function M.draw(tree, reload)
if not tree.bufnr then return end
api.nvim_buf_set_option(tree.bufnr, 'modifiable', true)
local cursor = api.nvim_win_get_cursor(tree.winnr)
if reload then
index = 0
lines = {}
hl = {}
update_draw_data(tree, 0, {})
end
api.nvim_buf_set_lines(tree.bufnr, 0, -1, false, lines)
M.render_hl(tree.bufnr)
if #lines >= cursor[1] then
api.nvim_win_set_cursor(tree.winnr, cursor)
end
api.nvim_buf_set_option(tree.bufnr, 'modifiable', false)
end
function M.render_hl(bufnr)
if not bufnr then return end
api.nvim_buf_clear_namespace(bufnr, namespace_id, 0, -1)
for _, data in ipairs(hl) do
api.nvim_buf_add_highlight(bufnr, namespace_id, data[1], data[2], data[3], data[4])
end
end
return M

View File

@ -1,14 +0,0 @@
local M = {}
local api = vim.api
function M.path_to_matching_str(path)
return path:gsub('(%-)', '(%%-)'):gsub('(%.)', '(%%.)'):gsub('(%_)', '(%%_)')
end
function M.echo_warning(msg)
api.nvim_command('echohl WarningMsg')
api.nvim_command("echom '[LuaTree] "..msg:gsub("'", "''").."'")
api.nvim_command('echohl None')
end
return M

View File

@ -1,201 +0,0 @@
local luv = vim.loop
local lib = require'lib.lib'
local config = require'lib.config'
local colors = require'lib.colors'
local renderer = require'lib.renderer'
local fs = require'lib.fs'
local utils = require'lib.utils'
local api = vim.api
local M = {}
function M.toggle()
if lib.win_open() then
lib.close()
else
if vim.g.lua_tree_follow == 1 then
M.find_file(true)
else
lib.open()
end
end
end
function M.close()
if lib.win_open() then
lib.close()
return true
end
end
function M.open()
if not lib.win_open() then
lib.open()
end
end
local winopts = config.window_options()
function M.tab_change()
-- we need defer_fn to make sure we close/open after we enter the tab
vim.defer_fn(function()
if M.close() then
M.open()
api.nvim_command('wincmd '..winopts.open_command)
end
end, 1)
end
local function gen_go_to(mode)
local icon_state = config.get_icon_state()
local flags = mode == 'prev_git_item' and 'b' or ''
local icons = table.concat(vim.tbl_values(icon_state.icons.git_icons), '\\|')
return function()
return icon_state.show_git_icon and vim.fn.search(icons, flags)
end
end
local keypress_funcs = {
create = fs.create,
remove = fs.remove,
rename = fs.rename,
copy = fs.copy,
cut = fs.cut,
paste = fs.paste,
toggle_ignored = lib.toggle_ignored,
toggle_dotfiles = lib.toggle_dotfiles,
refresh = lib.refresh_tree,
prev_git_item = gen_go_to('prev_git_item'),
next_git_item = gen_go_to('next_git_item'),
preview = function(node)
if node.entries ~= nil or node.name == '..' then return end
return lib.open_file('preview', node.absolute_path)
end,
}
function M.on_keypress(mode)
local node = lib.get_node_at_cursor()
if not node then return end
if keypress_funcs[mode] then
return keypress_funcs[mode](node)
end
if node.name == ".." then
return lib.change_dir("..")
elseif mode == "cd" and node.entries ~= nil then
return lib.change_dir(node.absolute_path)
elseif mode == "cd" then
return
end
if node.link_to then
local stat = luv.fs_stat(node.link_to)
-- TODO: potentially CD here
if stat.type == 'directory' then return end
lib.open_file(mode, node.link_to)
elseif node.entries ~= nil then
lib.unroll_dir(node)
else
lib.open_file(mode, node.absolute_path)
end
end
function M.refresh()
lib.refresh_tree()
end
function M.print_clipboard()
fs.print_clipboard()
end
function M.on_enter()
local bufnr = api.nvim_get_current_buf()
local bufname = api.nvim_buf_get_name(bufnr)
local stats = luv.fs_stat(bufname)
local is_dir = stats and stats.type == 'directory'
if is_dir then
api.nvim_command('cd '..bufname)
end
local should_open = vim.g.lua_tree_auto_open == 1 and (bufname == '' or is_dir)
colors.setup()
lib.init(should_open, should_open)
end
local function is_file_readable(fname)
local stat = luv.fs_stat(fname)
if not stat or not stat.type == 'file' or not luv.fs_access(fname, 'R') then return false end
return true
end
function M.find_file(with_open)
local bufname = vim.fn.bufname()
local filepath = vim.fn.fnamemodify(bufname, ':p')
if with_open then
M.open()
lib.win_focus()
end
if not is_file_readable(filepath) then return end
lib.set_index_and_redraw(filepath)
end
function M.on_leave()
vim.defer_fn(function()
if #api.nvim_list_wins() == 1 and lib.win_open() then
api.nvim_command(':qa!')
end
end, 50)
end
local function update_root_dir()
local bufname = api.nvim_buf_get_name(api.nvim_get_current_buf())
if not is_file_readable(bufname) or not lib.Tree.cwd then return end
-- this logic is a hack
-- 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
if bufname:match(utils.path_to_matching_str(lib.Tree.cwd)) then
return
end
local new_cwd = luv.cwd()
if lib.Tree.cwd == new_cwd then return end
lib.change_dir(new_cwd)
end
function M.buf_enter()
update_root_dir()
if vim.g.lua_tree_follow == 1 then
M.find_file(false)
end
end
function M.reset_highlight()
colors.setup()
renderer.render_hl(lib.Tree.bufnr)
end
function M.xdg_open()
local node = lib.get_node_at_cursor()
-- TODO: this should open symlink targets
if not node or node.entries or node.link_to then return end
local cmd
if vim.fn.has('unix') == 1 then
cmd = 'xdg-open'
else
cmd = 'open'
end
vim.loop.spawn(cmd, {args={node.absolute_path}}, vim.schedule_wrap(function(code)
if code ~= 0 then
api.nvim_err_writeln("Could not open "..node.absolute_path)
end
end))
end
M.on_enter()
return M