Skip to content

feat: complete TextMate Extensions rendering layer#112

Merged
SSobol77 merged 5 commits into
mainfrom
issue/101-textmate-grammar-catalog-language-detection
Jun 21, 2026
Merged

feat: complete TextMate Extensions rendering layer#112
SSobol77 merged 5 commits into
mainfrom
issue/101-textmate-grammar-catalog-language-detection

Conversation

@SSobol77

@SSobol77 SSobol77 commented Jun 21, 2026

Copy link
Copy Markdown
Owner

Summary

This PR brings the completed TextMate Extensions rendering layer into main.

The original #101 PR already merged the grammar catalog and language detection baseline. After that, #102 was stacked on top of #101 and merged into the restored #101 branch. This PR brings the remaining #102 work into main.

What changed

  • Added extension-backed TextMate syntax service.
  • Added extension-backed theme registry.
  • Added stable theme numbering contract and migration behavior.
  • Preserved legacy ECLI/PySH themes as compatibility themes.
  • Implemented viewport-first bounded rendering with tokenizer budgets and caches.
  • Fixed large-file scrolling freezes on Makefile and logs.
  • Added multiline comment/string protection for Python, JavaScript, TypeScript, HTML, and CSS.
  • Prevented log and ignore files from resolving as SQL or Transact-SQL.
  • Documented TextMate, onigurumacffi, and Oniguruma requirements.
  • Added real rendering, performance, PTY, dependency, config, theme-numbering, and multiline acceptance tests.
  • Kept imported upstream extension assets unchanged.

Manual validation

Manual validation was performed in uv run ecli.

Confirmed:

  • multiline comments now render correctly in Python, JavaScript, TypeScript, HTML, and CSS
  • Makefile scrolling no longer freezes the terminal
  • logs and ignore files do not resolve as SQL or Transact-SQL
  • TextMate/theme rendering works visually

Validation

Validated locally with:

  • uv run ruff check src tests
  • uv run ruff format --check src tests
  • uv run python scripts/check_runtime_imports.py
  • uv run mypy src/ecli/extensions/ecli_integration
  • uv run pytest -q tests/extensions tests/packaging tests/docs tests/core/test_config_loading.py tests/core/test_syntax_highlighting_toggle.py tests/ui/test_terminal_panel_reservation.py tests/ui/test_pysh_console_panel.py tests/ui/test_pysh_console_panel_keybindings.py
  • uv run pytest -q tests/extensions/test_textmate_tokenization.py tests/extensions/test_theme_bridge_priority.py tests/extensions/test_editor_syntax_rendering.py tests/extensions/test_textmate_render_performance.py tests/extensions/test_textmate_tokenizer_budget.py tests/extensions/test_textmate_render_regressions.py tests/extensions/test_textmate_scroll_regression.py tests/extensions/test_textmate_multiline_protection.py tests/ui/test_textmate_scroll_pty_smoke.py

Observed:

  • main validation suite: 713 passed
  • focused TextMate/performance/multiline suite: 79 passed
  • ruff passed
  • format check passed
  • runtime import check passed
  • mypy passed
  • imported upstream extension check passed with no upstream extension assets modified

Scope boundaries

Not changed:

  • F11 PySH Console Panel behavior
  • future F4 Diagnostics / Linter Panel
  • future F7 AI Code Assistant
  • VMLab / QEMU / QMP
  • imported upstream extension assets
  • VS Code extension host runtime
  • Node/TypeScript activation
  • Copilot runtime
  • package.json script execution
  • generic PTY terminal emulator scope

Follow-up

After this PR is merged, continue with the next Extensions-layer milestone:

  1. F4 Diagnostics / Linter Panel
  2. F7 AI Code Assistant as extensions layer
  3. plugin layer for new themes, linters, and AI extensions

