ruff-sync 0.1.5.dev2__tar.gz → 0.1.5.dev3__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.
- ruff_sync-0.1.5.dev3/.agents/skills/mike/SKILL.md +150 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/.agents/skills/textual/references/widgets.md +26 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/.agents/tui_design.md +19 -10
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/.agents/tui_requirements.md +8 -4
- ruff_sync-0.1.5.dev3/.agents/tui_rule_browsing.md +44 -0
- ruff_sync-0.1.5.dev3/.agents/tui_rule_browsing_design.md +66 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/.github/workflows/ci.yaml +24 -1
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/PKG-INFO +1 -1
- ruff_sync-0.1.5.dev3/docs/overrides/partials/version_warning.html +27 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/mkdocs.yml +2 -3
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/pyproject.toml +3 -1
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/src/ruff_sync/__init__.py +2 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/src/ruff_sync/cli.py +25 -9
- ruff_sync-0.1.5.dev3/src/ruff_sync/dependencies.py +64 -0
- ruff_sync-0.1.5.dev3/src/ruff_sync/system.py +176 -0
- ruff_sync-0.1.5.dev3/src/ruff_sync/tui/__init__.py +26 -0
- ruff_sync-0.1.5.dev3/src/ruff_sync/tui/app.py +304 -0
- ruff_sync-0.1.5.dev3/src/ruff_sync/tui/constants.py +9 -0
- ruff_sync-0.1.5.dev3/src/ruff_sync/tui/screens.py +185 -0
- ruff_sync-0.1.5.dev3/src/ruff_sync/tui/themes.py +21 -0
- ruff_sync-0.1.5.dev3/src/ruff_sync/tui/widgets.py +293 -0
- ruff_sync-0.1.5.dev3/tests/conftest.py +123 -0
- ruff_sync-0.1.5.dev3/tests/test_dependencies.py +59 -0
- ruff_sync-0.1.5.dev3/tests/test_minimal_imports.sh +54 -0
- ruff_sync-0.1.5.dev3/tests/test_rule_logic.py +99 -0
- ruff_sync-0.1.5.dev3/tests/test_themes.py +44 -0
- ruff_sync-0.1.5.dev3/tests/test_tui.py +299 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/uv.lock +3 -1
- ruff_sync-0.1.5.dev2/.agents/skills/mike/SKILL.md +0 -106
- ruff_sync-0.1.5.dev2/docs/overrides/partials/version_warning.html +0 -18
- ruff_sync-0.1.5.dev2/src/ruff_sync/dependencies.py +0 -38
- ruff_sync-0.1.5.dev2/src/ruff_sync/system.py +0 -45
- ruff_sync-0.1.5.dev2/tests/conftest.py +0 -64
- ruff_sync-0.1.5.dev2/tests/test_dependencies.py +0 -35
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/.agents/DEPENDENCIES.md +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/.agents/TESTING.md +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/.agents/formatters-architecture.md +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/.agents/gitlab-reports.md +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/.agents/issue-102-context.md +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/.agents/skills/dirty-equals/SKILL.md +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/.agents/skills/dirty-equals/references/common-matchers.md +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/.agents/skills/dirty-equals/references/toml-matching.md +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/.agents/skills/dirty-equals/trigger_eval.json +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/.agents/skills/gh-issues/SKILL.md +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/.agents/skills/mike/references/commands.md +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/.agents/skills/mkdocs-generation/SKILL.md +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/.agents/skills/mkdocs-generation/examples.md +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/.agents/skills/mkdocs-generation/templates/api-reference.md +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/.agents/skills/mkdocs-generation/templates/getting-started.md +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/.agents/skills/mkdocs-generation/templates/index.md +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/.agents/skills/mkdocs-generation/templates/mkdocs.yml +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/.agents/skills/release-notes-generation/SKILL.md +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/.agents/skills/ruff-sync-usage/SKILL.md +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/.agents/skills/ruff-sync-usage/references/ci-integration.md +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/.agents/skills/ruff-sync-usage/references/configuration.md +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/.agents/skills/ruff-sync-usage/references/troubleshooting.md +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/.agents/skills/textual/SKILL.md +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/.agents/skills/textual/examples/basic_app.py +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/.agents/skills/textual/examples/reactive_example.py +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/.agents/skills/textual/references/events.md +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/.agents/skills/textual/references/styling.md +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/.agents/skills/textual/references/testing.md +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/.agents/workflows/add-test-case.md +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/.git-blame-ignore-revs +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/.github/dependabot.yml +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/.github/workflows/complexity.yaml +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/.github/workflows/docs.yaml +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/.gitignore +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/.pre-commit-config.yaml +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/.pre-commit-hooks.yaml +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/AGENTS.md +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/CONTRIBUTING.md +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/LICENSE.md +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/README.md +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/codecov.yml +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/configs/data-science-engineering/ruff.toml +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/configs/fastapi/ruff.toml +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/configs/kitchen-sink/ruff.toml +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/docs/agent-skill.md +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/docs/assets/favicon.png +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/docs/assets/github-pr-annotation.png +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/docs/assets/logo.png +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/docs/assets/ruff_sync_banner.png +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/docs/best-practices.md +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/docs/ci-integration.md +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/docs/configuration.md +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/docs/contributing.md +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/docs/examples/advanced-config.toml +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/docs/examples/basic-config.toml +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/docs/gen_ref_pages.py +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/docs/index.md +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/docs/installation.md +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/docs/overrides/main.html +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/docs/pre-commit.md +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/docs/pre-defined-configs.md +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/docs/troubleshooting.md +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/docs/url-resolution.md +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/docs/usage.md +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/scripts/check_dogfood.sh +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/scripts/gitclone_dogfood.sh +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/scripts/pull_dogfood.sh +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/skills-lock.json +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/src/ruff_sync/__main__.py +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/src/ruff_sync/config_io.py +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/src/ruff_sync/constants.py +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/src/ruff_sync/core.py +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/src/ruff_sync/formatters.py +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/src/ruff_sync/pre_commit.py +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/tasks.py +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/tests/__init__.py +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/tests/lifecycle_tomls/multi_upstream_final.toml +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/tests/lifecycle_tomls/multi_upstream_initial.toml +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/tests/lifecycle_tomls/multi_upstream_up1.toml +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/tests/lifecycle_tomls/multi_upstream_up2.toml +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/tests/lifecycle_tomls/no_changes_final.toml +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/tests/lifecycle_tomls/no_changes_initial.toml +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/tests/lifecycle_tomls/no_changes_upstream.toml +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/tests/lifecycle_tomls/no_dotted_keys_final.toml +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/tests/lifecycle_tomls/no_dotted_keys_initial.toml +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/tests/lifecycle_tomls/no_dotted_keys_upstream.toml +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/tests/lifecycle_tomls/no_ruff_cfg_final.toml +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/tests/lifecycle_tomls/no_ruff_cfg_initial.toml +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/tests/lifecycle_tomls/no_ruff_cfg_upstream.toml +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/tests/lifecycle_tomls/readme_excludes_final.toml +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/tests/lifecycle_tomls/readme_excludes_initial.toml +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/tests/lifecycle_tomls/readme_excludes_upstream.toml +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/tests/lifecycle_tomls/standard_final.toml +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/tests/lifecycle_tomls/standard_initial.toml +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/tests/lifecycle_tomls/standard_upstream.toml +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/tests/ruff.toml +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/tests/test_basic.py +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/tests/test_check.py +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/tests/test_ci_integration.py +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/tests/test_ci_validation.py +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/tests/test_config_io.py +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/tests/test_config_validation.py +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/tests/test_constants.py +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/tests/test_corner_cases.py +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/tests/test_deprecation.py +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/tests/test_e2e.py +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/tests/test_formatters.py +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/tests/test_git_fetch.py +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/tests/test_pre_commit.py +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/tests/test_project.py +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/tests/test_scaffold.py +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/tests/test_serialization.py +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/tests/test_system.py +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/tests/test_toml_operations.py +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/tests/test_url_handling.py +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/tests/test_whitespace.py +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/tests/w_ruff_sync_cfg/pyproject.toml +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/tests/wo_ruff_cfg/pyproject.toml +0 -0
- {ruff_sync-0.1.5.dev2 → ruff_sync-0.1.5.dev3}/tests/wo_ruff_sync_cfg/pyproject.toml +0 -0
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: mike
|
|
3
|
+
description: Use this skill to manage multiple versions of documentation for MkDocs-powered sites. Deploy new versions, update aliases (like 'latest' or 'stable'), set the default version for the site root, and manage versioned subdirectories in the deployment branch. Use this whenever the user wants to publish, version, or alias documentation, even if they don't explicitly mention "mike". Also use this when the user wants to troubleshoot or debug versioned documentation.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# mike: MkDocs Versioning
|
|
7
|
+
|
|
8
|
+
`mike` is used in this project to manage a versioned documentation site, allowing side-by-side availability of `dev` (main branch) and stable release docs (e.g., `0.1.4`).
|
|
9
|
+
|
|
10
|
+
## Prerequisites
|
|
11
|
+
|
|
12
|
+
`mike` is included in the `docs` dependency group.
|
|
13
|
+
```bash
|
|
14
|
+
# Sync documentation dependencies
|
|
15
|
+
uv sync --group docs
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Project Strategy
|
|
19
|
+
|
|
20
|
+
This project follows a specific versioning strategy:
|
|
21
|
+
1. **`dev`**: Represents the current `main` branch.
|
|
22
|
+
2. **Stable Releases**: Versioned documentation (e.g., `0.1.4`) created upon release.
|
|
23
|
+
3. **`stable`**: An alias always pointing to the most recent non-dev release.
|
|
24
|
+
4. **`latest`**: An alias pointing to the most recent release (including dev, if applicable).
|
|
25
|
+
|
|
26
|
+
## Theme Overrides
|
|
27
|
+
|
|
28
|
+
To support the version switcher and custom banners, the project uses a `custom_dir` override in `mkdocs.yml`:
|
|
29
|
+
|
|
30
|
+
```yaml
|
|
31
|
+
theme:
|
|
32
|
+
name: material
|
|
33
|
+
custom_dir: docs/overrides
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### Version switcher
|
|
37
|
+
|
|
38
|
+
The version switcher is enabled via `extra.version.provider: mike`:
|
|
39
|
+
|
|
40
|
+
```yaml
|
|
41
|
+
extra:
|
|
42
|
+
version:
|
|
43
|
+
provider: mike
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Versioning Banner
|
|
47
|
+
|
|
48
|
+
A custom banner is displayed when users are viewing the `dev` documentation. This is handled via `docs/overrides/main.html` and `docs/overrides/partials/version_warning.html`.
|
|
49
|
+
|
|
50
|
+
### How it works:
|
|
51
|
+
- `main.html`: Extends the base template and includes the `version_warning.html` partial at the start of the `content` block.
|
|
52
|
+
- `version_warning.html`: Contains an HTML snippet that is hidden by default and shown via JavaScript if the URL path contains `/dev/`.
|
|
53
|
+
|
|
54
|
+
Example in `version_warning.html`:
|
|
55
|
+
```html
|
|
56
|
+
<div id="version-warning" style="display: none;">
|
|
57
|
+
<div class="admonition warning">
|
|
58
|
+
<p class="admonition-title">Warning</p>
|
|
59
|
+
<p>
|
|
60
|
+
You are viewing the documentation for the <strong>development</strong> version.
|
|
61
|
+
The latest stable release can be found at <a href="https://kilo59.github.io/ruff-sync/">kilo59.github.io/ruff-sync</a>.
|
|
62
|
+
</p>
|
|
63
|
+
</div>
|
|
64
|
+
</div>
|
|
65
|
+
<script>
|
|
66
|
+
(function() {
|
|
67
|
+
const version_warning = document.getElementById("version-warning");
|
|
68
|
+
if (!version_warning) return;
|
|
69
|
+
|
|
70
|
+
// mike provides a 'mike' object with some metadata if available
|
|
71
|
+
// Otherwise fall back to checking the pathname
|
|
72
|
+
const isDev = window.location.pathname.includes("/dev/") ||
|
|
73
|
+
(window.mike && typeof window.mike.version === 'string' && window.mike.version === "dev");
|
|
74
|
+
|
|
75
|
+
if (isDev) {
|
|
76
|
+
version_warning.style.display = "block";
|
|
77
|
+
}
|
|
78
|
+
})();
|
|
79
|
+
</script>
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### 1. Deploying Development Docs
|
|
83
|
+
Run this from the `main` branch to update the `dev` version:
|
|
84
|
+
```bash
|
|
85
|
+
mike deploy dev --push --update-aliases
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### 2. Deploying a Stable Release
|
|
89
|
+
When a new version is released (e.g., `0.1.4`), deploy it and update the `stable` alias:
|
|
90
|
+
```bash
|
|
91
|
+
# Deploy the specific version and update 'stable'
|
|
92
|
+
mike deploy 0.1.4 stable --push --update-aliases
|
|
93
|
+
|
|
94
|
+
# Set 'stable' as the default version for the site root
|
|
95
|
+
mike set-default --push stable
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## Reference Commands
|
|
99
|
+
|
|
100
|
+
| Action | Command |
|
|
101
|
+
| :--- | :--- |
|
|
102
|
+
| **Deploy** | `mike deploy <version> [alias]` |
|
|
103
|
+
| **List** | `mike list` |
|
|
104
|
+
| **Set Default** | `mike set-default <version>` |
|
|
105
|
+
| **Alias** | `mike alias <version> <alias>` |
|
|
106
|
+
| **Delete** | `mike delete <identifier>` |
|
|
107
|
+
|
|
108
|
+
## CI/CD Integration
|
|
109
|
+
|
|
110
|
+
The deployment logic is automated in [.github/workflows/ci.yaml](.github/workflows/ci.yaml). It automatically:
|
|
111
|
+
- Extracts the version from `pyproject.toml`.
|
|
112
|
+
- Deploys to `dev` if the version contains `.dev`.
|
|
113
|
+
- Deploys to `<version>` and updates `stable` for official releases.
|
|
114
|
+
|
|
115
|
+
> [!IMPORTANT]
|
|
116
|
+
> **Do NOT** use `mike install-gh-pages`. It is deprecated and removed in the version used by this project. `mike deploy` handles branch initialization automatically.
|
|
117
|
+
|
|
118
|
+
> [!TIP]
|
|
119
|
+
> Use `mike serve` locally to preview the version switcher before pushing changes.
|
|
120
|
+
|
|
121
|
+
## Troubleshooting
|
|
122
|
+
|
|
123
|
+
### Version Selector Not Appearing
|
|
124
|
+
- **Missing `versions.json`**: Ensure `mike deploy` or `mike update-aliases` has been run. The file must exist at the site root.
|
|
125
|
+
- **Incomplete `versions.json`**: If the current page's version (e.g., `stable`) is not listed in `versions.json`, some themes (like Material) may hide the selector.
|
|
126
|
+
- **`site_url` Case Sensitivity**: On GitHub Pages, ensure `site_url` in `mkdocs.yml` matches the actual deployment URL (usually lowercase). Discrepancies can cause the switcher to fail to find `versions.json` due to 404s.
|
|
127
|
+
- **Redundant Config**: Ensure `theme.version` is NOT set in `mkdocs.yml`. Use `extra.version.provider: mike` instead.
|
|
128
|
+
- **`canonical_version` Missing**: If the switcher is hidden on the root page, adding `canonical_version: stable` (or your main alias) to the `mike` plugin configuration can help the theme associate the root with the switcher metadata.
|
|
129
|
+
|
|
130
|
+
### 404 for `versions.json`
|
|
131
|
+
- If you see a 404 for `/versions.json` but `https://<user>.github.io/<repo>/versions.json` exists, the switcher is looking at the domain root instead of the project root. Verify `site_url` includes the repository name and has a trailing slash.
|
|
132
|
+
|
|
133
|
+
## Post-Mortem & Known Issues
|
|
134
|
+
|
|
135
|
+
> [!CAUTION]
|
|
136
|
+
> **Current Status**: Documentation versioning is currently **BROKEN** on the live site (`kilo59.github.io/ruff-sync`).
|
|
137
|
+
|
|
138
|
+
### Failed Repair History
|
|
139
|
+
The following fixes have been attempted and **FAILED** to resolve the issue:
|
|
140
|
+
1. **Lowercasing `site_url`**: Normalizing the repository name in the URL (e.g., `ruff-sync` instead of `Ruff-Sync`) did not fix the 404s for `versions.json`.
|
|
141
|
+
2. **Removing `theme.version`**: Removing the redundant Material 9.x config did not restore the switcher.
|
|
142
|
+
3. **Adding `canonical_version: stable`**: Adding this to the `mike` plugin in `mkdocs.yml` was intended to fix path resolution but has not fixed the root page 404.
|
|
143
|
+
4. **CI Restoration Logic**: Adding `mike alias --push stable stable` to the CI to manually repair `versions.json` hasn't restored the picker on the root page.
|
|
144
|
+
|
|
145
|
+
### Root Cause Suspicions
|
|
146
|
+
- **GitHub Pages Subfolder Pathing**: The site is served from a subfolder (`/ruff-sync/`). `mike`'s JavaScript for the version switcher frequently struggles with calculating relative paths to `versions.json` when served from a subfolder if `site_url` or base paths are not perfectly aligned with the deployment environment.
|
|
147
|
+
- **`versions.json` Drift**: The `versions.json` file on the `gh-pages` branch frequently becomes desynchronized or loses the `stable` entry, which triggers `mkdocs-material` to hide the switcher entirely.
|
|
148
|
+
|
|
149
|
+
### Guidance for Future Agents
|
|
150
|
+
Before attempting another "fix," you **MUST** verify the current state of `versions.json` on the `gh-pages` branch and check the browser console on the live site for 404 paths. Do not assume standard configurations will work without manual verification of the deployed assets.
|
|
@@ -57,3 +57,29 @@ def on_key(self, event: events.Key) -> None:
|
|
|
57
57
|
|
|
58
58
|
> [!TIP]
|
|
59
59
|
> Use `BINDINGS` in your `App` or `Screen` class for most navigation tasks. Textual manages the labels and shortcuts in the `Footer` for you.
|
|
60
|
+
|
|
61
|
+
### `ModalScreen` & Overlays
|
|
62
|
+
Modals are screens with a transparent or dim background that overlay the main app.
|
|
63
|
+
```python
|
|
64
|
+
from textual.screen import ModalScreen
|
|
65
|
+
from textual.app import App
|
|
66
|
+
|
|
67
|
+
class OmniboxScreen(ModalScreen[str]):
|
|
68
|
+
# A modal screen that returns a `str` when dismissed.
|
|
69
|
+
def compose(self) -> ComposeResult:
|
|
70
|
+
# yield your input/search widgets here
|
|
71
|
+
yield Input(placeholder="Search...")
|
|
72
|
+
|
|
73
|
+
# Dismiss the screen and return data
|
|
74
|
+
def on_input_submitted(self, event: Input.Submitted) -> None:
|
|
75
|
+
self.dismiss(event.value)
|
|
76
|
+
|
|
77
|
+
# In the main App or Screen:
|
|
78
|
+
def on_key(self, event: events.Key) -> None:
|
|
79
|
+
if event.key == "ctrl+p":
|
|
80
|
+
self.push_screen(OmniboxScreen(), self.handle_omnibox_result)
|
|
81
|
+
|
|
82
|
+
def handle_omnibox_result(self, result: str | None) -> None:
|
|
83
|
+
if result:
|
|
84
|
+
print(f"Selected: {result}")
|
|
85
|
+
```
|
|
@@ -12,7 +12,10 @@ Before we build the TUI feature itself, some of the existing codebase should be
|
|
|
12
12
|
Currently, `ruff-sync` is primarily concerned with TOML serialization. The TUI introduces a requirement to execute the system `ruff` binary (e.g. `ruff rule <CODE>`).
|
|
13
13
|
**Refactoring Task:**
|
|
14
14
|
- Create a generalized, safe abstraction for interacting with the `ruff` executable.
|
|
15
|
-
- Provide
|
|
15
|
+
- Provide typed async functions:
|
|
16
|
+
- `async def get_ruff_rule_markdown(rule_code: str) -> str | None`
|
|
17
|
+
- `async def get_ruff_config_markdown(setting_path: str) -> str | None`
|
|
18
|
+
- These should use `asyncio.create_subprocess_exec` to fetch and return the text. This prevents raw `subprocess` sprawl across TUI widgets.
|
|
16
19
|
|
|
17
20
|
### B. Configuration Reader Extraction (`src/ruff_sync/config_io.py` or similar)
|
|
18
21
|
Right now, discovering and extracting the local `pyproject.toml` is slightly coupled to the lifecycle of pulling from upstreams (`pull()` / `check()` in `core.py`).
|
|
@@ -59,16 +62,21 @@ Right now, discovering and extracting the local `pyproject.toml` is slightly cou
|
|
|
59
62
|
### [NEW] src/ruff_sync/tui/app.py
|
|
60
63
|
- Define `RuffSyncApp` subclassing `textual.app.App`.
|
|
61
64
|
- **CSS**: Define embedded TCSS.
|
|
62
|
-
- Layout: `Horizontal` split with `Tree` (left) sized `1fr`, and a `Vertical` container (right) sized `2fr`.
|
|
65
|
+
- Layout: `Horizontal` split with `Tree` (left) sized `1fr`, and a `Vertical` container (`#content-pane`) (right) sized `2fr`.
|
|
66
|
+
- **Dynamic Layout**:
|
|
67
|
+
- `#category-table` takes **40% height** by default.
|
|
68
|
+
- `#inspector` (Markdown) takes **60% height** by default.
|
|
69
|
+
- When the table is hidden, the `#inspector` uses a `.full-height` class (**100% height**) to fill the content pane.
|
|
70
|
+
- Both widgets utilize `overflow-y: auto` for vertical scrolling only when needed.
|
|
63
71
|
- **Compose Method**:
|
|
64
72
|
```python
|
|
65
73
|
def compose(self) -> ComposeResult:
|
|
66
74
|
yield Header()
|
|
67
75
|
with Horizontal():
|
|
68
76
|
yield ConfigTree(id="config-tree")
|
|
69
|
-
with Vertical():
|
|
77
|
+
with Vertical(id="content-pane"):
|
|
70
78
|
yield CategoryTable(id="category-table")
|
|
71
|
-
yield RuleInspector(id="inspector"
|
|
79
|
+
yield RuleInspector(id="inspector")
|
|
72
80
|
yield Footer()
|
|
73
81
|
```
|
|
74
82
|
- **Lifecycle (`on_mount`)**:
|
|
@@ -87,9 +95,9 @@ Contains all custom Textual widgets required for this view.
|
|
|
87
95
|
- Automatically clears and updates columns/rows when a tree node is highlighted.
|
|
88
96
|
|
|
89
97
|
**3. `RuleInspector` (inherits `textual.widgets.Markdown`)**:
|
|
90
|
-
- Displays `ruff rule <CODE>`
|
|
91
|
-
- Features an `async def fetch_and_display(self,
|
|
92
|
-
- **Background Worker**: Uses Textual `@work(thread=True)` to execute
|
|
98
|
+
- Displays documentation for both rules (`ruff rule <CODE>`) and settings (`ruff config <SETTING>`).
|
|
99
|
+
- Features an `async def fetch_and_display(self, target: str, is_rule: bool = True)` method.
|
|
100
|
+
- **Background Worker**: Uses Textual `@work(thread=True)` to execute the appropriate refactored `get_ruff_*_markdown()` function.
|
|
93
101
|
|
|
94
102
|
---
|
|
95
103
|
|
|
@@ -98,10 +106,11 @@ Contains all custom Textual widgets required for this view.
|
|
|
98
106
|
### [MODIFY] src/ruff_sync/tui/app.py (Reactivity)
|
|
99
107
|
- Tie widgets together using Textual's event routing (`@on`):
|
|
100
108
|
- `@on(Tree.NodeSelected)`:
|
|
101
|
-
- If the node is a configuration section (e.g. `lint.isort`),
|
|
102
|
-
- If the node represents a
|
|
109
|
+
- If the node is a configuration section (e.g. `lint.isort`), ensure the `CategoryTable` is visible (remove "hidden" class), remove the `.full-height` class from the inspector, and populate it with settings. It also triggers `inspector.fetch_and_display(section_path, is_rule=False)` to show section-level docs if available.
|
|
110
|
+
- If the node represents a rule code, add the "hidden" class to `CategoryTable` to maximize vertical space, add the `.full-height` class to the `RuleInspector`, and display the rule via `fetch_and_display(code, is_rule=True)`.
|
|
103
111
|
- `@on(DataTable.RowSelected)`:
|
|
104
|
-
- If the focused row represents a Ruff Rule Code (e.g., `RUF012`), reveal the `RuleInspector` widget and call `inspector.fetch_and_display("RUF012")`.
|
|
112
|
+
- If the focused row represents a Ruff Rule Code (e.g., `RUF012`), hide the `CategoryTable`, reveal the `RuleInspector` widget, apply `.full-height`, and call `inspector.fetch_and_display("RUF012", is_rule=True)`.
|
|
113
|
+
- If the focused row represents a configuration setting, reveal the `RuleInspector` (at default height if table is shown) and call `inspector.fetch_and_display(setting_key, is_rule=False)`.
|
|
105
114
|
- Expose related context natively based on selections.
|
|
106
115
|
|
|
107
116
|
---
|
|
@@ -21,15 +21,19 @@
|
|
|
21
21
|
- Provide visual grouping for rule categories (e.g., `E` for pycodestyle, `F` for Pyflakes, `TC` for flake8-type-checking).
|
|
22
22
|
3. **Contextual Inspector & Documentation**
|
|
23
23
|
- When a user highlights a specific rule (e.g., `RUF012`), asynchronously execute `ruff rule <CODE>` to fetch and render the official documentation as Markdown.
|
|
24
|
-
-
|
|
25
|
-
|
|
24
|
+
- When a user highlights a configuration setting (e.g., `lint.isort.combine-as-imports`), asynchronously execute `ruff config <SETTING>` to fetch its documentation, default value, and type information.
|
|
25
|
+
- Surface related context depending on the selection: highlighting a rule exposes its documentation AND related configuration settings; highlighting a config setting (in the Tree or CategoryTable) exposes its definition and usage examples.
|
|
26
|
+
4. **Rich Metadata Rendering**
|
|
27
|
+
- The Inspector should distinguish between Rule documentation and Setting documentation.
|
|
28
|
+
- Setting documentation should clearly call out **Default Value** and **Type** in a dedicated header or sidebar within the inspector.
|
|
29
|
+
5. **Fuzzy Search**
|
|
26
30
|
- A search bar to quickly locate a specific configuration key or rule code without manual scrolling.
|
|
27
31
|
|
|
28
32
|
### 2.2 UX / UI Layout Concept
|
|
29
33
|
- **Header:** Application title and current local repository path.
|
|
30
34
|
- **Left Sidebar (Navigation):** `Tree` widget for configuration categories (`Global`, `Linting`, `Formatting`, `Rule Index`).
|
|
31
|
-
- **Center Area (Main Content):** `DataTable` or `ListView` showing the keys and values for the selected category.
|
|
32
|
-
- **Right/Bottom Panel (Inspector):** Context-aware inspector. Because `ruff rule <CODE>` output contains proper Markdown, this panel MUST robustly render Markdown (e.g., utilizing Textual's `Markdown` widget) while dynamically adjoining related setting/rule cross-references around it.
|
|
35
|
+
- **Center Area (Main Content):** `DataTable` or `ListView` showing the keys and values for the selected category. This panel is dynamically hidden when inspecting dense documentation to maximize reading space.
|
|
36
|
+
- **Right/Bottom Panel (Inspector):** Context-aware scrollable inspector (`overflow-y: auto`). Because `ruff rule <CODE>` output contains proper Markdown, this panel MUST robustly render Markdown (e.g., utilizing Textual's `Markdown` widget) while dynamically adjoining related setting/rule cross-references around it.
|
|
33
37
|
- **Footer:** Action key bindings (`q` to Quit, `/` to Search, `?` for Help).
|
|
34
38
|
|
|
35
39
|
---
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Ruff-Sync TUI: Rule Browsing & Discovery Proposals
|
|
2
|
+
|
|
3
|
+
This document outlines additional convenience features and alternative navigation paradigms for browsing and exploring specific Ruff rules and groups outside the standard TOML hierarchy.
|
|
4
|
+
|
|
5
|
+
**Related Documents:**
|
|
6
|
+
- [TUI Requirements](tui_requirements.md)
|
|
7
|
+
- [TUI Technical Design](tui_design.md)
|
|
8
|
+
- [Rule Browsing Detailed Design](tui_rule_browsing_design.md)
|
|
9
|
+
|
|
10
|
+
## Background
|
|
11
|
+
While the TOML hierarchy (as established in the core requirements) provides an exact structural representation (e.g., exposing `tool.ruff.lint.select`), it is not always the most intuitive way to discover or understand the net set of rules actively evaluating the project.
|
|
12
|
+
|
|
13
|
+
The following proposals are designed to augment the current "Read-Only" TUI mode to support rapid interrogation, global searching, and global discovery of Ruff rules.
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## 1. The "Effective Rules" Flat Table
|
|
18
|
+
Instead of exclusively browsing via the TOML tree (`tool.ruff.lint.select`), we introduce a top-level **"Effective Rules"** dashboard.
|
|
19
|
+
- **How it works:** A single, sortable `DataTable` that flattens all configuration vectors (`select`, `extend-select`, `ignore`, `per-file-ignores`) into a definitive list.
|
|
20
|
+
- **Columns:** `Code` (e.g., F401), `Name` (e.g., unused-import), `Category` (e.g., Pyflakes), and `Status` (Enabled/Ignored).
|
|
21
|
+
- **Benefit:** Gives the user a complete, "at-a-glance" ledger of exactly what the linter is checking without having to manually perform the mental math of `select` minus `ignore`.
|
|
22
|
+
|
|
23
|
+
## 2. Category / Linter Prefix Grouping
|
|
24
|
+
Ruff is conceptually built around "Linters" (e.g., `Pyflakes`, `pycodestyle`, `flake8-bugbear`). The TOML configuration often just specifies a prefix like `select = ["E", "F", "B"]`.
|
|
25
|
+
- **How it works:** Add a new root node in the `Tree` called **"Linters & Categories"**.
|
|
26
|
+
- **Interaction:** Navigating to "flake8-bugbear (B)" displays a table of all `B` rules, instantly showing which ones are locally enabled, ignored, or inactive.
|
|
27
|
+
- **Benefit:** Maps directly to how developers usually think about adding new rulesets to their projects.
|
|
28
|
+
|
|
29
|
+
## 3. Global Fuzzy Command Palette ("Omnibox")
|
|
30
|
+
Navigating a tree or a table can be tedious if the user knows exactly what they are looking for.
|
|
31
|
+
- **How it works:** A global keybind (e.g., `Ctrl+P` or `/`) that opens a fuzzy search overlay modal.
|
|
32
|
+
- **Interaction:** The user types "unused" and the palette immediately surfaces `F401 (unused-import)`, `F841 (unused-variable)`, etc. Hitting Enter drops them directly into the `RuleInspector` for that specific rule, completely bypassing the Tree hierarchy.
|
|
33
|
+
- **Benefit:** The fastest possible way to interrogate a specific rule.
|
|
34
|
+
|
|
35
|
+
## 4. Quick-Filter State Toggles
|
|
36
|
+
When inside any view displaying rules (like the flattened table or the prefix grouping), give the user hotkeys to rapidly shift perspectives.
|
|
37
|
+
- **How it works:** Add toggles (e.g., `1: All`, `2: Enabled`, `3: Ignored`).
|
|
38
|
+
- **Benefit:** If a user is looking at a massive category like `E` (pycodestyle), they can quickly press `3` to filter the table down to ONLY the rules they explicitly ignored, providing an instant audit trail.
|
|
39
|
+
|
|
40
|
+
## 5. "Rule Registry" / Discovery Mode
|
|
41
|
+
Currently, the user only sees rules they explicitly mention in their `pyproject.toml` or have inherited. How do they discover new rules to adopt?
|
|
42
|
+
- **How it works:** By executing `ruff rule --all` under the hood, the TUI could populate a "Discovery" tab. This lists every single rule Ruff supports.
|
|
43
|
+
- **Visuals:** Rules that are currently enabled in the local project are highlighted or checked off.
|
|
44
|
+
- **Benefit:** Huge value-add for configuration exploration. Users can browse new rules they might want to adopt directly inside the TUI without referring back to the Ruff website.
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# Detailed Implementation Plan: Effective Rules & Omnibox
|
|
2
|
+
|
|
3
|
+
This document provides exhaustive technical instructions to implement Features 1 (Effective Rules Flat Table) and 3 (Global Fuzzy Command Palette) from the [Rule Browsing Proposals](tui_rule_browsing.md).
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 1. Data Access & Subprocess Upgrades
|
|
8
|
+
To present a flat list of rules or allow fuzzy searching across all rules, the TUI must have structural knowledge of every rule Ruff supports.
|
|
9
|
+
|
|
10
|
+
### A. `get_all_ruff_rules() -> list[dict]`
|
|
11
|
+
- In `src/ruff_sync/system.py` (or the equivalent subprocess wrapper module), implement an async function that executes `uv run ruff rule --all --output-format json` (or `ruff rule --all --output-format json` depending on the environment context).
|
|
12
|
+
- This returns a JSON array of objects representing all rules (fields include `name`, `code`, `linter`, `summary`, etc.).
|
|
13
|
+
|
|
14
|
+
### B. `get_ruff_linters() -> list[dict]`
|
|
15
|
+
- Implement an async function that executes `ruff linter --output-format json`. Returns categories/prefixes (fields include `prefix`, `name`, `categories`).
|
|
16
|
+
|
|
17
|
+
### C. Active Rule Evaluation Logic
|
|
18
|
+
- Create a pure utility function `compute_effective_rules(all_rules: list[dict], toml_config: dict) -> list[dict]`.
|
|
19
|
+
- `toml_config` is the unwrapped TOML dictionary.
|
|
20
|
+
- The function iterates over `all_rules`. For each rule, it checks the rule's `code` (e.g. `F401`) against the `[tool.ruff.lint]` keys `select`, `ignore`, `extend-select`.
|
|
21
|
+
- **Heuristic**: Length-based prefix matching. If `select = ["F"]` and `ignore = ["F401"]`, `F401` matches both. Since `F401` (len 4) is a longer and more specific prefix match than `F` (len 1), `ignore` wins. The rule is marked with `status="Ignored"`. If it was only partially matched in `select` it gets `status="Enabled"`.
|
|
22
|
+
- Return an enriched list of dictionaries mimicking the original rules but adding a `status` key.
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## 2. The "Effective Rules" Flat Table UI
|
|
27
|
+
|
|
28
|
+
### A. Tree Hierarchy Updates (`src/ruff_sync/tui/widgets.py`)
|
|
29
|
+
- Modify the `ConfigTree` (which parses the `pyproject.toml` hierarchy) to inject a synthetic root node at the very top: **"Effective Active Rules"**.
|
|
30
|
+
|
|
31
|
+
### B. Table Integration (`src/ruff_sync/tui/app.py` & `widgets.py`)
|
|
32
|
+
- When the user selects the "Effective Active Rules" tree node, intercept the event in `@on(Tree.NodeSelected)`.
|
|
33
|
+
- Make the `CategoryTable` visible and hide the `RuleInspector` initially.
|
|
34
|
+
- Clear existing columns and add `["Code", "Name", "Linter", "Status"]`.
|
|
35
|
+
- Fetch the enriched rules list from `compute_effective_rules`.
|
|
36
|
+
- Iterate the enriched rules, adding them to the `CategoryTable`. Use Textual Rich markup (e.g., `[green]Enabled[/green]`, `[red]Ignored[/red]`) for the Status column.
|
|
37
|
+
|
|
38
|
+
### C. Row Selection Linkage
|
|
39
|
+
- Ensure `@on(DataTable.RowSelected)` correctly parses the Row Data to extract the "Rule Code" (e.g. `F401`).
|
|
40
|
+
- Hiding the Table and revealing the `RuleInspector` should fire seamlessly by calling `self.query_one("#inspector").fetch_and_display(rule_code, is_rule=True)`.
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## 3. The Global Fuzzy "Omnibox" UI
|
|
45
|
+
|
|
46
|
+
### A. App-Level Keybind (`src/ruff_sync/tui/app.py`)
|
|
47
|
+
- In `RuffSyncApp.BINDINGS`, add `("/", "search", "Search Rules")`.
|
|
48
|
+
- Add `def action_search(self) -> None:` to intercept the hotkey.
|
|
49
|
+
|
|
50
|
+
### B. `OmniboxScreen` Widget (`src/ruff_sync/tui/screens.py`)
|
|
51
|
+
- Create a module `screens.py` and define `class OmniboxScreen(ModalScreen[str]):`.
|
|
52
|
+
- `compose()` should yield an `Input(placeholder="Search rules (e.g. F401, unused)...")` and optionally an initially-empty `OptionList` or `ListView` beneath it for results.
|
|
53
|
+
- **TCSS**: Center the `OmniboxScreen` contents vertically and horizontally. Give the main container a distinct background color and border to pop out over the main App.
|
|
54
|
+
|
|
55
|
+
### C. Fuzzy Search Logic (`@on(Input.Changed)`)
|
|
56
|
+
- Read `all_rules` from the background fetching mechanism.
|
|
57
|
+
- For every keystroke (`Input.Changed`), perform a simple substring or fuzzy match against both `rule["code"]` and `rule["name"]`.
|
|
58
|
+
- Populate the `ListView`/`OptionList` with the top 10-15 matches.
|
|
59
|
+
|
|
60
|
+
### D. Submission (`@on(Input.Submitted)` or `OptionList.OptionSelected`)
|
|
61
|
+
- When the user hits enter on a search result, call `self.dismiss(result_rule_code)`.
|
|
62
|
+
|
|
63
|
+
### E. App Callback Integration
|
|
64
|
+
- In `action_search`, execute `self.push_screen(OmniboxScreen(), self.handle_omnibox_result)`.
|
|
65
|
+
- `def handle_omnibox_result(self, rule_code: str | None) -> None:`
|
|
66
|
+
- If `rule_code` is provided, act exactly as if a row was selected in the `CategoryTable`: Hide the table, show the inspector via `self.query_one("#inspector").fetch_and_display(rule_code, is_rule=True)`.
|
|
@@ -84,6 +84,25 @@ jobs:
|
|
|
84
84
|
token: ${{ secrets.CODECOV_TOKEN }}
|
|
85
85
|
slug: Kilo59/ruff-sync
|
|
86
86
|
|
|
87
|
+
test-no-optional-deps:
|
|
88
|
+
name: Test without optional dependencies
|
|
89
|
+
runs-on: ubuntu-latest
|
|
90
|
+
steps:
|
|
91
|
+
- name: Checkout
|
|
92
|
+
uses: actions/checkout@v4
|
|
93
|
+
|
|
94
|
+
- name: Set up Python
|
|
95
|
+
uses: actions/setup-python@v5
|
|
96
|
+
with:
|
|
97
|
+
python-version: "3.10"
|
|
98
|
+
|
|
99
|
+
- name: Install ruff-sync (no extras)
|
|
100
|
+
# We install only the base package without 'dev' or 'tui' groups.
|
|
101
|
+
run: pip install .
|
|
102
|
+
|
|
103
|
+
- name: Run optional dependency validation script
|
|
104
|
+
run: bash tests/test_minimal_imports.sh
|
|
105
|
+
|
|
87
106
|
pre-publish:
|
|
88
107
|
name: Test package installation
|
|
89
108
|
needs: [static-analysis, tests]
|
|
@@ -185,7 +204,11 @@ jobs:
|
|
|
185
204
|
echo "Current Version: $VERSION"
|
|
186
205
|
|
|
187
206
|
if [[ "$VERSION" == *".dev"* ]]; then
|
|
188
|
-
echo "Deploying DEV documentation
|
|
207
|
+
echo "Deploying DEV documentation..."
|
|
208
|
+
# Ensure 'stable' exists in versions.json so the switcher doesn't disappear.
|
|
209
|
+
# 'mike alias' will create it if missing, pointing to the current stable root.
|
|
210
|
+
# We use --push to ensure versions.json is updated on gh-pages.
|
|
211
|
+
uv run mike alias --push stable stable || true
|
|
189
212
|
uv run mike deploy --push --update-aliases dev
|
|
190
213
|
else
|
|
191
214
|
echo "Deploying STABLE documentation..."
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ruff-sync
|
|
3
|
-
Version: 0.1.5.
|
|
3
|
+
Version: 0.1.5.dev3
|
|
4
4
|
Summary: Synchronize Ruff linter configuration across projects
|
|
5
5
|
Project-URL: Homepage, https://github.com/Kilo59/ruff-sync
|
|
6
6
|
Project-URL: Documentation, https://kilo59.github.io/ruff-sync/
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{% if config.extra.version and config.extra.version.provider == "mike" %}
|
|
2
|
+
<div id="version-warning" style="display: none;">
|
|
3
|
+
<div class="admonition warning">
|
|
4
|
+
<p class="admonition-title">Warning</p>
|
|
5
|
+
<p>
|
|
6
|
+
You are viewing the documentation for the <strong>development</strong> version.
|
|
7
|
+
The latest stable release can be found at <a href="https://kilo59.github.io/ruff-sync/">kilo59.github.io/ruff-sync</a>.
|
|
8
|
+
</p>
|
|
9
|
+
</div>
|
|
10
|
+
</div>
|
|
11
|
+
|
|
12
|
+
<script>
|
|
13
|
+
(function() {
|
|
14
|
+
const version_warning = document.getElementById("version-warning");
|
|
15
|
+
if (!version_warning) return;
|
|
16
|
+
|
|
17
|
+
// mike provides a 'mike' object with some metadata if available
|
|
18
|
+
// Otherwise fall back to checking the pathname
|
|
19
|
+
const isDev = window.location.pathname.includes("/dev/") ||
|
|
20
|
+
(window.mike && typeof window.mike.version === 'string' && window.mike.version === "dev");
|
|
21
|
+
|
|
22
|
+
if (isDev) {
|
|
23
|
+
version_warning.style.display = "block";
|
|
24
|
+
}
|
|
25
|
+
})();
|
|
26
|
+
</script>
|
|
27
|
+
{% endif %}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
site_name: ruff-sync
|
|
2
2
|
site_description: Synchronize Ruff linter configuration across Python projects.
|
|
3
|
-
site_url: https://
|
|
3
|
+
site_url: https://kilo59.github.io/ruff-sync/
|
|
4
4
|
|
|
5
5
|
repo_name: Kilo59/ruff-sync
|
|
6
6
|
repo_url: https://github.com/Kilo59/ruff-sync
|
|
@@ -26,8 +26,6 @@ theme:
|
|
|
26
26
|
toggle:
|
|
27
27
|
icon: material/brightness-4
|
|
28
28
|
name: Switch to light mode
|
|
29
|
-
version:
|
|
30
|
-
method: mike
|
|
31
29
|
features:
|
|
32
30
|
- content.code.copy
|
|
33
31
|
- content.tabs.link
|
|
@@ -98,6 +96,7 @@ plugins:
|
|
|
98
96
|
- search
|
|
99
97
|
- mike:
|
|
100
98
|
alias_type: copy
|
|
99
|
+
canonical_version: stable
|
|
101
100
|
- gen-files:
|
|
102
101
|
scripts:
|
|
103
102
|
- docs/gen_ref_pages.py
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "ruff-sync"
|
|
3
|
-
version = "0.1.5.
|
|
3
|
+
version = "0.1.5.dev3"
|
|
4
4
|
description = "Synchronize Ruff linter configuration across projects"
|
|
5
5
|
keywords = ["ruff", "linter", "config", "synchronize", "python", "linting", "automation", "tomlkit", "pre-commit"]
|
|
6
6
|
authors = [
|
|
@@ -41,6 +41,7 @@ Changelog = "https://github.com/Kilo59/ruff-sync/releases"
|
|
|
41
41
|
|
|
42
42
|
[project.scripts]
|
|
43
43
|
ruff-sync = "ruff_sync:main"
|
|
44
|
+
ruff-inspect = "ruff_sync:inspect"
|
|
44
45
|
|
|
45
46
|
[dependency-groups]
|
|
46
47
|
dev = [
|
|
@@ -57,6 +58,7 @@ dev = [
|
|
|
57
58
|
"respx>=0.21.1",
|
|
58
59
|
"ruamel-yaml>=0.18.6",
|
|
59
60
|
"ruff>=0.15.0",
|
|
61
|
+
"textual>=8.2.2",
|
|
60
62
|
"wily>=1.25.0",
|
|
61
63
|
]
|
|
62
64
|
docs = [
|
|
@@ -9,6 +9,7 @@ from .cli import (
|
|
|
9
9
|
Arguments,
|
|
10
10
|
__version__,
|
|
11
11
|
get_config,
|
|
12
|
+
inspect,
|
|
12
13
|
main,
|
|
13
14
|
)
|
|
14
15
|
from .config_io import (
|
|
@@ -46,6 +47,7 @@ __all__ = [
|
|
|
46
47
|
"get_formatter",
|
|
47
48
|
"get_ruff_config",
|
|
48
49
|
"get_ruff_tool_table",
|
|
50
|
+
"inspect",
|
|
49
51
|
"is_ruff_toml_file",
|
|
50
52
|
"load_local_ruff_config",
|
|
51
53
|
"main",
|
|
@@ -42,6 +42,7 @@ from ruff_sync.core import (
|
|
|
42
42
|
pull,
|
|
43
43
|
resolve_raw_url,
|
|
44
44
|
)
|
|
45
|
+
from ruff_sync.dependencies import DependencyError
|
|
45
46
|
|
|
46
47
|
if TYPE_CHECKING:
|
|
47
48
|
from collections.abc import Iterable, Mapping
|
|
@@ -378,6 +379,9 @@ def _resolve_upstream(args: CLIArguments, config: Config) -> tuple[URL, ...]:
|
|
|
378
379
|
f"got {type(config_upstream).__name__}"
|
|
379
380
|
)
|
|
380
381
|
|
|
382
|
+
if args.command == "inspect":
|
|
383
|
+
return ()
|
|
384
|
+
|
|
381
385
|
PARSER.error(
|
|
382
386
|
"❌ the following arguments are required: upstream "
|
|
383
387
|
f"(or define it in [tool.ruff-sync] in {RuffConfigFileName.PYPROJECT_TOML}) 💥"
|
|
@@ -599,25 +603,37 @@ def main() -> int:
|
|
|
599
603
|
|
|
600
604
|
try:
|
|
601
605
|
if exec_args.command == "inspect":
|
|
602
|
-
from ruff_sync.
|
|
603
|
-
|
|
604
|
-
try:
|
|
605
|
-
require_dependency("textual", extra_name="tui")
|
|
606
|
-
except ImportError as e:
|
|
607
|
-
LOGGER.error(f"❌ {e}") # noqa: TRY400
|
|
608
|
-
return 1
|
|
606
|
+
from ruff_sync.tui import get_tui_app # noqa: PLC0415
|
|
609
607
|
|
|
610
|
-
|
|
611
|
-
return
|
|
608
|
+
app_class = get_tui_app()
|
|
609
|
+
return app_class(exec_args).run() or 0
|
|
612
610
|
|
|
613
611
|
if exec_args.command == "check":
|
|
614
612
|
return asyncio.run(check(exec_args))
|
|
615
613
|
return asyncio.run(pull(exec_args))
|
|
614
|
+
except DependencyError as e:
|
|
615
|
+
LOGGER.error(f"❌ {e}") # noqa: TRY400
|
|
616
|
+
return 1
|
|
616
617
|
except UpstreamError as e:
|
|
617
618
|
for url, err in e.errors:
|
|
618
619
|
LOGGER.error(f"❌ Failed to fetch {url}: {err}") # noqa: TRY400
|
|
619
620
|
return 4
|
|
620
621
|
|
|
621
622
|
|
|
623
|
+
def inspect() -> int:
|
|
624
|
+
"""Entry point for the ruff-inspect console script."""
|
|
625
|
+
# Handle optional subcommands/args if user passed any to ruff-inspect
|
|
626
|
+
# but primarily ensure "inspect" is the command.
|
|
627
|
+
if len(sys.argv) > 1 and sys.argv[1] not in ("-h", "--help", "--version"):
|
|
628
|
+
# If they passed args but no command, insert 'inspect'
|
|
629
|
+
if sys.argv[1] not in ("pull", "check", "inspect"):
|
|
630
|
+
sys.argv.insert(1, "inspect")
|
|
631
|
+
else:
|
|
632
|
+
# Default to 'inspect' if no args or just flags
|
|
633
|
+
sys.argv.insert(1, "inspect")
|
|
634
|
+
|
|
635
|
+
return main()
|
|
636
|
+
|
|
637
|
+
|
|
622
638
|
if __name__ == "__main__":
|
|
623
639
|
sys.exit(main())
|