2
1
Fork 0

Merge branch 'frontend-rewrite'

This commit is contained in:
outfoxxed 2024-11-09 00:14:25 -08:00
commit 52514ee9fb
Signed by: outfoxxed
GPG key ID: 4C88A185FB89301E
5 changed files with 191 additions and 146 deletions

View file

@ -4,6 +4,7 @@ use anyhow::{anyhow, Context};
mod outform; mod outform;
mod parse; mod parse;
mod reformat;
mod resolver; mod resolver;
mod typespec; mod typespec;
@ -133,6 +134,7 @@ hidetitle = true
} }
let index = outform::ModuleIndex { let index = outform::ModuleIndex {
name: module.header.name.to_string(),
description: module.header.description, description: module.header.description,
details: module.details.to_string(), details: module.details.to_string(),
}; };

View file

@ -4,14 +4,23 @@ use serde::Serialize;
#[derive(Debug, Serialize)] #[derive(Debug, Serialize)]
pub struct ModuleIndex { pub struct ModuleIndex {
pub name: String,
pub description: String, pub description: String,
pub details: String, pub details: String,
} }
#[derive(Debug, Serialize)]
pub struct TypeInfo {
pub name: String,
pub module: String,
#[serde(flatten)]
pub details: TypeDetails,
}
#[derive(Debug, Serialize)] #[derive(Debug, Serialize)]
#[serde(rename_all = "lowercase")] #[serde(rename_all = "lowercase")]
#[serde(tag = "type")] #[serde(tag = "type")]
pub enum TypeInfo { pub enum TypeDetails {
Class(ClassInfo), Class(ClassInfo),
Enum(EnumInfo), Enum(EnumInfo),
} }

View file

@ -4,7 +4,10 @@ use anyhow::{anyhow, bail, Context};
use fancy_regex::Regex; use fancy_regex::Regex;
use serde::Deserialize; use serde::Deserialize;
use crate::typespec; use crate::{
reformat::{self, ReformatPass},
typespec,
};
#[derive(Deserialize, Debug)] #[derive(Deserialize, Debug)]
pub struct ModuleInfoHeader { pub struct ModuleInfoHeader {
@ -751,7 +754,6 @@ impl From<InvokableParam<'_>> for typespec::FnParam {
fn parse_details(comment: Comment) -> String { fn parse_details(comment: Comment) -> String {
let mut seen_content = false; let mut seen_content = false;
let mut callout = false;
let mut str = comment let mut str = comment
.text .text
@ -768,127 +770,14 @@ fn parse_details(comment: Comment) -> String {
seen_content |= any; seen_content |= any;
filter filter
}) })
.map(|line| match callout {
true => {
if line.starts_with('>') {
Cow::Borrowed(line[1..].strip_prefix(' ').unwrap_or(&line[1..]))
} else {
callout = false;
Cow::Owned(format!("{{{{< /callout >}}}}\n{line}"))
}
},
false => {
if line.starts_with("> [!") {
let code = line[4..].split_once(']');
if let Some((code, line)) = code {
let code = code.to_lowercase();
callout = true;
return Cow::Owned(format!("{{{{< callout type=\"{code}\" >}}}}\n{line}"))
}
}
return Cow::Borrowed(line);
},
})
.map(|line| {
if line.contains("@@") {
let mut src: &str = &*line;
let mut accum = String::new();
while let Some(i) = src.find("@@") {
accum += &src[..i];
src = &src[i + 2..];
let separators = [
('$', true),
(' ', false),
(',', false),
(';', false),
(':', false),
];
let (mut end, mut ty) = src.chars().enumerate()
.find_map(|(i, char)| {
separators.iter()
.find(|(sc, _)| char == *sc)
.map(|(_, strip)| (i + if *strip { 1 } else { 0 }, &src[..i]))
})
.unwrap_or_else(|| (src.len(), src));
// special case for . as it is contained in valid types as well
if ty.ends_with('.') {
end -= 1;
ty = &ty[..ty.len() - 1];
}
let (ty, member) = match ty.chars().next() {
None => (None, None),
Some(c) if c.is_lowercase() => (None, Some(ty)),
Some(_) => {
let mut split = ty.rsplit_once('.').unwrap_or(("", ty));
let member = split
.1
.chars()
.next()
.unwrap()
.is_lowercase()
.then(|| {
let prop = split.1;
split = split.0.rsplit_once('.').unwrap_or(("", split.0));
prop
})
.unwrap_or("");
let (mut module, name) = split;
if module.is_empty() {
module = comment.module;
}
(Some((module, name)), Some(member))
},
};
let (membertype, membername) = match member {
None => ("", ""),
Some(name) if name.ends_with("()") => ("func", &name[..name.len() - 2]),
Some(name) if name.ends_with("(s)") => ("signal", &name[..name.len() - 3]),
Some(name) if name.is_empty() => ("", ""),
Some(name) => ("prop", name),
};
let ((linktype, module), name) = match ty {
Some((module, name)) => {
let module = match module {
module if module.starts_with("Quickshell") => ("local", module.to_string()),
module => ("qt", format!("qml.{module}")),
};
(module, name)
},
None => (("", String::new()), ""),
};
accum += &format!(
r#"{{{{< qmltypelink type="{linktype}" module="{module}" name="{name}" mtype="{membertype}" mname="{membername}" >}}}}"#
);
src = &src[end..];
}
accum += src;
return Cow::Owned(accum);
} else {
return line;
}
})
.fold(String::new(), |accum, line| accum + line.as_ref() + "\n"); .fold(String::new(), |accum, line| accum + line.as_ref() + "\n");
if callout { let reformat_ctx = reformat::Context {
str += "\n{{< /callout >}}"; module: comment.module,
} };
crate::reformat::GfmQuoteBlocks::new().reformat(&reformat_ctx, &mut str);
crate::reformat::TypeLinks.reformat(&reformat_ctx, &mut str);
str str
} }

