Skip to content

Commit

Permalink
feat(cli): implement doc sub-command in the CLI tool
Browse files Browse the repository at this point in the history
Integrate the mabo-doc crate into the CLI to be able to generate the
docs for any project (or individual files).
  • Loading branch information
dnaka91 committed Jan 10, 2024
1 parent b04202d commit 03cdc30
Show file tree
Hide file tree
Showing 16 changed files with 158 additions and 70 deletions.
4 changes: 4 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion book/.vitepress/config.mts
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,8 @@ export default defineConfig({
items: [
{ text: "mabo lint", link: "/reference/cli/lint" },
{ text: "mabo check", link: "/reference/cli/check" },
{ text: "mabo format", link: "/reference/cli/format" },
{ text: "mabo fmt", link: "/reference/cli/fmt" },
{ text: "mabo doc", link: "/reference/cli/doc" },
],
},
{
Expand Down
1 change: 1 addition & 0 deletions book/src/reference/cli/check.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# mabo check
1 change: 1 addition & 0 deletions book/src/reference/cli/doc.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# mabo doc
1 change: 1 addition & 0 deletions book/src/reference/cli/fmt.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# mabo fmt
Empty file removed book/src/reference/cli/format.md
Empty file.
1 change: 1 addition & 0 deletions book/src/reference/cli/lint.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# mabo lint
2 changes: 1 addition & 1 deletion crates/mabo-benches/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ name = "varint"
harness = false

[dependencies]
mimalloc.workspace = true
mabo-compiler = { path = "../mabo-compiler" }
mabo-parser = { path = "../mabo-parser" }
mimalloc.workspace = true

[dev-dependencies]
divan = "0.1.8"
Expand Down
6 changes: 3 additions & 3 deletions crates/mabo-build/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@ repository.workspace = true
license.workspace = true

[dependencies]
mabo-compiler = { path = "../mabo-compiler" }
mabo-parser = { path = "../mabo-parser" }
mabo-project = { path = "../mabo-project" }
miette = { workspace = true, features = ["fancy-no-backtrace"] }
prettyplease = "0.2.16"
proc-macro2.workspace = true
quote.workspace = true
mabo-compiler = { path = "../mabo-compiler" }
mabo-parser = { path = "../mabo-parser" }
mabo-project = { path = "../mabo-project" }
syn.workspace = true
thiserror.workspace = true

Expand Down
6 changes: 5 additions & 1 deletion crates/mabo-cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,15 @@ name = "mabo"
path = "src/main.rs"

[dependencies]
anyhow.workspace = true
clap.workspace = true
glob.workspace = true
mabo-compiler = { path = "../mabo-compiler" }
mabo-doc = { path = "../mabo-doc" }
mabo-parser = { path = "../mabo-parser" }
mabo-project = { path = "../mabo-project" }
miette = { workspace = true, features = ["fancy-no-backtrace"] }
mimalloc.workspace = true
mabo-parser = { path = "../mabo-parser" }

[lints]
workspace = true
52 changes: 40 additions & 12 deletions crates/mabo-cli/src/cli.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::path::PathBuf;

use clap::{Parser, Subcommand};
use clap::{Args, Parser, Subcommand};

#[derive(Parser)]
#[command(about, author, version, propagate_version = true)]
Expand All @@ -11,17 +11,45 @@ pub struct Cli {

#[derive(Subcommand)]
pub enum Command {
Init {
path: Option<PathBuf>,
},
Check {
#[arg(num_args(1..))]
files: Vec<String>,
},
Format {
#[arg(num_args(1..))]
files: Vec<String>,
},
#[command(alias = "initialize")]
Init(InitArgs),
Check(CheckArgs),
#[command(alias = "format")]
Fmt(FmtArgs),
#[command(alias = "document")]
Doc(DocArgs),
}

/// Arguments for the [`Command::Init`] subcommand.
#[derive(Args)]
pub struct InitArgs {
#[arg(long)]
pub name: Option<String>,
pub path: Option<PathBuf>,
}

/// Arguments for the [`Command::Check`] subcommand.
#[derive(Args)]
pub struct CheckArgs {
#[arg(long)]
pub project_dir: Option<PathBuf>,
pub files: Vec<String>,
}

/// Arguments for the [`Command::Fmt`] subcommand.
#[derive(Args)]
pub struct FmtArgs {
#[arg(long)]
pub project_dir: Option<PathBuf>,
pub files: Vec<String>,
}

/// Arguments for the [`Command::Doc`] subcommand.
#[derive(Args)]
pub struct DocArgs {
#[arg(long)]
pub project_dir: Option<PathBuf>,
pub out_dir: PathBuf,
}

impl Cli {
Expand Down
133 changes: 90 additions & 43 deletions crates/mabo-cli/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
//! Main command line interface for tooling support of Mabo schema files.

use std::{fs, process::ExitCode};
use std::{
fs,
path::{Path, PathBuf},
process::ExitCode,
};

use anyhow::Context;
use mabo_parser::Schema;
use miette::{Context, IntoDiagnostic, Result};
use miette::Context as _;

use self::cli::Cli;
use self::cli::{CheckArgs, Cli, DocArgs, FmtArgs};

mod cli;

Expand All @@ -17,12 +22,13 @@ fn main() -> ExitCode {

if let Some(cmd) = cli.cmd {
let result = match cmd {
cli::Command::Init { path } => {
println!("TODO: create basic setup at {path:?}");
cli::Command::Init(args) => {
println!("TODO: create basic setup at {:?}", args.path);
Ok(())
}
cli::Command::Check { files } => check(files),
cli::Command::Format { files } => format(files),
cli::Command::Check(args) => check(args),
cli::Command::Fmt(args) => format(args),
cli::Command::Doc(args) => doc(args),
};

return match result {
Expand All @@ -37,51 +43,92 @@ fn main() -> ExitCode {
ExitCode::SUCCESS
}

fn check(patterns: Vec<String>) -> Result<()> {
for pattern in patterns {
for entry in glob::glob(&pattern)
.into_diagnostic()
.wrap_err("Failed parsing glob pattern")?
{
let entry = entry.into_diagnostic().wrap_err("Failed reading entry")?;
let buf = fs::read_to_string(&entry)
.into_diagnostic()
.wrap_err_with(|| format!("Failed reading {entry:?}"))?;

if let Err(e) = Schema::parse(&buf, Some(&entry)).wrap_err("Failed parsing schema file")
{
eprintln!("{e:?}");
}
fn check(args: CheckArgs) -> anyhow::Result<()> {
for file in project_or_files(args.project_dir, args.files)? {
let buf = fs::read_to_string(&file).with_context(|| format!("failed reading {file:?}"))?;

if let Err(e) = Schema::parse(&buf, Some(&file)).wrap_err("failed parsing schema file") {
eprintln!("{e:?}");
}
}

Ok(())
}

fn format(patterns: Vec<String>) -> Result<()> {
for pattern in patterns {
for entry in glob::glob(&pattern)
.into_diagnostic()
.wrap_err("Failed parsing glob pattern")?
{
let entry = entry.into_diagnostic().wrap_err("Failed reading entry")?;
let buf = fs::read_to_string(&entry).into_diagnostic()?;
let schema =
match Schema::parse(&buf, Some(&entry)).wrap_err("Failed parsing schema file") {
Ok(schema) => schema,
Err(e) => {
eprintln!("{e:?}");
continue;
}
};

let formatted = schema.to_string();

if buf != formatted {
fs::write(entry, &formatted).into_diagnostic()?;
fn format(args: FmtArgs) -> anyhow::Result<()> {
for file in project_or_files(args.project_dir, args.files)? {
let buf = fs::read_to_string(&file)?;
let schema = match Schema::parse(&buf, Some(&file)).wrap_err("Failed parsing schema file") {
Ok(schema) => schema,
Err(e) => {
eprintln!("{e:?}");
continue;
}
};

let formatted = schema.to_string();

if buf != formatted {
fs::write(file, &formatted)?;
}
}

Ok(())
}

fn doc(args: DocArgs) -> anyhow::Result<()> {
let project = mabo_project::load(project_dir(args.project_dir)?)?;

for file in project.files {
let content = std::fs::read_to_string(&file)?;
let schema = mabo_parser::Schema::parse(&content, Some(&file))?;
let schema = mabo_compiler::simplify_schema(&schema);
let docs = mabo_doc::render_schema(&mabo_doc::Opts {}, &schema)?;

write_doc_output(&docs, &args.out_dir.join(docs.name))?;
}

Ok(())
}

fn write_doc_output(output: &mabo_doc::Output<'_>, parent: &Path) -> anyhow::Result<()> {
let path = parent.join(output.name);
let file = parent.join(&output.file);

fs::create_dir_all(file.parent().unwrap())?;
fs::write(file, &output.content)?;

for module in &output.modules {
write_doc_output(module, &path)?;
}

Ok(())
}

fn project_or_files(
project: Option<PathBuf>,
patterns: Vec<String>,
) -> anyhow::Result<Vec<PathBuf>> {
Ok(if patterns.is_empty() {
mabo_project::load(project_dir(project)?)?.files
} else {
let mut files = Vec::new();
for pattern in patterns {
for entry in glob::glob(&pattern).context("failed parsing glob pattern")? {
let entry = entry.context("failed reading entry")?;
if !entry.extension().map_or(false, |ext| ext == "mabo") {
continue;
}
files.push(entry);
}
}
files
})
}

fn project_dir(arg: Option<PathBuf>) -> anyhow::Result<PathBuf> {
arg.map_or_else(
|| std::env::current_dir().context("failed finding current directory"),
Ok,
)
}
2 changes: 1 addition & 1 deletion crates/mabo-compiler/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@ license.workspace = true
[dependencies]
anstream.workspace = true
anstyle.workspace = true
mabo-parser = { path = "../mabo-parser" }
miette.workspace = true
schemars = { version = "0.8.16", optional = true }
serde = { workspace = true, optional = true }
serde_json = { workspace = true, optional = true }
mabo-parser = { path = "../mabo-parser" }
thiserror.workspace = true

[dev-dependencies]
Expand Down
4 changes: 2 additions & 2 deletions crates/mabo-go/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@ repository.workspace = true
license.workspace = true

[dependencies]
anyhow.workspace = true
clap.workspace = true
heck = "0.4.1"
miette = { workspace = true, features = ["fancy-no-backtrace"] }
mabo-compiler = { path = "../mabo-compiler" }
mabo-parser = { path = "../mabo-parser" }
mabo-project = { path = "../mabo-project" }
miette = { workspace = true, features = ["fancy-no-backtrace"] }
mimalloc.workspace = true
anyhow.workspace = true

[dev-dependencies]
insta.workspace = true
Expand Down
10 changes: 5 additions & 5 deletions crates/mabo-lsp/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,15 @@ line-index = "0.1.1"
log = { version = "0.4.20", features = ["kv_unstable_std", "std"] }
lsp-server = "0.7.6"
lsp-types = { version = "0.95.0", features = ["proposed"] }
ouroboros = "0.18.2"
parking_lot = "0.12.1"
ropey = "1.6.1"
serde.workspace = true
serde_json.workspace = true
mabo-compiler = { path = "../mabo-compiler" }
mabo-meta = { path = "../mabo-meta" }
mabo-parser = { path = "../mabo-parser" }
mabo-project = { path = "../mabo-project" }
ouroboros = "0.18.2"
parking_lot = "0.12.1"
ropey = "1.6.1"
serde_json.workspace = true
serde.workspace = true
time = { version = "0.3.31", features = ["formatting", "local-offset", "macros"] }

[lints]
Expand Down
2 changes: 1 addition & 1 deletion crates/mabo-parser/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ rustc-args = ["--cfg", "docsrs"]
[dependencies]
anstream.workspace = true
anstyle.workspace = true
miette.workspace = true
mabo-derive = { path = "../mabo-derive" }
miette.workspace = true
winnow = "0.5.33"

[dev-dependencies]
Expand Down

0 comments on commit 03cdc30

Please sign in to comment.