From db73ccf0d1fa6d8732e59f37b5b3ecf3c790154c Mon Sep 17 00:00:00 2001 From: outfoxxed Date: Mon, 22 Jul 2024 15:00:09 -0700 Subject: [PATCH 01/13] typegen: add module names --- typegen/src/main.rs | 1 + typegen/src/outform.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/typegen/src/main.rs b/typegen/src/main.rs index d1736ab..a14255c 100644 --- a/typegen/src/main.rs +++ b/typegen/src/main.rs @@ -107,6 +107,7 @@ hidetitle = true } let index = outform::ModuleIndex { + name: module.header.name.to_string(), description: module.header.description, details: module.details.to_string(), }; diff --git a/typegen/src/outform.rs b/typegen/src/outform.rs index 185cc5b..a7910f6 100644 --- a/typegen/src/outform.rs +++ b/typegen/src/outform.rs @@ -4,6 +4,7 @@ use serde::Serialize; #[derive(Debug, Serialize)] pub struct ModuleIndex { + pub name: String, pub description: String, pub details: String, } From 4b9a0e9ff218be74e80615aaea6bf39d42b00f77 Mon Sep 17 00:00:00 2001 From: outfoxxed Date: Mon, 22 Jul 2024 15:24:43 -0700 Subject: [PATCH 02/13] typegen: add module and name fields to type files --- typegen/src/outform.rs | 10 +++++++- typegen/src/resolver.rs | 53 ++++++++++++++++++++++------------------- 2 files changed, 38 insertions(+), 25 deletions(-) diff --git a/typegen/src/outform.rs b/typegen/src/outform.rs index a7910f6..641d64c 100644 --- a/typegen/src/outform.rs +++ b/typegen/src/outform.rs @@ -9,10 +9,18 @@ pub struct ModuleIndex { pub details: String, } +#[derive(Debug, Serialize)] +pub struct TypeInfo { + pub name: String, + pub module: String, + #[serde(flatten)] + pub details: TypeDetails, +} + #[derive(Debug, Serialize)] #[serde(rename_all = "lowercase")] #[serde(tag = "type")] -pub enum TypeInfo { +pub enum TypeDetails { Class(ClassInfo), Enum(EnumInfo), } diff --git a/typegen/src/resolver.rs b/typegen/src/resolver.rs index 8c2f609..984c582 100644 --- a/typegen/src/resolver.rs +++ b/typegen/src/resolver.rs @@ -211,37 +211,42 @@ pub fn resolve_types( None => HashMap::new(), }; - let type_ = outform::ClassInfo { - superclass, - description: class.description.clone(), - details: class.details.clone(), - flags: { - let mut flags = Vec::new(); + let type_ = outform::TypeInfo { + name: mapping.name.clone(), + module: mapping.module.clone().unwrap(), + details: outform::TypeDetails::Class(outform::ClassInfo { + superclass, + description: class.description.clone(), + details: class.details.clone(), + flags: { + let mut flags = Vec::new(); - if coreenum.is_some() { - flags.push(Flag::Enum); - } else if class.singleton { - flags.push(Flag::Singleton); - } else if class.uncreatable { - flags.push(Flag::Uncreatable); - } + if coreenum.is_some() { + flags.push(Flag::Enum); + } else if class.singleton { + flags.push(Flag::Singleton); + } else if class.uncreatable { + flags.push(Flag::Uncreatable); + } - flags - }, - properties, - functions, - signals, - variants, + flags + }, + properties, + functions, + signals, + variants, + }), }; - outtypes.insert(mapping.name.clone(), outform::TypeInfo::Class(type_)); + outtypes.insert(mapping.name.clone(), type_); } for enum_ in typespec.enums { if enum_.module.as_ref().map(|v| v as &str) == Some(module) { - outtypes.insert( - enum_.name, - outform::TypeInfo::Enum(outform::EnumInfo { + outtypes.insert(enum_.name.clone(), outform::TypeInfo { + name: enum_.name, + module: enum_.module.unwrap(), + details: outform::TypeDetails::Enum(outform::EnumInfo { description: enum_.description, details: enum_.details, variants: enum_ @@ -254,7 +259,7 @@ pub fn resolve_types( }) .collect(), }), - ); + }); } } From 89a533173b69b24430d3e42a0e98de29fce76c33 Mon Sep 17 00:00:00 2001 From: outfoxxed Date: Tue, 23 Jul 2024 22:08:20 -0700 Subject: [PATCH 03/13] typegen: detect flags in enum namespaces Currently doesn't mark them as flags or work outside of enum namespaces, just a baseline so they show up at all. --- typegen/src/parse.rs | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/typegen/src/parse.rs b/typegen/src/parse.rs index 2a8d7f8..172d7f8 100644 --- a/typegen/src/parse.rs +++ b/typegen/src/parse.rs @@ -154,7 +154,7 @@ impl Parser { fn_param_regex: Regex::new(r#"(const\s+)?(?(\w|::|<|>)+\*?)&?\s+(?\w+)(,|$)"#).unwrap(), signals_regex: Regex::new(r#"signals:(?(\s*(\s*///.*\s*)*void .*;)*)"#).unwrap(), defaultprop_classinfo_regex: Regex::new(r#"^\s*"DefaultProperty", "(?.+)"\s*$"#).unwrap(), - enum_ns_regex: Regex::new(r#"(?(\s*\/\/\/.*\n)+)?\s*namespace (?\w+)\s*\{[\s\S]*?(QML_ELEMENT|QML_NAMED_ELEMENT\((?\w+)\));[\s\S]*?enum\s*(?\w+)\s*\{(?[\s\S]*?)\};[\s\S]*?\}"#).unwrap(), + enum_ns_regex: Regex::new(r#"(?(\s*\/\/\/.*\n)+)?\s*namespace (?\w+)\s*\{(?[\s\S]*?(QML_ELEMENT|QML_NAMED_ELEMENT\((?\w+)\));[\s\S]*?enum\s*(?\w+)\s*\{(?[\s\S]*?)\};[\s\S]*?)\}"#).unwrap(), enum_class_regex: Regex::new(r#"(?(\s*\/\/\/.*\n)+)?\s*enum\s*(?\w+)\s*\{(?[\s\S]*?)\};\s+Q_ENUM\(.+\);"#).unwrap(), enum_variant_regex: Regex::new(r#"(?(\s*\/\/\/.*\n)+)?\s*(?\w+)\s*=\s*.+,"#).unwrap(), } @@ -384,14 +384,41 @@ impl Parser { let comment = enum_.name("comment").map(|m| m.as_str()); let namespace = enum_.name("namespace").unwrap().as_str(); - let enum_name = enum_.name("enum_name").unwrap().as_str(); + let mut enum_name = enum_.name("enum_name").unwrap().as_str(); let qml_name = enum_ .name("qml_name") .map(|m| m.as_str()) .unwrap_or(namespace); + let nsbody = enum_.name("nsbody").unwrap().as_str(); let body = enum_.name("body").unwrap().as_str(); let variants = self.parse_enum_variants(body, ctx)?; + for macro_ in self.macro_regex.captures_iter(nsbody) { + let macro_ = macro_?; + + let type_ = macro_.name("type").unwrap().as_str(); + let args = macro_.name("args").map(|m| m.as_str()); + + (|| { + match type_ { + "Q_DECLARE_FLAGS" => { + enum_name = args + .expect("Q_DECLARE_FLAGS must have arguments") + .split_once(',') + .expect("Q_DECLARE_FLAGS must have two arguments") + .0 + .trim(); + }, + _ => {}, + } + + Ok::<_, anyhow::Error>(()) + })() + .with_context(|| { + format!("while parsing macro `{}`", macro_.get(0).unwrap().as_str()) + })?; + } + ctx.enums.push(EnumInfo { namespace, enum_name, From 18debdc9db241693d22a1cf94f33ed877cef36c2 Mon Sep 17 00:00:00 2001 From: outfoxxed Date: Tue, 23 Jul 2024 22:14:00 -0700 Subject: [PATCH 04/13] nix: update lockfile --- flake.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/flake.lock b/flake.lock index b8a3733..d105a7c 100644 --- a/flake.lock +++ b/flake.lock @@ -22,11 +22,11 @@ ] }, "locked": { - "lastModified": 1720770600, - "narHash": "sha256-Ouic1xV4pJns1rbw6wnee9fO4VWkcv73hxSLQkPYabk=", + "lastModified": 1721797947, + "narHash": "sha256-vZRlP0Z5b5weGUYW//IjGrgjkS8YPrBoZb4K4DddeXQ=", "ref": "refs/heads/master", - "rev": "d630cc7f76b56ad3ebe084159df6beab48db9866", - "revCount": 247, + "rev": "ebfa8ec448c7d4ee2f1bf6b463f1dbf2e65db060", + "revCount": 260, "type": "git", "url": "https://git.outfoxxed.me/outfoxxed/quickshell" }, From 419ebe0cd3beae9041cfa7e8fea44d4f4e7753dd Mon Sep 17 00:00:00 2001 From: outfoxxed Date: Tue, 23 Jul 2024 22:16:46 -0700 Subject: [PATCH 05/13] typegen: add missing qmltypelink shortcode --- layouts/shortcodes/qmltypelink.html | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 layouts/shortcodes/qmltypelink.html diff --git a/layouts/shortcodes/qmltypelink.html b/layouts/shortcodes/qmltypelink.html new file mode 100644 index 0000000..018ebd5 --- /dev/null +++ b/layouts/shortcodes/qmltypelink.html @@ -0,0 +1,9 @@ +{{- $params := dict + "type" (.Get "type") + "module" (.Get "module") + "name" (.Get "name") + "mtype" (.Get "mtype") + "mname" (.Get "mname") +-}} + +{{- partial "qmltype.html" $params -}} From 08cad1f0e83a5cab6feaddac6cff32b0b7abef87 Mon Sep 17 00:00:00 2001 From: outfoxxed Date: Tue, 23 Jul 2024 22:21:02 -0700 Subject: [PATCH 06/13] template: fix module page headers --- layouts/docs/list.html | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 layouts/docs/list.html diff --git a/layouts/docs/list.html b/layouts/docs/list.html new file mode 100644 index 0000000..fc5c73a --- /dev/null +++ b/layouts/docs/list.html @@ -0,0 +1,18 @@ +{{ define "main" }} +
+ {{ partial "sidebar.html" (dict "context" .) }} + {{ partial "toc.html" . }} +
+
+ {{ partial "breadcrumb.html" . }} +
+ {{- if not (isset .Params "hidetitle") -}}

