%D \module %D [ file=t-inifile, %D version=2008.07.15, %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. %C You can find the latest version of this module on %C http://modules.contextgarden.net/ % This program is free software; you can redistribute it and/or % modify it under the terms of the GNU General Public License % as published by the Free Software Foundation; either version 2 % of the License, or (at your option) any later version. % This program is distributed in the hope that it will be useful, % but without any warranty; without even the implied warranty of % merchantability or fitness for a particular purpose. See the % GNU General Public License for more details. \writestatus{loading}{Formatting of ini-files} \doifnotmode{mkiv}{\writestatus{error}{needs luatex}\wait\end} \unprotect \startluacode -- namespace thirddata = thirddata or { } thirddata.inifile = {} -- sort the table -- s1: primary key -- s2: secondary key -- s3: third key local function sort_table(s1, s2, s3) local function cmp(a, b) if s2 ~= "" and a[s1] == b[s1] then if s3 ~= "" and a[s2] == b[s2] then return a[s3] < b[s3] else return a[s2] < b[s2] end else return a[s1] < b[s1] end end if s1 ~= "" then table.sort(thirddata.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 thirddata.inifile.t[i][k] = v end end -- generate table from ini-file -- d: default values for all entries -- s1: primary sort-key -- s2: secondary sort-key -- s3: third sort-key function thirddata.inifile.make_table(d, s1, s2, s3) thirddata.inifile.t = {} local i = 0 local lastkey 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 thirddata.inifile.t[i] = {} thirddata.inifile.t[i]["key"] = key thirddata.inifile.t[i]["n"] = i 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 local c = string.match(l, "^%s+(.*)$") if c then thirddata.inifile.t[i][lastkey] = thirddata.inifile.t[i][lastkey] .. " " .. c end -- get a new key value pair: key, val = string.match(l, "^([%w_]+)%s*=%s(.*)$") if key then thirddata.inifile.t[i][key] = val lastkey = key end break end end sort_table(s1, s2, s3) print(table.serialize(thirddata.inifile.t)) end -- let ConTeXt print the sorted table with user defined formatting -- c: the user supplied command to print one entry function thirddata.inifile.print(c) for i = 1,#thirddata.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 thirddata.inifile.newentry(i) for k, v in pairs(thirddata.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 thirddata.inifile.filter(k, s, r) for i = 1,#thirddata.inifile.t do thirddata.inifile.t[i][k] = string.gsub(thirddata.inifile.t[i][k], s, r) end end \stopluacode \getparameters[IF@][defaults=,sortA=,sortB=,sortC=,file=/dev/null] \def\setupIniFile[#1]{ \getparameters[IF@][#1] \ctxlua{io.input("\IF@file")} \ctxlua{thirddata.inifile.make_table("\IF@defaults", "\IF@sortA", "\IF@sortB", "\IF@sortC")} } \def\IniFilePrint{\ctxlua{thirddata.inifile.print("\IF@command")}} \def\IniFileNewEntry{\ctxlua{thirddata.inifile.newentry(\IF@index)}} \def\IniFileFilter[#1][#2][#3]{\ctxlua{thirddata.inifile.filter("#1", "#2", "#3")}} \protect \doifnotmode{demo}{\endinput} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %D Usage example: \startbuffer[thewho] [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 comment = very very very very long line [k_m] givenname = Keith surname = Moon birthyear = 1946 comment = another very very very very \ long line [k_j] givenname = Kenney surname = Jones birthyear = 1948 comment = yet another very very very very \ long line \stopbuffer \savebuffer[thewho] \usemodule[inifile] \setupIniFile[defaults={birthyear=1944,comment=}, sortA=birthyear,sortB=key,command=FormatMember,file=\jobname-thewho.tmp] \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 and multi-line values: \IFcomment}} \starttext \title{The Who} \IniFilePrint \stoptext