Skip to content

Instantly share code, notes, and snippets.

@wfdewith
Last active January 15, 2024 16:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wfdewith/978e4f8e09f481a480cb1bf645e8d518 to your computer and use it in GitHub Desktop.
Save wfdewith/978e4f8e09f481a480cb1bf645e8d518 to your computer and use it in GitHub Desktop.
local DocSettings = require("docsettings")
local ffiUtil = require("ffi/util")
local FileChooser = require("ui/widget/filechooser")
local _ = require("gettext")
--[[
This algorithm sorts books as follows.
First, it sorts them into three blocks in the following order: in progress,
unread and finished.
The in progress block is then further sorted by access time, where the last
accessed book is sorted first. If the access time is equal, they will be sorted
by their name. Equal access times are not rare on FAT32 because it is only
precise to a day.
The other blocks are sorted only by name.
Directories are considered to have the properties of their 'smallest' child
item, except for the name.
--]]
local function weirdsort(x, y)
local a = x.sort_item
local b = y.sort_item
-- If any sort_item is nil, they are empty directories
if not a then
return false
elseif not b then
return true
end
-- Note that we use the original x and y for the strcoll calls, to sort by
-- the original directory name.
if a.opened == b.opened then
if a.opened then
if a.status == b.status then
if a.status == "reading" then
if a.attr.access == b.attr.access then
return ffiUtil.strcoll(x.text, y.text)
else
return a.attr.access > b.attr.access
end
else
return ffiUtil.strcoll(x.text, y.text)
end
else
return a.status == "reading"
end
else
return ffiUtil.strcoll(x.text, y.text)
end
else
if a.opened then
return a.status == "reading"
else
return b.status ~= "reading"
end
end
end
FileChooser.collates.weirdsort = {
text = _("Wim's custom sort"),
menu_order = 999,
can_collate_mixed = true,
init_sort_func = function(cache)
return weirdsort, cache
end,
mandatory_func = function(item)
return item.opened and string.format("%d %%", 100 * item.percent_finished) or "–"
end,
item_func = function(item)
if item.attr.mode == "file" then
local percent_finished, summary
item.opened = DocSettings:hasSidecarFile(item.path)
if item.opened then
local doc_settings = DocSettings:open(item.path)
percent_finished = doc_settings:readSetting("percent_finished")
summary = doc_settings:readSetting("summary")
end
item.percent_finished = percent_finished or 0
item.status = summary and summary.status or nil
item.sort_item = item
elseif item.attr.mode == "directory" then
local function smallest_child(dirs, files)
local first
if #dirs > 0 then
first = dirs[1]
elseif #files > 0 then
first = files[1]
end
for i, d in ipairs(dirs) do
if weirdsort(d.sort_item, first) then
first = d.sort_item
end
end
for i, f in ipairs(files) do
if weirdsort(f.sort_item, first) then
first = f.sort_item
end
end
return first
end
local dirs, files = FileChooser:getList(item.path, FileChooser.collates.weirdsort)
for i, d in ipairs(dirs) do
local subdirs, subfiles = FileChooser:getList(d.path, FileChooser.collates.weirdsort)
d.sort_item = smallest_child(subdirs, subfiles)
end
item.sort_item = smallest_child(dirs, files)
end
return item
end,
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment