IniManager

Название IniManager
Имя файла (*.txt) IniManager.txt
Описание Создает и обновляет файлы конфигурации для разных целей
Автор Вахмурка
Параметры "b"|"s"|"r"|"c"|"n"|"i"|"имя_конфигурации"
(см. комментарии)
Вызываемые плагины ini, file, vec, win, miscplugin
Версия 3.0
Дата обновления 03.03.15
;;Если wincmd.ini находится не в директории Windows, укажите его полный путь:
static Config = env("WINDIR") ++ "\wincmd.ini"
local hwnd = win.handle("c=TTOTAL_CMD")
local TotalPath = file.folder(win.exepath(hwnd))
local Total = TotalPath ++ "\" ++ ifelse(arg(2), arg(2), win.exename(hwnd)) ++ ".exe"
;"\inis\" – имя поддиректории %COMMANDER_PATH%, в которой лежат разные файлы конфигурации
local Path = TotalPath ++ "\inis\"
local Backup = Path ++ "Backup.ini"
local j, k, OneSec, OneKey, NewKeys, MainKeys, Counter, NewValue, MainValue, Name 
local MainSections, MainNumber, TempConf
static I = ".ini"
static IMS = "IniManager Script"
ini.error_dialog_off()

v = vec.createfromwords("left right lefttabs righttabs")
if(v <= 0) do
	messagebox("ok error", "Vector not created", "VEC plugin error #1")
	quit
endif

if(arg(1) == "b") do
	file.copy(Config, Backup)
	quit
elseif(arg(1) == "r") do
	file.copy(Backup, Config)
	win.sendmessage(hwnd, 0x400+51, 24340, 0)

	for(j = 0; j < 4; j++)
		ini.delete_section(Backup, v[j])
		ini.copy_section(v[j], Backup, v[j], Config)
	endfor

	do(Total)
	quit
elseif(arg(1) == "s") do
	jump Save
elseif(arg(1) == "c") do
	jump Copy
elseif(arg(1) == "n") do
	jump New
elseif(arg(1) == "i") do
	jump Insert
endif

Name = arg(1)
TempConf = miscplugin.tempfilename(Name, Path) ++ I
Name = Path ++ Name ++ I
MainSections = ini.enum_sections(Config)
MainNumber = line(MainSections, 0)

for(j = 1; j <= MainNumber; j++)
	OneSec = line(MainSections, j)
	MainKeys = ini.enum_keys(Config, OneSec)
	Counter = line(MainKeys, 0)
	if(ini.check_exists(Name, OneSec) == 2) do
		for(k = 1; k <= Counter; k++)
			OneKey = line(MainKeys, k)
			if(ini.check_exists(Name, OneSec, OneKey) == 3) do
				NewValue = ini.get(Name, OneSec, OneKey)
			else
				NewValue = ini.get(Config, OneSec, OneKey)
			endif
		ini.set(TempConf, OneSec, OneKey, NewValue)
		endfor
	else
		ini.copy_section(OneSec, Config, OneSec, TempConf)
	endif
endfor

for(j = 0; j < 4; j++)
	ini.delete_section(TempConf, v[j]) 
	ini.copy_section(v[j], Name, v[j], TempConf)
endfor

do(Total, "/n /i=" ++ TempConf)

quit

@Save
win.sendmessage(hwnd, 0x400+51, 580, 0)
MainSections = ini.enum_sections(Backup)
MainNumber = line(MainSections, 0)
Name = inputcancel("Input new INI file name")
Name = Path ++ Name ++ I
flag set 1

for(j = 1; j <= MainNumber; j++)
	OneSec = line(MainSections, j)
	if(ini.check_exists(Config, OneSec) == 2) do
		MainKeys = ini.enum_keys(Backup, OneSec)
		Counter = line(MainKeys, 0)

		for(k = 1; k <= Counter; k++)
			OneKey = line(MainKeys, k)
			if(ini.check_exists(Config, OneSec, OneKey) == 3) do
				NewValue = ini.get(Config, OneSec, OneKey) 
				MainValue = ini.get(Backup, OneSec, OneKey)
				if(NewValue != MainValue) do
					ini.set(Name, OneSec, OneKey, NewValue)
					flag clear 1
				endif
			endif
		endfor
	endif
endfor

if(pproflag(1))
	messagebox("ok warning", "No changes detected", "INI file not created")

for(j = 0; j < 4; j++)
	ini.delete_section(Backup, v[j])
	ini.copy_section(v[j], Config, v[j], Name)
endfor

quit

