From d980ff8feaa7d58ad8567c5dba706cd2b82147fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Haudebourg?= Date: Thu, 4 Apr 2024 18:12:06 +0200 Subject: [PATCH] Add cli documentation. --- README.md | 84 +++++++++++++++++++++++++++++++++++++++++++--- src/format/rdf.rs | 37 ++++++++++---------- src/format/tree.rs | 36 ++++++++++---------- src/main.rs | 8 ++--- test.json | 1 - 5 files changed, 118 insertions(+), 48 deletions(-) delete mode 100644 test.json diff --git a/README.md b/README.md index f6aab92..1864fcb 100644 --- a/README.md +++ b/README.md @@ -18,20 +18,94 @@ level. > generators. We will reintroduce the missing DSL and generators in future > updates. -## Installation +## Install -You will need [Rust](https://rust-lang.org) 1.70 or later +You will need [Rust](https://rust-lang.org) 1.74 or later to install TreeLDR, with [cargo](https://doc.rust-lang.org/cargo/). TreeLDR can be installed from the source by first cloning the git repository: -``` -git clone https://github.com/spruceid/treeldr.git +```console +$ git clone https://github.com/spruceid/treeldr.git ``` This repository contains the different libraries and executables composing the TreeLDR framework. You can then build everything from the repository root: +```console +$ cargo build +``` + +Alternatively if you want to install the binaries on you computer, use +```console +$ cargo install --path . ``` -cargo build + +## Usage + +The top-level package provides a command-line interface which can use TreeLDR +layouts to serialize or deserialize tree value (like JSON), or generate code. +If you want to use TreeLDR layouts directly in your code, use the +[`treeldr-layouts` library](treeldr-layouts). + +In this section, the `tldr` command can be replaced with `cargo run -- ` if +you chose not to install the binary. + +### Deserialization + +Use the `dehydrate` subcommand to turn any *tree value* (JSON) into an RDF +dataset using a given layout. +The input tree is read from the standard input, and the output written to the +standard output. + +```console +$ tldr path/to/layout.json dehydrate +``` + +Example layouts are found in the `layouts/examples` folder. + +You can specify the input (tree) format using the `-i` option after `dehydrate`. +Similarly, you can specify the output (RDF) format using the `-o` option. +Supported formats are given in the [#supported-formats] section below. + +### Serialization + +Use `hydrate` subcommand to turn any *RDF dataset* into a tree value (JSON) +using a given layout. +The input dataset is read from the standard input, and the output written to the +standard output. + +```console +$ tldr path/to/layout.json hydrate +``` + +Example layouts are found in the `layouts/examples` folder. + +You can specify the input (RDF) format using the `-i` option after `hydrate`. +Similarly, you can specify the output (tree) format using the `-o` option. +Supported formats are given in the [#supported-formats] section below. + +### Supported formats + +The following table lists all the tree formats supported by TreeLDR. +The "Option value" can be given to the `-i` option of the `dehydrate` +subcommand, or the `-o` option of the `hydrate` subcommand. + +| Tree format | Option value(s) | +| ----------- | ------------------------------------------------ | +| JSON | `application/json`, `json` | + +The following table lists all the RDF formats supported by TreeLDR. +The "Option value" can be given to the `-i` option of the `hydrate` subcommand, +or the `-i` option of the `dehydrate` subcommand. + +| RDF format | Option value(s) | +| ----------- | ------------------------------------------------ | +| N-Quads | `application/n-quads`, `n-quads`, `nquads`, `nq` | + +## Tesing + +To run all the tests, use the following command: +```console +$ cargo test --workspace --all-features ``` \ No newline at end of file diff --git a/src/format/rdf.rs b/src/format/rdf.rs index 43b7170..c3d586f 100644 --- a/src/format/rdf.rs +++ b/src/format/rdf.rs @@ -1,17 +1,11 @@ use core::fmt; -use std::{ - io::{self, BufRead, Write}, - str::FromStr, -}; +use std::io::{self, BufRead, Write}; +use clap::builder::TypedValueParser; use locspan::Span; use nquads_syntax::Parse; use rdf_types::dataset::BTreeDataset; -#[derive(Debug, thiserror::Error)] -#[error("unknown RDF format `{0}`")] -pub struct UnknownRDFFormat(String); - #[derive(Debug, thiserror::Error)] pub enum LoadError { #[error("N-Quads parse error: {0}")] @@ -26,6 +20,22 @@ pub enum RDFFormat { } impl RDFFormat { + pub const POSSIBLE_VALUES: &'static [&'static str] = + &["application/n-quads", "n-quads", "nquads", "nq"]; + + pub fn parser( + ) -> clap::builder::MapValueParser Self> { + clap::builder::PossibleValuesParser::new(Self::POSSIBLE_VALUES) + .map(|s| Self::new(&s).unwrap()) + } + + pub fn new(name: &str) -> Option { + match name { + "nq" | "nquads" | "n-quads" | "application/n-quads" => Some(Self::NQuads), + _ => None, + } + } + pub fn as_str(&self) -> &'static str { match self { Self::NQuads => "application/n-quads", @@ -65,14 +75,3 @@ impl fmt::Display for RDFFormat { self.as_str().fmt(f) } } - -impl FromStr for RDFFormat { - type Err = UnknownRDFFormat; - - fn from_str(s: &str) -> Result { - match s { - "nq" | "nquads" | "n-quads" | "application/n-quads" => Ok(Self::NQuads), - _ => Err(UnknownRDFFormat(s.to_owned())), - } - } -} diff --git a/src/format/tree.rs b/src/format/tree.rs index 4326eb6..c9afd88 100644 --- a/src/format/tree.rs +++ b/src/format/tree.rs @@ -1,16 +1,10 @@ use core::fmt; -use std::{ - io::{self, BufRead, Write}, - str::FromStr, -}; +use std::io::{self, BufRead, Write}; +use clap::builder::TypedValueParser; use json_syntax::Print; use treeldr_layouts::value::NonJsonValue; -#[derive(Debug, thiserror::Error)] -#[error("unknown tree format `{0}`")] -pub struct UnknownTreeFormat(String); - #[derive(Debug, thiserror::Error)] pub enum LoadError { #[error("JSON parse error: {0}")] @@ -32,6 +26,21 @@ pub enum TreeFormat { } impl TreeFormat { + pub const POSSIBLE_VALUES: &'static [&'static str] = &["application/json", "json"]; + + pub fn parser( + ) -> clap::builder::MapValueParser Self> { + clap::builder::PossibleValuesParser::new(Self::POSSIBLE_VALUES) + .map(|s| Self::new(&s).unwrap()) + } + + pub fn new(name: &str) -> Option { + match name { + "json" | "application/json" => Some(Self::Json), + _ => None, + } + } + pub fn as_str(&self) -> &'static str { match self { Self::Json => "application/json", @@ -77,14 +86,3 @@ impl fmt::Display for TreeFormat { self.as_str().fmt(f) } } - -impl FromStr for TreeFormat { - type Err = UnknownTreeFormat; - - fn from_str(s: &str) -> Result { - match s { - "json" | "application/json" => Ok(Self::Json), - _ => Err(UnknownTreeFormat(s.to_owned())), - } - } -} diff --git a/src/main.rs b/src/main.rs index 4ead360..f0e8926 100644 --- a/src/main.rs +++ b/src/main.rs @@ -58,11 +58,11 @@ enum Command { /// Serializes an RDF dataset into a tree value. Hydrate { /// Format of the input RDF dataset. - #[arg(short, long, default_value = "n-quads")] + #[arg(short, long, value_parser = RDFFormat::parser(), default_value = "n-quads")] input: RDFFormat, /// Format of the output tree value. - #[arg(short, long, default_value = "json")] + #[arg(short, long, value_parser = TreeFormat::parser(), default_value = "json")] output: TreeFormat, /// Serializing layout. @@ -85,11 +85,11 @@ enum Command { /// Deserializes a tree value into an RDF dataset. Dehydrate { /// Format of the input tree value. - #[clap(short, long, default_value = "json")] + #[arg(short, long, value_parser = TreeFormat::parser(), default_value = "json")] input: TreeFormat, /// Format of the output RDF dataset. - #[clap(short, long, default_value = "n-quads")] + #[arg(short, long, value_parser = RDFFormat::parser(), default_value = "n-quads")] output: RDFFormat, /// Deserializing layout. diff --git a/test.json b/test.json deleted file mode 100644 index e53cd86..0000000 --- a/test.json +++ /dev/null @@ -1 +0,0 @@ -{ "id": "https://example.org/#bob", "name": "Bob" }