Summary by CodeRabbit

  • New Features
    • Enabled TextMate-based syntax highlighting as the default, with viewport-aware rendering and improved multiline comment/string protection.
    • Added optional, safer TextMate tokenization with graceful fallback when native dependencies are unavailable.
    • Expanded AI assistant provider support: DeepSeek, Qwen, and Kimi.
    • Introduced a stable numeric theme system with extended professional themes and compatibility mappings.
  • Documentation
    • Updated installation/build guidance for TextMate dependencies (including Oniguruma).
    • Documented theme numbering policy, config migration behavior, and fallback rules.

SSobol77 added 2 commits June 21, 2026 20:58
- add extension-backed TextMate tokenization and theme registry
- define stable theme numbering contract and migration behavior
- preserve legacy ECLI/PySH themes as compatibility themes
- implement viewport-first bounded rendering with tokenizer budgets and caches
- fix large-file scrolling freezes on Makefile and logs
- protect multiline comments and strings across Python, JavaScript, TypeScript, HTML, and CSS
- prevent log and ignore files from resolving as SQL or Transact-SQL
- document TextMate, onigurumacffi, and Oniguruma packaging requirements
- add real rendering, performance, PTY, config, and multiline acceptance tests
- keep imported upstream extension assets unchanged
…ax-service-editor-rendering

feat: stabilize TextMate syntax rendering

* add extension-backed TextMate tokenization and theme registry
* define stable theme numbering contract and migration behavior
* preserve legacy ECLI/PySH themes as compatibility themes
* implement viewport-first bounded rendering with tokenizer budgets and caches
* fix large-file scrolling freezes on Makefile and logs
* protect multiline comments and strings across Python, JavaScript, TypeScript, HTML, and CSS
* prevent log and ignore files from resolving as SQL or Transact-SQL
* document TextMate, onigurumacffi, and Oniguruma packaging requirements
* add real rendering, performance, PTY, config, theme-numbering, dependency, and multiline acceptance tests
* keep imported upstream extension assets unchanged
@coderabbitai

coderabbitai Bot commented Jun 21, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

Pull request was closed or merged during review

📝 Walkthrough

Walkthrough

