X-Git-Url: http://git.draconx.ca/gitweb/homepage.git/blobdiff_plain/5aa756ee68dc2134b6acac8a66af2f1c14521721..e7306bc0bbfea36e6414684b00ad4ef1c7269aed:/layouts/listing.erb
diff --git a/layouts/listing.erb b/layouts/listing.erb
new file mode 100644
index 0000000..02017a0
--- /dev/null
+++ b/layouts/listing.erb
@@ -0,0 +1,150 @@
+<%
+# 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 UTC" 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]
+ ""
+ end} |
+ #{
+ if key == ".." then "[Parent Directory]" else key end
+ } |
+ #{f[:displaytime]} |
+ #{f[:displaysize]} |
+ EOF
+end
+%>
+
+
+
+ |
+ Name |
+ Last Modified |
+ Size |
+
+
+
+<%=
+ 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
+%>
+
+