@Copy
win.sendmessage(hwnd, 0x400+51, 580, 0)
Name = file.listfiles(Path ++ "*" ++ I)
v = vec.createfromlines(Name, 1)

if(v == 0) do
	messagebox("ok error", "Vector not created", "VEC plugin error #2")
	quit
endif

Counter = vec.length(v)
vec.insert(v, Counter, Config)
Counter++
if(TempConf)
	vec.insert(v, Counter, TempConf)

Name = vec.makelines(v)
local From = pickstring(Name, "Select FILE to copy FROM")

if(not From) do
	quit

MainSections = ini.enum_sections(From)
NewValue = "Select SECTION in file '" ++ From ++ "' to copy FROM"
OneSec = pickstring(MainSections, NewValue)

if(not OneSec)
	quit

NewValue = "Select FILE to copy section '" ++ OneSec ++ "' TO"
local To = pickstring(Name, NewValue)
if(not To)
	quit

ini.copy_section(OneSec, From, OneSec, To) 
quit

@New
TempConf = miscplugin.tempfilename() ++ I
do(Total, "/n /i=" ++ TempConf)
quit

@Insert
local Point, From, To, Dir
local Str = "~Dir=Copy direction (Source > Target)??|[Dirmenu] > [user]|[user] > [Dirmenu],"
Str ++= "From=Source item number to copy (FROM),To=Source item number to copy (TO),"
Str ++= "Point=Target section number to copy AFTER"

Name = inputdialog(Str, "Copy Keys from One Section to Another")

if(not Name)
	quit

v[0] = "user"
v[1] = "Dirmenu"
local Source = v[not Dir]
local Target = v[Dir]

MainKeys = ini.enum_keys(Config, Target)

for(j = line(MainKeys, 0); j >= 0; j--)
	Name = line(MainKeys, j)
	NewKeys = ini.get(Config, Target, Name)
	Counter = 0
	NewValue = ""
	for(k = 0; k <= length(Name); k++)
		MainValue = Name[k]
		if(miscplugin.is_int(MainValue)) do
			Counter ++= MainValue
		else
			NewValue ++= MainValue
		endif
	endfor

	if(Counter < Point) do
		break
	else
		MainNumber = Counter + To - From + 1
		ini.set(Config, Target, NewValue ++ MainNumber, NewKeys)
	endif

endfor

MainKeys = ini.enum_keys(Config, Source)

for(j = 1; j <= line(MainKeys, 0); j++)
	Name = line(MainKeys, j)
	NewKeys = ini.get(Config, Source, Name)
	Counter = 0
	NewValue = ""
	for(k = 0; k <= length(Name); k++)
		MainValue = Name[k]
		if(miscplugin.is_int(MainValue)) do
			Counter ++= MainValue
		else
			NewValue ++= MainValue
		endif
	endfor

	if(Counter >= From && Counter <= To) do
		MainNumber = Counter - From + Point
		ini.set(Config, Target, NewValue ++ MainNumber, NewKeys)
	endif

	if(Counter > To)
		break
endfor

Комментарии:

На первый взгляд может показаться, что с введением в четвертой версии копирования в фоне, а в шестой – вкладок, а в версии 8.50 – поиска в отдельном процессе, отпала необходимость в запуске нескольких копий Total Commander. Однако со временем оказывается, что такая необходимость стала менее насущной, но вовсе не исчезла.

Самый распространенный случай, когда она возникает – групповое переименование. При большом числе файлов для переименования с полями content-плагинов процесс может занять несколько десятков минут, в течение которых работа с Total Commander (точнее, с текущей ее копией) оказывается невозможной. Скрипт работает вне зависимости от того, установлен или сброшен флаг "Allow only 1 copy of Total Commander at a time".

Второй случай, когда предлагаемый скрипт может оказаться полезным – необходимость работы в Total Commander с разными настройками. К примеру, для определенных проектов нужен особый набор плагинов, который при обычной работе не используется и только мешает. То же самое может касаться настроек колонок, цветовых схем, горячих клавиш и т. п.

В Total Commander предусмотрено решение и этой проблемы – ключ /i командной строки, позволяющий загружать заданный файл конфигурации вместо оного по умолчанию wincmd.ini. Однако оказывается, что это решение не всегда удобно.

Представьте себе, что вы кропотливым трудом создали некий альтернативный файл конфигурации, отличающегося от стандартного ("основного") набором плагинов. За те несколько месяцев, когда новый файл был не нужен, вы успели внести много нового – определили несколько горячих клавиш (и основательно к ним привыкли), добавили множество пунктов в Start menu, изменили цвета, создали пользовательские виды с полями content-плагинов, и т. д. В итоге, загрузив другой файл конфигурации, вы больше проиграли, чем выиграли – клавиши работают "по-старому", цветовая гамма выглядит ужасно, в меню (Start и Directory hotlist) не хватает самого необходимого... Короче говоря – интерфейс непривычен и не соответствует вашему текущему уровню.

