1if not modules then modules = { } end modules ['cldf-scn'] = {
2 version = 1.001,
3 comment = "companion to cldf-ini.mkiv",
4 author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
5 copyright = "PRAGMA ADE / ConTeXt Development Team",
6 license = "see context related readme files"
7}
8
9local load, type, tostring = load, type, tostring
10
11local formatters = string.formatters
12local char = string.char
13local concat = table.concat
14
15local lpegmatch = lpeg.match
16local p_unquoted = lpeg.Cs(lpeg.patterns.unquoted)
17
18local f_action_f = formatters["action%s(%s)"]
19local f_action_s = formatters["local action%s = action[%s]"]
20local f_command = formatters["local action = tokens._action\n%\nt\nreturn function(%s) return %s end"]
21
22local interfaces = interfaces
23local commands = commands
24local register = interfaces.registerscanner
25local knownscanner = interfaces.knownscanner
26
27local compile = tokens.compile or function() end
28local presets = tokens.presets
29
30local dummy = function() end
31
32local report = logs.reporter("interfaces","implementor")
33
34function interfaces.implement(specification)
35 local name = specification.name
36 if name == "" then
37 name = nil
38 end
39 local actions = specification.actions
40 local arguments = specification.arguments
41 local private = specification.scope == "private"
42 local onlyonce = specification.onlyonce
43 if not actions then
44 if name then
45 report("error: no actions for %a",name)
46 else
47 report("error: no actions and no name")
48 end
49 return
50 end
51 local p = arguments and presets[arguments]
52 if p then
53 arguments = p
54 end
55 local scanner
56 local resetter = onlyonce and name and commands.ctxresetter(name)
57 if resetter then
58 local scan = compile(specification)
59 if private then
60 scanner = function()
61 resetter()
62 return scan()
63 end
64 else
65 scanner = function()
66 commands[name] = dummy
67 resetter()
68 return scan()
69 end
70 end
71 else
72 scanner = compile(specification)
73 end
74 if not name then
75 return scanner
76 end
77 if knownscanner(name) and not specification.overload then
78 report("warning: interface scanner %a is overloaded",name)
79 end
80
81 register(name,scanner,specification)
82 if private then
83 return
84 end
85 local command
86 if onlyonce then
87 if type(actions) == "function" then
88 actions = { actions }
89 elseif #actions == 1 then
90 actions = { actions[1] }
91 end
92 end
93 if type(actions) == "function" then
94 command = actions
95 elseif #actions == 1 then
96 command = actions[1]
97 else
98
99 tokens._action = actions
100 local f = { }
101 local args
102 if not arguments then
103 args = ""
104 elseif type(arguments) == "table" then
105 local a = { }
106 for i=1,#arguments do
107 local v = arguments[i]
108 local t = type(v)
109 if t == "boolean" then
110 a[i] = tostring(v)
111 elseif t == "number" then
112 a[i] = tostring(v)
113 elseif t == "string" then
114 local s = lpegmatch(p_unquoted,v)
115 if s and v ~= s then
116 a[i] = v
117 else
118 a[i] = char(96+i)
119 end
120 else
121
122 a[i] = char(96+i)
123 end
124 end
125 args = concat(a,",")
126 else
127 args = "a"
128 end
129 command = args
130 for i=1,#actions do
131 command = f_action_f(i,command)
132 f[i] = f_action_s(i,i)
133 end
134 command = f_command(f,args,command)
135 command = load(command)
136 if command then
137 if resetter then
138 local cmd = command()
139 command = function()
140 commands[name] = dummy
141 resetter()
142 cmd()
143 end
144 else
145 command = command()
146 end
147 end
148 tokens._action = nil
149 end
150 if commands[name] and not specification.overload then
151 report("warning: 'commands.%s' is redefined",name)
152 end
153 commands[name] = command
154
155end
156
157
158
159interfaces.defined = tokens.defined
160
161interfaces.setmacro = tokens.setters.macro
162interfaces.setcount = tokens.setters.count
163interfaces.setdimen = tokens.setters.dimen
164 |