1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
|
--[[
Puts cursor on a recently modified/changed/accessed entry in current view,
which frees from the need to change and restore 'sort' to do it otherwise.
Adds the following mappings:
* [count]rm -- puts cursor on a [count]'s recently modified entry
* [count]rc -- puts cursor on a [count]'s recently changed entry
* [count]ra -- puts cursor on a [count]'s recently accessed entry
--]]
local M = {}
local function make_entries_sorter(attr)
-- sorts entries by `attr` and entry name in descending order
return function(e1, e2)
-- like -attr in 'sort'
if e1[attr] ~= e2[attr] then
return e1[attr] > e2[attr]
-- like +dir in 'sort'
elseif (e1.isdir and not e2.isdir) or (not e1.isdir and e2.isdir) then
return e1.isdir
-- like +name in 'sort'
else
return e1.name < e2.name
end
end
end
local function full_path(e)
return e.location .. '/' .. e.name
end
local function recent_entry_index(attr, num)
local currview = vifm.currview()
local curr_entry = currview.cursor:entry()
local curr_loc = curr_entry.location
local entries = {}
local entry_pos = {}
local function remember_entry_and_position(e, pos)
table.insert(entries, e)
entry_pos[full_path(e)] = pos
end
if currview.custom == nil or currview.custom.type ~= 'tree' then
for i = 1, currview.entrycount do
local e = currview:entry(i)
remember_entry_and_position(e, i)
end
else
-- limit to location of current entry in tree-view
remember_entry_and_position(curr_entry, currview.cursor.pos)
local function belongs_to_curr_entry_location(i)
local e = currview:entry(i)
if e.location:sub(1, curr_loc:len()) ~= curr_loc then
return false
end
if e.location == curr_loc then
remember_entry_and_position(e, i)
end
return true
end
-- gather entries around the cursor
local i = currview.cursor.pos - 1
while i >= 1 and belongs_to_curr_entry_location(i) do
i = i - 1
end
local i = currview.cursor.pos + 1
while i <= currview.entrycount and belongs_to_curr_entry_location(i) do
i = i + 1
end
end
table.sort(entries, make_entries_sorter(attr))
local num = math.max(num or 1, 1)
local idx = math.min(num, #entries)
return entry_pos[full_path(entries[idx])]
end
local function make_handler(attr)
return function(info)
vifm.currview().cursor.pos = recent_entry_index(attr, info.count)
end
end
local function make_handler_selector(attr)
return function(info)
local currview = vifm.currview()
local begin = recent_entry_index(attr, info.count)
local end_ = currview.cursor.pos
if begin > end_ then
begin, end_ = end_, begin
end
local indexes = {}
for i = begin, end_ do
table.insert(indexes, i)
end
return {
indexes = indexes,
cursorpos = indexes[1],
}
end
end
local function add_key(key, attr, desc)
local added = vifm.keys.add {
shortcut = key,
description = 'move cursor to recently ' .. desc .. ' entry',
modes = { 'normal', 'visual' },
handler = make_handler(attr),
}
if not added then
vifm.sb.error('Failed to register ' .. key)
end
local added = vifm.keys.add {
shortcut = key,
description = 'move cursor to recently ' .. desc .. ' entry',
modes = { 'normal' },
isselector = true,
handler = make_handler_selector(attr),
}
if not added then
vifm.sb.error('Failed to register selector ' .. key)
end
end
add_key('rm', 'mtime', 'modified')
add_key('rc', 'ctime', 'changed')
add_key('ra', 'atime', 'accessed')
return M
|