Через все это я в свое время прошел и наконец-то сподобился предложить себе (ну и остальным заодно) если не панацею, то некое приближение к ней.

Скрипт выполняет шесть разных функций в зависимости от значения единственного параметра. Первая функция – сохранение текущей конфигурации, задается параметром "b" (от "backup"). Резервная копия основной конфигурации сохраняется в поддиректории inis рабочей директории Total Commander и получает имя Backup.ini. Кстати, операцию резервного копирования имеет смысл проводить и перед тем, как, к примеру, затевать какие-либо смелые экспериметы. Если их результат окажется неудачным, конфигурация восстанавливается с помощью параметра "r" (от "restore").

Итак, шаг первый – сохранение основной конфигурации ("b"). Затем мы начинаем изменять настройки, подключая и отключая плагины, подбирая цвета, создавая новые горячие клавиши, настраивая шаблоны поиска и т. д. После того, как создание новой конфигурации закончено, вызываем скрипт с параметром "s" (от "save"). На запрос вводим подходящее имя новой конфигурации (для определенности MyConfig) и получаем файл MyConfig.ini, содержащий только те настройки, которые отличаются от соответствующих настроек основной конфигурации. Полученный файл, разумеется, можно просмотреть и подправить, если необходимо. Упрощает задачу "чистовой обработки" то, что файл MyConfig.ini будет содержать относительно немного разделов и ключей. Этим завершается шаг второй.

Шаг третий – если вы собираетесь использовать новую конфигурацию довольно часто (по меньшей мере раз в несколько месяцев), то можно создать кнопку на панели с вызовом данного скрипта, причем параметром является имя конфигурации. В нашем случае параметр команды запуска будет выглядеть как runfile.IniManager("MyConfig").

Таким образом, можно наплодить конфигураций под все проекты, на все случаи жизни, и каждой из них сопоставить кнопку и/или горячую клавишу. Все шаблоны конфигураций хранятся там же, где и резервная копия основной конфигурации.

Когда создание разных конфигураций завершено, запускаем скрипт с параметром "r" и возвращаемся к основной конфигурации.

Время для четвертого шага придет, возможно, очень не скоро, когда в основную конфигурацию будет внесено сколь угодно много изменений. Зато можно быть уверенным – запустив скрипт с именем другой конфигурации (например, через созданную кнопку), мы, соответственно, получим изменения только в настройках, которые были сохранены на втором шаге. Таким образом, если целью создания конфигурации MyConfig был новый набор плагинов, то именно он, и только он, будет отличаться от основного. Все остальные настройки будут точно такими же, как и минуту назад.

Может показаться, что скрипт мало полезен в тех случаях, когда предполагается проводить групповое переименование. Я тоже так думал. Но вот допустим, что вы просто открыли вторую копию Total Commander, а в первой запустили переименование. Но к тому моменту, как процесс завершится, вы уже успеете, к примеру, открыть несколько файлов в Lister'е. Теперь, если закрыть вторую копию как более не нужную, Lister закроется вместе с ней, и придется начинать все заново. Поэтому, скорее всего, до конца сеанса у вас так и останутся запущенными две копии... Вы в них не путаетесь?! Завидую. Настройки почти одинаковые, внешний вид – тоже... Мало того – обе копии используют один и тот же файл конфигурации. Конфликтов я, правда, в такой ситуации не наблюдал, но мелкие неприятности случались. Так что по всем признакам лучше запускать вторую копию со второй конфигурацией, третью – с третьей, и т. д.

Еще одна функция скрипта, стоящая несколько особняком от ранее описанных – копирование раздела одного файла конфигурации в другой файл. Собственно говоря, термин "копирование" не вполне уместен, поскольку старое содержимое раздела удаляется и полностью заменяется новым. Поэтому лучше было бы вести речь о "замене", но Alan Campbell, автор плагина ini, по одному ему известным причинам, называет эту операцию "copy", а соответствующую функцию – "copy_section".

Итак, запустив скрипт с параметром "c" (copy), мы последовательно получаем три запроса. Прежде всего необходимо выбрать имя файла конфигурации, из которого будет копироваться раздел. Чтобы не запутаться, что куда копируется, следует внимательно читать заголовок окна. В список файлов конфигурации входят следующие файлы:

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

