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 expanderName option ?arg arg ...?
107
108 Option and the args determine the exact behavior of the command.
109
110 The following commands are possible for expander objects:
111
112 expanderName cappend text
113 Appends a string to the output in the current context. This
114 command should rarely be used by macros or application code.
115
116 expanderName cget varname
117 Retrieves the value of variable varname, defined in the current
118 context.
119
120 expanderName cis cname
121 Determines whether or not the name of the current context is
122 cname.
123
124 expanderName cname
125 Returns the name of the current context.
126
127 expanderName cpop cname
128 Pops a context from the context stack, returning all accumulated
129 output in that context. The context must be named cname, or an
130 error results.
131
132 expanderName ctopandclear
133 Returns the output currently captured in the topmost context and
134 clears that buffer. This is similar to a combination of cpop
135 followed by cpush, except that internal state (brackets) is pre‐
136 served here.
137
138 expanderName cpush cname
139 Pushes a context named cname onto the context stack. The con‐
140 text must be popped by cpop before expansion ends or an error
141 results.
142
143 expanderName cset varname value
144 Sets variable varname to value in the current context.
145
146 expanderName cvar varname
147 Retrieves the internal variable name of context variable var‐
148 name; this allows the variable to be passed to commands like
149 lappend.
150
151 expanderName errmode newErrmode
152 Sets the macro expansion error mode to one of nothing, macro,
153 error, or fail; the default value is fail. The value determines
154 what the expander does if an error is detected during expansion
155 of a macro.
156
157 fail The error propagates normally and can be caught or
158 ignored by the application.
159
160 error The macro expands into a detailed error message, and
161 expansion continues.
162
163 macro The macro expands to itself; that is, it is passed along
164 to the output unchanged.
165
166 nothing
167 The macro expands to the empty string, and is effectively
168 ignored.
169
170
171 expanderName evalcmd ?newEvalCmd?
172 Returns the current evaluation command, which defaults to
173 uplevel #0. If specified, newEvalCmd will be saved for future
174 use and then returned; it must be a Tcl command expecting one
175 additional argument: the macro to evaluate.
176
177 expanderName expand string ?brackets?
178 Expands the input string, replacing embedded macros with their
179 expanded values, and returns the expanded string.
180
181 If brackets is given, it must be a list of two strings; the
182 items will be used as the left and right macro expansion bracket
183 sequences for this expansion only.
184
185 expanderName lb ?newbracket?
186 Returns the current value of the left macro expansion bracket;
187 this is for use as or within a macro, when the bracket needs to
188 be included in the output text. If newbracket is specified, it
189 becomes the new bracket, and is returned.
190
191 expanderName rb ?newbracket?
192 Returns the current value of the right macro expansion bracket;
193 this is for use as or within a macro, when the bracket needs to
194 be included in the output text. If newbracket is specified, it
195 becomes the new bracket, and is returned.
196
197 expanderName reset
198 Resets all expander settings to their initial values. Unusual
199 results are likely if this command is called from within a call
200 to expand.
201
202 expanderName setbrackets lbrack rbrack
203 Sets the left and right macro expansion brackets. This command
204 is for use as or within a macro, or to permanently change the
205 bracket definitions. By default, the brackets are [ and ], but
206 any non-empty string can be used; for example, < and > or (* and
207 *) or even Hello, and World!.
208
209 expanderName textcmd ?newTextCmd?
210 Returns the current command for processing plain text, which
211 defaults to the empty string, meaning identity. If specified,
212 newTextCmd will be saved for future use and then returned; it
213 must be a Tcl command expecting one additional argument: the
214 text to process. The expander object will this command for all
215 plain text it encounters, giving the user of the object the
216 ability to process all plain text in some standard way before
217 writing it to the output. The object expects that the command
218 returns the processed plain text.
219
220 Note that the combination of "textcmd plaintext" is run through
221 the evalcmd for the actual evaluation. In other words, the
222 textcmd is treated as a special macro implicitly surrounding all
223 plain text in the template.
224
225 expanderName where
226 Returns a three-element list containing the current character
227 position, line, and column the expander is at in the processing
228 of the current input string.
229
231 BASICS
232 To begin, create an expander object:
233
234 % package require expander
235 1.2
236 % ::expander::expander myexp
237 ::myexp
238 %
239
240
241 The created ::myexp object can be used to expand text strings contain‐
242 ing embedded Tcl commands. By default, embedded commands are delimited
243 by square brackets. Note that expander doesn't attempt to interpolate
244 variables, since variables can be referenced by embedded commands:
245
246 % set greeting "Howdy"
247 Howdy
248 % proc place {} {return "World"}
249 % ::myexp expand {[set greeting], [place]!}
250 Howdy, World!
251 %
252
253
254 EMBEDDING MACROS
255 An expander macro is simply a Tcl script embedded within a text string.
256 Expander evaluates the script in the global context, and replaces it
257 with its result string. For example,
258
259 % set greetings {Howdy Hi "What's up"}
260 Howdy Hi "What's up"
261 % ::myexp expand {There are many ways to say "Hello, World!":
262 [set result {}
263 foreach greeting $greetings {
264 append result "$greeting, World!\\n"
265 }
266 set result]
267 And that's just a small sample!}
268 There are many ways to say "Hello, World!":
269 Howdy, World!
270 Hi, World!
271 What's up, World!
272
273 And that's just a small sample!
274 %
275
276
277 WRITING MACRO COMMANDS
278 More typically, macro commands are used to create a markup language. A
279 macro command is just a Tcl command that returns an output string. For
280 example, expand can be used to implement a generic document markup lan‐
281 guage that can be retargeted to HTML or any other output format:
282
283 % proc bold {} {return "<b>"}
284 % proc /bold {} {return "</b>"}
285 % ::myexp expand {Some of this text is in [bold]boldface[/bold]}
286 Some of this text is in <b>boldface</b>
287 %
288
289
290 The above definitions of bold and /bold returns HTML, but such commands
291 can be as complicated as needed; they could, for example, decide what
292 to return based on the desired output format.
293
294 CHANGING THE EXPANSION BRACKETS
295 By default, embedded macros are enclosed in square brackets, [ and ].
296 If square brackets need to be included in the output, the input can
297 contain the lb and rb commands. Alternatively, or if square brackets
298 are objectionable for some other reason, the macro expansion brackets
299 can be changed to any pair of non-empty strings.
300
301 The setbrackets command changes the brackets permanently. For example,
302 you can write pseudo-html by change them to < and >:
303
304 % ::myexp setbrackets < >
305 % ::myexp expand {<bold>This is boldface</bold>}
306 <b>This is boldface</b>
307
308
309 Alternatively, you can change the expansion brackets temporarily by
310 passing the desired brackets to the expand command:
311
312 % ::myexp setbrackets "\\[" "\\]"
313 % ::myexp expand {<bold>This is boldface</bold>} {< >}
314 <b>This is boldface</b>
315 %
316
317
318 CUSTOMIZED MACRO EXPANSION
319 By default, macros are evaluated using the Tcl uplevel #0 command, so
320 that the embedded code executes in the global context. The application
321 can provide a different evaluation command using evalcmd; this allows
322 the application to use a safe interpreter, for example, or even to
323 evaluated something other than Tcl code. There is one caveat: to be
324 recognized as valid, a macro must return 1 when passed to Tcl's "info
325 complete" command.
326
327 For example, the following code "evaluates" each macro by returning the
328 macro text itself.
329
330 proc identity {macro} {return $macro}
331 ::myexp evalcmd identity
332
333
334 USING THE CONTEXT STACK
335 Often it's desirable to define a pair of macros which operate in some
336 way on the plain text between them. Consider a set of macros for
337 adding footnotes to a web page: one could have implement something like
338 this:
339
340 Dr. Pangloss, however, thinks that this is the best of all
341 possible worlds.[footnote "See Candide, by Voltaire"]
342
343
344 The footnote macro would, presumably, assign a number to this footnote
345 and save the text to be formatted later on. However, this solution is
346 ugly if the footnote text is long or should contain additional markup.
347 Consider the following instead:
348
349 Dr. Pangloss, however, thinks that this is the best of all
350 possible worlds.[footnote]See [bookTitle "Candide"], by
351 [authorsName "Voltaire"], for more information.[/footnote]
352
353
354 Here the footnote text is contained between footnote and /footnote
355 macros, continues onto a second line, and contains several macros of
356 its own. This is both clearer and more flexible; however, with the
357 features presented so far there's no easy way to do it. That's the
358 purpose of the context stack.
359
360 All macro expansion takes place in a particular context. Here, the
361 footnote macro pushes a new context onto the context stack. Then, all
362 expanded text gets placed in that new context. /footnote retrieves it
363 by popping the context. Here's a skeleton implementation of these two
364 macros:
365
366 proc footnote {} {
367 ::myexp cpush footnote
368 }
369
370 proc /footnote {} {
371 set footnoteText [::myexp cpop footnote]
372
373 # Save the footnote text, and return an appropriate footnote
374 # number and link.
375 }
376
377
378 The cpush command pushes a new context onto the stack; the argument is
379 the context's name. It can be any string, but would typically be the
380 name of the macro itself. Then, cpop verifies that the current context
381 has the expected name, pops it off of the stack, and returns the accu‐
382 mulated text.
383
384 Expand provides several other tools related to the context stack. Sup‐
385 pose the first macro in a context pair takes arguments or computes val‐
386 ues which the second macro in the pair needs. After calling cpush, the
387 first macro can define one or more context variables; the second macro
388 can retrieve their values any time before calling cpop. For example,
389 suppose the document must specify the footnote number explicitly:
390
391 proc footnote {footnoteNumber} {
392 ::myexp cpush footnote
393 ::myexp csave num $footnoteNumber
394 # Return an appropriate link
395 }
396
397 proc /footnote {} {
398 set footnoteNumber [::myexp cget num]
399 set footnoteText [::myexp cpop footnote]
400
401 # Save the footnote text and its footnoteNumber for future
402 # output.
403 }
404
405
406 At times, it might be desirable to define macros that are valid only
407 within a particular context pair; such macros should verify that they
408 are only called within the correct context using either cis or cname.
409
411 expander was written by William H. Duquette; it is a repackaging of the
412 central algorithm of the expand macro processing tool.
413
415 This document, and the package it describes, will undoubtedly contain
416 bugs and other problems. Please report such in the category textutil
417 :: expander of the Tcllib SF Trackers [http://source‐
418 forge.net/tracker/?group_id=12883]. Please also report any ideas for
419 enhancements you may have for either package and/or documentation.
420
422 http://www.wjduquette.com/expand, regexp, split, string
423
425 string, template processing, text expansion
426
428 Copyright (c) William H. Duquette, http://www.wjduquette.com/expand
429
430
431
432
433textutil 1.3.1 textutil::expander(n)