Besides some smaller fixes with the styling of the page, and in particular the diagrams introduced in 2019-10-24
,
I finally (re-)implemented children-ordering in the fs
-store of mmmmfs
(the sql
store is still missing it, but I am not currently using it either) [a62f63b
]:
Files on the regular filesystem don’t have a particular order, but in mmmfs the order of children is is guaranteed,
so that arranging children in a particular order becomes a meaningful tool.
To store the ordering data, a ‘magic’ file called $order
is (optionally) stored in each directory in the filesystem.
The file lists all child fileders by name in the given order.
When the children of a fileder are requested (in list_fileders_in
or get_index
, which relies on the former),
all children that are mentioned in $order
are returned in that order,
while all remaining children are sorted alphabetically and appended at the end of the list.
This way the order is guaranteed to be stable even if no $order
file is specified,
or when the $order
file has not been updated after adding new children.
Here is the commented implementation in MoonScript:
list_fileders_in: (path='') =>
-- create a mapping of all child-fileders
-- in 'entries' (name -> path)
entries = {}
for entry_name in lfs.dir @root .. path
continue if '.' == entry_name\sub 1, 1
entry_path = @root .. "#{path}/#{entry_name}"
if 'directory' ~= lfs.attributes entry_path, 'mode'
continue
entries[entry_name] = "#{path}/#{entry_name}"
-- where we will store our sorted list of children
sorted = {}
-- check for existance of the order file
order_file = @root .. "#{path}/$order"
if 'file' == lfs.attributes order_file, 'mode'
for line in io.lines order_file
path = assert entries[line], "entry in $order but not on disk: #{line}"
-- add all $order-entries to the sorted output in the same order they appear.
-- also flag these entries as already added
table.insert sorted, path
sorted[line] = true
-- find the he remaining (non-flagged) entries, sort them alphabetically
-- and then append them to the sorted output list
entries = [path for entry, path in pairs entries when not sorted[entry]]
table.sort entries
for path in *entries
table.insert sorted, path
-- return an iterator over the sorted output
coroutine.wrap ->
for path in *sorted
coroutine.yield path
The interface for reordering fileders is still missing in the code,
and just while writing this I realized that the current implementation is in fact buggy:
when a fileder that is mentioned in $order
is deleted via the stores.fs
API,
it is not removed from $order
, causing an error the next time the fileder is listed.
I will probably get around to fixing both of these problems when I build the corresponding UI.