Check-in by ben on 2024-09-29 18:39:15
When displaying a user's list of lists, sort by name and id.
INSERTED DELETED
33 12 src/lists/index.dcgi.m4
45 0 src/util.awk
78 12 TOTAL over 2 changed files
Index: src/lists/index.dcgi.m4
==================================================================
--- src/lists/index.dcgi.m4
+++ src/lists/index.dcgi.m4
@@ -8,37 +8,42 @@
include(src/config.awk)
incl(src/api.awk)
incl(src/cgi.awk)
incl(src/util.awk)
-function main( cmd, iaout, id, is_private, item_count, item_id, \
- label, name, url)
+function main( cmd, count, fields, iaout, i, id, is_private, item, \
+ item_count, item_id, label, name, record, records, url)
{
- print search "'s Lists"
- print ""
-
iaout = gettemp()
url = api_ssl_endpoint "/services/users/" search "/lists"
api_request(url, "GET", iaout)
# format list as a gopher directory (menu)
cmd = sprintf("%s <%s 2>&1", cmd_json2tsv, iaout)
FS = "\t"
- name = ""
+ count = 0
+ delete fields[0]
id = 0
is_private = 0
+ item = ""
item_count = 0
item_id = ""
+ name = ""
+ record = ""
+ delete records[0]
while ((cmd | getline) > 0) {
if ($1 == ".value[]" && $2 == "o") {
- # print information for previous list
+ # add information for previous list
if (!is_private && length(name) > 0 && item_count > 0) {
label = shorten_left(name, 50)
- printf "[1|%4d Items: %-50s|%s/list/%%09%s/%d|%s|%s]\n",
- item_count, label, cgipath, search, id, server, port
+ item = sprintf("[1|%4d Items: %-50s|%s/list/%%09%s/%d|%s|%s]", \
+ item_count, label, cgipath, search, id, server, port)
+ record = label "\t" id "\t" item
+ count++
+ records[count] = record
}
} else if ($1 == ".value[].list_name" && $2 == "s") {
name = $3
id = 0
is_private = 0
@@ -53,15 +58,31 @@
item_count++
}
}
close(cmd)
- # print information for previous list
+ # add information for previous list
if (!is_private && length(name) > 0 && item_count > 0) {
label = shorten_left(name, 50)
- printf "[1|%4d Items: %-50s|%s/list/%%09%s/%d|%s|%s]\n",
- item_count, label, cgipath, search, id, server, port
+ item = sprintf("[1|%4d Items: %-50s|%s/list/%%09%s/%d|%s|%s]", \
+ item_count, label, cgipath, search, id, server, port)
+ record = label "\t" id "\t" item
+ count++
+ records[count] = record
+ }
+
+ # sort lists by label and id
+ hsort(records, count)
+
+ print search "'s Lists"
+ print ""
+
+ for (i = 1; i <= count; i++) {
+ record = records[i]
+ split(record, fields, /\t/)
+ item = fields[3]
+ print item
}
print ""
printf "[1|PHAROS|%s|%s|%s]\n", cgipath, server, port
Index: src/util.awk
==================================================================
--- src/util.awk
+++ src/util.awk
@@ -51,10 +51,55 @@
print "Error: mktemp failed, no tmpfile"
exit
}
return retval
}
+
+# heapsort
+#
+# Unstable, and unlike merge and quicksort it relies on random-access
+# so has poorer cache performance.
+#
+# Advantage over quicksort is that its worst-case same as avg: O(n log n)
+#
+# This presentation based on
http://dada.perl.it/shootout/heapsort.lua5.html
+#
+# From: <
https://raw.githubusercontent.com/
+# dubiousjim/awkenough/refs/heads/master/library.awk>
+#
+# Requires 1-based numerically indexed arrays.
+
+function hsort(A, n, c, p, t, i) {
+ if (!n) {
+ n = 1
+ while (n in A) n++
+ n--
+ }
+ i = int(n/2) + 1
+ while (1) {
+ if (i > 1) {
+ i--
+ t = A[i]
+ } else {
+ t = A[n]
+ A[n] = A[1]
+ n--
+ if (n == 1) {
+ A[1] = t
+ return
+ }
+ }
+ for (p = i; (c = 2*p) <= n; p = c) {
+ if ((c < n) && (A[c] < A[c+1]))
+ c++
+ if (t < A[c])
+ A[p] = A[c]
+ else break
+ }
+ A[p] = t
+ }
+}
function human_size(bytes) {
if (bytes > size_gb) {
retval = sprintf("%.1fG", bytes / size_gb)
} else if (bytes > size_mb) {