Module:Unimplemented
Module:Unimplemented attempts to work around Semantic MediaWiki's limitations by deriving a list of unimplemented tasks from multiple SMW inline queries. This script could then be invoked from a suitable template.
Usage[edit]
Invoke Module:Unimplemented
with one of the tasks
, drafts
or omitted
functions and the target language.
Here we've used TypeScript
as the example language.
{{#invoke:Unimplemented|tasks|TypeScript}}
{{#invoke:Unimplemented|drafts|TypeScript}}
{{#invoke:Unimplemented|omitted|TypeScript}}
Combined unimplemented task page[edit]
Unimplemented|page|<language>
combines unimplemented tasks, draft tasks and omitted tasks into one function call. It includes sub headings for each list and formats those lists grouped by the first character in a task's title.
{{#invoke:Unimplemented|page|TypeScript}}
Invoking from a template[edit]
When invoking Module:Unimplemented from a template and using template parameters as arguments, it is probably a good idea to wrap each call to #invoke
in <includeonly></includeonly>
. This should prevent unnecessary function calls and improve page load times when viewing the template page directly.
See Control template inclusion for more information.
Example[edit]
The following example shows the output of the page
function for the Go language.
{{#invoke:Unimplemented|page|Go}}
Tasks not implemented in Go
B
C
D
E
F
G
H
I
P
R
S
T
W
Draft tasks not implemented in Go
3
A
B
C
- CLI-based maze-game
- Compiler/Preprocessor
- Compiler/Simple file inclusion pre processor
- Convert CSV records to TSV
- Countdown
- Create an executable for a program in an interpreted language
- Create your own text control codes
- Cross compilation
- Cycles of a permutation
D
- Dating agency
- Day of the week of Christmas and New Year
- Diophantine linear system solving
- Divide a rectangle into a number of unequal triangles
E
F
G
I
J
K
L
M
N
O
P
- Pairs with common factors
- Pan base non-primes
- Prime reciprocal sum
- Primes: n*2^m+1
- Protecting Memory Secrets
R
S
- Sanitize user input
- Sealed classes and methods
- Segmentation fault protection
- Selection bias in clinical sciences
- Simulated optics experiment/Data analysis
- Simulated optics experiment/Simulator
- Singly-linked list/Reversal
- Solve equations with substitution method
- Solve hanging lantern problem
- Sorensen–Dice coefficient
- Statistics/Chi-squared distribution
- Sub-unit squares
- Super-Poulet numbers
T
U
V
W
- Wasteful, equidigital and frugal numbers
- Wave function collapse
- WebGL rotating F
- WiktionaryDumps to words
- Worthwhile task shaving
Z
Tasks omitted from Go
local p = {}
local SEP = "|"
local column_style = "-webkit-column-count: 3; -moz-column-count: 3; " ..
"column-count: 3; -webkit-column-width: 24em; " ..
"-moz-column-width: 24em; column-width: 24em;"
local list_style = "margin-top: 0; margin-bottom: 0;"
local list_item_style = "-webkit-column-break-inside: avoid; " ..
"page-break-inside: avoid; " ..
"break-inside: avoid-column;"
local column_div = '<div class="mw-category mw-category-columns" style="' .. column_style .. '">'
local group_list = '<ul style="' .. list_style .. '">'
local group_list_item = '<li style="' .. list_item_style .. '">'
--- Return the sequence of elements in `a` that are not in `b`.
-- Assumes that `a` and `b` are "arrays" with distinct items
-- that are already sorted. If `a` or `b` are empty, return `a`
-- without copying it.
local function difference(a, b)
local size_a = #a
local size_b = #b
if size_a == 0 or size_b == 0 then return a end
local i = 1
local j = 1
local result = {}
while i <= size_a and j <= size_b do
local a_i = a[i]
local b_j = b[j]
if a_i == b_j then
i = i + 1
j = j + 1
elseif a_i < b_j then
table.insert(result, a_i)
i = i + 1
else
j = j + 1
end
end
-- and the rest of a, if a is longer than b
while i <= size_a do
table.insert(result, a[i])
i = i + 1
end
return result
end
--- Split the input string on the configured separator token `SEP`.
--
-- Don't be tempted to replace this with `mw.text.split`. As of Feb 2023,
-- `mw.text.split` is particularly slow, causing this this module to
-- timeout when invoked.
--
-- Returns an array of strings split on `SEP`.
local function split(str)
local result = {}
for match in string.gmatch(str, "([^" .. SEP .. "]+)") do
table.insert(result, match)
end
table.sort(result)
return result
end
--- Call `#ask` repeatedly until we've got all results defined by `args`.
-- This works around the SMW result limit of 500 records.
--
-- Returns the concatenation of `#ask` results separated by `args.sep`.
-- Assumes `args.format` is "plainlist" and `args.sep` is set. It is not
-- safe to reuse `args` after calling this function.
local function ask_all(args)
local frame = mw.getCurrentFrame()
local limit = tonumber(args.limit or 500)
local offset = tonumber(args.offset or 0)
local strings = {}
local response = ""
args.limit = tostring(limit) -- TODO: do we need to cast to string?
args.offset = tostring(offset)
repeat
response = frame:callParserFunction { name = "#ask", args = args }
offset = offset + limit
args.offset = tostring(offset)
if #response > 0 then
table.insert(strings, args.sep)
table.insert(strings, response)
end
until #response == 0
return table.concat(strings)
end
--- Return an array of task titles implemented in the given language.
-- Includes draft tasks.
local function language_tasks(language)
local args = {
"[[Implemented in language::" .. language .. "]]",
"?Title",
format = "plainlist",
limit = "500",
link = "none",
sep = SEP,
searchlabel = ""
}
return split(ask_all(args))
end
--- Return an array of task titles omitted from the given language.
-- Includes draft tasks.
local function omitted_language_tasks(language)
local args = {
"[[Category:" .. language .. "/Omit]]",
"?Title",
format = "plainlist",
limit = "500",
link = "none",
sep = SEP,
searchlabel = ""
}
return split(ask_all(args))
end
-- Return an array of task titles in the Programming Tasks category.
local function programming_tasks()
local args = {
"[[Category:Programming Tasks]]",
"?Title",
format = "plainlist",
limit = "500",
link = "none",
sep = SEP,
searchlabel = ""
}
return split(ask_all(args))
end
-- Return an array of task titles in the Draft Programming Tasks category.
local function draft_tasks()
local args = {
"[[Category:Draft Programming Tasks]]",
"?Title",
format = "plainlist",
limit = "500",
link = "none",
sep = SEP,
searchlabel = ""
}
return split(ask_all(args))
end
--- Format an array of task titles as a continuous unordered list.
local function format(tasks)
local strings = {}
for _, task in ipairs(tasks) do
table.insert(strings, "* [[" .. task .. "]]")
end
return table.concat(strings, "\n")
end
--- Format an array of task titles into lists grouped by their first
-- character.
local function format_with_group_headings(tasks)
if #tasks == 0 then
return ""
end
local wiki_markup = {}
local ch = ""
for _, task in ipairs(tasks) do
local task_ch = string.upper(string.sub(task, 1, 1))
if ch ~= task_ch then
table.insert(wiki_markup, "=== " .. task_ch .. " ===")
ch = task_ch
end
table.insert(wiki_markup, "* [[" .. task .. "]]")
end
return table.concat(wiki_markup, "\n")
end
--- Format an array of tasks titles into columns and groups, just like
-- regular MediaWiki category pages.
local function format_multi_column_groups(tasks)
if #tasks == 0 then
return ""
end
local content = { column_div }
local group_ch = ""
for i, task in ipairs(tasks) do
local task_ch = string.upper(string.sub(task, 1, 1))
if group_ch ~= task_ch then
if i > 1 then
table.insert(content, '</ul>')
table.insert(content, '</div>') -- /.mw-category-group
end
table.insert(content, '<div class="mw-category-group">')
table.insert(content, "=== " .. task_ch .. " ===")
table.insert(content, group_list)
group_ch = task_ch
end
table.insert(content, group_list_item .. "[[" .. task .. "]]</li>")
end
table.insert(content, "</div>") -- /.mw-category-group
table.insert(content, "</div>") -- /.mw-category
return table.concat(content, "\n")
end
--- Return the target language given a frame object.
local function language_arg(frame)
local language = frame.args[1]
if language == nil then
error("too few arguments, a programming language is required", 2)
end
return language
end
--- Display a list of programming tasks not implemented in a given language.
-- Usage: `{{#invoke:Unimplemented|tasks|<language>}}` where `<language>` is
-- the Rosetta Code language category name.
--
-- For example `{{#invoke:Unimplemented|tasks|TypeScript}}`
function p.tasks(frame)
local language = language_arg(frame)
local implemented = language_tasks(language)
local omitted = omitted_language_tasks(language)
local tasks = programming_tasks()
local unimplemented = difference(difference(tasks, implemented), omitted)
return format(unimplemented)
end
--- Display a list of draft programming tasks not implemented in a given
-- language. Usage: `{{#invoke:Unimplemented|drafts|<language>}}` where
-- `<language>` is the Rosetta Code language category name.
--
-- For example `{{#invoke:Unimplemented|drafts|TypeScript}}`
function p.drafts(frame)
local language = language_arg(frame)
local implemented = language_tasks(language)
local omitted = omitted_language_tasks(language)
local tasks = draft_tasks()
local unimplemented = difference(difference(tasks, implemented), omitted)
return format(unimplemented)
end
--- Display a list of tasks omitted from a given language, including draft tasks.
-- Usage: `{{#invoke:Unimplemented|omitted|<language>}}` where `<language>`
-- is the Rosetta Code language category name.
--
-- For example `{{#invoke:Unimplemented|omitted|TypeScript}}`
function p.omitted(frame)
local language = language_arg(frame)
local omitted = omitted_language_tasks(language)
return format(omitted)
end
--- Display lists of unimplemented tasks, unimplemented drafts and omitted
-- tasks for a given language, including wiki headings.
--
-- Usage: `{{#invoke:Unimplemented|page|<language>}}` where `<language>`is the
-- Rosetta Code language category name.
--
-- For example `{{#invoke:Unimplemented|page|TypeScript}}`
function p.page(frame)
local language = language_arg(frame)
local implemented = language_tasks(language)
local omitted = omitted_language_tasks(language)
local unimplemented_tasks = difference(
difference(programming_tasks(), implemented),
omitted
)
local unimplemented_drafts = difference(
difference(draft_tasks(), implemented),
omitted
)
local wiki_markup = {
"==Tasks not implemented in " .. language .. "==",
format_with_group_headings(unimplemented_tasks),
"==Draft tasks not implemented in " .. language .. "==",
format_with_group_headings(unimplemented_drafts),
"==Tasks omitted from " .. language .. "==",
format_with_group_headings(omitted)
}
return table.concat(wiki_markup, "\n")
end
return p