summaryrefslogtreecommitdiff
path: root/macros/context/contrib/context-inifile/tex/context/third/inifile/t-inifile.tex
blob: df1c8830803ad00478b759899491249b5909672a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
%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