From 7273b45faf200d3ed2668aedfbe4e1273b854aba Mon Sep 17 00:00:00 2001 From: Daniel Reeves <31971762+dwreeves@users.noreply.github.com> Date: Sun, 21 Apr 2024 22:30:21 -0400 Subject: [PATCH] Docs cleanup (#185) * update * try something * update * Generate new screengrabs with rich-codex * updates * experiment * update * Generate new screengrabs with rich-codex * update * updates * Generate new screengrabs with rich-codex * almost done with docs * Generate new screengrabs with rich-codex * update * delete unused file --------- Co-authored-by: github-actions[bot] --- .github/workflows/build-docs.yml | 18 +- .github/workflows/pre-commit.yml | 10 +- .github/workflows/pytest.yml | 18 +- .github/workflows/rich-codex.yml | 9 +- .github/workflows/test-examples.yml | 18 +- .pre-commit-config.yaml | 6 + .vscode/settings.template.jsonc | 8 +- CHANGELOG.md | 18 +- CONTRIBUTING.md | 21 ++ .../introduction_to_click/hello.py | 9 + .../introduction_to_click/hello_rich.py | 20 ++ .../introduction_to_click/hello_v2.py | 22 ++ .../introduction_to_click/hello_v3.py | 20 ++ docs/code_snippets/rich_click_cli/app.py | 68 ++++ docs/css/editor.css | 48 ++- docs/css/extra.css | 8 +- docs/css/termynal.css | 119 +++---- docs/documentation/formatting_and_styles.md | 38 ++- docs/documentation/introduction_to_click.md | 174 +++-------- docs/documentation/rich_click_cli.md | 191 +++--------- docs/images/arguments.svg | 118 +++---- .../introduction_to_click/hello.svg | 62 ++++ .../introduction_to_click/hello_help.svg | 82 +++++ .../introduction_to_click/hello_rich.svg | 114 +++++++ .../introduction_to_click/hello_v2.svg | 74 +++++ .../introduction_to_click/hello_v2_help.svg | 90 ++++++ .../introduction_to_click/hello_v3_help.svg | 98 ++++++ .../hello_v3_subcommand.svg | 62 ++++ .../hello_v3_subcommand_help.svg | 82 +++++ .../rich_click_cli/output_to_html.svg | 111 +++++++ .../rich_click_cli/output_to_svg.svg | 111 +++++++ .../rich_click_cli/rich_click.svg | 117 +++++++ docs/images/custom_error.svg | 70 ++--- docs/images/error.svg | 60 ++-- docs/images/markdown.svg | 140 ++++----- docs/images/metavars_appended.svg | 100 +++--- docs/images/metavars_default.svg | 118 +++---- .../images/rich_click_cli_examples/celery.svg | 226 ++++++++++++++ .../rich_click_cli_examples/dagster.svg | 161 ++++++++++ docs/images/rich_click_cli_examples/flask.svg | 167 ++++++++++ docs/images/rich_markup.svg | 148 ++++----- docs/images/style_tables.svg | 260 ++++++++-------- docs/js/custom.js | 108 ------- docs/js/termynal.js | 293 ------------------ docs/overrides/editor.html | 63 ++-- mkdocs.yml | 3 - pyproject.toml | 4 +- src/rich_click/patch.py | 2 +- 48 files changed, 2535 insertions(+), 1352 deletions(-) create mode 100644 docs/code_snippets/introduction_to_click/hello.py create mode 100644 docs/code_snippets/introduction_to_click/hello_rich.py create mode 100644 docs/code_snippets/introduction_to_click/hello_v2.py create mode 100644 docs/code_snippets/introduction_to_click/hello_v3.py create mode 100644 docs/code_snippets/rich_click_cli/app.py create mode 100644 docs/images/code_snippets/introduction_to_click/hello.svg create mode 100644 docs/images/code_snippets/introduction_to_click/hello_help.svg create mode 100644 docs/images/code_snippets/introduction_to_click/hello_rich.svg create mode 100644 docs/images/code_snippets/introduction_to_click/hello_v2.svg create mode 100644 docs/images/code_snippets/introduction_to_click/hello_v2_help.svg create mode 100644 docs/images/code_snippets/introduction_to_click/hello_v3_help.svg create mode 100644 docs/images/code_snippets/introduction_to_click/hello_v3_subcommand.svg create mode 100644 docs/images/code_snippets/introduction_to_click/hello_v3_subcommand_help.svg create mode 100644 docs/images/code_snippets/rich_click_cli/output_to_html.svg create mode 100644 docs/images/code_snippets/rich_click_cli/output_to_svg.svg create mode 100644 docs/images/code_snippets/rich_click_cli/rich_click.svg create mode 100644 docs/images/rich_click_cli_examples/celery.svg create mode 100644 docs/images/rich_click_cli_examples/dagster.svg create mode 100644 docs/images/rich_click_cli_examples/flask.svg delete mode 100644 docs/js/custom.js delete mode 100644 docs/js/termynal.js diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml index 7cb37a82..828f4bba 100644 --- a/.github/workflows/build-docs.yml +++ b/.github/workflows/build-docs.yml @@ -1,4 +1,4 @@ -name: Build images / docs +name: Build docs on: workflow_dispatch: push: @@ -15,26 +15,24 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out the repo - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Set up Python - uses: actions/setup-python@v3 + uses: actions/setup-python@v4 with: python-version: 3.x - - uses: actions/cache@v2 - with: - key: ${{ github.ref }} - path: .cache - - name: Install requirements for docs - run: pip install -e ".[docs]" + run: | + pip install -U uv + uv pip install --system --editable ".[docs]" - name: Generate terminal images with rich-codex uses: ewels/rich-codex@v1 with: commit_changes: "true" - clean_img_paths: docs/img/*.svg + clean_img_paths: docs/images/*.svg + skip_git_checks: "true" - name: Build and deploy docs run: mkdocs gh-deploy --force diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml index bd4d66f9..4983cd62 100644 --- a/.github/workflows/pre-commit.yml +++ b/.github/workflows/pre-commit.yml @@ -7,8 +7,12 @@ jobs: pre-commit: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - - uses: actions/setup-python@v3 + - uses: actions/checkout@v4 + - uses: actions/setup-python@v4 + with: + python-version: 3.x - name: Install dependencies - run: pip install '.[dev]' + run: | + pip install -U uv + uv pip install --system --editable ".[dev]" - uses: pre-commit/action@v2.0.3 diff --git a/.github/workflows/pytest.yml b/.github/workflows/pytest.yml index 79b5ff7a..a63b1c8e 100644 --- a/.github/workflows/pytest.yml +++ b/.github/workflows/pytest.yml @@ -5,12 +5,12 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python: [3.7.x, 3.11.x] # Only test lowest + highest Python versions supported + python: [3.7.x, 3.11.x, 3.12.x] click: [7.0.*, 7.1.*, 8.0.*, 8.1.*] rich: [12.*, 13.*] steps: - name: Check out the repo - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Set up Python uses: actions/setup-python@v4 @@ -18,8 +18,20 @@ jobs: python-version: ${{ matrix.python }} - name: Install dependencies + if: matrix.python != '3.7.x' run: | - pip install '.[dev]' + pip install -U uv + uv pip install --system --editable ".[dev]" + uv pip install --system --upgrade "click==$CLICK_VERSION" + uv pip install --system --upgrade "rich==$RICH_VERSION" + env: + CLICK_VERSION: ${{ matrix.click }} + RICH_VERSION: ${{ matrix.rich }} + + - name: Install dependencies (Python 3.7) + if: matrix.python == '3.7.x' + run: | + pip install --editable ".[dev]" pip install --upgrade "click==$CLICK_VERSION" pip install --upgrade "rich==$RICH_VERSION" env: diff --git a/.github/workflows/rich-codex.yml b/.github/workflows/rich-codex.yml index b9bae841..19c88adb 100644 --- a/.github/workflows/rich-codex.yml +++ b/.github/workflows/rich-codex.yml @@ -11,13 +11,15 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out the repo - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Set up Python - uses: actions/setup-python@v3 + uses: actions/setup-python@v4 + with: + python-version: 3.x - name: Install your custom tools - run: pip install . + run: pip install ".[dev]" - name: Generate terminal images with rich-codex uses: ewels/rich-codex@v1 @@ -26,3 +28,4 @@ jobs: clean_img_paths: docs/images/*.svg terminal_width: 80 skip_git_checks: "true" + working_dir: "." diff --git a/.github/workflows/test-examples.yml b/.github/workflows/test-examples.yml index 66ce80b3..8c52383c 100644 --- a/.github/workflows/test-examples.yml +++ b/.github/workflows/test-examples.yml @@ -5,7 +5,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python: [3.7.x, 3.8.x, 3.9.x, 3.10.x, 3.11.x] + python: [3.7.x, 3.11.x, 3.12.x] click: [7.0.*, 8.0.*, 8.1.*] # Skip click 7.1 since regression coverage is strictly higher in 7.0. steps: - name: Check out the repo @@ -16,9 +16,19 @@ jobs: with: python-version: ${{ matrix.python }} - - name: Install rich-click and click + - name: Install dependencies + if: matrix.python != '3.7.x' run: | - pip install . + pip install -U uv + uv pip install --system --editable "." + uv pip install --system --upgrade "click==$CLICK_VERSION" + env: + CLICK_VERSION: ${{ matrix.click }} + + - name: Install dependencies (Python 3.7) + if: matrix.python == '3.7.x' + run: | + pip install --editable "." pip install --upgrade "click==$CLICK_VERSION" env: CLICK_VERSION: ${{ matrix.click }} @@ -28,5 +38,5 @@ jobs: for f in examples/*py do echo -e "\n\n$f" - python $f --help || exit 1; + python "${f}" --help || exit 1; done diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 4d562f4c..0a135ee4 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -12,6 +12,11 @@ repos: # hooks: # - id: prettier + - repo: https://github.com/rhysd/actionlint + rev: v1.6.27 + hooks: + - id: actionlint + - repo: https://github.com/tox-dev/pyproject-fmt rev: 1.7.0 hooks: @@ -35,6 +40,7 @@ repos: hooks: - id: black language_version: python3.12 + exclude: ^docs/ - repo: local hooks: diff --git a/.vscode/settings.template.jsonc b/.vscode/settings.template.jsonc index 84c49cf0..7f637d1e 100644 --- a/.vscode/settings.template.jsonc +++ b/.vscode/settings.template.jsonc @@ -5,5 +5,11 @@ "python.testing.pytestPath": "venv/bin/pytest", "python.linting.flake8Path": "venv/bin/flake8", "python.linting.flake8Enabled": true, - "python.testing.pytestEnabled": true + "python.testing.pytestEnabled": true, + "yaml.schemas": { + "https://raw.githubusercontent.com/ewels/rich-codex/main/src/rich_codex/config-schema.yml": [ + ".rich-codex.yml", + ".rich-codex.yaml" + ] + } } diff --git a/CHANGELOG.md b/CHANGELOG.md index 8aefa37f..1325c414 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,16 +17,16 @@ - Moved to `text_markup: Literal["markdown", "rich", None]` instead of booleans. - Fixed issue where error messages would not print to `stderr` by default. - New configuration options: [[#178](https://github.com/ewels/rich-click/pull/178)] - - `STYLE_OPTIONS_PANEL_BOX` - - `STYLE_COMMANDS_PANEL_BOX` - - `STYLE_ERRORS_PANEL_BOX` + - `STYLE_OPTIONS_PANEL_BOX` + - `STYLE_COMMANDS_PANEL_BOX` + - `STYLE_ERRORS_PANEL_BOX` - Many quality of life improvements for command and option groups: - - Support both `command_path` and `command.name`. - - Added wildcard (`*`) option for command groups and option groups, with thanks to [@ITProKyle](https://github.com/ITProKyle)! - - Resolve duplicates. - - Better typing for option groups and command groups with `TypedDict` [[#156](https://github.com/ewels/rich-click/pull/156)] - - Added `panel_styles` support to groups. [[#178](https://github.com/ewels/rich-click/pull/178)] - - Allow `table_styles` and `panel_styles` to be defined for the positional arguments group. + - Support both `command_path` and `command.name`. + - Added wildcard (`*`) option for command groups and option groups, with thanks to [@ITProKyle](https://github.com/ITProKyle)! + - Resolve duplicates. + - Better typing for option groups and command groups with `TypedDict` [[#156](https://github.com/ewels/rich-click/pull/156)] + - Added `panel_styles` support to groups. [[#178](https://github.com/ewels/rich-click/pull/178)] + - Allow `table_styles` and `panel_styles` to be defined for the positional arguments group. ## Version 1.7.4 (2024-03-12) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4403f3ae..b5f49536 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -11,6 +11,27 @@ or better still, dive right in with a pull-request. 3. Install our the package as an editable including all dev dependencies with `pip3 install -e ".[dev]"` 4. Install pre-commit with `pre-commit install` +### One-shot script (OSX) + +Requirements: + +- `brew install pyenv pyenv-virtualenv uv` +- Initialize `pyenv-virtualenv`: run `pyenv virtualenv-init` and follow instructions. + +``` +pyenv install --skip-existing 3.7 3.12 +pyenv virtualenv 3.7 rich-click-3.7 +pyenv virtualenv 3.12 rich-click-3.12 +echo '#rich-click-3.7 +rich-click-3.12' >.python-version +uv pip install --all-extras -r pyproject.toml --editable . +echo 'rich-click-3.7 +#rich-click-3.12' >.python-version +uv pip install --extra dev -r pyproject.toml --editable . +``` + +Note: 3.7 is the minimum supported Python version for **rich-click**, but docs are rendered in 3.12. + ## Pre-commit Our pre-commit hooks contain the following hooks: diff --git a/docs/code_snippets/introduction_to_click/hello.py b/docs/code_snippets/introduction_to_click/hello.py new file mode 100644 index 00000000..0e3c2c36 --- /dev/null +++ b/docs/code_snippets/introduction_to_click/hello.py @@ -0,0 +1,9 @@ +import click + +@click.command() +def hello(): + """Prints 'hello, world!' into the terminal.""" + print("Hello, world!") + +if __name__ == "__main__": + hello() diff --git a/docs/code_snippets/introduction_to_click/hello_rich.py b/docs/code_snippets/introduction_to_click/hello_rich.py new file mode 100644 index 00000000..5b9a0690 --- /dev/null +++ b/docs/code_snippets/introduction_to_click/hello_rich.py @@ -0,0 +1,20 @@ +import rich_click as click + +@click.group("greetings") +def greetings_cli(): + """CLI for greetings.""" + +@greetings_cli.command("english") +@click.argument("name") +def english(name): + """Greet in English""" + print(f"Hello, {name}!") + +@greetings_cli.command("french") +@click.argument("name") +def french(name): + """Greet in French""" + print(f"Bonjour, {name}!") + +if __name__ == "__main__": + greetings_cli() diff --git a/docs/code_snippets/introduction_to_click/hello_v2.py b/docs/code_snippets/introduction_to_click/hello_v2.py new file mode 100644 index 00000000..5492d65d --- /dev/null +++ b/docs/code_snippets/introduction_to_click/hello_v2.py @@ -0,0 +1,22 @@ +import click + +@click.command() +@click.argument("name") +@click.option("--times", "-t", + default=1, + type=click.INT, + show_default=True, + help="Number of times to print the greeting.") +@click.option("--say-goodbye", + is_flag=True, + default=False, + help="After saying hello, say goodbye.") +def hello(name, times, say_goodbye): + """Prints 'hello, [name]!' into the terminal N times.""" + for t in range(times): + print(f"Hello, {name}!") + if say_goodbye: + print("Goodbye!") + +if __name__ == "__main__": + hello() diff --git a/docs/code_snippets/introduction_to_click/hello_v3.py b/docs/code_snippets/introduction_to_click/hello_v3.py new file mode 100644 index 00000000..2a377afe --- /dev/null +++ b/docs/code_snippets/introduction_to_click/hello_v3.py @@ -0,0 +1,20 @@ +import click + +@click.group("greetings") +def greetings_cli(): + """CLI for greetings.""" + +@greetings_cli.command("english") +@click.argument("name") +def english(name): + """Greet in English""" + print(f"Hello, {name}!") + +@greetings_cli.command("french") +@click.argument("name") +def french(name): + """Greet in French""" + print(f"Bonjour, {name}!") + +if __name__ == "__main__": + greetings_cli() diff --git a/docs/code_snippets/rich_click_cli/app.py b/docs/code_snippets/rich_click_cli/app.py new file mode 100644 index 00000000..a9118468 --- /dev/null +++ b/docs/code_snippets/rich_click_cli/app.py @@ -0,0 +1,68 @@ +# This is a fleshed-out application built with Click. +# (Except for the fact that it doesn't do anything!) +# +# Run the command `rich-click app:main --help` to render it with rich-click! +import logging + +import click +from rich.logging import RichHandler + +logger = logging.getLogger(__name__) +logger.addHandler(RichHandler()) +logger.setLevel(logging.INFO) + +@click.group("my-app") +@click.option("--environment", "-e", + type=click.Choice(["production", "staging", "integration"]), + default="production", + show_default=True, + help="Environment to run in.") +@click.version_option(version="1.0.1", prog_name="my-app") +def main(environment): + """CLI for my-app""" + logger.debug("Running in environment=%s", environment) + + +@main.command("deploy") +@click.argument("version") +@click.pass_context +def deploy(ctx, version): + """Deploy my-app""" + logger.info("Deploying version=%s in environment=%s", version, ctx.parent.params["environment"]) + +@main.group("user") +def user_cli(): + """Manage users to my-app""" + +@user_cli.command("create") +@click.option("--email", "-e", + required=True, + help="User's email") +@click.password_option("--password", "-p", + required=True, + prompt=True, + help="User's password") +@click.option("--admin", + is_flag=True, + default=False, + help="If flag is passed, give admin permissions") +@click.pass_context +def create(ctx, email, password, admin): + """Create my-app users""" + if len(password) < 6: + logger.error("Password must be ≥ 6 characters") + ctx.exit(1) + logger.info("Creating user with email=%s admin=%s", email, admin) + + +@user_cli.command("delete") +@click.argument("user_id", + type=click.INT) +def delete(user_id): + """Delete my-app users""" + click.confirm(click.style(f"Are you sure you want to delete user={user_id!r}?", fg="red"), abort=True) + logger.info("Deleting user with user_id=%i", user_id) + + +if __name__ == "__main__": + main() diff --git a/docs/css/editor.css b/docs/css/editor.css index d3f55c62..566f1c45 100644 --- a/docs/css/editor.css +++ b/docs/css/editor.css @@ -10,16 +10,57 @@ [data-termynal] { width: 100%; padding: 75px 25px 25px; + overflow-x: hidden; } .container { display: flex; - height: 100%; + align-items: flex-start; } .container .left-column { - flex: 3 0 auto; + flex: 1 0 auto; align-content: center; + padding-top: 5px; +} + +#option-table { + display: block; + width: 100%; +} + +.container .left-column thead { + background-color: rgba(133, 133, 133, 0.07); +} + +.container .left-column table thead tr th:nth-child(1), +.container .left-column table tbody tr td:nth-child(1) { + max-width: 270px; + min-width: 270px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.container .left-column table thead tr th:nth-child(2), +.container .left-column table tbody tr td:nth-child(2) { + max-width: 100px; + min-width: 100px; +} + +.container .left-column table thead tr th:nth-child(3), +.container .left-column table tbody tr td:nth-child(3) { + max-width: 200px; + min-width: 200px; +} + + +.container .left-column table tbody { + height: 460px; + width: auto; + overflow-y: scroll; + overflow-x: hidden; + display: block; } .container .right-column { @@ -27,6 +68,9 @@ padding: 25px 15px; align-content: center; display: inline-block; + overflow-x: hidden; + white-space: nowrap; + } @media (max-width: 74em) { diff --git a/docs/css/extra.css b/docs/css/extra.css index 684d64fb..0cc34160 100644 --- a/docs/css/extra.css +++ b/docs/css/extra.css @@ -12,13 +12,7 @@ background-color: rgba(127, 127, 127, 0.4); } -.termynal-comment { - color: #4a968f; - font-style: italic; - display: block; -} - -.termy [data-termynal] { +[data-termynal] { white-space: pre; } diff --git a/docs/css/termynal.css b/docs/css/termynal.css index f89d69a0..40c13471 100644 --- a/docs/css/termynal.css +++ b/docs/css/termynal.css @@ -7,109 +7,84 @@ */ :root { - --color-bg: #252a33; - --color-text: #eee; - --color-text-subtle: #a2a2a2; + --color-text: #eee; + --color-text-subtle: #a2a2a2; } [data-termynal] { - width: 750px; - background: var(--color-bg); - color: var(--color-text); - /* font-size: 18px; */ - font-size: 15px; - /* font-family: 'Fira Mono', Consolas, Menlo, Monaco, 'Courier New', Courier, monospace; */ - font-family: "Roboto Mono", "Fira Mono", Consolas, Menlo, Monaco, - "Courier New", Courier, monospace; - border-radius: 4px; - padding: 75px 45px 35px; - position: relative; - -webkit-box-sizing: border-box; - box-sizing: border-box; - line-height: 1.2; - overflow-x: scroll; - white-space: nowrap; + width: 750px; + max-width: 100%; + color: var(--color-text); + font-size: 14px; + font-family: 'Fira Mono', Consolas, Menlo, Monaco, 'Courier New', Courier, monospace; + box-shadow: 0 3px 10px 1px rgba(87, 87, 87, 0.6); + border-radius: 4px; + padding: 15px 25px 15px; + position: relative; + -webkit-box-sizing: border-box; + box-sizing: border-box; } [data-termynal]:before { - content: ""; - position: absolute; - top: 15px; - left: 15px; - display: inline-block; - width: 15px; - height: 15px; - border-radius: 50%; - /* A little hack to display the window buttons in one pseudo element. */ - background: #d9515d; - -webkit-box-shadow: - 25px 0 0 #f4c025, - 50px 0 0 #3ec930; - box-shadow: - 25px 0 0 #f4c025, - 50px 0 0 #3ec930; -} - -[data-termynal]:after { - content: "bash"; - position: absolute; - color: var(--color-text-subtle); - top: 5px; - left: 0; - width: 100%; - text-align: center; -} - -a[data-terminal-control] { - text-align: right; - display: block; - color: #aebbff; + content: ''; + position: absolute; + top: 15px; + left: 15px; + display: inline-block; + width: 15px; + height: 15px; + border-radius: 50%; + /* A little hack to display the window buttons in one pseudo element. */ + background: #d9515d; + -webkit-box-shadow: 25px 0 0 #f4c025, 50px 0 0 #3ec930; + box-shadow: 25px 0 0 #f4c025, 50px 0 0 #3ec930; } [data-ty] { - display: block; - line-height: 2; + display: block; + line-height: 2; } [data-ty]:before { - /* Set up defaults and ensure empty lines are displayed. */ - content: ""; - display: inline-block; - vertical-align: middle; + /* Set up defaults and ensure empty lines are displayed. */ + content: ''; + display: inline-block; + vertical-align: middle; } [data-ty="input"]:before, [data-ty-prompt]:before { - margin-right: 0.75em; - color: var(--color-text-subtle); + margin-right: 0.75em; + color: var(--color-text-subtle); } [data-ty="input"]:before { - content: "$"; + content: '$'; } [data-ty][data-ty-prompt]:before { - content: attr(data-ty-prompt); + content: attr(data-ty-prompt); } [data-ty-cursor]:after { - content: attr(data-ty-cursor); - font-family: monospace; - margin-left: 0.5em; - -webkit-animation: blink 1s infinite; - animation: blink 1s infinite; + content: attr(data-ty-cursor); + font-family: monospace; + margin-left: 0.5em; + -webkit-animation: blink 1s infinite; + animation: blink 1s infinite; } + /* Cursor animation */ @-webkit-keyframes blink { - 50% { - opacity: 0; - } + 50% { + opacity: 0; + } } @keyframes blink { - 50% { - opacity: 0; - } + 50% { + opacity: 0; + } } diff --git a/docs/documentation/formatting_and_styles.md b/docs/documentation/formatting_and_styles.md index 762465a0..101f3208 100644 --- a/docs/documentation/formatting_and_styles.md +++ b/docs/documentation/formatting_and_styles.md @@ -45,7 +45,10 @@ for example: `[dim]\[my-default: foo][\]` click.rich_click.TEXT_MARKUP = "rich" ``` -![`python ../../examples/04_rich_markup.py --help`](../images/rich_markup.svg "Rich markup example"){.screenshot} + +![`python examples/04_rich_markup.py --help`](../images/rich_markup.svg "Rich markup example"){.screenshot} > See [`examples/04_rich_markup.py`](examples/04_rich_markup.py) for an example. @@ -63,7 +66,10 @@ If you prefer, you can use Markdown text. click.rich_click.TEXT_MARKUP = "markdown" ``` -![`python ../../examples/05_markdown.py --help`](../images/markdown.svg "Markdown example"){.screenshot} + +![`python examples/05_markdown.py --help`](../images/markdown.svg "Markdown example"){.screenshot} > See [`examples/05_markdown.py`](examples/05_markdown.py) for an example. @@ -89,7 +95,10 @@ By default, they will get their own panel, but you can tell rich-click to bundle click.rich_click.GROUP_ARGUMENTS_OPTIONS = True ``` -![`python ../../examples/06_arguments.py --help`](../images/arguments.svg "Positional arguments example"){.screenshot} + +![`python examples/06_arguments.py --help`](../images/arguments.svg "Positional arguments example"){.screenshot} > See [`examples/06_arguments.py`](examples/06_arguments.py) for an example. @@ -102,7 +111,10 @@ If you have a choice, the metavar is a list of the possible values. By default, rich-click shows metavars in their own column. However, if you have a long list of choices, this column can be quite wide and result in a lot of white space: -![`python ../../examples/08_metavars_default.py --help`](../images/metavars_default.svg "Default metavar display"){.screenshot} + +![`python examples/08_metavars_default.py --help`](../images/metavars_default.svg "Default metavar display"){.screenshot} It may look better to show metavars appended to the help text, instead of in their own column. For this, use the following: @@ -121,7 +133,10 @@ For this, use the following: click.rich_click.APPEND_METAVARS_HELP = True ``` -![`python ../../examples/08_metavars.py --help`](../images/metavars_appended.svg "Appended metavar"){.screenshot} + +![`python examples/08_metavars.py --help`](../images/metavars_appended.svg "Appended metavar"){.screenshot} > See [`examples/08_metavars.py`](examples/08_metavars.py) for an example. @@ -129,7 +144,10 @@ For this, use the following: By default, rich-click gives some nice formatting to error messages: -![`python ../../examples/01_simple.py --hep || true`](../images/error.svg "Error message"){.screenshot} + +![`python examples/01_simple.py --hep || true`](../images/error.svg "Error message"){.screenshot} You can customise the _Try 'command --help' for help._ message with `ERRORS_SUGGESTION` using rich-click though, and add some text after the error with `ERRORS_EPILOGUE`. @@ -153,7 +171,10 @@ For example, from [`examples/07_custom_errors.py`](examples/07_custom_errors.py) click.rich_click.ERRORS_EPILOGUE = "To find out more, visit [link=https://mytool.com]https://mytool.com[/link]" ``` -![`python ../../examples/07_custom_errors.py --hep || true`](../images/custom_error.svg "Custom error message"){.screenshot} + +![`python examples/07_custom_errors.py --hep || true`](../images/custom_error.svg "Custom error message"){.screenshot} > See [`examples/07_custom_errors.py`](examples/07_custom_errors.py) for an example. @@ -199,11 +220,12 @@ click.rich_click.STYLE_OPTIONS_TABLE_BOX = "SIMPLE" You can make some really ~horrible~ _colourful_ solutions using these styles if you wish: +![`python examples/10_table_styles.py --help`](../images/style_tables.svg "Rich markup example"){.screenshot} -![`python ../../examples/10_table_styles.py --help`](../images/style_tables.svg "Rich markup example"){.screenshot} > See [`examples/10_table_styles.py`](examples/10_table_styles.py) for an example. diff --git a/docs/documentation/introduction_to_click.md b/docs/documentation/introduction_to_click.md index 4a70ad65..40ce01c1 100644 --- a/docs/documentation/introduction_to_click.md +++ b/docs/documentation/introduction_to_click.md @@ -16,36 +16,21 @@ Click utilizes function decorators as its primary interface for composing a CLI. For example, the `@click.command` decorator creates a `Command` object that calls the function: ```python -# hello.py -import click - -@click.command() -def hello(): - """Prints 'hello, world!' into the terminal.""" - print("Hello, world!") - -if __name__ == "__main__": - hello() +# docs/code_snippets/introduction_to_click/hello.py +{!code_snippets/introduction_to_click/hello.py!} ``` You can run the file like normal, or you can run `--help` to render the function's docstring: -
-```console -$ python hello.py - -Hello, world! - -$ python hello.py --help + +![`python hello.py`](../images/code_snippets/introduction_to_click/hello.svg){.screenshot} -Usage: hello.py [OPTIONS] - - Prints 'hello, world!' into the terminal. - -Options: - --help Show this message and exit. -``` -
+ +![`python hello.py --help`](../images/code_snippets/introduction_to_click/hello_help.svg){.screenshot} ### Arguments and Options @@ -57,53 +42,19 @@ Arguments and options are also added with decorators. The difference between arg The below code shows some of the features available with options and arguments: ```python -# hello.py -import click - -@click.command() -@click.argument("name") -@click.option("--times", "-t", - default=1, - type=click.INT, - show_default=True, - help="Number of times to print the greeting.") -@click.option("--say-goodbye", - is_flag=True, - default=False, - help="After saying hello, say goodbye.") -def hello(name, times, say_goodbye): - """Prints 'hello, [name]!' into the terminal N times.""" - for t in range(times): - print(f"Hello, {name}!") - if say_goodbye: - print("Goodbye!") - -if __name__ == "__main__": - hello() +# docs/code_snippets/introduction_to_click/hello_v2.py +{!code_snippets/introduction_to_click/hello_v2.py!} ``` -
-```console -$ python hello.py --say-goodbye --times 3 Edward - -Hello, Edward! -Hello, Edward! -Hello, Edward! -Goodbye! - -$ python hello.py --help - -Usage: hello.py [OPTIONS] NAME + +![`python hello_v2.py --say-goodbye --times 3 Edward`](../images/code_snippets/introduction_to_click/hello_v2.svg){.screenshot} - Prints 'hello, [name]!' into the terminal N times. - -Options: - -t, --times INTEGER Number of times to print the greeting. - [default: 1] - --say-goodbye After saying hello, say goodbye. - --help Show this message and exit. -``` -
+ +![`python hello_v2.py --help`](../images/code_snippets/introduction_to_click/hello_v2_help.svg){.screenshot} Click is able to parse the new arguments and options, e.g. it knows that `--times [number]` maps to the function argument `times`. Additionally, Click also knows to render these new arguments in the help text. @@ -113,65 +64,28 @@ Additionally, Click also knows to render these new arguments in the help text. Last but not least, Click allows for command groups and sub-commands, which allows you to nest commands inside other commands. ```python -# hello.py -import click - -@click.group("greetings") -def greetings_cli(): - """CLI for greetings.""" - -@greetings_cli.command("english") -@click.argument("name") -def english(name): - """Greet in English""" - print(f"Hello, {name}!") - -@greetings_cli.command("french") -@click.argument("name") -def french(name): - """Greet in French""" - print(f"Bonjour, {name}!") - -if __name__ == "__main__": - greetings_cli() +# docs/code_snippets/introduction_to_click/hello_v3.py +{!code_snippets/introduction_to_click/hello_v3.py!} ``` Running `python hello.py --help` gives you the help text for the group and lists the subcommands: -
-```console -$ python hello.py --help -Usage: hello.py [OPTIONS] COMMAND [ARGS]... - - CLI for greetings. - -Options: - --help Show this message and exit. - -Commands: - english Greet in English. - french Greet in French. -``` -
+ +![`python hello_v3.py --help`](../images/code_snippets/introduction_to_click/hello_v3_help.svg){.screenshot} And you can run any of the subcommands like so: -
-```console -$ python hello.py french Jennifer - -Bonjour, Jennifer! + +![`python hello_v3.py french Jennifer`](../images/code_snippets/introduction_to_click/hello_v3_subcommand.svg){.screenshot} -$ python hello.py french --help - -Usage: hello.py french [OPTIONS] NAME - - Greet in French. - -Options: - --help Show this message and exit. -``` -
+ +![`python hello_v3.py french --help`](../images/code_snippets/introduction_to_click/hello_v3_subcommand_help.svg){.screenshot} ## Next Steps @@ -194,22 +108,10 @@ import rich_click as click That's the **_only_** change needed to use **rich-click**! And now we get the following beautiful help text: -
-```console -$ python hello.py --help - -Usage: my_file [OPTIONS] NAME - - Prints 'hello, [name]!' into the terminal N times. - -╭─ Options ────────────────────────────────────────────────────────────╮ - --times -t INTEGER Number of times to print the greeting. - [default: 1] - --say-goodbye After saying hello, say goodbye. - --help Show this message and exit. -╰──────────────────────────────────────────────────────────────────────╯ -``` -
+ +![`python hello_rich.py --help`](../images/code_snippets/introduction_to_click/hello_rich.svg){.screenshot} ## Other CLI libraries diff --git a/docs/documentation/rich_click_cli.md b/docs/documentation/rich_click_cli.md index 84c11749..b8180061 100644 --- a/docs/documentation/rich_click_cli.md +++ b/docs/documentation/rich_click_cli.md @@ -4,143 +4,24 @@ **rich-click** comes with a CLI tool that allows you to format the Click help output for any CLI that uses Click. -
-```console -$ rich-click --help - - Usage: - rich_click - [OPTIONS] [SCRIPT | MODULE:CLICK_COMMAND] [-- SCRIPT_ARGS...] - - The rich-click CLI provides attractive help output from any tool using - click, formatted with rich. - -// The rest of the output is omitted -``` -
- -To use, simply prefix `rich-click` to the command. Here are a few examples: - -=== "flask" - -
- ```console - $ rich-click flask --help - - Usage: flask [OPTIONS] COMMAND [ARGS]... - - A general utility script for Flask applications. - An application to load must be given with the '--app' option, - 'FLASK_APP' environment variable, or with a 'wsgi.py' or 'app.py' file - in the current directory. - - ╭─ Options ────────────────────────────────────────────────────────────╮ - --env-file -e FILE Load environment variables from this - file. python-dotenv must be - installed. - --app -A IMPORT The Flask application or factory - function to load, in the form - 'module:name'. Module can be a - dotted import or file path. Name is - not required if it is 'app', - 'application', 'create_app', or - 'make_app', and can be 'name(args)' - to pass arguments. - --debug/--no-debug Set debug mode. - --version Show the Flask version. - --help Show this message and exit. - ╰──────────────────────────────────────────────────────────────────────╯ - ╭─ Commands ───────────────────────────────────────────────────────────╮ - routes Show the routes for the app. - run Run a development server. - shell Run a shell in the app context. - ╰──────────────────────────────────────────────────────────────────────╯ - ``` -
- -=== "celery" - -
- ```console - $ rich-click celery --help - - Usage: celery [OPTIONS] COMMAND [ARGS]... - - Celery command entrypoint. - - ╭─ Options ──────────────────────────────────────────────────────────────╮ - --app -A APPLICATION - --broker -b TEXT - --result-backend TEXT - --loader TEXT - --config TEXT - --workdir PATH - --no-color -C - --quiet -q - --version - --skip-checks Skip Django core checks on startup. - Setting the SKIP_CHECKS environment - variable to any non-empty string - will have the same effect. - --help Show this message and exit. - ╰────────────────────────────────────────────────────────────────────────╯ - ╭─ Commands ─────────────────────────────────────────────────────────────╮ - amqp AMQP Administration Shell. - beat Start the beat periodic task scheduler. - call Call a task by name. - control Workers remote control. - events Event-stream utilities. - graph The ``celery graph`` command. - inspect Inspect the worker at runtime. - list Get info from broker. - logtool The ``celery logtool`` command. - migrate Migrate tasks from one broker to another. - multi Start multiple worker instances. - purge Erase all messages from all known task queues. - report Shows information useful to include in bug-reports. - result Print the return value for a given task id. - shell Start shell session with convenient access to celery symbols. - status Show list of workers that are online. - upgrade Perform upgrade between versions. - worker Start worker instance. - ╰────────────────────────────────────────────────────────────────────────╯ - - - Specify one of these sub-commands and you can find more help from there. - ``` -
- -=== "dagster" - -
- ```console - $ rich-click dagster --help - Usage: dagster [OPTIONS] COMMAND [ARGS]... - - CLI tools for working with Dagster. - - ╭─ Options ──────────────────────────────────────────────────────────────╮ - --version -v Show the version and exit. - --help -h Show this message and exit. - ╰────────────────────────────────────────────────────────────────────────╯ - ╭─ Commands ─────────────────────────────────────────────────────────────╮ - asset Commands for working with Dagster assets. - code-server Commands for working with Dagster code servers. - debug Commands for helping debug Dagster issues by dumping or - loading artifacts from specific runs. - dev Start a local deployment of Dagster, including - dagster-webserver running on localhost and the - dagster-daemon running in the background - instance Commands for working with the current Dagster instance. - job Commands for working with Dagster jobs. - project Commands for bootstrapping new Dagster projects and code - locations. - run Commands for working with Dagster job runs. - schedule Commands for working with Dagster schedules. - sensor Commands for working with Dagster sensors. - ╰────────────────────────────────────────────────────────────────────────╯ - ``` -
+ +![`rich-click --help`](../images/code_snippets/rich_click_cli/rich_click.svg){.screenshot} + +To use, simply prefix `rich-click` to the command. Here are a few real world examples: + +=== "`flask`" + + ![](../images/rich_click_cli_examples/flask.svg "flask --help"){.screenshot} + +=== "`celery`" + + ![](../images/rich_click_cli_examples/celery.svg "celery --help"){.screenshot} + +=== "`dagster`" + + ![](../images/rich_click_cli_examples/dagster.svg "dagster --help"){.screenshot} If the CLI is not installed as a script, you can also pass the location with: `:`. @@ -152,23 +33,29 @@ You can also use `rich-click --output=html [command]` to render rich HTML for he This works for RichCommands as well as normal click Commands. -Notably, we used this functionality to help write these docs you are reading right now. :) +HTML example: -
-```console -$ rich-click --output=html flask --help + +![`rich-click --output svg app:main --help | grep -Eo '.{1,120}'`](../images/code_snippets/rich_click_cli/output_to_html.svg){.screenshot} -<span style="color: #808000; text-decoration-color: #808000">Usage:</span> <span style="font-weight: bold">flask</span> [<span style="color: #008080; text-decoration-color: #008080; font-weight: bold">OPTIONS</span>] <span style="color: #008080; text-decoration-color: #008080; font-weight: bold">COMMAND</span> [<span style="color: #008080; text-decoration-color: #008080; font-weight: bold">ARGS</span>]... +SVG example: -A general utility script for Flask applications. - <span style="color: #7f7f7f; text-decoration-color: #7f7f7f">An application to load must be given with the &#x27;</span><span style="color: #7fbfbf; text-decoration-color: #7fbfbf; font-weight: bold">--app</span><span style="color: #7f7f7f; text-decoration-color: #7f7f7f">&#x27; option, </span> - <span style="color: #7f7f7f; text-decoration-color: #7f7f7f">&#x27;FLASK_APP&#x27; environment variable, or with a &#x27;wsgi.py&#x27; or &#x27;app.py&#x27; file</span> -<span style="color: #7f7f7f; text-decoration-color: #7f7f7f">in the current directory.</span> + +![`rich-click --output html app:main --help | grep -Eo '.{1,120}'`](../images/code_snippets/rich_click_cli/output_to_svg.svg){.screenshot} -// The rest of the output is omitted - -``` -
+_SVG and HTML generated from [`docs/code_snippets/rich_click_cli/app.py`](https://github.com/ewels/rich-click/blob/main/docs/code_snippets/rich_click_cli/app.py)_ ## Notes on how the `rich-click` CLI works @@ -198,7 +85,7 @@ That said, custom, non-**rich-click** implementations are ignored. The functionality that `rich-click` uses to patch Click internals is available for use by **rich-click** end users, and it occasionally comes in handy outside of the `rich-click` CLI. -In some situations, you might be registering a command from another Click CLI that does not use Rich-Click: +In some situations, you might be registering a command from another Click CLI that does not use **rich-click**: ```python import rich_click as click @@ -213,7 +100,7 @@ cli.add_command(another_cli) ``` In this situation, `another_cli` retains its original help text behavior. -In order to make `another_cli` work with Rich-Click, you need to patch `click` before you import `another_cli`. +In order to make `another_cli` work with **rich-click**, you need to patch `click` before you import `another_cli`. You can patch Click with `rich_click.patch.patch` like this: ```python diff --git a/docs/images/arguments.svg b/docs/images/arguments.svg index fca65a04..e2704a72 100644 --- a/docs/images/arguments.svg +++ b/docs/images/arguments.svg @@ -19,132 +19,132 @@ font-weight: 700; } - .terminal-3004572887-matrix { + .terminal-557917121-matrix { font-family: Fira Code, monospace; font-size: 20px; line-height: 24.4px; font-variant-east-asian: full-width; } - .terminal-3004572887-title { + .terminal-557917121-title { font-size: 18px; font-weight: bold; font-family: arial; } - .terminal-3004572887-r1 { fill: #c5c8c6 } -.terminal-3004572887-r2 { fill: #d0b344 } -.terminal-3004572887-r3 { fill: #c5c8c6;font-weight: bold } -.terminal-3004572887-r4 { fill: #68a0b3;font-weight: bold } -.terminal-3004572887-r5 { fill: #868887 } -.terminal-3004572887-r6 { fill: #4e707b;font-weight: bold } -.terminal-3004572887-r7 { fill: #cc555a } -.terminal-3004572887-r8 { fill: #d0b344;font-weight: bold } -.terminal-3004572887-r9 { fill: #8a4346 } -.terminal-3004572887-r10 { fill: #8d7b39;font-weight: bold } + .terminal-557917121-r1 { fill: #c5c8c6 } +.terminal-557917121-r2 { fill: #d0b344 } +.terminal-557917121-r3 { fill: #c5c8c6;font-weight: bold } +.terminal-557917121-r4 { fill: #68a0b3;font-weight: bold } +.terminal-557917121-r5 { fill: #868887 } +.terminal-557917121-r6 { fill: #4e707b;font-weight: bold } +.terminal-557917121-r7 { fill: #cc555a } +.terminal-557917121-r8 { fill: #d0b344;font-weight: bold } +.terminal-557917121-r9 { fill: #8a4346 } +.terminal-557917121-r10 { fill: #8d7b39;font-weight: bold } - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - Positional arguments example + Positional arguments example - + - - $ python ../../examples/06_arguments.py --help - -Usage:06_arguments.py [OPTIONSINPUTOUTPUT {yaml|json} [FLAVOUR]             - - My amazing tool does all the things.                                            -This is a minimal example based on documentation from the 'click' package. -You can try using --help at the top level and also for specific group  -subcommands. - -╭─ Arguments ──────────────────────────────────────────────────────────────────╮ -*  INPUT      PATH       [required] -*  OUTPUT     PATH       [required] -*  FORMAT     {yaml|json}[required] -    FLAVOUR    TEXT        -╰──────────────────────────────────────────────────────────────────────────────╯ -╭─ Options ────────────────────────────────────────────────────────────────────╮ ---typeTEXT  Type of file to sync [default: files] ---all  Sync all the things?                                         ---debug  Enable debug mode                                            ---help  Show this message and exit.                                  -╰──────────────────────────────────────────────────────────────────────────────╯ - + + $ python examples/06_arguments.py --help + +Usage:06_arguments.py [OPTIONSINPUTOUTPUT {yaml|json} [FLAVOUR]             + + My amazing tool does all the things.                                            +This is a minimal example based on documentation from the 'click' package. +You can try using --help at the top level and also for specific group  +subcommands. + +╭─ Arguments ──────────────────────────────────────────────────────────────────╮ +*  INPUT      PATH       [required] +*  OUTPUT     PATH       [required] +*  FORMAT     {yaml|json}[required] +    FLAVOUR    TEXT        +╰──────────────────────────────────────────────────────────────────────────────╯ +╭─ Options ────────────────────────────────────────────────────────────────────╮ +--typeTEXT  Type of file to sync [default: files] +--all  Sync all the things?                                         +--debug  Enable debug mode                                            +--help  Show this message and exit.                                  +╰──────────────────────────────────────────────────────────────────────────────╯ + diff --git a/docs/images/code_snippets/introduction_to_click/hello.svg b/docs/images/code_snippets/introduction_to_click/hello.svg new file mode 100644 index 00000000..d6eb4627 --- /dev/null +++ b/docs/images/code_snippets/introduction_to_click/hello.svg @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + + + + + + $ python hello.py +Hello, world! + + + + diff --git a/docs/images/code_snippets/introduction_to_click/hello_help.svg b/docs/images/code_snippets/introduction_to_click/hello_help.svg new file mode 100644 index 00000000..d51f7df9 --- /dev/null +++ b/docs/images/code_snippets/introduction_to_click/hello_help.svg @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $ python hello.py --help +Usage: hello.py [OPTIONS] + +  Prints 'hello, world!' into the terminal. + +Options: +  --help  Show this message and exit. + + + + diff --git a/docs/images/code_snippets/introduction_to_click/hello_rich.svg b/docs/images/code_snippets/introduction_to_click/hello_rich.svg new file mode 100644 index 00000000..ca8b103d --- /dev/null +++ b/docs/images/code_snippets/introduction_to_click/hello_rich.svg @@ -0,0 +1,114 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $ python hello_rich.py --help + +Usage:hello_rich.py [OPTIONSCOMMAND [ARGS]...                                + + CLI for greetings.                                                              + +╭─ Options ────────────────────────────────────────────────────────────────────╮ +--help      Show this message and exit.                                       +╰──────────────────────────────────────────────────────────────────────────────╯ +╭─ Commands ───────────────────────────────────────────────────────────────────╮ +english                  Greet in English                                    +french                   Greet in French                                     +╰──────────────────────────────────────────────────────────────────────────────╯ + + + + + diff --git a/docs/images/code_snippets/introduction_to_click/hello_v2.svg b/docs/images/code_snippets/introduction_to_click/hello_v2.svg new file mode 100644 index 00000000..75257a88 --- /dev/null +++ b/docs/images/code_snippets/introduction_to_click/hello_v2.svg @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $ python hello_v2.py --say-goodbye --times 3 Edward +Hello, Edward! +Hello, Edward! +Hello, Edward! +Goodbye! + + + + diff --git a/docs/images/code_snippets/introduction_to_click/hello_v2_help.svg b/docs/images/code_snippets/introduction_to_click/hello_v2_help.svg new file mode 100644 index 00000000..d23c9c34 --- /dev/null +++ b/docs/images/code_snippets/introduction_to_click/hello_v2_help.svg @@ -0,0 +1,90 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $ python hello_v2.py --help +Usage: hello_v2.py [OPTIONS] NAME + +  Prints 'hello, [name]!' into the terminal N times. + +Options: +  -t, --times INTEGER  Number of times to print the greeting.  [default: 1] +  --say-goodbye        After saying hello, say goodbye. +  --help               Show this message and exit. + + + + diff --git a/docs/images/code_snippets/introduction_to_click/hello_v3_help.svg b/docs/images/code_snippets/introduction_to_click/hello_v3_help.svg new file mode 100644 index 00000000..7d8cc148 --- /dev/null +++ b/docs/images/code_snippets/introduction_to_click/hello_v3_help.svg @@ -0,0 +1,98 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $ python hello_v3.py --help +Usage: hello_v3.py [OPTIONS] COMMAND [ARGS]... + +  CLI for greetings. + +Options: +  --help  Show this message and exit. + +Commands: +  english  Greet in English +  french   Greet in French + + + + diff --git a/docs/images/code_snippets/introduction_to_click/hello_v3_subcommand.svg b/docs/images/code_snippets/introduction_to_click/hello_v3_subcommand.svg new file mode 100644 index 00000000..55dd6199 --- /dev/null +++ b/docs/images/code_snippets/introduction_to_click/hello_v3_subcommand.svg @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + + + + + + $ python hello_v3.py french Jennifer +Bonjour, Jennifer! + + + + diff --git a/docs/images/code_snippets/introduction_to_click/hello_v3_subcommand_help.svg b/docs/images/code_snippets/introduction_to_click/hello_v3_subcommand_help.svg new file mode 100644 index 00000000..850fab91 --- /dev/null +++ b/docs/images/code_snippets/introduction_to_click/hello_v3_subcommand_help.svg @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $ python hello_v3.py french --help +Usage: hello_v3.py french [OPTIONS] NAME + +  Greet in French + +Options: +  --help  Show this message and exit. + + + + diff --git a/docs/images/code_snippets/rich_click_cli/output_to_html.svg b/docs/images/code_snippets/rich_click_cli/output_to_html.svg new file mode 100644 index 00000000..51cc1a34 --- /dev/null +++ b/docs/images/code_snippets/rich_click_cli/output_to_html.svg @@ -0,0 +1,111 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $ rich-click --output svg app:main --help +<svg class="rich-terminal" viewBox="0 0 994 416.0" xmlns="http://www.w3.org/2000/svg"> +    <!-- Generated with Rich https://www.textualize.io --> +    <style> +    @font-face { +        font-family: "Fira Code"; +        src: local("FiraCode-Regular"), +                url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff2/FiraCode-Regular.woff2") format("woff2" +), +                url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff/FiraCode-Regular.woff") format("woff"); +        font-style: normal; +        font-weight: 400; +    } +[..truncated..] + + + + diff --git a/docs/images/code_snippets/rich_click_cli/output_to_svg.svg b/docs/images/code_snippets/rich_click_cli/output_to_svg.svg new file mode 100644 index 00000000..0318ad7c --- /dev/null +++ b/docs/images/code_snippets/rich_click_cli/output_to_svg.svg @@ -0,0 +1,111 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $ rich-click --output html app:main --help + + <span style="color: #808000; text-decoration-color: #808000">Usage:</span> <span style="font-weight: bold">app</span> [ +<span style="color: #008080; text-decoration-color: #008080; font-weight: bold">OPTIONS</span>] <span style="color: #008 +080; text-decoration-color: #008080; font-weight: bold">COMMAND</span> [<span style="color: #008080; text-decoration-col +or: #008080; font-weight: bold">ARGS</span>]...                                          + + CLI for my-app                                                                  + +<span style="color: #7f7f7f; text-decoration-color: #7f7f7f">╭─ Options ──────────────────────────────────────────────── +────────────────────╮</span> +<span style="color: #7f7f7f; text-decoration-color: #7f7f7f">│</span> <span style="color: #008080; text-decoration-color +: #008080; font-weight: bold">--environment</span>  <span style="color: #008000; text-decoration-color: #008000; font-we +[..truncated..] + + + + diff --git a/docs/images/code_snippets/rich_click_cli/rich_click.svg b/docs/images/code_snippets/rich_click_cli/rich_click.svg new file mode 100644 index 00000000..480a59b7 --- /dev/null +++ b/docs/images/code_snippets/rich_click_cli/rich_click.svg @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $ rich-click --help + +Usage:                                                       rich-click + [OPTIONS] [SCRIPT | MODULE:CLICK_COMMAND] [-- SCRIPT_ARGS...]                   + + The rich-click CLI provides attractive help output from any tool using click,   + formatted with rich.                                                            +The rich-click command line tool can be prepended before any Python package  +using native click to provide attractive richified click help output. +For example, if you have a package called my_package that uses click, you can  +run: +>>> rich-clickmy_package--help +This does not always work if the package is using customised click.group() or  +[..truncated..] + + + + diff --git a/docs/images/custom_error.svg b/docs/images/custom_error.svg index 1a4d15a8..f2e7d515 100644 --- a/docs/images/custom_error.svg +++ b/docs/images/custom_error.svg @@ -19,86 +19,86 @@ font-weight: 700; } - .terminal-3504293245-matrix { + .terminal-1270695015-matrix { font-family: Fira Code, monospace; font-size: 20px; line-height: 24.4px; font-variant-east-asian: full-width; } - .terminal-3504293245-title { + .terminal-1270695015-title { font-size: 18px; font-weight: bold; font-family: arial; } - .terminal-3504293245-r1 { fill: #c5c8c6 } -.terminal-3504293245-r2 { fill: #d0b344 } -.terminal-3504293245-r3 { fill: #c5c8c6;font-weight: bold } -.terminal-3504293245-r4 { fill: #68a0b3;font-weight: bold } -.terminal-3504293245-r5 { fill: #98729f;font-style: italic; } -.terminal-3504293245-r6 { fill: #98a84b } -.terminal-3504293245-r7 { fill: #cc555a } -.terminal-3504293245-r8 { fill: #1984e9;text-decoration: underline; } + .terminal-1270695015-r1 { fill: #c5c8c6 } +.terminal-1270695015-r2 { fill: #d0b344 } +.terminal-1270695015-r3 { fill: #c5c8c6;font-weight: bold } +.terminal-1270695015-r4 { fill: #68a0b3;font-weight: bold } +.terminal-1270695015-r5 { fill: #98729f;font-style: italic; } +.terminal-1270695015-r6 { fill: #98a84b } +.terminal-1270695015-r7 { fill: #cc555a } +.terminal-1270695015-r8 { fill: #1984e9;text-decoration: underline; } - + - + - + - + - + - + - + - + - + - + - + - Custom error message + Custom error message - + - - $ python ../../examples/07_custom_errors.py --hep || true - -Usage:07_custom_errors.py [OPTIONSINPUT - -Try running the '--help' flag for more information. -╭─ Error ──────────────────────────────────────────────────────────────────────╮ - No such option: --hep Did you mean --help?                                    -╰──────────────────────────────────────────────────────────────────────────────╯ - - To find out more, visit https://mytool.com - + + $ python examples/07_custom_errors.py --hep || true + +Usage:07_custom_errors.py [OPTIONSINPUT + +Try running the '--help' flag for more information. +╭─ Error ──────────────────────────────────────────────────────────────────────╮ + No such option: --hep Did you mean --help?                                    +╰──────────────────────────────────────────────────────────────────────────────╯ + + To find out more, visit https://mytool.com + diff --git a/docs/images/error.svg b/docs/images/error.svg index 23e2d8bc..1c828e68 100644 --- a/docs/images/error.svg +++ b/docs/images/error.svg @@ -19,77 +19,77 @@ font-weight: 700; } - .terminal-1476374681-matrix { + .terminal-4185829251-matrix { font-family: Fira Code, monospace; font-size: 20px; line-height: 24.4px; font-variant-east-asian: full-width; } - .terminal-1476374681-title { + .terminal-4185829251-title { font-size: 18px; font-weight: bold; font-family: arial; } - .terminal-1476374681-r1 { fill: #c5c8c6 } -.terminal-1476374681-r2 { fill: #d0b344 } -.terminal-1476374681-r3 { fill: #c5c8c6;font-weight: bold } -.terminal-1476374681-r4 { fill: #68a0b3;font-weight: bold } -.terminal-1476374681-r5 { fill: #868887 } -.terminal-1476374681-r6 { fill: #4a637a } -.terminal-1476374681-r7 { fill: #cc555a } + .terminal-4185829251-r1 { fill: #c5c8c6 } +.terminal-4185829251-r2 { fill: #d0b344 } +.terminal-4185829251-r3 { fill: #c5c8c6;font-weight: bold } +.terminal-4185829251-r4 { fill: #68a0b3;font-weight: bold } +.terminal-4185829251-r5 { fill: #868887 } +.terminal-4185829251-r6 { fill: #4a637a } +.terminal-4185829251-r7 { fill: #cc555a } - + - + - + - + - + - + - + - + - + - Error message + Error message - + - - $ python ../../examples/01_simple.py --hep || true - -Usage:01_simple.py [OPTIONSCOMMAND [ARGS]...                                 - -Try'01_simple.py --help'for help -╭─ Error ──────────────────────────────────────────────────────────────────────╮ - No such option: --hep Did you mean --help?                                    -╰──────────────────────────────────────────────────────────────────────────────╯ - + + $ python examples/01_simple.py --hep || true + +Usage:01_simple.py [OPTIONSCOMMAND [ARGS]...                                 + +Try'01_simple.py --help'for help +╭─ Error ──────────────────────────────────────────────────────────────────────╮ + No such option: --hep Did you mean --help?                                    +╰──────────────────────────────────────────────────────────────────────────────╯ + diff --git a/docs/images/markdown.svg b/docs/images/markdown.svg index cd4a828e..b7ecc460 100644 --- a/docs/images/markdown.svg +++ b/docs/images/markdown.svg @@ -19,151 +19,151 @@ font-weight: 700; } - .terminal-1739523751-matrix { + .terminal-2871723409-matrix { font-family: Fira Code, monospace; font-size: 20px; line-height: 24.4px; font-variant-east-asian: full-width; } - .terminal-1739523751-title { + .terminal-2871723409-title { font-size: 18px; font-weight: bold; font-family: arial; } - .terminal-1739523751-r1 { fill: #c5c8c6 } -.terminal-1739523751-r2 { fill: #d0b344 } -.terminal-1739523751-r3 { fill: #c5c8c6;font-weight: bold } -.terminal-1739523751-r4 { fill: #68a0b3;font-weight: bold } -.terminal-1739523751-r5 { fill: #c5c8c6;font-weight: bold;font-style: italic; } -.terminal-1739523751-r6 { fill: #868887 } -.terminal-1739523751-r7 { fill: #5c7f8d;font-weight: bold } -.terminal-1739523751-r8 { fill: #4a637a;font-style: italic;;text-decoration: underline; } -.terminal-1739523751-r9 { fill: #4a637a;text-decoration: underline; } -.terminal-1739523751-r10 { fill: #6b546f } -.terminal-1739523751-r11 { fill: #8d7b39;font-weight: bold } -.terminal-1739523751-r12 { fill: #d0b344;font-weight: bold } -.terminal-1739523751-r13 { fill: #c5c8c6;font-style: italic; } + .terminal-2871723409-r1 { fill: #c5c8c6 } +.terminal-2871723409-r2 { fill: #d0b344 } +.terminal-2871723409-r3 { fill: #c5c8c6;font-weight: bold } +.terminal-2871723409-r4 { fill: #68a0b3;font-weight: bold } +.terminal-2871723409-r5 { fill: #c5c8c6;font-weight: bold;font-style: italic; } +.terminal-2871723409-r6 { fill: #868887 } +.terminal-2871723409-r7 { fill: #5c7f8d;font-weight: bold } +.terminal-2871723409-r8 { fill: #4a637a;font-style: italic;;text-decoration: underline; } +.terminal-2871723409-r9 { fill: #4a637a;text-decoration: underline; } +.terminal-2871723409-r10 { fill: #6b546f } +.terminal-2871723409-r11 { fill: #8d7b39;font-weight: bold } +.terminal-2871723409-r12 { fill: #d0b344;font-weight: bold } +.terminal-2871723409-r13 { fill: #c5c8c6;font-style: italic; } - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - Markdown example + Markdown example - + - - $ python ../../examples/05_markdown.py --help - -Usage:05_markdown.py [OPTIONS]                                                 - - My amazing tool does all the things.                                            -This is a minimal example based on documentation from the click package. - -▌ Remember: -▌  • You can try using --help at the top level -▌  • Also for specific group subcommands. - -╭─ Options ────────────────────────────────────────────────────────────────────╮ ---inputPATH  Input file[default: a custom default] ---typeTEXT  Type of file to sync                                         -[default: files]                                            ---all  Sync                                                         - - 1 all                                                       - 2 the                                                       - 3 things?                                                   ---debug  ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓  -                  ┃                    Enable debug mode                    ┃  -                  ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛  ---help  Show this message and exit.                                  -╰──────────────────────────────────────────────────────────────────────────────╯ - + + $ python examples/05_markdown.py --help + +Usage:05_markdown.py [OPTIONS]                                                 + + My amazing tool does all the things.                                            +This is a minimal example based on documentation from the click package. + +▌ Remember: +▌  • You can try using --help at the top level +▌  • Also for specific group subcommands. + +╭─ Options ────────────────────────────────────────────────────────────────────╮ +--inputPATH  Input file[default: a custom default] +--typeTEXT  Type of file to sync                                         +[default: files]                                            +--all  Sync                                                         + + 1 all                                                       + 2 the                                                       + 3 things?                                                   +--debug  ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓  +                  ┃                    Enable debug mode                    ┃  +                  ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛  +--help  Show this message and exit.                                  +╰──────────────────────────────────────────────────────────────────────────────╯ + diff --git a/docs/images/metavars_appended.svg b/docs/images/metavars_appended.svg index 506d232e..247a22b4 100644 --- a/docs/images/metavars_appended.svg +++ b/docs/images/metavars_appended.svg @@ -19,117 +19,117 @@ font-weight: 700; } - .terminal-610888738-matrix { + .terminal-3832703756-matrix { font-family: Fira Code, monospace; font-size: 20px; line-height: 24.4px; font-variant-east-asian: full-width; } - .terminal-610888738-title { + .terminal-3832703756-title { font-size: 18px; font-weight: bold; font-family: arial; } - .terminal-610888738-r1 { fill: #c5c8c6 } -.terminal-610888738-r2 { fill: #d0b344 } -.terminal-610888738-r3 { fill: #c5c8c6;font-weight: bold } -.terminal-610888738-r4 { fill: #68a0b3;font-weight: bold } -.terminal-610888738-r5 { fill: #868887 } -.terminal-610888738-r6 { fill: #4e707b;font-weight: bold } -.terminal-610888738-r7 { fill: #8d7b39 } + .terminal-3832703756-r1 { fill: #c5c8c6 } +.terminal-3832703756-r2 { fill: #d0b344 } +.terminal-3832703756-r3 { fill: #c5c8c6;font-weight: bold } +.terminal-3832703756-r4 { fill: #68a0b3;font-weight: bold } +.terminal-3832703756-r5 { fill: #868887 } +.terminal-3832703756-r6 { fill: #4e707b;font-weight: bold } +.terminal-3832703756-r7 { fill: #8d7b39 } - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - Appended metavar + Appended metavar - + - - $ python ../../examples/08_metavars.py --help - -Usage:08_metavars.py [OPTIONS]                                                 - - My amazing tool does all the things.                                            -This is a minimal example based on documentation from the 'click' package. -You can try using --help at the top level and also for specific group  -subcommands. - -╭─ Options ────────────────────────────────────────────────────────────────────╮ ---debug     Enable debug mode.                                                ---number    This click choice has loads of options.                           -(one|two|three|four|five|six|seven|eight|nine|ten|eleven|twelve| -thirteen|fourteen|fifteen|sixteen|seventeen|eighteen|nineteen|tw -enty|twenty-one|twenty-two|twenty-three|twenty-four|twenty-five| -twenty-six|twenty-seven|twenty-eight|twenty-nine|thirty)         ---help      Show this message and exit.                                       -╰──────────────────────────────────────────────────────────────────────────────╯ - + + $ python examples/08_metavars.py --help + +Usage:08_metavars.py [OPTIONS]                                                 + + My amazing tool does all the things.                                            +This is a minimal example based on documentation from the 'click' package. +You can try using --help at the top level and also for specific group  +subcommands. + +╭─ Options ────────────────────────────────────────────────────────────────────╮ +--debug     Enable debug mode.                                                +--number    This click choice has loads of options.                           +(one|two|three|four|five|six|seven|eight|nine|ten|eleven|twelve| +thirteen|fourteen|fifteen|sixteen|seventeen|eighteen|nineteen|tw +enty|twenty-one|twenty-two|twenty-three|twenty-four|twenty-five| +twenty-six|twenty-seven|twenty-eight|twenty-nine|thirty)         +--help      Show this message and exit.                                       +╰──────────────────────────────────────────────────────────────────────────────╯ + diff --git a/docs/images/metavars_default.svg b/docs/images/metavars_default.svg index 85f4bee6..34e60ae1 100644 --- a/docs/images/metavars_default.svg +++ b/docs/images/metavars_default.svg @@ -19,134 +19,134 @@ font-weight: 700; } - .terminal-187538908-matrix { + .terminal-3012861126-matrix { font-family: Fira Code, monospace; font-size: 20px; line-height: 24.4px; font-variant-east-asian: full-width; } - .terminal-187538908-title { + .terminal-3012861126-title { font-size: 18px; font-weight: bold; font-family: arial; } - .terminal-187538908-r1 { fill: #c5c8c6 } -.terminal-187538908-r2 { fill: #d0b344 } -.terminal-187538908-r3 { fill: #c5c8c6;font-weight: bold } -.terminal-187538908-r4 { fill: #68a0b3;font-weight: bold } -.terminal-187538908-r5 { fill: #868887 } -.terminal-187538908-r6 { fill: #4e707b;font-weight: bold } -.terminal-187538908-r7 { fill: #d0b344;font-weight: bold } -.terminal-187538908-r8 { fill: #8d7b39;font-weight: bold } + .terminal-3012861126-r1 { fill: #c5c8c6 } +.terminal-3012861126-r2 { fill: #d0b344 } +.terminal-3012861126-r3 { fill: #c5c8c6;font-weight: bold } +.terminal-3012861126-r4 { fill: #68a0b3;font-weight: bold } +.terminal-3012861126-r5 { fill: #868887 } +.terminal-3012861126-r6 { fill: #4e707b;font-weight: bold } +.terminal-3012861126-r7 { fill: #d0b344;font-weight: bold } +.terminal-3012861126-r8 { fill: #8d7b39;font-weight: bold } - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - Default metavar display + Default metavar display - + - - $ python ../../examples/08_metavars_default.py --help - -Usage:08_metavars_default.py [OPTIONS]                                         - - My amazing tool does all the things.                                            -This is a minimal example based on documentation from the 'click' package. -You can try using --help at the top level and also for specific group  -subcommands. - -╭─ Options ────────────────────────────────────────────────────────────────────╮ ---debug  Enable debug mode.                ---number[one|two|three|four|five|six|s  This click choice has loads of    -even|eight|nine|ten|eleven|twe  options.                          -lve|thirteen|fourteen|fifteen| -sixteen|seventeen|eighteen|nin -eteen|twenty|twenty-one|twenty --two|twenty-three|twenty-four| -twenty-five|twenty-six|twenty- -seven|twenty-eight|twenty-nine -|thirty] ---help  Show this message and exit.       -╰──────────────────────────────────────────────────────────────────────────────╯ - + + $ python examples/08_metavars_default.py --help + +Usage:08_metavars_default.py [OPTIONS]                                         + + My amazing tool does all the things.                                            +This is a minimal example based on documentation from the 'click' package. +You can try using --help at the top level and also for specific group  +subcommands. + +╭─ Options ────────────────────────────────────────────────────────────────────╮ +--debug  Enable debug mode.                +--number[one|two|three|four|five|six|s  This click choice has loads of    +even|eight|nine|ten|eleven|twe  options.                          +lve|thirteen|fourteen|fifteen| +sixteen|seventeen|eighteen|nin +eteen|twenty|twenty-one|twenty +-two|twenty-three|twenty-four| +twenty-five|twenty-six|twenty- +seven|twenty-eight|twenty-nine +|thirty] +--help  Show this message and exit.       +╰──────────────────────────────────────────────────────────────────────────────╯ + diff --git a/docs/images/rich_click_cli_examples/celery.svg b/docs/images/rich_click_cli_examples/celery.svg new file mode 100644 index 00000000..74edd8a6 --- /dev/null +++ b/docs/images/rich_click_cli_examples/celery.svg @@ -0,0 +1,226 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Rich + + + + + + + + + + +Usage:celery[OPTIONSCOMMAND [ARGS]... + +Celery command entrypoint. + +╭─ Options ────────────────────────────────────────────────────────────────────╮ +--app-AAPPLICATION +--broker-bTEXT        +--result-backendTEXT        +--loaderTEXT        +--configTEXT        +--workdirPATH        +--no-color-C +--quiet-q +--version +--skip-checksSkip Django core checks on startup.       +Setting the SKIP_CHECKS environment       +variable to any non-empty string will     +have the same effect.                     +--helpShow this message and exit. +╰──────────────────────────────────────────────────────────────────────────────╯ +╭─ Commands ───────────────────────────────────────────────────────────────────╮ +amqp    AMQP Administration Shell.                                         +beat    Start the beat periodic task scheduler.                            +call    Call a task by name.                                               +control Workers remote control.                                            +events  Event-stream utilities.                                            +graph   The ``celery graph`` command.                                      +inspect Inspect the worker at runtime.                                     +list    Get info from broker.                                              +logtool The ``celery logtool`` command.                                    +migrate Migrate tasks from one broker to another.                          +multi   Start multiple worker instances.                                   +purge   Erase all messages from all known task queues.                     +report  Shows information useful to include in bug-reports.                +result  Print the return value for a given task id.                        +shell   Start shell session with convenient access to celery symbols.      +status  Show list of workers that are online.                              +upgrade Perform upgrade between versions.                                  +worker  Start worker instance.                                             +╰──────────────────────────────────────────────────────────────────────────────╯ + + + + + diff --git a/docs/images/rich_click_cli_examples/dagster.svg b/docs/images/rich_click_cli_examples/dagster.svg new file mode 100644 index 00000000..60a990f0 --- /dev/null +++ b/docs/images/rich_click_cli_examples/dagster.svg @@ -0,0 +1,161 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Rich + + + + + + + + + + +Usage:dagster[OPTIONSCOMMAND [ARGS]... + +CLI tools for working with Dagster. + +╭─ Options ────────────────────────────────────────────────────────────────────╮ +--version-vShow the version and exit. +--help-hShow this message and exit. +╰──────────────────────────────────────────────────────────────────────────────╯ +╭─ Commands ───────────────────────────────────────────────────────────────────╮ +asset      Commands for working with Dagster assets.                       +code-serverCommands for working with Dagster code servers.                 +debug      Commands for helping debug Dagster issues by dumping or loading +artifacts from specific runs.                                   +dev        Start a local deployment of Dagster, including                  +dagster-webserver running on localhost and the dagster-daemon   +running in the background                                       +instance   Commands for working with the current Dagster instance.         +job        Commands for working with Dagster jobs.                         +project    Commands for bootstrapping new Dagster projects and code        +locations.                                                      +run        Commands for working with Dagster job runs.                     +schedule   Commands for working with Dagster schedules.                    +sensor     Commands for working with Dagster sensors.                      +╰──────────────────────────────────────────────────────────────────────────────╯ + + + + + diff --git a/docs/images/rich_click_cli_examples/flask.svg b/docs/images/rich_click_cli_examples/flask.svg new file mode 100644 index 00000000..58b15658 --- /dev/null +++ b/docs/images/rich_click_cli_examples/flask.svg @@ -0,0 +1,167 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Rich + + + + + + + + + + +Usage:flask[OPTIONSCOMMAND [ARGS]... + +A general utility script for Flask applications. +An application to load must be given with the '--app' option, 'FLASK_APP'  +environment variable, or with a 'wsgi.py' or 'app.py' file in the current  +directory. + +╭─ Options ────────────────────────────────────────────────────────────────────╮ +--env-file-eFILE  Load environment variables from this file.   +python-dotenv must be installed.             +--app-AIMPORTThe Flask application or factory function to +load, in the form 'module:name'. Module can  +be a dotted import or file path. Name is not +required if it is 'app', 'application',      +'create_app', or 'make_app', and can be      +'name(args)' to pass arguments.              +--debug/--no-debugSet debug mode. +--versionShow the Flask version. +--helpShow this message and exit. +╰──────────────────────────────────────────────────────────────────────────────╯ +╭─ Commands ───────────────────────────────────────────────────────────────────╮ +routes       Show the routes for the app.                                  +run          Run a development server.                                     +shell        Run a shell in the app context.                               +╰──────────────────────────────────────────────────────────────────────────────╯ + + + + + diff --git a/docs/images/rich_markup.svg b/docs/images/rich_markup.svg index 9b2e75f9..e67f346b 100644 --- a/docs/images/rich_markup.svg +++ b/docs/images/rich_markup.svg @@ -1,4 +1,4 @@ - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - Rich markup example + Rich markup example - + - - $ python ../../examples/04_rich_markup.py --help -/home/runner/work/rich-click/rich-click/docs/documentation/../../examples/04_rich_markup.py:11: SyntaxWarning: invalid escape sequence '\[' -  help="Input [magenta bold]file[/]. [dim]\[default: a custom default][/]", - -Usage:04_rich_markup.py [OPTIONS]                                              - - My amazing tool does  all the things .                                          -This is a minimal example based on documentation from the 'click' package. -You can try using --help at the top level and also for specific group  -subcommands. - -╭─ Options ────────────────────────────────────────────────────────────────────╮ ---inputPATH  Input file[default: a custom default] ---typeTEXT  Type of file to sync [default: files] ---all  Sync all the things?                                         ---debug  Enable 👉 debug mode 👈                                      ---help  Show this message and exit.                                  -╰──────────────────────────────────────────────────────────────────────────────╯ - + + $ python examples/04_rich_markup.py --help +/home/runner/work/rich-click/rich-click/examples/04_rich_markup.py:11: SyntaxWarning: invalid escape sequence '\[' +  help="Input [magenta bold]file[/]. [dim]\[default: a custom default][/]", + +Usage:04_rich_markup.py [OPTIONS]                                              + + My amazing tool does  all the things .                                          +This is a minimal example based on documentation from the 'click' package. +You can try using --help at the top level and also for specific group  +subcommands. + +╭─ Options ────────────────────────────────────────────────────────────────────╮ +--inputPATH  Input file[default: a custom default] +--typeTEXT  Type of file to sync [default: files] +--all  Sync all the things?                                         +--debug  Enable 👉 debug mode 👈                                      +--help  Show this message and exit.                                  +╰──────────────────────────────────────────────────────────────────────────────╯ + diff --git a/docs/images/style_tables.svg b/docs/images/style_tables.svg index cba70d20..0f497179 100644 --- a/docs/images/style_tables.svg +++ b/docs/images/style_tables.svg @@ -19,271 +19,271 @@ font-weight: 700; } - .terminal-414580282-matrix { + .terminal-1631386916-matrix { font-family: Fira Code, monospace; font-size: 20px; line-height: 24.4px; font-variant-east-asian: full-width; } - .terminal-414580282-title { + .terminal-1631386916-title { font-size: 18px; font-weight: bold; font-family: arial; } - .terminal-414580282-r1 { fill: #c5c8c6 } -.terminal-414580282-r2 { fill: #d0b344 } -.terminal-414580282-r3 { fill: #c5c8c6;font-weight: bold } -.terminal-414580282-r4 { fill: #68a0b3;font-weight: bold } -.terminal-414580282-r5 { fill: #868887 } -.terminal-414580282-r6 { fill: #4e707b;font-weight: bold } -.terminal-414580282-r7 { fill: #d0b344;font-weight: bold } -.terminal-414580282-r8 { fill: #98a84b;font-weight: bold } -.terminal-414580282-r9 { fill: #cc555a } -.terminal-414580282-r10 { fill: #98729f;font-weight: bold } -.terminal-414580282-r11 { fill: #98729f } -.terminal-414580282-r12 { fill: #68a0b3 } -.terminal-414580282-r13 { fill: #98a84b } + .terminal-1631386916-r1 { fill: #c5c8c6 } +.terminal-1631386916-r2 { fill: #d0b344 } +.terminal-1631386916-r3 { fill: #c5c8c6;font-weight: bold } +.terminal-1631386916-r4 { fill: #68a0b3;font-weight: bold } +.terminal-1631386916-r5 { fill: #868887 } +.terminal-1631386916-r6 { fill: #4e707b;font-weight: bold } +.terminal-1631386916-r7 { fill: #d0b344;font-weight: bold } +.terminal-1631386916-r8 { fill: #98a84b;font-weight: bold } +.terminal-1631386916-r9 { fill: #cc555a } +.terminal-1631386916-r10 { fill: #98729f;font-weight: bold } +.terminal-1631386916-r11 { fill: #98729f } +.terminal-1631386916-r12 { fill: #68a0b3 } +.terminal-1631386916-r13 { fill: #98a84b } - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - Rich markup example + Rich markup example - + - - $ python ../../examples/10_table_styles.py --help - -Usage:10_table_styles.py [OPTIONSCOMMAND [ARGS]...                                                                                                           - - My amazing tool does all the things.                                                                                                                            -This is a minimal example based on documentation from the 'click' package. -You can try using --help at the top level and also for specific group subcommands. - -╭─ Options ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ - ---typeTEXTType of file to sync. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed sed mauris euismod, semper leo      -quis, sodales augue. Donec posuere nulla quis egestas ornare. Nam efficitur ex quis diam tempus, nec euismod diam      -consectetur. Etiam vitae nisi at odio hendrerit dictum in at dui. Aliquam nulla lacus, pellentesque id ultricies sit   -amet, mollis nec tellus. Aenean arcu justo, pellentesque viverra justo eget, tempus tincidunt lectus. Maecenas         -porttitor risus vitae libero dapibus ullamcorper. Cras faucibus euismod erat in porta. Phasellus cursus gravida ante   -vel aliquet. In accumsan enim nec ullamcorper gravida. Donec malesuada dui ac metus tristique cursus. Sed gravida      -condimentum fermentum. Ut sit amet nulla commodo, iaculis tellus vitae, accumsan enim. Curabitur mollis semper velit a -suscipit.                                                                                                              - ---debug/--no-debug-d/-n   Show the debug log messages. Suspendisse dictum hendrerit turpis eu rutrum. Vivamus magna ex, elementum sit amet         -                                      sapien laoreet, tempor consequat eros. Morbi semper feugiat nisi eget sodales. Pellentesque et turpis erat. Donec ac     -                                      aliquam risus. Nam leo tellus, rutrum et scelerisque vitae, ultrices sed metus. Ut sollicitudin convallis turpis, sit    -                                      amet sollicitudin felis semper feugiat. In sapien dui, aliquam eget dui quis, auctor maximus nibh. Suspendisse maximus   -                                      sem arcu. Pellentesque sit amet semper est. Cras pulvinar ut tellus a semper. In facilisis tellus odio, non porta nisl   -                                      accumsan nec. Pellentesque sollicitudin quam ac felis congue, ac congue enim tempor.                                     - ---versionShow the version and exit. - ---help   Show this message and exit.                                                                                              - -╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ -╭─ Commands ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ -╔══════════╦═══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════╗ -auth    Authenticate the app. Duis lacus nibh, feugiat a nibh a, commodo dictum libero. Ut ac nulla tincidunt, bibendum nisi vitae, sodales ex.       -Vestibulum efficitur, lectus quis venenatis porta, dolor elit varius mauris, consequat interdum lectus est quis mi. Vestibulum imperdiet sed  -dolor eget semper. Cras ut mauris ac libero hendrerit congue. Vivamus pretium nunc turpis, eget imperdiet sapien tempor auctor. Phasellus     -risus nisi, laoreet in posuere sit amet, sodales non diam. Aliquam non malesuada urna, a faucibus risus.                                      -╠══════════╬═══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════╣ -config  Set up the configuration. Sed accumsan ornare odio dictum aliquam. Pellentesque habitant morbi tristique senectus et netus et malesuada fames -ac turpis egestas. Curabitur in pellentesque mauris. Nulla mollis dui finibus, dictum neque id, suscipit nisl. Nunc mauris ex, laoreet nec    -tincidunt ut, pellentesque ut tortor. Mauris fermentum diam at porttitor tempor. Aliquam euismod nisi massa, nec placerat ante euismod quis.  -╠══════════╬═══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════╣ -downloadPretend to download some files from somewhere. Integer bibendum libero nunc, sed aliquet ex tincidunt vel. Duis vitae sem vel odio luctus     -suscipit nec vitae enim. Curabitur vel lectus nec quam maximus dapibus. Phasellus eros velit, maximus non hendrerit nec, tempor fringilla     -urna. Vivamus vel nibh quis sapien consectetur fermentum. Curabitur at ultrices quam, vel molestie justo. Nunc lobortis orci vel nibh         -sagittis pretium. Morbi rhoncus sapien luctus, ultrices urna vel, convallis tortor.                                                           -╠══════════╬═══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════╣ -sync    Synchronise all your files between two places. Curabitur congue eget lorem in lacinia. Praesent tempus nunc nec nulla dignissim, et lacinia   -ipsum accumsan. Duis sodales, sapien at fermentum condimentum, diam metus porttitor lacus, nec gravida mi diam eget ligula. Pellentesque      -elementum at justo a luctus. Mauris a interdum odio. Maecenas in consectetur velit. Ut tristique congue felis at tempus. Donec pulvinar       -tortor ut odio posuere imperdiet. Fusce lacinia iaculis diam in scelerisque. Pellentesque in lorem est. Nulla efficitur luctus lacus, auctor  -auctor dui hendrerit a. Ut nec iaculis dolor. Morbi metus lectus, aliquet et sapien nec, congue euismod lorem. Pellentesque tristique tempus  -augue at convallis.                                                                                                                           -╚══════════╩═══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════╝ -╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ - + + $ python examples/10_table_styles.py --help + +Usage:10_table_styles.py [OPTIONSCOMMAND [ARGS]...                                                                                                           + + My amazing tool does all the things.                                                                                                                            +This is a minimal example based on documentation from the 'click' package. +You can try using --help at the top level and also for specific group subcommands. + +╭─ Options ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ + +--typeTEXTType of file to sync. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed sed mauris euismod, semper leo      +quis, sodales augue. Donec posuere nulla quis egestas ornare. Nam efficitur ex quis diam tempus, nec euismod diam      +consectetur. Etiam vitae nisi at odio hendrerit dictum in at dui. Aliquam nulla lacus, pellentesque id ultricies sit   +amet, mollis nec tellus. Aenean arcu justo, pellentesque viverra justo eget, tempus tincidunt lectus. Maecenas         +porttitor risus vitae libero dapibus ullamcorper. Cras faucibus euismod erat in porta. Phasellus cursus gravida ante   +vel aliquet. In accumsan enim nec ullamcorper gravida. Donec malesuada dui ac metus tristique cursus. Sed gravida      +condimentum fermentum. Ut sit amet nulla commodo, iaculis tellus vitae, accumsan enim. Curabitur mollis semper velit a +suscipit.                                                                                                              + +--debug/--no-debug-d/-n   Show the debug log messages. Suspendisse dictum hendrerit turpis eu rutrum. Vivamus magna ex, elementum sit amet         +                                      sapien laoreet, tempor consequat eros. Morbi semper feugiat nisi eget sodales. Pellentesque et turpis erat. Donec ac     +                                      aliquam risus. Nam leo tellus, rutrum et scelerisque vitae, ultrices sed metus. Ut sollicitudin convallis turpis, sit    +                                      amet sollicitudin felis semper feugiat. In sapien dui, aliquam eget dui quis, auctor maximus nibh. Suspendisse maximus   +                                      sem arcu. Pellentesque sit amet semper est. Cras pulvinar ut tellus a semper. In facilisis tellus odio, non porta nisl   +                                      accumsan nec. Pellentesque sollicitudin quam ac felis congue, ac congue enim tempor.                                     + +--versionShow the version and exit. + +--help   Show this message and exit.                                                                                              + +╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ +╭─ Commands ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ +╔══════════╦═══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════╗ +auth    Authenticate the app. Duis lacus nibh, feugiat a nibh a, commodo dictum libero. Ut ac nulla tincidunt, bibendum nisi vitae, sodales ex.       +Vestibulum efficitur, lectus quis venenatis porta, dolor elit varius mauris, consequat interdum lectus est quis mi. Vestibulum imperdiet sed  +dolor eget semper. Cras ut mauris ac libero hendrerit congue. Vivamus pretium nunc turpis, eget imperdiet sapien tempor auctor. Phasellus     +risus nisi, laoreet in posuere sit amet, sodales non diam. Aliquam non malesuada urna, a faucibus risus.                                      +╠══════════╬═══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════╣ +config  Set up the configuration. Sed accumsan ornare odio dictum aliquam. Pellentesque habitant morbi tristique senectus et netus et malesuada fames +ac turpis egestas. Curabitur in pellentesque mauris. Nulla mollis dui finibus, dictum neque id, suscipit nisl. Nunc mauris ex, laoreet nec    +tincidunt ut, pellentesque ut tortor. Mauris fermentum diam at porttitor tempor. Aliquam euismod nisi massa, nec placerat ante euismod quis.  +╠══════════╬═══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════╣ +downloadPretend to download some files from somewhere. Integer bibendum libero nunc, sed aliquet ex tincidunt vel. Duis vitae sem vel odio luctus     +suscipit nec vitae enim. Curabitur vel lectus nec quam maximus dapibus. Phasellus eros velit, maximus non hendrerit nec, tempor fringilla     +urna. Vivamus vel nibh quis sapien consectetur fermentum. Curabitur at ultrices quam, vel molestie justo. Nunc lobortis orci vel nibh         +sagittis pretium. Morbi rhoncus sapien luctus, ultrices urna vel, convallis tortor.                                                           +╠══════════╬═══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════╣ +sync    Synchronise all your files between two places. Curabitur congue eget lorem in lacinia. Praesent tempus nunc nec nulla dignissim, et lacinia   +ipsum accumsan. Duis sodales, sapien at fermentum condimentum, diam metus porttitor lacus, nec gravida mi diam eget ligula. Pellentesque      +elementum at justo a luctus. Mauris a interdum odio. Maecenas in consectetur velit. Ut tristique congue felis at tempus. Donec pulvinar       +tortor ut odio posuere imperdiet. Fusce lacinia iaculis diam in scelerisque. Pellentesque in lorem est. Nulla efficitur luctus lacus, auctor  +auctor dui hendrerit a. Ut nec iaculis dolor. Morbi metus lectus, aliquet et sapien nec, congue euismod lorem. Pellentesque tristique tempus  +augue at convallis.                                                                                                                           +╚══════════╩═══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════╝ +╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ + diff --git a/docs/js/custom.js b/docs/js/custom.js deleted file mode 100644 index a017a1c7..00000000 --- a/docs/js/custom.js +++ /dev/null @@ -1,108 +0,0 @@ -document.querySelectorAll(".use-termynal").forEach((node) => { - node.style.display = "block"; - new Termynal(node, { - lineDelay: 500, - }); -}); -const progressLiteralStart = "---> 100%"; -const promptLiteralStart = "$ "; -const customPromptLiteralStart = "# "; -const termynalActivateClass = "termy"; -let termynals = []; - -function createTermynals() { - document - .querySelectorAll(`.${termynalActivateClass} .highlight`) - .forEach((node) => { - const text = node.textContent; - const lines = text.split("\n"); - const useLines = []; - let buffer = []; - function saveBuffer() { - if (buffer.length) { - let isBlankSpace = true; - buffer.forEach((line) => { - if (line) { - isBlankSpace = false; - } - }); - dataValue = {}; - if (isBlankSpace) { - dataValue["delay"] = 0; - } - if (buffer[buffer.length - 1] === "") { - // A last single
won't have effect - // so put an additional one - buffer.push(""); - } - const bufferValue = buffer.join("
"); - dataValue["value"] = bufferValue; - useLines.push(dataValue); - buffer = []; - } - } - for (let line of lines) { - if (line === progressLiteralStart) { - saveBuffer(); - useLines.push({ - type: "progress", - }); - } else if (line.startsWith(promptLiteralStart)) { - saveBuffer(); - const value = line.replace(promptLiteralStart, "").trimEnd(); - useLines.push({ - type: "input", - value: value, - }); - } else if (line.startsWith("// ")) { - saveBuffer(); - const value = "💬 " + line.replace("// ", "").trimEnd(); - useLines.push({ - value: value, - class: "termynal-comment", - delay: 0, - }); - } else if (line.startsWith(customPromptLiteralStart)) { - saveBuffer(); - const promptStart = line.indexOf(promptLiteralStart); - if (promptStart === -1) { - console.error("Custom prompt found but no end delimiter", line); - } - const prompt = line - .slice(0, promptStart) - .replace(customPromptLiteralStart, ""); - let value = line.slice(promptStart + promptLiteralStart.length); - useLines.push({ - type: "input", - value: value, - prompt: prompt, - }); - } else { - buffer.push(line); - } - } - saveBuffer(); - const div = document.createElement("div"); - node.replaceWith(div); - const termynal = new Termynal(div, { - lineData: useLines, - noInit: true, - typeDelay: 50, - lineDelay: 500 - }); - termynals.push(termynal); - }); -} - -function loadVisibleTermynals() { - termynals = termynals.filter((termynal) => { - if (termynal.container.getBoundingClientRect().top - innerHeight <= 0) { - termynal.init(); - return false; - } - return true; - }); -} -window.addEventListener("scroll", loadVisibleTermynals); -createTermynals(); -loadVisibleTermynals(); diff --git a/docs/js/termynal.js b/docs/js/termynal.js deleted file mode 100644 index 200cc517..00000000 --- a/docs/js/termynal.js +++ /dev/null @@ -1,293 +0,0 @@ -/** - * termynal.js - * A lightweight, modern and extensible animated terminal window, using - * async/await. - * - * @author Ines Montani - * @version 0.0.1 - * @license MIT - */ - -"use strict"; - -/** Generate a terminal widget. */ -class Termynal { - /** - * Construct the widget's settings. - * @param {(string|Node)=} container - Query selector or container element. - * @param {Object=} options - Custom settings. - * @param {string} options.prefix - Prefix to use for data attributes. - * @param {number} options.startDelay - Delay before animation, in ms. - * @param {number} options.typeDelay - Delay between each typed character, in ms. - * @param {number} options.lineDelay - Delay between each line, in ms. - * @param {number} options.progressLength - Number of characters displayed as progress bar. - * @param {string} options.progressChar – Character to use for progress bar, defaults to █. - * @param {number} options.progressPercent - Max percent of progress. - * @param {string} options.cursor – Character to use for cursor, defaults to ▋. - * @param {Object[]} lineData - Dynamically loaded line data objects. - * @param {boolean} options.noInit - Don't initialise the animation. - * @param {boolean} options.static - No animation; just render the text. */ - constructor(container = "#termynal", options = {}) { - this.container = - typeof container === "string" - ? document.querySelector(container) - : container; - this.pfx = `data-${options.prefix || "ty"}`; - this.originalStartDelay = this.startDelay = - options.startDelay || - parseFloat(this.container.getAttribute(`${this.pfx}-startDelay`)) || - 600; - this.originalTypeDelay = this.typeDelay = - options.typeDelay || - parseFloat(this.container.getAttribute(`${this.pfx}-typeDelay`)) || - 90; - this.originalLineDelay = this.lineDelay = - options.lineDelay || - parseFloat(this.container.getAttribute(`${this.pfx}-lineDelay`)) || - 1500; - this.progressLength = - options.progressLength || - parseFloat(this.container.getAttribute(`${this.pfx}-progressLength`)) || - 40; - this.progressChar = - options.progressChar || - this.container.getAttribute(`${this.pfx}-progressChar`) || - "█"; - this.progressPercent = - options.progressPercent || - parseFloat(this.container.getAttribute(`${this.pfx}-progressPercent`)) || - 100; - this.cursor = - options.cursor || - this.container.getAttribute(`${this.pfx}-cursor`) || - "▋"; - this.lineData = this.lineDataToElements(options.lineData || []); - this.static = - options.static || - this.container.hasAttribute(`static`) - || false; - - this.loadLines(); - if (!options.noInit) this.init(); - } - - loadLines() { - // Load all the lines and create the container so that the size is fixed - // Otherwise it would be changing and the user viewport would be constantly - // moving as she/he scrolls - const finish = this.generateFinish(); - finish.style.visibility = "hidden"; - this.container.appendChild(finish); - // Appends dynamically loaded lines to existing line elements. - this.lines = [...this.container.querySelectorAll(`[${this.pfx}]`)].concat( - this.lineData, - ); - for (let line of this.lines) { - line.style.visibility = "hidden"; - this.container.appendChild(line); - } - const restart = this.generateRestart(); - restart.style.visibility = "hidden"; - this.container.appendChild(restart); - this.container.setAttribute("data-termynal", ""); - } - - /** - * Initialise the widget, get lines, clear container and start animation. - */ - init() { - /** - * Calculates width and height of Termynal container. - * If container is empty and lines are dynamically loaded, defaults to browser `auto` or CSS. - */ - const containerStyle = getComputedStyle(this.container); - this.container.style.width = - containerStyle.width !== "0px" ? containerStyle.width : undefined; - this.container.style.minHeight = - containerStyle.height !== "0px" ? containerStyle.height : undefined; - - this.container.setAttribute("data-termynal", ""); - this.container.innerHTML = ""; - for (let line of this.lines) { - line.style.visibility = "visible"; - } - this.start(); - } - - /** - * Start the animation and rener the lines depending on their data attributes. - */ - async start() { - if (!this.static) { - this.addFinish(); - } - await this._wait(this.startDelay); - - for (let line of this.lines) { - const type = line.getAttribute(this.pfx); - const delay = line.getAttribute(`${this.pfx}-delay`) || this.lineDelay; - - if (type === "input") { - line.setAttribute(`${this.pfx}-cursor`, this.cursor); - await this.type(line); - await this._wait(delay); - } else if (type === "progress") { - await this.progress(line); - await this._wait(delay); - } else { - this.container.appendChild(line); - await this._wait(delay); - } - - line.removeAttribute(`${this.pfx}-cursor`); - } - if (!this.static) { - this.addRestart(); - } - this.finishElement.style.visibility = "hidden"; - this.lineDelay = this.originalLineDelay; - this.typeDelay = this.originalTypeDelay; - this.startDelay = this.originalStartDelay; - } - - generateRestart() { - const restart = document.createElement("a"); - restart.onclick = (e) => { - e.preventDefault(); - this.container.innerHTML = ""; - this.init(); - }; - restart.href = "#"; - restart.setAttribute("data-terminal-control", ""); - restart.innerHTML = "restart ↻"; - return restart; - } - - generateFinish() { - const finish = document.createElement("a"); - finish.onclick = (e) => { - e.preventDefault(); - this.lineDelay = 0; - this.typeDelay = 0; - this.startDelay = 0; - }; - finish.href = "#"; - finish.setAttribute("data-terminal-control", ""); - finish.innerHTML = "fast →"; - this.finishElement = finish; - return finish; - } - - addRestart() { - const restart = this.generateRestart(); - this.container.appendChild(restart); - } - - addFinish() { - const finish = this.generateFinish(); - this.container.appendChild(finish); - } - - /** - * Animate a typed line. - * @param {Node} line - The line element to render. - */ - async type(line) { - const chars = [...line.textContent]; - line.textContent = ""; - this.container.appendChild(line); - - for (let char of chars) { - const delay = - line.getAttribute(`${this.pfx}-typeDelay`) || this.typeDelay; - await this._wait(delay); - line.textContent += char; - } - } - - /** - * Animate a progress bar. - * @param {Node} line - The line element to render. - */ - async progress(line) { - const progressLength = - line.getAttribute(`${this.pfx}-progressLength`) || this.progressLength; - const progressChar = - line.getAttribute(`${this.pfx}-progressChar`) || this.progressChar; - const chars = progressChar.repeat(progressLength); - const progressPercent = - line.getAttribute(`${this.pfx}-progressPercent`) || this.progressPercent; - line.textContent = ""; - this.container.appendChild(line); - - for (let i = 1; i < chars.length + 1; i++) { - await this._wait(this.typeDelay); - const percent = Math.round((i / chars.length) * 100); - line.textContent = `${chars.slice(0, i)} ${percent}%`; - if (percent > progressPercent) { - break; - } - } - } - - /** - * Helper function for animation delays, called with `await`. - * @param {number} time - Timeout, in ms. - */ - _wait(time) { - return new Promise((resolve) => setTimeout(resolve, time)); - } - - /** - * Converts line data objects into line elements. - * - * @param {Object[]} lineData - Dynamically loaded lines. - * @param {Object} line - Line data object. - * @returns {Element[]} - Array of line elements. - */ - lineDataToElements(lineData) { - return lineData.map((line) => { - let div = document.createElement("div"); - div.innerHTML = `${ - line.value || "" - }`; - - return div.firstElementChild; - }); - } - - /** - * Helper function for generating attributes string. - * - * @param {Object} line - Line data object. - * @returns {string} - String of attributes. - */ - _attributes(line) { - let attrs = ""; - for (let prop in line) { - // Custom add class - if (prop === "class") { - attrs += ` class=${line[prop]} `; - continue; - } - if (prop === "type") { - attrs += `${this.pfx}="${line[prop]}" `; - } else if (prop !== "value") { - attrs += `${this.pfx}-${prop}="${line[prop]}" `; - } - } - - return attrs; - } -} - -/** - * HTML API: If current script has container(s) specified, initialise Termynal. - */ -if (document.currentScript.hasAttribute("data-termynal-container")) { - const containers = document.currentScript.getAttribute( - "data-termynal-container", - ); - containers.split("|") - .forEach((container) => new Termynal(container, {static: true})); -} diff --git a/docs/overrides/editor.html b/docs/overrides/editor.html index fbe8dfd4..0bd30ac1 100644 --- a/docs/overrides/editor.html +++ b/docs/overrides/editor.html @@ -1,8 +1,8 @@ {% extends 'base.html' %} -{% set COLORS = ["black", "blue", "green", "yellow", "cyan", "white", "magenta", "red"] %} +{% set COLORS = ["black", "red", "green", "yellow", "blue", "magenta", "cyan", "white"] %} {% set DEFAULT_STYLE_DICT = { - "style_argument": { + "style_option": { "color": "cyan", "bold": true, "dim": false, @@ -104,25 +104,25 @@ {% endblock %} {% set live_terminal %} - Usage: docs [OPTIONS] FOO COMMAND [ARGS]... + Usage: docs [OPTIONS] FOO COMMAND [ARGS]... Help text for CLI - Second line of help text. + Second line of help text. -╭─ Options ────────────────────────────────────────────────────────────╮ - --bar -b TEXT Lorem ipsum [default: (someval)] - * --baz [a|b|c] Choose wisely [required] - --help Show this message and exit. -╰──────────────────────────────────────────────────────────────────────╯ -╭─ Commands ───────────────────────────────────────────────────────────╮ - subcommand Help text for subcommand -╰──────────────────────────────────────────────────────────────────────╯ +╭─ Options ────────────────────────────────────────────────────────────╮ + --bar -b TEXT Lorem ipsum [default: (someval)] + * --baz [a|b|c] Choose wisely [required] + --help Show this message and exit. +╰──────────────────────────────────────────────────────────────────────╯ +╭─ Commands ───────────────────────────────────────────────────────────╮ + subcommand Help text for subcommand +╰──────────────────────────────────────────────────────────────────────╯ {% endset %} {% block content %}

Live Style Editor

-

This page contains a live editor for `rich-click` styles.

+

This page contains a live editor for rich-click styles.

At the bottom of the page, there is generated code for the sample output.

@@ -133,22 +133,24 @@

Live Style Editor

- - - + + + + + {% for option_name, attrs in DEFAULT_STYLE_DICT.items() %} {% set css_cls = "rccfg-" ~ option_name.replace("_", "-") %}
- Option - - Color - - Other styles -
+ Option + + Color + + Other styles +
- +
@@ -172,10 +174,10 @@

Live Style Editor

-
-
+        
+
 {%- for row in live_terminal.split("\n") %}
-{{ row | escape }}
+{{ row }}
 {%- endfor %}
         
@@ -257,8 +259,7 @@

Live Style Editor

{% endblock %} diff --git a/mkdocs.yml b/mkdocs.yml index f5baf53d..22158007 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -86,6 +86,3 @@ extra_css: - css/termynal.css - css/extra.css -extra_javascript: - - js/termynal.js - - js/custom.js diff --git a/pyproject.toml b/pyproject.toml index 0ee9182f..2043fa28 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -36,6 +36,7 @@ dev = [ "pre-commit", "pytest", "pytest-cov", + "rich-codex", "ruff", "types-setuptools", ] @@ -43,9 +44,10 @@ docs = [ "markdown_include", "mkdocs", "mkdocs-glightbox", - "mkdocs-material", + "mkdocs-material[imaging]~=9.5.18", "mkdocs-material-extensions", "mkdocstrings[python]", + "rich-codex", ] [project.urls] Documentation = "https://github.com/ewels/rich-click" diff --git a/src/rich_click/patch.py b/src/rich_click/patch.py index 8f95457b..3cca423d 100644 --- a/src/rich_click/patch.py +++ b/src/rich_click/patch.py @@ -40,7 +40,7 @@ def rich_group(*args, **kwargs): # type: ignore[no-untyped-def] def patch(rich_config: Optional[RichHelpConfiguration] = None) -> None: - """Patch Click internals to use Rich-Click types.""" + """Patch Click internals to use rich-click types.""" rich_click.rich_command.OVERRIDES_GUARD = True click.group = rich_group click.command = rich_command