<% # Nick's web site: Generate directory listing. # # Copyright © 2021 Nick Bowler # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see mydir = rep_uri files = {} @items.find_all(@item[:pattern]).each do |item| t = item[:updated_at] item.reps.each do |rep| next if rep == @rep p = rep_uri(rep) d, f = File.split(p) next unless "#{d}/" == mydir if p =~ %r{/$} displaysize = Dir.children(File.dirname(rep.raw_path)).length - 1 size = displaysize - 1000000 type = :DIR else size = File.size(rep.raw_path) displaysize = human_filesize(size) type = nil end files[f] = { sorttime: if t then t.to_f else 0.0 end, displaytime: if t then t.getutc.strftime "%Y-%m-%d %H:%M\u00a0UTC" end, displaysize: displaysize, size: size, type: type, } end end if @items["#{File.dirname(mydir)}/index.lst"] files[".."] = { type: :UP } end def render_entry(files, key) f = files[key] return <<~EOF #{if f[:type] "#{f[:type]}" end} #{ if key == ".." then "[Parent Directory]" else key end } #{f[:displaytime]} #{f[:displaysize]} EOF end %> <%= parentrow = if files[".."] then "#{render_entry(files, "..")}" end files.delete("..") if parentrow then "#{parentrow}" end %> <% by_name = files.keys.sort{ |a, b| strverscmp(a, b) } by_name.each do |key| entry = render_entry(files, key) %> <%= entry %> <% end %> <% def meta_cmp(files, key, a, b) av, bv = files[a][key], files[b][key] return av <=> bv if av != bv return strverscmp(a, b) end by_date = files.keys.sort { |a, b| meta_cmp(files, :sorttime, a, b) } by_size = files.keys.sort { |a, b| meta_cmp(files, :size, a, b) } listnames = [ "namerev", "datefwd", "daterev", "sizefwd", "sizerev" ] lists = [ by_name.reverse, by_date, by_date.reverse, by_size, by_size.reverse ] if parentrow %> <%= parentrow %> <% end evenmap = (0..(lists.length-1)).map { false } even = false while not (elems = lists.map(&:first)).compact.empty? matches = (0..(lists.length-1)).to_a.keep_if { |x| evenmap[x] == even } if !matches.empty? elems = elems.values_at(*matches).compact mode = elems.group_by{|a| a}.max{|a, b| a[1].length <=> b[1].length}[0] matches = [] lists.each_index do |i| if evenmap[i] == even and lists[i].first.eql? mode lists[i].shift evenmap[i] ^= true evenmap[i] = nil if lists[i].empty? matches << i end end %> <%= render_entry(files, mode) %> <% else %> <% end even ^= true end %>
Name Last Modified Size