Jump to content

Module:Pseudocode

From Encyclopedia of Algorithms

Documentation for this module may be created at Module:Pseudocode/doc

local p = {}

local keywords = {
	['for'] = true, ['to'] = true, ['downto'] = true, ['while'] = true,
	['repeat'] = true, ['until'] = true, ['if'] = true, ['then'] = true,
	['else'] = true, ['elseif'] = true, ['do'] = true, ['return'] = true,
	['and'] = true, ['or'] = true, ['not'] = true, ['break'] = true,
	['each'] = true, ['in'] = true, ['error'] = true, ['nil'] = true,
	['true'] = true, ['false'] = true,
}

local LT, GT, AMP, HYP = '\1', '\2', '\3', '\4'
local DASH = '\45'

local function levelOf(line)
	local tabs = line:match('^(\t*)')
	if #tabs > 0 then
		return #tabs
	end
	return math.floor(#(line:match('^( *)')) / 4)
end

local function classify(word)
	local isProc = word:find(HYP, 1, true) ~= nil
	local plain = word:gsub(HYP, DASH)
	local lower = mw.ustring.lower(plain)
	if keywords[lower] then
		return "'''" .. lower .. "'''"
	end
	if isProc or (mw.ustring.len(plain) > 1 and plain:match('^%u%l')) then
		return '<span class="eoa-proc">' .. plain .. '</span>'
	end
	return '<span class="eoa-var">' .. plain .. '</span>'
end

local function formatLine(line)
	local out = line:gsub('^[ \t]+', '')
	out = out:gsub('&', AMP):gsub('<', LT):gsub('>', GT)
	out = out:gsub('(%a)%-(%a)', '%1' .. HYP .. '%2')
	out = out:gsub('%a[%w' .. HYP .. ']*', classify)
	out = out:gsub(AMP, '&amp;'):gsub(LT, '&lt;'):gsub(GT, '&gt;')
	return out
end

function p.line(frame)
	local text = frame.args[1] or ''
	if text == '' then
		return ''
	end
	return formatLine(text)
end

function p.render(frame)
	local code = frame:getParent().args.code or ''
	local list = mw.html.create('ol')
	for raw in code:gmatch('[^\n]+') do
		if raw:match('%S') then
			local item = list:tag('li')
			local depth = levelOf(raw)
			if depth > 0 then
				item:tag('span')
					:css('display', 'inline-block')
					:css('width', (depth * 1.7) .. 'em')
					:done()
			end
			item:wikitext(formatLine(raw))
		end
	end
	return tostring(list)
end

return p