#!/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' {inner} ' f" |