Module:Unimplemented builds lists of links to programming tasks that have not yet been implemented in a programming language. This module is invoked from Template:Unimpl_Page.

We work around Semantic MediaWiki's limitations by deriving a list of unimplemented tasks from multiple SMW inline queries.

Usage

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

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

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.


local p = {} local SEP = "|"  --- 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   --- 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