Capefeather (talk | contribs) No edit summary |
Capefeather (talk | contribs) (putting multiple splits into p.SplitTable) |
||
(27 intermediate revisions by the same user not shown) | |||
Line 42: | Line 42: | ||
end |
end |
||
− | local function |
+ | local function findFirstRow(wikitable, str) |
− | -- |
+ | -- Finds the first row in the wikitable containing the requested string str. |
⚫ | |||
− | return delimiterPositions(rowtext, "|", "$")[1] |
||
⚫ | |||
⚫ | |||
⚫ | |||
− | |||
⚫ | |||
− | local function columns(rowtext) |
||
− | + | i = i + 1 |
|
− | return delimiterPositions(rowtext, "|", "$")[2] |
||
⚫ | |||
− | |||
− | local function findFirstRow(wikitable, str, col) |
||
− | newCol = col or 0 |
||
⚫ | |||
⚫ | |||
− | while string.find(string.sub(wikitable, pos), str) ~= nil do |
||
⚫ | |||
⚫ | |||
⚫ | |||
− | candidate = n - 1 |
||
− | if newCol == 0 then |
||
− | return candidate |
||
− | else |
||
− | colP = columnPositions(fetchOneRow(wikitable, candidate)) |
||
− | nextColP = colP[newCol + 1] or columns(fetchOneRow(wikitable, candidate)) |
||
− | if colP[newCol] < p and colP[newCol + 1] > p then |
||
− | return candidate |
||
− | end |
||
− | end |
||
− | pos = rowP[n] |
||
− | break |
||
− | end |
||
− | end |
||
end |
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 87: | Line 63: | ||
end |
end |
||
− | function p. |
+ | function p.tableRange(frame) |
− | -- Constructs a subtable of the given table containing the specified range of rows |
+ | -- 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 99: | Line 76: | ||
end |
end |
||
− | function p. |
+ | function p.tableRangeByString(frame) |
+ | -- Like tableRange, but searches for two strings to determine the range. |
||
− | -- Like p.partialTable but with row ranges specified using table contents. Usage: {{#invoke:table|conditionalPartialTable|(table)|first=|last=|col=(column number (optional))}} |
||
− | -- |
+ | -- {{#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 wikitable = frame.args[1] |
||
local rowP = rowPositions(wikitable) |
local rowP = rowPositions(wikitable) |
||
local length = rows(wikitable) |
local length = rows(wikitable) |
||
− | local firstRow = findFirstRow(wikitable, frame.args[ |
+ | local firstRow = findFirstRow(wikitable, frame.args[2]) or 1 |
− | local lastRow = findFirstRow(wikitable, frame.args[ |
+ | local lastRow = findFirstRow(wikitable, frame.args[3]) - 1 or length - 1 |
− | lastRow = lastRow - 1 |
||
local header = string.sub(wikitable, 1, rowP[1] - 1) |
local header = string.sub(wikitable, 1, rowP[1] - 1) |
||
local body = fetchRows(wikitable, firstRow, lastRow) |
local body = fetchRows(wikitable, firstRow, lastRow) |
||
return header .. body .. "}" |
return header .. body .. "}" |
||
⚫ | |||
+ | |||
+ | 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 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 |
||
⚫ | |||
+ | 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]]