From 8c12ae96474ec8f82e9baa7812899108fa47b46f Mon Sep 17 00:00:00 2001 From: Philip Z Date: Sun, 6 Sep 2026 16:00:06 +0800 Subject: [PATCH] fix(cli): make root help task-oriented Closes #5 --- README.md | 61 ++++++++++++++++++++++++++++++++--------------- src/cli.rs | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 107 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index 45572ec..5ea1664 100644 --- a/README.md +++ b/README.md @@ -2,31 +2,50 @@ [![OpenSSF Best Practices](https://www.bestpractices.dev/projects/13620/badge)](https://www.bestpractices.dev/projects/13620) -Rust CLI for TeaQL code generation workflows. +Rust CLI for evaluating TeaQL semantic models, generating language-native +libraries and workspaces, and discovering generated APIs through model-aware +Assist. ## Commands ```bash -cargo-teaql - -# Examples: -cargo-teaql java-app-console ./model -cargo-teaql rust-lib-core ./model -cargo-teaql services -cargo-teaql version -cargo-teaql show-config -cargo-teaql config -cargo-teaql install-links +# Discover the targets currently offered by the service. +cargo teaql services + +# Evaluate before generation. +cargo teaql evaluate --input models/ + +# Generate a library or runnable workspace. +cargo teaql rust-lib-core --input models/ --output build/ +cargo teaql java-app-console --input models/ --output build/ + +# Discover the generated API progressively. +cargo teaql rust-assist-query/school --input models/ +cargo teaql rust-assist-query/school.established_date --input models/ + +# Local maintenance commands. +cargo teaql show-config +cargo teaql config +cargo teaql ping +cargo teaql check --tests ``` -The CLI supports dynamic command routing. If the target service is not a built-in command, the CLI will automatically forward the request to the backend. If an input path is provided, it acts as a code generation target (e.g. `java-app-console`). If no input path is provided, it acts as a general GET request (e.g. `services`). +Generation and Assist targets are provided dynamically by the TeaQL service, +so the fixed `Commands` list in `--help` is not their complete inventory. Run +`cargo teaql services` to discover the current targets and `cargo teaql version` +to inspect their versions. + +Use `--input` for the KSML model file or directory. A dynamic target with model +input performs evaluation, generation, or Assist; a remote information target +such as `services` or `version` performs a GET request. -If no arguments are provided at all, it automatically defaults to `cargo-teaql services`. +If no command is provided, the CLI defaults to `cargo teaql services`. +`cargo-teaql` is an equivalent direct invocation. ### CLI flags ```bash -cargo-teaql java-app-console \ +cargo teaql java-app-console --input models/ \ --endpoint-prefix https://api.teaql.io/latest/ \ --api-key ******** \ --output ./build \ @@ -43,7 +62,7 @@ However, if a directory is provided but it **does not contain a `main.xml`**, th If you create symlink aliases to the same binary, these names also work: ```bash -cargo teaql-java-app-console +cargo teaql-java-app-console --input models/ cargo teaql-services cargo teaql-version cargo teaql-show-config @@ -62,8 +81,11 @@ You can also target a custom directory with `cargo-teaql install-links --dir /so TeaQL provides specialized assist commands designed to help AI coding agents (and developers) quickly generate safe, compliant boilerplate templates for various business scenarios. -The command format is: -`cargo-teaql -assist-/ --input ` +The entity-level command format is: +`cargo teaql -assist-/ --input ` + +For field-specific help, append the KSML field name: +`cargo teaql -assist-/. --input ` Currently supported `rust-assist-*` targets: - `rust-assist-query`: Generate a comprehensive query template with field selections and mandatory `.purpose()`/`.comment()` cascades. @@ -77,8 +99,9 @@ Currently supported `rust-assist-*` targets: **Example Usage:** ```bash -cargo-teaql rust-assist-query/book --input modeling/bookstore.xml -cargo-teaql java-assist-create/customer --input modeling/bookstore.xml +cargo teaql rust-assist-query/book --input modeling/bookstore.xml +cargo teaql rust-assist-query/book.published_at --input modeling/bookstore.xml +cargo teaql java-assist-create/customer --input modeling/bookstore.xml ``` ## Configuration diff --git a/src/cli.rs b/src/cli.rs index 9d8909a..f20125b 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -3,38 +3,72 @@ use std::path::PathBuf; use clap::{Args, Parser, Subcommand}; +const ROOT_USAGE: &str = "cargo teaql [OPTIONS] [COMMAND]\n cargo teaql [OPTIONS] --input [--output ]\n cargo teaql [OPTIONS] -assist-/[.] --input "; + +const ROOT_EXAMPLES: &str = r#"REMOTE WORKFLOWS (dynamic commands): + Discover the targets and versions currently provided by the TeaQL service: + cargo teaql services + cargo teaql version + + Evaluate a KSML model before generation: + cargo teaql evaluate --input models/ + + Generate a typed library or runnable workspace: + cargo teaql rust-lib-core --input models/ --output build/ + cargo teaql typescript-app-console --input models/ --output build/ + + Ask model-aware Assist about an entity or one field: + cargo teaql rust-assist-query/school --input models/ + cargo teaql rust-assist-query/school.established_date --input models/ + +Run `cargo teaql services` for the current remote target inventory. +With no command, TeaQL runs `services`. `cargo-teaql` is an equivalent invocation."#; + #[derive(Debug, Parser)] #[command( name = "teaql", version, - about = "TeaQL toolchain", + about = "Evaluate TeaQL models, generate typed applications, and discover model-aware APIs", + long_about = "TeaQL turns a KSML semantic model into evaluated, language-native libraries and runnable workspaces. It also provides progressive, model-aware Assist for discovering the generated API without reading generated source.", + override_usage = ROOT_USAGE, + after_help = ROOT_EXAMPLES, disable_help_subcommand = true )] pub struct Cli { + /// Workspace directory used by local commands and relative output paths. #[arg(long, global = true, default_value = ".")] pub cwd: PathBuf, + /// Show configuration sources and request progress. #[arg(long, short, global = true)] pub verbose: bool, + /// Show additional diagnostic details. #[arg(long, global = true)] pub debug: bool, + /// KSML model file or directory; multi-file models use the directory containing main.xml. #[arg(long, global = true)] pub input: Option, + /// TeaQL service endpoint prefix, for example https://api.teaql.io/latest/. #[arg(long, global = true)] pub endpoint_prefix: Option, + /// Deprecated alias for --endpoint-prefix. #[arg(long, global = true)] + #[arg(hide = true)] pub service_url: Option, + /// TeaQL API key; the built-in free-tier key is used by default. #[arg(long, global = true)] pub api_key: Option, + /// Generated output directory; relative paths are resolved from --cwd. #[arg(long, global = true)] pub output: Option, + /// Remote request timeout in seconds. #[arg(long, global = true)] pub timeout_seconds: Option, @@ -44,13 +78,13 @@ pub struct Cli { #[derive(Debug, Subcommand)] pub enum Commands { - /// Show effective local config. + /// Show the saved workspace configuration and its file path. ShowConfig, - /// Configure TeaQL in the current workspace. + /// Interactively configure TeaQL for the current workspace. Config, - /// Ping the TeaQL service. + /// Verify service connectivity with a built-in model round trip. Ping(ServiceArgs), - /// Install symlink aliases for cargo-style command names. + /// Install executable aliases used by cargo-style invocation. InstallLinks(InstallLinksArgs), /// Run cargo check and map any compiler errors back to the source KSML (XML) file. Check(CheckArgs), @@ -167,3 +201,29 @@ pub struct InstallLinksArgs { #[arg(long)] pub force: bool, } + +#[cfg(test)] +mod tests { + use clap::CommandFactory; + + use super::Cli; + + #[test] + fn root_help_exposes_primary_workflows() { + let help = Cli::command().render_long_help().to_string(); + + assert!(help.contains("cargo teaql evaluate --input models/")); + assert!(help.contains("cargo teaql rust-lib-core --input models/")); + assert!(help.contains("rust-assist-query/school.established_date")); + assert!(help.contains("cargo teaql services")); + } + + #[test] + fn root_help_explains_global_options_without_deprecated_alias() { + let help = Cli::command().render_long_help().to_string(); + + assert!(help.contains("KSML model file or directory")); + assert!(help.contains("relative paths are resolved from --cwd")); + assert!(!help.contains("--service-url")); + } +}