Add tabular rvctl command overview
This commit is contained in:
@@ -71,6 +71,13 @@ rvctl.py
|
|||||||
`rvctl` jest jedynym publicznym entrypointem. `rvctl.py` jest implementacja
|
`rvctl` jest jedynym publicznym entrypointem. `rvctl.py` jest implementacja
|
||||||
uruchamiana przez wrapper i nie wymaga osobnego wywolywania przez ucznia.
|
uruchamiana przez wrapper i nie wymaga osobnego wywolywania przez ucznia.
|
||||||
|
|
||||||
|
Uruchomienie bez argumentow pokazuje tabelaryczny skrot komend:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./rvctl
|
||||||
|
./rvctl tokens
|
||||||
|
```
|
||||||
|
|
||||||
## Autoryzacja
|
## Autoryzacja
|
||||||
|
|
||||||
Masz dwie drogi.
|
Masz dwie drogi.
|
||||||
@@ -253,9 +260,11 @@ cd rv-launcher
|
|||||||
Przyklady:
|
Przyklady:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
./rvctl
|
||||||
./rvctl show-config
|
./rvctl show-config
|
||||||
./rvctl list-series
|
./rvctl list-series
|
||||||
./rvctl list-cards inf
|
./rvctl list-cards inf
|
||||||
|
./rvctl tokens
|
||||||
./rvctl submission inf 03 --class 4i --nick u1
|
./rvctl submission inf 03 --class 4i --nick u1
|
||||||
./rvctl tmux-container inf 03 --dry-run
|
./rvctl tmux-container inf 03 --dry-run
|
||||||
./rvctl tmux-container inf 03 --session rv-inf03 --attach
|
./rvctl tmux-container inf 03 --session rv-inf03 --attach
|
||||||
|
|||||||
@@ -65,6 +65,14 @@ rvctl.py
|
|||||||
`rvctl` jest jedynym publicznym entrypointem. `rvctl.py` jest implementacja
|
`rvctl` jest jedynym publicznym entrypointem. `rvctl.py` jest implementacja
|
||||||
uruchamiana przez wrapper i nie wymaga osobnego wywolywania przez ucznia.
|
uruchamiana przez wrapper i nie wymaga osobnego wywolywania przez ucznia.
|
||||||
|
|
||||||
|
Uruchomienie bez argumentow pokazuje tabelaryczny skrot komend:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./rvctl
|
||||||
|
./rvctl tokens
|
||||||
|
./rvctl help tokens
|
||||||
|
```
|
||||||
|
|
||||||
### Autoryzacja
|
### Autoryzacja
|
||||||
|
|
||||||
Masz dwie drogi.
|
Masz dwie drogi.
|
||||||
@@ -174,6 +182,23 @@ Globalne przelaczniki:
|
|||||||
- `--config PATH`
|
- `--config PATH`
|
||||||
Uzywa innego pliku `workspace.json`.
|
Uzywa innego pliku `workspace.json`.
|
||||||
|
|
||||||
|
Pomoc tabelaryczna:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./rvctl
|
||||||
|
./rvctl help
|
||||||
|
./rvctl tokens
|
||||||
|
./rvctl help tokens
|
||||||
|
```
|
||||||
|
|
||||||
|
Szczegolowy help parsera:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./rvctl --help
|
||||||
|
./rvctl <komenda> --help
|
||||||
|
./rvctl tokens <komenda> --help
|
||||||
|
```
|
||||||
|
|
||||||
Komendy:
|
Komendy:
|
||||||
|
|
||||||
- `show-config`
|
- `show-config`
|
||||||
|
|||||||
@@ -1108,6 +1108,140 @@ def add_store_selection_options(parser: argparse.ArgumentParser) -> None:
|
|||||||
parser.add_argument("--token-name", help="Token name inside the selected user entry, for example 't1'.")
|
parser.add_argument("--token-name", help="Token name inside the selected user entry, for example 't1'.")
|
||||||
|
|
||||||
|
|
||||||
|
def print_table(headers: list[str], rows: list[list[str]]) -> None:
|
||||||
|
widths = [len(header) for header in headers]
|
||||||
|
for row in rows:
|
||||||
|
for index, value in enumerate(row):
|
||||||
|
widths[index] = max(widths[index], len(value))
|
||||||
|
|
||||||
|
print(" ".join(header.ljust(widths[index]) for index, header in enumerate(headers)))
|
||||||
|
print(" ".join("-" * width for width in widths))
|
||||||
|
for row in rows:
|
||||||
|
print(" ".join(value.ljust(widths[index]) for index, value in enumerate(row)))
|
||||||
|
|
||||||
|
|
||||||
|
def print_config_summary(config_path: Path) -> None:
|
||||||
|
try:
|
||||||
|
config = load_config(config_path)
|
||||||
|
except (OSError, json.JSONDecodeError, KeyError, TypeError, ValueError) as error:
|
||||||
|
print("Config:")
|
||||||
|
print_table(
|
||||||
|
["field", "value"],
|
||||||
|
[
|
||||||
|
["config", str(config_path)],
|
||||||
|
["status", f"unavailable: {error}"],
|
||||||
|
],
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
print("Config:")
|
||||||
|
print_table(
|
||||||
|
["field", "value"],
|
||||||
|
[
|
||||||
|
["config", str(config.config_path)],
|
||||||
|
["workspace", str(config.workspace_root)],
|
||||||
|
["series", str(config.series_root)],
|
||||||
|
["tokens", str(config.token_path)],
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def print_main_overview(config_path: Path) -> None:
|
||||||
|
print("RVCTL - launcher workspace RV")
|
||||||
|
print()
|
||||||
|
print("Usage:")
|
||||||
|
print(" ./rvctl <command> [options]")
|
||||||
|
print(" ./rvctl tokens <command> [options]")
|
||||||
|
print(" ./rvctl <command> --help")
|
||||||
|
print()
|
||||||
|
print("Commands:")
|
||||||
|
print_table(
|
||||||
|
["command", "arguments", "purpose"],
|
||||||
|
[
|
||||||
|
["show-config", "", "show resolved paths and Git defaults"],
|
||||||
|
["list-series", "", "list series from workspace"],
|
||||||
|
["list-cards", "[series]", "list cards in a selected series"],
|
||||||
|
["tmux-container", "[series] [card]", "start tmux with container in pane 0"],
|
||||||
|
["submission", "[series] [card] --class K --nick N", "prepare answer repo and student branch"],
|
||||||
|
["tokens", "scan|read|stats|write|update", "manage tokens.json and Git remote credentials"],
|
||||||
|
],
|
||||||
|
)
|
||||||
|
print()
|
||||||
|
print("Typical flow:")
|
||||||
|
print_table(
|
||||||
|
["step", "command", "result"],
|
||||||
|
[
|
||||||
|
["1", "./rvctl tokens scan", "read credentials from remotes if present"],
|
||||||
|
["2", "./rvctl list-series", "choose a series"],
|
||||||
|
["3", "./rvctl list-cards inf", "choose a card"],
|
||||||
|
["4", "./rvctl tmux-container inf <card>", "start the working container"],
|
||||||
|
["5", "./rvctl submission inf <card> --class 4i --nick u1", "prepare answer remote and branch"],
|
||||||
|
],
|
||||||
|
)
|
||||||
|
print()
|
||||||
|
print_config_summary(config_path)
|
||||||
|
print()
|
||||||
|
print("Docs:")
|
||||||
|
print(" doc/rvctl.md")
|
||||||
|
print(" doc/tokens.md")
|
||||||
|
print(" doc/workspace.md")
|
||||||
|
|
||||||
|
|
||||||
|
def print_tokens_overview() -> None:
|
||||||
|
print("RVCTL tokens - token store and Git remote credentials")
|
||||||
|
print()
|
||||||
|
print("Usage:")
|
||||||
|
print(" ./rvctl tokens <command> [options]")
|
||||||
|
print(" ./rvctl tokens <command> --help")
|
||||||
|
print()
|
||||||
|
print("Commands:")
|
||||||
|
print_table(
|
||||||
|
["command", "common options", "direction", "purpose"],
|
||||||
|
[
|
||||||
|
["scan", "[--repo PATH]", "repo -> tokens.json", "scan remotes and store credentials found in URLs"],
|
||||||
|
["read", "[--server ENDPOINT]", "tokens.json", "show servers, users and token names"],
|
||||||
|
["stats", "[--repo PATH]", "repo + tokens.json", "compare remote URLs with local token store"],
|
||||||
|
["write", "--remote R [--replace]", "tokens.json -> repo", "write selected token into a remote URL"],
|
||||||
|
["update", "--from remotes|store", "selected", "run scan or write with explicit direction"],
|
||||||
|
],
|
||||||
|
)
|
||||||
|
print()
|
||||||
|
print("Examples:")
|
||||||
|
print_table(
|
||||||
|
["case", "command"],
|
||||||
|
[
|
||||||
|
["scan current repo", "./rvctl tokens scan"],
|
||||||
|
["scan selected card", "./rvctl tokens scan --repo ~/dev/workspace/rv/series/inf/03"],
|
||||||
|
["compare state", "./rvctl tokens stats --repo ~/dev/workspace/rv/series/inf/03"],
|
||||||
|
["write auth to r1", "./rvctl tokens write --repo PATH --remote r1 --server URL --user u1 --token-name t1"],
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def extract_config_path(argv: list[str]) -> tuple[Path, list[str]]:
|
||||||
|
config_path = Path(__file__).with_name("workspace.json")
|
||||||
|
remaining: list[str] = []
|
||||||
|
index = 0
|
||||||
|
while index < len(argv):
|
||||||
|
arg = argv[index]
|
||||||
|
if arg == "--config":
|
||||||
|
if index + 1 >= len(argv):
|
||||||
|
remaining.append(arg)
|
||||||
|
index += 1
|
||||||
|
continue
|
||||||
|
config_path = Path(argv[index + 1])
|
||||||
|
index += 2
|
||||||
|
continue
|
||||||
|
if arg.startswith("--config="):
|
||||||
|
config_path = Path(arg.split("=", 1)[1])
|
||||||
|
index += 1
|
||||||
|
continue
|
||||||
|
remaining.append(arg)
|
||||||
|
index += 1
|
||||||
|
|
||||||
|
return config_path, remaining
|
||||||
|
|
||||||
|
|
||||||
def build_parser() -> argparse.ArgumentParser:
|
def build_parser() -> argparse.ArgumentParser:
|
||||||
parser = argparse.ArgumentParser(
|
parser = argparse.ArgumentParser(
|
||||||
prog="rvctl",
|
prog="rvctl",
|
||||||
@@ -1223,6 +1357,14 @@ def build_parser() -> argparse.ArgumentParser:
|
|||||||
|
|
||||||
|
|
||||||
def main() -> int:
|
def main() -> int:
|
||||||
|
config_path, command_args = extract_config_path(sys.argv[1:])
|
||||||
|
if not command_args or command_args == ["help"]:
|
||||||
|
print_main_overview(config_path)
|
||||||
|
return 0
|
||||||
|
if command_args in (["tokens"], ["help", "tokens"], ["tokens", "help"]):
|
||||||
|
print_tokens_overview()
|
||||||
|
return 0
|
||||||
|
|
||||||
parser = build_parser()
|
parser = build_parser()
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
config = load_config(args.config)
|
config = load_config(args.config)
|
||||||
|
|||||||
Reference in New Issue
Block a user