Рассмотрим пример. Как мы помним, файл конфигурации с другим списком плагинов был нами создан и назван MyConfig.ini. Если запустить скрипт с параметром "c", первое диалоговое окно будет содержать следующие файлы:

Напомним, что файл Backup.ini был создан тогда, когда мы создавали MyConfig.ini, поэтому, возможно, его разделы давным-давно потеряли актуальность, а возможно, напротив, содержат нечто, ценность чего вы в свое время не осознали.

Теперь предположим, что мы запустили вторую копию Total Commander на основе MyConfig.ini, и тогда список дополнится файлом с именем типа

D:\Documents and Settings\Administrator\Local Settings\Temp\MyConfig5.ini

(само собой, пути соответствуют моему компьютеру).

Скорее всего, возникнет необходимость скопировать раздел из MyConfig5.ini в MyConfig.ini. Пусть это будет раздел [ContentPlugins] – потому что мы добавили несколько новых плагинов. Итак, в первом окне выбираем

D:\Documents and Settings\Administrator\Local Settings\Temp\MyConfig5.ini

и нажимаем "ОК". Во втором окне выберем раздел ContentPlugins, и, наконец, в третьем окне d:\Utils\TotalCmd\inis\MyConfig.ini, тем самым обновив последний.

Еще одна функция скрипта – запуск Total Commander'а с пустой конфигурацией (параметр "n"). Это – первый шаг при обнаружении бага. Ведь вполне возможно (и скорее всего, так оно и есть), что баг вызван не ошибками в самом Total Commander'е, а ошибками в плагинах или внешних утилитах. Тогда в новой, пустой конфигурации он неминуемо исчезнет. Затем начинают поиск "злодея", либо копируя разделы один за другим из основного файла в новый, либо последовательным комментированием раздела основного.

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

Известно, что максимальное число пунктов обоих пользовательских меню, содержащихся в разделах [user] и [DirMenu], равно 200. Практика показала, что достижение этого предела – лишь вопрос времени. Допустим, что у вас в [DirMenu] 197 пунктов, и вы решаете перенести часть меню в раздел [user] (пусть там еще достаточно места). Но как? Надо либо вручную менять номера у всех ключей, либо вставлять большое число пустых, фиктивных команд, "заглушек", чтобы потом их же и удалить. К тому же, даже тогда простое перетаскивание создать много сложностей для структурированного, многоуровневого, меню, потому что перемещать пункты в обоих списках средствами ТС можно лишь по одной!

  1. Делаем резервную копию конфигурации, например, с помощью параметра "b" данного скрипта;
  2. Загружаем wincmd.ini в текстовый редактор или, лучше, программу просмотра текстовых файлов;
  3. Закрываем окно Total Commander'а. Во-первых, он может внезапно захотеть обновить конфигурацию, а далеко не все текстовые редакторы поддерживают запрос на обновление редактируемого файла, и не все умеют это делать динамически. То есть либо наши изменения потеряются, либо начнут конфликтовать с текущими установками. Последствия непредсказуемы! Во-вторых, после внесенных изменений Total Commander все равно придется перезапускать;
  4. Смотрим в раздел [DirMenu] и намечаем к переносу пункты с номерами, допустим, от 5 до 24, всего 20. То есть начинается наш список со строки menu5=…, а заканчивается, вероятно, строкой cmd24=… (это без учета ключей типа path24, param24 и т. д.);
  5. Смотрим в раздел [user] и решаем, что начинаться переносимые пункты меню будут с номера 10;
  6. Запускаем скрипт с параметром "i". В первом списке выбираем направление копирования, в нашем случае "[Dirmenu] > [user]" (по умолчанию). Во втором поле вводим 5, в третьем 24, в четвертом 10, и нажимаем ОК. Происходит следующее: пункты меню [user] с номерами 1…9 остаются нетронутыми, все остальные увеличивают номера на 20, то есть 10 становится 30, 11 – 31, и т. д. Затем из раздела [DirMenu] пункты с номерами 5…24 копируются в раздел [user], получая освободившиеся номера: 5 становится 10, 6 – 11 и т. д.;

В случае благополучного результата удалять ключи из раздела [DirMenu] можно вручную.

Второй параметр скрипта полезен при запуске 64-битной версии Total Commander'а: для этого достаточно написать "TOTALCMD64". При отсутствии параметра запускается TOTALCMD.exe.

В заключение следует отметить, что скрипт может быть легко приспособлен для управления файлами конфигурации любой другой программы, хранящей свои настройки в файлах формата INI и позволяющей загружать заданный файл конфигурации.


На главную Все о Total Commander PowerPro PowerPro & Total Commander