Module:Color

From Wiki of ZZT
Revision as of 07:34, 11 January 2021 by Quantum (talk | contribs) (WIP: Add support for different input formats)
Jump to navigation Jump to search

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

local p = {}

local ega_hex_codes = {
	"#000",
	"#00a",
	"#0a0",
	"#0aa",
	"#a00",
	"#a0a",
	"#a50",
	"#aaa",
	"#555",
	"#55f",
	"#5f5",
	"#5ff",
	"#f55",
	"#f5f",
	"#ff5",
	"#fff"
}

local ega_color_names = {
	"black",
	"dark blue",
	"dark green",
	"dark cyan",
	"dark red",
	"dark purple",
	"dark brown",
	"light gray",
	"dark gray",
	"blue",
	"green",
	"cyan",
	"red",
	"purple",
	"yellow",
	"white"
}

function p.swatch(frame)
	local bg = string_to_index(frame.args.bg)
	local fg = string_to_index(frame.args.fg)
	return combo_name(bg, fg)
end

function combo_name(bg, fg)
	local blinking = is_blinking(bg)
	if blinking then
		bg = non_blinking(bg)
	end
	result = index_to_name(fg) .. " on " .. index_to_name(bg)
	if blinking then
		result = "blinking " .. result
	end
	return result
end

function is_blinking(index)
	return index ~= nil and index >= 8
end

function non_blinking(index)
	if index == nil then
		return nil
	elseif index < 8 then
		return index
	end
	return index - 8
end

function index_to_name(i)
	if i == nil then
		return "???"
	end
	return ega_color_names[i + 1]
end

function string_to_index(input)
	-- Handle decimal numbers, hex numbers starting with "0x"
	local number = tonumber(input)
	if number ~= nil then
		if number ~= math.floor(number) or number < 0 or number > 15 then
			return nil
		end
		return number
	end
	
	-- Handle strings
	local name = string.gsub(input, "grey", "gray")
	name = string.gsub(name, "^light ", "")
	local special_cases = {
		["dark yellow"] = "dark brown",
		brown           = "dark brown",
		gray            = "light gray",
	}
	if special_cases[name] ~= nil then
		name = special_cases[name]
	end
	for i = 1, #ega_color_names do
		if name == ega_color_names[i] then
			return i - 1
		end
	end
	return nil
end

return p