140
typegen/src/reformat.rs Normal file
View file

@ -0,0 +1,140 @@
use std::borrow::Cow;
use fancy_regex::Regex;
pub struct Context<'a> {
pub module: &'a str,
}
pub trait ReformatPass {
fn reformat(&self, context: &Context, text: &mut String);
}
pub struct GfmQuoteBlocks {
callout_regex: Regex,
}
impl GfmQuoteBlocks {
pub fn new() -> Self {
Self {
callout_regex: Regex::new(r#">\s+\[!(?<type>\w+)]\s+(?=\w)"#).unwrap()
}
}
}
impl ReformatPass for GfmQuoteBlocks {
fn reformat(&self, _: &Context, text: &mut String) {
*text = text.replace("> [!INFO]", "> [!NOTE]");
*text = self.callout_regex.replace_all(text, "> [!$type]\n> ").to_string();
}
}
pub struct TypeLinks;
impl ReformatPass for TypeLinks {
fn reformat(&self ,context: &Context, text: &mut String) {
let lines = text.lines().map(|line| {
if line.contains("@@") {
let mut src: &str = &*line;
let mut accum = String::new();
while let Some(i) = src.find("@@") {
accum += &src[..i];
src = &src[i + 2..];
let separators = [
('$', true),
(' ', false),
(',', false),
(';', false),
(':', false),
];
let (mut end, mut ty) = src
.chars()
.enumerate()
.find_map(|(i, char)| {
separators
.iter()
.find(|(sc, _)| char == *sc)
.map(|(_, strip)| (i + if *strip { 1 } else { 0 }, &src[..i]))
})
.unwrap_or_else(|| (src.len(), src));
// special case for . as it is contained in valid types as well
if ty.ends_with('.') {
end -= 1;
ty = &ty[..ty.len() - 1];
}
let (ty, member) = match ty.chars().next() {
None => (None, None),
Some(c) if c.is_lowercase() => (None, Some(ty)),
Some(_) => {
let mut split = ty.rsplit_once('.').unwrap_or(("", ty));
let member = split
.1
.chars()
.next()
.unwrap()
.is_lowercase()
.then(|| {
let prop = split.1;
split = split.0.rsplit_once('.').unwrap_or(("", split.0));
prop
})
.unwrap_or("");
let (mut module, name) = split;
if module.is_empty() {
module = context.module;
}
(Some((module, name)), Some(member))
},
};
let (membertype, membername) = match member {
None => ("", ""),
Some(name) if name.ends_with("()") => ("func", &name[..name.len() - 2]),
Some(name) if name.ends_with("(s)") => ("signal", &name[..name.len() - 3]),
Some(name) if name.is_empty() => ("", ""),
Some(name) => ("prop", name),
};
accum += "TYPE";
if let Some((module, name)) = ty {
if module.starts_with("Quickshell") {
accum += "99MQS";
} else {
accum += "99MQT_qml";
}
accum = module
.split('.')
.fold(accum, |accum, next| accum + "_" + next)
+ "99N" + name;
}
if !membername.is_empty() {
accum += &format!("99V{membername}99T{membertype}");
}
accum += "99TYPE";
src = &src[end..];
}
accum += src;
return Cow::Owned(accum);
} else {
return Cow::Borrowed(line);
}
});
*text = lines.fold(String::new(), |accum, line| accum + line.as_ref() + "\n");
}
}

View file

@ -235,37 +235,42 @@ pub fn resolve_types(
None => HashMap::new(), None => HashMap::new(),
}; };
let type_ = outform::ClassInfo { let type_ = outform::TypeInfo {
superclass, name: mapping.name.clone(),
description: class.description.clone(), module: mapping.module.clone().unwrap(),
details: class.details.clone(), details: outform::TypeDetails::Class(outform::ClassInfo {
flags: { superclass,
let mut flags = Vec::new(); description: class.description.clone(),
details: class.details.clone(),
flags: {
let mut flags = Vec::new();
if coreenum.is_some() { if coreenum.is_some() {
flags.push(Flag::Enum); flags.push(Flag::Enum);
} else if class.singleton { } else if class.singleton {
flags.push(Flag::Singleton); flags.push(Flag::Singleton);
} else if class.uncreatable { } else if class.uncreatable {
flags.push(Flag::Uncreatable); flags.push(Flag::Uncreatable);
} }
flags flags
}, },
properties, properties,
functions, functions,
signals, signals,
variants, variants,
}),
}; };
outtypes.insert(mapping.name.clone(), outform::TypeInfo::Class(type_)); outtypes.insert(mapping.name.clone(), type_);
} }
for enum_ in typespec.enums { for enum_ in typespec.enums {
if enum_.module.as_ref().map(|v| v as &str) == Some(module) { if enum_.module.as_ref().map(|v| v as &str) == Some(module) {
outtypes.insert( outtypes.insert(enum_.name.clone(), outform::TypeInfo {
enum_.name, name: enum_.name,
outform::TypeInfo::Enum(outform::EnumInfo { module: enum_.module.unwrap(),
details: outform::TypeDetails::Enum(outform::EnumInfo {
description: enum_.description, description: enum_.description,
details: enum_.details, details: enum_.details,
variants: enum_ variants: enum_
@ -278,7 +283,7 @@ pub fn resolve_types(
}) })
.collect(), .collect(),
}), }),
); });
} }
} }