1textutil::expander(Tne)xt and string utilities, macro processtienxgtutil::expander(n)
2
3
4
5______________________________________________________________________________
6
8 textutil::expander - Procedures to process templates and expand text.
9
11 package require Tcl 8.2
12
13 package require textutil::expander ?1.3.1?
14
15 ::textutil::expander expanderName
16
17 expanderName cappend text
18
19 expanderName cget varname
20
21 expanderName cis cname
22
23 expanderName cname
24
25 expanderName cpop cname
26
27 expanderName ctopandclear
28
29 expanderName cpush cname
30
31 expanderName cset varname value
32
33 expanderName cvar varname
34
35 expanderName errmode newErrmode
36
37 expanderName evalcmd ?newEvalCmd?
38
39 expanderName expand string ?brackets?
40
41 expanderName lb ?newbracket?
42
43 expanderName rb ?newbracket?
44
45 expanderName reset
46
47 expanderName setbrackets lbrack rbrack
48
49 expanderName textcmd ?newTextCmd?
50
51 expanderName where
52
53______________________________________________________________________________
54
56 The Tcl subst command is often used to support a kind of template pro‐
57 cessing. Given a string with embedded variables or function calls,
58 subst will interpolate the variable and function values, returning the
59 new string:
60
61 % set greeting "Howdy"
62 Howdy
63 % proc place {} {return "World"}
64 % subst {$greeting, [place]!}
65 Howdy, World!
66 %
67
68
69 By defining a suitable set of Tcl commands, subst can be used to imple‐
70 ment a markup language similar to HTML.
71
72 The subst command is efficient, but it has three drawbacks for this
73 kind of template processing:
74
75 · There's no way to identify and process the plain text between
76 two embedded Tcl commands; that makes it difficult to handle
77 plain text in a context-sensitive way.
78
79 · Embedded commands are necessarily bracketed by [ and ]; it's
80 convenient to be able to choose different brackets in special
81 cases. Someone producing web pages that include a large quan‐
82 tity of Tcl code examples might easily prefer to use << and >>
83 as the embedded code delimiters instead.
84
85 · There's no easy way to handle incremental input, as one might
86 wish to do when reading data from a socket.
87
88 At present, expander solves the first two problems; eventually it will
89 solve the third problem as well.
90
91 The following section describes the command API to the expander; this
92 is followed by the tutorial sections, see TUTORIAL.
93
95 The textutil::expander package provides only one command, described
96 below. The rest of the section is taken by a description of the methods
97 for the expander objects created by this command.
98
99 ::textutil::expander expanderName
100 The command creates a new expander object with an associated Tcl
101 command whose name is expanderName. This command may be used to
102 invoke various operations on the graph. If the expanderName is
103 not fully qualified it is interpreted as relative to the current
104 namespace. The command has the following general form:
105
106
107 expanderName option ?arg arg ...?
108
109
110 Option and the args determine the exact behavior of the command.
111
112 The following commands are possible for expander objects:
113
114 expanderName cappend text
115 Appends a string to the output in the current context. This
116 command should rarely be used by macros or application code.
117
118 expanderName cget varname
119 Retrieves the value of variable varname, defined in the current
120 context.
121
122 expanderName cis cname
123 Determines whether or not the name of the current context is
124 cname.
125
126 expanderName cname
127 Returns the name of the current context.
128
129 expanderName cpop cname
130 Pops a context from the context stack, returning all accumulated
131 output in that context. The context must be named cname, or an
132 error results.
133
134 expanderName ctopandclear
135 Returns the output currently captured in the topmost context and
136 clears that buffer. This is similar to a combination of cpop
137 followed by cpush, except that internal state (brackets) is pre‐
138 served here.
139
140 expanderName cpush cname
141 Pushes a context named cname onto the context stack. The con‐
142 text must be popped by cpop before expansion ends or an error
143 results.
144
145 expanderName cset varname value
146 Sets variable varname to value in the current context.
147
148 expanderName cvar varname
149 Retrieves the internal variable name of context variable var‐
150 name; this allows the variable to be passed to commands like
151 lappend.
152
153 expanderName errmode newErrmode
154 Sets the macro expansion error mode to one of nothing, macro,
155 error, or fail; the default value is fail. The value determines
156 what the expander does if an error is detected during expansion
157 of a macro.
158
159 fail The error propagates normally and can be caught or
160 ignored by the application.
161
162 error The macro expands into a detailed error message, and
163 expansion continues.
164
165 macro The macro expands to itself; that is, it is passed along
166 to the output unchanged.
167
168 nothing
169 The macro expands to the empty string, and is effectively
170 ignored.
171
172
173 expanderName evalcmd ?newEvalCmd?
174 Returns the current evaluation command, which defaults to
175 uplevel #0. If specified, newEvalCmd will be saved for future
176 use and then returned; it must be a Tcl command expecting one
177 additional argument: the macro to evaluate.
178
179 expanderName expand string ?brackets?
180 Expands the input string, replacing embedded macros with their
181 expanded values, and returns the expanded string.
182
183 Note that this method pushes a new (empty) context on the stack
184 of contexts while it is running, and removes it on return.
185
186 If brackets is given, it must be a list of two strings; the
187 items will be used as the left and right macro expansion bracket
188 sequences for this expansion only.
189
190 expanderName lb ?newbracket?
191 Returns the current value of the left macro expansion bracket;
192 this is for use as or within a macro, when the bracket needs to
193 be included in the output text. If newbracket is specified, it
194 becomes the new bracket, and is returned.
195
196 expanderName rb ?newbracket?
197 Returns the current value of the right macro expansion bracket;
198 this is for use as or within a macro, when the bracket needs to
199 be included in the output text. If newbracket is specified, it
200 becomes the new bracket, and is returned.
201
202 expanderName reset
203 Resets all expander settings to their initial values. Unusual
204 results are likely if this command is called from within a call
205 to expand.
206
207 expanderName setbrackets lbrack rbrack
208 Sets the left and right macro expansion brackets. This command
209 is for use as or within a macro, or to permanently change the
210 bracket definitions. By default, the brackets are [ and ], but
211 any non-empty string can be used; for example, < and > or (* and
212 *) or even Hello, and World!.
213
214 expanderName textcmd ?newTextCmd?
215 Returns the current command for processing plain text, which
216 defaults to the empty string, meaning identity. If specified,
217 newTextCmd will be saved for future use and then returned; it
218 must be a Tcl command expecting one additional argument: the
219 text to process. The expander object will this command for all
220 plain text it encounters, giving the user of the object the
221 ability to process all plain text in some standard way before
222 writing it to the output. The object expects that the command
223 returns the processed plain text.
224
225 Note that the combination of "textcmd plaintext" is run through
226 the evalcmd for the actual evaluation. In other words, the
227 textcmd is treated as a special macro implicitly surrounding all
228 plain text in the template.
229
230 expanderName where
231 Returns a three-element list containing the current character
232 position, line, and column the expander is at in the processing
233 of the current input string.
234
236 BASICS
237 To begin, create an expander object:
238
239 % package require textutil::expander
240 1.2
241 % ::textutil::expander myexp
242 ::myexp
243 %
244
245
246 The created ::myexp object can be used to expand text strings contain‐
247 ing embedded Tcl commands. By default, embedded commands are delimited
248 by square brackets. Note that expander doesn't attempt to interpolate
249 variables, since variables can be referenced by embedded commands:
250
251 % set greeting "Howdy"
252 Howdy
253 % proc place {} {return "World"}
254 % ::myexp expand {[set greeting], [place]!}
255 Howdy, World!
256 %
257
258
259 EMBEDDING MACROS
260 An expander macro is simply a Tcl script embedded within a text string.
261 Expander evaluates the script in the global context, and replaces it
262 with its result string. For example,
263
264 % set greetings {Howdy Hi "What's up"}
265 Howdy Hi "What's up"
266 % ::myexp expand {There are many ways to say "Hello, World!":
267 [set result {}
268 foreach greeting $greetings {
269 append result "$greeting, World!\\n"
270 }
271 set result]
272 And that's just a small sample!}
273 There are many ways to say "Hello, World!":
274 Howdy, World!
275 Hi, World!
276 What's up, World!
277
278 And that's just a small sample!
279 %
280
281
282 WRITING MACRO COMMANDS
283 More typically, macro commands are used to create a markup language. A
284 macro command is just a Tcl command that returns an output string. For
285 example, expand can be used to implement a generic document markup lan‐
286 guage that can be retargeted to HTML or any other output format:
287
288 % proc bold {} {return "<b>"}
289 % proc /bold {} {return "</b>"}
290 % ::myexp expand {Some of this text is in [bold]boldface[/bold]}
291 Some of this text is in <b>boldface</b>
292 %
293
294
295 The above definitions of bold and /bold returns HTML, but such commands
296 can be as complicated as needed; they could, for example, decide what
297 to return based on the desired output format.
298
299 CHANGING THE EXPANSION BRACKETS
300 By default, embedded macros are enclosed in square brackets, [ and ].
301 If square brackets need to be included in the output, the input can
302 contain the lb and rb commands. Alternatively, or if square brackets
303 are objectionable for some other reason, the macro expansion brackets
304 can be changed to any pair of non-empty strings.
305
306 The setbrackets command changes the brackets permanently. For example,
307 you can write pseudo-html by change them to < and >:
308
309 % ::myexp setbrackets < >
310 % ::myexp expand {<bold>This is boldface</bold>}
311 <b>This is boldface</b>
312
313
314 Alternatively, you can change the expansion brackets temporarily by
315 passing the desired brackets to the expand command:
316
317 % ::myexp setbrackets "\\[" "\\]"
318 % ::myexp expand {<bold>This is boldface</bold>} {< >}
319 <b>This is boldface</b>
320 %
321
322
323 CUSTOMIZED MACRO EXPANSION
324 By default, macros are evaluated using the Tcl uplevel #0 command, so
325 that the embedded code executes in the global context. The application
326 can provide a different evaluation command using evalcmd; this allows
327 the application to use a safe interpreter, for example, or even to
328 evaluated something other than Tcl code. There is one caveat: to be
329 recognized as valid, a macro must return 1 when passed to Tcl's "info
330 complete" command.
331
332 For example, the following code "evaluates" each macro by returning the
333 macro text itself.
334
335 proc identity {macro} {return $macro}
336 ::myexp evalcmd identity
337
338
339 USING THE CONTEXT STACK
340 Often it's desirable to define a pair of macros which operate in some
341 way on the plain text between them. Consider a set of macros for
342 adding footnotes to a web page: one could have implement something like
343 this:
344
345 Dr. Pangloss, however, thinks that this is the best of all
346 possible worlds.[footnote "See Candide, by Voltaire"]
347
348
349 The footnote macro would, presumably, assign a number to this footnote
350 and save the text to be formatted later on. However, this solution is
351 ugly if the footnote text is long or should contain additional markup.
352 Consider the following instead:
353
354 Dr. Pangloss, however, thinks that this is the best of all
355 possible worlds.[footnote]See [bookTitle "Candide"], by
356 [authorsName "Voltaire"], for more information.[/footnote]
357
358
359 Here the footnote text is contained between footnote and /footnote
360 macros, continues onto a second line, and contains several macros of
361 its own. This is both clearer and more flexible; however, with the
362 features presented so far there's no easy way to do it. That's the
363 purpose of the context stack.
364
365 All macro expansion takes place in a particular context. Here, the
366 footnote macro pushes a new context onto the context stack. Then, all
367 expanded text gets placed in that new context. /footnote retrieves it
368 by popping the context. Here's a skeleton implementation of these two
369 macros:
370
371 proc footnote {} {
372 ::myexp cpush footnote
373 }
374
375 proc /footnote {} {
376 set footnoteText [::myexp cpop footnote]
377
378 # Save the footnote text, and return an appropriate footnote
379 # number and link.
380 }
381
382
383 The cpush command pushes a new context onto the stack; the argument is
384 the context's name. It can be any string, but would typically be the
385 name of the macro itself. Then, cpop verifies that the current context
386 has the expected name, pops it off of the stack, and returns the accu‐
387 mulated text.
388
389 Expand provides several other tools related to the context stack. Sup‐
390 pose the first macro in a context pair takes arguments or computes val‐
391 ues which the second macro in the pair needs. After calling cpush, the
392 first macro can define one or more context variables; the second macro
393 can retrieve their values any time before calling cpop. For example,
394 suppose the document must specify the footnote number explicitly:
395
396 proc footnote {footnoteNumber} {
397 ::myexp cpush footnote
398 ::myexp csave num $footnoteNumber
399 # Return an appropriate link
400 }
401
402 proc /footnote {} {
403 set footnoteNumber [::myexp cget num]
404 set footnoteText [::myexp cpop footnote]
405
406 # Save the footnote text and its footnoteNumber for future
407 # output.
408 }
409
410
411 At times, it might be desirable to define macros that are valid only
412 within a particular context pair; such macros should verify that they
413 are only called within the correct context using either cis or cname.
414
416 expander was written by William H. Duquette; it is a repackaging of the
417 central algorithm of the expand macro processing tool.
418
420 This document, and the package it describes, will undoubtedly contain
421 bugs and other problems. Please report such in the category textutil
422 of the Tcllib Trackers [http://core.tcl.tk/tcllib/reportlist]. Please
423 also report any ideas for enhancements you may have for either package
424 and/or documentation.
425
426 When proposing code changes, please provide unified diffs, i.e the out‐
427 put of diff -u.
428
429 Note further that attachments are strongly preferred over inlined
430 patches. Attachments can be made by going to the Edit form of the
431 ticket immediately after its creation, and then using the left-most
432 button in the secondary navigation bar.
433
435 [uri, http://www.wjduquette.com/expand, regexp, split, string
436
438 string, template processing, text expansion
439
441 Documentation tools
442
444 Copyright (c) William H. Duquette, http://www.wjduquette.com/expand
445
446
447
448
449tcllib 1.3.1 textutil::expander(n)