+local function mk_completion_test(str, sub_ok, casei_ok)
+ if not str then
+ return function(s) return true end
+ end
+
+ local function mk(str, sub_ok)
+ if sub_ok then
+ return function(s) return string.find(s, str, 1, true) end
+ else
+ local len=string.len(str)
+ return function(s) return string.sub(s, 1, len)==str end
+ end
+ end
+
+ local casei=(casei_ok and mod_query.get().caseicompl)
+
+ if not casei then
+ return mk(str, sub_ok)
+ else
+ local fn=mk(string.lower(str), sub_ok)
+ return function(s) return fn(string.lower(s)) end
+ end
+end
+
+
+local function mk_completion_add(entries, str, sub_ok, casei_ok)
+ local tst=mk_completion_test(str, sub_ok, casei_ok)
+
+ return function(s)
+ if s and tst(s) then
+ table.insert(entries, s)
+ end
+ end
+end
+
+
+function mod_query.complete_keys(list, str, sub_ok, casei_ok)
+ local results={}
+ local test_add=mk_completion_add(results, str, sub_ok, casei_ok)
+
+ for m, _ in pairs(list) do
+ test_add(m)
+ end
+
+ return results
+end
+
+
+function mod_query.complete_name(str, iter)
+ local sub_ok_first=true
+ local casei_ok=true
+ local entries={}
+ local tst_add=mk_completion_add(entries, str, sub_ok_first, casei_ok)
+
+ iter(function(reg)
+ tst_add(reg:name())
+ return true
+ end)
+
+ if #entries==0 and not sub_ok_first then
+ local tst_add2=mk_completion_add(entries, str, true, casei_ok)
+ iter(function(reg)
+ tst_add2(reg:name())
+ return true
+ end)
+ end
+
+ return entries
+end
+
+
+function mod_query.make_completor(completefn)
+ local function completor(cp, str, point)
+ cp:set_completions(completefn(str, point))
+ end
+ return completor
+end
+
+