{{ .Title }}

{{- end -}} + {{ .Content }} +
+ {{ partial "components/last-updated.html" . }} + {{ partial "components/pager.html" . }} + {{ partial "components/comments.html" . }} +
+
+
+{{ end }} From 63c4583bd5ceccee48121953706489a5b6d8a807 Mon Sep 17 00:00:00 2001 From: outfoxxed Date: Fri, 26 Jul 2024 10:08:22 -0700 Subject: [PATCH 07/13] nix: update lockfile --- flake.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/flake.lock b/flake.lock index d105a7c..018946e 100644 --- a/flake.lock +++ b/flake.lock @@ -22,11 +22,11 @@ ] }, "locked": { - "lastModified": 1721797947, - "narHash": "sha256-vZRlP0Z5b5weGUYW//IjGrgjkS8YPrBoZb4K4DddeXQ=", + "lastModified": 1722013616, + "narHash": "sha256-77wE/fN8+7H6WqnIYOHmDkb20HP28i+qXJam9Wao5Vw=", "ref": "refs/heads/master", - "rev": "ebfa8ec448c7d4ee2f1bf6b463f1dbf2e65db060", - "revCount": 260, + "rev": "4b2e569e942de2d52354d9e81951f6e31d5329dc", + "revCount": 267, "type": "git", "url": "https://git.outfoxxed.me/outfoxxed/quickshell" }, From e574e37bfc956f9e3093281dd8d3ce63c4ef6f05 Mon Sep 17 00:00:00 2001 From: outfoxxed Date: Tue, 30 Jul 2024 23:25:39 -0700 Subject: [PATCH 08/13] nix: update lockfile --- flake.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/flake.lock b/flake.lock index 018946e..6ff7c93 100644 --- a/flake.lock +++ b/flake.lock @@ -22,11 +22,11 @@ ] }, "locked": { - "lastModified": 1722013616, - "narHash": "sha256-77wE/fN8+7H6WqnIYOHmDkb20HP28i+qXJam9Wao5Vw=", + "lastModified": 1722407094, + "narHash": "sha256-XiYaugzfTRp4ggL7q7Crzs5ZqnNlyTbFuiQsmzmGZ5E=", "ref": "refs/heads/master", - "rev": "4b2e569e942de2d52354d9e81951f6e31d5329dc", - "revCount": 267, + "rev": "76744c903ac4c07e5dfe4b9e32d72af8237afff5", + "revCount": 274, "type": "git", "url": "https://git.outfoxxed.me/outfoxxed/quickshell" }, From fcc4533b2b85de3d34c6b3125e91f6b030ec09af Mon Sep 17 00:00:00 2001 From: outfoxxed Date: Mon, 9 Sep 2024 03:15:53 -0700 Subject: [PATCH 09/13] typegen: accept //@ Q_INVOKABLE for doc-only functions --- typegen/src/parse.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/typegen/src/parse.rs b/typegen/src/parse.rs index 172d7f8..32337d6 100644 --- a/typegen/src/parse.rs +++ b/typegen/src/parse.rs @@ -149,7 +149,7 @@ impl Parser { class_regex: Regex::new(r#"(?(\s*\/\/\/.*\n)+)?\s*class\s+(?\w+)(?:\s*:\s*public\s+((?\w+)(<.+>)?)(\s*,(\s*\w+)*)*)?\s*\{(?[\s\S]*?)(?!};\s*Q_ENUM)};"#).unwrap(), macro_regex: Regex::new(r#"(?(\s*\/\/\/.*\n)+)?\s*(?QSDOC_HIDE\s)?(?(Q|QML|QSDOC)_\w+)\s*(\(\s*(?.*)\s*\))?;"#).unwrap(), property_regex: Regex::new(r#"^\s*(?(\w|::|, |<|>|\*)+)\*?\s+(?\w+)(\s+(MEMBER\s+(?\w+)|READ\s+(?\w+)|WRITE\s+(?\w+)|NOTIFY\s+(?\w+)|(?CONSTANT)))+\s*$"#).unwrap(), - fn_regex: Regex::new(r#"(?(\s*\/\/\/.*\n)+)?\s*Q_INVOKABLE\s+(\[\[.*\]\]\s+)?(static\s+)?(?(\w|::|<|>)+\*?)\s+(?\w+)\((?[\s\S]*?)\)(\s*const)?;"#).unwrap(), + fn_regex: Regex::new(r#"(?(\s*\/\/\/.*\n)+)?\s*(\/\/@\s+)?Q_INVOKABLE\s+(\[\[.*\]\]\s+)?(static\s+)?(?(\w|::|<|>)+\*?)\s+(?\w+)\((?[\s\S]*?)\)(\s*const)?;"#).unwrap(), signal_regex: Regex::new(r#"(?(\s*\/\/\/.*\n)+)?\s*void\s+(?\w+)\((?[\s\S]*?)\);"#).unwrap(), fn_param_regex: Regex::new(r#"(const\s+)?(?(\w|::|<|>)+\*?)&?\s+(?\w+)(,|$)"#).unwrap(), signals_regex: Regex::new(r#"signals:(?(\s*(\s*///.*\s*)*void .*;)*)"#).unwrap(), From 43ccb1ea874425606c69a4b67e02e61e38701d65 Mon Sep 17 00:00:00 2001 From: outfoxxed Date: Mon, 9 Sep 2024 03:16:43 -0700 Subject: [PATCH 10/13] nix: update lockfile --- flake.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/flake.lock b/flake.lock index 6ff7c93..2b27804 100644 --- a/flake.lock +++ b/flake.lock @@ -22,11 +22,11 @@ ] }, "locked": { - "lastModified": 1722407094, - "narHash": "sha256-XiYaugzfTRp4ggL7q7Crzs5ZqnNlyTbFuiQsmzmGZ5E=", + "lastModified": 1725876916, + "narHash": "sha256-3SDm2pV1ZIQHqIhAe7BjuXhNdVyzcxPiwaFyqE8ODdc=", "ref": "refs/heads/master", - "rev": "76744c903ac4c07e5dfe4b9e32d72af8237afff5", - "revCount": 274, + "rev": "85be3861ceadba6e3d877a64cade15015ea0c96f", + "revCount": 324, "type": "git", "url": "https://git.outfoxxed.me/outfoxxed/quickshell" }, From b78b75f006938188a0e393b2631838b4403f3441 Mon Sep 17 00:00:00 2001 From: outfoxxed Date: Mon, 22 Jul 2024 15:00:09 -0700 Subject: [PATCH 11/13] typegen: add module names --- typegen/src/main.rs | 1 + typegen/src/outform.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/typegen/src/main.rs b/typegen/src/main.rs index d1736ab..a14255c 100644 --- a/typegen/src/main.rs +++ b/typegen/src/main.rs @@ -107,6 +107,7 @@ hidetitle = true } let index = outform::ModuleIndex { + name: module.header.name.to_string(), description: module.header.description, details: module.details.to_string(), }; diff --git a/typegen/src/outform.rs b/typegen/src/outform.rs index 185cc5b..a7910f6 100644 --- a/typegen/src/outform.rs +++ b/typegen/src/outform.rs @@ -4,6 +4,7 @@ use serde::Serialize; #[derive(Debug, Serialize)] pub struct ModuleIndex { + pub name: String, pub description: String, pub details: String, } From 997eb9e87643fa3b509b3f8c2c812298c65bea5e Mon Sep 17 00:00:00 2001 From: outfoxxed Date: Mon, 22 Jul 2024 15:24:43 -0700 Subject: [PATCH 12/13] typegen: add module and name fields to type files --- typegen/src/outform.rs | 10 +++++++- typegen/src/resolver.rs | 53 ++++++++++++++++++++++------------------- 2 files changed, 38 insertions(+), 25 deletions(-) diff --git a/typegen/src/outform.rs b/typegen/src/outform.rs index a7910f6..641d64c 100644 --- a/typegen/src/outform.rs +++ b/typegen/src/outform.rs @@ -9,10 +9,18 @@ pub struct ModuleIndex { pub details: String, } +#[derive(Debug, Serialize)] +pub struct TypeInfo { + pub name: String, + pub module: String, + #[serde(flatten)] + pub details: TypeDetails, +} + #[derive(Debug, Serialize)] #[serde(rename_all = "lowercase")] #[serde(tag = "type")] -pub enum TypeInfo { +pub enum TypeDetails { Class(ClassInfo), Enum(EnumInfo), } diff --git a/typegen/src/resolver.rs b/typegen/src/resolver.rs index 8c2f609..984c582 100644 --- a/typegen/src/resolver.rs +++ b/typegen/src/resolver.rs @@ -211,37 +211,42 @@ pub fn resolve_types( None => HashMap::new(), }; - let type_ = outform::ClassInfo { - superclass, - description: class.description.clone(), - details: class.details.clone(), - flags: { - let mut flags = Vec::new(); + let type_ = outform::TypeInfo { + name: mapping.name.clone(), + module: mapping.module.clone().unwrap(), + details: outform::TypeDetails::Class(outform::ClassInfo { + superclass, + description: class.description.clone(), + details: class.details.clone(), + flags: { + let mut flags = Vec::new(); - if coreenum.is_some() { - flags.push(Flag::Enum); - } else if class.singleton { - flags.push(Flag::Singleton); - } else if class.uncreatable { - flags.push(Flag::Uncreatable); - } + if coreenum.is_some() { + flags.push(Flag::Enum); + } else if class.singleton { + flags.push(Flag::Singleton); + } else if class.uncreatable { + flags.push(Flag::Uncreatable); + } - flags - }, - properties, - functions, - signals, - variants, + flags + }, + properties, + functions, + signals, + variants, + }), }; - outtypes.insert(mapping.name.clone(), outform::TypeInfo::Class(type_)); + outtypes.insert(mapping.name.clone(), type_); } for enum_ in typespec.enums { if enum_.module.as_ref().map(|v| v as &str) == Some(module) { - outtypes.insert( - enum_.name, - outform::TypeInfo::Enum(outform::EnumInfo { + outtypes.insert(enum_.name.clone(), outform::TypeInfo { + name: enum_.name, + module: enum_.module.unwrap(), + details: outform::TypeDetails::Enum(outform::EnumInfo { description: enum_.description, details: enum_.details, variants: enum_ @@ -254,7 +259,7 @@ pub fn resolve_types( }) .collect(), }), - ); + }); } } From 0c55789923252215be77e81fdea7a52ec4504eee Mon Sep 17 00:00:00 2001 From: outfoxxed Date: Mon, 9 Sep 2024 23:17:28 -0700 Subject: [PATCH 13/13] typegen: restructure type links and callouts for new site --- typegen/src/main.rs | 1 + typegen/src/parse.rs | 131 +++------------------------------------- typegen/src/reformat.rs | 127 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 138 insertions(+), 121 deletions(-) create mode 100644 typegen/src/reformat.rs diff --git a/typegen/src/main.rs b/typegen/src/main.rs index a14255c..0e22cc9 100644 --- a/typegen/src/main.rs +++ b/typegen/src/main.rs @@ -4,6 +4,7 @@ use anyhow::{anyhow, Context}; mod outform; mod parse; +mod reformat; mod resolver; mod typespec; diff --git a/typegen/src/parse.rs b/typegen/src/parse.rs index 32337d6..3b2b73a 100644 --- a/typegen/src/parse.rs +++ b/typegen/src/parse.rs @@ -4,7 +4,10 @@ use anyhow::{anyhow, bail, Context}; use fancy_regex::Regex; use serde::Deserialize; -use crate::typespec; +use crate::{ + reformat::{self, ReformatPass}, + typespec, +}; #[derive(Deserialize, Debug)] pub struct ModuleInfoHeader { @@ -625,7 +628,6 @@ impl From> for typespec::FnParam { fn parse_details(comment: Comment) -> String { let mut seen_content = false; - let mut callout = false; let mut str = comment .text @@ -642,127 +644,14 @@ fn parse_details(comment: Comment) -> String { seen_content |= any; 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"); - if callout { - str += "\n{{< /callout >}}"; - } + let reformat_ctx = reformat::Context { + module: comment.module, + }; + + crate::reformat::GfmQuoteBlocks::reformat(&reformat_ctx, &mut str); + crate::reformat::TypeLinks::reformat(&reformat_ctx, &mut str); str } diff --git a/typegen/src/reformat.rs b/typegen/src/reformat.rs new file mode 100644 index 0000000..1a22b93 --- /dev/null +++ b/typegen/src/reformat.rs @@ -0,0 +1,127 @@ +use std::borrow::Cow; + +pub struct Context<'a> { + pub module: &'a str, +} + +pub trait ReformatPass { + fn reformat(context: &Context, text: &mut String); +} + +pub struct GfmQuoteBlocks; + +impl ReformatPass for GfmQuoteBlocks { + fn reformat(_: &Context, text: &mut String) { + *text = text.replace("> [!INFO]", "> [!NOTE]"); + } +} + +pub struct TypeLinks; + +impl ReformatPass for TypeLinks { + fn reformat(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"); + } +}