Capefeather (talk | contribs) (Re-inserted ender) |
Capefeather (talk | contribs) (putting multiple splits into p.SplitTable) |
||
(35 intermediate revisions by the same user not shown) | |||
Line 40: | Line 40: | ||
-- Gets the contents of a single row. |
-- Gets the contents of a single row. |
||
return fetchRows(wikitable, row, row) |
return fetchRows(wikitable, row, row) |
||
+ | end |
||
+ | |||
+ | local function findFirstRow(wikitable, str) |
||
+ | -- Finds the first row in the wikitable containing the requested string str. |
||
+ | local rowP = rowPositions(wikitable) |
||
+ | local pos, _ = string.find(wikitable, str) |
||
+ | local i = 1 |
||
+ | while rowP[i] < pos do |
||
+ | i = i + 1 |
||
+ | end |
||
+ | return i - 1 |
||
end |
end |
||
local function columns(wikitable) |
local function columns(wikitable) |
||
-- Gets the names of the columns. |
-- Gets the names of the columns. |
||
− | names = {} |
+ | local names = {} |
− | posTable = delimiterPositions(wikitable, "!", "|-") |
+ | local posTable = delimiterPositions(wikitable, "!", "|-") |
for n = 1, posTable[2] do |
for n = 1, posTable[2] do |
||
names[n] = string.sub(wikitable, posTable[1][n] + 1, posTable[1][n + 1] - 1) |
names[n] = string.sub(wikitable, posTable[1][n] + 1, posTable[1][n + 1] - 1) |
||
Line 52: | Line 63: | ||
end |
end |
||
− | function p. |
+ | function p.tableRange(frame) |
− | -- Constructs a subtable of the given table containing the specified |
+ | -- Constructs a subtable of the given table containing the specified range of rows. |
+ | -- {{#invoke:table|tableRange|(table)|3|7}} produces a table using rows 3-7 of the original table. |
||
local wikitable = frame.args[1] |
local wikitable = frame.args[1] |
||
local rowP = rowPositions(wikitable) |
local rowP = rowPositions(wikitable) |
||
Line 62: | Line 74: | ||
local body = fetchRows(wikitable, firstRow, lastRow) |
local body = fetchRows(wikitable, firstRow, lastRow) |
||
return header .. body .. "}" |
return header .. body .. "}" |
||
+ | end |
||
+ | |||
+ | function p.tableRangeByString(frame) |
||
+ | -- Like tableRange, but searches for two strings to determine the range. |
||
+ | -- {{#invoke:table|tableRangeByString|(table)|1970|1980}} produces a table starting from the first row that contains 1970 to the first row that contains 1980. |
||
+ | local wikitable = frame.args[1] |
||
+ | local rowP = rowPositions(wikitable) |
||
+ | local length = rows(wikitable) |
||
+ | local firstRow = findFirstRow(wikitable, frame.args[2]) or 1 |
||
+ | local lastRow = findFirstRow(wikitable, frame.args[3]) - 1 or length - 1 |
||
+ | local header = string.sub(wikitable, 1, rowP[1] - 1) |
||
+ | local body = fetchRows(wikitable, firstRow, lastRow) |
||
+ | return header .. body .. "}" |
||
+ | end |
||
+ | |||
+ | function p.splitTable(frame) |
||
+ | -- Splits a table along a specified row. |
||
+ | -- Example: {{#invoke:table|splitTable|(table)|130|==Header==}} |
||
+ | local wikitable = frame.args[1] |
||
+ | local rowP = rowPositions(wikitable) |
||
+ | local length = rows(wikitable) |
||
+ | local header = string.sub(wikitable, 1, rowP[1] - 1) |
||
+ | local prevMarker = 1 |
||
+ | local nextMarker = 1 |
||
+ | local result = "" |
||
+ | for n = 1, math.floor(#frame.args / 2) do |
||
+ | prevMarker = nextMarker |
||
+ | nextMarker = math.max(frame.args[2 * n], 1) |
||
+ | local tween = frame.args[2 * n + 1] or "" |
||
+ | local body = fetchRows(wikitable, prevMarker, nextMarker) |
||
+ | result = result .. header .. body .. "}" .. tween |
||
+ | end |
||
+ | return result .. header .. fetchRows(wikitable, nextMarker, length) .. "}" |
||
end |
end |
||
Revision as of 03:46, 11 July 2020
Module for searching and manipulating wikitables.
-- Module for searching and manipulating wikitables.
local p = {}
local function delimiterPositions(wikitable, delimiter, ender)
-- Gets the positions and number of instances of a delimiter in a table's wikitext. By "position", we mean that, for example, the letter "e" in "hello" is in position 2, and the pattern "ll" in "hello" is in position 3.
local positions = {}
local index = 1
for pos = 1, string.len(wikitable) - 1 do
if string.sub(wikitable, pos, pos + string.len(delimiter) - 1) == delimiter then
positions[index] = pos
index = index + 1
elseif string.sub(wikitable, pos, pos + string.len(ender) - 1) == ender then
positions[index] = pos
break
end
end
return {positions, index - 1}
end
local function rowPositions(wikitable)
-- Gets the positions of instances of the row delimiter |- in a table's wikitext.
return delimiterPositions(wikitable, "|-", "|}")[1]
end
local function rows(wikitable)
-- Gets the number of rows in a table's wikitext.
return delimiterPositions(wikitable, "|-", "|}")[2]
end
local function fetchRows(wikitable, firstRow, lastRow)
-- Gets the contents of the rows between firstRow and lastRow inclusively. For example, fetchRows(wikitable, 3, 7) returns rows 3, 4, 5, 6, and 7 of the table.
local rowP = rowPositions(wikitable)
return string.sub(wikitable, rowP[firstRow], rowP[lastRow + 1])
end
local function fetchOneRow(wikitable, row)
-- Gets the contents of a single row.
return fetchRows(wikitable, row, row)
end
local function findFirstRow(wikitable, str)
-- Finds the first row in the wikitable containing the requested string str.
local rowP = rowPositions(wikitable)
local pos, _ = string.find(wikitable, str)
local i = 1
while rowP[i] < pos do
i = i + 1
end
return i - 1
end
local function columns(wikitable)
-- Gets the names of the columns.
local names = {}
local posTable = delimiterPositions(wikitable, "!", "|-")
for n = 1, posTable[2] do
names[n] = string.sub(wikitable, posTable[1][n] + 1, posTable[1][n + 1] - 1)
end
return names
end
function p.tableRange(frame)
-- Constructs a subtable of the given table containing the specified range of rows.
-- {{#invoke:table|tableRange|(table)|3|7}} produces a table using rows 3-7 of the original table.
local wikitable = frame.args[1]
local rowP = rowPositions(wikitable)
local length = rows(wikitable)
local firstRow = math.max(frame.args[2], 1) or 1
local lastRow = math.min(frame.args[3], length) or length
local header = string.sub(wikitable, 1, rowP[1] - 1)
local body = fetchRows(wikitable, firstRow, lastRow)
return header .. body .. "}"
end
function p.tableRangeByString(frame)
-- Like tableRange, but searches for two strings to determine the range.
-- {{#invoke:table|tableRangeByString|(table)|1970|1980}} produces a table starting from the first row that contains 1970 to the first row that contains 1980.
local wikitable = frame.args[1]
local rowP = rowPositions(wikitable)
local length = rows(wikitable)
local firstRow = findFirstRow(wikitable, frame.args[2]) or 1
local lastRow = findFirstRow(wikitable, frame.args[3]) - 1 or length - 1
local header = string.sub(wikitable, 1, rowP[1] - 1)
local body = fetchRows(wikitable, firstRow, lastRow)
return header .. body .. "}"
end
function p.splitTable(frame)
-- Splits a table along a specified row.
-- Example: {{#invoke:table|splitTable|(table)|130|==Header==}}
local wikitable = frame.args[1]
local rowP = rowPositions(wikitable)
local length = rows(wikitable)
local header = string.sub(wikitable, 1, rowP[1] - 1)
local prevMarker = 1
local nextMarker = 1
local result = ""
for n = 1, math.floor(#frame.args / 2) do
prevMarker = nextMarker
nextMarker = math.max(frame.args[2 * n], 1)
local tween = frame.args[2 * n + 1] or ""
local body = fetchRows(wikitable, prevMarker, nextMarker)
result = result .. header .. body .. "}" .. tween
end
return result .. header .. fetchRows(wikitable, nextMarker, length) .. "}"
end
return p
--[[Category:Modules]]