Skip to main content

bslfmt

Детерминированный форматтер структурных отступов BSL. Проект работает как Python-библиотека и CLI; интеграция с MCP 1C будет отдельным потребителем пакета.

Границы

Форматтер приводит отступы и форматирование поддерживаемых операторов, а регистр ключевых слов — к каноническому. Он сохраняет значимые токены (без учёта регистра) и порядок кода, строк, комментариев и директив. Он не проверяет синтаксис BSL и не компилирует модули. Если структурное форматирование небезопасно, команда завершает работу с диагностикой, не перезаписывая источник.

Стиль форматирования

Стиль один, настроек нет. Он следует стандартам 1С «Тексты модулей» (std456) и «Перенос выражений» (std444) и практике типовых конфигураций.

  • Отступы — табуляцией, по вложенности блоков: процедуры и функции, Если/ИначеЕсли/Иначе, циклы, Попытка/Исключение. Английские и смешанные ключевые слова распознаются.
  • С колонки 0 — Процедура/Функция и их концы, аннотации (&НаСервере…), директивы препроцессора (#Область, #Если…, в том числе внутри процедур), переменные и код модуля вне процедур.
  • Строки продолжения многострочной инструкции — +1 отступ к её первой строке. Строка с ведущим И/Или/+/. (а также [, ,, ) или литералом) — продолжение инструкции, как и строка после Новый, Процедура/Функция или И/Или/Не в конце строки; Экспорт на своей строке — часть объявления. ) стоит на уровне строки с открывающей скобкой. Текст запроса сразу после = и после одиночного Возврат — как раньше.
  • Многострочные строки: строки | сдвигаются вместе со строкой, где начался литерал; пробелы перед | не входят в значение строки.
  • Комментарии // встают на отступ следующей строки кода; перед строкой, которая закрывает блок (КонецЕсли, Иначе…) или начинается с ), — на уровень глубже. Комментарий в колонке 0 (маркеры доработок //!, //++, закомментированный код) остаётся в колонке 0. Текст комментариев не меняется.
  • Перенос строк: каждая инструкция — на своей строке (А = 1; Б = 2; → две строки); после Тогда, Цикл, Попытка, Иначе, Исключение тело начинается со следующей строки, а КонецЕсли, КонецЦикла, КонецПопытки, Иначе, ИначеЕсли, Исключение стоят отдельной строкой. Пустая инструкция (Цикл;, Иначе;) остаётся при своём слове, комментарий в конце строки — у последней части.
  • Раскладка по ширине 120: инструкция (в том числе заголовок и объявление), которая с отступом (таб — 4 знака) помещается в 120 знаков, — одна строка; переносы автора внутри неё убираются. Иначе она режется по порядку: Или → И → + (каждая часть на своей строке, оператор в начале) → последняя пара скобок (параметры одной строкой, иначе по одному на строку, ) отдельной строкой; пропущенные параметры — на строке предыдущего); части длиннее 120 режутся так же, рекурсивно. Если резать некуда, инструкция остаётся как была. Комментарий в конце строки в ширину не входит. Не трогаются инструкции с комментарием внутри, многострочным литералом или подряд идущими литералами, директивой, областью правки; литералы не режутся никогда. Внутри строки автора пробелы сохраняются как написаны (Не(А) остаётся Не(А)); на месте бывших переносов действует общее правило (Ф / (А) → Ф(А)). Идентификаторы могут содержать буквы любого алфавита (і, казахские Қ, Ү…): они раскладываются так же.
  • Пробелы: вокруг бинарных операторов (=, <>, +, %…), после запятой; без пробелов перед , ; ) и после (. Лишние пробелы внутри строки схлопываются, хвостовые удаляются; выравнивание табами внутри строки заменяется одним пробелом.
  • Пустые строки: не больше одной подряд. Строки из одних пробелов и табов (так их заполняет конфигуратор) не очищаются.
  • Регистр ключевых слов — как в синтакс-помощнике 1С: или → Или, конецЕсЛи → КонецЕсли, НЕ → Не, NULL → Null. Так же директивы препроцессора и их символы (#если сервер тогда → #Если Сервер Тогда, #область → #Область) и аннотации (&наклиенте → &НаКлиенте). Английские слова остаются английскими (endif → EndIf). Не меняются имена переменных, методов и свойств (Запрос.выполнить()), имена меток и областей, неизвестные аннотации и символы препроцессора. Имя метода, совпадающее с ключевым словом, в объявлении получает его регистр (Процедура выполнить() → Процедура Выполнить()), а в вызове через точку (Об.выполнить()) — нет; на работу кода это не влияет.
  • Методы расширений с &ИзменениеИКонтроль форматируются как обычный код: платформа не сверяет пробелы и табы в контролируемых строках.
  • Не трогаются: строки и даты, текст комментариев, области #Вставка/#Удаление, регистр букв вне ключевых слов, порядок кода.

Установка

Нужен Python 3.10+ или uv — он сам скачает Python. Пакет без зависимостей, одинаков для Windows, macOS и Linux.

uv tool install bslfmt        # команда bslfmt в терминале (рекомендуется)
pipx install bslfmt           # то же через pipx
uvx bslfmt Модуль.bsl         # разовый запуск без установки

Установить uv: Windows — winget install astral-sh.uv (или powershell -c "irm https://astral.sh/uv/install.ps1 | iex"); macOS — brew install uv; macOS и Linux — curl -LsSf https://astral.sh/uv/install.sh | sh. Обновление: uv tool upgrade bslfmt (или pipx upgrade bslfmt).

Для агентов и хуков

Форматировать файл на месте — одна команда, модуль через контекст агента не передаётся:

uvx bslfmt -i Модуль.bsl            # отформатировать файл (uv сам поставит пакет)
uvx bslfmt --check Модуль.bsl       # код выхода 1 — файл нужно отформатировать
uvx bslfmt -i -sbc Модуль.bsl       # и удалить комментарии внутри методов

Если пакет установлен (uv tool install bslfmt), то же без uvx. Вывод — UTF-8; сводка на файл: ФАЙЛ: изменён (строк: N) или ФАЙЛ: без изменений.

Установка для разработки

python -m venv .venv
. .venv/bin/activate
python -m pip install -e .
python -m unittest discover -s tests -v

Команда bslfmt появляется в активном окружении.

CI (GitHub Actions) прогоняет тесты на Windows, macOS и Linux и проверяет установленную команду: python tests/cli_smoke.py после pip install ..

CLI

bslfmt Модуль.bsl                        # результат на экран, файл не меняется
bslfmt -i Модуль.bsl Форма.bsl           # отформатировать файлы на месте
bslfmt --check Модуль.bsl Форма.bsl      # только проверить (для CI и хуков)
bslfmt --check --diff Модуль.bsl         # проверить и показать различия
bslfmt Модуль.bsl --output Новый.bsl     # записать результат в новый файл
bslfmt - < Модуль.bsl                    # стандартный ввод
bslfmt -i -sbc Модуль.bsl                # и удалить комментарии внутри методов
bslfmt --help                            # справка по всем режимам

-i переписывает только файлы, которым нужна правка: запись атомарная (временный файл рядом и замена), при отказе форматирования файл не меняется. Замена создаёт новый файл: права копируются, а владелец, ACL, расширенные атрибуты и жёсткие ссылки — нет. Символическая ссылка остаётся ссылкой, переписывается её цель, даже вне текущего каталога: в CI и хуках по чужому репозиторию передавайте -i только свои файлы. Сводка на каждый файл: ФАЙЛ: изменён (строк: N) или ФАЙЛ: без изменений. Файл только для чтения не переписывается (ошибка, код 2). -- завершает флаги: bslfmt --check -- -файл.bsl. Короткие флаги — только целиком (-s не сокращение -sbc). -sbc, --strip-body-comments (с любым режимом) удаляет строки-комментарии внутри процедур и функций — закомментированный код, маркеры доработок, пояснения. Это же касается строк-комментариев между строками многострочного литерала (//| Поле, в тексте запроса): в значение строки они не входят. Комментарии в конце строки кода, над методами, внутри самого текста строки (|// … — часть запроса: маркеры для СтрЗаменить, разделитель пакета) и в областях #Вставка/#Удаление остаются. Значения строк не меняются — это проверяется при каждом запуске. Без ключа комментарии не удаляются. --check ничего не записывает и перечисляет файлы, которые нужно отформатировать. Несколько файлов — только с -i, --check или --diff; каждый обрабатывается отдельно. --output создаёт новый файл и отказывается перезаписывать существующий.

Ввод и вывод (текст, различия, сводка, ошибки) — UTF-8 на любой ОС; переводы строк и BOM сохраняются как в исходнике. Читаются обычные файлы и каналы (bslfmt <(git show HEAD:Модуль.bsl)) не больше 80 000 000 байт; устройства — нет.

Коды выхода (худший по всем файлам): 0 — успех (при --check — всё отформатировано); 1 — --check нашёл файлы для форматирования; 2 — ошибка аргументов, чтения или записи, неверная кодировка или отказ форматирования (сообщение в stderr с именем файла и номером строки, если он известен); 3 — внутренняя ошибка форматтера.

Python API

from bslfmt import format_code

formatted = format_code(source)

Исключения: FormatError — форматировать небезопасно (отказ, превышен лимит); LexerError — исходник не разбирается (незакрытая строка или дата). Оба — подклассы ValueError и импортируются из bslfmt; номер строки — в атрибуте line.

Для недоверенного ввода есть лимиты: max_chars — длина исходника (по умолчанию 20 000 000 символов), max_depth — вложенность блоков (по умолчанию 100). При превышении — FormatError; None отключает лимит.

formatted = format_code(source, max_chars=1_000_000, max_depth=50)
cleaned = format_code(source, strip_body_comments=True)

Сервису, который принимает код извне, стоит также запускать форматирование в отдельном процессе с ограничением памяти и времени.

Поддерживаемые функции и ограничения уточняются по синтетическим тестам в tests/; локальные корпуса и конфигурации в репозиторий не входят.

Лицензия

Apache License 2.0 — см. LICENSE и NOTICE. Проект не аффилирован с ООО «1С».

Metadata

Release files for bslfmt 0.27.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for bslfmt 0.27.0
File Size Uploaded
bslfmt-0.27.0.tar.gz 93.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for bslfmt 0.27.0
File Interpreter ABI Platform
bslfmt-0.27.0-py3-none-any.whl Python 3 none any Details

Total release size: 157.6 kB

Release files / bslfmt-0.27.0.tar.gz

Download URL bslfmt-0.27.0.tar.gz
Size 93.9 kB
Tags Source
SHA-256 checksum
How to use checksums
43138eede94b28a92a39932f3943cb2924ebc06ae559dd108c0ae935a1835ec6
BLAKE2b-256 checksum
How to use checksums
dad04f9d59f8fe92017a4464728aea3d2d0d7a9d6480c9ce0dfaaecd054f3ae1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 2, 2026.

Transparency log

Release files / bslfmt-0.27.0-py3-none-any.whl

Download URL bslfmt-0.27.0-py3-none-any.whl
Size 63.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
28a7b5e877a0dcc799ea95b8b1834a065310d582ad1653717f3c0effa909bfea
BLAKE2b-256 checksum
How to use checksums
14f423b907c24911f1eefc9873d2880606349da657c6a554ceac88db85f1a85b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 2, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.27.0 This release

2 release files

0.23.0

2 release files

0.21.0

2 release files

0.20.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page