typegen: add shorthand for type/property links
This commit is contained in:
parent
11ff70f1a8
commit
db5c3aa3f4
|
@ -13,5 +13,16 @@
|
||||||
{{- $of = printf "<%s>" (partial "qmltype.html" .of) }}
|
{{- $of = printf "<%s>" (partial "qmltype.html" .of) }}
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
|
|
||||||
<a href="{{ $link }}">{{ .name }}</a>{{ $of | safeHTML -}}
|
{{- $member := "" -}}
|
||||||
|
|
||||||
|
{{- if .prop -}}
|
||||||
|
{{- $member = printf ".%s" .prop -}}
|
||||||
|
{{- if eq .type "qt" -}}
|
||||||
|
{{- $link = printf "%s#%s-prop" $link .prop -}}
|
||||||
|
{{- else if eq .type "local" -}}
|
||||||
|
{{- $link = printf "%s#prop.%s" $link .prop -}}
|
||||||
|
{{- end -}}
|
||||||
|
{{- end -}}
|
||||||
|
|
||||||
|
<a href="{{ $link }}">{{ .name }}{{ $member }}</a>{{ $of | safeHTML -}}
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
|
|
|
@ -36,7 +36,8 @@ fn main() -> anyhow::Result<()> {
|
||||||
.collect::<Result<HashMap<_, _>, _>>()?;
|
.collect::<Result<HashMap<_, _>, _>>()?;
|
||||||
|
|
||||||
let parser = parse::Parser::new();
|
let parser = parse::Parser::new();
|
||||||
let mut ctx = parse::ParseContext::default();
|
let mut ctx = parse::ParseContext::new(&module.header.name);
|
||||||
|
|
||||||
texts
|
texts
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(header, text)| {
|
.map(|(header, text)| {
|
||||||
|
|
|
@ -33,6 +33,18 @@ pub fn parse_module(text: &str) -> anyhow::Result<ModuleInfo> {
|
||||||
Ok(ModuleInfo { header, details })
|
Ok(ModuleInfo { header, details })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
pub struct Comment<'a> {
|
||||||
|
pub text: &'a str,
|
||||||
|
pub module: &'a str,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Comment<'a> {
|
||||||
|
fn new(text: &'a str, module: &'a str) -> Self {
|
||||||
|
Self { text, module }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ClassInfo<'a> {
|
pub struct ClassInfo<'a> {
|
||||||
pub type_: ClassType,
|
pub type_: ClassType,
|
||||||
|
@ -41,7 +53,7 @@ pub struct ClassInfo<'a> {
|
||||||
pub superclass: Option<&'a str>,
|
pub superclass: Option<&'a str>,
|
||||||
pub singleton: bool,
|
pub singleton: bool,
|
||||||
pub uncreatable: bool,
|
pub uncreatable: bool,
|
||||||
pub comment: Option<&'a str>,
|
pub comment: Option<Comment<'a>>,
|
||||||
pub properties: Vec<Property<'a>>,
|
pub properties: Vec<Property<'a>>,
|
||||||
pub invokables: Vec<Invokable<'a>>,
|
pub invokables: Vec<Invokable<'a>>,
|
||||||
pub signals: Vec<Signal<'a>>,
|
pub signals: Vec<Signal<'a>>,
|
||||||
|
@ -58,7 +70,7 @@ pub enum ClassType {
|
||||||
pub struct Property<'a> {
|
pub struct Property<'a> {
|
||||||
pub type_: &'a str,
|
pub type_: &'a str,
|
||||||
pub name: &'a str,
|
pub name: &'a str,
|
||||||
pub comment: Option<&'a str>,
|
pub comment: Option<Comment<'a>>,
|
||||||
pub readable: bool,
|
pub readable: bool,
|
||||||
pub writable: bool,
|
pub writable: bool,
|
||||||
pub default: bool,
|
pub default: bool,
|
||||||
|
@ -68,14 +80,14 @@ pub struct Property<'a> {
|
||||||
pub struct Invokable<'a> {
|
pub struct Invokable<'a> {
|
||||||
pub name: &'a str,
|
pub name: &'a str,
|
||||||
pub ret: &'a str,
|
pub ret: &'a str,
|
||||||
pub comment: Option<&'a str>,
|
pub comment: Option<Comment<'a>>,
|
||||||
pub params: Vec<InvokableParam<'a>>,
|
pub params: Vec<InvokableParam<'a>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Signal<'a> {
|
pub struct Signal<'a> {
|
||||||
pub name: &'a str,
|
pub name: &'a str,
|
||||||
pub comment: Option<&'a str>,
|
pub comment: Option<Comment<'a>>,
|
||||||
pub params: Vec<InvokableParam<'a>>,
|
pub params: Vec<InvokableParam<'a>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,14 +102,14 @@ pub struct EnumInfo<'a> {
|
||||||
pub namespace: &'a str,
|
pub namespace: &'a str,
|
||||||
pub enum_name: &'a str,
|
pub enum_name: &'a str,
|
||||||
pub qml_name: &'a str,
|
pub qml_name: &'a str,
|
||||||
pub comment: Option<&'a str>,
|
pub comment: Option<Comment<'a>>,
|
||||||
pub variants: Vec<Variant<'a>>,
|
pub variants: Vec<Variant<'a>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub struct Variant<'a> {
|
pub struct Variant<'a> {
|
||||||
pub name: &'a str,
|
pub name: &'a str,
|
||||||
pub comment: Option<&'a str>,
|
pub comment: Option<Comment<'a>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Parser {
|
pub struct Parser {
|
||||||
|
@ -116,13 +128,15 @@ pub struct Parser {
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ParseContext<'a> {
|
pub struct ParseContext<'a> {
|
||||||
|
pub module: &'a str,
|
||||||
pub classes: Vec<ClassInfo<'a>>,
|
pub classes: Vec<ClassInfo<'a>>,
|
||||||
pub enums: Vec<EnumInfo<'a>>,
|
pub enums: Vec<EnumInfo<'a>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for ParseContext<'_> {
|
impl<'a> ParseContext<'a> {
|
||||||
fn default() -> Self {
|
pub fn new(module: &'a str) -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
module,
|
||||||
classes: Vec::new(),
|
classes: Vec::new(),
|
||||||
enums: Vec::new(),
|
enums: Vec::new(),
|
||||||
}
|
}
|
||||||
|
@ -223,7 +237,7 @@ impl Parser {
|
||||||
properties.push(Property {
|
properties.push(Property {
|
||||||
type_: prop.name("type").unwrap().as_str(),
|
type_: prop.name("type").unwrap().as_str(),
|
||||||
name: prop.name("name").unwrap().as_str(),
|
name: prop.name("name").unwrap().as_str(),
|
||||||
comment,
|
comment: comment.map(|v| Comment::new(v, ctx.module)),
|
||||||
readable: read || member,
|
readable: read || member,
|
||||||
writable: !constant && (write || member),
|
writable: !constant && (write || member),
|
||||||
default: false,
|
default: false,
|
||||||
|
@ -279,7 +293,7 @@ impl Parser {
|
||||||
invokables.push(Invokable {
|
invokables.push(Invokable {
|
||||||
name,
|
name,
|
||||||
ret: type_,
|
ret: type_,
|
||||||
comment,
|
comment: comment.map(|v| Comment::new(v, ctx.module)),
|
||||||
params,
|
params,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -317,7 +331,7 @@ impl Parser {
|
||||||
|
|
||||||
signals.push(Signal {
|
signals.push(Signal {
|
||||||
name,
|
name,
|
||||||
comment,
|
comment: comment.map(|v| Comment::new(v, ctx.module)),
|
||||||
params,
|
params,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -329,13 +343,13 @@ impl Parser {
|
||||||
let comment = enum_.name("comment").map(|m| m.as_str());
|
let comment = enum_.name("comment").map(|m| m.as_str());
|
||||||
let enum_name = enum_.name("enum_name").unwrap().as_str();
|
let enum_name = enum_.name("enum_name").unwrap().as_str();
|
||||||
let body = enum_.name("body").unwrap().as_str();
|
let body = enum_.name("body").unwrap().as_str();
|
||||||
let variants = self.parse_enum_variants(body)?;
|
let variants = self.parse_enum_variants(body, ctx)?;
|
||||||
|
|
||||||
enums.push(EnumInfo {
|
enums.push(EnumInfo {
|
||||||
namespace: name,
|
namespace: name,
|
||||||
enum_name,
|
enum_name,
|
||||||
qml_name: enum_name,
|
qml_name: enum_name,
|
||||||
comment,
|
comment: comment.map(|v| Comment::new(v, ctx.module)),
|
||||||
variants,
|
variants,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -353,7 +367,7 @@ impl Parser {
|
||||||
superclass,
|
superclass,
|
||||||
singleton,
|
singleton,
|
||||||
uncreatable,
|
uncreatable,
|
||||||
comment,
|
comment: comment.map(|v| Comment::new(v, ctx.module)),
|
||||||
properties,
|
properties,
|
||||||
invokables,
|
invokables,
|
||||||
signals,
|
signals,
|
||||||
|
@ -376,13 +390,13 @@ impl Parser {
|
||||||
.map(|m| m.as_str())
|
.map(|m| m.as_str())
|
||||||
.unwrap_or(namespace);
|
.unwrap_or(namespace);
|
||||||
let body = enum_.name("body").unwrap().as_str();
|
let body = enum_.name("body").unwrap().as_str();
|
||||||
let variants = self.parse_enum_variants(body)?;
|
let variants = self.parse_enum_variants(body, ctx)?;
|
||||||
|
|
||||||
ctx.enums.push(EnumInfo {
|
ctx.enums.push(EnumInfo {
|
||||||
namespace,
|
namespace,
|
||||||
enum_name,
|
enum_name,
|
||||||
qml_name,
|
qml_name,
|
||||||
comment,
|
comment: comment.map(|v| Comment::new(v, ctx.module)),
|
||||||
variants,
|
variants,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -390,7 +404,11 @@ impl Parser {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_enum_variants<'a>(&self, body: &'a str) -> anyhow::Result<Vec<Variant<'a>>> {
|
pub fn parse_enum_variants<'a>(
|
||||||
|
&self,
|
||||||
|
body: &'a str,
|
||||||
|
ctx: &ParseContext<'a>,
|
||||||
|
) -> anyhow::Result<Vec<Variant<'a>>> {
|
||||||
let mut variants = Vec::new();
|
let mut variants = Vec::new();
|
||||||
|
|
||||||
for variant in self.enum_variant_regex.captures_iter(body) {
|
for variant in self.enum_variant_regex.captures_iter(body) {
|
||||||
|
@ -399,7 +417,10 @@ impl Parser {
|
||||||
let comment = variant.name("comment").map(|m| m.as_str());
|
let comment = variant.name("comment").map(|m| m.as_str());
|
||||||
let name = variant.name("name").unwrap().as_str();
|
let name = variant.name("name").unwrap().as_str();
|
||||||
|
|
||||||
variants.push(Variant { name, comment });
|
variants.push(Variant {
|
||||||
|
name,
|
||||||
|
comment: comment.map(|v| Comment::new(v, ctx.module)),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(variants)
|
Ok(variants)
|
||||||
|
@ -575,11 +596,12 @@ impl From<InvokableParam<'_>> for typespec::FnParam {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_details(text: &str) -> String {
|
fn parse_details(comment: Comment) -> String {
|
||||||
let mut seen_content = false;
|
let mut seen_content = false;
|
||||||
let mut callout = false;
|
let mut callout = false;
|
||||||
|
|
||||||
let mut str = text
|
let mut str = comment
|
||||||
|
.text
|
||||||
.lines()
|
.lines()
|
||||||
.map(|line| {
|
.map(|line| {
|
||||||
line.trim()
|
line.trim()
|
||||||
|
@ -616,6 +638,63 @@ fn parse_details(text: &str) -> String {
|
||||||
return Cow::Borrowed(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 endmk = src.find('$');
|
||||||
|
let endsp = src.find(' ');
|
||||||
|
|
||||||
|
let (end, ty) = match (endmk, endsp) {
|
||||||
|
(Some(i), _) if i < endsp.unwrap_or(usize::MAX) => (i + 1, &src[..i]),
|
||||||
|
(_, Some(i)) => (i, &src[..i]),
|
||||||
|
_ => (src.len(), src),
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut split = ty.rsplit_once('.').unwrap_or(("", ty));
|
||||||
|
|
||||||
|
let prop = 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
let (linktype, module) = match module.starts_with("Quickshell") {
|
||||||
|
true => ("local", module.to_string()),
|
||||||
|
false => ("qt", format!("qml.{module}")),
|
||||||
|
};
|
||||||
|
|
||||||
|
accum += &format!(
|
||||||
|
r#"{{{{< qmltypelink type="{linktype}" module="{module}" name="{name}" prop="{prop}" >}}}}"#
|
||||||
|
);
|
||||||
|
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 {
|
if callout {
|
||||||
|
@ -625,8 +704,8 @@ fn parse_details(text: &str) -> String {
|
||||||
str
|
str
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_details_desc(text: &str) -> (Option<String>, Option<String>) {
|
fn parse_details_desc(comment: Comment) -> (Option<String>, Option<String>) {
|
||||||
let details = parse_details(text);
|
let details = parse_details(comment);
|
||||||
if details.starts_with('!') {
|
if details.starts_with('!') {
|
||||||
match details[1..].split_once('\n') {
|
match details[1..].split_once('\n') {
|
||||||
Some((desc, details)) => (
|
Some((desc, details)) => (
|
||||||
|
|
Loading…
Reference in a new issue