lune/scripts/font_enum_map.luau
2023-07-22 14:46:40 +02:00

193 lines
5.3 KiB
Lua

--!nocheck
-- NOTE: This must be ran in Roblox Studio to get up-to-date font values
local contents = ""
contents ..= "\ntype FontData = (&'static str, FontWeight, FontStyle);\n"
local ENUM_IMPLEMENTATION = [[
#[derive(Debug, Clone, Copy, PartialEq)]
pub(crate) enum <<ENUM_NAME>> {
<<ENUM_NAMES>>
}
impl <<ENUM_NAME>> {
pub(crate) fn as_<<NUMBER_TYPE>>(&self) -> <<NUMBER_TYPE>> {
match self {
<<ENUM_TO_NUMBERS>>
}
}
pub(crate) fn from_<<NUMBER_TYPE>>(n: <<NUMBER_TYPE>>) -> Option<Self> {
match n {
<<NUMBERS_TO_ENUM>>
_ => None,
}
}
}
impl Default for <<ENUM_NAME>> {
fn default() -> Self {
Self::<<DEFAULT_NAME>>
}
}
impl std::str::FromStr for <<ENUM_NAME>> {
type Err = &'static str;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
<<STRINGS_TO_ENUM>>
_ => Err("Unknown <<ENUM_NAME>>"),
}
}
}
impl std::fmt::Display for <<ENUM_NAME>> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"{}",
match self {
<<ENUM_TO_STRINGS>>
}
)
}
}
impl<'lua> FromLua<'lua> for <<ENUM_NAME>> {
fn from_lua(lua_value: LuaValue<'lua>, _: &'lua Lua) -> LuaResult<Self> {
let mut message = None;
if let LuaValue::UserData(ud) = &lua_value {
let value = ud.borrow::<EnumItem>()?;
if value.parent.desc.name == "<<ENUM_NAME>>" {
if let Ok(value) = <<ENUM_NAME>>::from_str(&value.name) {
return Ok(value);
} else {
message = Some(format!(
"Found unknown Enum.<<ENUM_NAME>> value '{}'",
value.name
));
}
} else {
message = Some(format!(
"Expected Enum.<<ENUM_NAME>>, got Enum.{}",
value.parent.desc.name
));
}
}
Err(LuaError::FromLuaConversionError {
from: lua_value.type_name(),
to: "Enum.<<ENUM_NAME>>",
message,
})
}
}
impl<'lua> ToLua<'lua> for <<ENUM_NAME>> {
fn to_lua(self, lua: &'lua Lua) -> LuaResult<LuaValue<'lua>> {
match EnumItem::from_enum_name_and_name("<<ENUM_NAME>>", self.to_string()) {
Some(enum_item) => Ok(LuaValue::UserData(lua.create_userdata(enum_item)?)),
None => Err(LuaError::ToLuaConversionError {
from: "<<ENUM_NAME>>",
to: "EnumItem",
message: Some(format!("Found unknown Enum.<<ENUM_NAME>> value '{}'", self)),
}),
}
}
}
]]
-- FontWeight enum and implementation
local function makeRustEnum(enum, default, numType: string)
local name = tostring(enum)
name = string.gsub(name, "^Enum.", "")
local defaultName = tostring(default)
defaultName = string.gsub(defaultName, "^Enum.", "")
defaultName = string.gsub(defaultName, "^" .. name .. ".", "")
local enumNames = ""
local enumToNumbers = ""
local numbersToEnum = ""
local stringsToEnum = ""
local enumToStrings = ""
for _, enum in enum:GetEnumItems() do
enumNames ..= `\n{enum.Name},`
enumToNumbers ..= `\nSelf::{enum.Name} => {enum.Value},`
numbersToEnum ..= `\n{enum.Value} => Some(Self::{enum.Name}),`
stringsToEnum ..= `\n"{enum.Name}" => Ok(Self::{enum.Name}),`
enumToStrings ..= `\nSelf::{enum.Name} => "{enum.Name}",`
end
local mappings: { [string]: string } = {
["<<ENUM_NAME>>"] = name,
["<<DEFAULT_NAME>>"] = defaultName,
["<<NUMBER_TYPE>>"] = numType,
["<<ENUM_NAMES>>"] = enumNames,
["<<ENUM_TO_NUMBERS>>"] = enumToNumbers,
["<<ENUM_TO_STRINGS>>"] = enumToStrings,
["<<NUMBERS_TO_ENUM>>"] = numbersToEnum,
["<<STRINGS_TO_ENUM>>"] = stringsToEnum,
}
local result = ENUM_IMPLEMENTATION
for key, replacement in mappings do
result = string.gsub(result, "(\t*)" .. key, function(tabbing)
local spacing = string.gsub(tabbing, "\t", " ")
local inner = string.gsub(replacement, "\n", "\n" .. spacing)
inner = string.gsub(inner, "^\n+", "")
return inner
end)
end
return result
end
contents ..= makeRustEnum(Enum.FontWeight, Enum.FontWeight.Regular, "u16")
contents ..= "\n"
contents ..= makeRustEnum(Enum.FontStyle, Enum.FontStyle.Normal, "u8")
contents ..= "\n"
-- Font constant map from enum to font data
local longestNameLen = 0
local longestFamilyLen = 0
local longestWeightLen = 0
for _, enum in Enum.Font:GetEnumItems() do
longestNameLen = math.max(longestNameLen, #enum.Name)
if enum ~= Enum.Font.Unknown then
local font = Font.fromEnum(enum)
longestFamilyLen = math.max(longestFamilyLen, #font.Family)
longestWeightLen = math.max(longestWeightLen, #font.Weight.Name)
end
end
contents ..= "\n#[rustfmt::skip]\nconst FONT_ENUM_MAP: &[(&str, Option<FontData>)] = &[\n"
for _, enum in Enum.Font:GetEnumItems() do
if enum == Enum.Font.Unknown then
contents ..= string.format(
' ("Unknown",%s None),\n',
string.rep(" ", longestNameLen - #enum.Name)
)
else
local font = Font.fromEnum(enum)
contents ..= string.format(
' ("%s",%s Some(("%s",%s FontWeight::%s,%s FontStyle::%s))),\n',
enum.Name,
string.rep(" ", longestNameLen - #enum.Name),
font.Family,
string.rep(" ", longestFamilyLen - #font.Family),
font.Weight.Name,
string.rep(" ", longestWeightLen - #font.Weight.Name),
font.Style.Name
)
end
end
contents ..= "];\n"
print(contents)