From 298c04f83e42192b69f1889373524d6dfb8872b0 Mon Sep 17 00:00:00 2001 From: PerishCode Date: Tue, 9 Jun 2026 18:27:45 +0800 Subject: [PATCH] tool: tighten help consistency --- app/src/core/tool/help/basic.rs | 158 +++++++++++++++++++++++++++++--- app/src/core/tool/help/mod.rs | 12 ++- app/tests/internal_tool.rs | 10 +- 3 files changed, 165 insertions(+), 15 deletions(-) diff --git a/app/src/core/tool/help/basic.rs b/app/src/core/tool/help/basic.rs index 3ae27fa..f6121a9 100644 --- a/app/src/core/tool/help/basic.rs +++ b/app/src/core/tool/help/basic.rs @@ -27,9 +27,55 @@ pub const JSON: Entry = Entry { pub const JSON_GET: Entry = Entry { key: "json.get", usage: "runseal @tool json get ", - about: None, + about: Some("Print one JSON value selected by the path expression."), + sections: &[Section { + title: "Arguments", + items: &[ + ("", "input JSON text"), + ("", "path expression such as `.[0].databaseId`"), + ], + }], + examples: &["runseal @tool json get '[{\"databaseId\":123}]' '.[0].databaseId'"], +}; + +pub const JSON_EMPTY: Entry = Entry { + key: "json.empty", + usage: "runseal @tool json empty ", + about: Some("Print `true` when the JSON array, object, or string length is zero."), sections: &[], - examples: &[], + examples: &["runseal @tool json empty '[]'"], +}; + +pub const JSON_LEN: Entry = Entry { + key: "json.len", + usage: "runseal @tool json len ", + about: Some("Print the JSON array, object, or string length as an integer."), + sections: &[], + examples: &["runseal @tool json len '[1,2,3]'"], +}; + +pub const JSON_PRETTY: Entry = Entry { + key: "json.pretty", + usage: "runseal @tool json pretty ", + about: Some("Print formatted JSON with indentation."), + sections: &[], + examples: &["runseal @tool json pretty '{\"a\":1}'"], +}; + +pub const JSON_FIND: Entry = Entry { + key: "json.find", + usage: "runseal @tool json find ", + about: Some("Print the first object in the JSON array with ` == `."), + sections: &[], + examples: &["runseal @tool json find '[{\"id\":1}]' id 1"], +}; + +pub const JSON_FILTER: Entry = Entry { + key: "json.filter", + usage: "runseal @tool json filter ...", + about: Some("Print objects in the JSON array whose `` matches any provided value."), + sections: &[], + examples: &["runseal @tool json filter '[{\"env\":\"dev\"},{\"env\":\"prod\"}]' env dev prod"], }; pub const STRING: Entry = Entry { @@ -168,10 +214,10 @@ pub const ARCHIVE_LOCAL: Entry = Entry { examples: &[], }; -pub const ARCHIVE_LOCAL_COMMAND: Entry = Entry { +pub const ARCHIVE_LOCAL_EXPORT: Entry = Entry { key: "archive.local.export", - usage: "runseal @tool archive local export|import --source --archive (--password |--password-env ) [--force]", - about: Some("Encrypt or decrypt a .local-style directory archive."), + usage: "runseal @tool archive local export --source --archive (--password |--password-env )", + about: Some("Encrypt one .local-style directory archive."), sections: &[Section { title: "Flags", items: &[ @@ -185,13 +231,36 @@ pub const ARCHIVE_LOCAL_COMMAND: Entry = Entry { "--password-env ", "read the password from one environment variable", ), + ], + }], + examples: &[ + "runseal @tool archive local export --source .local --archive backup.seal --password-env ESTATE_LOCAL_PASSWORD", + ], +}; + +pub const ARCHIVE_LOCAL_IMPORT: Entry = Entry { + key: "archive.local.import", + usage: "runseal @tool archive local import --source --archive (--password |--password-env ) [--force]", + about: Some("Decrypt one .local-style directory archive into the source directory."), + sections: &[Section { + title: "Flags", + items: &[ + ("--source ", "destination directory to restore into"), + ("--archive ", "archive file to read"), + ("--password ", "explicit archive password"), + ( + "--password-env ", + "read the password from one environment variable", + ), ( "--force", - "allow overwriting the destination archive or restore target", + "allow replacing an existing destination directory", ), ], }], - examples: &[], + examples: &[ + "runseal @tool archive local import --source .local --archive backup.seal --password-env ESTATE_LOCAL_PASSWORD --force", + ], }; pub const FS: Entry = Entry { @@ -302,12 +371,77 @@ pub const GITEE_PR: Entry = Entry { examples: &[], }; -pub const GITEE_PR_COMMAND: Entry = Entry { +pub const GITEE_PR_CREATE: Entry = Entry { key: "gitee.pr.create", - usage: "runseal @tool gitee pr create|pass-gates|merge ...", - about: None, - sections: &[], - examples: &[], + usage: "runseal @tool gitee pr create --owner --repo --base --head --title --body [--token |--token-file ]", + about: Some("Create a Gitee pull request and print the API response JSON."), + sections: &[Section { + title: "Flags", + items: &[ + ("--owner ", "Gitee repository owner"), + ("--repo ", "Gitee repository name"), + ("--base ", "target branch"), + ("--head ", "source branch"), + ("--title ", "pull request title"), + ("--body ", "pull request body"), + ("--token ", "explicit Gitee token"), + ( + "--token-file ", + "env-style file containing `GITEE_TOKEN`", + ), + ], + }], + examples: &[ + "runseal @tool gitee pr create --owner perishme --repo perish.top --base main --head auto/demo --title demo --body demo", + ], +}; + +pub const GITEE_PR_PASS_GATES: Entry = Entry { + key: "gitee.pr.pass-gates", + usage: "runseal @tool gitee pr pass-gates --owner --repo --number [--token |--token-file ]", + about: Some("Best-effort pass available Gitee PR gates and print the result JSON."), + sections: &[Section { + title: "Flags", + items: &[ + ("--owner ", "Gitee repository owner"), + ("--repo ", "Gitee repository name"), + ("--number ", "pull request number"), + ("--token ", "explicit Gitee token"), + ( + "--token-file ", + "env-style file containing `GITEE_TOKEN`", + ), + ], + }], + examples: &[ + "runseal @tool gitee pr pass-gates --owner perishme --repo perish.top --number 123", + ], +}; + +pub const GITEE_PR_MERGE: Entry = Entry { + key: "gitee.pr.merge", + usage: "runseal @tool gitee pr merge --owner --repo --number [--method ] [--token |--token-file ]", + about: Some("Merge a Gitee pull request and print the API response JSON."), + sections: &[Section { + title: "Flags", + items: &[ + ("--owner ", "Gitee repository owner"), + ("--repo ", "Gitee repository name"), + ("--number ", "pull request number"), + ( + "--method ", + "merge method; default `squash`", + ), + ("--token ", "explicit Gitee token"), + ( + "--token-file ", + "env-style file containing `GITEE_TOKEN`", + ), + ], + }], + examples: &[ + "runseal @tool gitee pr merge --owner perishme --repo perish.top --number 123 --method squash", + ], }; pub const GITHUB: Entry = Entry { diff --git a/app/src/core/tool/help/mod.rs b/app/src/core/tool/help/mod.rs index 6409ed3..16157b5 100644 --- a/app/src/core/tool/help/mod.rs +++ b/app/src/core/tool/help/mod.rs @@ -20,6 +20,11 @@ pub struct Section { const ENTRIES: &[Entry] = &[ basic::JSON, basic::JSON_GET, + basic::JSON_EMPTY, + basic::JSON_LEN, + basic::JSON_PRETTY, + basic::JSON_FIND, + basic::JSON_FILTER, basic::STRING, basic::STRING_TRIM, basic::STRING_JOIN, @@ -32,14 +37,17 @@ const ENTRIES: &[Entry] = &[ basic::PROCESS_EXISTS, basic::ARCHIVE, basic::ARCHIVE_LOCAL, - basic::ARCHIVE_LOCAL_COMMAND, + basic::ARCHIVE_LOCAL_EXPORT, + basic::ARCHIVE_LOCAL_IMPORT, basic::FS, basic::FS_LIST, basic::GITEE, basic::GITEE_REPO, basic::GITEE_REPO_PARSE_ORIGIN, basic::GITEE_PR, - basic::GITEE_PR_COMMAND, + basic::GITEE_PR_CREATE, + basic::GITEE_PR_PASS_GATES, + basic::GITEE_PR_MERGE, basic::GITHUB, basic::GITHUB_PR, basic::GITHUB_PR_CHECKS, diff --git a/app/tests/internal_tool.rs b/app/tests/internal_tool.rs index 7b11bd3..3792253 100644 --- a/app/tests/internal_tool.rs +++ b/app/tests/internal_tool.rs @@ -90,7 +90,7 @@ fn tool_help_is_progressive() { ), ( vec!["@tool", "json", "get", "--help"], - "usage: runseal @tool json get ", + "Usage: runseal @tool json get ", ), ( vec!["@tool", "string", "--help"], @@ -183,6 +183,14 @@ fn richer_help() { vec!["@tool", "github", "pr", "checks", "probe", "--help"], "usage: runseal @tool github pr checks probe ", ), + ( + vec!["@tool", "gitee", "pr", "merge", "--help"], + "Merge a Gitee pull request and print the API response JSON.", + ), + ( + vec!["@tool", "archive", "local", "import", "--help"], + "Decrypt one .local-style directory archive into the source directory.", + ), ] { let output = bin() .current_dir(&cwd)