#!/usr/bin/env python3 """ e4_code_format.py — Генератор HTML-таблицы с подсветкой кода 1С в стиле встроенной справки 1С:Предприятие Результат копируется в буфер обмена и сохраняется в файл. """ # ═══════════════════════════════════════════════════════════════ # ВВЕДИТЕ КОД 1С ЗДЕСЬ: # ═══════════════════════════════════════════════════════════════ CODE_1C = """\ // Пример чтения JSON &НаСервере Процедура ЗагрузкаНаСервере(Путь) Чтение = Новый ЧтениеJSON; Чтение.ОткрытьФайл(Путь); Данные = ПрочитатьJSON(Чтение); Чтение.Закрыть(); Количество = 0; Для Каждого Товар Из Данные Цикл Ссылка = Справочники.ЗагрузкаТоваров.НайтиПоКоду(Товар.id); Элемент = ?(Ссылка.Пустая(), Справочники.ЗагрузкаТоваров.СоздатьЭлемент(), Ссылка.ПолучитьОбъект()); Элемент.Код = Товар.article; Элемент.Наименование = Товар.name; Элемент.Цена = Товар.price; Элемент.Цвет = Товар.color; Элемент.Записать(); Количество = Количество + 1; КонецЦикла; Сообщить("Загружено " + Количество); КонецПроцедуры &НаКлиенте Асинх Процедура Загрузка(Команда) Диалог = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Открытие); Диалог.Фильтр = "ДжейсонСтетхэм (*.json) | *.json"; Если Ждать Диалог.ВыбратьАсинх() Тогда ЗагрузкаНаСервере(Диалог.ПолноеИмяФайла); КонецЕсли; КонецПроцедуры """ # ═══════════════════════════════════════════════════════════════ # Словари ключевых слов # ═══════════════════════════════════════════════════════════════ KEYWORDS = { # Русские "Если", "Тогда", "ИначеЕсли", "Иначе", "КонецЕсли", "Для", "Каждого", "Из", "По", "Цикл", "КонецЦикла", "Пока", "Процедура", "КонецПроцедуры", "Функция", "КонецФункции", "Перем", "Возврат", "Продолжить", "Прервать", "И", "Или", "Не", "Попытка", "Исключение", "КонецПопытки", "ВызватьИсключение", "Новый", "Выполнить", "Знач", "Экспорт", "Истина", "Ложь", "Неопределено", "NULL", # Английские "If", "Then", "ElsIf", "Else", "EndIf", "For", "Each", "In", "To", "Do", "EndDo", "While", "Procedure", "EndProcedure", "Function", "EndFunction", "Var", "Return", "Continue", "Break", "And", "Or", "Not", "Try", "Except", "EndTry", "Raise", "New", "Execute", "Val", "Export", "True", "False", "Undefined", } CONTEXT_DIRECTIVES = { "&НаКлиенте", "&НаСервере", "&НаКлиентеНаСервере", "&НаСервереБезКонтекста", "&AtClient", "&AtServer", "&AtClientAtServer", "&AtServerNoContext", } COLORS = { "keyword": "#ff0000", "string": "#000000", "comment": "#008000", "operator": "#ff0000", "identifier": "#0000ff", "number": "#000000", "directive": "#ff0000", "context": "#884422", } OPERATORS = set("=+-*/<>().,;[]%?") # ═══════════════════════════════════════════════════════════════ # Лексер # ═══════════════════════════════════════════════════════════════ def tokenize(code): tokens = [] i = 0 n = len(code) while i < n: ch = code[i] # Перенос строки if ch == "\r": tokens.append(("newline", "\n")) i += 2 if i + 1 < n and code[i + 1] == "\n" else 1 continue if ch == "\n": tokens.append(("newline", "\n")) i += 1 continue # Пробелы if ch in " \t": j = i while j < n and code[j] in " \t": j += 1 tokens.append(("space", code[i:j])) i = j continue # Комментарий // if ch == "/" and i + 1 < n and code[i + 1] == "/": j = i while j < n and code[j] != "\n": j += 1 tokens.append(("comment", code[i:j])) i = j continue # Строка "..." if ch == '"': j = i + 1 while j < n: if code[j] == '"': if j + 1 < n and code[j + 1] == '"': j += 2 else: j += 1 break else: j += 1 tokens.append(("string", code[i:j])) i = j continue # Число if ch.isdigit(): j = i while j < n and (code[j].isdigit() or code[j] == "."): j += 1 tokens.append(("number", code[i:j])) i = j continue # Операторы if ch in OPERATORS: if ch == "<" and i + 1 < n and code[i + 1] == ">": tokens.append(("operator", "<>")) i += 2 continue if ch in "<>" and i + 1 < n and code[i + 1] == "=": tokens.append(("operator", code[i : i + 2])) i += 2 continue tokens.append(("operator", ch)) i += 1 continue # Контекстная директива &НаКлиенте if ch == "&": j = i while j < n and ( code[j].isalnum() or code[j] in {"_", "&"} or ord(code[j]) > 127 ): j += 1 word = code[i:j] if word in CONTEXT_DIRECTIVES: tokens.append(("context", word)) else: tokens.append(("identifier", word)) i = j continue # Директива # if ch == "#": j = i while j < n and code[j] not in "\r\n": j += 1 tokens.append(("directive", code[i:j])) i = j continue # Идентификатор / ключевое слово if ch.isalpha() or ch == "_" or ord(ch) > 127: j = i while j < n and (code[j].isalnum() or code[j] == "_" or ord(code[j]) > 127): j += 1 word = code[i:j] tokens.append(("keyword" if word in KEYWORDS else "identifier", word)) i = j continue tokens.append(("other", ch)) i += 1 return tokens # ═══════════════════════════════════════════════════════════════ # Генератор HTML # ═══════════════════════════════════════════════════════════════ def escape(text): return text.replace("&", "&").replace("<", "<").replace(">", ">") def nbsp(text): return text.replace(" ", " ") def token_html(typ, text): if typ == "newline": return "
" if typ == "space": return nbsp(escape(text)) e = nbsp(escape(text)) color = COLORS.get(typ) return f'{e}' if color else e def generate(code): tokens = tokenize(code) inner = "".join(token_html(t, v) for t, v in tokens) return ( f'

Пример:

' f'' f"
" f' {inner}
' f"
" ) # ═══════════════════════════════════════════════════════════════ # Запуск # ═══════════════════════════════════════════════════════════════ if __name__ == "__main__": code = CODE_1C.strip() result = generate(code) # Сохраняем результат with open("result_code.html", "w", encoding="utf-8") as f: f.write(result) # Сохраняем предпросмотр preview = ( '' "Предпросмотр" f"

Предпросмотр:

{result}" f'

HTML:

" ) with open("preview_code.html", "w", encoding="utf-8") as f: f.write(preview) # Копируем в буфер обмена try: import subprocess subprocess.run("clip", input=result.encode("utf-8"), check=True, shell=True) print("HTML скопирован в буфер обмена!") except Exception: pass print(f"Сохранено: result_code.html") print(f"Предпросмотр: preview_code.html") print(f"\nHTML ({len(result)} символов):") print(result[:200] + "...")