mirror of
https://github.com/tiennm99/tiennm99bot.git
synced 2026-10-11 03:13:46 +00:00
refactor(commands): standardize parameter conventions
This commit is contained in:
1 parent
a211b7f8b7
commit
d2c3129d41
10 files changed
+329
-21
No files matched your search
@@ -29,11 +29,8 @@ deleting commands, update all related surfaces:
|
|||||||
- tests for registration, handlers, and command menu behavior
|
- tests for registration, handlers, and command menu behavior
|
||||||
- README/docs when behavior changes are user-visible
|
- README/docs when behavior changes are user-visible
|
||||||
|
|
||||||
Use lowercase, descriptive parameter names in command metadata and usage text.
|
Follow `docs/command-parameter-conventions.md` for all command parameter
|
||||||
Include units or currencies when meaningful (for example, `<vnd_amount>`), use
|
metadata and usage text. Keep metadata, usage errors, examples, and tests exact.
|
||||||
`[...]` for optional input, append `...` for remaining free text, and use
|
|
||||||
parentheses to document structured input (for example,
|
|
||||||
`<ratio(owned:new)>`). Keep metadata, usage errors, examples, and tests exact.
|
|
||||||
Telegram's native menu and `/help` show command syntax plus the summary without
|
Telegram's native menu and `/help` show command syntax plus the summary without
|
||||||
example invocations.
|
example invocations.
|
||||||
|
|
||||||
|
|||||||
@@ -33,12 +33,9 @@ description:
|
|||||||
`/help` combines the full command syntax and summary on one line. Neither
|
`/help` combines the full command syntax and summary on one line. Neither
|
||||||
discovery surface includes example invocations.
|
discovery surface includes example invocations.
|
||||||
|
|
||||||
For future commands, use lowercase descriptive parameter names. Include units
|
Future commands must follow the
|
||||||
or currencies when they affect meaning (`<vnd_amount>`, `<usd_to_spend>`), use
|
[command parameter conventions](docs/command-parameter-conventions.md). Keep
|
||||||
square brackets for optional input (`[date]`), append `...` when an argument
|
command metadata, handler usage text, tests, and documentation aligned.
|
||||||
accepts remaining text (`[target...]`), and describe structured input in
|
|
||||||
parentheses (`<ratio(owned:new)>`, `<options(comma-separated)>`). Keep command
|
|
||||||
metadata, handler usage text, tests, and this documentation aligned.
|
|
||||||
|
|
||||||
### Stock dividend commands
|
### Stock dividend commands
|
||||||
|
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ func TestCommandDiscovery_AllPublicCommandsHaveSafeMetadata(t *testing.T) {
|
|||||||
"gold_sell": "<luong>",
|
"gold_sell": "<luong>",
|
||||||
"lol": "[date]",
|
"lol": "[date]",
|
||||||
"loldle": "[champion]",
|
"loldle": "[champion]",
|
||||||
"random": "<options(comma-separated)>",
|
"random": "<option,...>",
|
||||||
"stats": "[users | user <username> | cmd <command_name>]",
|
"stats": "[users | user <username> | cmd <command_name>]",
|
||||||
"stock_price": "<ticker>",
|
"stock_price": "<ticker>",
|
||||||
"stock_topup": "<vnd_amount>",
|
"stock_topup": "<vnd_amount>",
|
||||||
@@ -78,7 +78,7 @@ func TestCommandDiscovery_AllPublicCommandsHaveSafeMetadata(t *testing.T) {
|
|||||||
"stock_dividend": "<vnd_per_share> <ratio(owned:new)> <ticker>",
|
"stock_dividend": "<vnd_per_share> <ratio(owned:new)> <ticker>",
|
||||||
"trongtruonghop": "[target...]",
|
"trongtruonghop": "[target...]",
|
||||||
"tth": "[target...]",
|
"tth": "[target...]",
|
||||||
"wheelofnames": "<options(comma-separated)>",
|
"wheelofnames": "<option,...>",
|
||||||
"wordle": "[word]",
|
"wordle": "[word]",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,72 @@
|
|||||||
|
# Command Parameter Conventions
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
Every Telegram command declares optional `Parameters` metadata. The bot reuses
|
||||||
|
that string in `/help` and Telegram's native command menu, so it must be short,
|
||||||
|
consistent, and understandable on a phone.
|
||||||
|
|
||||||
|
Treat `Parameters` as display syntax, not as a validation schema. Handlers
|
||||||
|
remain responsible for parsing and validation.
|
||||||
|
|
||||||
|
## Syntax
|
||||||
|
|
||||||
|
| Meaning | Format | Example |
|
||||||
|
|---|---|---|
|
||||||
|
| Required value | `<name>` | `<ticker>` |
|
||||||
|
| Required comma-separated values | `<name,...>` | `<option,...>` |
|
||||||
|
| Optional value | `[name]` | `[date]` |
|
||||||
|
| Optional remaining text | `[name...]` | `[target...]` |
|
||||||
|
| Alternatives in an optional group | `[literal | literal <name>]` | `[users | user <username>]` |
|
||||||
|
|
||||||
|
Use only constructs required by the command. Do not introduce a formal schema
|
||||||
|
language or extra punctuation without a user-facing need.
|
||||||
|
|
||||||
|
## Naming
|
||||||
|
|
||||||
|
- Use lowercase `snake_case`.
|
||||||
|
- Prefer one descriptive noun: `<ticker>`, `<quantity>`, `<champion>`.
|
||||||
|
- Include units or currencies when they prevent ambiguity: `<vnd_amount>`,
|
||||||
|
`<usd_to_spend>`.
|
||||||
|
- Do not add primitive types such as `<quantity:number>` or `<date:string>`.
|
||||||
|
- Keep literal subcommands bare: `users`, `user`, `cmd`.
|
||||||
|
- Put spaces around `|` in alternatives.
|
||||||
|
- Do not repeat format prose inside a placeholder.
|
||||||
|
- Show punctuation that users must type exactly when omitting it would be
|
||||||
|
error-prone. `<ratio(owned:new)>` and `<option,...>` are approved compact
|
||||||
|
shapes.
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
```text
|
||||||
|
/stock_buy <quantity> <ticker>
|
||||||
|
/lol [date]
|
||||||
|
/trongtruonghop [target...]
|
||||||
|
/stats [users | user <username> | cmd <command_name>]
|
||||||
|
/stock_share_dividend <ratio(owned:new)> <ticker>
|
||||||
|
/random <option,...>
|
||||||
|
```
|
||||||
|
|
||||||
|
## Change Checklist
|
||||||
|
|
||||||
|
When adding or changing a command:
|
||||||
|
|
||||||
|
1. Make `Parameters` match the handler's accepted argument order.
|
||||||
|
2. Keep the parameter string single-line and concise enough for Telegram's
|
||||||
|
command-description limit.
|
||||||
|
3. Update handler usage and error text to use the same syntax.
|
||||||
|
4. Update registration, handler, `/help`, and native-menu tests.
|
||||||
|
5. Update README or feature documentation when behavior is user-visible.
|
||||||
|
6. Follow the stats migration rules in `AGENTS.md` when a command name changes
|
||||||
|
or a command is deleted.
|
||||||
|
|
||||||
|
## References
|
||||||
|
|
||||||
|
- [POSIX.1-2024 utility conventions](https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap12.html)
|
||||||
|
- [GNU command-line interface standards](https://www.gnu.org/prep/standards/html_node/Command_002dLine-Interfaces.html)
|
||||||
|
- [Microsoft command-line syntax key](https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/command-line-syntax-key)
|
||||||
|
- [Python argparse documentation](https://docs.python.org/3/library/argparse.html)
|
||||||
|
- [docopt usage-pattern grammar](https://github.com/docopt/docopt/blob/master/README.rst)
|
||||||
|
|
||||||
|
The supporting project-specific analysis is in
|
||||||
|
[`plans/reports/260721-1418-command-parameter-schema-research.md`](../plans/reports/260721-1418-command-parameter-schema-research.md).
|
||||||
@@ -1,5 +1,10 @@
|
|||||||
# Telegram Command Discovery Journal
|
# Telegram Command Discovery Journal
|
||||||
|
|
||||||
|
> Historical note: the later command-parameter convention simplifies
|
||||||
|
> `<options(comma-separated)>` to `<option,...>`, keeping the literal delimiter
|
||||||
|
> visible without prose inside the placeholder. See
|
||||||
|
> `docs/command-parameter-conventions.md`.
|
||||||
|
|
||||||
## Context
|
## Context
|
||||||
|
|
||||||
Telegram's native command menu and `/help` exposed only short descriptions,
|
Telegram's native command menu and `/help` exposed only short descriptions,
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
# Command Parameter Conventions Journal
|
||||||
|
|
||||||
|
## Context
|
||||||
|
|
||||||
|
Command parameter labels had grown organically, especially for comma-separated
|
||||||
|
arguments. Researched common CLI notation to establish a minimal display syntax
|
||||||
|
for Telegram's native menu, `/help`, and handler usage text.
|
||||||
|
|
||||||
|
## What Changed
|
||||||
|
|
||||||
|
- Added the evergreen `docs/command-parameter-conventions.md` reference with
|
||||||
|
concise rules for required, optional, variadic, alternative, and structured
|
||||||
|
parameters.
|
||||||
|
- Recorded the user-selected `<option,...>` notation for required
|
||||||
|
comma-separated values.
|
||||||
|
- Updated `/random` and `/wheelofnames` metadata, usage text, and contract tests
|
||||||
|
from `<options(comma-separated)>` to `<option,...>`.
|
||||||
|
- Linked project guidance and README command-discovery documentation to the
|
||||||
|
shared convention reference.
|
||||||
|
|
||||||
|
## Reflection
|
||||||
|
|
||||||
|
The compact notation communicates both one-or-more values and the literal comma
|
||||||
|
separator without turning display metadata into a schema language. Keeping the
|
||||||
|
rules in an evergreen document avoids repeating policy in project instructions
|
||||||
|
and feature docs.
|
||||||
|
|
||||||
|
## Decisions
|
||||||
|
|
||||||
|
- Parameter strings remain presentation-only; handlers own validation.
|
||||||
|
- `/random` and `/wheelofnames` parsing and runtime behavior remain unchanged.
|
||||||
|
- Metadata, usage errors, and tests must use the same exact notation.
|
||||||
|
|
||||||
|
## Verification
|
||||||
|
|
||||||
|
- Passed: focused command-presentation and misc tests.
|
||||||
|
- Passed: `go test ./...`
|
||||||
|
- Passed: `go vet ./...`
|
||||||
|
- Passed: `go build ./...`
|
||||||
|
- Passed: `golangci-lint run`
|
||||||
|
|
||||||
|
## Next Steps
|
||||||
|
|
||||||
|
- Apply the evergreen conventions whenever command parameters change.
|
||||||
@@ -26,14 +26,14 @@ func TestCommandPresentation(t *testing.T) {
|
|||||||
menu: "Health check!",
|
menu: "Health check!",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "variadic parameters keep ellipsis",
|
name: "concise parameter name",
|
||||||
command: Command{
|
command: Command{
|
||||||
Name: "random",
|
Name: "random",
|
||||||
Parameters: "<options(comma-separated)>",
|
Parameters: "<option,...>",
|
||||||
Description: "Pick one option",
|
Description: "Pick one option",
|
||||||
},
|
},
|
||||||
invocation: "/random <options(comma-separated)>",
|
invocation: "/random <option,...>",
|
||||||
menu: "<options(comma-separated)>. Pick one option.",
|
menu: "<option,...>. Pick one option.",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import (
|
|||||||
"github.com/tiennm99/miti99bot/internal/modules/util/chathelper"
|
"github.com/tiennm99/miti99bot/internal/modules/util/chathelper"
|
||||||
)
|
)
|
||||||
|
|
||||||
const randomUsage = "Usage: /random <options(comma-separated)>"
|
const randomUsage = "Usage: /random <option,...>"
|
||||||
|
|
||||||
func splitWheelOptions(arg string) []string {
|
func splitWheelOptions(arg string) []string {
|
||||||
parts := strings.Split(arg, ",")
|
parts := strings.Split(arg, ",")
|
||||||
@@ -30,7 +30,7 @@ func randomCommand() modules.Command {
|
|||||||
Name: "random",
|
Name: "random",
|
||||||
Visibility: modules.VisibilityPublic,
|
Visibility: modules.VisibilityPublic,
|
||||||
Description: "Pick one random comma-separated option",
|
Description: "Pick one random comma-separated option",
|
||||||
Parameters: "<options(comma-separated)>",
|
Parameters: "<option,...>",
|
||||||
Handler: func(ctx context.Context, b *bot.Bot, update *models.Update) error {
|
Handler: func(ctx context.Context, b *bot.Bot, update *models.Update) error {
|
||||||
if update.Message == nil {
|
if update.Message == nil {
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ func wheelOfNamesCommand() modules.Command {
|
|||||||
Name: "wheelofnames",
|
Name: "wheelofnames",
|
||||||
Visibility: modules.VisibilityPublic,
|
Visibility: modules.VisibilityPublic,
|
||||||
Description: "Pick one comma-separated option with wheel GIF when configured",
|
Description: "Pick one comma-separated option with wheel GIF when configured",
|
||||||
Parameters: "<options(comma-separated)>",
|
Parameters: "<option,...>",
|
||||||
Handler: func(ctx context.Context, b *bot.Bot, update *models.Update) error {
|
Handler: func(ctx context.Context, b *bot.Bot, update *models.Update) error {
|
||||||
if update.Message == nil {
|
if update.Message == nil {
|
||||||
return nil
|
return nil
|
||||||
@@ -63,7 +63,7 @@ func wheelOfNamesCommand() modules.Command {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const wheelUsage = "Usage: /wheelofnames <options(comma-separated)>"
|
const wheelUsage = "Usage: /wheelofnames <option,...>"
|
||||||
|
|
||||||
func wheelResultCaption(result string) string {
|
func wheelResultCaption(result string) string {
|
||||||
result = truncateWheelResultCaption(result)
|
result = truncateWheelResultCaption(result)
|
||||||
|
|||||||
@@ -0,0 +1,193 @@
|
|||||||
|
---
|
||||||
|
type: research-report
|
||||||
|
conducted_at: 2026-07-21T14:18:00+07:00
|
||||||
|
scope: Telegram command discovery syntax
|
||||||
|
status: complete
|
||||||
|
---
|
||||||
|
|
||||||
|
# Research Report: Minimal Command Parameter Schema
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
Keep the project's current lightweight schema. It already matches familiar CLI
|
||||||
|
synopsis conventions closely enough:
|
||||||
|
|
||||||
|
```text
|
||||||
|
<name> required value
|
||||||
|
[name] optional value
|
||||||
|
[name...] optional remaining text
|
||||||
|
a | b alternatives inside one optional group
|
||||||
|
```
|
||||||
|
|
||||||
|
Do not add types such as `<quantity:number>`. Common CLI usage lines describe
|
||||||
|
structure, not a type system. Use a descriptive name (`<quantity>`,
|
||||||
|
`<vnd_amount>`) and put validation details in the summary or usage error.
|
||||||
|
|
||||||
|
Only one current notation is needlessly heavy. After project-owner review, the
|
||||||
|
approved compact replacement is:
|
||||||
|
|
||||||
|
```text
|
||||||
|
<options(comma-separated)> -> <option,...>
|
||||||
|
```
|
||||||
|
|
||||||
|
This keeps the literal comma visible without putting prose inside the
|
||||||
|
placeholder. Keep `<ratio(owned:new)>` for the same reason: the separator is
|
||||||
|
essential input syntax and the concise shape prevents a likely user error.
|
||||||
|
|
||||||
|
## Contents
|
||||||
|
|
||||||
|
- [Scope and method](#scope-and-method)
|
||||||
|
- [Evidence](#evidence)
|
||||||
|
- [Recommended schema](#recommended-schema)
|
||||||
|
- [Current command audit](#current-command-audit)
|
||||||
|
- [Rejected alternatives](#rejected-alternatives)
|
||||||
|
- [Next steps](#next-steps)
|
||||||
|
- [References](#references)
|
||||||
|
- [Unresolved questions](#unresolved-questions)
|
||||||
|
|
||||||
|
## Scope and Method
|
||||||
|
|
||||||
|
Evaluated only the syntax displayed after `/command` in Telegram's native menu
|
||||||
|
and `/help`. Criteria, in order:
|
||||||
|
|
||||||
|
1. Understandable without a legend
|
||||||
|
2. Minimal visual noise on a phone
|
||||||
|
3. Accurate to the parser
|
||||||
|
4. Consistent across commands
|
||||||
|
5. Familiar to terminal users
|
||||||
|
|
||||||
|
Sources span POSIX.1-2024, current GNU guidance, Python 3.14 documentation,
|
||||||
|
Microsoft's command-line syntax key, docopt's usage grammar, and Telegram's
|
||||||
|
current Bot API. The configured Gemini path was disabled. Web search returned
|
||||||
|
an authorization error, so primary sources were retrieved directly over HTTPS.
|
||||||
|
|
||||||
|
## Evidence
|
||||||
|
|
||||||
|
### Strong consensus
|
||||||
|
|
||||||
|
- Square brackets mean optional material. POSIX, Microsoft, argparse, and
|
||||||
|
docopt all use this convention.
|
||||||
|
- Angle brackets are a recognized way to mark a value the user must replace.
|
||||||
|
POSIX explicitly permits `<parameter name>`; Microsoft defines angle-bracket
|
||||||
|
text as a placeholder.
|
||||||
|
- A vertical bar separates mutually exclusive alternatives. Microsoft and
|
||||||
|
docopt explicitly document this.
|
||||||
|
- An ellipsis indicates repetition. POSIX uses `[operand ...]`; docopt uses
|
||||||
|
`FILE ...` for one or more and `[FILE ...]` for zero or more.
|
||||||
|
- Metavariable names should explain the role of the value. Python argparse uses
|
||||||
|
`metavar` for this purpose and generates the structural punctuation itself.
|
||||||
|
|
||||||
|
### Important nuance
|
||||||
|
|
||||||
|
Traditional terminal help often uses uppercase metavariables such as `FILE` or
|
||||||
|
`FOO`. Lowercase angle-bracket names such as `<ticker>` remain unambiguous and
|
||||||
|
are calmer in Telegram's compact UI. Changing case would add churn without
|
||||||
|
improving comprehension.
|
||||||
|
|
||||||
|
POSIX's spaced ellipsis (`operand ...`) means repeated operands. This bot's
|
||||||
|
`[target...]` means one optional free-text remainder. That is a small local
|
||||||
|
extension, but it communicates the behavior better than `[target]`, which can
|
||||||
|
look limited to one word. Document it once and keep it consistent.
|
||||||
|
|
||||||
|
## Recommended Schema
|
||||||
|
|
||||||
|
Use only constructs the project currently needs:
|
||||||
|
|
||||||
|
| Meaning | Format | Example |
|
||||||
|
|---|---|---|
|
||||||
|
| Required value | `<name>` | `<ticker>` |
|
||||||
|
| Required comma-separated values | `<name,...>` | `<option,...>` |
|
||||||
|
| Optional value | `[name]` | `[date]` |
|
||||||
|
| Optional remaining text | `[name...]` | `[target...]` |
|
||||||
|
| Optional alternatives | `[literal | literal <name>]` | `[users | user <username>]` |
|
||||||
|
|
||||||
|
Naming rules:
|
||||||
|
|
||||||
|
- Lowercase `snake_case`.
|
||||||
|
- Prefer one plain noun: `<ticker>`, `<quantity>`, `<champion>`.
|
||||||
|
- Include a unit when it prevents ambiguity: `<vnd_amount>`, `<usd_to_spend>`.
|
||||||
|
- Do not encode primitive types: avoid `<quantity:number>` and `<date:string>`.
|
||||||
|
- Do not put format prose inside a placeholder.
|
||||||
|
- Include a compact value shape only when users must type its punctuation
|
||||||
|
exactly: `<ratio(owned:new)>`, `<option,...>`.
|
||||||
|
- Keep literal subcommands bare: `users`, `user`, `cmd`.
|
||||||
|
- Put spaces around `|`; readability is worth the two characters.
|
||||||
|
|
||||||
|
This is presentation metadata, not a machine-validated schema language. Avoid
|
||||||
|
adding an AST, parser, enums, or type annotations until the bot needs generated
|
||||||
|
validation or completion.
|
||||||
|
|
||||||
|
## Current Command Audit
|
||||||
|
|
||||||
|
| Commands | Current | Recommendation | Reason |
|
||||||
|
|---|---|---|---|
|
||||||
|
| `/random`, `/wheelofnames` | `<options(comma-separated)>` | `<option,...>` | Shows the literal delimiter without prose. |
|
||||||
|
| `/stats` | `[users | user <username> | cmd <command_name>]` | Keep | Accurate compact grammar; `command_name` avoids confusing the value with a literal command. |
|
||||||
|
| `/trongtruonghop`, `/tth` | `[target...]` | Keep | Clearly signals optional multi-word remainder. |
|
||||||
|
| `/lol` | `[date]` | Keep | Minimal; accepted date shapes belong in the summary/error. |
|
||||||
|
| `/loldle`, `/wordle` | `[champion]`, `[word]` | Keep | Optional value accurately reflects start-without-argument behavior. |
|
||||||
|
| Coin commands | `<coin>`, `<usd_amount>`, `<coin> <usd_to_spend>`, `<coin> <usd_to_receive>` | Keep | Names expose currency and transaction intent without type noise. |
|
||||||
|
| Gold commands | `<vnd_amount>`, `<luong>` | Keep | Units are essential and concise. |
|
||||||
|
| Stock price/trade commands | `<ticker>`, `<vnd_amount>`, `<quantity> <ticker>` | Keep | Conventional positional metavariables. |
|
||||||
|
| Stock dividend commands | `<vnd_per_share>`, `<ratio(owned:new)>`, `<ticker>` combinations | Keep | The ratio shape is valuable syntax, not redundant prose. |
|
||||||
|
|
||||||
|
Result: change two registrations and their matching usage/tests; leave every
|
||||||
|
other public parameter string unchanged.
|
||||||
|
|
||||||
|
## Rejected Alternatives
|
||||||
|
|
||||||
|
### Uppercase metavariables
|
||||||
|
|
||||||
|
```text
|
||||||
|
<TICKER> <QUANTITY>
|
||||||
|
```
|
||||||
|
|
||||||
|
Familiar in man pages, but redundant when angle brackets already mark values.
|
||||||
|
It is visually louder and would touch every command for no behavior gain.
|
||||||
|
|
||||||
|
### Inline type annotations
|
||||||
|
|
||||||
|
```text
|
||||||
|
<quantity:number> <ticker:string>
|
||||||
|
```
|
||||||
|
|
||||||
|
Not a common shell synopsis convention. Longer, falsely formal, and still
|
||||||
|
cannot express real constraints such as positive integers or known tickers.
|
||||||
|
|
||||||
|
### Generic names everywhere
|
||||||
|
|
||||||
|
```text
|
||||||
|
<amount> <value> <input>
|
||||||
|
```
|
||||||
|
|
||||||
|
Short but ambiguous. Minimalism should remove redundancy, not meaning.
|
||||||
|
|
||||||
|
### Full docopt grammar
|
||||||
|
|
||||||
|
Docopt can represent required groups, nested alternatives, and repetition
|
||||||
|
precisely. The bot does not need that complexity. Adopt only its familiar
|
||||||
|
surface notation when a real command requires it.
|
||||||
|
|
||||||
|
## Next Steps
|
||||||
|
|
||||||
|
1. Change `/random` and `/wheelofnames` parameter metadata to `<option,...>`.
|
||||||
|
2. Change their handler usage strings and exact-string tests at the same time.
|
||||||
|
3. Update README/AGENTS guidance: value format belongs in the summary or usage
|
||||||
|
error unless punctuation is essential, as with `<ratio(owned:new)>`.
|
||||||
|
4. Keep current registration validation: non-empty descriptions, single-line
|
||||||
|
parameters, and Telegram's length limit.
|
||||||
|
5. Do not build a schema parser.
|
||||||
|
|
||||||
|
## References
|
||||||
|
|
||||||
|
- [POSIX.1-2024, Utility Conventions](https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap12.html)
|
||||||
|
- [GNU Standards, Command-Line Interfaces](https://www.gnu.org/prep/standards/html_node/Command_002dLine-Interfaces.html)
|
||||||
|
- [Microsoft command-line syntax key](https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/command-line-syntax-key)
|
||||||
|
- [Python 3 argparse documentation](https://docs.python.org/3/library/argparse.html)
|
||||||
|
- [docopt usage-pattern grammar](https://github.com/docopt/docopt/blob/master/README.rst)
|
||||||
|
- [Telegram Bot API](https://core.telegram.org/bots/api#botcommand)
|
||||||
|
|
||||||
|
## Unresolved Questions
|
||||||
|
|
||||||
|
None. The recommendation is intentionally small and implementable without
|
||||||
|
changing command parsing or persisted data.
|
||||||
Reference in new issue
Block a user