diff --git a/flake.lock b/flake.lock index 2b27804..b8a3733 100644 --- a/flake.lock +++ b/flake.lock @@ -22,11 +22,11 @@ ] }, "locked": { - "lastModified": 1725876916, - "narHash": "sha256-3SDm2pV1ZIQHqIhAe7BjuXhNdVyzcxPiwaFyqE8ODdc=", + "lastModified": 1720770600, + "narHash": "sha256-Ouic1xV4pJns1rbw6wnee9fO4VWkcv73hxSLQkPYabk=", "ref": "refs/heads/master", - "rev": "85be3861ceadba6e3d877a64cade15015ea0c96f", - "revCount": 324, + "rev": "d630cc7f76b56ad3ebe084159df6beab48db9866", + "revCount": 247, "type": "git", "url": "https://git.outfoxxed.me/outfoxxed/quickshell" }, diff --git a/layouts/docs/list.html b/layouts/docs/list.html deleted file mode 100644 index fc5c73a..0000000 --- a/layouts/docs/list.html +++ /dev/null @@ -1,18 +0,0 @@ -{{ 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 }} diff --git a/layouts/shortcodes/qmltypelink.html b/layouts/shortcodes/qmltypelink.html deleted file mode 100644 index 018ebd5..0000000 --- a/layouts/shortcodes/qmltypelink.html +++ /dev/null @@ -1,9 +0,0 @@ -{{- $params := dict - "type" (.Get "type") - "module" (.Get "module") - "name" (.Get "name") - "mtype" (.Get "mtype") - "mname" (.Get "mname") --}} - -{{- partial "qmltype.html" $params -}} diff --git a/typegen/src/main.rs b/typegen/src/main.rs index 0e22cc9..a14255c 100644 --- a/typegen/src/main.rs +++ b/typegen/src/main.rs @@ -4,7 +4,6 @@ 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 3b2b73a..2a8d7f8 100644 --- a/typegen/src/parse.rs +++ b/typegen/src/parse.rs @@ -4,10 +4,7 @@ use anyhow::{anyhow, bail, Context}; use fancy_regex::Regex; use serde::Deserialize; -use crate::{ - reformat::{self, ReformatPass}, - typespec, -}; +use crate::typespec; #[derive(Deserialize, Debug)] pub struct ModuleInfoHeader { @@ -152,12 +149,12 @@ 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*(\/\/@\s+)?Q_INVOKABLE\s+(\[\[.*\]\]\s+)?(static\s+)?(?(\w|::|<|>)+\*?)\s+(?\w+)\((?[\s\S]*?)\)(\s*const)?;"#).unwrap(), + fn_regex: Regex::new(r#"(?(\s*\/\/\/.*\n)+)?\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(), 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(), } @@ -387,41 +384,14 @@ impl Parser { let comment = enum_.name("comment").map(|m| m.as_str()); let namespace = enum_.name("namespace").unwrap().as_str(); - let mut enum_name = enum_.name("enum_name").unwrap().as_str(); + let 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, @@ -628,6 +598,7 @@ 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 @@ -644,14 +615,127 @@ 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"); - let reformat_ctx = reformat::Context { - module: comment.module, - }; - - crate::reformat::GfmQuoteBlocks::reformat(&reformat_ctx, &mut str); - crate::reformat::TypeLinks::reformat(&reformat_ctx, &mut str); + if callout { + str += "\n{{< /callout >}}"; + } str } diff --git a/typegen/src/reformat.rs b/typegen/src/reformat.rs deleted file mode 100644 index 1a22b93..0000000 --- a/typegen/src/reformat.rs +++ /dev/null @@ -1,127 +0,0 @@ -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"); - } -}