diff --git a/lua/vfiler.lua b/lua/vfiler.lua index fa51b58..b67153d 100644 --- a/lua/vfiler.lua +++ b/lua/vfiler.lua @@ -1,5 +1,6 @@ local config = require('vfiler/config') local core = require('vfiler/libs/core') +local event = require('vfiler/event') local vim = require('vfiler/libs/vim') local VFiler = require('vfiler/vfiler') @@ -68,7 +69,9 @@ function M.start(dirpath, configs) local merged_configs = core.table.copy(config.configs) core.table.merge(merged_configs, configs or {}) + -- Preparation before starting VFiler.cleanup() + event.start() -- Correction of option values local options = merged_configs.options diff --git a/lua/vfiler/action.lua b/lua/vfiler/action.lua index ab749e1..b69b3ea 100644 --- a/lua/vfiler/action.lua +++ b/lua/vfiler/action.lua @@ -13,6 +13,7 @@ local action_modules = { 'yank', } +-- Load each action APIs. local M = setmetatable({}, { __index = function(t, key) for _, name in ipairs(action_modules) do diff --git a/lua/vfiler/actions/bookmark.lua b/lua/vfiler/actions/bookmark.lua index ad4a6a5..49e6561 100644 --- a/lua/vfiler/actions/bookmark.lua +++ b/lua/vfiler/actions/bookmark.lua @@ -1,4 +1,4 @@ -local api = require('vfiler/actions/api') +local utils = require('vfiler/actions/utilities') local M = {} @@ -11,10 +11,10 @@ function M.list_bookmark(vfiler, context, view) local Bookmark = require('vfiler/extensions/bookmark') local bookmark = Bookmark.new(vfiler, { on_selected = function(filer, c, v, path, open_type) - api.open_file(filer, c, v, path, open_type) + utils.open_file(filer, c, v, path, open_type) end, }) - api.start_extension(vfiler, context, view, bookmark) + utils.start_extension(vfiler, context, view, bookmark) end return M diff --git a/lua/vfiler/actions/buffer.lua b/lua/vfiler/actions/buffer.lua index af8a452..f8b7f71 100644 --- a/lua/vfiler/actions/buffer.lua +++ b/lua/vfiler/actions/buffer.lua @@ -1,4 +1,4 @@ -local api = require('vfiler/actions/api') +local utils = require('vfiler/actions/utilities') local core = require('vfiler/libs/core') local vim = require('vfiler/libs/vim') @@ -12,13 +12,13 @@ local M = {} function M.quit(vfiler, context, view) if context.options.quit then - api.close_preview(vfiler, context, view) + utils.close_preview(vfiler, context, view) vfiler:quit() end end function M.quit_force(vfiler, context, view) - api.close_preview(vfiler, context, view) + utils.close_preview(vfiler, context, view) vfiler:quit() end @@ -43,7 +43,7 @@ function M.switch_to_filer(vfiler, context, view) end -- close preview window - api.close_preview(vfiler, context, view) + utils.close_preview(vfiler, context, view) local linked = context.linked -- already linked @@ -53,7 +53,7 @@ function M.switch_to_filer(vfiler, context, view) else linked:open('right') end - linked:do_action(api.open_preview) + linked:do_action(utils.open_preview) return end @@ -65,12 +65,8 @@ function M.switch_to_filer(vfiler, context, view) newfiler:start(context.root.path) core.cursor.move(lnum) - -- redraw current - vfiler:focus() view:draw(context) - - newfiler:focus() -- return other filer - newfiler:do_action(api.open_preview) + newfiler:do_action(utils.open_preview) end function M.sync_with_current_filer(vfiler, context, view) @@ -78,11 +74,8 @@ function M.sync_with_current_filer(vfiler, context, view) if not (linked and linked:visible()) then return end - - linked:focus() linked:update(context) - linked:do_action(api.cd, context.root.path) - vfiler:focus() -- return current window + linked:do_action(utils.cd, context.root.path) end return M diff --git a/lua/vfiler/actions/directory.lua b/lua/vfiler/actions/directory.lua index 0f35922..2a901e9 100644 --- a/lua/vfiler/actions/directory.lua +++ b/lua/vfiler/actions/directory.lua @@ -1,4 +1,4 @@ -local api = require('vfiler/actions/api') +local utils = require('vfiler/actions/utilities') local cmdline = require('vfiler/libs/cmdline') local core = require('vfiler/libs/core') @@ -31,7 +31,7 @@ end function M.change_to_parent(vfiler, context, view) local current_path = context.root.path - api.cd(vfiler, context, view, context:parent_path()) + utils.cd(vfiler, context, view, context:parent_path()) view:move_cursor(current_path) end @@ -45,7 +45,7 @@ function M.jump_to_directory(vfiler, context, view) core.message.error('Not exists the "%s" path.', dirpath) return end - api.cd(vfiler, context, view, dirpath) + utils.cd(vfiler, context, view, dirpath) end function M.jump_to_history_directory(vfiler, context, view) @@ -59,20 +59,20 @@ function M.jump_to_history_directory(vfiler, context, view) initial_items = history, on_selected = function(filer, ctx, v, path) - api.cd(filer, ctx, v, path) + utils.cd(filer, ctx, v, path) end, }) - api.start_extension(vfiler, context, view, menu) + utils.start_extension(vfiler, context, view, menu) end function M.jump_to_home(vfiler, context, view) local dirpath = vim.fn.expand('~') - api.cd(vfiler, context, view, dirpath) + utils.cd(vfiler, context, view, dirpath) end function M.jump_to_root(vfiler, context, view) local dirpath = core.path.root(context.root.path) - api.cd(vfiler, context, view, dirpath) + utils.cd(vfiler, context, view, dirpath) end function M.close_tree(vfiler, context, view) @@ -90,7 +90,7 @@ function M.close_tree_or_cd(vfiler, context, view) local level = item and item.level or 0 if level == 0 or (level <= 1 and not item.opened) then local path = context.root.path - api.cd(vfiler, context, view, context:parent_path()) + utils.cd(vfiler, context, view, context:parent_path()) view:move_cursor(path) else M.close_tree(vfiler, context, view) @@ -151,7 +151,7 @@ function M.switch_to_drive(vfiler, context, view) v:move_cursor(focus_path) end, }) - api.start_extension(vfiler, context, view, menu) + utils.start_extension(vfiler, context, view, menu) end return M diff --git a/lua/vfiler/actions/event.lua b/lua/vfiler/actions/event.lua deleted file mode 100644 index 5817209..0000000 --- a/lua/vfiler/actions/event.lua +++ /dev/null @@ -1,59 +0,0 @@ -local core = require('vfiler/libs/core') -local vim = require('vfiler/libs/vim') -local buffer = require('vfiler/actions/buffer') - -local M = {} - -local event_lock = setmetatable({ - _bufnrs = {}, -}, {}) - -function event_lock:lock(bufnr) - if self._bufnrs[bufnr] then - return true - end - self._bufnrs[bufnr] = true -end - -function event_lock:unlock(bufnr) - self._bufnrs[bufnr] = nil -end - -function M.latest_update(vfiler, context, view) - local bufnr = view:bufnr() - if event_lock:lock(bufnr) then - return - end - - core.try({ - function() - local root = context.root - if vim.fn.getftime(root.path) > root.time then - vfiler:do_action(buffer.reload) - return - end - - for item in view:walk_items() do - if item.type == 'directory' then - if vim.fn.getftime(item.path) > item.time then - vfiler:do_action(buffer.reload) - return - end - end - end - end, - finally = function() - event_lock:unlock(bufnr) - end, - }) -end - -function M.leave(vfiler, context, view) - -- For floating windows, close the window, - -- including the buffer, as this will lead to problems. - if view:type() == 'floating' then - vfiler:wipeout() - end -end - -return M diff --git a/lua/vfiler/actions/file_operation.lua b/lua/vfiler/actions/file_operation.lua index 668dfd7..0000644 100644 --- a/lua/vfiler/actions/file_operation.lua +++ b/lua/vfiler/actions/file_operation.lua @@ -1,4 +1,4 @@ -local api = require('vfiler/actions/api') +local utils = require('vfiler/actions/utilities') local buffer = require('vfiler/actions/buffer') local clipboard = require('vfiler/clipboard') local cmdline = require('vfiler/libs/cmdline') @@ -58,7 +58,7 @@ local function rename_files(vfiler, context, view, targets) end end, }) - api.start_extension(vfiler, context, view, rename) + utils.start_extension(vfiler, context, view, rename) end local function rename_one_file(vfiler, context, view, target) diff --git a/lua/vfiler/actions/open.lua b/lua/vfiler/actions/open.lua index a12d44e..3190fd4 100644 --- a/lua/vfiler/actions/open.lua +++ b/lua/vfiler/actions/open.lua @@ -1,39 +1,39 @@ -local api = require('vfiler/actions/api') +local utils = require('vfiler/actions/utilities') local M = {} function M.open(vfiler, context, view) local path = view:get_item().path - api.open_file(vfiler, context, view, path) + utils.open_file(vfiler, context, view, path) end function M.open_by_choose(vfiler, context, view) local path = view:get_item().path - api.open_file(vfiler, context, view, path, 'choose') + utils.open_file(vfiler, context, view, path, 'choose') end function M.open_by_choose_or_cd(vfiler, context, view) local item = view:get_item() if item.type == 'directory' then - api.cd(vfiler, context, view, item.path) + utils.cd(vfiler, context, view, item.path) else - api.open_file(vfiler, context, view, item.path, 'choose') + utils.open_file(vfiler, context, view, item.path, 'choose') end end function M.open_by_split(vfiler, context, view) local path = view:get_item().path - api.open_file(vfiler, context, view, path, 'bottom') + utils.open_file(vfiler, context, view, path, 'bottom') end function M.open_by_tabpage(vfiler, context, view) local path = view:get_item().path - api.open_file(vfiler, context, view, path, 'tab') + utils.open_file(vfiler, context, view, path, 'tab') end function M.open_by_vsplit(vfiler, context, view) local path = view:get_item().path - api.open_file(vfiler, context, view, path, 'right') + utils.open_file(vfiler, context, view, path, 'right') end return M diff --git a/lua/vfiler/actions/preview.lua b/lua/vfiler/actions/preview.lua index 26e0d87..7249c2a 100644 --- a/lua/vfiler/actions/preview.lua +++ b/lua/vfiler/actions/preview.lua @@ -1,4 +1,4 @@ -local api = require('vfiler/actions/api') +local utils = require('vfiler/actions/utilities') local vim = require('vfiler/libs/vim') local Preview = require('vfiler/preview') @@ -6,7 +6,7 @@ local Preview = require('vfiler/preview') local M = {} function M.close_preview(vfiler, context, view) - api.close_preview(vfiler, context, view) + utils.close_preview(vfiler, context, view) end function M.preview_cursor_moved(vfiler, context, view) @@ -19,9 +19,9 @@ function M.preview_cursor_moved(vfiler, context, view) local line = vim.fn.line('.') if preview.line ~= line then if in_preview.once then - api.close_preview(vfiler, context, view) + utils.close_preview(vfiler, context, view) else - api.open_preview(vfiler, context, view) + utils.open_preview(vfiler, context, view) end preview.line = line end @@ -41,12 +41,12 @@ function M.toggle_auto_preview(vfiler, context, view) in_preview.preview = Preview.new(context.options.preview) end in_preview.once = false - api.open_preview(vfiler, context, view) + utils.open_preview(vfiler, context, view) end function M.toggle_preview(vfiler, context, view) local in_preview = context.in_preview - if api.close_preview(vfiler, context, view) then + if utils.close_preview(vfiler, context, view) then in_preview.preview = nil return end @@ -54,7 +54,7 @@ function M.toggle_preview(vfiler, context, view) in_preview.preview = Preview.new(context.options.preview) in_preview.once = true end - api.open_preview(vfiler, context, view) + utils.open_preview(vfiler, context, view) end return M diff --git a/lua/vfiler/actions/api.lua b/lua/vfiler/actions/utilities.lua similarity index 99% rename from lua/vfiler/actions/api.lua rename to lua/vfiler/actions/utilities.lua index 0a35a62..d7dc5e3 100644 --- a/lua/vfiler/actions/api.lua +++ b/lua/vfiler/actions/utilities.lua @@ -122,9 +122,7 @@ local function open_file(vfiler, context, view, path, layout) local dest_winid = vim.fn.win_getid() --if layout ~= 'tab' and dest_winid ~= view:winid() then if dest_winid ~= view:winid() then - vfiler:focus() view:redraw() - core.window.move(dest_winid) end end diff --git a/lua/vfiler/actions/view.lua b/lua/vfiler/actions/view.lua index bf0feae..38e130d 100644 --- a/lua/vfiler/actions/view.lua +++ b/lua/vfiler/actions/view.lua @@ -1,4 +1,4 @@ -local api = require('vfiler/actions/api') +local utils = require('vfiler/actions/utilities') local sort = require('vfiler/sort') local M = {} @@ -20,7 +20,7 @@ function M.change_sort(vfiler, context, view) v:move_cursor(item.path) end, }) - api.start_extension(vfiler, context, view, menu) + utils.start_extension(vfiler, context, view, menu) end function M.toggle_show_hidden(vfiler, context, view) diff --git a/lua/vfiler/config.lua b/lua/vfiler/config.lua index 805c012..eeb5875 100644 --- a/lua/vfiler/config.lua +++ b/lua/vfiler/config.lua @@ -1,6 +1,5 @@ local action = require('vfiler/action') local core = require('vfiler/libs/core') -local event = require('vfiler/actions/event') local vim = require('vfiler/libs/vim') local M = {} @@ -95,14 +94,20 @@ M.configs = { }, events = { - vfiler = { + vfiler_buffer = { { event = { 'BufEnter', 'FocusGained', 'VimResized' }, action = action.reload_all, }, { event = { 'BufLeave', 'TabLeave' }, - action = event.leave, + action = function(vfiler, context, view) + -- For floating windows, close the window, + -- including the buffer, as this will lead to problems. + if view:type() == 'floating' then + vfiler:wipeout() + end + end, }, }, diff --git a/lua/vfiler/event.lua b/lua/vfiler/event.lua index d0921ee..73763d0 100644 --- a/lua/vfiler/event.lua +++ b/lua/vfiler/event.lua @@ -1,102 +1,21 @@ -local core = require('vfiler/libs/core') -local vim = require('vfiler/libs/vim') +local config = require('vfiler/events/config') +local event = require('vfiler/events/event') -local registered_events = {} +local M = {} -local Event = {} -Event.__index = Event - -function Event.new(config) - local self = setmetatable({ - _bufnr = config.bufnr, - _callback = config.callback, - _args = config.args, - _event_actions = {}, - }, Event) - self:_register(config.events) - return self -end - -function Event._handle(bufnr, group, event) - local e = registered_events[bufnr] - if not e then - return - end - e:handle(group, event) -end - -function Event:handle(group, event) - local events = self._event_actions[group] - if not events then - core.message.error('Event group "%s" is not registered.', group) - return - end - - local actions = events[event] - if not actions then - core.message.error('Event "%s" is not registered.', event) - return - end - - for _, action in ipairs(actions) do - self._callback(action, self._args) - end +function M.setup(configs) + config.setup(configs) end -function Event:unregister() - local bufnr = self._bufnr - if bufnr <= 0 then +function M.start() + local configs = config.configs + if not configs.enabled then + event.clear(0) return end - - for group, _ in pairs(self._event_actions) do - core.autocmd.delete_group(group) - end - - if registered_events[bufnr] then - registered_events[bufnr] = nil - end - self._bufnr = -1 -end - -function Event:_register(events) - for group, eventlist in pairs(events) do - local commands = { core.autocmd.start_group(group) } - local actions = {} - local function register(event, action) - if not actions[event] then - actions[event] = {} - end - table.insert(actions[event], action) - - local cmd = (':lua require("vfiler/event")._handle(%d, "%s", "%s")'):format( - self._bufnr, - group, - event - ) - table.insert(commands, core.autocmd.create(event, cmd, { buffer = 0 })) - end - - for i, event in ipairs(eventlist) do - if type(event.event) == 'string' then - register(event.event, event.action) - elseif type(event.event) == 'table' then - for _, e in ipairs(event.event) do - register(e, event.action) - end - else - core.message.error( - 'Invalid event has been set for group "%s". (%d)', - group, - i - ) - end - end - self._event_actions[group] = actions - table.insert(commands, core.autocmd.end_group()) - vim.commands(commands) + for group, events in pairs(configs.events) do + event.register(group, events, 0) end - registered_events[self._bufnr] = self end -return Event +return M diff --git a/lua/vfiler/events/config.lua b/lua/vfiler/events/config.lua new file mode 100644 index 0000000..27c5d02 --- /dev/null +++ b/lua/vfiler/events/config.lua @@ -0,0 +1,60 @@ +local core = require('vfiler/libs/core') + +local M = {} + +-- TODO: +-- Update the file action. +--local function action_update_file(vfiler, context, view, path) +-- local lnum = view:lineof(path) +-- if lnum == 0 then +-- return +-- end +-- local item = view:get_item(lnum) +-- context:reload_item(item) +-- view:redraw_line(lnum) +-- -- NOTE: Reload the parent directory as git status is updated. +-- local parent = item.parent +-- while parent ~= nil do +-- lnum = view:lineof(parent.path) +-- if lnum > 0 then +-- view:redraw_line(lnum) +-- end +-- parent = parent.parent +-- end +--end + +-- TODO: +-- Update the file. +--local function update_file(bufnr, group, event) +-- local vfilers = VFiler.get_visible_in_tabpage(0) +-- if #vfilers == 0 then +-- return +-- end +-- local path = core.path.normalize(vim.fn.bufname(bufnr)) +-- for _, vfiler in ipairs(vfilers) do +-- vfiler:do_action(action_update_file, path) +-- end +--end + +-- Default configs +M.configs = { + enabled = true, + events = { + -- TODO: + --vfiler = { + -- { + -- event = { 'BufWritePost' }, + -- callback = update_file, + -- }, + --}, + }, +} + +--- Setup vfiler global events. +---@param configs table +function M.setup(configs) + core.table.merge(M.configs, configs) + return M.configs +end + +return M diff --git a/lua/vfiler/events/event.lua b/lua/vfiler/events/event.lua new file mode 100644 index 0000000..8d8390c --- /dev/null +++ b/lua/vfiler/events/event.lua @@ -0,0 +1,103 @@ +local core = require('vfiler/libs/core') +local vim = require('vfiler/libs/vim') + +local registered_events = {} + +local function get_group_name(group, bufnr) + return (bufnr > 0) and (group .. '_' .. bufnr) or group +end + +local M = {} + +function M._handle(bufnr, group, event) + local registered = registered_events[bufnr] + if not registered then + return + end + local events = registered[group] + if not events then + return + end + local callbacks = events[event] + if not callbacks then + return + end + if bufnr == 0 then + -- NOTE: Convert to integer type. + bufnr = vim.fn.expand('') + 0 + end + for _, callback in ipairs(callbacks) do + callback(bufnr, group, event) + end +end + +function M.register(group, events, bufnr) + bufnr = bufnr or 0 + local group_name = get_group_name(group, bufnr) + + -- Delete previously registered events, and re-register. + core.autocmd.delete_group(group_name) + + local commands = { core.autocmd.start_group(group_name) } + local this_module = 'require("vfiler/events/event")' + local callbacks = {} + local options = {} + if bufnr > 0 then + options.buffer = bufnr + end + + local function register(event, callback) + if not callbacks[event] then + callbacks[event] = {} + end + table.insert(callbacks[event], callback) + + local method = ('_handle(%d, "%s", "%s")'):format(bufnr, group, event) + local cmd = (':lua %s.%s'):format(this_module, method) + table.insert(commands, core.autocmd.create(event, cmd, options)) + end + + if not registered_events[bufnr] then + registered_events[bufnr] = {} + end + local registered = registered_events[bufnr] + + for _, event in ipairs(events) do + local type = type(event.event) + if type == 'string' then + register(event.event, event.callback) + elseif type == 'table' then + for _, e in ipairs(event.event) do + register(e, event.callback) + end + else + core.message.error('Invalid event for group "%s".', group) + end + end + registered[group] = callbacks + table.insert(commands, core.autocmd.end_group()) + vim.commands(commands) +end + +function M.unregister(group, bufnr) + bufnr = bufnr or 0 + local group_name = get_group_name(group, bufnr) + core.autocmd.delete_group(group_name) + local registered = registered_events[bufnr] + if registered then + registered[group] = nil + end +end + +function M.clear(bufnr) + local registered = registered_events[bufnr] + if not registered then + return + end + for group, _ in pairs(registered) do + core.autocmd.delete_group(get_group_name(group, bufnr)) + end + registered_events[bufnr] = nil +end + +return M diff --git a/lua/vfiler/extensions/extension.lua b/lua/vfiler/extensions/extension.lua index 656fab3..f58ea05 100644 --- a/lua/vfiler/extensions/extension.lua +++ b/lua/vfiler/extensions/extension.lua @@ -1,9 +1,8 @@ local cmdline = require('vfiler/libs/cmdline') local core = require('vfiler/libs/core') +local event = require('vfiler/events/event') local vim = require('vfiler/libs/vim') -local Event = require('vfiler/event') - local extensions = {} local Extension = {} @@ -273,14 +272,18 @@ function Extension:start() self._mappings = define(configs.mappings) -- register events - self._event = Event.new({ - events = configs.events, - bufnr = self._buffer.number, - args = self, - callback = function(action, args) - args:do_action(action) - end, - }) + for group, elist in pairs(configs.events) do + local events = {} + for _, e in ipairs(elist) do + table.insert(events, { + event = e.event, + callback = function(_, _, _) + self:do_action(e.action) + end, + }) + end + event.register(group, events, self._buffer.number) + end -- draw line texts and syntax self:_on_draw(self._buffer, lines) diff --git a/lua/vfiler/items/directory.lua b/lua/vfiler/items/directory.lua index 72d947d..efce3d3 100644 --- a/lua/vfiler/items/directory.lua +++ b/lua/vfiler/items/directory.lua @@ -98,16 +98,6 @@ function Directory:open(recursive) self.opened = true end -function Directory:update() - local stat = fs.stat(self.path) - if not stat then - return - end - self.size = stat.size - self.time = stat.time - self.mode = stat.mode -end - function Directory:_add(item) item.parent = self item.level = self.level + 1 diff --git a/lua/vfiler/items/file.lua b/lua/vfiler/items/file.lua index daafc73..7ac1f9a 100644 --- a/lua/vfiler/items/file.lua +++ b/lua/vfiler/items/file.lua @@ -30,4 +30,8 @@ function File:move(destpath) return nil end +function File:reload() + self:_set_stat(fs.stat(self.path)) +end + return File diff --git a/lua/vfiler/items/item.lua b/lua/vfiler/items/item.lua index 3dd2e66..0b45d9b 100644 --- a/lua/vfiler/items/item.lua +++ b/lua/vfiler/items/item.lua @@ -5,19 +5,13 @@ local Item = {} Item.__index = Item function Item.new(stat) - return setmetatable({ + local self = setmetatable({ gitstatus = nil, level = 0, - name = stat.name, parent = nil, - path = stat.path, selected = false, - size = stat.size, - time = stat.time, - type = stat.type, - mode = stat.mode, - link = stat.link, }, Item) + return self:_set_stat(stat) end function Item:delete() @@ -40,6 +34,14 @@ function Item:rename(name) return true end +function Item:update() + local stat = fs.stat(self.path) + if not stat then + return + end + self:_set_stat(stat) +end + --- Remove from parent tree function Item:_become_orphan() if not self.parent then @@ -66,4 +68,15 @@ function Item:_move(destpath) return true end +function Item:_set_stat(stat) + self.name = stat.name + self.path = stat.path + self.size = stat.size + self.time = stat.time + self.type = stat.type + self.mode = stat.mode + self.link = stat.link + return self +end + return Item diff --git a/lua/vfiler/libs/core.lua b/lua/vfiler/libs/core.lua index 0b2c13a..1c9369a 100644 --- a/lua/vfiler/libs/core.lua +++ b/lua/vfiler/libs/core.lua @@ -361,9 +361,12 @@ function M.autocmd.create(event, cmd, options) table.insert(commands, '') else M.message.error('Unknown "buffer" option.') + return nil end elseif options.pattern then table.insert(commands, options.pattern) + else + table.insert(commands, '*') end if options.once then @@ -372,6 +375,8 @@ function M.autocmd.create(event, cmd, options) if options.nested then table.insert(commands, '++nested') end + else + table.insert(commands, '*') end table.insert(commands, cmd) diff --git a/lua/vfiler/libs/timer.lua b/lua/vfiler/libs/timer.lua new file mode 100644 index 0000000..0a93544 --- /dev/null +++ b/lua/vfiler/libs/timer.lua @@ -0,0 +1,82 @@ +local vim = require('vfiler/libs/vim') + +local Timer = {} +Timer.__index = Timer + +local function create_result_data(laptimes) + if #laptimes == 0 then + return {} + end + -- Create result data + local lap = laptimes[1] + local times = { + { + mark = lap.mark, + time = lap.time, + total = lap.time, + }, + } + local prev = lap + for i = 2, #laptimes do + lap = laptimes[i] + table.insert(times, { + mark = lap.mark, + time = lap.time - prev.time, + total = lap.time, + }) + prev = lap + end + return times +end + +function Timer.start(name) + return setmetatable({ + _name = name, + _laptimes = {}, + _start = vim.fn.reltime(), + }, Timer) +end + +function Timer:lap(mark) + local time = vim.fn.reltimefloat(vim.fn.reltime(self._start)) + table.insert(self._laptimes, { + mark = mark, + time = time, + }) + return time +end + +function Timer:print() + local times = create_result_data(self._laptimes) + + -- Print result data + print('---', self._name, '---') + print('No\tMark\tTime(s)\tTotal') + for i, time in ipairs(times) do + local result = ('%d\t%s\t%.6f\t%.6f'):format( + i, + time.mark, + time.time, + time.total + ) + print(result) + end +end + +function Timer:write(path) + local times = create_result_data(self._laptimes) + local file, error = io.open(path, 'w') + if not file then + print(error) + return + end + file:write('No,Mark,Time(s),Total\n') + for i, time in ipairs(times) do + file:write( + ('%d,%s,%.6f,%.6f\n'):format(i, time.mark, time.time, time.total) + ) + end + file:close() +end + +return Timer diff --git a/lua/vfiler/vfiler.lua b/lua/vfiler/vfiler.lua index b6960f2..b095401 100644 --- a/lua/vfiler/vfiler.lua +++ b/lua/vfiler/vfiler.lua @@ -1,9 +1,8 @@ local core = require('vfiler/libs/core') +local event = require('vfiler/events/event') local status = require('vfiler/status') local vim = require('vfiler/libs/vim') -local Event = require('vfiler/event') - local vfiler_objects = {} local VFiler = {} @@ -117,10 +116,8 @@ function VFiler.foreach(action, ...) return end for _, filer in ipairs(VFiler.get_visible()) do - filer:focus() filer:do_action(action, ...) end - current:focus() end --- Get the filer from the buffer number @@ -164,7 +161,7 @@ function VFiler.get_visible_in_tabpage(tabpage) return visibilities end ---- Create a filer obuject +--- Create a filer object ---@param context table function VFiler.new(context) -- create buffer @@ -178,7 +175,6 @@ function VFiler.new(context) _context = context, _view = View.new(context.options), _mappings = nil, - _event = nil, }, VFiler) -- add vfiler resource @@ -319,7 +315,7 @@ end --- Is the filer visible? function VFiler:visible() - return self._view:winnr() >= 0 + return self._view:winid() > 0 end --- Wipeout filer @@ -330,6 +326,7 @@ function VFiler:wipeout() if bufnr <= 0 then return end + self:_unregister_events() self._buffer:wipeout() vfiler_objects[bufnr] = nil end @@ -342,14 +339,24 @@ function VFiler:_define_mappings() end function VFiler:_register_events() - self._event = Event.new({ - events = self._context.events, - bufnr = self._buffer.number, - args = self, - callback = function(action, args) - args:do_action(action) - end, - }) + for group, elist in pairs(self._context.events) do + local events = {} + for _, e in ipairs(elist) do + table.insert(events, { + event = e.event, + callback = function(_, _, _) + self:do_action(e.action) + end, + }) + end + event.register(group, events, self._buffer.number) + end +end + +function VFiler:_unregister_events() + for group, _ in pairs(self._context.events) do + event._unregister_events(group, self._buffer.number) + end end return VFiler diff --git a/lua/vfiler/view.lua b/lua/vfiler/view.lua index d110357..af5a5d1 100644 --- a/lua/vfiler/view.lua +++ b/lua/vfiler/view.lua @@ -230,6 +230,16 @@ function View:has_column(name) return self._columns.table[name] ~= nil end +--- Find the item of the item in the view buffer for the specified path +---@param path string +function View:itemof(path) + local index = self:indexof(path) + if index == 0 then + return nil + end + return self._items.list[index] +end + --- Find the index of the item in the view buffer for the specified path ---@param path string function View:indexof(path) @@ -240,6 +250,16 @@ function View:indexof(path) return item.index end +--- Find the line of the item in the view buffer for the specified path +---@param path string +function View:lineof(path) + local index = self:indexof(path) + if index == 0 then + return 0 + end + return index + (self:top_lnum() - 1) +end + --- Get the index of the first sibling item function View:indexof_first_sibling(lnum) local level = self._items.lnum_indexes[lnum].level @@ -321,20 +341,21 @@ end --- Redraw the current contents function View:redraw() local buffer = self._buffer - if not buffer or (buffer.number ~= vim.fn.bufnr()) then - -- for debug - --core.message.warning( - -- 'Cannot draw because the buffer is different. (%d != %d)', - -- buffer.number, - -- vim.fn.bufnr() - --) - return - end + -- NOTE: for debugging. + --if not buffer or (buffer.number ~= vim.fn.bufnr()) then + -- core.message.warning( + -- 'Cannot draw because the buffer is different. (%d != %d)', + -- buffer.number, + -- vim.fn.bufnr() + -- ) + -- return + --end local cache = self._cache local winid = self:winid() if winid < 0 then - core.message.warning('The buffer is invisible and cannot be drawn.') + -- NOTE: for debugging. + --core.message.warning('The buffer is invisible and cannot be drawn.') return elseif cache.winid ~= winid then -- set window options @@ -483,11 +504,6 @@ function View:width() return self._cache.win_width end ---- Get the window number of the view -function View:winnr() - return vim.fn.bufwinnr(self._buffer.number) -end - --- Get the window ID of the view function View:winid() if not self._window then diff --git a/tests/init.vim b/tests/init.vim index 27d5090..ee7836a 100644 --- a/tests/init.vim +++ b/tests/init.vim @@ -1,4 +1,4 @@ -set rtp+=. +set rtp+=./ set rtp+=../plenary.nvim/ set shellslash diff --git a/tests/utility.lua b/tests/utilities.lua similarity index 100% rename from tests/utility.lua rename to tests/utilities.lua diff --git a/tests/vfiler/actions/buffer_spec.lua b/tests/vfiler/actions/buffer_spec.lua index bf11ef3..0dcdd53 100644 --- a/tests/vfiler/actions/buffer_spec.lua +++ b/tests/vfiler/actions/buffer_spec.lua @@ -1,5 +1,5 @@ local a = require('vfiler/actions/buffer') -local u = require('tests/utility') +local u = require('tests/utilities') local VFiler = require('vfiler/vfiler') local configs = { diff --git a/tests/vfiler/actions/cursor_spec.lua b/tests/vfiler/actions/cursor_spec.lua index b8638ca..e61164f 100644 --- a/tests/vfiler/actions/cursor_spec.lua +++ b/tests/vfiler/actions/cursor_spec.lua @@ -1,5 +1,5 @@ local a = require('vfiler/actions/cursor') -local u = require('tests/utility') +local u = require('tests/utilities') describe('cursor actions', function() local vfiler = u.vfiler.start(u.vfiler.generate_options()) diff --git a/tests/vfiler/actions/directory/close_tree_or_cd_spec.lua b/tests/vfiler/actions/directory/close_tree_or_cd_spec.lua index ab165c7..3c463ee 100644 --- a/tests/vfiler/actions/directory/close_tree_or_cd_spec.lua +++ b/tests/vfiler/actions/directory/close_tree_or_cd_spec.lua @@ -1,6 +1,6 @@ local core = require('vfiler/libs/core') local a = require('vfiler/actions/directory') -local u = require('tests/utility') +local u = require('tests/utilities') local configs = { options = u.vfiler.generate_options(), diff --git a/tests/vfiler/actions/directory/open_and_close_tree_spec.lua b/tests/vfiler/actions/directory/open_and_close_tree_spec.lua index fe03c7b..31ae83f 100644 --- a/tests/vfiler/actions/directory/open_and_close_tree_spec.lua +++ b/tests/vfiler/actions/directory/open_and_close_tree_spec.lua @@ -1,5 +1,5 @@ local a = require('vfiler/actions/directory') -local u = require('tests/utility') +local u = require('tests/utilities') local configs = { options = u.vfiler.generate_options(), diff --git a/tests/vfiler/actions/directory/open_tree_recursive_spec.lua b/tests/vfiler/actions/directory/open_tree_recursive_spec.lua index 189639f..dfe24d3 100644 --- a/tests/vfiler/actions/directory/open_tree_recursive_spec.lua +++ b/tests/vfiler/actions/directory/open_tree_recursive_spec.lua @@ -1,5 +1,5 @@ local a = require('vfiler/actions/directory') -local u = require('tests/utility') +local u = require('tests/utilities') local configs = { options = u.vfiler.generate_options(), diff --git a/tests/vfiler/actions/open/open_by_choose_spec.lua b/tests/vfiler/actions/open/open_by_choose_spec.lua index 1c1c85c..819e28d 100644 --- a/tests/vfiler/actions/open/open_by_choose_spec.lua +++ b/tests/vfiler/actions/open/open_by_choose_spec.lua @@ -1,6 +1,6 @@ local core = require('vfiler/libs/core') local a = require('vfiler/actions/open') -local u = require('tests/utility') +local u = require('tests/utilities') local configs = { options = u.vfiler.generate_options(), diff --git a/tests/vfiler/actions/open/open_by_split_spec.lua b/tests/vfiler/actions/open/open_by_split_spec.lua index 66ef363..db0f33a 100644 --- a/tests/vfiler/actions/open/open_by_split_spec.lua +++ b/tests/vfiler/actions/open/open_by_split_spec.lua @@ -1,6 +1,6 @@ local core = require('vfiler/libs/core') local a = require('vfiler/actions/open') -local u = require('tests/utility') +local u = require('tests/utilities') local configs = { options = u.vfiler.generate_options(), diff --git a/tests/vfiler/actions/open/open_by_tabpage_spec.lua b/tests/vfiler/actions/open/open_by_tabpage_spec.lua index 9d0e7fb..5a8a5ba 100644 --- a/tests/vfiler/actions/open/open_by_tabpage_spec.lua +++ b/tests/vfiler/actions/open/open_by_tabpage_spec.lua @@ -1,6 +1,6 @@ local core = require('vfiler/libs/core') local a = require('vfiler/actions/open') -local u = require('tests/utility') +local u = require('tests/utilities') local configs = { options = u.vfiler.generate_options(), diff --git a/tests/vfiler/actions/open/open_by_vsplit_spec.lua b/tests/vfiler/actions/open/open_by_vsplit_spec.lua index a87c94c..32d84c0 100644 --- a/tests/vfiler/actions/open/open_by_vsplit_spec.lua +++ b/tests/vfiler/actions/open/open_by_vsplit_spec.lua @@ -1,6 +1,6 @@ local core = require('vfiler/libs/core') local a = require('vfiler/actions/open') -local u = require('tests/utility') +local u = require('tests/utilities') local configs = { options = u.vfiler.generate_options(), diff --git a/tests/vfiler/actions/open/open_spec.lua b/tests/vfiler/actions/open/open_spec.lua index 76ddc27..94383ee 100644 --- a/tests/vfiler/actions/open/open_spec.lua +++ b/tests/vfiler/actions/open/open_spec.lua @@ -1,5 +1,5 @@ local a = require('vfiler/actions/open') -local u = require('tests/utility') +local u = require('tests/utilities') local configs = { options = u.vfiler.generate_options(), diff --git a/tests/vfiler/actions/select_spec.lua b/tests/vfiler/actions/select_spec.lua index 7b6c96d..5085d8e 100644 --- a/tests/vfiler/actions/select_spec.lua +++ b/tests/vfiler/actions/select_spec.lua @@ -1,5 +1,5 @@ local a = require('vfiler/actions/select') -local u = require('tests/utility') +local u = require('tests/utilities') describe('select actions', function() u.randomseed() diff --git a/tests/vfiler/actions/view_spec.lua b/tests/vfiler/actions/view_spec.lua index 7c6a8b5..8d6a82b 100644 --- a/tests/vfiler/actions/view_spec.lua +++ b/tests/vfiler/actions/view_spec.lua @@ -1,5 +1,5 @@ local a = require('vfiler/actions/view') -local u = require('tests/utility') +local u = require('tests/utilities') local function find(view, target) for item in view:walk_items() do @@ -38,7 +38,6 @@ describe('view actions', function() it(u.vfiler.desc('toggle_sort', vfiler), function() vfiler:do_action(a.toggle_sort) assert.is_equal('Name', context.options.sort) - -- TODO: vfiler:do_action(a.toggle_sort) assert.is_equal('name', context.options.sort) diff --git a/tests/vfiler/actions/yank_spec.lua b/tests/vfiler/actions/yank_spec.lua index 145e461..eb55ce2 100644 --- a/tests/vfiler/actions/yank_spec.lua +++ b/tests/vfiler/actions/yank_spec.lua @@ -1,5 +1,5 @@ local a = require('vfiler/actions/yank') -local u = require('tests/utility') +local u = require('tests/utilities') local core = require('vfiler/libs/core') local cursor = require('vfiler/actions/cursor') diff --git a/tests/vfiler/item_spec.lua b/tests/vfiler/item_spec.lua new file mode 100644 index 0000000..f539dd8 --- /dev/null +++ b/tests/vfiler/item_spec.lua @@ -0,0 +1,63 @@ +local core = require('vfiler/libs/core') +local fs = require('vfiler/libs/filesystem') + +local Directory = require('vfiler/items/directory') +local File = require('vfiler/items/file') + +describe('item', function() + local root = vim.fn.fnamemodify('./', ':p') + + describe('directory', function() + it('create and delete', function() + local dirpath = core.path.join(root, 'foo') + local dir = Directory.create(dirpath) + assert.is_not_nil(dir) + assert.is_true(core.path.exists(dirpath)) + + local result = dir:delete() + assert.is_true(result) + assert.is_false(core.path.exists(dirpath)) + end) + + it('update', function() + local stat = fs.stat(root) + local dir = Directory.new(stat) + assert.is_not_nil(dir) + dir:update() + end) + end) + + describe('file', function() + it('create and delete', function() + local filepath = core.path.join(root, 'foo') + local file = File.create(filepath) + assert.is_not_nil(file) + assert.is_true(core.path.exists(filepath)) + + local result = file:delete() + assert.is_true(result) + assert.is_false(core.path.exists(filepath)) + end) + + it('update', function() + local path = core.path.join(root, 'README.md') + local stat = fs.stat(path) + local file = File.new(stat) + assert.is_not_nil(file) + + local expected = { + name = file.name, + path = file.path, + size = file.size, + time = file.time, + type = file.type, + mode = file.mode, + link = file.link, + } + file:update() + for prop, value in pairs(expected) do + assert.equal(value, file[prop]) + end + end) + end) +end) diff --git a/tests/vfiler/libs/core_spec.lua b/tests/vfiler/libs/core_spec.lua index 995612b..28f534f 100644 --- a/tests/vfiler/libs/core_spec.lua +++ b/tests/vfiler/libs/core_spec.lua @@ -374,12 +374,12 @@ describe('core.autocmd', function() basic = { event = 'BufEnter', cmd = ':echo', - expected = 'autocmd! BufEnter :echo', + expected = 'autocmd! BufEnter * :echo', }, events = { event = { 'BufEnter', 'BufLeave' }, cmd = ':echo', - expected = 'autocmd! BufEnter,BufLeave :echo', + expected = 'autocmd! BufEnter,BufLeave * :echo', }, options_buffer1 = { event = 'BufEnter', @@ -411,7 +411,7 @@ describe('core.autocmd', function() options = { buffer = {}, }, - expected = 'autocmd! BufEnter :echo', + expected = nil, }, options_pattern = { event = 'BufEnter', @@ -446,7 +446,7 @@ describe('core.autocmd', function() nested = true, once = true, }, - expected = 'autocmd! BufEnter ++once ++nested :echo', + expected = 'autocmd! BufEnter * ++once ++nested :echo', }, } diff --git a/tests/vfiler/libs/git_spec.lua b/tests/vfiler/libs/git_spec.lua new file mode 100644 index 0000000..e312a44 --- /dev/null +++ b/tests/vfiler/libs/git_spec.lua @@ -0,0 +1,75 @@ +local git = require('vfiler/libs/git') + +describe('git', function() + local rootpath = vim.fn.fnamemodify('./', ':p') + + describe('get_toplevel', function() + it('call', function() + local path = git.get_toplevel(rootpath) + assert.is_not_nil(path) + end) + end) + + describe('reload_status_async', function() + it('call', function() + local options = {} + local job = git.reload_status_async(rootpath, options, function(status) + assert.is_not_nil(status) + end) + assert.is_not_nil(job) + job:wait() + + options = { + untracked = ture, + } + job = git.reload_status_async(rootpath, options, function(status) + assert.is_not_nil(status) + end) + assert.is_not_nil(job) + job:wait() + + options = { + ignored = ture, + } + job = git.reload_status_async(rootpath, options, function(status) + assert.is_not_nil(status) + end) + assert.is_not_nil(job) + job:wait() + + options = { + untracked = ture, + ignored = ture, + } + job = git.reload_status_async(rootpath, options, function(status) + assert.is_not_nil(status) + end) + assert.is_not_nil(job) + job:wait() + end) + end) + + describe('reload_status_file', function() + it('call', function() + local options = {} + local path = vim.fn.fnamemodify('./README.md', ':p') + local status = git.reload_status_file(rootpath, path, options) + + options = { + untracked = ture, + } + status = git.reload_status_file(rootpath, path, options) + + options = { + ignored = ture, + } + status = git.reload_status_file(rootpath, path, options) + + options = { + untracked = ture, + ignored = ture, + } + status = git.reload_status_file(rootpath, path, options) + end) + end) +end) diff --git a/tests/vfiler/vfiler_spec.lua b/tests/vfiler/vfiler_spec.lua index ed9e543..a34fe10 100644 --- a/tests/vfiler/vfiler_spec.lua +++ b/tests/vfiler/vfiler_spec.lua @@ -1,4 +1,4 @@ -local u = require('tests/utility') +local u = require('tests/utilities') local Buffer = require('vfiler/buffer') describe('vfiler', function() diff --git a/tests/vfiler/view_spec.lua b/tests/vfiler/view_spec.lua index 0b8c76f..705dbdf 100644 --- a/tests/vfiler/view_spec.lua +++ b/tests/vfiler/view_spec.lua @@ -1,6 +1,9 @@ -local u = require('tests/utility') +local core = require('vfiler/libs/core') +local u = require('tests/utilities') describe('view', function() + local root = vim.fn.fnamemodify('./', ':p') + it('has_column', function() local vfiler = u.vfiler.start() local view = vfiler._view @@ -9,6 +12,46 @@ describe('view', function() vfiler:quit(true) end) + it('indexof', function() + local vfiler = u.vfiler.start() + local view = vfiler._view + local path = core.path.join(root, 'README.md') + local index = view:indexof(path) + assert.not_equal(0, index) + + -- Purposely set a path that does not exist. + path = core.path.join(root, 'foo.xxx') + index = view:indexof(path) + assert.equal(0, index) + end) + + it('itemof', function() + local vfiler = u.vfiler.start() + local view = vfiler._view + local path = core.path.join(root, 'README.md') + local item = view:itemof(path) + assert.not_nil(item) + assert.equal(path, item.path) + + -- Purposely set a path that does not exist. + path = core.path.join(root, 'foo.xxx') + item = view:itemof(path) + assert.is_nil(item) + end) + + it('lineof', function() + local vfiler = u.vfiler.start() + local view = vfiler._view + local path = core.path.join(root, 'README.md') + local lnum = view:lineof(path) + assert.is_true(lnum ~= 0) + + -- Purposely set a path that does not exist. + path = core.path.join(root, 'foo.xxx') + lnum = view:lineof(path) + assert.is_true(lnum == 0) + end) + it('top_lnum', function() local vfiler = u.vfiler.start({ options = {