mycli 2.27.0__tar.gz → 2.28.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {mycli-2.27.0 → mycli-2.28.0}/.github/workflows/ci.yml +7 -7
- {mycli-2.27.0 → mycli-2.28.0}/.github/workflows/publish.yml +17 -11
- {mycli-2.27.0 → mycli-2.28.0}/.github/workflows/typecheck.yml +1 -1
- {mycli-2.27.0 → mycli-2.28.0}/AGENTS.md +7 -0
- {mycli-2.27.0/mycli.egg-info → mycli-2.28.0}/PKG-INFO +1 -2
- {mycli-2.27.0 → mycli-2.28.0}/changelog.md +33 -0
- mycli-2.28.0/doc/cookbook.md +71 -0
- mycli-2.28.0/doc/known_bugs.md +61 -0
- {mycli-2.27.0 → mycli-2.28.0}/docker/resources/test_db-1.0.7.tar.gz +1 -1
- {mycli-2.27.0 → mycli-2.28.0}/mycli/constants.py +1 -0
- {mycli-2.27.0 → mycli-2.28.0}/mycli/key_bindings.py +3 -3
- {mycli-2.27.0 → mycli-2.28.0}/mycli/main_modes/checkup.py +3 -3
- {mycli-2.27.0 → mycli-2.28.0}/mycli/main_modes/repl.py +30 -23
- {mycli-2.27.0 → mycli-2.28.0}/mycli/output.py +5 -1
- mycli-2.28.0/mycli/packages/fzf.py +78 -0
- mycli-2.27.0/mycli/packages/ptoolkit/fzf.py → mycli-2.28.0/mycli/packages/ptoolkit/fzf_history.py +5 -15
- {mycli-2.27.0 → mycli-2.28.0}/mycli/packages/special/__init__.py +0 -8
- {mycli-2.27.0 → mycli-2.28.0}/mycli/packages/special/iocommands.py +4 -4
- {mycli-2.27.0 → mycli-2.28.0}/mycli/packages/sqlresult.py +9 -1
- {mycli-2.27.0 → mycli-2.28.0}/mycli/query_runner.py +27 -12
- {mycli-2.27.0 → mycli-2.28.0}/mycli/sqlexecute.py +15 -7
- {mycli-2.27.0 → mycli-2.28.0/mycli.egg-info}/PKG-INFO +1 -2
- {mycli-2.27.0 → mycli-2.28.0}/mycli.egg-info/SOURCES.txt +6 -2
- {mycli-2.27.0 → mycli-2.28.0}/mycli.egg-info/requires.txt +0 -1
- {mycli-2.27.0 → mycli-2.28.0}/mycli.egg-info/scm_file_list.json +6 -2
- mycli-2.28.0/mycli.egg-info/scm_version.json +8 -0
- {mycli-2.27.0 → mycli-2.28.0}/pyproject.toml +6 -3
- {mycli-2.27.0 → mycli-2.28.0}/test/features/basic_commands.feature +2 -2
- {mycli-2.27.0 → mycli-2.28.0}/test/features/iocommands.feature +3 -3
- {mycli-2.27.0 → mycli-2.28.0}/test/features/steps/basic_commands.py +4 -4
- {mycli-2.27.0 → mycli-2.28.0}/test/features/steps/iocommands.py +1 -1
- {mycli-2.27.0 → mycli-2.28.0}/test/features/steps/named_queries.py +17 -17
- {mycli-2.27.0 → mycli-2.28.0}/test/pytests/test_checkup.py +2 -2
- {mycli-2.27.0 → mycli-2.28.0}/test/pytests/test_client_commands.py +1 -1
- {mycli-2.27.0 → mycli-2.28.0}/test/pytests/test_completion_engine.py +39 -23
- mycli-2.28.0/test/pytests/test_fzf.py +126 -0
- {mycli-2.27.0 → mycli-2.28.0}/test/pytests/test_hybrid_redirection.py +1 -1
- {mycli-2.27.0 → mycli-2.28.0}/test/pytests/test_key_bindings.py +2 -2
- {mycli-2.27.0 → mycli-2.28.0}/test/pytests/test_main.py +6 -6
- {mycli-2.27.0 → mycli-2.28.0}/test/pytests/test_main_modes_repl.py +144 -11
- {mycli-2.27.0 → mycli-2.28.0}/test/pytests/test_output.py +83 -1
- mycli-2.27.0/test/pytests/test_ptoolkit_fzf.py → mycli-2.28.0/test/pytests/test_ptoolkit_fzf_history.py +35 -37
- {mycli-2.27.0 → mycli-2.28.0}/test/pytests/test_query_runner.py +131 -3
- {mycli-2.27.0 → mycli-2.28.0}/test/pytests/test_smart_completion_public_schema_only.py +19 -18
- {mycli-2.27.0 → mycli-2.28.0}/test/pytests/test_special_dbcommands.py +6 -6
- {mycli-2.27.0 → mycli-2.28.0}/test/pytests/test_special_init.py +1 -1
- {mycli-2.27.0 → mycli-2.28.0}/test/pytests/test_special_iocommands.py +27 -27
- {mycli-2.27.0 → mycli-2.28.0}/test/pytests/test_special_llm.py +20 -20
- {mycli-2.27.0 → mycli-2.28.0}/test/pytests/test_special_main.py +12 -12
- {mycli-2.27.0 → mycli-2.28.0}/test/pytests/test_sql_utils.py +8 -8
- {mycli-2.27.0 → mycli-2.28.0}/test/pytests/test_sqlexecute.py +39 -1
- {mycli-2.27.0 → mycli-2.28.0}/test/pytests/test_sqlresult.py +24 -0
- {mycli-2.27.0 → mycli-2.28.0}/test/utils.py +12 -0
- mycli-2.27.0/mycli.egg-info/scm_version.json +0 -8
- {mycli-2.27.0 → mycli-2.28.0}/.git-blame-ignore-revs +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/.github/dependabot.yml +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/.github/workflows/lint.yml +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/.gitignore +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/AUTHORS.md +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/CONTRIBUTING.md +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/LICENSE.txt +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/MANIFEST.in +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/README.md +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/SPONSORS.md +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/doc/key_bindings.md +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/doc/llm.md +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/doc/screenshots/main.gif +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/doc/screenshots/polars_describe.png +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/doc/screenshots/polars_group_by.png +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/doc/screenshots/polars_histogram.png +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/doc/screenshots/polars_pivot.png +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/doc/screenshots/tables.png +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/doc/transforms.md +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/docker/Dockerfile +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/docker/resources/test_db_license.md +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/mycli/AUTHORS +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/mycli/SPONSORS +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/mycli/TIPS +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/mycli/__init__.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/mycli/app_state.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/mycli/boundary_tunnel.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/mycli/cli_runner.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/mycli/clibuffer.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/mycli/client.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/mycli/client_commands.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/mycli/client_connection.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/mycli/client_query.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/mycli/clistyle.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/mycli/clitoolbar.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/mycli/compat.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/mycli/completion_refresher.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/mycli/config.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/mycli/keyring_utils.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/mycli/kubectl_tunnel.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/mycli/lexer.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/mycli/macos_keychain.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/mycli/main.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/mycli/main_modes/batch.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/mycli/main_modes/completions.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/mycli/main_modes/execute.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/mycli/main_modes/list_dsn.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/mycli/myclirc +0 -0
- {mycli-2.27.0/test/features/steps → mycli-2.28.0/mycli/packages}/__init__.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/mycli/packages/batch_utils.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/mycli/packages/cli_utils.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/mycli/packages/completion_engine.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/mycli/packages/filepaths.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/mycli/packages/hybrid_redirection.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/mycli/packages/interactive_utils.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/mycli/packages/key_binding_utils.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/mycli/packages/polars_completion.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/mycli/packages/polars_transform.py +0 -0
- {mycli-2.27.0/test/features → mycli-2.28.0/mycli/packages/ptoolkit}/__init__.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/mycli/packages/ptoolkit/history.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/mycli/packages/ptoolkit/utils.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/mycli/packages/special/dbcommands.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/mycli/packages/special/delimitercommand.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/mycli/packages/special/dsn_aliases.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/mycli/packages/special/favoritequeries.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/mycli/packages/special/llm.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/mycli/packages/special/main.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/mycli/packages/special/source.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/mycli/packages/special/utils.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/mycli/packages/sql_utils.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/mycli/packages/string_utils.py +0 -0
- {mycli-2.27.0/test → mycli-2.28.0/mycli/packages/tabular_output}/__init__.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/mycli/packages/tabular_output/sql_format.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/mycli/password_sources.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/mycli/resources/completions/bash/mycli +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/mycli/resources/completions/fish/mycli.fish +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/mycli/resources/completions/zsh/_mycli +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/mycli/schema_prefetcher.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/mycli/sqlcompleter.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/mycli/ssh_tunnel.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/mycli/types.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/mycli/vault.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/mycli.egg-info/dependency_links.txt +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/mycli.egg-info/entry_points.txt +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/mycli.egg-info/top_level.txt +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/setup.cfg +0 -0
- {mycli-2.27.0/mycli/packages/tabular_output → mycli-2.28.0/test}/__init__.py +0 -0
- {mycli-2.27.0/mycli/packages/ptoolkit → mycli-2.28.0/test/features}/__init__.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/test/features/auto_vertical.feature +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/test/features/connection.feature +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/test/features/crud_database.feature +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/test/features/crud_table.feature +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/test/features/db_utils.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/test/features/environment.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/test/features/fixture_data/help_commands.txt +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/test/features/fixture_utils.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/test/features/named_queries.feature +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/test/features/specials.feature +0 -0
- {mycli-2.27.0/mycli/packages → mycli-2.28.0/test/features/steps}/__init__.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/test/features/steps/auto_vertical.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/test/features/steps/connection.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/test/features/steps/crud_database.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/test/features/steps/crud_table.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/test/features/steps/specials.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/test/features/steps/utils.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/test/features/steps/wrappers.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/test/features/wrappager.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/test/myclirc +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/test/mylogin.cnf +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/test/pytests/conftest.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/test/pytests/test_app_state.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/test/pytests/test_bash_completion.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/test/pytests/test_batch_utils.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/test/pytests/test_boundary_tunnel.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/test/pytests/test_cli_runner.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/test/pytests/test_cli_utils.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/test/pytests/test_clibuffer.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/test/pytests/test_client.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/test/pytests/test_client_connection.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/test/pytests/test_client_query.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/test/pytests/test_clistyle.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/test/pytests/test_clitoolbar.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/test/pytests/test_completer_use_switch.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/test/pytests/test_completion_refresher.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/test/pytests/test_config.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/test/pytests/test_delimitercommand.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/test/pytests/test_dsn_aliases.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/test/pytests/test_favoritequeries.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/test/pytests/test_filepaths.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/test/pytests/test_fish_completion.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/test/pytests/test_interactive_utils.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/test/pytests/test_key_binding_utils.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/test/pytests/test_keyring_utils.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/test/pytests/test_kubectl_tunnel.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/test/pytests/test_macos_keychain.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/test/pytests/test_main_modes_batch.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/test/pytests/test_main_modes_execute.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/test/pytests/test_main_modes_list_dsn.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/test/pytests/test_naive_completion.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/test/pytests/test_password_sources.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/test/pytests/test_polars_completion.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/test/pytests/test_polars_transform.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/test/pytests/test_ptoolkit_history.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/test/pytests/test_ptoolkit_utils.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/test/pytests/test_schema_prefetcher.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/test/pytests/test_special_source.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/test/pytests/test_special_utils.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/test/pytests/test_sqlcompleter.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/test/pytests/test_ssh_tunnel.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/test/pytests/test_string_utils.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/test/pytests/test_tabular_output.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/test/pytests/test_vault.py +0 -0
- {mycli-2.27.0 → mycli-2.28.0}/test/pytests/test_zsh_completion.py +0 -0
|
@@ -38,7 +38,7 @@ jobs:
|
|
|
38
38
|
sudo /etc/init.d/mysql start
|
|
39
39
|
|
|
40
40
|
- name: Install dependencies
|
|
41
|
-
run: uv sync --
|
|
41
|
+
run: uv sync --extra dev,llm,dataframe -p ${{ matrix.python-version }}
|
|
42
42
|
|
|
43
43
|
- name: Wait for MySQL connection
|
|
44
44
|
run: |
|
|
@@ -52,7 +52,7 @@ jobs:
|
|
|
52
52
|
PYTEST_HOST: 127.0.0.1
|
|
53
53
|
TERM: xterm
|
|
54
54
|
run: |
|
|
55
|
-
|
|
55
|
+
./.venv/bin/tox -e py${{ matrix.python-version }}
|
|
56
56
|
|
|
57
57
|
tests-macos:
|
|
58
58
|
name: Tests macOS
|
|
@@ -84,7 +84,7 @@ jobs:
|
|
|
84
84
|
brew services start mysql
|
|
85
85
|
|
|
86
86
|
- name: Install dependencies
|
|
87
|
-
run: uv sync --
|
|
87
|
+
run: uv sync --extra dev,llm,dataframe -p ${{ matrix.python-version }}
|
|
88
88
|
|
|
89
89
|
- name: Wait for MySQL connection
|
|
90
90
|
run: |
|
|
@@ -102,7 +102,7 @@ jobs:
|
|
|
102
102
|
PYTEST_HOST: 127.0.0.1
|
|
103
103
|
TERM: xterm
|
|
104
104
|
run: |
|
|
105
|
-
|
|
105
|
+
./.venv/bin/tox -e py${{ matrix.python-version }}
|
|
106
106
|
|
|
107
107
|
tests-windows:
|
|
108
108
|
name: Tests Windows
|
|
@@ -127,7 +127,7 @@ jobs:
|
|
|
127
127
|
|
|
128
128
|
- name: Install dependencies
|
|
129
129
|
shell: cmd
|
|
130
|
-
run: uv sync --
|
|
130
|
+
run: uv sync --extra dev,llm,dataframe -p ${{ matrix.python-version }}
|
|
131
131
|
|
|
132
132
|
- name: Set up MySQL
|
|
133
133
|
uses: shogo82148/actions-setup-mysql@083ec148d28e62f2b24b8f4541693dfe1d50488d # v1.54.0
|
|
@@ -182,7 +182,7 @@ jobs:
|
|
|
182
182
|
run: |
|
|
183
183
|
export PATH="$HOME/.local/bin:$PATH"
|
|
184
184
|
cd /root/mycli
|
|
185
|
-
uv sync --
|
|
185
|
+
uv sync --extra dev,llm,dataframe --python 3.14
|
|
186
186
|
|
|
187
187
|
- name: Start MySQL in WSL
|
|
188
188
|
shell: wsl-bash {0}
|
|
@@ -248,7 +248,7 @@ jobs:
|
|
|
248
248
|
PYTEST_HOST: 127.0.0.1
|
|
249
249
|
TERM: xterm
|
|
250
250
|
run: |
|
|
251
|
-
|
|
251
|
+
./.venv/bin/tox -e py3.14
|
|
252
252
|
|
|
253
253
|
docker-x86-build:
|
|
254
254
|
name: Build x86 Docker Image
|
|
@@ -46,7 +46,7 @@ jobs:
|
|
|
46
46
|
sudo /etc/init.d/mysql start
|
|
47
47
|
|
|
48
48
|
- name: Install dependencies
|
|
49
|
-
run: uv sync --
|
|
49
|
+
run: uv sync --extra dev,llm,dataframe -p ${{ matrix.python-version }}
|
|
50
50
|
|
|
51
51
|
- name: Wait for MySQL connection
|
|
52
52
|
run: |
|
|
@@ -54,16 +54,22 @@ jobs:
|
|
|
54
54
|
sleep 5
|
|
55
55
|
done
|
|
56
56
|
|
|
57
|
+
# arguably this should be made identical to CI for PRs
|
|
58
|
+
# better would be a composite GH action
|
|
59
|
+
- name: Run Style Checks
|
|
60
|
+
run: ./.venv/bin/tox -e style
|
|
61
|
+
|
|
62
|
+
# arguably this should be made identical to CI for PRs
|
|
63
|
+
# better would be a composite GH action
|
|
64
|
+
- name: Run Typechecker
|
|
65
|
+
run: ./.venv/bin/tox -e typecheck
|
|
66
|
+
|
|
57
67
|
- name: Pytest / behave
|
|
58
68
|
env:
|
|
59
69
|
PYTEST_PASSWORD: root
|
|
60
70
|
PYTEST_HOST: 127.0.0.1
|
|
61
71
|
run: |
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
# arguably this should be made identical to CI for PRs
|
|
65
|
-
- name: Run Style Checks
|
|
66
|
-
run: uv run tox -e style
|
|
72
|
+
./.venv/bin/tox -e py${{ matrix.python-version }}
|
|
67
73
|
|
|
68
74
|
tests-macos:
|
|
69
75
|
name: Tests macOS
|
|
@@ -95,7 +101,7 @@ jobs:
|
|
|
95
101
|
brew services start mysql
|
|
96
102
|
|
|
97
103
|
- name: Install dependencies
|
|
98
|
-
run: uv sync --
|
|
104
|
+
run: uv sync --extra dev,llm,dataframe -p ${{ matrix.python-version }}
|
|
99
105
|
|
|
100
106
|
- name: Wait for MySQL connection
|
|
101
107
|
run: |
|
|
@@ -113,7 +119,7 @@ jobs:
|
|
|
113
119
|
PYTEST_HOST: 127.0.0.1
|
|
114
120
|
TERM: xterm
|
|
115
121
|
run: |
|
|
116
|
-
|
|
122
|
+
./.venv/bin/tox -e py${{ matrix.python-version }}
|
|
117
123
|
|
|
118
124
|
tests-windows:
|
|
119
125
|
name: Tests Windows
|
|
@@ -138,7 +144,7 @@ jobs:
|
|
|
138
144
|
|
|
139
145
|
- name: Install dependencies
|
|
140
146
|
shell: cmd
|
|
141
|
-
run: uv sync --
|
|
147
|
+
run: uv sync --extra dev,llm,dataframe -p ${{ matrix.python-version }}
|
|
142
148
|
|
|
143
149
|
- name: Set up MySQL
|
|
144
150
|
uses: shogo82148/actions-setup-mysql@083ec148d28e62f2b24b8f4541693dfe1d50488d # v1.54.0
|
|
@@ -193,7 +199,7 @@ jobs:
|
|
|
193
199
|
run: |
|
|
194
200
|
export PATH="$HOME/.local/bin:$PATH"
|
|
195
201
|
cd /root/mycli
|
|
196
|
-
uv sync --
|
|
202
|
+
uv sync --extra dev,llm,dataframe --python 3.14
|
|
197
203
|
|
|
198
204
|
- name: Start MySQL in WSL
|
|
199
205
|
shell: wsl-bash {0}
|
|
@@ -240,7 +246,7 @@ jobs:
|
|
|
240
246
|
python-version: '3.14'
|
|
241
247
|
|
|
242
248
|
- name: Install dependencies
|
|
243
|
-
run: uv sync --
|
|
249
|
+
run: uv sync --extra llm,dataframe -p 3.14
|
|
244
250
|
|
|
245
251
|
- name: Build
|
|
246
252
|
run: uv build
|
|
@@ -8,6 +8,12 @@ A command line client for MySQL with auto-completion and syntax highlighting.
|
|
|
8
8
|
├── .github/ # GitHub Actions and configuration
|
|
9
9
|
├── pyproject.toml # project configuration
|
|
10
10
|
├── doc/ # documentation
|
|
11
|
+
├── doc/cookbook.md # recipes for how to configure and use mycli
|
|
12
|
+
├── doc/key_bindings.md # documentation of key binding behaviors
|
|
13
|
+
├── doc/known_bugs.md # documentation of known bugs and limitations
|
|
14
|
+
├── doc/llm.md # documentation on how to use LLM features
|
|
15
|
+
├── doc/transforms.md # documentation on how to use dataframe transform/plot features
|
|
16
|
+
├── doc/screenshots/ # screenshots for documentation
|
|
11
17
|
├── mycli/ # application source
|
|
12
18
|
├── mycli/__init__.py # provides version number
|
|
13
19
|
├── mycli/app_state.py # `AppStateMixin` application state mixin and related functions
|
|
@@ -44,6 +50,7 @@ A command line client for MySQL with auto-completion and syntax highlighting.
|
|
|
44
50
|
├── mycli/packages/cli_utils.py # utilities for parsing CLI arguments
|
|
45
51
|
├── mycli/packages/completion_engine.py # implementation of completion suggestions
|
|
46
52
|
├── mycli/packages/filepaths.py # utilities for files, including completion suggestions
|
|
53
|
+
├── mycli/packages/fzf.py # general interface to fzf chooser
|
|
47
54
|
├── mycli/packages/hybrid_redirection.py # implementation of shell-style redirects
|
|
48
55
|
├── mycli/packages/interactive_utils.py # utilities for confirming on destructive statements
|
|
49
56
|
├── mycli/packages/key_binding_utils.py # handlers for key bindings and related special commands
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mycli
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.28.0
|
|
4
4
|
Summary: Rich MySQL terminal client with autocompletion, syntax highlighting, and dataframes
|
|
5
5
|
Author: Mycli Core Team
|
|
6
6
|
License-Expression: BSD-3-Clause
|
|
@@ -41,7 +41,6 @@ Requires-Dist: cli_helpers[styles]~=2.15.1
|
|
|
41
41
|
Requires-Dist: wcwidth~=0.8.3
|
|
42
42
|
Requires-Dist: pyperclip~=1.11.0
|
|
43
43
|
Requires-Dist: pycryptodomex~=3.23.0
|
|
44
|
-
Requires-Dist: pyfzf~=0.3.1
|
|
45
44
|
Requires-Dist: rapidfuzz~=3.14.5
|
|
46
45
|
Requires-Dist: keyring~=25.7.0
|
|
47
46
|
Requires-Dist: jinja2~=3.1.6
|
|
@@ -1,3 +1,36 @@
|
|
|
1
|
+
v2.28.0 (2026/10/02)
|
|
2
|
+
==============
|
|
3
|
+
|
|
4
|
+
Features
|
|
5
|
+
--------
|
|
6
|
+
* Add "streaming" query state when `--unbuffered` is in effect.
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
Bug Fixes
|
|
10
|
+
--------
|
|
11
|
+
* Correct row counts when `--unbuffered` is in effect.
|
|
12
|
+
* Don't let `--unbuffered` override the state-update interval.
|
|
13
|
+
* Fix a brief blankout of query state feedback on large results.
|
|
14
|
+
* Note that `sqlglotc` is optional for performance in `--checkup`.
|
|
15
|
+
* Make imports less lazy, to load special commands under Python 3.15.
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
Documentation
|
|
19
|
+
--------
|
|
20
|
+
* Add `doc/known_bugs.md` for known bugs and limitations.
|
|
21
|
+
* Add `doc/cookbook.md` for recipes on how to use mycli.
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
Internal
|
|
25
|
+
--------
|
|
26
|
+
* Replace `pyfzf` dependency with internal implementation.
|
|
27
|
+
* Use the `uv` outside of the `tox` environment when testing.
|
|
28
|
+
* Use forward-slash forms of special commands in the behave test suite.
|
|
29
|
+
* Use forward-slash forms of special commands in the pytest test suite.
|
|
30
|
+
* Add a `tox` typecheck command.
|
|
31
|
+
* Add a typecheck step to the `publish.yml` workflow.
|
|
32
|
+
|
|
33
|
+
|
|
1
34
|
v2.27.0 (2026/09/29)
|
|
2
35
|
==============
|
|
3
36
|
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# Cookbook
|
|
2
|
+
|
|
3
|
+
Recipes for configuring and using mycli.
|
|
4
|
+
|
|
5
|
+
## faster table rendering
|
|
6
|
+
|
|
7
|
+
A substantial amount of time is spent rendering tables in `tabulate` when
|
|
8
|
+
the number of rows returned is say 100K or more. The reason is that
|
|
9
|
+
`tabulate` scans every row in pure Python to determine cell width.
|
|
10
|
+
|
|
11
|
+
One workaround for faster viewing of large results is to configure the output
|
|
12
|
+
format to CSV in `~/.myclirc`:
|
|
13
|
+
|
|
14
|
+
```ini
|
|
15
|
+
[main]
|
|
16
|
+
table_format = csv
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
and to configure the pager to a fast CSV viewer such as [csvlens](https://github.com/ys-l/csvlens):
|
|
20
|
+
|
|
21
|
+
```ini
|
|
22
|
+
[main]
|
|
23
|
+
pager = csvlens
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
which has the effect of moving cell-width calculations from Python to Rust.
|
|
27
|
+
|
|
28
|
+
## keyring
|
|
29
|
+
|
|
30
|
+
Use of the system keyring was left disabled in the default `~/.myclirc` to avoid
|
|
31
|
+
silently changing default behaviors. But it is recommended to enable it!
|
|
32
|
+
|
|
33
|
+
```ini
|
|
34
|
+
[main]
|
|
35
|
+
use_keyring = auto
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Sources eligible for the keyring can also be configured with
|
|
39
|
+
|
|
40
|
+
```ini
|
|
41
|
+
[main]
|
|
42
|
+
keyring_sources = prompt, literal, file, environment, dsn, login_path, fallback
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## completions trigger
|
|
46
|
+
|
|
47
|
+
Mycli's default completions trigger the display of candidates at the first
|
|
48
|
+
character, which might be distracting for some.
|
|
49
|
+
|
|
50
|
+
For more of an industry-standard experience, in which completions are deferred
|
|
51
|
+
until more information is typed, set `min_completion_trigger` to a small value
|
|
52
|
+
in `~/.myclirc`:
|
|
53
|
+
|
|
54
|
+
```ini
|
|
55
|
+
[main]
|
|
56
|
+
min_completion_trigger = 3
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## DSN environment variables
|
|
60
|
+
|
|
61
|
+
If using a tool such as [mise](https://github.com/jdx/mise) or [direnv](https://github.com/direnv/direnv) to manage
|
|
62
|
+
environment variables, it may be convenient to enable this setting in
|
|
63
|
+
`~/.myclirc`:
|
|
64
|
+
|
|
65
|
+
```ini
|
|
66
|
+
[main]
|
|
67
|
+
expand_dsn_alias_env_vars = True
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
which allows environment variables in the form `${VAR}` to be substituted
|
|
71
|
+
in DSNs.
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# Known Bugs
|
|
2
|
+
|
|
3
|
+
These are known bugs or limitations in mycli which it would be welcome to
|
|
4
|
+
fix.
|
|
5
|
+
|
|
6
|
+
## custom delimiters
|
|
7
|
+
|
|
8
|
+
A custom delimiter (query terminator) string may be set with the `/delimiter`
|
|
9
|
+
special command, but the custom delimiter is not respected in all parts of
|
|
10
|
+
mycli's code.
|
|
11
|
+
|
|
12
|
+
## completions after backtick
|
|
13
|
+
|
|
14
|
+
Completions after a backtick character are too exuberant. Example:
|
|
15
|
+
|
|
16
|
+
```sql
|
|
17
|
+
SELECT `<tab>
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
will offer more completions than
|
|
21
|
+
|
|
22
|
+
```sql
|
|
23
|
+
SELECT <tab>
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Windows limitations
|
|
27
|
+
|
|
28
|
+
Mycli is only partially tested on Windows, and several features such as
|
|
29
|
+
filename completion after `/source` may not work as expected.
|
|
30
|
+
|
|
31
|
+
## double-dash with shell redirections
|
|
32
|
+
|
|
33
|
+
The interpretation of `--` may not be consistent with `$|`. The double-dahs
|
|
34
|
+
is inherently ambiguous, being either a SQL comment initiator, or a common
|
|
35
|
+
part of a shell command. The rules for resolving the ambiguity should be
|
|
36
|
+
simple, and better documented.
|
|
37
|
+
|
|
38
|
+
## enum completions
|
|
39
|
+
|
|
40
|
+
Completions on enum values may fail if the values contain spaces.
|
|
41
|
+
|
|
42
|
+
## keyring support
|
|
43
|
+
|
|
44
|
+
If "Always Allow" is chosen on Mac, then all Python applications will have
|
|
45
|
+
access to the credential.
|
|
46
|
+
|
|
47
|
+
When making connections via a kubectl tunnel, the keyring is disabled, because
|
|
48
|
+
the Kubernetes context is not known.
|
|
49
|
+
|
|
50
|
+
## explorer
|
|
51
|
+
|
|
52
|
+
There is a trailing blank line in the explorer choices.
|
|
53
|
+
|
|
54
|
+
## prompt efficiency
|
|
55
|
+
|
|
56
|
+
The prompt and toolbar are updated more often than needed, even with caching.
|
|
57
|
+
|
|
58
|
+
## history search preview highlighting
|
|
59
|
+
|
|
60
|
+
When syntax highlighting with `pygmentize` is enabled for history search previews,
|
|
61
|
+
the colors do not match the user's preferences in `~/.myclirc`.
|
|
@@ -19,7 +19,7 @@ from prompt_toolkit.selection import SelectionType
|
|
|
19
19
|
|
|
20
20
|
from mycli.constants import DOCS_URL
|
|
21
21
|
from mycli.packages import key_binding_utils
|
|
22
|
-
from mycli.packages.ptoolkit.
|
|
22
|
+
from mycli.packages.ptoolkit.fzf_history import search_history
|
|
23
23
|
from mycli.packages.ptoolkit.utils import safe_invalidate_display
|
|
24
24
|
|
|
25
25
|
_logger = logging.getLogger(__name__)
|
|
@@ -43,9 +43,9 @@ def print_f1_help():
|
|
|
43
43
|
app.print_text('\n')
|
|
44
44
|
app.print_text([
|
|
45
45
|
('', 'Inline help — type "'),
|
|
46
|
-
('bold', 'help'),
|
|
46
|
+
('bold', '/help'),
|
|
47
47
|
('', '" or "'),
|
|
48
|
-
('bold', r'
|
|
48
|
+
('bold', r'/?'),
|
|
49
49
|
('', '"\n'),
|
|
50
50
|
])
|
|
51
51
|
app.print_text([
|
|
@@ -34,8 +34,8 @@ def _dependencies_checkup() -> None:
|
|
|
34
34
|
('pygments', 'required'),
|
|
35
35
|
('pymysql', 'required'),
|
|
36
36
|
('sqlglot', 'required'),
|
|
37
|
-
('sqlglotc', 'required'),
|
|
38
37
|
('tabulate', 'required'),
|
|
38
|
+
('sqlglotc', 'optional for performance'),
|
|
39
39
|
('llm', 'optional for /llm command'),
|
|
40
40
|
('polars', 'optional for .| operator'),
|
|
41
41
|
('altair', 'optional for .| operator'),
|
|
@@ -71,8 +71,8 @@ def _environment_checkup() -> None:
|
|
|
71
71
|
print('\n### Environment variables:\n')
|
|
72
72
|
table = []
|
|
73
73
|
for variable, purpose in [
|
|
74
|
-
('EDITOR', r'optional for
|
|
75
|
-
('VISUAL', r'optional for
|
|
74
|
+
('EDITOR', r'optional for /edit and C-x C-e'),
|
|
75
|
+
('VISUAL', r'optional for /edit and C-x C-e'),
|
|
76
76
|
]:
|
|
77
77
|
if value := os.environ.get(variable):
|
|
78
78
|
table.append([f'${variable}', value, purpose])
|
|
@@ -530,33 +530,40 @@ def _output_results(
|
|
|
530
530
|
else:
|
|
531
531
|
max_width = None
|
|
532
532
|
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
533
|
+
runner = runner_for(mycli)
|
|
534
|
+
with runner.rendering() if runner else nullcontext():
|
|
535
|
+
formatted = mycli.format_sqlresult(
|
|
536
|
+
result,
|
|
537
|
+
is_expanded=special.is_expanded_output(),
|
|
538
|
+
is_redirected=special.is_redirected(),
|
|
539
|
+
null_string=mycli.null_string,
|
|
540
|
+
numeric_alignment=mycli.numeric_alignment,
|
|
541
|
+
binary_display=mycli.binary_display,
|
|
542
|
+
max_width=max_width,
|
|
543
|
+
)
|
|
542
544
|
|
|
543
|
-
|
|
544
|
-
try:
|
|
545
|
-
if result_count > 0:
|
|
546
|
-
mycli.echo('')
|
|
545
|
+
duration = time.time() - start
|
|
547
546
|
try:
|
|
548
|
-
|
|
547
|
+
if result_count > 0:
|
|
548
|
+
if runner:
|
|
549
|
+
runner.stop_rendering()
|
|
550
|
+
mycli.echo('')
|
|
551
|
+
try:
|
|
552
|
+
mycli.output(formatted, result)
|
|
553
|
+
except KeyboardInterrupt:
|
|
554
|
+
if raise_interrupts:
|
|
555
|
+
raise
|
|
556
|
+
finally:
|
|
557
|
+
if runner:
|
|
558
|
+
runner.stop_rendering()
|
|
559
|
+
if mycli.beep_after_seconds > 0 and duration >= mycli.beep_after_seconds:
|
|
560
|
+
assert mycli.prompt_session is not None
|
|
561
|
+
mycli.prompt_session.output.bell()
|
|
562
|
+
if special.is_timing_enabled():
|
|
563
|
+
mycli.output_timing(f'Time: {duration:0.03f}s')
|
|
549
564
|
except KeyboardInterrupt:
|
|
550
565
|
if raise_interrupts:
|
|
551
566
|
raise
|
|
552
|
-
if mycli.beep_after_seconds > 0 and duration >= mycli.beep_after_seconds:
|
|
553
|
-
assert mycli.prompt_session is not None
|
|
554
|
-
mycli.prompt_session.output.bell()
|
|
555
|
-
if special.is_timing_enabled():
|
|
556
|
-
mycli.output_timing(f'Time: {duration:0.03f}s')
|
|
557
|
-
except KeyboardInterrupt:
|
|
558
|
-
if raise_interrupts:
|
|
559
|
-
raise
|
|
560
567
|
|
|
561
568
|
start = time.time()
|
|
562
569
|
result_count += 1
|
|
@@ -1137,7 +1144,7 @@ def _tips_picker() -> str:
|
|
|
1137
1144
|
except FileNotFoundError:
|
|
1138
1145
|
pass
|
|
1139
1146
|
|
|
1140
|
-
return random.choice(tips) if tips else r'
|
|
1147
|
+
return random.choice(tips) if tips else r'/? or /help for help!'
|
|
1141
1148
|
|
|
1142
1149
|
|
|
1143
1150
|
def _configure_editor(mycli: 'MyCli') -> None:
|
|
@@ -344,7 +344,11 @@ class OutputMixin(MyCliState):
|
|
|
344
344
|
if result.postamble:
|
|
345
345
|
output = itertools.chain(output, [result.postamble])
|
|
346
346
|
|
|
347
|
-
|
|
347
|
+
def finalized_output() -> Generator[str, None, None]:
|
|
348
|
+
yield from output
|
|
349
|
+
result.finalize_status()
|
|
350
|
+
|
|
351
|
+
return itertools.chain(finalized_output())
|
|
348
352
|
|
|
349
353
|
def get_reserved_space(self) -> int:
|
|
350
354
|
"""Get the number of lines to reserve for the completion menu."""
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"""Inspired by
|
|
2
|
+
https://github.com/nk412/pyfzf
|
|
3
|
+
and the fork
|
|
4
|
+
https://github.com/purarue/pyfzf
|
|
5
|
+
|
|
6
|
+
This code is trivially short and very far from the originals, but the MIT license
|
|
7
|
+
header from pyfzf is included anyway.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
# Portions Copyright (c) 2022 Nagarjuna Kumarappan
|
|
11
|
+
#
|
|
12
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
13
|
+
# of this software and associated documentation files (the "Software"), to deal
|
|
14
|
+
# in the Software without restriction, including without limitation the rights
|
|
15
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
16
|
+
# copies of the Software, and to permit persons to whom the Software is
|
|
17
|
+
# furnished to do so, subject to the following conditions:
|
|
18
|
+
#
|
|
19
|
+
# The above copyright notice and this permission notice shall be included in
|
|
20
|
+
# all copies or substantial portions of the Software.
|
|
21
|
+
#
|
|
22
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
23
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
24
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
25
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
26
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
27
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
28
|
+
# THE SOFTWARE.
|
|
29
|
+
|
|
30
|
+
from shutil import which
|
|
31
|
+
import subprocess
|
|
32
|
+
from typing import Any, Iterable
|
|
33
|
+
|
|
34
|
+
DELIMITER = '\x00'
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class Fzf:
|
|
38
|
+
def __init__(
|
|
39
|
+
self,
|
|
40
|
+
executable: str = 'fzf',
|
|
41
|
+
):
|
|
42
|
+
self.executable: str | None = executable
|
|
43
|
+
|
|
44
|
+
if not which(executable):
|
|
45
|
+
self.executable = None
|
|
46
|
+
|
|
47
|
+
def is_available(self) -> bool:
|
|
48
|
+
return self.executable is not None
|
|
49
|
+
|
|
50
|
+
def prompt(
|
|
51
|
+
self,
|
|
52
|
+
items: Iterable[Any],
|
|
53
|
+
options: list[str] | None = None,
|
|
54
|
+
) -> str | None:
|
|
55
|
+
options_final = ['--read0', '--print0'] + (options or [])
|
|
56
|
+
|
|
57
|
+
fzf_process = subprocess.Popen(
|
|
58
|
+
[self.executable or 'fzf', *options_final],
|
|
59
|
+
stdin=subprocess.PIPE,
|
|
60
|
+
stdout=subprocess.PIPE,
|
|
61
|
+
encoding='utf-8',
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
assert fzf_process.stdin is not None, 'Error creating fzf input stream'
|
|
65
|
+
try:
|
|
66
|
+
for item in items:
|
|
67
|
+
fzf_process.stdin.write(str(item) + DELIMITER)
|
|
68
|
+
except BrokenPipeError:
|
|
69
|
+
pass
|
|
70
|
+
|
|
71
|
+
stdout_str, _stderr_str = fzf_process.communicate()
|
|
72
|
+
|
|
73
|
+
if stdout_str:
|
|
74
|
+
# in mycli there is no meaning for multiple selection, so
|
|
75
|
+
# just return the first item
|
|
76
|
+
return stdout_str.split(DELIMITER)[0]
|
|
77
|
+
|
|
78
|
+
return None
|
mycli-2.27.0/mycli/packages/ptoolkit/fzf.py → mycli-2.28.0/mycli/packages/ptoolkit/fzf_history.py
RENAMED
|
@@ -4,22 +4,12 @@ from shutil import which
|
|
|
4
4
|
|
|
5
5
|
from prompt_toolkit import search
|
|
6
6
|
from prompt_toolkit.key_binding.key_processor import KeyPressEvent
|
|
7
|
-
from pyfzf import FzfPrompt
|
|
8
7
|
|
|
8
|
+
from mycli.packages.fzf import Fzf
|
|
9
9
|
from mycli.packages.ptoolkit.history import FileHistoryWithTimestamp
|
|
10
10
|
from mycli.packages.ptoolkit.utils import safe_invalidate_display
|
|
11
11
|
|
|
12
12
|
|
|
13
|
-
class Fzf(FzfPrompt):
|
|
14
|
-
def __init__(self):
|
|
15
|
-
self.executable = which("fzf")
|
|
16
|
-
if self.executable:
|
|
17
|
-
super().__init__()
|
|
18
|
-
|
|
19
|
-
def is_available(self) -> bool:
|
|
20
|
-
return self.executable is not None
|
|
21
|
-
|
|
22
|
-
|
|
23
13
|
def search_history(
|
|
24
14
|
event: KeyPressEvent,
|
|
25
15
|
highlight_preview: bool = False,
|
|
@@ -60,17 +50,17 @@ def search_history(
|
|
|
60
50
|
]
|
|
61
51
|
|
|
62
52
|
if highlight_preview and which('pygmentize'):
|
|
63
|
-
options.append(f'--preview=
|
|
53
|
+
options.append(f'--preview=printf \'%s\' {{}} | pygmentize -l mysql -P style={shlex.quote(highlight_style)}')
|
|
64
54
|
else:
|
|
65
|
-
options.append('--preview=
|
|
55
|
+
options.append('--preview=printf \'%s\' {}')
|
|
66
56
|
|
|
67
57
|
result = fzf.prompt(
|
|
68
58
|
formatted_history_items,
|
|
69
|
-
|
|
59
|
+
options=options,
|
|
70
60
|
)
|
|
71
61
|
safe_invalidate_display(event.app)
|
|
72
62
|
|
|
73
63
|
if result:
|
|
74
|
-
selected_index = formatted_history_items.index(result
|
|
64
|
+
selected_index = formatted_history_items.index(result)
|
|
75
65
|
buffer.text = original_history_items[selected_index]
|
|
76
66
|
buffer.cursor_position = len(buffer.text)
|
|
@@ -1,11 +1,3 @@
|
|
|
1
|
-
__lazy_modules__ = [
|
|
2
|
-
'mycli.packages.special.dbcommands',
|
|
3
|
-
'mycli.packages.special.iocommands',
|
|
4
|
-
'mycli.packages.special.llm',
|
|
5
|
-
'mycli.packages.special.main',
|
|
6
|
-
'mycli.packages.special.source',
|
|
7
|
-
]
|
|
8
|
-
|
|
9
1
|
import os
|
|
10
2
|
|
|
11
3
|
from mycli.packages.special.dbcommands import (
|