%D \module
%D   [      file=t-inifile,
%D        version=2008.02.25,
%D          title=\CONTEXT\ User Module,
%D       subtitle=Formatting of ini-files,
%D         author=Peter Münster,
%D           date=\currentdate,
%D      copyright={Peter Münster}]
%C This module is copyrighted by Peter Münster.
%C Please send any comments to pmrb at free.fr.

\writestatus{loading}{Formatting of ini-files}

\unprotect

\startluacode
-- namespace
inifile = {}

-- just for debugging: print the table to stdout
local function print_table()
	for i = 1,#inifile.t do
		print("")
		print(i, inifile.t[i].key)
		for k, v in pairs(inifile.t[i]) do
			print("", k, v)
		end
		print("")
	end
end

-- sort the table
-- s1: primary key
-- s2: secondary key
local function sort_table(s1, s2)
	local function cmp(a, b)
		if s2 ~= "" and a[s1] == b[s1] then
			return a[s2] < b[s2]
		else
			return a[s1] < b[s1]
		end
	end
	if s1 ~= "" then
		table.sort(inifile.t, cmp)
	end
end

-- write default values to table entry
-- d: the default values separated by commas
-- i: the index of the entry
local function write_defaults(d, i)
	for k, v in string.gmatch(d, "[,%s]*(.-)=([^,]*)") do
		inifile.t[i][k] = v
	end
end

-- generate table from ini-file
-- d: default values for all entries
-- s1: primary sort-key
-- s1: secondary sort-key
function inifile.make_table(d, s1, s2)
	inifile.t = {}
	local i = 0
	while true do
		local l = io.read()
		if not l then
			break
		end
		while true do
			-- check for new entry:
			key = string.match(l, "^%[(.+)%]$")
			if key then
				i = i + 1
				inifile.t[i] = {}
				inifile.t[i]["key"] = key
				write_defaults(d, i)
				break			-- continue !
			end
			-- treat continued lines:
			while string.match(l, "\\$") do
				local c = io.read()
				l = string.match(l, "^(.*)\\$") .. c
			end
			-- get a new key value pair:
			key, val = string.match(l, "^([%w_]+)%s*=%s(.*)$")
			if key then
				inifile.t[i][key] = val
			end
			break
		end
	end
	sort_table(s1, s2)
	print_table()
end

-- let ConTeXt print the sorted table with user defined formatting
-- c: the user supplied command to print one entry
function inifile.print(c)
	for i = 1,#inifile.t do
		tex.print(string.format("%s\\def\\IF@index{%d}%s\\%s",
								"\\unprotect", i, "\\protect", c))
	end
end

-- initialise the new entry, in general to be called in the beginning
-- of the user supplied formatting command
-- i: the index of the new entry
function inifile.newentry(i)
	for k, v in pairs(inifile.t[i]) do
		tex.print(string.format("\\def\\IF%s{%s}", k, v))
	end
end

-- filter applied to values of a key
-- k: the key
-- s: the search pattern
-- r: the replace string
function inifile.filter(k, s, r)
	for i = 1,#inifile.t do
		inifile.t[i][k] = string.gsub(inifile.t[i][k], s, r)
	end
end
\stopluacode

\def\setupIniFile[#1]{
  \getparameters[IF@][defaults=,sortA=,sortB=,#1]
  \ctxlua{io.input("\IF@file")}
  \ctxlua{inifile.make_table("\IF@defaults", "\IF@sortA", "\IF@sortB")}
}
\def\IniFilePrint{\ctxlua{inifile.print("\IF@command")}}
\def\IniFileNewEntry{\ctxlua{inifile.newentry(\IF@index)}}
\def\IniFileFilter[#1][#2][#3]{\ctxlua{inifile.filter("#1", "#2", "#3")}}

\protect

\doifnotmode{demo}{\endinput}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%D Usage example:

\usemodule[inifile]

\setupIniFile[defaults={birthyear=1944,comment=},
  sortA=birthyear,sortB=key,command=FormatMember,file=thewho.txt]
\IniFileFilter[comment][\%\% ][\\letterpercent\\space ]
\IniFileFilter[comment][\%\%][\\letterpercent ]

\setupTABLE[frame=off,width=0.5\textwidth]
\nonknuthmode

\def\IFbirthyear{}
\def\FormatMember{
  \edef\LastBirthyear{\IFbirthyear}
  \IniFileNewEntry
  \doifnot\IFbirthyear\LastBirthyear{\section{\IFbirthyear}}
  \subsection{\WORD{\IFkey}}
  \bTABLE\bTR
  \bTD Given name: \IFgivenname\eTD\bTD Surname: \IFsurname\eTD
  \eTR\eTABLE
  \doifsomething\IFcomment{Comment to show the treatment of the percent
    sign: \IFcomment}}

\starttext
\title{The Who}
\IniFilePrint
\stoptext

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

Put this into the file thewho.txt for the usage example:

[p_t]
givenname = Peter
surname = Townshend
birthyear = 1945
comment = 100 % with nobreakspace

[r_d]
givenname = Roger
surname = Daltrey
comment = 100 % with thinspace

[j_e]
givenname = John
surname = Entwistle

[k_m]
givenname = Keith
surname = Moon
birthyear = 1946

[k_j]
givenname = Kenney
surname = Jones
birthyear = 1948

%%% Local Variables: 
%%% default-tab-width: 4
%%% End: 
