typegen: scan for module files
This commit is contained in:
parent
2fde54b3bc
commit
2fa8ed73c0
8 changed files with 361 additions and 212 deletions
61
Justfile
61
Justfile
|
@ -6,68 +6,17 @@ build_typegen := if typegen_bin == './typegen/target/debug/typegen' { "true" } e
|
||||||
clean:
|
clean:
|
||||||
rm -rf public
|
rm -rf public
|
||||||
rm -rf build
|
rm -rf build
|
||||||
rm -rf data/modules/Quickshell
|
rm -rf data/modules/*
|
||||||
rm -rf content/docs/types/Quickshell
|
rm -rf content/docs/types/*
|
||||||
rm -rf data/modules/Quickshell.Io
|
|
||||||
rm -rf content/docs/types/Quickshell.Io
|
|
||||||
rm -rf data/modules/Quickshell.Wayland
|
|
||||||
rm -rf content/docs/types/Quickshell.Wayland
|
|
||||||
rm -rf data/modules/Quickshell.DBusMenu
|
|
||||||
rm -rf content/docs/types/Quickshell.DBusMenu
|
|
||||||
rm -rf data/modules/Quickshell.Services.SystemTray
|
|
||||||
rm -rf content/docs/types/Quickshell.Services.SystemTray
|
|
||||||
rm -rf data/modules/Quickshell.Services.Pipewire
|
|
||||||
rm -rf content/docs/types/Quickshell.Services.Pipewire
|
|
||||||
rm -rf data/modules/Quickshell.Services.Mpris
|
|
||||||
rm -rf content/docs/types/Quickshell.Services.Mpris
|
|
||||||
rm -rf data/modules/Quickshell.Services.Pam
|
|
||||||
rm -rf content/docs/types/Quickshell.Services.Pam
|
|
||||||
rm -rf data/modules/Quickshell.Services.Greetd
|
|
||||||
rm -rf content/docs/types/Quickshell.Services.Greetd
|
|
||||||
rm -rf data/modules/Quickshell.Services.UPower
|
|
||||||
rm -rf content/docs/types/Quickshell.Services.UPower
|
|
||||||
rm -rf data/modules/Quickshell.Services.Notifications
|
|
||||||
rm -rf content/docs/types/Quickshell.Services.Notifications
|
|
||||||
rm -rf data/modules/Quickshell.Hyprland
|
|
||||||
rm -rf content/docs/types/Quickshell.Hyprland
|
|
||||||
rm -rf data/modules/Quickshell.I3
|
|
||||||
rm -rf content/docs/types/Quickshell.I3
|
|
||||||
rm -rf data/modules/Quickshell.Widgets
|
|
||||||
rm -rf content/docs/types/Quickshell.Widgets
|
|
||||||
|
|
||||||
buildtypegen:
|
buildtypegen:
|
||||||
({{build_typegen}} && cd typegen && cargo build) || true
|
({{build_typegen}} && cd typegen && cargo build) || true
|
||||||
|
|
||||||
typedocs: clean buildtypegen
|
typedocs: clean buildtypegen
|
||||||
|
mkdir -p data/modules
|
||||||
mkdir -p build/types/types
|
mkdir -p build/types/types
|
||||||
{{typegen_bin}} gentypes {{src_path}}/core/module.md build/types/types/Quickshell.json
|
mkdir -p content/docs/types
|
||||||
{{typegen_bin}} gentypes {{src_path}}/io/module.md build/types/types/Quickshell.Io.json
|
{{typegen_bin}} fulltypegen {{src_path}} build/types/types data/modules content/docs/types types
|
||||||
{{typegen_bin}} gentypes {{src_path}}/wayland/module.md build/types/types/Quickshell.Wayland.json
|
|
||||||
{{typegen_bin}} gentypes {{src_path}}/dbus/dbusmenu/module.md build/types/types/Quickshell.DBusMenu.json
|
|
||||||
{{typegen_bin}} gentypes {{src_path}}/services/status_notifier/module.md build/types/types/Quickshell.Services.SystemTray.json
|
|
||||||
{{typegen_bin}} gentypes {{src_path}}/services/pipewire/module.md build/types/types/Quickshell.Services.Pipewire.json
|
|
||||||
{{typegen_bin}} gentypes {{src_path}}/services/mpris/module.md build/types/types/Quickshell.Services.Mpris.json
|
|
||||||
{{typegen_bin}} gentypes {{src_path}}/services/pam/module.md build/types/types/Quickshell.Services.Pam.json
|
|
||||||
{{typegen_bin}} gentypes {{src_path}}/services/greetd/module.md build/types/types/Quickshell.Services.Greetd.json
|
|
||||||
{{typegen_bin}} gentypes {{src_path}}/services/upower/module.md build/types/types/Quickshell.Services.UPower.json
|
|
||||||
{{typegen_bin}} gentypes {{src_path}}/services/notifications/module.md build/types/types/Quickshell.Services.Notifications.json
|
|
||||||
{{typegen_bin}} gentypes {{src_path}}/wayland/hyprland/module.md build/types/types/Quickshell.Hyprland.json
|
|
||||||
{{typegen_bin}} gentypes {{src_path}}/x11/i3/module.md build/types/types/Quickshell.I3.json
|
|
||||||
{{typegen_bin}} gentypes {{src_path}}/widgets/module.md build/types/types/Quickshell.Widgets.json
|
|
||||||
sh -c '{{typegen_bin}} gendocs {{src_path}}/core/module.md data/modules/Quickshell content/docs/types/Quickshell types/* build/types/types/*'
|
|
||||||
sh -c '{{typegen_bin}} gendocs {{src_path}}/io/module.md data/modules/Quickshell.Io content/docs/types/Quickshell.Io types/* build/types/types/*'
|
|
||||||
sh -c '{{typegen_bin}} gendocs {{src_path}}/wayland/module.md data/modules/Quickshell.Wayland content/docs/types/Quickshell.Wayland types/* build/types/types/*'
|
|
||||||
sh -c '{{typegen_bin}} gendocs {{src_path}}/dbus/dbusmenu/module.md data/modules/Quickshell.DBusMenu content/docs/types/Quickshell.DBusMenu types/* build/types/types/*'
|
|
||||||
sh -c '{{typegen_bin}} gendocs {{src_path}}/services/status_notifier/module.md data/modules/Quickshell.Services.SystemTray content/docs/types/Quickshell.Services.SystemTray types/* build/types/types/*'
|
|
||||||
sh -c '{{typegen_bin}} gendocs {{src_path}}/services/pipewire/module.md data/modules/Quickshell.Services.Pipewire content/docs/types/Quickshell.Services.Pipewire types/* build/types/types/*'
|
|
||||||
sh -c '{{typegen_bin}} gendocs {{src_path}}/services/mpris/module.md data/modules/Quickshell.Services.Mpris content/docs/types/Quickshell.Services.Mpris types/* build/types/types/*'
|
|
||||||
sh -c '{{typegen_bin}} gendocs {{src_path}}/services/pam/module.md data/modules/Quickshell.Services.Pam content/docs/types/Quickshell.Services.Pam types/* build/types/types/*'
|
|
||||||
sh -c '{{typegen_bin}} gendocs {{src_path}}/services/greetd/module.md data/modules/Quickshell.Services.Greetd content/docs/types/Quickshell.Services.Greetd types/* build/types/types/*'
|
|
||||||
sh -c '{{typegen_bin}} gendocs {{src_path}}/services/upower/module.md data/modules/Quickshell.Services.UPower content/docs/types/Quickshell.Services.UPower types/* build/types/types/*'
|
|
||||||
sh -c '{{typegen_bin}} gendocs {{src_path}}/services/notifications/module.md data/modules/Quickshell.Services.Notifications content/docs/types/Quickshell.Services.Notifications types/* build/types/types/*'
|
|
||||||
sh -c '{{typegen_bin}} gendocs {{src_path}}/wayland/hyprland/module.md data/modules/Quickshell.Hyprland content/docs/types/Quickshell.Hyprland types/* build/types/types/*'
|
|
||||||
sh -c '{{typegen_bin}} gendocs {{src_path}}/x11/i3/module.md data/modules/Quickshell.I3 content/docs/types/Quickshell.I3 types/* build/types/types/*'
|
|
||||||
sh -c '{{typegen_bin}} gendocs {{src_path}}/widgets/module.md data/modules/Quickshell.Widgets content/docs/types/Quickshell.Widgets types/* build/types/types/*'
|
|
||||||
|
|
||||||
serve: typedocs
|
serve: typedocs
|
||||||
hugo server --buildDrafts --disableFastRender
|
hugo server --buildDrafts --disableFastRender
|
||||||
|
|
102
typegen/Cargo.lock
generated
102
typegen/Cargo.lock
generated
|
@ -118,6 +118,15 @@ version = "1.0.16"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c"
|
checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "same-file"
|
||||||
|
version = "1.0.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
|
||||||
|
dependencies = [
|
||||||
|
"winapi-util",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.196"
|
version = "1.0.196"
|
||||||
|
@ -212,6 +221,7 @@ dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"toml",
|
"toml",
|
||||||
|
"walkdir",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -220,6 +230,98 @@ version = "1.0.12"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
|
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "walkdir"
|
||||||
|
version = "2.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b"
|
||||||
|
dependencies = [
|
||||||
|
"same-file",
|
||||||
|
"winapi-util",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-util"
|
||||||
|
version = "0.1.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
|
||||||
|
dependencies = [
|
||||||
|
"windows-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-sys"
|
||||||
|
version = "0.59.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
|
||||||
|
dependencies = [
|
||||||
|
"windows-targets",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-targets"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
|
||||||
|
dependencies = [
|
||||||
|
"windows_aarch64_gnullvm",
|
||||||
|
"windows_aarch64_msvc",
|
||||||
|
"windows_i686_gnu",
|
||||||
|
"windows_i686_gnullvm",
|
||||||
|
"windows_i686_msvc",
|
||||||
|
"windows_x86_64_gnu",
|
||||||
|
"windows_x86_64_gnullvm",
|
||||||
|
"windows_x86_64_msvc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_gnullvm"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_msvc"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_gnu"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_gnullvm"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_msvc"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnu"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnullvm"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_msvc"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winnow"
|
name = "winnow"
|
||||||
version = "0.5.37"
|
version = "0.5.37"
|
||||||
|
|
|
@ -9,3 +9,4 @@ fancy-regex = "^0.13"
|
||||||
serde = { version = "^1", features = ["derive"] }
|
serde = { version = "^1", features = ["derive"] }
|
||||||
serde_json = "^1"
|
serde_json = "^1"
|
||||||
toml = "^0.8"
|
toml = "^0.8"
|
||||||
|
walkdir = "2.5.0"
|
||||||
|
|
|
@ -6,5 +6,5 @@
|
||||||
version = "0.1.0";
|
version = "0.1.0";
|
||||||
|
|
||||||
src = nix-gitignore.gitignoreSource [] ./.;
|
src = nix-gitignore.gitignoreSource [] ./.;
|
||||||
cargoHash = "sha256-bOOYzCLIyze6DbtMDupSuRFgJAKjbcFXrZw7vclorYQ=";
|
cargoHash = "sha256-vLj/EKfBzlfRdmVr114evJS+Owzz4PdARNGBE3aPUo4=";
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
use std::{collections::HashMap, path::Path};
|
use std::{
|
||||||
|
collections::HashMap,
|
||||||
|
path::{Path, PathBuf},
|
||||||
|
};
|
||||||
|
|
||||||
use anyhow::{anyhow, Context};
|
use anyhow::{anyhow, Context};
|
||||||
|
use walkdir::WalkDir;
|
||||||
|
|
||||||
mod outform;
|
mod outform;
|
||||||
mod parse;
|
mod parse;
|
||||||
|
@ -12,152 +16,79 @@ fn main() -> anyhow::Result<()> {
|
||||||
let args = std::env::args().collect::<Vec<_>>();
|
let args = std::env::args().collect::<Vec<_>>();
|
||||||
|
|
||||||
match args.get(1).map(|v| v as &str) {
|
match args.get(1).map(|v| v as &str) {
|
||||||
|
Some("fulltypegen") => {
|
||||||
|
let path = args.get(2).expect("expected basedir");
|
||||||
|
let outpath = args.get(3).expect("expected outpath");
|
||||||
|
let datapath = args.get(4).expect("expected datapath");
|
||||||
|
let templatepath = args.get(5).expect("expected templatepath");
|
||||||
|
let extratypedirs = &args[6..];
|
||||||
|
|
||||||
|
let module_files = WalkDir::new(path)
|
||||||
|
.into_iter()
|
||||||
|
.filter(|e| {
|
||||||
|
e.as_ref()
|
||||||
|
.map(|e| e.file_name() == "module.md")
|
||||||
|
.unwrap_or(false)
|
||||||
|
})
|
||||||
|
.map(|entry| match entry {
|
||||||
|
Ok(entry) => {
|
||||||
|
let path = entry.path().to_string_lossy().to_string();
|
||||||
|
let text = std::fs::read_to_string(&path)?;
|
||||||
|
let module = parse::parse_module(&text)?;
|
||||||
|
Ok((path, module.header))
|
||||||
|
},
|
||||||
|
Err(e) => Err(anyhow!(e)),
|
||||||
|
})
|
||||||
|
.collect::<Result<Vec<(String, parse::ModuleInfoHeader)>, anyhow::Error>>()?;
|
||||||
|
|
||||||
|
println!("Generating types -> {outpath}");
|
||||||
|
|
||||||
|
for (path, header) in module_files.iter() {
|
||||||
|
let name = &header.name;
|
||||||
|
let mod_outpath = format!("{outpath}/{name}.json");
|
||||||
|
println!("Gentypes :: {path} ({name}) -> {mod_outpath}");
|
||||||
|
gentypes(path, &mod_outpath)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut typefiledirs = extratypedirs.to_vec();
|
||||||
|
typefiledirs.push(outpath.clone());
|
||||||
|
|
||||||
|
println!("Generating docs {typefiledirs:?} -> {datapath}");
|
||||||
|
|
||||||
|
// this is crap but I don't care, typegen is getting replaced
|
||||||
|
let typefiles = typefiledirs
|
||||||
|
.iter()
|
||||||
|
.map(|dir| {
|
||||||
|
let dirs = Path::new(dir)
|
||||||
|
.read_dir()?
|
||||||
|
.flatten()
|
||||||
|
.map(|e| e.path().to_string_lossy().to_string())
|
||||||
|
.collect::<Vec<String>>();
|
||||||
|
Ok::<_, anyhow::Error>(dirs)
|
||||||
|
})
|
||||||
|
.collect::<Result<Vec<Vec<String>>, anyhow::Error>>()?
|
||||||
|
.into_iter()
|
||||||
|
.flatten()
|
||||||
|
.collect::<Vec<String>>();
|
||||||
|
|
||||||
|
for (path, header) in module_files.iter() {
|
||||||
|
let name = &header.name;
|
||||||
|
let mod_datapath = format!("{datapath}/{name}");
|
||||||
|
let mod_templatepath = format!("{templatepath}/{name}");
|
||||||
|
println!("Gendocs :: {path} ({name}) to {mod_datapath}");
|
||||||
|
gendocs(path, &mod_datapath, &mod_templatepath, &typefiles[..])?;
|
||||||
|
}
|
||||||
|
},
|
||||||
Some("gentypes") => {
|
Some("gentypes") => {
|
||||||
let modinfo = args.get(2).expect("expected module file");
|
let modinfo = args.get(2).expect("expected module file");
|
||||||
let outpath = args.get(3).expect("expected output path");
|
let outpath = args.get(3).expect("expected output path");
|
||||||
let path = Path::new(modinfo);
|
gentypes(modinfo, outpath)?;
|
||||||
let dir = path.parent().unwrap();
|
|
||||||
let text = std::fs::read_to_string(path).expect("failed to read module file");
|
|
||||||
let module = parse::parse_module(&text)?;
|
|
||||||
|
|
||||||
let texts = module
|
|
||||||
.header
|
|
||||||
.headers
|
|
||||||
.iter()
|
|
||||||
.map(|header| {
|
|
||||||
let text = std::fs::read_to_string(dir.join(header)).with_context(|| {
|
|
||||||
format!(
|
|
||||||
"failed to read module header `{header}` at {:?}",
|
|
||||||
dir.join(header)
|
|
||||||
)
|
|
||||||
})?;
|
|
||||||
|
|
||||||
Ok::<_, anyhow::Error>((header, text))
|
|
||||||
})
|
|
||||||
.collect::<Result<HashMap<_, _>, _>>()?;
|
|
||||||
|
|
||||||
let qml_texts = module
|
|
||||||
.header
|
|
||||||
.qml_files
|
|
||||||
.iter()
|
|
||||||
.map(|file| {
|
|
||||||
let text = std::fs::read_to_string(dir.join(file)).with_context(|| {
|
|
||||||
format!(
|
|
||||||
"failed to read module qml file `{file}` at {:?}",
|
|
||||||
dir.join(file)
|
|
||||||
)
|
|
||||||
})?;
|
|
||||||
|
|
||||||
Ok::<_, anyhow::Error>((file, text))
|
|
||||||
})
|
|
||||||
.collect::<Result<HashMap<_, _>, _>>()?;
|
|
||||||
|
|
||||||
let header_parser = parse::CppParser::new();
|
|
||||||
let qml_parser = parse::QmlParser::new();
|
|
||||||
let mut ctx = parse::ParseContext::new(&module.header.name);
|
|
||||||
|
|
||||||
texts
|
|
||||||
.iter()
|
|
||||||
.map(|(header, text)| {
|
|
||||||
header_parser
|
|
||||||
.parse(&text, &mut ctx)
|
|
||||||
.with_context(|| format!("while parsing module header `{header}`"))
|
|
||||||
})
|
|
||||||
.collect::<Result<_, _>>()?;
|
|
||||||
|
|
||||||
qml_texts
|
|
||||||
.iter()
|
|
||||||
.map(|(file, text)| {
|
|
||||||
qml_parser
|
|
||||||
.parse(&file, &text, &mut ctx)
|
|
||||||
.with_context(|| format!("while parsing module qml file `{file}`"))
|
|
||||||
})
|
|
||||||
.collect::<Result<_, _>>()?;
|
|
||||||
|
|
||||||
let typespec = ctx.gen_typespec(&module.header.name);
|
|
||||||
|
|
||||||
let text = serde_json::to_string_pretty(&typespec).unwrap();
|
|
||||||
|
|
||||||
std::fs::write(outpath, text).context("saving typespec")?;
|
|
||||||
},
|
},
|
||||||
Some("gendocs") => {
|
Some("gendocs") => {
|
||||||
let modinfo = args.get(2).expect("expected module file");
|
let modinfo = args.get(2).expect("expected module file");
|
||||||
let datapath = args.get(3).expect("expected datapath");
|
let datapath = args.get(3).expect("expected datapath");
|
||||||
let templatepath = args.get(4).expect("expected templatepath");
|
let templatepath = args.get(4).expect("expected templatepath");
|
||||||
|
gendocs(modinfo, datapath, templatepath, &args[5..])?;
|
||||||
let text = std::fs::read_to_string(modinfo).expect("failed to read module file");
|
|
||||||
let module = parse::parse_module(&text)?;
|
|
||||||
|
|
||||||
let mut typespec = typespec::TypeSpec::default();
|
|
||||||
|
|
||||||
for path in &args[5..] {
|
|
||||||
let text = std::fs::read_to_string(&path)
|
|
||||||
.with_context(|| anyhow!("attempting to read {path}"))?;
|
|
||||||
|
|
||||||
let ts = serde_json::from_str::<typespec::TypeSpec>(&text)
|
|
||||||
.with_context(|| anyhow!("attempting to parse {path}"))?;
|
|
||||||
|
|
||||||
typespec.typemap.extend(ts.typemap);
|
|
||||||
typespec.classes.extend(ts.classes);
|
|
||||||
typespec.gadgets.extend(ts.gadgets);
|
|
||||||
typespec.enums.extend(ts.enums);
|
|
||||||
}
|
|
||||||
|
|
||||||
let types = resolver::resolve_types(&module.header.name, typespec)?;
|
|
||||||
|
|
||||||
let datapath = Path::new(datapath);
|
|
||||||
let templatepath = Path::new(templatepath);
|
|
||||||
std::fs::create_dir_all(datapath)?;
|
|
||||||
std::fs::create_dir_all(templatepath)?;
|
|
||||||
|
|
||||||
for (name, info) in types {
|
|
||||||
let json = serde_json::to_string_pretty(&info).unwrap();
|
|
||||||
let datapath = datapath.join(format!("{name}.json"));
|
|
||||||
std::fs::write(&datapath, json)
|
|
||||||
.with_context(|| format!("while writing {datapath:?}"))?;
|
|
||||||
|
|
||||||
let template = format!(
|
|
||||||
"+++
|
|
||||||
title = \"{name}\"
|
|
||||||
hidetitle = true
|
|
||||||
+++
|
|
||||||
|
|
||||||
{{{{< qmltype module=\"{module}\" type=\"{name}\" >}}}}
|
|
||||||
",
|
|
||||||
name = name,
|
|
||||||
module = module.header.name
|
|
||||||
);
|
|
||||||
|
|
||||||
let templatepath = templatepath.join(format!("{name}.md"));
|
|
||||||
std::fs::write(&templatepath, template)
|
|
||||||
.with_context(|| format!("while writing {templatepath:?}"))?;
|
|
||||||
}
|
|
||||||
|
|
||||||
let index = outform::ModuleIndex {
|
|
||||||
name: module.header.name.to_string(),
|
|
||||||
description: module.header.description,
|
|
||||||
details: module.details.to_string(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let datapath = datapath.join("index.json");
|
|
||||||
let json = serde_json::to_string_pretty(&index).unwrap();
|
|
||||||
std::fs::write(&datapath, json)
|
|
||||||
.with_context(|| format!("while writing {datapath:?}"))?;
|
|
||||||
|
|
||||||
let template = format!(
|
|
||||||
"+++
|
|
||||||
title = \"{name}\"
|
|
||||||
hidetitle = true
|
|
||||||
+++
|
|
||||||
|
|
||||||
{{{{< qmlmodule module=\"{name}\" >}}}}
|
|
||||||
",
|
|
||||||
name = module.header.name
|
|
||||||
);
|
|
||||||
|
|
||||||
let templatepath = templatepath.join(format!("_index.md"));
|
|
||||||
std::fs::write(&templatepath, template)
|
|
||||||
.with_context(|| format!("while writing {templatepath:?}"))?;
|
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
panic!("typegen invoked without mode");
|
panic!("typegen invoked without mode");
|
||||||
|
@ -166,3 +97,149 @@ hidetitle = true
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn gentypes(modinfo: &str, outpath: &str) -> anyhow::Result<()> {
|
||||||
|
let path = Path::new(modinfo);
|
||||||
|
let dir = path.parent().unwrap();
|
||||||
|
let text = std::fs::read_to_string(path).expect("failed to read module file");
|
||||||
|
let module = parse::parse_module(&text)?;
|
||||||
|
|
||||||
|
let texts = module
|
||||||
|
.header
|
||||||
|
.headers
|
||||||
|
.iter()
|
||||||
|
.map(|header| {
|
||||||
|
let text = std::fs::read_to_string(dir.join(header)).with_context(|| {
|
||||||
|
format!(
|
||||||
|
"failed to read module header `{header}` at {:?}",
|
||||||
|
dir.join(header)
|
||||||
|
)
|
||||||
|
})?;
|
||||||
|
|
||||||
|
Ok::<_, anyhow::Error>((header, text))
|
||||||
|
})
|
||||||
|
.collect::<Result<HashMap<_, _>, _>>()?;
|
||||||
|
|
||||||
|
let qml_texts = module
|
||||||
|
.header
|
||||||
|
.qml_files
|
||||||
|
.iter()
|
||||||
|
.map(|file| {
|
||||||
|
let text = std::fs::read_to_string(dir.join(file)).with_context(|| {
|
||||||
|
format!(
|
||||||
|
"failed to read module qml file `{file}` at {:?}",
|
||||||
|
dir.join(file)
|
||||||
|
)
|
||||||
|
})?;
|
||||||
|
|
||||||
|
Ok::<_, anyhow::Error>((file, text))
|
||||||
|
})
|
||||||
|
.collect::<Result<HashMap<_, _>, _>>()?;
|
||||||
|
|
||||||
|
let header_parser = parse::CppParser::new();
|
||||||
|
let qml_parser = parse::QmlParser::new();
|
||||||
|
let mut ctx = parse::ParseContext::new(&module.header.name);
|
||||||
|
|
||||||
|
texts
|
||||||
|
.iter()
|
||||||
|
.map(|(header, text)| {
|
||||||
|
header_parser
|
||||||
|
.parse(&text, &mut ctx)
|
||||||
|
.with_context(|| format!("while parsing module header `{header}`"))
|
||||||
|
})
|
||||||
|
.collect::<Result<_, _>>()?;
|
||||||
|
|
||||||
|
qml_texts
|
||||||
|
.iter()
|
||||||
|
.map(|(file, text)| {
|
||||||
|
qml_parser
|
||||||
|
.parse(&file, &text, &mut ctx)
|
||||||
|
.with_context(|| format!("while parsing module qml file `{file}`"))
|
||||||
|
})
|
||||||
|
.collect::<Result<_, _>>()?;
|
||||||
|
|
||||||
|
let typespec = ctx.gen_typespec(&module.header.name);
|
||||||
|
|
||||||
|
let text = serde_json::to_string_pretty(&typespec).unwrap();
|
||||||
|
|
||||||
|
std::fs::write(outpath, text).context("saving typespec")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn gendocs(
|
||||||
|
modinfo: &str,
|
||||||
|
datapath: &str,
|
||||||
|
templatepath: &str,
|
||||||
|
typepaths: &[String],
|
||||||
|
) -> anyhow::Result<()> {
|
||||||
|
let text = std::fs::read_to_string(modinfo).expect("failed to read module file");
|
||||||
|
let module = parse::parse_module(&text)?;
|
||||||
|
|
||||||
|
let mut typespec = typespec::TypeSpec::default();
|
||||||
|
|
||||||
|
for path in typepaths {
|
||||||
|
let text =
|
||||||
|
std::fs::read_to_string(&path).with_context(|| anyhow!("attempting to read {path}"))?;
|
||||||
|
|
||||||
|
let ts = serde_json::from_str::<typespec::TypeSpec>(&text)
|
||||||
|
.with_context(|| anyhow!("attempting to parse {path}"))?;
|
||||||
|
|
||||||
|
typespec.typemap.extend(ts.typemap);
|
||||||
|
typespec.classes.extend(ts.classes);
|
||||||
|
typespec.gadgets.extend(ts.gadgets);
|
||||||
|
typespec.enums.extend(ts.enums);
|
||||||
|
}
|
||||||
|
|
||||||
|
let types = resolver::resolve_types(&module.header.name, typespec)?;
|
||||||
|
|
||||||
|
let datapath = Path::new(datapath);
|
||||||
|
let templatepath = Path::new(templatepath);
|
||||||
|
std::fs::create_dir_all(datapath)?;
|
||||||
|
std::fs::create_dir_all(templatepath)?;
|
||||||
|
|
||||||
|
for (name, info) in types {
|
||||||
|
let json = serde_json::to_string_pretty(&info).unwrap();
|
||||||
|
let datapath = datapath.join(format!("{name}.json"));
|
||||||
|
std::fs::write(&datapath, json).with_context(|| format!("while writing {datapath:?}"))?;
|
||||||
|
|
||||||
|
let template = format!(
|
||||||
|
"+++
|
||||||
|
title = \"{name}\"
|
||||||
|
hidetitle = true
|
||||||
|
+++
|
||||||
|
|
||||||
|
{{{{< qmltype module=\"{module}\" type=\"{name}\" >}}}}
|
||||||
|
",
|
||||||
|
name = name,
|
||||||
|
module = module.header.name
|
||||||
|
);
|
||||||
|
|
||||||
|
let templatepath = templatepath.join(format!("{name}.md"));
|
||||||
|
std::fs::write(&templatepath, template)
|
||||||
|
.with_context(|| format!("while writing {templatepath:?}"))?;
|
||||||
|
}
|
||||||
|
|
||||||
|
let index = outform::ModuleIndex {
|
||||||
|
name: module.header.name.to_string(),
|
||||||
|
description: module.header.description,
|
||||||
|
details: module.details.to_string(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let datapath = datapath.join("index.json");
|
||||||
|
let json = serde_json::to_string_pretty(&index).unwrap();
|
||||||
|
std::fs::write(&datapath, json).with_context(|| format!("while writing {datapath:?}"))?;
|
||||||
|
|
||||||
|
let template = format!(
|
||||||
|
"+++
|
||||||
|
title = \"{name}\"
|
||||||
|
hidetitle = true
|
||||||
|
+++
|
||||||
|
|
||||||
|
{{{{< qmlmodule module=\"{name}\" >}}}}
|
||||||
|
",
|
||||||
|
name = module.header.name
|
||||||
|
);
|
||||||
|
|
||||||
|
let templatepath = templatepath.join(format!("_index.md"));
|
||||||
|
std::fs::write(&templatepath, template)
|
||||||
|
.with_context(|| format!("while writing {templatepath:?}"))
|
||||||
|
}
|
||||||
|
|
|
@ -214,7 +214,10 @@ impl CppParser {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
let comment = macro_.name("comment").map(|m| m.as_str()).or(carryover.as_ref().map(|c| c.comment).flatten());
|
let comment = macro_
|
||||||
|
.name("comment")
|
||||||
|
.map(|m| m.as_str())
|
||||||
|
.or(carryover.as_ref().map(|c| c.comment).flatten());
|
||||||
let type_ = macro_.name("type").unwrap().as_str();
|
let type_ = macro_.name("type").unwrap().as_str();
|
||||||
let args = macro_.name("args").map(|m| m.as_str());
|
let args = macro_.name("args").map(|m| m.as_str());
|
||||||
|
|
||||||
|
@ -243,13 +246,14 @@ impl CppParser {
|
||||||
"QML_UNCREATABLE" => uncreatable = true,
|
"QML_UNCREATABLE" => uncreatable = true,
|
||||||
"QSDOC_CREATABLE" => force_creatable = true,
|
"QSDOC_CREATABLE" => force_creatable = true,
|
||||||
"QSDOC_TYPE_OVERRIDE" => {
|
"QSDOC_TYPE_OVERRIDE" => {
|
||||||
let type_override = args.ok_or_else(|| anyhow!("expected param for QSDOC_GENERIC"))?;
|
let type_override = args
|
||||||
|
.ok_or_else(|| anyhow!("expected param for QSDOC_GENERIC"))?;
|
||||||
|
|
||||||
carryover = Some(Carryover {
|
carryover = Some(Carryover {
|
||||||
type_override: Some(type_override),
|
type_override: Some(type_override),
|
||||||
comment,
|
comment,
|
||||||
});
|
});
|
||||||
}
|
},
|
||||||
"Q_PROPERTY" | "QSDOC_PROPERTY_OVERRIDE" => {
|
"Q_PROPERTY" | "QSDOC_PROPERTY_OVERRIDE" => {
|
||||||
let prop =
|
let prop =
|
||||||
self.property_regex
|
self.property_regex
|
||||||
|
@ -268,7 +272,13 @@ impl CppParser {
|
||||||
}
|
}
|
||||||
|
|
||||||
properties.push(Property {
|
properties.push(Property {
|
||||||
type_: Cow::Borrowed(this_carryover.as_ref().map(|c| c.type_override).flatten().unwrap_or_else(|| prop.name("type").unwrap().as_str())),
|
type_: Cow::Borrowed(
|
||||||
|
this_carryover
|
||||||
|
.as_ref()
|
||||||
|
.map(|c| c.type_override)
|
||||||
|
.flatten()
|
||||||
|
.unwrap_or_else(|| prop.name("type").unwrap().as_str()),
|
||||||
|
),
|
||||||
name: prop.name("name").unwrap().as_str(),
|
name: prop.name("name").unwrap().as_str(),
|
||||||
comment: comment.map(|v| Comment::new(v, ctx.module)),
|
comment: comment.map(|v| Comment::new(v, ctx.module)),
|
||||||
readable: read || member,
|
readable: read || member,
|
||||||
|
|
|
@ -11,28 +11,31 @@ pub trait ReformatPass {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct GfmQuoteBlocks {
|
pub struct GfmQuoteBlocks {
|
||||||
callout_regex: Regex,
|
callout_regex: Regex,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GfmQuoteBlocks {
|
impl GfmQuoteBlocks {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
callout_regex: Regex::new(r#">\s+\[!(?<type>\w+)]\s+"#).unwrap()
|
callout_regex: Regex::new(r#">\s+\[!(?<type>\w+)]\s+"#).unwrap(),
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ReformatPass for GfmQuoteBlocks {
|
impl ReformatPass for GfmQuoteBlocks {
|
||||||
fn reformat(&self, _: &Context, text: &mut String) {
|
fn reformat(&self, _: &Context, text: &mut String) {
|
||||||
*text = text.replace("> [!INFO]", "> [!NOTE]");
|
*text = text.replace("> [!INFO]", "> [!NOTE]");
|
||||||
*text = self.callout_regex.replace_all(text, "> [!$type]\n> ").to_string();
|
*text = self
|
||||||
|
.callout_regex
|
||||||
|
.replace_all(text, "> [!$type]\n> ")
|
||||||
|
.to_string();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct TypeLinks;
|
pub struct TypeLinks;
|
||||||
|
|
||||||
impl ReformatPass for TypeLinks {
|
impl ReformatPass for TypeLinks {
|
||||||
fn reformat(&self ,context: &Context, text: &mut String) {
|
fn reformat(&self, context: &Context, text: &mut String) {
|
||||||
let lines = text.lines().map(|line| {
|
let lines = text.lines().map(|line| {
|
||||||
if line.contains("@@") {
|
if line.contains("@@") {
|
||||||
let mut src: &str = &*line;
|
let mut src: &str = &*line;
|
||||||
|
|
|
@ -110,7 +110,14 @@ pub fn resolve_types(
|
||||||
typespec
|
typespec
|
||||||
.enums
|
.enums
|
||||||
.iter()
|
.iter()
|
||||||
.find(|type_| type_.cname.as_ref().map(|v| v as &str).map(|v| !v.is_empty() && ctype.ends_with(v) ).unwrap_or(false))
|
.find(|type_| {
|
||||||
|
type_
|
||||||
|
.cname
|
||||||
|
.as_ref()
|
||||||
|
.map(|v| v as &str)
|
||||||
|
.map(|v| !v.is_empty() && ctype.ends_with(v))
|
||||||
|
.unwrap_or(false)
|
||||||
|
})
|
||||||
.map(|type_| (&type_.module, &type_.name))
|
.map(|type_| (&type_.module, &type_.name))
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue