Перем мЛеваяСкобкаПараметра;
Перем мПраваяСкобкаПараметра;
Перем ВремИмяПараметра;
Перем мТекущаяСтрокаПараметра;
Перем мИмяОткрытогоФайла;
Перем мРасширениеФайла;
Перем мСтароеИмяПараметра;
Перем мОписаниеРасширенияФайла;
Перем мПлатформа;
Перем РегВычислитель;
Перем РегВычислительЛокальный;
Перем шИмя;
Перем мСтарыйПроверочныйТекст;
Перем мСтруктураВосстановления;
Перем мРежимРедактора Экспорт;
Перем мНачальноеКоличествоКолонок;
Перем мОлеСервер;
Перем мИсторияФайлов; 
Перем мПолеТекстаПоиска;
Перем мПоследняяПозицияПодсказки;

Функция СохраняемаяНастройкаФормы(выхНаименование, выхИменаСвойств) Экспорт 
	выхИменаСвойств = "Форма.АвтообновлениеПроверочногоТекста, Форма.Автовыделение, Форма.ПереносСлов, Форма.ИменаГруппВместоИндексов";
	Возврат Неопределено;
КонецФункции

Процедура ОсновныеДействияФормыСохранитьНастройки(Кнопка)
	
	ирКлиент.ВыбратьИСохранитьНастройкуФормыЛкс(ЭтаФорма);
	
КонецПроцедуры

Процедура ОсновныеДействияФормыЗагрузитьНастройки(Кнопка)
	
	ирКлиент.ВыбратьИЗагрузитьНастройкуФормыЛкс(ЭтаФорма);

КонецПроцедуры

Процедура ПриОткрытии()
	
	ирКлиент.Форма_ПриОткрытииЛкс(ЭтаФорма);
	КлсКомандаНажатие(ЭлементыФормы.КП_Вхождения.Кнопки.Идентификаторы);
	КлсКомандаНажатие(ЭлементыФормы.КП_Вхождения.Кнопки.Идентификаторы);
	мПолеТекстаПоиска = ирКлиент.ОболочкаПоляТекстаЛкс(ЭлементыФормы.ПроверочныйТекст);
	ТаблицаИзМакета = ирОбщий.ТаблицаЗначенийИзТабличногоДокументаЛкс(ПолучитьМакет("ДоступныеЭлементы"));
	ДоступныеЭлементы.Загрузить(ТаблицаИзМакета);
	Если ТипЗнч(ВладелецФормы) = Тип("Форма") Тогда
		ВладелецФормы.Панель.Доступность = Ложь;
	КонецЕсли;
	Если Ложь
		Или мРежимРедактора 
		Или ЗначениеЗаполнено(ПараметрВыражение) 
		Или ЗначениеЗаполнено(ПараметрПроверочныйТекст) 
	Тогда
		Если мРежимРедактора Тогда
			ЭтаФорма.РежимВыбора = Истина;
		КонецЕсли;
		СоздатьФайл();
		ЭтаФорма.Выражение = ПараметрВыражение;
		ЭлементыФормы.ПолеТекстаВыражения.Значение = ПараметрВыражение;
		Если ПараметрПроверочныйТекст <> Неопределено Тогда
			#Если Сервер И Не Сервер Тогда
				УстановитьПроверочныйТекстОтложенно();
			#КонецЕсли
			ПодключитьОбработчикОжидания("УстановитьПроверочныйТекстОтложенно", 0.1, Истина);
		КонецЕсли; 
	Иначе
		ОписаниеФайлаВосстановления = Новый Структура;
		ИмяФайлаВосстановления = ирКлиент.ПроверитьВыбратьФайлВосстановленияКонсолиЛкс(мСтруктураВосстановления, ОписаниеФайлаВосстановления, ПараметрИмяФайлаВосстановления);
		Если ИмяФайлаВосстановления <> "" Тогда
			мИмяОткрытогоФайла = ИмяФайлаВосстановления;
			АвтообновлениеПроверочногоТекста = Ложь;
		Иначе
			// Попытаемся загрузить последний открывавшийся файл
			мИмяОткрытогоФайла = ирОбщий.ВосстановитьЗначениеЛкс(Метаданные().Имя + "_ИмяФайла");
			Если мИмяОткрытогоФайла = НеОпределено Тогда
				мИмяОткрытогоФайла = "";
			КонецЕсли;
		КонецЕсли;
		Если ПустаяСтрока(мИмяОткрытогоФайла) Тогда
			СоздатьФайл();
		Иначе
			ЗагрузитьИзФайла();
		КонецЕсли;
		Если ИмяФайлаВосстановления <> "" Тогда
			ЭтаФорма.Модифицированность = Истина;
			мИмяОткрытогоФайла = ирКлиент.ПослеВосстановленияФайлаКонсолиЛкс(ОписаниеФайлаВосстановления);
		КонецЕсли; 
		Кнопки = ЭлементыФормы.ДействияФормы.Кнопки;
		Кнопки.Удалить(Кнопки.Применить);
	КонецЕсли; 
	ЭлементыФормы.Параметры.ОтборСтрок.ЭтоВариант.Установить(Ложь);
	мИсторияФайлов = ирОбщий.ВосстановитьЗначениеЛкс(Метаданные().Имя + "_ИсторияФайлов");
	Если мИсторияФайлов = Неопределено Тогда
		мИсторияФайлов = Новый СписокЗначений;
	КонецЕсли;
	#Если Сервер И Не Сервер Тогда
		РегВычислитель = Обработки.ирОболочкаРегВыражение.Создать();
	#КонецЕсли
	ОбновитьПодменюИсторииФайлов();
	ОбновитьПодсказкуДоступногоЭлемента();
	
	// Для теста
	//ирОбщий.СообщитьЛкс(1,, Истина);
	//_список = Новый СписокЗначений;
	//_список.Добавить(1);
	//_список.ВыбратьЭлемент();

КонецПроцедуры  

Процедура УстановитьПроверочныйТекстОтложенно()
	
	УстановитьПроверочныйТекст(ПараметрПроверочныйТекст);
	ОбновитьВыражениеПараметра();
	ЭтаФорма.Модифицированность = Ложь;

КонецПроцедуры

Функция СоздатьФайл()
	
	мИмяОткрытогоФайла = "";
	ОчиститьПараметры();
	ЭлементыФормы.ПроверочныйТекст.УстановитьТекст("");
	мСтарыйПроверочныйТекст = "";
	ДобавитьПервуюСтроку();
	УстановитьТекущуюСтрокуПараметра();
	ЭтаФорма.ИгнорироватьРегистр = Истина;
	ЭтаФорма.Многострочный = Ложь;
	ЭтаФорма.Модифицированность = Ложь;

КонецФункции

Процедура ДобавитьПервуюСтроку()
	
	СтрокаПараметра = Параметры.Добавить();
	СтрокаПараметра.Имя = "Корень";
	ОбновитьИмяВНижнемРегистре(СтрокаПараметра);

КонецПроцедуры

Процедура ОбновитьИмяВНижнемРегистре(Знач СтрокаПараметра = Неопределено)
	
	Если СтрокаПараметра = Неопределено Тогда
		СтрокаПараметра = ЭлементыФормы.Параметры.ТекущаяСтрока;
	КонецЕсли; 
	СтрокаПараметра.НИмя = НРег(СтрокаПараметра.Имя);

КонецПроцедуры

Процедура ПриЗакрытии()
	
	ирКлиент.Форма_ПриЗакрытииЛкс(ЭтаФорма);
	ирКлиент.УдалитьФайлВосстановленияКонсолиСБлокировкойЛкс(мСтруктураВосстановления);
	СохранитьИмяФайла();
	Если ТипЗнч(ВладелецФормы) = Тип("Форма") Тогда
		ВладелецФормы.Панель.Доступность = Истина;
	КонецЕсли;
	
КонецПроцедуры

Функция СохранитьВФайл(ЗапрашиватьСохранение = Ложь, ЗапрашиватьИмяФайла = Ложь, Знач ИмяФайла = Неопределено, СброситьМодифицированность = Истина)

	Если ИмяФайла = Неопределено Тогда
		ИмяФайла = мИмяОткрытогоФайла;
	КонецЕсли; 
	Если СброситьМодифицированность Тогда
		ОбновитьВыражениеПараметра();
	КонецЕсли; 
	Если Не ЗапрашиватьИмяФайла Тогда
		Если ЗапрашиватьСохранение Тогда
			Если Не Модифицированность Тогда
				Возврат Истина;
			Иначе
				Ответ = Вопрос("Сохранить текущий файл?", РежимДиалогаВопрос.ДаНетОтмена);
				Если Ответ = КодВозвратаДиалога.Отмена Тогда
					Возврат Ложь;
				ИначеЕсли Ответ = КодВозвратаДиалога.Нет Тогда
					Возврат Истина;
				КонецЕсли;
			КонецЕсли;
		КонецЕсли; 
	КонецЕсли;
	СохраняемыеДанные = Новый Структура;
	СохраняемыеДанные.Вставить("Параметры", Параметры.Выгрузить());
	СохраняемыеДанные.Вставить("ПроверочныйТекст", ЭлементыФормы.ПроверочныйТекст.ПолучитьТекст());
	СохраняемыеДанные.Вставить("Многострочный", Многострочный);
	СохраняемыеДанные.Вставить("ИгнорироватьРегистр", ИгнорироватьРегистр);
	СохраняемыеДанные.Вставить("ШаблонЗамены", ШаблонЗамены);
	СохраняемыеДанные.Вставить("ДвижокВычислителя", ДвижокВычислителя);
	//ирОбщий.СохранитьЗначениеВФайлЛкс(СохраняемыеДанные, ИмяСохраняемогоФайла);
	ДиалогВыбораФайла = ирКлиент.ДиалогВыбораФайлаЛкс(Ложь, мРасширениеФайла, мОписаниеРасширенияФайла);
	ФайлВыбран = ирКлиент.СохранитьФайлВКонсолиСВосстановлениемЛкс(ДиалогВыбораФайла, ИмяФайла, мИмяОткрытогоФайла, СохраняемыеДанные, мСтруктураВосстановления, ЗапрашиватьИмяФайла);
	Если ФайлВыбран Тогда
		СохранитьИмяФайла();
	Иначе
		Возврат Ложь;
	КонецЕсли;
	Если СброситьМодифицированность Тогда
		ЭтаФорма.Модифицированность = Ложь;
	КонецЕсли; 
	Обновить();
	Возврат Истина;

КонецФункции

Процедура ОсновныеДействияФормыОК(Кнопка)
	
	//СохранитьИзменения();
	
КонецПроцедуры

Процедура ПередЗакрытием(Отказ, СтандартнаяОбработка)
	
	Если Не ПроверитьСохранитьПолноеВыражение() Тогда 
		Отказ = Истина;
	КонецЕсли; 
	
КонецПроцедуры

Функция ПроверитьСохранитьПолноеВыражение()
	
	Отказ = Ложь;
	Если Модифицированность Тогда
		ирКлиент.ПередОтображениемДиалогаПередЗакрытиемФормыЛкс(ЭтаФорма);
		Ответ = Вопрос("Выражение было изменено. Сохранить изменения?", РежимДиалогаВопрос.ДаНетОтмена);
		Если Ответ = КодВозвратаДиалога.Да Тогда
			Отказ = Не СохранитьВФайл();
		ИначеЕсли Ответ = КодВозвратаДиалога.Отмена Тогда
			Отказ = Истина;
		КонецЕсли;
	КонецЕсли;
	Возврат Не Отказ;

КонецФункции

Процедура ОсновныеДействияФормыСтруктураФормы(Кнопка)
	
	ирКлиент.ОткрытьСтруктуруФормыЛкс(ЭтаФорма);
	
КонецПроцедуры

Процедура ПанельДоступныеЭлементыПриСменеСтраницы(Элемент, ТекущаяСтраница)
	
	ЭлементОтбора = ЭлементыФормы.ДоступныеЭлементы.ОтборСтрок.Категория;
	ЭлементОтбора.Установить(ЭлементыФормы.ПанельДоступныеЭлементы.ТекущаяСтраница.Имя);
	ЭлементОтбора.Использование = ЭлементыФормы.ПанельДоступныеЭлементы.ТекущаяСтраница <> ЭлементыФормы.ПанельДоступныеЭлементы.Страницы.Все;
	
КонецПроцедуры

Процедура КПВыражениеВынестиВПараметры(Кнопка)
	
	Перем Значение;
	Фокус = ЭлементыФормы.ПолеТекстаВыражения;
	ВыделенныйТекст = Фокус.ВыделенныйТекст;
	ИзвлечьФорматирование(ВыделенныйТекст);
	Если ПустаяСтрока(ВыделенныйТекст) Тогда
		Возврат;
	КонецЕсли;
	ИмяПараметра = ""; 
	Для каждого СтрокаПараметра Из Параметры Цикл
		Если Истина
			И СтрокаПараметра <> мТекущаяСтрокаПараметра
			И ирОбщий.СтрокиРавныЛкс(СтрокаПараметра.Значение, ВыделенныйТекст) 
		Тогда
			ИмяПараметра = СтрокаПараметра.Имя;
			Прервать;
		КонецЕсли;
	КонецЦикла;
	Если ЗначениеЗаполнено(ИмяПараметра) Тогда
		Ответ = Вопрос("Хотите связать выбранный фрагмент с параметром " + ИмяПараметра + "?", РежимДиалогаВопрос.ДаНет,, КодВозвратаДиалога.Да);
		Если Ответ = КодВозвратаДиалога.Нет Тогда
			ИмяПараметра = "";
		КонецЕсли;
	КонецЕсли; 
	Если ПустаяСтрока(ИмяПараметра) Тогда
		Если НЕ ВвестиСтроку(ИмяПараметра, ВыделенныйТекст + " - имя?", 0) Тогда
			Возврат;
		КонецЕсли;
		Если Не ирОбщий.ЛиИмяПеременнойЛкс(ИмяПараметра) Тогда
			Предупреждение("Введенная строка не соответствует требованиям имени параметра");
			Возврат;
		КонецЕсли; 
		Если СтрокаПараметраПоИмени(ИмяПараметра) <> Неопределено Тогда
			Предупреждение("Такое имя уже существует.");
			Возврат;
		КонецЕсли;
		СтрокаПараметра = Параметры.Вставить(Параметры.Индекс(мТекущаяСтрокаПараметра) + 1);
		СтрокаПараметра.Имя = ИмяПараметра;
		ОбновитьИмяВНижнемРегистре(СтрокаПараметра);
		СтрокаПараметра.Значение = ВыделенныйТекст;
		ПроверитьСинтаксис(СтрокаПараметра);
	КонецЕсли;
	ЭтаФорма.Модифицированность = Истина;
	ПолноеИмяТэга = мЛеваяСкобкаПараметра + ИмяПараметра + мПраваяСкобкаПараметра;
	ВключитьСтроку(ПолноеИмяТэга);
	ОбновитьВыражениеПараметра();
	
КонецПроцедуры

Функция СтрокаБезФорматирования(Знач Текст)
	
	РегВычислитель.Multiline = Ложь;
	РегВычислитель.Global = Истина;
	РегВычислитель.IgnoreCase = Истина;
	РегВычислитель.Pattern = "\n\s*";
	Результат = РегВычислитель.Заменить(Текст, "");
	Возврат Результат;
	
КонецФункции

Функция ИзвлечьФорматирование(ФорматированнаяСтрока)
	
	Перем НачСтр, НачКол, КонСтр, КонКол;
	Форматирование = Новый Массив;
	Вхождения = ирОбщий.НайтиРегВыражениеЛкс(ФорматированнаяСтрока, "\t|\n",,,, Ложь,,, РегВычислитель);
	Для каждого СтрокаРезультата Из Вхождения Цикл
		Поз = СтрокаРезультата.ПозицияВхождения;
		Сим = СтрокаРезультата.ТекстВхождения;
		Если Сим = Символы.Таб Тогда
			Форматирование.Добавить(Поз);
		Иначе
			Форматирование.Добавить(-Поз);
		КонецЕсли;
	КонецЦикла;
	ФорматированнаяСтрока = СтрЗаменить(ФорматированнаяСтрока, Символы.Таб, "");
	ФорматированнаяСтрока = СтрЗаменить(ФорматированнаяСтрока, Символы.ПС, "");
	Если Форматирование.Количество() <> 0  Тогда
		Форматирование = ирОбщий.СтрСоединитьЛкс(Форматирование, ",");
	Иначе
		Форматирование = "";
	КонецЕсли;
	Возврат Форматирование;
	
КонецФункции

Функция ИмеетсяФорматирование(ФорматированнаяСтрока)
	Форматирование = Новый Массив;
	РегВычислитель.Multiline = Ложь;
	РегВычислитель.Global = Истина;
	РегВычислитель.IgnoreCase = Истина;
	РегВычислитель.Pattern = "\t|\n";
	Возврат РегВычислитель.Проверить(ФорматированнаяСтрока);
КонецФункции

Процедура ВключитьСтроку(ТекущаяПоследовательность)
	Перем НачСтр, НачКол, КонСтр, КонКол;
	Фокус = ЭлементыФормы.ПолеТекстаВыражения;
	Фокус.ПолучитьГраницыВыделения(НачСтр, НачКол, КонСтр, КонКол);
	ЭтаФорма.ТекущийЭлемент = Фокус;
	ВыделенныйТекст = Фокус.ВыделенныйТекст;
	Переформатировать = ИмеетсяФорматирование(ВыделенныйТекст);
	Если Переформатировать Тогда
		ИзвлечьФорматирование(ВыделенныйТекст);
		КонСтр = НачСтр;
		КонКол = НачКол + СтрДлина(ВыделенныйТекст);
		Фокус.ВыделенныйТекст = ВыделенныйТекст;
		Фокус.УстановитьГраницыВыделения(НачСтр, НачКол, КонСтр, КонКол);
	КонецЕсли;
	Поз = Найти(ТекущаяПоследовательность, "#");
	Если Поз = 0 Тогда
		Поз = СтрДлина(ТекущаяПоследовательность);
	Иначе
		ТекущаяПоследовательность = СтрЗаменить(ТекущаяПоследовательность, "#", "");
		Поз = Поз - 1;
	КонецЕсли;
	КонКол = НачКол + Поз;
	Фокус.ВыделенныйТекст = ТекущаяПоследовательность;
	Фокус.УстановитьГраницыВыделения(НачСтр, КонКол, КонСтр, КонКол);
	
	//Если Переформатировать Тогда
	//	ОтформатироватьВыражение();
	//КонецЕсли;
КонецПроцедуры

Процедура КПВыражениеКопироватьРезультат(Кнопка)
	
	ирКлиент.ТекстВБуферОбменаОСЛкс(РазвернутоеВыражение());
	
КонецПроцедуры

Процедура КПВыражениеСгенерироватьПрограммныйКод(Кнопка)
	
	НачальнаяСтрока = Параметры.Найти(Ложь, "ЭтоВариант");
	Если мТекущаяСтрокаПараметра <> НачальнаяСтрока Тогда
		Ответ = Вопрос("Генерировать полный текст (Да) или с текущего параметра (Нет)?", РежимДиалогаВопрос.ДаНет,, КодВозвратаДиалога.Да);
		Если Ответ = КодВозвратаДиалога.Нет Тогда
			НачальнаяСтрока = мТекущаяСтрокаПараметра;
		КонецЕсли;
	КонецЕсли; 
	СтрокаПараметраСоСписком = Неопределено;
	ПараметрыСоСписками = Параметры.НайтиСтроки(Новый Структура("Список", Истина));
	Пока ПараметрыСоСписками.Количество() > 0 И ПараметрыСоСписками[0].НомерСтроки <= НачальнаяСтрока.НомерСтроки Цикл
		ПараметрыСоСписками.Удалить(0);
	КонецЦикла;
	Если ПараметрыСоСписками.Количество() > 0 Тогда 
		СтрокаПараметраСоСписком = ПараметрыСоСписками[0];
		ВложенныеГруппы = ГруппыПараметра(СтрокаПараметраСоСписком);
		ИменаВложенныхГрупп = ВложенныеГруппы.ВыгрузитьКолонку("Имя");
		ИменаВложенныхГрупп.Удалить(0);
	КонецЕсли; 
	ПрограммныйКод = "";
	ПрограммныйКод = ПрограммныйКод + "// {Шаблон.Начало}" + Символы.ПС;
	Для ИндексПараметра = 0 По Параметры.Количество() - 1 Цикл
		СтрокаПараметра = Параметры[Параметры.Количество() - 1 - ИндексПараметра];
		ПрограммныйКод = ПрограммныйКод + "// " + ?(СтрокаПараметра.ЭтоВариант, "-", "+") + " " + мЛеваяСкобкаПараметра + СтрокаПараметра.Имя + мПраваяСкобкаПараметра + " = " 
			+ СтрокаБезФорматирования(СтрокаПараметра.Значение) + Символы.ПС;
		Если НачальнаяСтрока = СтрокаПараметра Тогда
			Прервать;
		КонецЕсли; 
	КонецЦикла;
	ПрограммныйКод = ПрограммныйКод + "// {Шаблон.Конец}" + Символы.ПС;
	Переменные = Новый Массив;
	// Мультиметка34що9ш40
	СтрокиПараметров = Параметры.НайтиСтроки(Новый Структура("ЭтоВариант", Ложь));
	Для Счетчик = СтрокиПараметров.Найти(НачальнаяСтрока) + 1 По СтрокиПараметров.Количество() Цикл
		ИндексРодителя = СтрокиПараметров.Найти(НачальнаяСтрока) + СтрокиПараметров.Количество() - Счетчик;
		СтрокаРодителя = СтрокиПараметров[ИндексРодителя];
		РезультатРодителя = СтрокаРодителя.Значение;
		РезультатРодителя = СтрЗаменить(РезультатРодителя, """", """""");
		Для ИндексПараметра = ИндексРодителя + 1 По СтрокиПараметров.Количество() - 1 Цикл
			СтрокаПараметра = СтрокиПараметров[ИндексПараметра];
			РезультатРодителя = СтрЗаменить(РезультатРодителя, мЛеваяСкобкаПараметра + СтрокаПараметра.Имя + мПраваяСкобкаПараметра, """" + " + " + СтрокаПараметра.Имя + " + """);
		КонецЦикла;
		Если ЗначениеЗаполнено(СтрокаРодителя.Комментарий) Тогда
			ПрограммныйКод = ПрограммныйКод + Сред(ирОбщий.ДобавитьМногострочнуюСтрокуВТекстЛкс(, СтрокаРодителя.Комментарий, "// ", Истина), 2) + Символы.ПС;
		КонецЕсли; 
		ПрограммныйКод = ПрограммныйКод + СтрокаРодителя.Имя + " = """ + СтрокаБезФорматирования(РезультатРодителя) + """;" + Символы.ПС;
		Переменные.Добавить(СтрокаРодителя.Имя);
	КонецЦикла;
	ПрограммныйКод = ПрограммныйКод + "// {ОписаниеРегулярногоВыражения.Конец}" + Символы.ПС;
    ВсеДвижки = РегВычислитель.ВсеДвижки();
	
	// Независимое выполнение
	ПрограммныйКод = ПрограммныйКод + "
	|// Независимое выполнение
	|Многострочный = " + ?(Многострочный, "ИСТИНА", "ЛОЖЬ") + ";
	|ИгнорироватьРегистр = " + ?(ИгнорироватьРегистр, "ИСТИНА", "ЛОЖЬ") + ";";
	Если ДвижокВычислителя = ВсеДвижки._1С Тогда
		ПрограммныйКод = ПрограммныйКод + "
		|Вхождения = СтрНайтиВсеПоРегулярномуВыражению(ТекстГдеИскать, " + НачальнаяСтрока.Имя + ", ИгнорироватьРегистр, Многострочный);
		|Для каждого Вхождение Из Вхождения Цикл
		|	Группы = Вхождение.ПолучитьГруппы();
		|";
		Для Каждого СтрокаГруппы Из Группы Цикл
			Если СтрокаГруппы.Индекс < 0 Тогда
				Продолжить;
			КонецЕсли; 
			ПрограммныйКод = ПрограммныйКод + "	" + СтрокаГруппы.Имя + "Значение = Группы[" + СтрокаГруппы.Индекс + "];" + Символы.ПС;
		КонецЦикла;
	ИначеЕсли ДвижокВычислителя = ВсеДвижки.PCRE2 Тогда
		ПрограммныйКод = ПрограммныйКод + "
		|Вычислитель = Новый (""AddIn.ВычислительРегВыражений.RegEx""); // https://github.com/alexkmbk/RegEx1CAddin
		|Вычислитель.Global = Истина;
		|Вычислитель.Multiline = Многострочный;
		|Вычислитель.IgnoreCase = ИгнорироватьРегистр;
		|Вычислитель.Pattern = " + НачальнаяСтрока.Имя + ";
		|Вычислитель.ВызыватьИсключения = Истина;
		|РезультатJSON = Вычислитель.MatchesJSON(ТекстГдеИскать);
		|ЧтениеJSON = Новый ЧтениеJSON;
		|ЧтениеJSON.УстановитьСтроку(РезультатJSON);
		|Вхождения = ПрочитатьJSON(ЧтениеJSON, Ложь);
		|Для каждого Вхождение Из Вхождения Цикл
		|	Начало = Вхождение.FirstIndex;
		|	Длина = Вхождение.Length;
		|	Значение = Вхождение.Value;
		|";
		Для Каждого СтрокаГруппы Из Группы Цикл
			Если СтрокаГруппы.Индекс < 0 Тогда
				Продолжить;
			КонецЕсли; 
			ПрограммныйКод = ПрограммныйКод + "	" + СтрокаГруппы.Имя + "Значение = Вхождение.SubMatches[" + СтрокаГруппы.Индекс + "];" + Символы.ПС;
		КонецЦикла; 
	Иначе
		ПрограммныйКод = ПрограммныйКод + "
		|Вычислитель = Новый COMОбъект(""VBScript.RegExp"");
		|Вычислитель.Global = Истина;
		|Вычислитель.Multiline = Многострочный;
		|Вычислитель.IgnoreCase = ИгнорироватьРегистр;
		|Вычислитель.Pattern = " + НачальнаяСтрока.Имя + ";";
		Если СтрокаПараметраСоСписком <> Неопределено Тогда
			ПрограммныйКод = ПрограммныйКод + "
			|РегВыражениеВложенное = Новый COMОбъект(""VBScript.RegExp"");
			|РегВыражениеВложенное.Global = Истина;
			|РегВыражениеВложенное.Multiline = Многострочный;
			|РегВыражениеВложенное.IgnoreCase = ИгнорироватьРегистр;
			|РегВыражениеВложенное.Pattern = " + СтрокаПараметраСоСписком.Имя + ";";
		КонецЕсли; 
		ПрограммныйКод = ПрограммныйКод + "
		|Вхождения = Вычислитель.Execute(ТекстГдеИскать);
		|Для каждого Вхождение Из Вхождения Цикл
		|	Начало = Вхождение.FirstIndex;
		|	Длина = Вхождение.Length;
		|	Значение = Вхождение.Value;
		|";
		Для Каждого СтрокаГруппы Из Группы Цикл
			Если СтрокаГруппы.Индекс < 0 Тогда
				Продолжить;
			КонецЕсли; 
			ПрограммныйКод = ПрограммныйКод + "	" + СтрокаГруппы.Имя + "Значение = Вхождение.SubMatches(" + СтрокаГруппы.Индекс + ");" + Символы.ПС;
		КонецЦикла; 
		Если СтрокаПараметраСоСписком <> Неопределено Тогда
			ПрограммныйКод = ПрограммныйКод + 
			"	ВложенныеВхождения = РегВыражениеВложенное.Execute(Значение);
			|	Для каждого ВложенноеВхождение Из ВложенныеВхождения Цикл
			|		Начало = ВложенноеВхождение.FirstIndex;
			|		Длина = ВложенноеВхождение.Length;
			|		Значение = ВложенноеВхождение.Value;
			|";
			Для Каждого СтрокаВложеннойГруппы Из ВложенныеГруппы Цикл
				Если СтрокаВложеннойГруппы.Индекс < 0 Тогда
					Продолжить;
				КонецЕсли; 
				ПрограммныйКод = ПрограммныйКод + "		" + СтрокаВложеннойГруппы.Имя + "Значение = ВложенноеВхождение.SubMatches(" + СтрокаВложеннойГруппы.Индекс + ");" + Символы.ПС;
			КонецЦикла; 
			ПрограммныйКод = ПрограммныйКод + "	КонецЦикла;" + Символы.ПС;
		КонецЕсли; 
	КонецЕсли;
	ПрограммныйКод = ПрограммныйКод + "КонецЦикла;" + Символы.ПС;
	
	// Выполнение в ИР
	ИменаГрупп = ИменаГрупп();
	СтрокаИменаГрупп = ирОбщий.СтрСоединитьЛкс(ИменаГрупп);
	ПрограммныйКод = ПрограммныйКод + "
	|// Выполнение в подсистеме ""Инструменты разработчика""
	|Многострочный = " + ?(Многострочный, "ИСТИНА", "ЛОЖЬ") + ";
	|ИгнорироватьРегистр = " + ?(ИгнорироватьРегистр, "ИСТИНА", "ЛОЖЬ") + ";
	|Вхождения = ирОбщий.НайтиРегВыражениеЛкс(ТекстГдеИскать, " + НачальнаяСтрока.Имя + ", """ + СтрокаИменаГрупп + """,, ИгнорироватьРегистр, Многострочный, Ложь);
	|#Если Сервер И Не Сервер Тогда
	|	Вхождения = Обработки.ирПлатформа.Создать().ВхожденияРегВыражения;
	|#КонецЕсли";
	Если СтрокаПараметраСоСписком <> Неопределено И ИменаГрупп.Найти(СтрокаПараметраСоСписком.Имя) = Неопределено Тогда
		ПрограммныйКод = ПрограммныйКод + "
		|Вхождения.Колонки.Добавить(""" + СтрокаПараметраСоСписком.Имя + """);";
	КонецЕсли; 
	ПрограммныйКод = ПрограммныйКод + "
	|Для каждого Вхождение Из Вхождения Цикл
	|	Начало = Вхождение.ПозицияВхождения;
	|	Длина = Вхождение.ДлинаВхождения;
	|	Значение = Вхождение.ТекстВхождения;
	|";
	Для Каждого СтрокаГруппы Из Группы Цикл
		Если СтрокаГруппы.Индекс < 0 Тогда
			Продолжить;
		КонецЕсли; 
		ПрограммныйКод = ПрограммныйКод + "	" + СтрокаГруппы.Имя + "Значение = Вхождение." + ИменаГрупп[СтрокаГруппы.Индекс] + ";" + Символы.ПС;
	КонецЦикла; 
	Если СтрокаПараметраСоСписком <> Неопределено Тогда
		ПрограммныйКод = ПрограммныйКод + 
		"	ВложенныеВхождения = ирОбщий.НайтиРегВыражениеЛкс(Вхождение.ТекстВхождения, " + СтрокаПараметраСоСписком.Имя + ", """ + ирОбщий.СтрСоединитьЛкс(ИменаВложенныхГрупп) + """,, ИгнорироватьРегистр, Многострочный, Ложь);
		|		#Если Сервер И Не Сервер Тогда
		|		    Вхождения = Обработки.ирПлатформа.Создать().ВхожденияРегВыражения;
		|		#КонецЕсли
		|	Вхождение." + СтрокаПараметраСоСписком.Имя + " = ВложенныеВхождения;
		|";
		ПрограммныйКод = ПрограммныйКод + 
		"	Для каждого ВложенноеВхождение Из ВложенныеВхождения Цикл
		|		Начало = ВложенноеВхождение.ПозицияВхождения;
		|		Длина = ВложенноеВхождение.ДлинаВхождения;
		|		Значение = ВложенноеВхождение.ТекстВхождения;
		|";
		Для Каждого СтрокаВложеннойГруппы Из ВложенныеГруппы Цикл
			Если СтрокаВложеннойГруппы.Индекс < 0 Тогда
				Продолжить;
			КонецЕсли; 
			ПрограммныйКод = ПрограммныйКод + "		" + СтрокаВложеннойГруппы.Имя + "Значение = ВложенноеВхождение." + ИменаВложенныхГрупп[СтрокаВложеннойГруппы.Индекс] + ";" + Символы.ПС;
		КонецЦикла; 
		ПрограммныйКод = ПрограммныйКод + "	КонецЦикла;" + Символы.ПС;
	КонецЕсли; 
	ПрограммныйКод = ПрограммныйКод + "КонецЦикла;" + Символы.ПС;
	ПрограммныйКод = "// Перем " + ирОбщий.СтрСоединитьЛкс(Переменные) + ";" + Символы.ПС + ПрограммныйКод;
	ПрограммныйКод = "// {ОписаниеРегулярногоВыражения.Начало} конструктор из подсистемы ""Инструменты разработчика"" (http://devtool1c.ucoz.ru)" + Символы.ПС + ПрограммныйКод;
	РазвернутоеВыражение(); // Для восстановления доступных параметров
	ирОбщий.ОперироватьСтруктуройЛкс(ПрограммныйКод,, Новый Структура("ТекстГдеИскать", ПроверочныйТекст()));
	
КонецПроцедуры

Функция ИменаГрупп()
	
	ИменаГрупп = Группы.ВыгрузитьКолонку("Имя");
	ИменаГрупп = ирОбщий.СвернутьМассивЛкс(ИменаГрупп); // Редко могут быть дубли, если имена параметров Я1, Я10, Я11
	ИменаГрупп.Удалить(0);
	Возврат ИменаГрупп;

КонецФункции

Процедура КПВыражениеТестироватьRegexBuddy(Кнопка)
	
	ОткрытьВыражениеВRegexBuddy();

КонецПроцедуры

Процедура ОткрытьВыражениеВRegexBuddy(НачатьОтладку = Ложь)
	
	ТекстовыйДокумент = Новый ТекстовыйДокумент;
	ТекстовыйДокумент.УстановитьТекст(ПроверочныйТекст());
	ТекстДляБуфераОбмена = РазвернутоеВыражение();
	Если мОлеСервер = Неопределено Тогда
		Попытка
			мОлеСервер = Новый COMОбъект("RegexBuddy.RegexBuddyIntf3");
		Исключение
			ирОбщий.СообщитьЛкс("Не удалось создать COM объект RegexBuddy.RegexBuddyIntf3: " + ОписаниеОшибки());
		КонецПопытки; 
	КонецЕсли;
	Если мОлеСервер = Неопределено Тогда
		// https://www.regexbuddy.com/manual.html#commandline
		ИсполняемыйФайлRegexBuddy = ирОбщий.ВосстановитьЗначениеЛкс("ИсполняемыйФайлRegexBuddy");
		Если Не ЗначениеЗаполнено(ИсполняемыйФайлRegexBuddy) Тогда
			ДействияФормыНастройки();
			Сообщить("Необходимо указать исполняемый файл RegexBuddy в настройках");
			//Возврат;
		КонецЕсли; 
		ИмяФайлаПроверочногоТекста = ПолучитьИмяВременногоФайла("txt");
		ТекстовыйДокумент.Записать(ИмяФайлаПроверочногоТекста);
		РазделительПараметров = Новый УникальныйИдентификатор;
		//РазделительПараметров = "?**?**?";
		СтрокаЗапуска = """" + ИсполняемыйФайлRegexBuddy + """ -appname ""1С"" -getfromclipboard -delimitclipboard " + РазделительПараметров + " -testfile """ + ИмяФайлаПроверочногоТекста + """";
		// Не заработало разделение
		//ТекстДляБуфераОбмена = ТекстДляБуфераОбмена + РазделительПараметров;
		//Если ИгнорироватьРегистр Тогда
		//	ТекстДляБуфераОбмена = ТекстДляБуфераОбмена + "-caseless";
		//КонецЕсли; 
		//Если Многострочный Тогда
		//	ТекстДляБуфераОбмена = ТекстДляБуфераОбмена + "-multiline";
		//КонецЕсли; 
		ирКлиент.ТекстВБуферОбменаОСЛкс(ТекстДляБуфераОбмена, "");
		ЗапуститьПриложение(СтрокаЗапуска);
	Иначе
		// https://www.regexbuddy.com/manual.html#comautomation
		мОлеСервер.IndicateApp("1C", 0);
		Массив = Новый Массив;
		Массив.Добавить(1);
		Массив.Добавить(0);
		Массив.Добавить(ТекстДляБуфераОбмена);
		Массив.Добавить("");
		Массив.Добавить(Ложь);
		Массив.Добавить(ИгнорироватьРегистр);
		Массив.Добавить(Многострочный);
		Массив.Добавить(0);
		Массив.Добавить("");
		ПараметрыДействия = Новый COMSafeArray(Массив, "VT_Variant");
		мОлеСервер.InitAction(ПараметрыДействия);
		мОлеСервер.SetTestString(ТекстовыйДокумент.ПолучитьТекст());
		ВыделениеВТексте = мПолеТекстаПоиска.ПолучитьВыделениеВДокументеHTML();
		Если НачатьОтладку Тогда
			мОлеСервер.DebugAtPos(ВыделениеВТексте.Начало); // Работает только начиная с RegexBuddy 4.13
		КонецЕсли; 
	КонецЕсли;

КонецПроцедуры

Процедура ПараметрыПриВыводеСтроки(Элемент, ОформлениеСтроки, ДанныеСтроки) Экспорт
	
	ОформлениеСтроки.Ячейки.Варианты.Значение = Параметры.НайтиСтроки(Новый Структура("Имя", ДанныеСтроки.Имя)).Количество(); // Надо делать до ТабличноеПолеПриВыводеСтрокиЛкс, иначе значение не будет отображаться
	ирКлиент.ТабличноеПолеПриВыводеСтрокиЛкс(ЭтаФорма, Элемент, ОформлениеСтроки, ДанныеСтроки);
	ОформлениеСтроки.Ячейки.КолонкаРавно.УстановитьТекст("=");
	Если Не ДанныеСтроки.Корректно Тогда
		ОформлениеСтроки.Ячейки.Значение.ЦветТекста = WebЦвета.Красный;
	КонецЕсли; 
	Если Параметры.НайтиСтроки(Новый Структура("Имя, Корректно", ДанныеСтроки.Имя, Ложь)).Количество() > 0 Тогда
		ОформлениеСтроки.Ячейки.Варианты.ЦветТекста = WebЦвета.Красный;
	КонецЕсли; 
	
КонецПроцедуры

Процедура КПВыражениеВставитьВыражение1С(Кнопка)
	
	Текст = ирКлиент.ТекстИзБуфераОбменаОСЛкс();
	Если Не ЗначениеЗаполнено(Текст) Тогда
		Возврат;
	КонецЕсли; 
	Текст = ирОбщий.ТекстИзВстроенногоЯзыкаЛкс(Текст);
	ЗаменитьИВыделитьВыделенныйТекстВыражения(Текст);
	
КонецПроцедуры

Процедура ЗаменитьИВыделитьВыделенныйТекстВыражения(Знач Текст)
	
	ирКлиент.ЗаменитьИВыделитьВыделенныйТекстПоляЛкс(ЭтаФорма, ЭлементыФормы.ПолеТекстаВыражения, Текст);
	ОбновитьВыражениеПараметра();

КонецПроцедуры

Процедура УстановитьТекущуюСтрокуПараметра()
	
	ЭлементыФормы.Параметры.ТекущаяСтрока = Параметры[0];
	АвтообновлениеПроверочногоТекста();
	
КонецПроцедуры

Процедура ОчиститьПараметры()
	
	мТекущаяСтрокаПараметра = Неопределено;
	Параметры.Очистить();

КонецПроцедуры

Процедура ПараметрыПриАктивизацииСтроки(Элемент = Неопределено)
	
	ирКлиент.ТабличноеПолеПриАктивизацииСтрокиЛкс(ЭтаФорма, Элемент);
	Если мТекущаяСтрокаПараметра <> Неопределено Тогда
		мТекущаяСтрокаПараметра.Значение = ЭлементыФормы.ПолеТекстаВыражения.Значение;
		мТекущаяСтрокаПараметра.Комментарий = ЭлементыФормы.Комментарий.ПолучитьТекст();
	КонецЕсли; 
	мТекущаяСтрокаПараметра = ЭлементыФормы.Параметры.ТекущаяСтрока;
	Если мТекущаяСтрокаПараметра = Неопределено Тогда
		ЭлементыФормы.ПолеТекстаВыражения.Значение = "";
		ЭлементыФормы.ПанельВыражение.Доступность = Ложь;
		Возврат;
	КонецЕсли; 
	ЭлементыФормы.ПанельВыражение.Доступность = Истина;
	ЭлементыФормы.ПолеТекстаВыражения.Значение = мТекущаяСтрокаПараметра.Значение;
	ЭлементыФормы.Варианты.ОтборСтрок.НИмя.Установить(ЭлементыФормы.Параметры.ТекущаяСтрока.НИмя);
	ЭлементыФормы.Варианты.ТекущаяСтрока = ЭлементыФормы.Параметры.ТекущаяСтрока;
	ИспользуетсяВ.Очистить();
	ОбращениеКПараметру = мЛеваяСкобкаПараметра + мТекущаяСтрокаПараметра.Имя + мПраваяСкобкаПараметра;
	Для Каждого СтрокаПараметра Из Параметры Цикл
		ПозицияОбращения = Найти(НРег(СтрокаПараметра.Значение), НРег(ОбращениеКПараметру));
		Если ПозицияОбращения = 0 Тогда
			Продолжить;
		КонецЕсли;
		Если ИспользуетсяВ.Найти(СтрокаПараметра.Имя, "Имя") = Неопределено Тогда
			ЗаполнитьЗначенияСвойств(ИспользуетсяВ.Добавить(), СтрокаПараметра, "Имя, Корректно"); 
		КонецЕсли; 
	КонецЦикла;
	ИспользуетсяВ.Сортировать("Имя");
	ЭлементыФормы.Комментарий.УстановитьТекст(мТекущаяСтрокаПараметра.Комментарий);
	ОбновитьВыражениеПараметра();

КонецПроцедуры

Процедура КПВариантыДобавить(Кнопка)
	
	
КонецПроцедуры

Процедура ВариантыПриАктивизацииСтроки(Элемент)
	
	Если ЭлементыФормы.Варианты.ТекущаяСтрока = Неопределено Тогда
		Возврат;
	КонецЕсли; 
	Если Истина
		И мТекущаяСтрокаПараметра <> Неопределено 
		И ЭлементыФормы.Варианты.ТекущаяСтрока <> мТекущаяСтрокаПараметра
		И мТекущаяСтрокаПараметра.Имя = ЭлементыФормы.Варианты.ТекущаяСтрока.Имя 
	Тогда
		мТекущаяСтрокаПараметра.ЭтоВариант = Истина;
	КонецЕсли;
	ирОбщий.ПрисвоитьЕслиНеРавноЛкс(ЭлементыФормы.Варианты.ТекущаяСтрока.ЭтоВариант, Ложь, ЭтаФорма.Модифицированность);
	ирОбщий.ПрисвоитьЕслиНеРавноЛкс(ЭлементыФормы.Параметры.ТекущаяСтрока, ЭлементыФормы.Варианты.ТекущаяСтрока);
	
КонецПроцедуры

Процедура ПанельВыражениеПриСменеСтраницы(Элемент, ТекущаяСтраница)
	
	ОбновитьВыражениеПараметра();
	ПараметрыПриАктивизацииСтроки();
	
КонецПроцедуры

Процедура ОбновитьВыражениеПараметра(Знач РазрешитьИзменятьСвернутость = Истина)
	
	СтрокаРодителя = ЭлементыФормы.Параметры.ТекущаяСтрока;
	Если СтрокаРодителя = Неопределено Тогда
		Возврат;
	КонецЕсли; 
	СтрокаРодителя.Значение = ЭлементыФормы.ПолеТекстаВыражения.Значение;
	ЭтаФорма.Группы = ГруппыПараметра(СтрокаРодителя);
	ЭлементыФормы.Группы.ТекущаяСтрока = Группы[0];
	ЭтаФорма.РазвернутоеВыражение = РазвернутоеВыражение();
	ЭлементыФормы.РазвернутоеВыражение.Доступность = Параметры.НайтиСтроки(Новый Структура("ЭтоВариант", Ложь)).Количество() > 1;
	ПроверитьСинтаксис(, Ложь);
	Если АвтообновлениеПроверочногоТекста Тогда
		ОбновитьПроверочныйТекст();
	КонецЕсли; 
	Если РазрешитьИзменятьСвернутость Тогда
		ИзменитьСвернутостьРазвернутоеВыражение(РазвернутоеВыражение <> ПолеТекстаВыражения);
	КонецЕсли;

КонецПроцедуры

Функция ГруппыПараметра(Знач СтрокаРодителя)
	
	Если СтрокаРодителя <> мТекущаяСтрокаПараметра Тогда
		ГруппыЛокальные = Группы.СкопироватьКолонки();
	Иначе
		ГруппыЛокальные = Группы;
	КонецЕсли; 
	ГруппыЛокальные.Очистить();
	ОбновитьСтрокуПараметра(СтрокаРодителя,, ГруппыЛокальные);
	СчетчикиПараметров = Новый Соответствие;
	Для Каждого СтрокаГруппы Из ГруппыЛокальные Цикл
		НомерГруппы = СчетчикиПараметров[СтрокаГруппы.Имя];
		Если НомерГруппы = Неопределено Тогда
			НомерГруппы = 0;
		Иначе
			НомерГруппы = НомерГруппы + 1;
		КонецЕсли; 
		СчетчикиПараметров[СтрокаГруппы.Имя] = НомерГруппы;
		СтрокаГруппы.Параметр = СтрокаГруппы.Имя;
		СтрокаГруппы.Имя = СтрокаГруппы.Имя + ?(НомерГруппы = 0, "", НомерГруппы);
	КонецЦикла;
	Возврат ГруппыЛокальные;

КонецФункции

Функция ОбновитьСтрокуПараметра(Знач СтрокаРодителя, Счетчик = Неопределено, ГруппыЛокальные = Неопределено, РазвернутыйСчетчик = 0)
	
	ЗначениеПараметра = СтрокаБезФорматирования(СтрокаРодителя.Значение);
	Если Счетчик = Неопределено Тогда 
		СтрокаГруппы = ГруппыЛокальные.Добавить();
		СтрокаГруппы.Индекс = -1;
		СтрокаГруппы.Имя = "<Группа>";
		СтрокаГруппы.НачальнаяПозиция = 1;
		СтрокаГруппы.НачальнаяПозицияРазвернутая = 1;
		Счетчик = 1;
		РазвернутыйСчетчик = 1;
	КонецЕсли; 
	СчетчикГрупп = 1;
	ПропускаемСимвол = Ложь;
	Пока Счетчик <= СтрДлина(ЗначениеПараметра) Цикл
		ТекущийСимвол = Сред(ЗначениеПараметра, Счетчик, 1);
		Счетчик = Счетчик + 1;
		РазвернутыйСчетчик = РазвернутыйСчетчик + 1;
		Если ПропускаемСимвол Тогда 
			ПропускаемСимвол = Ложь;
			Продолжить;
		КонецЕсли; 
		Если ТекущийСимвол = "\" Тогда
			ПропускаемСимвол = Истина;
			Продолжить;
		КонецЕсли; 
		ПропускаемСимвол = Ложь;
		Если ТекущийСимвол = "(" Тогда
			НачальнаяПозиция = Счетчик - 1;
			НачальнаяПозицияРазвернутая = РазвернутыйСчетчик - 1;
			ЭтоФиксируемаяГруппа = Сред(ЗначениеПараметра, Счетчик, 1) <> "?";
			Если ЭтоФиксируемаяГруппа Тогда
				СтрокаГруппы = ГруппыЛокальные.Добавить();
				СтрокаГруппы.Индекс = ГруппыЛокальные.Количество() - 2;
				СтрокаГруппы.Имя = СтрокаРодителя.Имя;
				СтрокаГруппы.НомерВнутриРодителя = СчетчикГрупп;
				СтрокаГруппы.НачальнаяПозиция = НачальнаяПозиция;
				СтрокаГруппы.КонечнаяПозиция = Счетчик - 1;
				СтрокаГруппы.НачальнаяПозицияРазвернутая = НачальнаяПозицияРазвернутая;
				СтрокаГруппы.КонечнаяПозицияРазвернутая = РазвернутыйСчетчик - 1;
				СтрокаГруппы.Параметр = СтрокаРодителя.Имя;
				СчетчикГрупп = СчетчикГрупп + 1;
			КонецЕсли; 
			ОбновитьСтрокуПараметра(СтрокаРодителя, Счетчик, ГруппыЛокальные, РазвернутыйСчетчик);
		ИначеЕсли ТекущийСимвол = ")" Тогда
			Возврат ГруппыЛокальные;
		ИначеЕсли ТекущийСимвол = мЛеваяСкобкаПараметра Тогда
			ИмяДочернегоПараметра = ирОбщий.ТекстМеждуМаркерамиЛкс(Сред(ЗначениеПараметра, Счетчик), , мПраваяСкобкаПараметра, Ложь);
			Если Не ЗначениеЗаполнено(ИмяДочернегоПараметра) Тогда
				Продолжить;
			КонецЕсли; 
			СтрокаПараметра = СтрокаПараметраПоИмени(ИмяДочернегоПараметра);
			Если СтрокаПараметра <> Неопределено Тогда
				Счетчик = Счетчик + СтрДлина(ИмяДочернегоПараметра) + 1; // 1 = СтрДлина(мПраваяСкобкаПараметра)
				РазвернутыйСчетчик = РазвернутыйСчетчик - 1;
				ОбновитьСтрокуПараметра(СтрокаПараметра, 1, ГруппыЛокальные, РазвернутыйСчетчик);
				Если Параметры.Индекс(СтрокаПараметра) < Параметры.Индекс(СтрокаРодителя) Тогда
					Параметры.Сдвинуть(СтрокаРодителя, Параметры.Индекс(СтрокаПараметра) - Параметры.Индекс(СтрокаРодителя));
				КонецЕсли; 
			КонецЕсли; 
		КонецЕсли; 
	КонецЦикла;
	Если СтрокаГруппы <> Неопределено Тогда
		СтрокаГруппы.КонечнаяПозиция = РазвернутыйСчетчик - 1;
	КонецЕсли; 
	Возврат ГруппыЛокальные;

КонецФункции

Процедура ОбновитьПроверочныйТекст(РазрешитьАвтовыделение = Истина, СообщатьОшибки = Ложь)
	
	СохранитьФайлДляВосстановления();
	Группы.ЗаполнитьЗначения(0, "Найдено");
	ВхожденияГруппы.Очистить();
	УдаляемыеКолонки = Новый Массив;
	ИндексТекущейГруппы = ЭлементыФормы.Группы.ТекущаяСтрока.Индекс;
	Для ИндексКолонки = мНачальноеКоличествоКолонок По ВхожденияГруппы.Колонки.Количество() - 1 Цикл
		УдаляемыеКолонки.Добавить(ВхожденияГруппы.Колонки[ИндексКолонки]);
	КонецЦикла;
	Для Каждого УдаляемаяКолонка Из УдаляемыеКолонки Цикл
		ЭлементыФормы.ВхожденияГруппы.Колонки.Удалить(ЭлементыФормы.ВхожденияГруппы.Колонки.Найти(УдаляемаяКолонка.Имя));
		ВхожденияГруппы.Колонки.Удалить(УдаляемаяКолонка);
	КонецЦикла;
	Если РазвернутоеВыражение <> "" Тогда
		Вхождения = ВычислитьВхождения(СообщатьОшибки);
		Если Вхождения = Неопределено Тогда
			Возврат;
		КонецЕсли; 
		Если ИндексТекущейГруппы = -1 Тогда
			Для ИндексКолонки = РегВычислитель.НоваяТаблицаВхождений().Колонки.Количество() По Вхождения.Колонки.Количество() - 1 Цикл
				КолонкаРезультата = Вхождения.Колонки[ИндексКолонки];
				ВхожденияГруппы.Колонки.Добавить(КолонкаРезультата.Имя, КолонкаРезультата.ТипЗначения, КолонкаРезультата.Заголовок, КолонкаРезультата.Ширина);
				КолонкаТП = ЭлементыФормы.ВхожденияГруппы.Колонки.Добавить(КолонкаРезультата.Имя);
				КолонкаТП.Данные = КолонкаРезультата.Имя; 
			КонецЦикла;
			ирОбщий.НастроитьДобавленныеКолонкиТабличногоПоляЛкс(ЭлементыФормы.ВхожденияГруппы,,,, Истина);
		КонецЕсли;
		НомерВхождения = 0;
		Для каждого Вхождение Из Вхождения Цикл
			НомерВхождения = НомерВхождения + 1;
			Начало = Вхождение.ПозицияВхождения;
			Длина = Вхождение.ДлинаВхождения;
			Конец = Начало + Длина;
			ТекстВхождения = Вхождение.ТекстВхождения;
			НайденнаяГруппа = ВхожденияГруппы.Добавить();
			НайденнаяГруппа.Номер = НомерВхождения;
			НайденнаяГруппа.Позиция = Начало;
			НайденнаяГруппа.Длина = Длина;
			НайденнаяГруппа.Значение = ТекстВхождения;
			НайденнаяГруппа.ПозицияГруппы = Начало;
			НайденнаяГруппа.ДлинаГруппы = Длина;
			Для ИндексКолонки = 0 По Вхождение.Группы.Количество() - 1 Цикл
				ЗначениеГруппы = Вхождение.Группы[ИндексКолонки];
				Если ИндексТекущейГруппы = -1 Тогда
					ЗаполнитьЗначенияСвойств(НайденнаяГруппа, Вхождение); 
				КонецЕсли; 
				ПредставлениеПодстроки = ПрижатьВлево(ЗначениеГруппы);
				НайденнаяГруппа.Группы.Добавить(Вхождение.Группы[ИндексКолонки], ПредставлениеПодстроки);
				Если ПредставлениеПодстроки <> Неопределено Тогда
					СтрокаГруппы = Группы.Найти(ИндексКолонки, "Индекс");
					Если СтрокаГруппы <> Неопределено Тогда
						СтрокаГруппы.Найдено = СтрокаГруппы.Найдено + 1;
					КонецЕсли;
				КонецЕсли; 
				Если ИндексКолонки = ИндексТекущейГруппы Тогда
					//НайденнаяГруппа.ПозицияГруппы = Начало + Найти(ТекстВхождения, ЗначениеГруппы) - 1;
					//НайденнаяГруппа.ДлинаГруппы = СтрДлина(ЗначениеГруппы);
					НайденнаяГруппа.ЗначениеГруппы = ЗначениеГруппы;
				КонецЕсли;
			КонецЦикла;
			Если ИндексТекущейГруппы = -1 Тогда
				НайденнаяГруппа.ЗначениеГруппы = ТекстВхождения;
			КонецЕсли; 
		КонецЦикла;
		СтрокаГруппы = Группы.Найти(-1, "Индекс");
		СтрокаГруппы.Найдено = Вхождения.Количество();
	КонецЕсли; 
	ИндексГруппы = ИндексТекущейГруппы; 
	ВыделениеВТексте = мПолеТекстаПоиска.ПолучитьВыделениеВДокументеHTML();
	мПолеТекстаПоиска.РазметитьТекстРезультатамиПоискаИУстановитьВПоле(, ВхожденияГруппы, ИндексГруппы, ПереносСлов);
	ДокументHtml = ЭлементыФормы.ПроверочныйТекст.Документ;
	Если Автовыделение И РазрешитьАвтовыделение Тогда
		Если ирКэш.ДоступноБраузерWebKitЛкс() Тогда
			ТекущееВыделение = ДокументHtml.getSelection();
			ТекущееВыделение.removeAllRanges();
		Иначе
			ТекстовыйДиапазон = ДокументHtml.body.createTextRange();
			ТекстовыйДиапазон.collapse();
			ТекстовыйДиапазон.select();
		КонецЕсли; 
		СледующееВхождениеНажатие();
	Иначе
		УстановитьВыделениеВПроверочномТексте(ВыделениеВТексте);
	КонецЕсли; 
	НовыйПроверочныйТекст = ПроверочныйТекст();
	Если Истина
		И Не ЭтаФорма.Модифицированность 
		И мСтарыйПроверочныйТекст <> Неопределено
		И мСтарыйПроверочныйТекст <> НовыйПроверочныйТекст 
	Тогда
		ЭтаФорма.Модифицированность = Истина;
	КонецЕсли; 
	мСтарыйПроверочныйТекст = НовыйПроверочныйТекст;

КонецПроцедуры

Функция ПрижатьВлево(Знач Текст) 
	
	РегВычислительЛокальный.Multiline = Ложь;
	РегВычислительЛокальный.Global = Истина;
	РегВычислительЛокальный.IgnoreCase = Истина;
	РегВычислительЛокальный.Pattern = "(^[ \s]*(?=[^ \s]))";
	Результат = Текст;
	Если ЗначениеЗаполнено(Результат) Тогда
		Найдено = РегВычислительЛокальный.НайтиВхождения(Текст);
		Для каждого Вхождение Из Найдено Цикл
			Длина = Вхождение.Length;
			Если Длина <> 0  Тогда
				Результат = "•" + Сред(Результат, Длина+1);
			КонецЕсли;
		КонецЦикла;
	КонецЕсли;
	Возврат Результат;
	
КонецФункции

Функция ПроверочныйТекст()
	Текст = мПолеТекстаПоиска.ПолучитьТекст(Ложь);
	Возврат Текст;
КонецФункции

Функция УстановитьПроверочныйТекст(Текст)
	
	ПолеТекста = ирКлиент.ОболочкаПоляТекстаЛкс(ЭлементыФормы.ПроверочныйТекст);
	#Если Сервер И Не Сервер Тогда
		 ПолеТекста = Обработки.ирОболочкаПолеТекста.Создать();
	 #КонецЕсли
	ПолеТекста.УстановитьОтображаемыйТекст(Текст, ПереносСлов);
	Возврат Текст;

КонецФункции

Функция РазвернутоеВыражение(ТекущаяСтрока = Неопределено)
	
	Если ТекущаяСтрока = Неопределено Тогда
		ТекущаяСтрока = ЭлементыФормы.Параметры.ТекущаяСтрока;
	КонецЕсли; 
	Результат = Неопределено;
	ДоступныеПараметры.Очистить();
	// Мультиметка34що9ш40
	СтрокиПараметров = Параметры.НайтиСтроки(Новый Структура("ЭтоВариант", Ложь));
	Для ИндексРодителя = СтрокиПараметров.Найти(ТекущаяСтрока) По СтрокиПараметров.Количество() - 1 Цикл
		СтрокаРодителя = СтрокиПараметров[ИндексРодителя];
		Если Результат = Неопределено Тогда
			Результат = ТекущаяСтрока.Значение;
			Для ИндексПараметра = ИндексРодителя + 1 По СтрокиПараметров.Количество() - 1 Цикл
				СтрокаПараметра = СтрокиПараметров[ИндексПараметра];
				СтрокаПоиска = мЛеваяСкобкаПараметра + СтрокаПараметра.НИмя + мПраваяСкобкаПараметра;
				ДоступныйПараметр = ДоступныеПараметры.Добавить();
				ЗаполнитьЗначенияСвойств(ДоступныйПараметр, СтрокаПараметра, "Имя, Корректно"); 
				ДоступныйПараметр.Использован = Найти(НРег(Результат), СтрокаПоиска) > 0;
			КонецЦикла;
		КонецЕсли;
		Для ИндексПараметра = ИндексРодителя + 1 По СтрокиПараметров.Количество() - 1 Цикл
			СтрокаПараметра = СтрокиПараметров[ИндексПараметра];
			СтрокаПоиска = мЛеваяСкобкаПараметра + СтрокаПараметра.Имя + мПраваяСкобкаПараметра;
			Результат = ирОбщий.СтрЗаменитьЛкс(Результат, СтрокаПоиска, СтрокаПараметра.Значение,, Ложь, Ложь);
		КонецЦикла;
	КонецЦикла;
	ДоступныеПараметры.Сортировать("Имя");
	Результат = СтрокаБезФорматирования(Результат);
	Возврат Результат;
	
КонецФункции

Процедура ПолеТекстаВыраженияАвтоПодборТекста(Элемент, Текст, ТекстАвтоПодбора, СтандартнаяОбработка)
	
	ОбновитьВыражениеПараметра(Ложь);

КонецПроцедуры

Процедура ОбновитьПодсказкуДоступногоЭлемента()

	// Портит текущее незаконченное выделение мышкой!
	ПолеТекста = ирКлиент.ОболочкаПоляТекстаЛкс(ЭлементыФормы.ПолеТекстаВыражения);
	#Если Сервер И Не Сервер Тогда
		ПолеТекста = Обработки.ирОболочкаПолеТекста.Создать();
	#КонецЕсли
	НачальнаяПозиция = Неопределено;
	КонечнаяПозиция = Неопределено;
	ПолеТекста.ВыделениеОдномерное(НачальнаяПозиция, КонечнаяПозиция);
	Если мПоследняяПозицияПодсказки <> КонечнаяПозиция И НачальнаяПозиция = КонечнаяПозиция Тогда
		мПоследняяПозицияПодсказки = КонечнаяПозиция;
		КонечнаяПозиция = КонечнаяПозиция - 1;
		Текст = ПолеТекста.ПолучитьТекст();
		Если Сред(Текст, КонечнаяПозиция, 1) = "\" Тогда
			Фрагмент = Лев(Текст, КонечнаяПозиция + 1);
		Иначе
			Фрагмент = Лев(Текст, КонечнаяПозиция);
		КонецЕсли;
		Фрагмент = ирОбщий.ПоследнийФрагментЛкс(Фрагмент, "\", Ложь);
		Если СтрДлина(Фрагмент) = 1 Тогда
			ДоступныйЭлемент = ДоступныеЭлементы.Найти("\" + Фрагмент, "Текст");
			Если Истина
				И ДоступныйЭлемент <> Неопределено 
				И ЭлементыФормы.ДоступныеЭлементы.ТекущаяСтрока <> ДоступныйЭлемент
			Тогда
				ЭлементыФормы.ПанельДоступныеЭлементы.ТекущаяСтраница = ЭлементыФормы.ПанельДоступныеЭлементы.Страницы.Все;
				ЭлементыФормы.ДоступныеЭлементы.ТекущаяСтрока = ДоступныйЭлемент;
			КонецЕсли;
		КонецЕсли;
	КонецЕсли;
	ПодключитьОбработчикОжидания("ОбновитьПодсказкуДоступногоЭлемента", 1, Истина);

КонецПроцедуры

Процедура ПолеТекстаВыраженияПриИзменении(Элемент)
	
	ОбновитьВыражениеПараметра();

КонецПроцедуры

Процедура КПВыражениеСправкаПоСинтаксису(Кнопка)
	
	Если ДвижокВычислителя = РегВычислитель.ВсеДвижки()._1С Тогда
		ирКлиент.ОткрытьСсылкуИТСЛкс("https://its.1c.ru/db/v?doc#bookmark:dev:TI000002651");
	Иначе
		ИмяВременногоФайла = ПолучитьИмяВременногоФайла("chm");
		ПолучитьМакет("СправкаRegexp").Записать(ИмяВременногоФайла);
		ЗапуститьПриложение(ИмяВременногоФайла);
	КонецЕсли;

КонецПроцедуры

Процедура ДействияФормыНовоеОкно(Кнопка)
	
	ирКлиент.ОткрытьНовоеОкноФормыЛкс(ЭтотОбъект);
	
КонецПроцедуры

Процедура ДействияФормыНовыйФайл(Кнопка)
	
	Если ПроверитьСохранитьПолноеВыражение() Тогда
		СоздатьФайл();
	КонецЕсли;

КонецПроцедуры

Процедура ДействияФормыСохранитьФайл(Кнопка)
	
	СохранитьВФайл();
	
КонецПроцедуры

Процедура ДействияФормыСохранитьКак(Кнопка)
	
	СохранитьВФайл(, Истина);
	
КонецПроцедуры

Процедура ДействияФормыОткрытьФайл(Кнопка)
	
	Если Не ПроверитьСохранитьПолноеВыражение() Тогда
		Возврат;
	КонецЕсли; 
	ОткрытьФайл();
	
КонецПроцедуры

Процедура ОткрытьФайл(РежимОбъединения = Ложь)
	
	ИмяФайла = ирКлиент.ВыбратьФайлЛкс(, мРасширениеФайла, мОписаниеРасширенияФайла);
	Если ИмяФайла = Неопределено Тогда
		Возврат;
	КонецЕсли; 
	ОткрытьФайлПоПолномуИмени(ИмяФайла, РежимОбъединения);

КонецПроцедуры

Процедура ЗагрузитьИзФайлаОтложенно()
	ЗагрузитьИзФайла();
КонецПроцедуры

Процедура ЗагрузитьИзФайла(ИмяФайла = "")
	
	Если Не ЗначениеЗаполнено(ИмяФайла) Тогда
		ИмяФайла = мИмяОткрытогоФайла;
		РежимОбъединения = Ложь;
	Иначе
		РежимОбъединения = Истина;
	КонецЕсли; 
	//ЗагружаемыеДанные = ирОбщий.ЗагрузитьЗначениеИзФайлаЛкс(ИмяВыбранногоФайла);
	ЗагружаемыеДанные = ирКлиент.ПрочитатьЗначениеИзФайлаСКонтролемПотерьЛкс(ИмяФайла);
	Если ЗагружаемыеДанные = Неопределено Тогда
		Возврат;
	КонецЕсли;
	#Если Сервер И Не Сервер Тогда
		ЗагружаемыеДанные = Новый Структура;
	#КонецЕсли
	ЭтаФорма.Модифицированность = РежимОбъединения;
	Если Не РежимОбъединения Тогда
		ОчиститьПараметры();
		//УстановитьЗаголовокФормы();
		ЭтаФорма.ПроверочныйТекстНовый = ЗагружаемыеДанные.ПроверочныйТекст;
		ПроверочныйТекстДокументСформирован();
		Если ЗагружаемыеДанные.Свойство("ИгнорироватьРегистр") Тогда
			ЭтаФорма.ИгнорироватьРегистр = ЗагружаемыеДанные.ИгнорироватьРегистр;
		Иначе
			ЭтаФорма.ИгнорироватьРегистр = Истина;
		КонецЕсли; 
		Если ЗагружаемыеДанные.Свойство("Многострочный") Тогда
			ЭтаФорма.Многострочный = ЗагружаемыеДанные.Многострочный;
		Иначе
			ЭтаФорма.Многострочный = Истина;
		КонецЕсли; 
		Если ЗагружаемыеДанные.Свойство("ШаблонЗамены") Тогда
			ЭтаФорма.ШаблонЗамены = ЗагружаемыеДанные.ШаблонЗамены;
		Иначе
			ЭтаФорма.ШаблонЗамены = "";
		КонецЕсли; 
		Если ЗагружаемыеДанные.Свойство("ДвижокВычислителя") Тогда
			Если ЭлементыФормы.ДвижокВычислителя.СписокВыбора.НайтиПоЗначению(ЗагружаемыеДанные.ДвижокВычислителя) <> Неопределено Тогда
				УстановитьДвижокВычислителя(ЗагружаемыеДанные.ДвижокВычислителя);
			КонецЕсли;
		КонецЕсли; 
		// Здесь пока старый текст
		//мСтарыйПроверочныйТекст = ПроверочныйТекст();
		УстановитьПроверочныйТекст("");
	Иначе
		ПересечениеПараметров = ирОбщий.ПересечьМассивыЛкс(Параметры.ВыгрузитьКолонку("НИмя"), ЗагружаемыеДанные.Параметры.ВыгрузитьКолонку("НИмя"));
		Если ПересечениеПараметров.Количество() > 0 Тогда
			ирОбщий.СообщитьЛкс("Объединение параетров невозможно, т.к. есть конфликты имен: " + ирОбщий.РасширенноеПредставлениеЛкс(ПересечениеПараметров));
			Возврат;
		КонецЕсли; 
	КонецЕсли; 
	Попытка
		ирОбщий.ЗагрузитьВТаблицуЗначенийЛкс(ЗагружаемыеДанные.Параметры, Параметры);
	Исключение
	КонецПопытки;
	Если Параметры.Количество() > 0 Тогда
		// https://www.hostedredmine.com/issues/928806
		#Если Сервер И Не Сервер Тогда
			УстановитьТекущуюСтрокуПараметра();
		#КонецЕсли
		ПодключитьОбработчикОжидания("УстановитьТекущуюСтрокуПараметра", 0.1, Истина);
	КонецЕсли; 

КонецПроцедуры

Процедура ДействияФормыОбъединитьФайл(Кнопка)
	
	ОткрытьФайл(Истина);
	
КонецПроцедуры

Процедура СохранитьФайлДляВосстановления()
	
	//ОбновитьВыражениеПараметра(); // Рекурсия
	СохранитьВФайл(,, "*", Ложь);
	
КонецПроцедуры

Процедура ОбновлениеОтображения()
	
	ирОбщий.ОбновитьЗаголовокФормыСОткрытымФайломЛкс(ЭтаФорма, мИмяОткрытогоФайла);
	ирКлиент.Форма_ОбновлениеОтображенияЛкс(ЭтаФорма);
	
	//// Этот способ почему то выдавал количество без учета отбора
	//ПостроительТабличногоПоля = ирКлиент.ПостроительТабличногоПоляСОтборомКлиентаЛкс(ЭлементыФормы.Варианты);
	//#Если Сервер И Не Сервер Тогда
	//    ПостроительТабличногоПоля = Новый ПостроительЗапроса;
	//#КонецЕсли
	//КоличествоВариантов = ПостроительТабличногоПоля.Результат.Выбрать().Количество();
	//
	КоличествоВариантов = 0;
	Если мТекущаяСтрокаПараметра <> Неопределено Тогда
		КоличествоВариантов = Параметры.НайтиСтроки(Новый Структура("НИмя", мТекущаяСтрокаПараметра.НИмя)).Количество();
	КонецЕсли; 
	
	ирОбщий.ОбновитьТекстПослеМаркераЛкс(ЭлементыФормы.ПанельВыражение.Страницы.Варианты.Заголовок, , "" + КоличествоВариантов + ")", "(");
	
КонецПроцедуры

Процедура ДействияФормыНастройки(Кнопка = Неопределено)
	
	ФормаНастроек = ПолучитьФорму("Настройки", ЭтаФорма);
	ФормаНастроек.Открыть();
	
КонецПроцедуры

Процедура ДоступныеЭлементыНачалоПеретаскивания(Элемент, ПараметрыПеретаскивания, Выполнение)
	
	ТекстВставки = ТекстВставкиДоступногоЭлемента();
	//ТекстВставки = СтрЗаменить(ТекстВставки, "шаблон", "");
	ПараметрыПеретаскивания.Значение = ТекстВставки;
	
КонецПроцедуры

Функция ТекстВставкиДоступногоЭлемента()
	
	ТекстВставки = ЭлементыФормы.ДоступныеЭлементы.ТекущаяСтрока.ТекстВставки;
	Если Не ЗначениеЗаполнено(ТекстВставки) Тогда
		ТекстВставки = ЭлементыФормы.ДоступныеЭлементы.ТекущаяСтрока.Текст;
	КонецЕсли;
	Возврат ТекстВставки;

КонецФункции

Процедура ДоступныеЭлементыВыбор(Элемент, ВыбраннаяСтрока, Колонка, СтандартнаяОбработка)
	
	ВыделенныйТекст = ЭлементыФормы.ПолеТекстаВыражения.ВыделенныйТекст;
	ТекстВставки = ТекстВставкиДоступногоЭлемента();
	ТекстВставки = СтрЗаменить(ТекстВставки, "шаблон", ВыделенныйТекст);
	ЗаменитьИВыделитьВыделенныйТекстВыражения(ТекстВставки);
	
КонецПроцедуры

Процедура КПВыражениеУстановитьФокус(Кнопка)
	
	ЭтаФорма.ТекущийЭлемент = ЭлементыФормы.ПолеТекстаВыражения;
	
КонецПроцедуры

Процедура КПВыражение1ПроверитьСинтаксис(Кнопка)
	
	ПроверитьСинтаксис(, Истина);
	
КонецПроцедуры

Функция ПроверитьСинтаксис(ТекущаяСтрока = Неопределено, СообщатьРезультат = Ложь)
	
	Если ТекущаяСтрока = Неопределено Тогда
		ТекущаяСтрока = ЭлементыФормы.Параметры.ТекущаяСтрока;
	КонецЕсли; 
	Успех = Истина;
	ОписаниеОшибки = "";
	РегВычислительЛокальный.Pattern = РазвернутоеВыражение(ТекущаяСтрока);
	Попытка
		РегВычислительЛокальный.НайтиВхождения("_");
	Исключение
		ИнформацияОбОшибке = ИнформацияОбОшибке();
		Если ИнформацияОбОшибке.Причина <> Неопределено Тогда
			ИнформацияОбОшибке = ИнформацияОбОшибке.Причина;
		КонецЕсли; 
		ОписаниеОшибки = ИнформацияОбОшибке.Описание;
		Успех = Ложь;
	КонецПопытки;
	ТекущаяСтрока.Корректно = Успех;
	Если ТекущаяСтрока = ЭлементыФормы.Параметры.ТекущаяСтрока Тогда
		Если Успех Тогда
			ЭлементыФормы.ПолеТекстаВыражения.ЦветТекстаПоля = Новый Цвет;
		Иначе
			ЭлементыФормы.ПолеТекстаВыражения.ЦветТекстаПоля = WebЦвета.Красный;
		КонецЕсли; 
		Если СообщатьРезультат Тогда
			Если Не Успех Тогда
				ОбработатьОшибкуВычисленияВыражения(ОписаниеОшибки);
			Иначе
				Сообщить("Выражение корректно");
			КонецЕсли; 
		КонецЕсли; 
	КонецЕсли; 
	Возврат Успех;

КонецФункции 

Процедура НадписьПроверочныйТекстНажатие(Элемент)
	
	ОбновитьПроверочныйТекст(, Истина);
	
КонецПроцедуры

Процедура АвтообновлениеПроверочногоТекстаПриИзменении(Элемент)
	
	АвтообновлениеПроверочногоТекста();
	
КонецПроцедуры

Процедура АвтообновлениеПроверочногоТекста()
	
	Если АвтообновлениеПроверочногоТекста Тогда
		ОбновитьПроверочныйТекст();
	КонецЕсли;

КонецПроцедуры

Процедура ГруппыВыбор(Элемент, ВыбраннаяСтрока, Колонка, СтандартнаяОбработка)
	
	СтандартнаяОбработка = Ложь;
	ОбновитьПроверочныйТекст();
	Если Колонка = ЭлементыФормы.Группы.Колонки.Параметр И ВыбраннаяСтрока.Индекс >= 0 Тогда
		КлючПоиска = Новый Структура("Параметр, НомерВнутриРодителя", ВыбраннаяСтрока.Параметр, ВыбраннаяСтрока.НомерВнутриРодителя);
		ПерейтиКПараметру(ВыбраннаяСтрока.Параметр);
		ВыбраннаяСтрока = Группы.НайтиСтроки(КлючПоиска)[0];
		ЭлементыФормы.Группы.ТекущаяСтрока = ВыбраннаяСтрока;
		ЭлементыФормы.ПолеТекстаВыражения.УстановитьГраницыВыделения(ВыбраннаяСтрока.НачальнаяПозиция, ВыбраннаяСтрока.КонечнаяПозиция + 1);
		ЭтаФорма.ТекущийЭлемент = ЭлементыФормы.ПолеТекстаВыражения;
	КонецЕсли; 
	Если ВыбраннаяСтрока.Индекс >= 0 Тогда
		Попытка
			ЭлементыФормы.РазвернутоеВыражение.УстановитьГраницыВыделения(ВыбраннаяСтрока.НачальнаяПозицияРазвернутая, ВыбраннаяСтрока.КонечнаяПозицияРазвернутая + 1);
		Исключение
			// Временно до исправления ошибок вычисления позиций групп
		КонецПопытки; 
		Если Колонка <> ЭлементыФормы.Группы.Колонки.Параметр Тогда
			ЭтаФорма.ТекущийЭлемент = ЭлементыФормы.РазвернутоеВыражение;
		КонецЕсли; 
	КонецЕсли; 
	//ЭлементыФормы.ВхожденияГруппы.Колонки.Группы.Видимость = ВыбраннаяСтрока.Индекс = -1;
	
КонецПроцедуры

Процедура ПараметрыПриНачалеРедактирования(Элемент, НоваяСтрока, Копирование)
	
	ТекущаяСтрока = ЭлементыФормы.Параметры.ТекущаяСтрока;
	Если НоваяСтрока Тогда
		Если Копирование Тогда
			мТекущаяСтрокаПараметра = Неопределено;
			ПараметрыПриАктивизацииСтроки();
		КонецЕсли; 
		ЭлементыФормы.Параметры.ТекущаяСтрока.Имя = ирОбщий.АвтоУникальноеИмяВКоллекцииЛкс(Параметры, ТекущаяСтрока,,, "Параметр");
		ОбновитьИмяВНижнемРегистре();
	КонецЕсли; 
	мСтароеИмяПараметра = ТекущаяСтрока.Имя;
	
КонецПроцедуры

Процедура ПараметрыПередУдалением(Элемент, Отказ)
	
	Отказ = Истина;
	Если ИспользуетсяВ.Количество() > 0 Тогда
		Сообщить("Параметр используется в других параметрах");
	Иначе
		СтрокиКУдалению = Параметры.НайтиСтроки(Новый Структура("Имя", мТекущаяСтрокаПараметра.Имя));
		мТекущаяСтрокаПараметра = Неопределено;
		Для Каждого СтрокаПараметра Из СтрокиКУдалению Цикл
			Параметры.Удалить(СтрокаПараметра);
		КонецЦикла;
		Если Параметры.Количество() = 0 Тогда
			ДобавитьПервуюСтроку();
		КонецЕсли; 
	КонецЕсли; 
	
КонецПроцедуры

Процедура ДоступныеПараметрыВыбор(Элемент, ВыбраннаяСтрока, Колонка, СтандартнаяОбработка)
	
	ПерейтиКПараметру(ВыбраннаяСтрока.Имя);
	
КонецПроцедуры

Процедура ПараметрыПрочееПриВыводеСтроки(Элемент, ОформлениеСтроки, ДанныеСтроки) Экспорт
	
	ОформитьСтрокуПараметраОбщее(ОформлениеСтроки);
	
КонецПроцедуры

Процедура ИспользуетсяВВыбор(Элемент, ВыбраннаяСтрока, Колонка, СтандартнаяОбработка)
	
	ПерейтиКПараметру(ВыбраннаяСтрока.Имя, "<" + ЭлементыФормы.Параметры.ТекущаяСтрока.Имя + ">");

КонецПроцедуры

Процедура ПараметрыПриОкончанииРедактирования(Элемент, НоваяСтрока, ОтменаРедактирования)
	
	Если НоваяСтрока И ОтменаРедактирования Тогда
		Возврат;
	КонецЕсли;
	НовоеИмяПараметра = ирОбщий.АвтоУникальноеИмяВКоллекцииЛкс(Параметры, ЭлементыФормы.Параметры.ТекущаяСтрока);
	ЭлементыФормы.Параметры.ТекущаяСтрока.Имя = НовоеИмяПараметра;
	ОбновитьИмяВНижнемРегистре();
	Если НовоеИмяПараметра <> мСтароеИмяПараметра Тогда
		Для Каждого ВариантПараметра Из Параметры.НайтиСтроки(Новый Структура("НИмя, ЭтоВариант", НРег(мСтароеИмяПараметра), Истина)) Цикл
			ВариантПараметра.Имя = НовоеИмяПараметра;
			ОбновитьИмяВНижнемРегистре(ВариантПараметра);
		КонецЦикла;
		ОбращениеКПараметруНовое = мЛеваяСкобкаПараметра + НовоеИмяПараметра + мПраваяСкобкаПараметра;
		ОбращениеКПараметруСтарое = мЛеваяСкобкаПараметра + мСтароеИмяПараметра + мПраваяСкобкаПараметра;
		Для Каждого СтрокаПараметра Из Параметры Цикл
			СтрокаПараметра.Значение = ирОбщий.СтрЗаменитьЛкс(СтрокаПараметра.Значение, ОбращениеКПараметруСтарое, ОбращениеКПараметруНовое,, Ложь, Ложь);
		КонецЦикла;
		ПараметрыПриАктивизацииСтроки();
	КонецЕсли; 
	
КонецПроцедуры

Процедура КПВыражениеПерейтиКОпределению(Кнопка)
	
	НачальнаяПозиция = 0;
	КонечнаяПозиция = 0;
	ТекстВыражения = ЭлементыФормы.ПолеТекстаВыражения.Значение;
	ЭлементыФормы.ПолеТекстаВыражения.ПолучитьГраницыВыделения(НачальнаяПозиция, КонечнаяПозиция, НачальнаяПозиция, КонечнаяПозиция);
	НачалоСтроки = Лев(ТекстВыражения, КонечнаяПозиция - 1);
	КонецСтроки = Сред(ТекстВыражения, КонечнаяПозиция);
	Результат = ирОбщий.НайтиРегВыражениеЛкс(НачалоСтроки, мЛеваяСкобкаПараметра + "(" + шИмя + ")?$",, Ложь,,,,, РегВычислитель);
	#Если Сервер И Не Сервер Тогда
	    Вхождения = Обработки.ирПлатформа.Создать().ВхожденияРегВыражения;
	#КонецЕсли
	Если Результат.Количество() = 0 Тогда
		Возврат;
	КонецЕсли;
	НачалоИмени = Результат[0].Группы[0];
	Результат = ирОбщий.НайтиРегВыражениеЛкс(КонецСтроки, "^(" + шИмя + ")?" + мПраваяСкобкаПараметра,, Ложь,,,,, РегВычислитель);
	#Если Сервер И Не Сервер Тогда
	    Вхождения = Обработки.ирПлатформа.Создать().ВхожденияРегВыражения;
	#КонецЕсли
	Если Результат.Количество() = 0 Тогда
		Возврат;
	КонецЕсли;
	КонецИмени = Результат[0].Группы[0];
	ТекущееИмя = НачалоИмени + КонецИмени;
	Если ЗначениеЗаполнено(ТекущееИмя) Тогда
		ПерейтиКПараметру(ТекущееИмя);
	КонецЕсли; 
	
КонецПроцедуры

Процедура ПерейтиКПараметру(Знач ТекущееИмя, Знач ВыделитьФрагментВВыражении = "")
	
	ЭлементыФормы.Параметры.ТекущаяСтрока = СтрокаПараметраПоИмени(ТекущееИмя);
	Если ЗначениеЗаполнено(ВыделитьФрагментВВыражении) Тогда
		ирКлиент.НайтиПоказатьФрагментВПолеТекстаЛкс(ЭтаФорма, ЭлементыФормы.ПолеТекстаВыражения, ВыделитьФрагментВВыражении);
	КонецЕсли; 

КонецПроцедуры

Функция СтрокаПараметраПоИмени(Знач ТекущееИмя)
	
	Результат = Неопределено;
	НайденныеСтроки = Параметры.НайтиСтроки(Новый Структура("НИмя, ЭтоВариант", НРег(ТекущееИмя), Ложь));
	Если НайденныеСтроки.Количество() > 0 Тогда
		Результат = НайденныеСтроки[0];
	КонецЕсли; 
	Возврат Результат;

КонецФункции

Процедура ПредыдущееВхождениеНажатие(Элемент = Неопределено, ОбновитьРазметкуТекста = Ложь)
	Если ОбновитьРазметкуТекста <> Ложь Тогда
		ОбновитьПроверочныйТекст(Ложь);
	КонецЕсли; 
	Вхождение = мПолеТекстаПоиска.ПредыдущееВхождениеНажатие(ЭлементыФормы.Группы.ТекущаяСтрока.Индекс);
	Если Вхождение <> Неопределено Тогда
		ЭлементыФормы.ВхожденияГруппы.ТекущаяСтрока = Вхождение;
	КонецЕсли;
КонецПроцедуры

Процедура СледующееВхождениеНажатие(Элемент = Неопределено, ОбновитьРазметкуТекста = Ложь)
	Если ОбновитьРазметкуТекста <> Ложь Тогда
		ОбновитьПроверочныйТекст(Ложь);
	КонецЕсли; 
	Вхождение = мПолеТекстаПоиска.СледующееВхождениеНажатие(ЭлементыФормы.Группы.ТекущаяСтрока.Индекс);
	Если Вхождение <> Неопределено Тогда
		ЭлементыФормы.ВхожденияГруппы.ТекущаяСтрока = Вхождение;
	КонецЕсли;
КонецПроцедуры

Процедура УстановитьВыделениеВПроверочномТексте(Знач ВыделениеВТексте, Знач РодительскийУзел = Неопределено)
	мПолеТекстаПоиска.УстановитьВыделениеВДокументеHTML(ВыделениеВТексте, РодительскийУзел);
КонецПроцедуры

Процедура КПВыражениеЭкранироватьТекст(Кнопка)
	
	ВыделенныйТекст = ЭлементыФормы.ПолеТекстаВыражения.ВыделенныйТекст;
	Если Не ЗначениеЗаполнено(ВыделенныйТекст) Тогда
		ВыделенныйТекст = ЭлементыФормы.ПолеТекстаВыражения.Значение;
		Если Не ЗначениеЗаполнено(ВыделенныйТекст) Тогда
			Возврат;
		КонецЕсли; 
		ЭлементыФормы.ПолеТекстаВыражения.УстановитьГраницыВыделения(1, СтрДлина(ВыделенныйТекст) + 1);
	КонецЕсли; 
	ТекстВставки = ирОбщий.ТекстДляРегВыраженияЛкс(ВыделенныйТекст);
	ЗаменитьИВыделитьВыделенныйТекстВыражения(ТекстВставки);
	
КонецПроцедуры

Процедура ГруппыПриВыводеСтроки(Элемент, ОформлениеСтроки, ДанныеСтроки) Экспорт
	
	ОформлениеСтроки.Ячейки.Параметр.УстановитьТекст("*");
	
КонецПроцедуры

Процедура ПереносСловПриИзменении(Элемент)
	
	УстановитьПроверочныйТекст(ПроверочныйТекст());
	ОбновитьПроверочныйТекст();
	
КонецПроцедуры

Процедура ДействияФормыПараметрыИзБуфераОбмена(Кнопка)

	Текст = ирКлиент.ТекстИзБуфераОбменаОСЛкс();
	
	// Сначала пробуем найти расширенное описание выражения
	// Пример
	// Описание регулярного выражения для конструктора из подсистемы "Инструменты разработчика"
	// {Шаблон.Начало}
	//	 + <Комментарий> = (<Строка комментария>(?:\n<ПР><Строка комментария>)*)
	//	 + <Строка комментария> = (?://<Текст>$)
	//	 - <Строка комментария> = (?://\s*<Текст>$)
	// {Шаблон.Конец}
	ТекстРасширенный = ирОбщий.ТекстМеждуМаркерамиЛкс(Текст, "{Шаблон.Начало}", "{Шаблон.Конец}", Ложь);
	Вхождения = ирОбщий.НайтиРегВыражениеЛкс(ТекстРасширенный, "(\+|\-)\s*" + мЛеваяСкобкаПараметра + "(" + шИмя + ")" + мПраваяСкобкаПараметра + "\s*=\s*(.*)\r",,,,,,, РегВычислитель);
	#Если Сервер И Не Сервер Тогда
	    Вхождения = Обработки.ирПлатформа.Создать().ВхожденияРегВыражения;
	#КонецЕсли
	Если Вхождения.Количество() > 0 Тогда
		СпроситьОчиститьПараметры();
		Для Каждого Вхождение Из Вхождения Цикл
			ИмяПараметра = Вхождение.Группы[1];
			СтрокаПараметра = Параметры.Найти(НРег(ИмяПараметра), "НИмя");
			Если СтрокаПараметра = Неопределено Тогда
				СтрокаПараметра = Параметры.Вставить(0);
				СтрокаПараметра.Имя = ИмяПараметра;
				ОбновитьИмяВНижнемРегистре(СтрокаПараметра);
			Иначе
				Параметры.Сдвинуть(СтрокаПараметра, -Параметры.Индекс(СтрокаПараметра));
			КонецЕсли; 
			СтрокаПараметра.ЭтоВариант = Вхождение.Группы[0] = "-";
			СтрокаПараметра.Значение = Вхождение.Группы[2];
			ПроверитьСинтаксис(СтрокаПараметра);
		КонецЦикла;
	Иначе
		// Теперь пробуем найти описание выражения в виде кода 1С
		// {ОписаниеРегулярногоВыражения.Начало} конструктор из подсистемы "Инструменты разработчика" (http://devtool1c.ucoz.ru)
		// Перем Комментарий1С, Разделитель1С, Идентификатор, ЛитералСтрока1С, СтроковоеВыражение1С, ИмяПараметра, ПрисвоениеСтроковогоЗначения;
		// {Шаблон.Начало}
		// + <Комментарий1С> = //[^\n]*\n
		// + <Разделитель1С> = (?:<Комментарий1С>|\s|^|$)
		// + <Идентификатор> = (?:[_ЁА-ЯA-Z][_ЁА-ЯA-Z0-9]*)
		// + <ЛитералСтрока1С> = "(?:(?:"")|[^"\n])*(?:<Разделитель1С>*\|(?:(?:"")|[^"\n])*)*(?:"|$)
		// + <СтроковоеВыражение1С> = (<ЛитералСтрока1С>(?:\s*\+\s*(?:<ЛитералСтрока1С>|<Идентификатор>))*)
		// + <ИмяПараметра> = (<Идентификатор>)
		// + <ПрисвоениеСтроковогоЗначения> = <ИмяПараметра>\s*=\s*<СтроковоеВыражение1С>\s*;
		// {Шаблон.Конец}
		Комментарий1С = "//[^\n]*\n";
		Разделитель1С = "(?:" + Комментарий1С + "|\s|^|$)";
		Идентификатор = "(?:[" + мПлатформа.шБуква + "][" + мПлатформа.шБукваЦифра + "]*)";
		ЛитералСтрока1С = """(?:(?:"""")|[^""\n])*(?:" + Разделитель1С + "*\|(?:(?:"""")|[^""\n])*)*(?:""|$)";
		СтроковоеВыражение1С = "(" + ЛитералСтрока1С + "(?:\s*\+\s*(?:" + ЛитералСтрока1С + "|" + Идентификатор + "))*)";
		ИмяПараметра = "(" + Идентификатор + ")";
		ПрисвоениеСтроковогоЗначения = "" + ИмяПараметра + "\s*=\s*" + СтроковоеВыражение1С + "\s*;";
		// {ОписаниеРегулярногоВыражения.Конец}
		Вхождения = ирОбщий.НайтиРегВыражениеЛкс(Текст, ПрисвоениеСтроковогоЗначения,,,,,,, РегВычислитель);
		#Если Сервер И Не Сервер Тогда
		    Вхождения = Обработки.ирПлатформа.Создать().ВхожденияРегВыражения;
		#КонецЕсли
		Если Вхождения.Количество() > 0 Тогда
			СпроситьОчиститьПараметры();
			Для каждого Вхождение Из Вхождения Цикл
				ИмяПараметра = Вхождение.Группы[0];
				ПрисвоенноеЗначение = Вхождение.Группы[1];
				// {ОписаниеРегулярногоВыражения.Начало} конструктор из подсистемы "Инструменты разработчика" (http://devtool1c.ucoz.ru)
				// Перем Комментарий1С, Разделитель1С, Идентификатор, ЛитералСтрока1С, СтроковоеВыражение1С;
				// {Шаблон.Начало}
				// + <Комментарий1С> = //[^\n]*\n
				// + <Разделитель1С> = (?:<Комментарий1С>|\s|^|$)
				// + <Идентификатор> = ([_ЁА-ЯA-Z][_ЁА-ЯA-Z0-9]*)
				// + <ЛитералСтрока1С> = ("(?:(?:"")|[^"\n])*(?:<Разделитель1С>*\|(?:(?:"")|[^"\n])*)*(?:"|$))
				// + <СтроковоеВыражение1С> = <ЛитералСтрока1С>|\s*\+\s*|<Идентификатор>
				// {Шаблон.Конец}
				Комментарий1С = "//[^\n]*\n";
				Разделитель1С = "(?:" + Комментарий1С + "|\s|^|$)";
				Идентификатор = "([" + мПлатформа.шБуква + "][" + мПлатформа.шБукваЦифра + "]*)";
				ЛитералСтрока1С = "(""(?:(?:"""")|[^""\n])*(?:" + Разделитель1С + "*\|(?:(?:"""")|[^""\n])*)*(?:""|$))";
				СтроковоеВыражение1С = "" + ЛитералСтрока1С + "|\s*\+\s*|" + Идентификатор + "";
				// {ОписаниеРегулярногоВыражения.Конец}
				Вхождения = ирОбщий.НайтиРегВыражениеЛкс(ПрисвоенноеЗначение, СтроковоеВыражение1С,,,,,,, РегВычислитель);
				ВыражениеПараметра = "";
				Для каждого Вхождение Из Вхождения Цикл
					ЛитералСтрока1С = Вхождение.Группы[0];
					Идентификатор = Вхождение.Группы[1];
					Если ЛитералСтрока1С <> Неопределено Тогда
						ВыражениеПараметра = ВыражениеПараметра + ирОбщий.ТекстИзВстроенногоЯзыкаЛкс(ЛитералСтрока1С);
					ИначеЕсли Идентификатор <> Неопределено Тогда
						ВыражениеПараметра = ВыражениеПараметра + мЛеваяСкобкаПараметра + Идентификатор + мПраваяСкобкаПараметра;
					КонецЕсли; 
				КонецЦикла;
				СтрокаПараметра = Параметры.Найти(НРег(ИмяПараметра), "НИмя");
				Если СтрокаПараметра = Неопределено Тогда
					СтрокаПараметра = Параметры.Вставить(0);
					СтрокаПараметра.Имя = ИмяПараметра;
					ОбновитьИмяВНижнемРегистре(СтрокаПараметра);
				Иначе
					Параметры.Сдвинуть(СтрокаПараметра, -Параметры.Индекс(СтрокаПараметра));
				КонецЕсли; 
				СтрокаПараметра.Значение = ВыражениеПараметра;
				ПроверитьСинтаксис(СтрокаПараметра);
			КонецЦикла;
		КонецЕсли; 
	КонецЕсли;
	Если Вхождения.Количество() = 0 Тогда
		Сообщить("В буфере обмена не найдено описания выражения");
		Возврат;
	КонецЕсли; 
	ЭтаФорма.Модифицированность = Истина;
	УстановитьТекущуюСтрокуПараметра();
	
КонецПроцедуры

Процедура СпроситьОчиститьПараметры()
	
	Ответ = Вопрос("Очистить текущие параметры?", РежимДиалогаВопрос.ДаНет,, КодВозвратаДиалога.Да);
	Если Ответ = КодВозвратаДиалога.Да Тогда
		Если ПроверитьСохранитьПолноеВыражение() Тогда
			ОчиститьПараметры();
		КонецЕсли; 
	КонецЕсли;

КонецПроцедуры

Процедура ДоступныеПараметрыПриВыводеСтроки(Элемент, ОформлениеСтроки, ДанныеСтроки) Экспорт
	
	ОформитьСтрокуПараметраОбщее(ОформлениеСтроки);
	Если ДанныеСтроки.Использован Тогда
		ОформлениеСтроки.ЦветФона = WebЦвета.СветлоЖелтый;
	КонецЕсли;
	ОформлениеСтроки.Ячейки.Имя.УстановитьТекст(мЛеваяСкобкаПараметра + ДанныеСтроки.Имя + мПраваяСкобкаПараметра);
	
КонецПроцедуры

Процедура ОформитьСтрокуПараметраОбщее(Знач ОформлениеСтроки)
	
	Если Не ОформлениеСтроки.ДанныеСтроки.Корректно Тогда
		ОформлениеСтроки.ЦветТекста = WebЦвета.Красный;
	КонецЕсли;

КонецПроцедуры

Процедура МногострочныйПриИзменении(Элемент)
	
	АвтообновлениеПроверочногоТекста();
	
КонецПроцедуры

Процедура ИгнорироватьРегистрПриИзменении(Элемент)
	
	АвтообновлениеПроверочногоТекста();

КонецПроцедуры

Процедура ОбновитьПроверочныйТекстОтложенно()
	
	ОбновитьПроверочныйТекст(Ложь);
	
КонецПроцедуры

Процедура ПроверочныйТекстonkeypress(Элемент, pEvtObj)
	
	Если АвтообновлениеПроверочногоТекста Тогда
		ПодключитьОбработчикОжидания("ОбновитьПроверочныйТекстОтложенно", 1, Истина);
	КонецЕсли; 
	
КонецПроцедуры

Процедура КП_ПроверочныйТекстОткрытьТаблицуРезультатов(Кнопка)
	
	Вхождения = ВычислитьВхождения(Истина);
	Если Вхождения = Неопределено Тогда
		Возврат;
	КонецЕсли; 
	ирКлиент.ОткрытьЗначениеЛкс(Вхождения,,,, Ложь);
	
КонецПроцедуры

Функция ВычислитьВхождения(СообщатьОшибки = Ложь)
	
	Текст = ПроверочныйТекст();
	ПараметрыСоСписками = Параметры.НайтиСтроки(Новый Структура("Список, ЭтоВариант", Истина, Ложь));
	Пока ПараметрыСоСписками.Количество() > 0 И ПараметрыСоСписками[0].НомерСтроки <= мТекущаяСтрокаПараметра.НомерСтроки Цикл
		ПараметрыСоСписками.Удалить(0);
	КонецЦикла;
	РазвернутоеВыражениеПараметра = РазвернутоеВыражение();
	Если РазвернутоеВыражениеПараметра = "" Тогда
		Возврат Неопределено;
	КонецЕсли;
	Если ИменаГруппВместоИндексов Тогда
		СтрокаИменаГрупп = ирОбщий.СтрСоединитьЛкс(ИменаГрупп());
	КонецЕсли;
	Вхождения = ирОбщий.НайтиРегВыражениеЛкс(Текст, РазвернутоеВыражениеПараметра, СтрокаИменаГрупп,, ИгнорироватьРегистр, Многострочный, Ложь,, РегВычислитель,,, мТекущаяСтрокаПараметра.Длительность);
	Если ТипЗнч(Вхождения) = Тип("Строка") Тогда
		Если СообщатьОшибки Тогда
			ОбработатьОшибкуВычисленияВыражения(Вхождения);
		КонецЕсли;
		Возврат Неопределено;
	КонецЕсли; 
	Для Каждого Вхождение Из Вхождения Цикл
		Если ПараметрыСоСписками.Количество() > 0 Тогда 
			СтрокаПараметраСоСписком = ПараметрыСоСписками[0];
			РазвернутоеВыражениеВложенное = РазвернутоеВыражение(СтрокаПараметраСоСписком);
			Если Не ЗначениеЗаполнено(РазвернутоеВыражениеВложенное) Тогда
				Продолжить;
			КонецЕсли; 
			Если Вхождения.Колонки.Найти(СтрокаПараметраСоСписком.Имя) = Неопределено Тогда
				Вхождения.Колонки.Добавить(СтрокаПараметраСоСписком.Имя);
			КонецЕсли; 
			ВложенныеВхождения = ирОбщий.НайтиРегВыражениеЛкс(Вхождение.ТекстВхождения, РазвернутоеВыражениеВложенное,,, ИгнорироватьРегистр, Многострочный, Ложь,, РегВычислитель);
			#Если Сервер И Не Сервер Тогда
				ВложенныеВхождения = Обработки.ирПлатформа.Создать().ВхожденияРегВыражения;
			#КонецЕсли
			Если ТипЗнч(ВложенныеВхождения) = Тип("Строка") Тогда
				Продолжить;
			КонецЕсли; 
			Вхождение[СтрокаПараметраСоСписком.Имя] = ВложенныеВхождения;
		КонецЕсли; 
	КонецЦикла;
	РазвернутоеВыражение(); // Для восстановления доступных параметров
	Возврат Вхождения;

КонецФункции

Процедура ОбработатьОшибкуВычисленияВыражения(Знач ТекстОшибки) Экспорт
	ТекстОшибки = РегВычислитель.ОбработатьТекстОшибки(ТекстОшибки, РазвернутоеВыражение());
	ирОбщий.СообщитьЛкс(ТекстОшибки, СтатусСообщения.Внимание);
КонецПроцедуры

Процедура ДействияФормыПрименить(Кнопка)
	
	ирКлиент.ПрименитьИзмененияИЗакрытьФормуЛкс(ЭтаФорма, РазвернутоеВыражение);
	
КонецПроцедуры

Процедура КПВыражениеРазэкранироватьТекст(Кнопка)
	// Вставить содержимое обработчика.
КонецПроцедуры

Процедура КПВыражениеОткрытьВыражениеНаСайтеRegex101(Кнопка)
	
	Если ирКэш.НомерВерсииПлатформыЛкс() < 803001 Тогда
		ирОбщий.СообщитьЛкс("Для функции требуется платформа 8.3 и выше");
		Возврат;
	КонецЕсли;
	// опции похоже уже не работают
	СтрокаURL = "https://regex101.com/?regex=" + РазвернутоеВыражениеДляЗапросаКСайту() + "&options=g" + ?(Многострочный, "m", "") + ?(ИгнорироватьРегистр, "i", "");
	ЗапуститьПриложение(СтрокаURL);
	
КонецПроцедуры

Функция РазвернутоеВыражениеДляЗапросаКСайту()
	
	КодированнаяСтрока = Вычислить("КодироватьСтроку(РазвернутоеВыражение, СпособКодированияСтроки.КодировкаURL)");
	Возврат КодированнаяСтрока;

КонецФункции

Процедура ПараметрыПриИзмененииФлажка(Элемент, Колонка)
	
	ирКлиент.ТабличноеПолеПриИзмененииФлажкаЛкс(ЭтаФорма, Элемент, Колонка);
	
КонецПроцедуры

Процедура ВхожденияГруппыВыбор(Элемент, ВыбраннаяСтрока, Колонка, СтандартнаяОбработка)
	
	Если Ложь
		Или Колонка = ЭлементыФормы.ВхожденияГруппы.Колонки.ЗначениеГруппы 
		Или Колонка = ЭлементыФормы.ВхожденияГруппы.Колонки.ПозицияГруппы
		Или Колонка = ЭлементыФормы.ВхожденияГруппы.Колонки.ДлинаГруппы
	Тогда
		мПолеТекстаПоиска.ВыделитьРезультатПоиска(ВыбраннаяСтрока, ЭлементыФормы.Группы.ТекущаяСтрока.Индекс);
	Иначе
		ирКлиент.ЯчейкаТабличногоПоляРасширенногоЗначения_ВыборЛкс(ЭтаФорма, Элемент, СтандартнаяОбработка);
	КонецЕсли; 
	
КонецПроцедуры

Процедура КлсКомандаНажатие(Кнопка) Экспорт 
	
	ирКлиент.УниверсальнаяКомандаФормыЛкс(ЭтаФорма, Кнопка);
	
КонецПроцедуры

Процедура ВнешнееСобытие(Источник, Событие, Данные) Экспорт
	
	ирКлиент.Форма_ВнешнееСобытиеЛкс(ЭтаФорма, Источник, Событие, Данные);

КонецПроцедуры

Процедура ТабличноеПолеПриПолученииДанных(Элемент, ОформленияСтрок) Экспорт 
	
	ирКлиент.ТабличноеПолеПриПолученииДанныхЛкс(ЭтаФорма, Элемент, ОформленияСтрок);

КонецПроцедуры

Процедура ОбработкаОповещения(ИмяСобытия, Параметр, Источник) Экспорт
	
	ирКлиент.Форма_ОбработкаОповещенияЛкс(ЭтаФорма, ИмяСобытия, Параметр, Источник); 

КонецПроцедуры

Процедура ВариантыПередУдалением(Элемент, Отказ)
	
	Если Параметры.НайтиСтроки(Новый Структура("НИмя", НРег(мТекущаяСтрокаПараметра.Имя))).Количество() = 1 Тогда
		Отказ = Истина;
		Возврат;
	КонецЕсли; 
	мТекущаяСтрокаПараметра = Неопределено;

КонецПроцедуры

Процедура ВариантыПередНачаломДобавления(Элемент, Отказ, Копирование)
	
	Отказ = Истина;
	СтрокаПараметра = Параметры.Вставить(Параметры.Индекс(мТекущаяСтрокаПараметра) + 1);
	ЗаполнитьЗначенияСвойств(СтрокаПараметра, ЭлементыФормы.Параметры.ТекущаяСтрока); 
	СтрокаПараметра.ЭтоВариант = Истина;

КонецПроцедуры

Процедура КПВыражениеСравнить(Кнопка)
	
	ирКлиент.ЗапомнитьСодержимоеЭлементаФормыДляСравненияЛкс(ЭтаФорма, ЭлементыФормы.ПолеТекстаВыражения);
	
КонецПроцедуры

Процедура ПараметрыПередОкончаниемРедактирования(Элемент, НоваяСтрока, ОтменаРедактирования, Отказ)
	Если ОтменаРедактирования И НоваяСтрока Тогда
		мТекущаяСтрокаПараметра = Неопределено;
	КонецЕсли; 
КонецПроцедуры

Процедура ПроверочныйТекстДокументСформирован(Элемент = Неопределено)
	
	Если ЗначениеЗаполнено(ПроверочныйТекстНовый) Тогда
		ЭлементыФормы.ПроверочныйТекст.УстановитьТекст(ПроверочныйТекстНовый);
		Если Элемент <> Неопределено Тогда
			ЭтаФорма.ПроверочныйТекстНовый = "";
		КонецЕсли; 
	КонецЕсли; 

КонецПроцедуры

Процедура ВхожденияГруппыПриВыводеСтроки(Элемент, ОформлениеСтроки, ДанныеСтроки) Экспорт
	
	ирКлиент.ТабличноеПолеПриВыводеСтрокиЛкс(ЭтаФорма, Элемент, ОформлениеСтроки, ДанныеСтроки, ЭлементыФормы.КП_Вхождения.Кнопки.Идентификаторы);
	
КонецПроцедуры

Процедура ВхожденияГруппыПриАктивизацииСтроки(Элемент)
	
	ирКлиент.ТабличноеПолеПриАктивизацииСтрокиЛкс(ЭтаФорма, Элемент);
	
КонецПроцедуры

Процедура ПараметрыВыбор(Элемент, ВыбраннаяСтрока, Колонка, СтандартнаяОбработка)
	
	Если Колонка = ЭлементыФормы.Параметры.Колонки.Значение Тогда
		ОбновитьПроверочныйТекст();
	КонецЕсли; 

КонецПроцедуры

Процедура ПараметрыСписокПриИзменении(Элемент)
	
	Для Каждого СтрокаПараметра Из Параметры Цикл
		СтрокаПараметра.Список = Истина
			И мТекущаяСтрокаПараметра.НИмя = СтрокаПараметра.НИмя
			И мТекущаяСтрокаПараметра.Список;
	КонецЦикла;

КонецПроцедуры

Процедура КП_ПроверочныйТекстОтладитьСПозицииRegexBuddy(Кнопка)
	
	ОткрытьВыражениеВRegexBuddy(Истина);
	
КонецПроцедуры

// Сохраняет имя файла и путь к нему для использования в последующих сеансах работы
//
// Параметры:
//  Нет.
//
Процедура СохранитьИмяФайла()
	
	ирОбщий.СохранитьЗначениеЛкс(Метаданные().Имя + "_ИмяФайла", мИмяОткрытогоФайла);
	Если ЗначениеЗаполнено(мИмяОткрытогоФайла) Тогда
		ирКлиент.ДобавитьФайлВИсториюФормыЛкс(мИсторияФайлов, мИмяОткрытогоФайла);
		ирОбщий.СохранитьЗначениеЛкс(Метаданные().Имя + "_ИсторияФайлов", мИсторияФайлов);
		ОбновитьПодменюИсторииФайлов();
	КонецЕсли; 
	
КонецПроцедуры

Процедура ОбновитьПодменюИсторииФайлов()
	
	//Если Не мРежимРедактора Тогда
		Кнопки = ЭлементыФормы.ДействияФормы.Кнопки.ОткрытьПоследние.Кнопки;
		ирКлиент.ОбновитьПодменюИсторииФайловЛкс(мИсторияФайлов, Кнопки);
	//КонецЕсли; 
	
КонецПроцедуры

Процедура ОткрытьФайлИзИстории(Кнопка) 
	
	Если СохранитьВФайл(Истина) Тогда
		СтрокаИстории = мИсторияФайлов[Число(Сред(Кнопка.Имя, 2))];
		ОткрытьФайлПоПолномуИмени(СтрокаИстории.Значение);
	КонецЕсли;
	
КонецПроцедуры

Процедура ОткрытьФайлПоПолномуИмени(ПолноеИмяФайла, РежимОбъединения = Ложь)
	
	Если РежимОбъединения Тогда
		ЗагрузитьИзФайла(ПолноеИмяФайла);
	Иначе
		мИмяОткрытогоФайла = ПолноеИмяФайла;
		ЗагрузитьИзФайла();
	КонецЕсли; 
	СохранитьИмяФайла();
	
КонецПроцедуры

Процедура ИменаГруппВместоИндексовПриИзменении(Элемент)
	
	ОбновитьПроверочныйТекст();
	
КонецПроцедуры

Процедура ПередОткрытием(Отказ, СтандартнаяОбработка)
	ирОбщий.ПроверитьПлатформаНеWindowsЛкс(Отказ,, Истина);
	ЭлементыФормы.ДвижокВычислителя.СписокВыбора = РегВычислитель.ДоступныеДвижки(Ложь);
	ЭтаФорма.ДвижокВычислителя = РегВычислитель.ТекущийДвижок();
КонецПроцедуры

Процедура БиблиотекаВычислителяПриИзменении(Элемент = Неопределено)
	
	УстановитьДвижокВычислителя(ДвижокВычислителя);
	АвтообновлениеПроверочногоТекста();
	
КонецПроцедуры

//.
// Параметры:
//    ДвижокВычислителя - Строка(10) - 
Процедура УстановитьДвижокВычислителя(Знач ДвижокВычислителя) Экспорт
	ЭтаФорма.ДвижокВычислителя = ДвижокВычислителя;
	РегВычислитель.УстановитьДвижок(ДвижокВычислителя);
	РегВычислительЛокальный.УстановитьДвижок(ДвижокВычислителя);
КонецПроцедуры

Процедура ЗаменитьНажатие(Элемент)
	СтарыйТекст = ПроверочныйТекст(); 
	#Если Сервер И Не Сервер Тогда
		РегВычислитель = Обработки.ирОболочкаРегВыражение.Создать();
	#КонецЕсли  
	РегВычислитель.Pattern = РазвернутоеВыражение();
	НовыйТекст = РегВычислитель.Заменить(СтарыйТекст, ШаблонЗамены);
	ирКлиент.Сравнить2ЗначенияВФормеЛкс(СтарыйТекст, НовыйТекст,, "Оригинал", "Замена");
КонецПроцедуры

Процедура ШаблонЗаменыПриИзменении(Элемент)
	ирКлиент.ПолеВводаСИсториейВыбора_ПриИзмененииЛкс(Элемент, ЭтаФорма);
КонецПроцедуры

Процедура ШаблонЗаменыНачалоВыбораИзСписка(Элемент, СтандартнаяОбработка)
	ирОбщий.ПолеВводаСИсториейВыбора_ОбновитьСписокЛкс(Элемент, ЭтаФорма);
КонецПроцедуры

Процедура ШаблонЗаменыНачалоВыбора(Элемент, СтандартнаяОбработка)
	
	ирКлиент.ПолеВводаРасширенногоЗначения_НачалоВыбораЛкс(Элемент, СтандартнаяОбработка);
	
КонецПроцедуры

Процедура ДоступныеЭлементыПриАктивизацииСтроки(Элемент)
	ирКлиент.ТабличноеПолеПриАктивизацииСтрокиЛкс(ЭтаФорма, Элемент);
КонецПроцедуры

Процедура ДоступныеЭлементыПриВыводеСтроки(Элемент, ОформлениеСтроки, ДанныеСтроки) Экспорт
	ирКлиент.ТабличноеПолеПриВыводеСтрокиЛкс(ЭтаФорма, Элемент, ОформлениеСтроки, ДанныеСтроки);
КонецПроцедуры

Процедура КПВыражениеОткрытьСхему(Кнопка)
	РазвернутоеВыражениеДляЗапросаКСайту = РазвернутоеВыражениеДляЗапросаКСайту();
	//ИнтернетПрокси = Новый ИнтернетПрокси(ИСТИНА);
	//СерверЗапроса = "regex101.com";
	//ПортВременный = 443;
	//ТаймаутЗапроса = 1;
	//СоединениеHTTP = ирОбщий.СоединениеHTTPЛкс(СерверЗапроса, ПортВременный,,, ИнтернетПрокси, ТаймаутЗапроса, Истина);
	//АдресРесурсаСПараметрами = "/?regex=" + РазвернутоеВыражениеДляЗапросаКСайту;
	//ЗапросHTTP = ирОбщий.ЗапросHTTPЛкс(АдресРесурсаСПараметрами);
	//ОтветHTTP = СоединениеHTTP.ВызватьHTTPМетод("GET", ЗапросHTTP);
	//КодСостояния = ОтветHTTP.КодСостояния;
	//ТелоОтветаСтрока = ОтветHTTP.ПолучитьТелоКакСтроку();
	//ПостроительDOM = Новый ПостроительDOM();
	//ЧтениеHTML = Новый ЧтениеHTML;
	//ЧтениеHTML.УстановитьСтроку(ТелоОтветаСтрока);
	//ДокументHTML = ПостроительDOM.Прочитать(ЧтениеHTML);
	//ирОбщий.ИсследоватьЛкс(ДокументHTML);
	Адрес = "https://regex-vis.com/?r=" + РазвернутоеВыражениеДляЗапросаКСайту;
	ЗапуститьПриложение(Адрес);
КонецПроцедуры

Процедура КП_ПроверочныйТекстКонструкторПоТексту(Кнопка)
	ВыделенныйТекст = "";
	мПолеТекстаПоиска.ПолучитьВыделениеВДокументеHTML(ВыделенныйТекст);
	КодированнаяСтрока = Вычислить("КодироватьСтроку(ВыделенныйТекст, СпособКодированияСтроки.КодировкаURL)");
	Адрес = "https://regex-generator.olafneumann.org/?sampleText=" + КодированнаяСтрока;
	ЗапуститьПриложение(Адрес);
КонецПроцедуры

Процедура КПВыражениеОткрытьВыражениеНаСайтеRegExr(Кнопка) 
	РазвернутоеВыражениеДляЗапросаКСайту = РазвернутоеВыражениеДляЗапросаКСайту();
	ПроверочныйТекст = Лев(ПроверочныйТекст(), 1000);
	ПроверочныйТекст = Вычислить("КодироватьСтроку(ПроверочныйТекст, СпособКодированияСтроки.КодировкаURL)");
	Адрес = "https://RegExr.com/?expression=/" + РазвернутоеВыражениеДляЗапросаКСайту + "/g" + ?(Многострочный, "m", "") + ?(ИгнорироватьРегистр, "i", "") 
		+ "&engine=" + ?(ДвижокВычислителя = РегВычислитель.ВсеДвижки().PCRE2, "pcre", "js") + "&text=" + ПроверочныйТекст;
	ЗапуститьПриложение(Адрес);
КонецПроцедуры

Процедура ДействияФормыОткрытьФайлВосстановления(Кнопка)
	ирКлиент.ОткрытьНовоеОкноФормыЛкс(ЭтаФорма, мСтруктураВосстановления); 
КонецПроцедуры

Процедура ИзменитьСвернутостьРазвернутоеВыражение(Знач Видимость, Знач ПередЗакрытием = Ложь)
	
	ирКлиент.ИзменитьСвернутостьЛкс(ЭтаФорма, Видимость, ЭлементыФормы.РазвернутоеВыражение, ЭтаФорма.ЭлементыФормы.Разделитель5, ЭлементыФормы.ПанельВыражение, "низ",, Ложь);
	
КонецПроцедуры

ирКлиент.ИнициироватьФормуЛкс(ЭтаФорма, "Обработка.ирКонструкторРегулярногоВыражения.Форма.Форма");
#Если Сервер И Не Сервер Тогда
	мПолеТекстаПоиска = Обработки.ирОболочкаПолеТекста.Создать();
#КонецЕсли
мПлатформа = ирКэш.Получить();
шИмя = мПлатформа.шИмя;
РегВычислитель = ирОбщий.НовоеРегВыражениеЛкс();
РегВычислительЛокальный = ирОбщий.НовоеРегВыражениеЛкс();
мЛеваяСкобкаПараметра = "<";
мПраваяСкобкаПараметра = ">";
мРежимРедактора = Ложь;
мРасширениеФайла = "rep";
мОписаниеРасширенияФайла = "Описание регулярного выражения";
ВхожденияГруппы.Колонки.Добавить("Позиция");
ВхожденияГруппы.Колонки.Добавить("Длина");
ВхожденияГруппы.Колонки.Добавить("Значение");
мНачальноеКоличествоКолонок = ВхожденияГруппы.Колонки.Количество();
АвтообновлениеПроверочногоТекста = Истина;
Автовыделение = Истина;
ПереносСлов = Истина;
мСтруктураВосстановления = ирКлиент.НоваяСтруктураВосстановленияКонсолиЛкс("irRegexpConstructor");
ЭтаФорма.ПроверочныйТекстНовый = "не загружен";