Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add file following support to the files section #64

Open
wants to merge 9 commits into
base: dev
Choose a base branch
from
2 changes: 2 additions & 0 deletions lua/sidebar-nvim.lua
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,8 @@ end
-- @param opts table
-- @param opts.section_index number
-- @param opts.cursor_at_content boolean
-- @param opts.query table data sent to the section (if found) to refine the location
-- @param opts.section_line_offset number
function M.focus(opts)
lib.focus(opts)
end
Expand Down
115 changes: 96 additions & 19 deletions lua/sidebar-nvim/builtin/files.lua
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ local icons = {
local yanked_files = {}
local cut_files = {}
local open_directories = {}
local focused_file_path = nil

local section_index = nil

local history = { position = 0, groups = {} }
local trash_dir = luv.os_homedir() .. "/.local/share/Trash/files/"
Expand Down Expand Up @@ -113,18 +116,27 @@ local function build_loclist(group, directory, level)
selected = { text = " *", hl = "SidebarNvimFilesCut" }
end

local name_hl = nil
if
focused_file_path ~= nil
and vim.fn.fnamemodify(node.path, ":.") == vim.fn.fnamemodify(focused_file_path, ":.")
then
name_hl = "SidebarNvimFocusedFile"
end

loclist_items[#loclist_items + 1] = {
group = group,
left = {
{ text = string.rep(" ", level) .. icon.text .. " ", hl = icon.hl },
{ text = node.name },
{ text = node.name, hl = name_hl },
selected,
},
name = node.name,
path = node.path,
type = node.type,
parent = node.parent,
node = node,
id = node.path,
}
elseif node.type == "directory" then
local icon
Expand Down Expand Up @@ -167,12 +179,75 @@ local function build_loclist(group, directory, level)
return loclist_items
end

local function update(group, directory)
local function update_current_dir(group, directory)
local node = { path = directory, children = scan_dir(directory) }

loclist:set_items(build_loclist(group, node, 0), { remove_groups = true })
end

local function update(_)
local cwd = vim.fn.getcwd()
local group = utils.shortest_path(cwd)

open_directories[cwd] = true

update_current_dir(group, cwd)
end

local function focus(filename, opts)
opts = vim.tbl_deep_extend("force", { move_cursor = false }, opts or {})

local parent_path
-- reset the open directories
open_directories = {}

if filename == nil then
filename = vim.fn.expand("%:p")
parent_path = vim.fn.expand("%:p:h")
else
filename = vim.fn.expand(filename)
filename = vim.fn.fnamemodify(filename, ":p")
parent_path = vim.fn.fnamemodify(filename, ":p:h")
end

local cwd = vim.fn.getcwd()
local relative_path = vim.fn.fnamemodify(parent_path, ":.")

-- if the file is at the root, then ignore parent folders
if cwd ~= relative_path then
local components = vim.split(relative_path, "/")

local sub_path = cwd

for _, component in ipairs(components) do
sub_path = sub_path .. "/" .. component

-- check wether we are outside of the current dir, in this case we have nothing to show. exit
if vim.fn.isdirectory(sub_path) == 0 then
return
end

open_directories[sub_path] = true
end
end

focused_file_path = filename

if opts.move_cursor then
require("sidebar-nvim.lib").run_after_next_draw(function()
local line = loclist:get_line_at_id(filename)
require("sidebar-nvim.lib").focus({
section_index = section_index,
cursor_at_content = true,
section_line_offset = line,
})
end)
end

update() --P(path)
require("sidebar-nvim.lib").update()
end

local function exec(group)
for _, op in ipairs(group.operations) do
op.exec()
Expand Down Expand Up @@ -263,26 +338,25 @@ end
return {
title = "Files",
icon = config["files"].icon,
setup = function(_)
vim.api.nvim_exec(
[[
augroup sidebar_nvim_files_update
autocmd!
autocmd ShellCmdPost * lua require'sidebar-nvim.builtin.files'.update()
autocmd BufLeave term://* lua require'sidebar-nvim.builtin.files'.update()
augroup END
]],
false
setup = function(ctx)
section_index = ctx.section_index
vim.api.nvim_create_augroup("sidebar_nvim_files_update", { clear = true })
vim.api.nvim_create_autocmd({ "ShellCmdPost" }, { group = "sidebar_nvim_files_update", callback = update })
vim.api.nvim_create_autocmd(
{ "BufLeave" },
{ group = "sidebar_nvim_files_update", pattern = "term://*", callback = update }
)
end,
update = function(_)
local cwd = vim.fn.getcwd()
local group = utils.shortest_path(cwd)

open_directories[cwd] = true

update(group, cwd)
if config["files"].follow then
vim.api.nvim_create_autocmd({ "BufEnter", "BufLeave" }, {
group = "sidebar_nvim_files_update",
callback = function(event)
focus(event.file)
end,
})
end
end,
update = update,
draw = function(ctx)
local lines = {}
local hl = {}
Expand All @@ -298,9 +372,12 @@ return {
SidebarNvimFilesDirectory = "SidebarNvimSectionTitle",
SidebarNvimFilesYanked = "SidebarNvimLabel",
SidebarNvimFilesCut = "DiagnosticError",
SidebarNvimFocusedFile = "CursorLine",
},
},

focus = focus,

bindings = {
-- delete
["d"] = function(line)
Expand Down
19 changes: 18 additions & 1 deletion lua/sidebar-nvim/components/loclist.lua
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,10 @@ function Loclist:new(o)
o = vim.tbl_deep_extend("force", vim.deepcopy(Loclist.DEFAULT_OPTIONS), o or {}, {
-- table(line_number -> group ref)
_group_indexes = {},
-- table(line__number -> item ref)
-- table(line_number -> item ref)
_location_indexes = {},
-- table(id -> line_number)
_line_by_ids = {},
-- used to keep the group list stable
_group_keys = {},
})
Expand All @@ -56,6 +58,7 @@ end
-- |--|- (string) item.left[n].text = "abc"
-- |--|- (string) item.left[n].hl = "<highlight group>"
-- |- (number) item.order items are sorted based on order within each group
-- |- (any) item.id a unique id across the whole loclist, this is used for fast lookups. The id must also be unique between groups. If no id is specified, a random id is assigned
function Loclist:add_item(item)
if not self.groups[item.group] then
self.groups[item.group] = { is_closed = self.groups_initially_closed or false }
Expand All @@ -65,6 +68,10 @@ function Loclist:add_item(item)
table.insert(self._group_keys, item.group)
end

if item.id == nil then
item.id = math.random(1000000)
end

local group_tbl = self.groups[item.group]
group_tbl[#group_tbl + 1] = item

Expand Down Expand Up @@ -169,6 +176,7 @@ function Loclist:draw_group(ctx, group_name, with_label, section_lines, section_

for _, item in ipairs(group) do
self._location_indexes[#section_lines] = item
self._line_by_ids[item.id] = #section_lines
local line = ""

if with_label then
Expand Down Expand Up @@ -241,6 +249,7 @@ end
function Loclist:draw(ctx, section_lines, section_hl)
self._group_indexes = {}
self._location_indexes = {}
self._line_by_ids = {}

if #self._group_keys == 1 and self.omit_single_group then
self:draw_group(ctx, self._group_keys[1], false, section_lines, section_hl)
Expand All @@ -260,6 +269,14 @@ function Loclist:get_location_at(line)
return location
end

-- returns the line of where the item id is placed
-- if there is no item with the requested id, return nil.
-- @see Loclist:add_item
-- @param (any) id
function Loclist:get_line_at_id(id)
return self._line_by_ids[id]
end

-- toggles the group open/close that is printed on line `line`
-- if there is no group at `line`, then do nothing
-- @param (number) line
Expand Down
46 changes: 33 additions & 13 deletions lua/sidebar-nvim/lib.lua
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ local first_init_done = false

local M = {}

M.State = { section_line_indexes = {} }
M.State = { section_line_indexes = {}, after_draw_call_queue = {} }

M.timer = nil

Expand All @@ -32,6 +32,14 @@ local function loop()

updater.draw()
_redraw()

for _, fn in ipairs(M.State.after_draw_call_queue) do
local ret = pcall(fn)
if not ret then
utils.echo_warning("after_draw_call failed")
end
end
M.State.after_draw_call_queue = {}
end

local function _start_timer(should_delay)
Expand Down Expand Up @@ -78,6 +86,10 @@ function M.update()
_start_timer(true)
end

function M.run_after_next_draw(fn)
table.insert(M.State.after_draw_call_queue, fn)
end

function M.open(opts)
view.open(opts or { focus = false })
M.update()
Expand Down Expand Up @@ -115,13 +127,9 @@ end
-- @param opts table
-- @param opts.section_index number
-- @param opts.cursor_at_content boolean
-- @param opts.section_line_offset number
function M.focus(opts)
if view.is_win_open() then
local winnr = view.get_winnr()
view.focus(winnr)
else
M.open({ focus = true })
end
local cursor = nil

if opts and opts.section_index then
local content_only = true
Expand All @@ -130,11 +138,21 @@ function M.focus(opts)
content_only = false
end

local cursor = M.find_cursor_at_section_index(opts.section_index, { content_only = content_only })
cursor = M.find_cursor_at_section_index(
opts.section_index,
{ content_only = content_only, section_line_offset = opts.section_line_offset }
)
end

if cursor then
api.nvim_win_set_cursor(0, cursor)
end
if view.is_win_open() then
local winnr = view.get_winnr(nil)
view.focus(winnr)
else
M.open({ focus = true })
end

if cursor then
api.nvim_win_set_cursor(0, cursor)
end
end

Expand Down Expand Up @@ -206,16 +224,18 @@ end
-- @param index number
-- @param opts table
-- @param |- opts.content_only boolean whether the cursor should be placed at the first line of content or the section title
-- @param |- opts.section_line_offset number
-- @return table with cursor {line: number, col: number}
-- @return nil
function M.find_cursor_at_section_index(index, opts)
opts = opts or { content_only = false }
opts = vim.tbl_deep_extend("force", { content_only = false, section_line_offset = 0 }, opts or {})

local cursor = { 0, 0 }

for section_index, section_line_index in ipairs(M.State.section_line_indexes) do
if section_index == index then
local start_line = get_start_line(opts.content_only, section_line_index)
local content_only = opts.content_only
local start_line = get_start_line(content_only, section_line_index) + opts.section_line_offset

cursor[1] = start_line
return cursor
Expand Down
9 changes: 4 additions & 5 deletions lua/sidebar-nvim/updater.lua
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
local utils = require("sidebar-nvim.utils")
local utils_sections = require("sidebar-nvim.utils_sections")
local view = require("sidebar-nvim.view")
local config = require("sidebar-nvim.config")
local profile = require("sidebar-nvim.profile")
Expand All @@ -17,8 +18,8 @@ function M.setup()

local ctx = { width = view.get_width() }

for section_index, section_data in ipairs(config.sections) do
local section = utils.resolve_section(section_index, section_data)
for section_index, section in utils_sections.section_iterator() do
ctx.section_index = section_index
if section then
local hl_def = section.highlights or {}

Expand Down Expand Up @@ -65,9 +66,7 @@ function M.draw()

local draw_ctx = { width = view.View.width }

for section_index, section_data in pairs(config.sections) do
local section = utils.resolve_section(section_index, section_data)

for section_index, section in utils_sections.section_iterator() do
if section ~= nil then
local section_lines = profile.run("draw.sections." .. section_index, section.draw, draw_ctx)
local data = { lines = section_lines, section = section }
Expand Down
21 changes: 21 additions & 0 deletions lua/sidebar-nvim/utils_sections.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
local utils = require("sidebar-nvim.utils")
local config = require("sidebar-nvim.config")

local M = {}

function M.section_iterator()
local i = 0
return function()
i = i + 1
if i <= #config.sections then
local section = utils.resolve_section(i, config.sections[i])
return i, section
end
end
end

function M.get_section_at_index(index)
return utils.resolve_section(index, config.sections[index])
end

return M
1 change: 1 addition & 0 deletions plugin/sidebar-nvim.vim
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ command! SidebarNvimClose lua require'sidebar-nvim'.close()
command! SidebarNvimToggle lua require'sidebar-nvim'.toggle()
command! SidebarNvimUpdate lua require'sidebar-nvim'.update()
command! SidebarNvimFocus lua require'sidebar-nvim'.focus()
command! SidebarNvimFilesFind lua require'sidebar-nvim.builtin.files'.focus('%', { move_cursor = true })
command! -nargs=1 SidebarNvimResize lua require'sidebar-nvim'.resize(<args>)

let &cpo = s:save_cpo
Expand Down