Implements end-to-end TextMate syntax highlighting (issue #102): adds a wall-clock-bounded tokenizer with grammar quarantine, a scope-to-category bridge, a JSONC theme registry with numeric numbering, a syntax service with multiline protected ranges, and editor integration in Ecli.py. Overhauls the theme system with extension-backed palettes and config migration that strips obsolete TOML tables. Adds DeepSeek, Qwen, and Kimi AI providers.

Changes

TextMate Syntax Engine, Theme System, and Config Migration

Layer / File(s) Summary
Docs, audit, and release contract updates
README.md, AGENTS.md, CODEX.md, .codex/PIPELINE.md, audit-report.md, docs/INSTALL.md, docs/architecture/extensions-layer.md, docs/config/config-*.md, docs/contributor/build-from-source.md, docs/release/*.md, tests/docs/test_textmate_dependency_contract.py
Adds TextMate dependency and theme numbering sections across all user-facing docs; defines Theme Numbering Contract in architecture docs; adds multiline protection addendum to audit report; adds maintainer priority order to AGENTS.md/CODEX.md/PIPELINE.md; tests enforce doc-contract presence for Python and Oniguruma.
Dependency, config defaults, and extension config acceptance
pyproject.toml, config.toml, src/ecli/services/config_service.py, src/ecli/extensions/ecli_integration/config.py, src/ecli/extensions/ecli_integration/__init__.py, src/ecli/utils/utils.py
Adds python-textmate>=0.2.0 dependency; updates config.toml theme to 207 and syntax_engine to "extension"; updates DEFAULT_CONFIG and _load_toml_file; changes _read_syntax_engine to accept "extension" directly; expands __init__.py to re-export all new syntax/theme/tokenizer symbols; updates AI model defaults.
Language detection fallbacks and theme contribution metadata
src/ecli/extensions/ecli_integration/language_detection.py, src/ecli/extensions/ecli_integration/manifest.py, src/ecli/extensions/ecli_integration/registry.py, tests/extensions/test_extension_language_detection.py, tests/extensions/test_extension_manifest_registry.py
Adds _REQUIRED_FALLBACK_EXTENSIONS mapping and dotfile-specific lookup tier in LanguageDetector; adds ThemeContribution dataclass and _parse_themes to manifest.py; extends ExtensionRegistry with list_themes/find_theme_by_id; tests expand representative filename cases, add gitignore/log/YAML contract tests, and validate theme path safety.
TextMate tokenizer: SIGALRM budget and grammar quarantine
src/ecli/extensions/ecli_integration/textmate_tokenizer.py, tests/extensions/test_textmate_tokenizer_budget.py
New textmate_tokenizer.py: wraps optional python-textmate engine with SIGALRM wall-clock budget, adaptive per-grammar quarantine after distinct-timeout-line threshold, bounded _warn_once diagnostics, UI-safe stdout/stderr suppression, and LRU-cached load_tokenizer. Tests cover per-line timing, catastrophic ifeq input, quarantine activation, and distinct-line deduplication.
Theme bridge scope mapping and JSONC theme registry
src/ecli/extensions/ecli_integration/theme_bridge.py, src/ecli/extensions/ecli_integration/theme_registry.py, tests/extensions/test_theme_bridge_priority.py, tests/extensions/test_extension_theme_registry.py, tests/extensions/test_theme_numbering_contract.py
New theme_bridge.py: CATEGORIES, _SCOPE_RULES priority table, scope_to_category, and tokens_to_spans with protected-range override. New theme_registry.py: JSONC stripping/include-chain resolution, TextMateTokenColor/ExtensionTheme/ThemeRegistry dataclasses, deterministic numeric assignment via TARGET_THEME_NUMBERS, and cached_theme_registry. Tests cover scope priority, protected-range overpainting, numbering policy bands, and no-execution constraint.
Theme utility overhaul and config migration
src/ecli/utils/themes.py, src/ecli/utils/utils.py, src/ecli/core/Ecli.py (init_colors), tests/core/test_theme_system.py, tests/core/test_config_loading.py
Rewrites themes.py: new ThemeId compatibility enum (181–382), DEFAULT_THEME_ID=207, ThemePalette.diagnostics, find_theme/resolve_theme(current_theme) with extension-backed _extension_theme_to_palette. Adds migrate_obsolete_config_tables in utils.py with pre-textmate.bak and pre-extension-theme-numbering.bak backups. Updates init_colors to pass active_theme into resolve_theme and surface diagnostics.
Syntax service: resolution, multiline protection, and LineHighlighter
src/ecli/extensions/ecli_integration/syntax_service.py, tests/extensions/test_extension_syntax_service.py, tests/extensions/test_textmate_tokenization.py, tests/extensions/test_textmate_multiline_protection.py, tests/extensions/test_no_fake_textmate_support.py
New syntax_service.py: SyntaxResolution dataclass, SyntaxService.resolve() for per-file language/grammar/engine selection, LineHighlighter with LRU span cache and multiline protected-range computation (Python tokenize, C-like/JS scanner, HTML <!-- -->), and build_syntax_service with process-wide catalog/detector caching. Tests cover representative resolution, fallback, determinism, immutability, no-runtime-execution constraint, and multiline protection per language.
Editor integration: extension rendering path and SQL suppression
src/ecli/core/Ecli.py, tests/extensions/test_editor_syntax_adapter.py, tests/extensions/test_editor_syntax_rendering.py, tests/extensions/test_textmate_render_performance.py, tests/extensions/test_textmate_scroll_regression.py, tests/ui/test_textmate_scroll_pty_smoke.py, tests/ui/test_design_system.py, tests/ui/test_professional_chrome.py, .github/workflows/macos-*.yml, scripts/build_and_package_macos.py, tests/packaging/test_*.py
Adds modified property with _buffer_edit_revision; initializes extension_syntax/_extension_highlighter; adds _resolve_extension_syntax_metadata, _apply_extension_highlighting with line-by-line legacy fallback, SQL-content suppression via _is_plain_operational_file/_is_non_sql_filename, and extension fast path in apply_syntax_highlighting_with_pygments. Tests cover adapter metadata, engine-selection rendering, retokenization guard, cache bounding, PTY scroll smoke test. macOS workflows and build script add Oniguruma prerequisite/env wiring.

AI Provider Expansion

Layer / File(s) Summary
OpenAI-compatible AI client base and three new provider subclasses
src/ecli/integrations/AI.py, config.toml (ai.models), src/ecli/core/Ecli.py (provider menu)
Adds OpenAICompatibleClient with async ask_async/error handling; adds DeepSeekClient, QwenClient, KimiClient subclasses; extends get_ai_client factory and _api_key_env_var; adds provider menu entries in select_ai_provider_and_ask; updates DEFAULT_CONFIG with new provider model defaults.

Sequence Diagram(s)

sequenceDiagram
    participant Ecli
    participant SyntaxService
    participant TextMateTokenizer
    participant LineHighlighter
    participant theme_bridge

    Ecli->>SyntaxService: resolve(filename)
    SyntaxService-->>Ecli: SyntaxResolution (language_id, scope_name, fallback_to_legacy)
    Ecli->>SyntaxService: build_line_highlighter(filename)
    SyntaxService->>TextMateTokenizer: load_tokenizer(grammar_path)
    TextMateTokenizer-->>SyntaxService: TextMateTokenizer or None
    SyntaxService-->>Ecli: LineHighlighter with protected ranges
    Ecli->>LineHighlighter: highlight_lines(viewport)
    LineHighlighter->>TextMateTokenizer: tokenize_line(line) [SIGALRM budget]
    TextMateTokenizer-->>LineHighlighter: [(scope, start, end)] or None
    LineHighlighter->>theme_bridge: tokens_to_spans(tokens, protected_ranges)
    theme_bridge-->>LineHighlighter: [(text, category)] spans
    LineHighlighter-->>Ecli: list[list[LineSpan] | None]
    Note over Ecli: Lines where highlighter returns None fall back to legacy Pygments tokenization
Loading

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

Possibly related issues

  • feat: connect extension-backed syntax service to editor rendering #102: This PR directly implements issue #102 — adds SyntaxService, TextMateTokenizer, theme_bridge.py, theme_registry.py, and integrates extension-backed TextMate rendering into Ecli.py with multiline protection, deterministic fallback to legacy highlighting when tokenizer unavailable, and comprehensive test coverage for syntax selection and bounded tokenization.

Possibly related PRs

  • SSobol77/ecli#110: This PR evolves the extensions-layer TextMate integration started in #110, specifically extending language_detection.py fallback mappings, adding ThemeContribution parsing to manifests, and flipping [extensions].syntax_engine from "legacy" to "extension" as the default.
  • SSobol77/ecli#87: Shares code-level overlap in config.toml mouse/syntax_highlighting settings, Ecli.py theme initialization/rendering updates, and terminal UI behavior changes introduced in both PRs.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 31.04% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: complete TextMate Extensions rendering layer' accurately and concisely summarizes the main change: completing the TextMate Extensions rendering implementation for syntax highlighting.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch issue/101-textmate-grammar-catalog-language-detection

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 11

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/ecli/core/Ecli.py`:
- Around line 1933-1937: The _is_non_sql_filename method currently returns True
when filename is None, which incorrectly suppresses SQL syntax highlighting
guessing for unnamed buffers. Modify the logic so that it only returns True when
filename is not None AND the filename does not end with .sql. This way, missing
filenames will be treated as unknown (returning False) and allow Pygments to
guess the language from content, while named non-SQL files will still be
correctly identified as non-SQL (returning True).
- Around line 1827-1884: The _apply_extension_highlighting method is too complex
(SonarCloud reports complexity 18 > 15) and needs to be refactored. Extract the
highlighter invocation logic (both the highlight_lines and individual highlight
code paths with their exception handling) into a separate helper method that
returns the highlighted_lines list. Then extract the per-line processing logic
(the for loop that validates spans, handles fallback tokenization via
_get_tokenized_line, and performs color mapping) into another helper method.
This will reduce the cyclomatic complexity of _apply_extension_highlighting
while preserving all the current behavior for exception recovery, span
validation, and fallback rendering.

In `@src/ecli/extensions/ecli_integration/syntax_service.py`:
- Around line 260-261: Remove the unused variable assignments for start_col and
end_col that are extracted from tok.end. These variables are assigned but never
referenced anywhere in the function, which is causing the Ruff linter to fail.
Simply delete both assignment statements or, if only start_row and start_col are
needed, remove the second line that unpacks tok.end into end_row and end_col.

In `@src/ecli/extensions/ecli_integration/textmate_tokenizer.py`:
- Around line 48-60: Fix the import ordering in the imports section at the
beginning of textmate_tokenizer.py by ensuring all standard library imports are
grouped together at the top. Currently, the imports io and json appear after the
from typing import statement and should be moved up to be grouped with the other
standard library imports like contextlib, logging, os, signal, threading, and
the from imports. Additionally, address the exception naming violation
referenced at line 130 by ensuring any custom exception or exception variable
naming follows Ruff's naming conventions and repository standards for exception
handling.

In `@src/ecli/extensions/ecli_integration/theme_bridge.py`:
- Around line 273-282: The span coalescing loop that processes character
sequences by category is using string concatenation with the += operator inside
the loop (at line 277 where current_text += line[index]), which causes O(n²)
performance on long same-category runs. Replace the string concatenation
approach with a list-based accumulator that collects the individual line
elements, then join them into a single string only when appending to the spans
list (when the category changes or at the end of iteration). This will reduce
the time complexity from O(n²) to O(n) by avoiding repeated string object
creation.

In `@src/ecli/extensions/ecli_integration/theme_registry.py`:
- Around line 248-280: The _strip_trailing_commas function exceeds the allowed
complexity threshold and needs refactoring through decomposition. Extract the
string mode handling logic (the in_string conditional block and the character
checking for quote characters) into a separate helper function, and extract the
comma lookahead detection logic (the lookahead while loop and the check for
closing brackets) into another helper function. This will break the main loop
into simpler, more focused operations while preserving the original
functionality of skipping trailing commas outside of string literals.
- Around line 205-245: The _strip_json_comments function has excessive
cyclomatic complexity due to multiple nested conditional branches handling
different states (string parsing, line comments, block comments). Refactor by
extracting the three main state-handling logic blocks into separate helper
functions: one to handle character logic when inside a string (checking for
escaped characters and quote termination), one to skip line comments starting
with //, and one to skip block comments between /* and */. Have the main loop in
_strip_json_comments call these helpers instead of containing the nested
conditionals, which will reduce complexity while preserving the exact current
behavior.

In `@src/ecli/integrations/AI.py`:
- Around line 919-926: The error handling block where response.status is checked
for non-200 values is logging the full response_text directly to the logger,
which can expose sensitive information like prompt fragments or secrets from the
provider's error payload. Instead of passing response_text directly to the
logger.error call, redact or truncate the response text before logging by
limiting it to a safe length or removing potentially sensitive patterns,
ensuring sensitive content is not exposed in logs while still maintaining enough
context for debugging.

In `@src/ecli/utils/utils.py`:
- Around line 541-545: The warning message in the logger.warning call for the
legacy theme table configuration contains duplicated wording that reads
awkwardly as "Set a root-level a valid root-level...". Remove the first
occurrence of "a root-level " in the message string so it correctly reads "Set a
valid root-level..." to provide clear and grammatically correct remediation
guidance to the user.
- Around line 564-567: The `toml.load()` method in the `_load_toml_file`
function does not accept `pathlib.Path` objects directly; it requires a string
path. Modify the `toml.load(path)` call to convert the path parameter to a
string using `str(path)` before passing it to the function. This ensures
compatibility with the toml package and prevents runtime TypeErrors that would
cause the function to fall back to default configuration values.

In `@tests/docs/test_textmate_dependency_contract.py`:
- Around line 34-38: The _read function currently uses pytest.skip() when a
required document file is missing, which masks contract regressions when docs
are deleted or renamed. Replace the pytest.skip() call with pytest.fail() or
raise an exception (such as FileNotFoundError) when the file does not exist, so
that the test fails fast and makes it immediately apparent that a required
document is missing rather than silently skipping the test.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 5fdd525f-9f2a-499d-9e86-7789d9fe1ebf

📥 Commits

Reviewing files that changed from the base of the PR and between f4e1583 and 3330f57.

📒 Files selected for processing (52)
  • .codex/PIPELINE.md
  • AGENTS.md
  • CODEX.md
  • README.md
  • audit-report.md
  • config.toml
  • docs/INSTALL.md
  • docs/architecture/extensions-layer.md
  • docs/config/config-precedence.md
  • docs/config/config-schema.md
  • docs/contributor/build-from-source.md
  • docs/release/packaging-flows.md
  • docs/release/release-checklist.md
  • pyproject.toml
  • src/ecli/core/Ecli.py
  • src/ecli/extensions/ecli_integration/__init__.py
  • src/ecli/extensions/ecli_integration/config.py
  • src/ecli/extensions/ecli_integration/grammar_catalog.py
  • src/ecli/extensions/ecli_integration/language_detection.py
  • src/ecli/extensions/ecli_integration/manifest.py
  • src/ecli/extensions/ecli_integration/registry.py
  • src/ecli/extensions/ecli_integration/syntax_service.py
  • src/ecli/extensions/ecli_integration/textmate_tokenizer.py
  • src/ecli/extensions/ecli_integration/theme_bridge.py
  • src/ecli/extensions/ecli_integration/theme_registry.py
  • src/ecli/integrations/AI.py
  • src/ecli/services/config_service.py
  • src/ecli/utils/themes.py
  • src/ecli/utils/utils.py
  • tests/core/test_config_loading.py
  • tests/core/test_theme_system.py
  • tests/docs/test_textmate_dependency_contract.py
  • tests/extensions/test_editor_syntax_adapter.py
  • tests/extensions/test_editor_syntax_rendering.py
  • tests/extensions/test_extension_language_detection.py
  • tests/extensions/test_extension_layer_config.py
  • tests/extensions/test_extension_manifest_registry.py
  • tests/extensions/test_extension_syntax_service.py
  • tests/extensions/test_extension_theme_registry.py
  • tests/extensions/test_no_fake_textmate_support.py
  • tests/extensions/test_textmate_grammar_catalog.py
  • tests/extensions/test_textmate_multiline_protection.py
  • tests/extensions/test_textmate_render_performance.py
  • tests/extensions/test_textmate_render_regressions.py
  • tests/extensions/test_textmate_scroll_regression.py
  • tests/extensions/test_textmate_tokenization.py
  • tests/extensions/test_textmate_tokenizer_budget.py
  • tests/extensions/test_theme_bridge_priority.py
  • tests/extensions/test_theme_numbering_contract.py
  • tests/ui/test_design_system.py
  • tests/ui/test_professional_chrome.py
  • tests/ui/test_textmate_scroll_pty_smoke.py

Comment thread src/ecli/core/Ecli.py
Comment thread src/ecli/core/Ecli.py
Comment thread src/ecli/extensions/ecli_integration/syntax_service.py Outdated
Comment thread src/ecli/extensions/ecli_integration/textmate_tokenizer.py Outdated
Comment thread src/ecli/extensions/ecli_integration/theme_bridge.py Outdated
Comment thread src/ecli/extensions/ecli_integration/theme_registry.py
Comment thread src/ecli/integrations/AI.py
Comment thread src/ecli/utils/utils.py
Comment thread src/ecli/utils/utils.py
Comment thread tests/docs/test_textmate_dependency_contract.py
@SSobol77 SSobol77 merged commit ba063b1 into main Jun 21, 2026
1 of 2 checks passed
@sonarqubecloud

Copy link
Copy Markdown

@SSobol77 SSobol77 deleted the issue/101-textmate-grammar-catalog-language-detection branch June 21, 2026 20:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant