diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index a37907a..d5a0b69 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -26,7 +26,7 @@ jobs: ${{ runner.os }}-pip- - name: Install dependencies run: | - pip install -e '.[test]' + pip install -e '.[test,tui]' - name: Run tests run: | pytest diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 2e706df..ab30b2d 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -28,7 +28,7 @@ jobs: ${{ runner.os }}-pip- - name: Install dependencies run: | - pip install -e '.[test,mypy,flake8]' + pip install -e '.[test,mypy,flake8,tui]' - name: Optionally install numpy if: matrix.numpy == 1 run: pip install numpy @@ -44,7 +44,8 @@ jobs: pytest -v - name: run mypy run: mypy sqlite_utils tests - - name: run flake8 + - name: run flake8 if Python 3.8 or higher + if: matrix.python-version >= 3.8 run: flake8 - name: Check formatting run: black . --check diff --git a/docs/_static/img/tui.png b/docs/_static/img/tui.png new file mode 100644 index 0000000..04cbeb1 Binary files /dev/null and b/docs/_static/img/tui.png differ diff --git a/docs/cli-reference.rst b/docs/cli-reference.rst index c108138..e38d08d 100644 --- a/docs/cli-reference.rst +++ b/docs/cli-reference.rst @@ -61,6 +61,7 @@ This page lists the ``--help`` for every ``sqlite-utils`` CLI sub-command. "create-spatial-index": "cli_spatialite_indexes", "install": "cli_install", "uninstall": "cli_uninstall", + "tui": "cli_tui", } commands.sort(key = lambda command: go_first.index(command) if command in go_first else 999) cog.out("\n") @@ -1025,6 +1026,23 @@ disable-fts -h, --help Show this message and exit. +.. _cli_ref_tui: + +tui +=== + +See :ref:`cli_tui`. + +:: + + Usage: sqlite-utils tui [OPTIONS] + + Open Textual TUI. + + Options: + -h, --help Show this message and exit. + + .. _cli_ref_optimize: optimize diff --git a/docs/cli.rst b/docs/cli.rst index d567cba..3b9ac31 100644 --- a/docs/cli.rst +++ b/docs/cli.rst @@ -2163,3 +2163,25 @@ You can uninstall packages that were installed using ``sqlite-utils install`` wi $ sqlite-utils uninstall beautifulsoup4 Use ``-y`` to skip the request for confirmation. + +.. _cli_tui: + +Experimental TUI +================ + +A TUI is a "text user interface" (or "terminal user interface") - a keyboard and mouse driven graphical interface running in your terminal. + +``sqlite-utils`` has experimental support for a TUI for building command-line invocations, built on top of the `Trogon `__ TUI library. + +To enable this feature you will need to install the ``trogon`` dependency. You can do that like so:: + + sqite-utils install trogon + +Once installed, running the ``sqlite-utils tui`` command will launch the TUI interface:: + + sqlite-utils tui + +You can then construct a command by selecting options from the menus, and execute it using ``Ctrl+R``. + +.. image:: _static/img/tui.png + :alt: A TUI interface for sqlite-utils - the left column shows a list of commands, while the right panel has a form for constructing arguments to the add-column command. diff --git a/setup.py b/setup.py index 3964b3a..5898ffa 100644 --- a/setup.py +++ b/setup.py @@ -47,6 +47,7 @@ setup( "data-science-types", ], "flake8": ["flake8"], + "tui": ["trogon"], }, entry_points=""" [console_scripts] diff --git a/sqlite_utils/cli.py b/sqlite_utils/cli.py index 5a88bd5..ab9c524 100644 --- a/sqlite_utils/cli.py +++ b/sqlite_utils/cli.py @@ -33,6 +33,11 @@ from .utils import ( TypeTracker, ) +try: + import trogon # type: ignore +except ImportError: + trogon = None + CONTEXT_SETTINGS = dict(help_option_names=["-h", "--help"]) @@ -112,6 +117,10 @@ def cli(): pass +if trogon is not None: + cli = trogon.tui()(cli) + + @cli.command() @click.argument( "path", diff --git a/tests/test_docs.py b/tests/test_docs.py index 7f2e3ed..c305c7a 100644 --- a/tests/test_docs.py +++ b/tests/test_docs.py @@ -5,7 +5,7 @@ import pytest import re docs_path = Path(__file__).parent.parent / "docs" -commands_re = re.compile(r"(?:\$ | )sqlite-utils (\S+) ") +commands_re = re.compile(r"(?:\$ | )sqlite-utils (\S+)") recipes_re = re.compile(r"r\.(\w+)\(")