IniManager

Title IniManager
File Name IniManager.txt
Description Creates and updates configuration files for different purposes
Author Vochomurka
Parameters "b"|"s"|"r"|"c"|"n"|"i"|Configuration_Name"
(see Comments)
Plugins Called ini, file, vec, win, miscplugin
Version 3.0
Updated on 03.03.15
;;If wincmd.ini is not in Windows directory, indicate its path implicitly:
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\" – subdirectory of %COMMANDER_PATH% to store configuration files
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

Comments:

Is there a necessity to run several copies of Total Commander? In the old days it was frequently. Fourth version allowed to copy/move in background, sixth version introduced the folder tabs, finally, version 8.50 aloows to search in separate process. But even now there are at least one operation when the current instance of Total Commander is not available for a certain (often very long) time: multi-rename, because it cannot be sent to background. Before starting long-term rename it is convenient to run another instance and work there while the first instance is working.

There is one more case when another instance of Total Commander is necessary – different configurations. For example, to work with special projects or problems we could need some specific plugins useless for our common tasks. The same concerns different custom views, hotkeys, Lister settings, packers, and so on.

It seems that the solution of the described problem is the /i command line key. But in reality this solution has at least one disadvantage.

Suppose we had spent a long time to create some alternative configuration differing from the default one by the plugin set. Some weeks (months?) later this set became needed again. But after running the new Total Commander instance with this configuration we realize that plugins are the only thing we like. Why? Because during the time we have not been using the alternative configuration the default one has heavily changed. Hotkeys, colors, start and directory menus – all this looks "old-fashioned", "outdated", and thus very inconvenient.

Has it ever happened to you? I am pretty sure it has.

It was just an introduction. Now it's time to talk about the script itself.

The script has six functions depending on the only parameter. First function is to backup the default configuration file (usually wincmd.ini) and is activated by the "b" parameter. Default configuration file is just copied to the inis\ subdirectory of the Total Commander installation folder. It's a good idea to make the backup before any grand-scale experiment with the settings. If this experiment fails, we could restore the initial state by running the same script with the "r" ("restore") parameter. It's the second function.

So, the first step is to backup the "main" (default) configuration ("b"). Then we can fearlessly do anything we want: loading/unloading plugins, changing colors, defining new and disabling old hotkeys, saving and deleting the search templates, and so forth. After the new configuration seems to be finished, the third function of script can be used. This function deals with "saving" the current (changed) configuration and is invoked by the "s" ("save") parameter. The new configuration must be named (for example, as MyConfig). What is happening next? In the inis\ subdirectory the MyConfig.ini file is created. This file contains only the settings that differ from those of the main configuration. The resulting file can be viewed and edited. It's quite simple because the sections and keys are less numerous than those of the main configuration. For example, if the only thing we have changed is the content plugin set, then the MyConfig.ini contains only one section [ContentPlugins]. This ends the second step.

Third step is to create a button or hotkey calling this script with a parameter equal to the new configuration name (runfile.IniManager("MyConfig") in our case). If we want we can create as many configurations as we would probably need. All the configuration files are stored in the same place as the backup copy of the main configuration – that is, in the inis\ subdirectory.

After saving each of new configurations we can restore the main one by running the script with the "r" parameter.

Henceforth we do not care about how much time would elapse till we need any of the saved configurations, and this is the main goal of the script presented. That is, running the script with the configuration name ("MyConfig") we get changes only in those settings that have been saved on the second step. If the MyConfig.ini file contains the only [ContentPlugins] section, then all other settings are exactly the same as in the default (current, one-second-ago) configuration.

Due to the /N command line parameter the script functioning does not depend on the "Allow only 1 copy of Total Commander at a time" option in the configuration.

The fifth function of the script covers all other needs in managing configurations. By running the script with the "c" ("copy") parameter we will invoke three dialog windows in turn.

First window allows to pick the configuration file whose section(s) we would like to copy from (you should carefully read the window caption to learn this). The list of configuration files available comprises:

For example, on my computer the list of available configuration files is as follows:

The d:\Utils\TotalCmd\inis\Backup.ini file is a backup copy of the main configuration created when the "b" parameter was used the last time. Therefore, this file can be very-very old!

Picking the desired file moves on the second dialog window with the list of sections containing in the file chosen. Pick one section to copy and press "OK". The third dialog window contains the same file list as the first window, but now you should pick the file to copy section to. After pressing "OK" the indicated section of this file will be completely replaced by the same section of the file picked in the first window. Be careful!

Let's consider an example. We have run the script with the "MyConfig" parameter and thus there are two instances of Total Commander currently loaded. The above list is therefore enriched by the following configuration file:

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

The same name can be retrieved by picking "Help\About" menu of the second instance of Total Commander.

Further, suppose we want to take the [ContentPlugins] section from MyConfig5.ini and replace the same section in MyConfig.ini. Run the script with the "c" parameter and pick the file

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

In the second window pick the [ContentPlugins] section, and, finally, in the third dialog pick the MyConfig.ini file. As a result, the content plugins of the MyConfig.ini configuration will be updated.

The sixth function is to run Total Commander with new (the "n" parameter), empty configuration. It is required to check whether some found bug is specific to Total Commander itself, or is a result of plugin, setting conflict, or external utility operation. Being run with an empty configuration, Total Commander has the settings as though we have just installed it. So, if the bug persists, it is Total Commander's one; if it disappears, there is no need to write a bug report.

Finally, the seventh function is copying keys from one section to another, with their synchronous renumbering. It is a rather specific task, but everyone would need it sooner or later.

It is known that greatest number of items for both user's menus from sections [user] and [DirMenu] is 200. It is obvious that reaching this limit is just a matter of time. Suppose you have 197 items in the [DirMenu] section, and you decide to copy some of them to section [user] (let it have enough space). Without the script you have either to edit the configuration manually, or to insert there "stubs": empty, fake items – just to delete them later. Further, even simple drag-n-drop is sophisticated problem for structured, multilevel menu, because Total Commander does not allow to drag-n-drop many items at a time!

  1. Do a backup copy of the configuration, for example, using the present script with the "b" parameter;
  2. Load wincmd.ini into any text editor or rather into text viewer;
  3. Close Total Commander. First, it could unexpectidly try to update the configuration, and not every text editor is able to request user to allow this, and not every editor is able to perform it dynamically. That is either our changes will be lost or, even worse, they will conflict with existing settings. Consequences are unpredictable! Second, after your changes Total Commander must be restarted anyway;
  4. Analyse the [DirMenu] section and conclude that items with numbers, say, from 5 to 24, totally 20, should be copied. That is, our list starts with key menu5=…, and ends probably with cmd24=… (to say nothing about keys like path24, param24 etc);
  5. You decide to insert items to the [user] section from item number, say, 10;
  6. Run the script with the "i" parameter. In the first dropdown list choose the copying direction, in your case "[Dirmenu] > [user]" (default). Second edit box must contain 5, third – 24, and fourth – 10. Press OK. The [user] section items with numbers 1…9 are left intact, all others are shifted by 20 (10 will be numbered as 30, 11 as 31, and so on). Then items with numbers 5…24 from the [DirMenu] section are copied to the [user] section, with renumbering: 5 becames 10, 6 becomes 11, etc;
  7. If the result is successful you can easily delete copied keys from the [DirMenu] section.

Second parameter, if specified, allows to run the 64-bit version of Total Commander. In this case the "TOTALCMD64" parameter is specified. By default the TOTALCMD.exe is run.


All Scripts Total Commander TotalCmd.net PowerPro