livetext 0.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/README.html +960 -0
- data/README.ltx +342 -0
- data/README.md +965 -0
- data/dlt +1 -0
- data/livetext.gemspec +12 -0
- data/notes.txt +146 -0
- metadata +50 -0
data/README.ltx
ADDED
@@ -0,0 +1,342 @@
|
|
1
|
+
.mixin lib/tutorial
|
2
|
+
.title Livetext: A smart processor for text
|
3
|
+
|
4
|
+
.p Livetext is simply a tool for transforming text from one format into another. The source file
|
5
|
+
has commands embedded in it, and the output is dependent on those commands.
|
6
|
+
|
7
|
+
.p Why is this special? It's very flexible, very extensible, and it's extensible _(in Ruby).
|
8
|
+
|
9
|
+
.section Why Livetext?
|
10
|
+
|
11
|
+
.p Livetext grew out of several motivations. One was a desire for a markup language that would permit
|
12
|
+
me to write articles (and even books) in my own way and on my own terms. I've done this more
|
13
|
+
than once (and I know others who have, as well).
|
14
|
+
|
15
|
+
.p I liked Softcover, but I found it to be very complex. I never liked Markdown much -- it is very
|
16
|
+
dumb and not extensible at all.
|
17
|
+
|
18
|
+
.p I wanted something that had the basic functionality of all my ad hoc solutions but allowed
|
19
|
+
extensions. Then my old solutions would be like subsets of the new format. This was a generalization
|
20
|
+
similar to the way we began several years ago to view HTML as a subset of XML.
|
21
|
+
|
22
|
+
.section What is Livetext really?
|
23
|
+
|
24
|
+
.p Here goes:
|
25
|
+
.list
|
26
|
+
It's a text transformer
|
27
|
+
It's Ruby-based (later on, more language agnostic)
|
28
|
+
It's (potentially) agnostic about output format
|
29
|
+
It's designed to be flexible, extensible, and easy
|
30
|
+
It's designed to be "plugin" oriented
|
31
|
+
It's like an old-fashioned text formatter (but extensible)
|
32
|
+
It's like a macro processor (but not)
|
33
|
+
It's like markdown and others (but not)
|
34
|
+
It's like erb or HAML (but not)
|
35
|
+
It's powerful but not too dangerous
|
36
|
+
It's not necesarily a markdown replacement
|
37
|
+
It's definitely not a softcover replacement
|
38
|
+
It could possibly augment markdown, softcover, others
|
39
|
+
.end
|
40
|
+
|
41
|
+
.section How does it work?
|
42
|
+
|
43
|
+
.p A Livetext file is simply a text file which may have commands interspersed. A command is
|
44
|
+
simply a period followed by a name and optional parameters (at the beginning of a line).
|
45
|
+
|
46
|
+
.p The period is configurable if you want to use another character. The names are (for now)
|
47
|
+
actual Ruby method names, so names such as `to_s and `inspect are currently not allowed.
|
48
|
+
|
49
|
+
.p Currently I am mostly emitting "dumb HTML" or Markdown as output. In theory, you can write
|
50
|
+
code (or use someone else's) to manipulate text in any way and output any format. Technically,
|
51
|
+
you could even emit PDF, PNG, or SVG formats.
|
52
|
+
|
53
|
+
. Idea: Make an RMagick DSL as an example.
|
54
|
+
|
55
|
+
.p It's possible to embed comments in the text, or even to pass them through to the output
|
56
|
+
in commented form.
|
57
|
+
|
58
|
+
.p The command `.end is special, marking the end of a body of text. Some commands may operate on
|
59
|
+
a block of lines rather than just a few parameters. (A text block is like a here-document.)
|
60
|
+
There is no method name corresponding to the `.end command.
|
61
|
+
|
62
|
+
.p The file extension I've chosen is `.lt (though this may change). *Note: The source for this
|
63
|
+
README is a `.lt file which uses its own little _(ad hoc) library (called `(readme.rb)). Refer to
|
64
|
+
the repo to see these.
|
65
|
+
|
66
|
+
.section Syntax, comments, and more
|
67
|
+
|
68
|
+
.p At first, my idea was to provide predefined commands and allow user-defined commands (to be
|
69
|
+
distinguished by a leading `. or `.. markers). So the single and double dots are both legal.
|
70
|
+
|
71
|
+
However, my concept at present is that the double dots (currently unused) will be used for
|
72
|
+
subcommmands.
|
73
|
+
|
74
|
+
.p User-defined commands may be added to the standard namespace marked with a period. They may
|
75
|
+
also be preceded by a specified character other than the period and thus stored in their own
|
76
|
+
namespace. More on that later.
|
77
|
+
|
78
|
+
.p When a leading period (or double period) is followed by a space, that line is a comment.
|
79
|
+
When it is follwed by a name, that name is typically understood to be a method name. Any
|
80
|
+
remaining text on the line is treated as a parameter list to be accessed by that method.
|
81
|
+
Some methods accept multiple lines of text, terminated by a `.end tag.
|
82
|
+
|
83
|
+
.section Boldface and italics
|
84
|
+
|
85
|
+
.p Very commonly we want to format short words or phrases in italics, boldface, or a monospaced
|
86
|
+
(fixed width) font. The Markdown spec provides ways to do this that are fairly intuitive; but I
|
87
|
+
personally don't like them. My own notation works a different way.
|
88
|
+
|
89
|
+
.p First of all, note that these don't work across source lines; they're strictly intra-line.
|
90
|
+
You may need (for example) an italicized phrase that spans across a newline; at present, you'll
|
91
|
+
need a workaround for that.
|
92
|
+
|
93
|
+
.p I find that most short items I want to format are single tokens. Therefore I use a prefixed
|
94
|
+
character in front of such a token: Underscore for italics, asterisk for boldface, and backtick
|
95
|
+
for "code font." The formatting ends when the first blank space is encountered, without any
|
96
|
+
kind of suffixed character. (This behavior may change to include certain punctuation marks as
|
97
|
+
terminators.)
|
98
|
+
|
99
|
+
.p Of course, there are cases where this won't work; a formatted string may contain spaces, or it
|
100
|
+
may exclude characters before the blank space. In this case, we can use an opening parenthesis
|
101
|
+
after the prefix and a closing parenthesis at the end of the string.
|
102
|
+
|
103
|
+
.p This means that it can be difficult to include a left paren inside a formatted token. I'm thinking
|
104
|
+
about that. It also means that a "literal" prefix character must be escaped.
|
105
|
+
|
106
|
+
.p This is all summarized in this example (taken from one of the testcases):
|
107
|
+
|
108
|
+
.testcase basic_formatting
|
109
|
+
|
110
|
+
.section Standard methods
|
111
|
+
|
112
|
+
.p The module `Livetext::Standard contains the set of standard or predefined methods. Their
|
113
|
+
names are essentially the same as the names of the dot-commands, with occasional exceptions.
|
114
|
+
(For example, it is impractical to use the name `def as a method name, so we use `_def instead.)
|
115
|
+
Here is the current list:
|
116
|
+
|
117
|
+
.dlist
|
118
|
+
`comment ~~ Start a comment block
|
119
|
+
`errout ~~ Write an error message to STDERR
|
120
|
+
`sigil ~~ Change the default sigil from `. to some other character
|
121
|
+
`_def ~~ Define a new method inline
|
122
|
+
`set ~~ Assign values to variables for later interpolation
|
123
|
+
`include ~~ Include an outside text file (to be interpreted as Livetext)
|
124
|
+
`mixin ~~ Mix this file of Ruby methods into the standard namespace
|
125
|
+
`copy ~~ Copy this input file verbatim (no interpretation)
|
126
|
+
`r ~~ Pass a single line through without processing
|
127
|
+
`raw ~~ Pass this special text block (terminated with `(__EOF__)) directly into output without processing
|
128
|
+
.end
|
129
|
+
|
130
|
+
.section Examples from the tests
|
131
|
+
|
132
|
+
Here are some tests from the suite. The file name reflects the general purpose of the test.
|
133
|
+
|
134
|
+
.testcase hello_world
|
135
|
+
.testcase comments_ignored_1
|
136
|
+
.testcase sigil_can_change
|
137
|
+
.testcase block_comment
|
138
|
+
.testcase def_method
|
139
|
+
.testcase simple_vars
|
140
|
+
.testcase simple_include
|
141
|
+
.testcase simple_mixin
|
142
|
+
.testcase simple_copy
|
143
|
+
.testcase copy_is_raw
|
144
|
+
.testcase raw_text_block
|
145
|
+
|
146
|
+
.section Writing custom methods
|
147
|
+
|
148
|
+
.p Suppose you wanted to write a method called `chapter that would simply
|
149
|
+
output a chapter number and title with certain heading tags and a
|
150
|
+
horizontal rule following. There is more than one way to do this.
|
151
|
+
|
152
|
+
.p The simplest way is just to define a method inline with the rest of
|
153
|
+
the text. Here's an example.
|
154
|
+
|
155
|
+
.code
|
156
|
+
.comment
|
157
|
+
This example shows how to define
|
158
|
+
a simple method "chapter" inline
|
159
|
+
.end
|
160
|
+
|
161
|
+
. This is also a comment, by the way.
|
162
|
+
.def chapter
|
163
|
+
params = _args
|
164
|
+
raise "chapter: expecting at least two args" unless params.size > 1
|
165
|
+
num, *title = params # Chapter number + title
|
166
|
+
title = title.join(" ") # Join all words into one string
|
167
|
+
text = <<-HTML
|
168
|
+
<h3>Chapter #{num}</h3>
|
169
|
+
<h2>#{title}</h2>
|
170
|
+
<hr>
|
171
|
+
HTML
|
172
|
+
_puts text
|
173
|
+
.end
|
174
|
+
. Now let's invoke it...
|
175
|
+
.chapter 1 Why I Went to the Woods
|
176
|
+
It was the best of times, and you can call me Ishmael. The clocks
|
177
|
+
were striking thirteen.
|
178
|
+
.end
|
179
|
+
|
180
|
+
.p What can we see from this example? First of all, notice that the part
|
181
|
+
between `.def and `.end (the body of the method) really is just Ruby
|
182
|
+
code. The method takes no parameters because parameter passing is
|
183
|
+
handled inside the Livetext engine and the instance variable `@_args is
|
184
|
+
initialized to the contents of this array. We usually refer to the
|
185
|
+
`@_args array only through the method `_args which returns it.
|
186
|
+
|
187
|
+
The `_args method is also an iterator. If a block is attached, that block
|
188
|
+
will be called for every argument.
|
189
|
+
|
190
|
+
.p We then create a string using these parameters and call it using the
|
191
|
+
`_puts method. This really does do a `puts call, but it applies it to
|
192
|
+
wherever the output is currently being sent (defaulting to STDOUT).
|
193
|
+
|
194
|
+
.p All the "helper" methods start with an underscore so as to avoid name
|
195
|
+
collisions. These are all stored in the `Livetext::Helpers module
|
196
|
+
(which also has some methods you will never use).
|
197
|
+
|
198
|
+
.p Here is the HTML output of the previous example:
|
199
|
+
|
200
|
+
.code
|
201
|
+
<h3>Chapter 1</h3>
|
202
|
+
<h2>Why I Went to the Woods</h2>
|
203
|
+
<hr>
|
204
|
+
It was the best of times, and you can call me Ishmael. The clocks
|
205
|
+
were striking thirteen.
|
206
|
+
.end
|
207
|
+
|
208
|
+
.p What are some other helper methods? Here's a list.
|
209
|
+
|
210
|
+
.dlist
|
211
|
+
`_args ~~ Returns an array of arguments for the method (or an enumerator for that array)
|
212
|
+
`_data ~~ A single "unsplit" string of all arguments in raw form
|
213
|
+
`_body ~~ Returns a string (or enumerator) giving access to the text block (preceding `(.end))
|
214
|
+
`_puts ~~ Write a line to output (STDOUT or wherever)
|
215
|
+
`_print ~~ Write a line to output (STDOUT or wherever) without a newline
|
216
|
+
`_formatting ~~ A function transforming boldface, italics, and monospace (Livetext conventions)
|
217
|
+
`_var_substitution ~~ Substitute variables into a string
|
218
|
+
`_passthru ~~ Feed a line directly into output after transforming and substituting
|
219
|
+
.end
|
220
|
+
|
221
|
+
.p Note that the last three methods are typically _not called in your own code. They could be,
|
222
|
+
but it remains to be seen whether something that advanced is useful.
|
223
|
+
|
224
|
+
.section More examples
|
225
|
+
|
226
|
+
.p Suppose you wanted to take a list of words, more than one per line, and alphabetize them.
|
227
|
+
Let's write a method called `alpha for that. This exercise and the next one are implemented
|
228
|
+
in the test suite.
|
229
|
+
|
230
|
+
.testcase example_alpha
|
231
|
+
|
232
|
+
.p I'll let that code stand on its own. Now suppose you wanted to allow columnar output. Let's
|
233
|
+
have the user specify a number of columns (from 1 to 5, defaulting to 1).
|
234
|
+
|
235
|
+
.testcase example_alpha2
|
236
|
+
|
237
|
+
.p What if we wanted to store the code outside the text file? There is more than one way to
|
238
|
+
do this.
|
239
|
+
|
240
|
+
.p Let's assume we have a file called `mylib.rb in the same directory as the file we're processing.
|
241
|
+
(Issues such as paths and security have not been addressed yet.) We'll stick the actual Ruby code
|
242
|
+
in here (and nothing else).
|
243
|
+
|
244
|
+
.code
|
245
|
+
# File: mylib.rb
|
246
|
+
|
247
|
+
def alpha
|
248
|
+
cols = _args.first
|
249
|
+
cols = "1" if cols == ""
|
250
|
+
cols = cols.to_i
|
251
|
+
raise "Columns must be 1-5" unless cols.between?(1,5)
|
252
|
+
text = _body.join
|
253
|
+
text.gsub!(/\n/, " ")
|
254
|
+
words = text.split.sort
|
255
|
+
words.each_slice(cols) do |row|
|
256
|
+
row.each {|w| _print '%-15s' % w }
|
257
|
+
_puts
|
258
|
+
end
|
259
|
+
end
|
260
|
+
.end
|
261
|
+
|
262
|
+
.p Now the `.lt file can be written this way:
|
263
|
+
|
264
|
+
.code
|
265
|
+
.mixin mylib
|
266
|
+
Here is an alphabetized list:
|
267
|
+
|
268
|
+
.alpha 3
|
269
|
+
fishmonger anarchist aardvark glyph gryphon
|
270
|
+
halcyon zymurgy mataeotechny zootrope
|
271
|
+
pareidolia manicotti quark bellicose anamorphic
|
272
|
+
cytology fusillade ectomorph
|
273
|
+
.end
|
274
|
+
|
275
|
+
I hope that worked a second time.
|
276
|
+
.end
|
277
|
+
|
278
|
+
.p The output, of course, is the same.
|
279
|
+
|
280
|
+
.p There is an important feature that has not yet been implemented (the
|
281
|
+
`require method). Like Ruby's `(require), it will grab Ruby code and
|
282
|
+
load it; however, unlike `(mixin), it will load it into a customized
|
283
|
+
object and associate a new sigil with it. So for example, the command
|
284
|
+
`.foobar would refer to a method in the `Livetext::Standard class
|
285
|
+
(whether predefined or user-defined). If we did a `require on a file
|
286
|
+
and associated the sigil `# with it, then `#foobar would be a method
|
287
|
+
on that new custom object. I will implement this soon.
|
288
|
+
|
289
|
+
.section Issues, open questions, and to-do items
|
290
|
+
|
291
|
+
.p This list is not prioritized yet.
|
292
|
+
|
293
|
+
.nlist
|
294
|
+
Add versioning information
|
295
|
+
Clean up code structure
|
296
|
+
Add RDoc
|
297
|
+
Think about command line executable
|
298
|
+
Write as pure library in addition to executable
|
299
|
+
Package as gem
|
300
|
+
Document: `require `include `copy `mixin `errout and others
|
301
|
+
Need much better error checking and corresponding tests
|
302
|
+
Worry about nesting of elements (probably mostly disallow)
|
303
|
+
Think about UTF-8
|
304
|
+
Document API fully
|
305
|
+
Add `_raw_args and let `_args honor quotes
|
306
|
+
Support quotes in `.set values
|
307
|
+
Support "namespaced" variables (`(.set code.font="whatever"))
|
308
|
+
Support functions (`($$func)) including namespacing
|
309
|
+
Create predefined variables and functions (e.g., `($_source_file), `$(_line), `($$_today))
|
310
|
+
Support markdown-style bold/italics? (`_markdown replaces `_formatting method)
|
311
|
+
Allow turning on/off: formatting, variable interpolation, function interpolation?
|
312
|
+
`.require with file and sigil parameters
|
313
|
+
Investigate "common intermediate format" - output renderers all read it
|
314
|
+
Comments passed through (e.g. as HTML comments)
|
315
|
+
`.run to execute arbitrary Ruby code inline?
|
316
|
+
Concept of `.proc (guaranteed to return no value, produce no output)?
|
317
|
+
Exceptions??
|
318
|
+
Ruby `$SAFE levels?
|
319
|
+
Warn when overriding existing names?
|
320
|
+
Think about passing data in (erb replacement)
|
321
|
+
Allow custom ending tag on `raw method
|
322
|
+
Ignore first blank line after `(.end)? (and after raw-tag?)
|
323
|
+
Allow/encourage custom `passthru method?
|
324
|
+
Must have sane support for CSS
|
325
|
+
Support for Pygments and/or other code processors
|
326
|
+
Support for gists? arbitrary links? other remote resouces?
|
327
|
+
Small libraries for special purposes (books? special Softcover support? blogs? PDF? RMagick?)
|
328
|
+
Experiment with idea of special libraries having pluggable output formats (via Ruby mixin?)
|
329
|
+
Imagining a lib that can run/test code fragments as part of document generation
|
330
|
+
Create vim (emacs?) syntax files
|
331
|
+
Someday: Support other languages (Elixir, Python, ...)
|
332
|
+
`.pry method?
|
333
|
+
`.irb method?
|
334
|
+
Other debugging features
|
335
|
+
Feature to "break" to EOF?
|
336
|
+
`.meth? method ending in `? takes a block that may be processed or thrown away (`(.else) perhaps?)
|
337
|
+
`.dump to dump all variables and their values
|
338
|
+
`.if and `(.else)?
|
339
|
+
Make any/all delimiters configurable
|
340
|
+
HTML helper? (in their own library?)
|
341
|
+
.end
|
342
|
+
|
data/README.md
ADDED
@@ -0,0 +1,965 @@
|
|
1
|
+
<center><h2>Livetext: A smart processor for text</h2></center>
|
2
|
+
|
3
|
+
Livetext is simply a tool for transforming text from one format into another. The source file
|
4
|
+
has commands embedded in it, and the output is dependent on those commands.
|
5
|
+
|
6
|
+
Why is this special? It's very flexible, very extensible, and it's extensible <i>in Ruby</i>.
|
7
|
+
|
8
|
+
<br><br><b><font size=+1>Why Livetext?</font></b><br>
|
9
|
+
|
10
|
+
Livetext grew out of several motivations. One was a desire for a markup language that would permit
|
11
|
+
me to write articles (and even books) in my own way and on my own terms. I've done this more
|
12
|
+
than once (and I know others who have, as well).
|
13
|
+
|
14
|
+
I liked Softcover, but I found it to be very complex. I never liked Markdown much -- it is very
|
15
|
+
dumb and not extensible at all.
|
16
|
+
|
17
|
+
I wanted something that had the basic functionality of all my ad hoc solutions but allowed
|
18
|
+
extensions. Then my old solutions would be like subsets of the new format. This was a generalization
|
19
|
+
similar to the way we began several years ago to view HTML as a subset of XML.
|
20
|
+
|
21
|
+
<br><br><b><font size=+1>What is Livetext really?</font></b><br>
|
22
|
+
|
23
|
+
Here goes:
|
24
|
+
<ul>
|
25
|
+
<li>It's a text transformer
|
26
|
+
</li>
|
27
|
+
<li>It's Ruby-based (later on, more language agnostic)
|
28
|
+
</li>
|
29
|
+
<li>It's (potentially) agnostic about output format
|
30
|
+
</li>
|
31
|
+
<li>It's designed to be flexible, extensible, and easy
|
32
|
+
</li>
|
33
|
+
<li>It's designed to be "plugin" oriented
|
34
|
+
</li>
|
35
|
+
<li>It's like an old-fashioned text formatter (but extensible)
|
36
|
+
</li>
|
37
|
+
<li>It's like a macro processor (but not)
|
38
|
+
</li>
|
39
|
+
<li>It's like markdown and others (but not)
|
40
|
+
</li>
|
41
|
+
<li>It's like erb or HAML (but not)
|
42
|
+
</li>
|
43
|
+
<li>It's powerful but not too dangerous
|
44
|
+
</li>
|
45
|
+
<li>It's not necesarily a markdown replacement
|
46
|
+
</li>
|
47
|
+
<li>It's definitely not a softcover replacement
|
48
|
+
</li>
|
49
|
+
<li>It could possibly augment markdown, softcover, others
|
50
|
+
</li>
|
51
|
+
</ul>
|
52
|
+
|
53
|
+
<br><br><b><font size=+1>How does it work?</font></b><br>
|
54
|
+
|
55
|
+
A Livetext file is simply a text file which may have commands interspersed. A command is
|
56
|
+
simply a period followed by a name and optional parameters (at the beginning of a line).
|
57
|
+
|
58
|
+
The period is configurable if you want to use another character. The names are (for now)
|
59
|
+
actual Ruby method names, so names such as <tt>to_s</tt> and <tt>inspect</tt> are currently not allowed.
|
60
|
+
|
61
|
+
Currently I am mostly emitting "dumb HTML" or Markdown as output. In theory, you can write
|
62
|
+
code (or use someone else's) to manipulate text in any way and output any format. Technically,
|
63
|
+
you could even emit PDF, PNG, or SVG formats.
|
64
|
+
|
65
|
+
|
66
|
+
It's possible to embed comments in the text, or even to pass them through to the output
|
67
|
+
in commented form.
|
68
|
+
|
69
|
+
The command <tt>.end</tt> is special, marking the end of a body of text. Some commands may operate on
|
70
|
+
a block of lines rather than just a few parameters. (A text block is like a here-document.)
|
71
|
+
There is no method name corresponding to the <tt>.end</tt> command.
|
72
|
+
|
73
|
+
The file extension I've chosen is <tt>.lt</tt> (though this may change). <b>Note:</b> The source for this
|
74
|
+
README is a <tt>.lt</tt> file which uses its own little <i>ad hoc</i> library (called <tt>readme.rb</tt>). Refer to
|
75
|
+
the repo to see these.
|
76
|
+
|
77
|
+
<br><br><b><font size=+1>Syntax, comments, and more</font></b><br>
|
78
|
+
|
79
|
+
At first, my idea was to provide predefined commands and allow user-defined commands (to be
|
80
|
+
distinguished by a leading <tt>.</tt> or <tt>..</tt> markers). So the single and double dots are both legal.
|
81
|
+
|
82
|
+
However, my concept at present is that the double dots (currently unused) will be used for
|
83
|
+
subcommmands.
|
84
|
+
|
85
|
+
User-defined commands may be added to the standard namespace marked with a period. They may
|
86
|
+
also be preceded by a specified character other than the period and thus stored in their own
|
87
|
+
namespace. More on that later.
|
88
|
+
|
89
|
+
When a leading period (or double period) is followed by a space, that line is a comment.
|
90
|
+
When it is follwed by a name, that name is typically understood to be a method name. Any
|
91
|
+
remaining text on the line is treated as a parameter list to be accessed by that method.
|
92
|
+
Some methods accept multiple lines of text, terminated by a <tt>.end</tt> tag.
|
93
|
+
|
94
|
+
<br><br><b><font size=+1>Boldface and italics</font></b><br>
|
95
|
+
|
96
|
+
Very commonly we want to format short words or phrases in italics, boldface, or a monospaced
|
97
|
+
(fixed width) font. The Markdown spec provides ways to do this that are fairly intuitive; but I
|
98
|
+
personally don't like them. My own notation works a different way.
|
99
|
+
|
100
|
+
First of all, note that these don't work across source lines; they're strictly intra-line.
|
101
|
+
You may need (for example) an italicized phrase that spans across a newline; at present, you'll
|
102
|
+
need a workaround for that.
|
103
|
+
|
104
|
+
I find that most short items I want to format are single tokens. Therefore I use a prefixed
|
105
|
+
character in front of such a token: Underscore for italics, asterisk for boldface, and backtick
|
106
|
+
for "code font." The formatting ends when the first blank space is encountered, without any
|
107
|
+
kind of suffixed character. (This behavior may change to include certain punctuation marks as
|
108
|
+
terminators.)
|
109
|
+
|
110
|
+
Of course, there are cases where this won't work; a formatted string may contain spaces, or it
|
111
|
+
may exclude characters before the blank space. In this case, we can use an opening parenthesis
|
112
|
+
after the prefix and a closing parenthesis at the end of the string.
|
113
|
+
|
114
|
+
This means that it can be difficult to include a left paren inside a formatted token. I'm thinking
|
115
|
+
about that. It also means that a "literal" prefix character must be escaped.
|
116
|
+
|
117
|
+
This is all summarized in this example (taken from one of the testcases):
|
118
|
+
|
119
|
+
|
120
|
+
<b>Test: <tt>015\_basic\_formatting</tt></b><br>
|
121
|
+
<center>
|
122
|
+
<table width=80% cellpadding=4>
|
123
|
+
<tr>
|
124
|
+
<td width=50%><b>Input</b></td>
|
125
|
+
<td width=50%><b>Output</b></td>
|
126
|
+
</tr>
|
127
|
+
<tr>
|
128
|
+
<td width=50% bgcolor=#fec0fe valign=top>
|
129
|
+
<pre> Here are examples of *boldface and \_italics and `code
|
130
|
+
as well as *(more complex) examples of \_(italicized text)
|
131
|
+
and `(code font).
|
132
|
+
|
133
|
+
Here are some random punctuation marks:
|
134
|
+
# . @ * \_ ` : ; % ^ & $
|
135
|
+
|
136
|
+
Oops, forgot to escape these: \* \\_ \`
|
137
|
+
</pre>
|
138
|
+
</td>
|
139
|
+
<td width=50% bgcolor=lightgray valign=top>
|
140
|
+
<pre> Here are examples of <b>boldface</b> and <i>italics</i> and <tt>code</tt>
|
141
|
+
as well as <b>more complex</b> examples of <i>italicized text</i>
|
142
|
+
and <tt>code font</tt>.
|
143
|
+
|
144
|
+
Here are some random punctuation marks:
|
145
|
+
# . @ * \_ ` : ; % ^ & $
|
146
|
+
|
147
|
+
Oops, forgot to escape these: * \_ `
|
148
|
+
</pre>
|
149
|
+
</td>
|
150
|
+
</tr>
|
151
|
+
</table>
|
152
|
+
</center>
|
153
|
+
|
154
|
+
<br><br><b><font size=+1>Standard methods</font></b><br>
|
155
|
+
|
156
|
+
The module <tt>Livetext::Standard</tt> contains the set of standard or predefined methods. Their
|
157
|
+
names are essentially the same as the names of the dot-commands, with occasional exceptions.
|
158
|
+
(For example, it is impractical to use the name <tt>def</tt> as a method name, so we use <tt>_def</tt> instead.)
|
159
|
+
Here is the current list:
|
160
|
+
|
161
|
+
<table>
|
162
|
+
<tr>
|
163
|
+
<td width=3%><td width=10%> <tt>comment</tt> </td><td> Start a comment block
|
164
|
+
</td>
|
165
|
+
</tr>
|
166
|
+
<tr>
|
167
|
+
<td width=3%><td width=10%> <tt>errout</tt> </td><td> Write an error message to STDERR
|
168
|
+
</td>
|
169
|
+
</tr>
|
170
|
+
<tr>
|
171
|
+
<td width=3%><td width=10%> <tt>sigil</tt> </td><td> Change the default sigil from <tt>.</tt> to some other character
|
172
|
+
</td>
|
173
|
+
</tr>
|
174
|
+
<tr>
|
175
|
+
<td width=3%><td width=10%> <tt>_def</tt> </td><td> Define a new method inline
|
176
|
+
</td>
|
177
|
+
</tr>
|
178
|
+
<tr>
|
179
|
+
<td width=3%><td width=10%> <tt>set</tt> </td><td> Assign values to variables for later interpolation
|
180
|
+
</td>
|
181
|
+
</tr>
|
182
|
+
<tr>
|
183
|
+
<td width=3%><td width=10%> <tt>include</tt> </td><td> Include an outside text file (to be interpreted as Livetext)
|
184
|
+
</td>
|
185
|
+
</tr>
|
186
|
+
<tr>
|
187
|
+
<td width=3%><td width=10%> <tt>mixin</tt> </td><td> Mix this file of Ruby methods into the standard namespace
|
188
|
+
</td>
|
189
|
+
</tr>
|
190
|
+
<tr>
|
191
|
+
<td width=3%><td width=10%> <tt>copy</tt> </td><td> Copy this input file verbatim (no interpretation)
|
192
|
+
</td>
|
193
|
+
</tr>
|
194
|
+
<tr>
|
195
|
+
<td width=3%><td width=10%> <tt>r</tt> </td><td> Pass a single line through without processing
|
196
|
+
</td>
|
197
|
+
</tr>
|
198
|
+
<tr>
|
199
|
+
<td width=3%><td width=10%> <tt>raw</tt> </td><td> Pass this special text block (terminated with <tt>__EOF__</tt>) directly into output without processing
|
200
|
+
</td>
|
201
|
+
</tr>
|
202
|
+
</table>
|
203
|
+
|
204
|
+
<br><br><b><font size=+1>Examples from the tests</font></b><br>
|
205
|
+
|
206
|
+
Here are some tests from the suite. The file name reflects the general purpose of the test.
|
207
|
+
|
208
|
+
|
209
|
+
<b>Test: <tt>001\_hello\_world</tt></b><br>
|
210
|
+
<center>
|
211
|
+
<table width=80% cellpadding=4>
|
212
|
+
<tr>
|
213
|
+
<td width=50%><b>Input</b></td>
|
214
|
+
<td width=50%><b>Output</b></td>
|
215
|
+
</tr>
|
216
|
+
<tr>
|
217
|
+
<td width=50% bgcolor=#fec0fe valign=top>
|
218
|
+
<pre> Hello,
|
219
|
+
world!
|
220
|
+
</pre>
|
221
|
+
</td>
|
222
|
+
<td width=50% bgcolor=lightgray valign=top>
|
223
|
+
<pre> Hello,
|
224
|
+
world!
|
225
|
+
</pre>
|
226
|
+
</td>
|
227
|
+
</tr>
|
228
|
+
</table>
|
229
|
+
</center>
|
230
|
+
|
231
|
+
<b>Test: <tt>002\_comments\_ignored\_1</tt></b><br>
|
232
|
+
<center>
|
233
|
+
<table width=80% cellpadding=4>
|
234
|
+
<tr>
|
235
|
+
<td width=50%><b>Input</b></td>
|
236
|
+
<td width=50%><b>Output</b></td>
|
237
|
+
</tr>
|
238
|
+
<tr>
|
239
|
+
<td width=50% bgcolor=#fec0fe valign=top>
|
240
|
+
<pre> . Comments are ignored
|
241
|
+
abc 123
|
242
|
+
this is a test
|
243
|
+
. whether at beginning, middle, or
|
244
|
+
more stuff
|
245
|
+
still more stuff
|
246
|
+
. end of the file
|
247
|
+
</pre>
|
248
|
+
</td>
|
249
|
+
<td width=50% bgcolor=lightgray valign=top>
|
250
|
+
<pre> abc 123
|
251
|
+
this is a test
|
252
|
+
more stuff
|
253
|
+
still more stuff
|
254
|
+
</pre>
|
255
|
+
</td>
|
256
|
+
</tr>
|
257
|
+
</table>
|
258
|
+
</center>
|
259
|
+
|
260
|
+
<b>Test: <tt>003\_comments\_ignored\_2</tt></b><br>
|
261
|
+
<center>
|
262
|
+
<table width=80% cellpadding=4>
|
263
|
+
<tr>
|
264
|
+
<td width=50%><b>Input</b></td>
|
265
|
+
<td width=50%><b>Output</b></td>
|
266
|
+
</tr>
|
267
|
+
<tr>
|
268
|
+
<td width=50% bgcolor=#fec0fe valign=top>
|
269
|
+
<pre> .. Comments (with a double-dot) are ignored
|
270
|
+
abc 123
|
271
|
+
this is a test
|
272
|
+
.. whether at beginning, middle, or
|
273
|
+
more stuff
|
274
|
+
still more stuff
|
275
|
+
.. end of the file
|
276
|
+
</pre>
|
277
|
+
</td>
|
278
|
+
<td width=50% bgcolor=lightgray valign=top>
|
279
|
+
<pre> abc 123
|
280
|
+
this is a test
|
281
|
+
more stuff
|
282
|
+
still more stuff
|
283
|
+
</pre>
|
284
|
+
</td>
|
285
|
+
</tr>
|
286
|
+
</table>
|
287
|
+
</center>
|
288
|
+
|
289
|
+
<b>Test: <tt>004\_sigil\_can\_change</tt></b><br>
|
290
|
+
<center>
|
291
|
+
<table width=80% cellpadding=4>
|
292
|
+
<tr>
|
293
|
+
<td width=50%><b>Input</b></td>
|
294
|
+
<td width=50%><b>Output</b></td>
|
295
|
+
</tr>
|
296
|
+
<tr>
|
297
|
+
<td width=50% bgcolor=#fec0fe valign=top>
|
298
|
+
<pre> . This is a comment
|
299
|
+
.sigil #
|
300
|
+
# Comments are ignored
|
301
|
+
abc 123
|
302
|
+
this is a test
|
303
|
+
. this is not a comment
|
304
|
+
# whether at beginning, middle, or
|
305
|
+
more stuff
|
306
|
+
.this means nothing
|
307
|
+
still more stuff
|
308
|
+
# end of the file
|
309
|
+
</pre>
|
310
|
+
</td>
|
311
|
+
<td width=50% bgcolor=lightgray valign=top>
|
312
|
+
<pre> abc 123
|
313
|
+
this is a test
|
314
|
+
. this is not a comment
|
315
|
+
more stuff
|
316
|
+
.this means nothing
|
317
|
+
still more stuff
|
318
|
+
</pre>
|
319
|
+
</td>
|
320
|
+
</tr>
|
321
|
+
</table>
|
322
|
+
</center>
|
323
|
+
|
324
|
+
<b>Test: <tt>005\_block\_comment</tt></b><br>
|
325
|
+
<center>
|
326
|
+
<table width=80% cellpadding=4>
|
327
|
+
<tr>
|
328
|
+
<td width=50%><b>Input</b></td>
|
329
|
+
<td width=50%><b>Output</b></td>
|
330
|
+
</tr>
|
331
|
+
<tr>
|
332
|
+
<td width=50% bgcolor=#fec0fe valign=top>
|
333
|
+
<pre> .comment
|
334
|
+
This is
|
335
|
+
a comment
|
336
|
+
.end
|
337
|
+
abc 123
|
338
|
+
xyz
|
339
|
+
.comment
|
340
|
+
And so is this.
|
341
|
+
.end
|
342
|
+
|
343
|
+
one
|
344
|
+
more
|
345
|
+
time
|
346
|
+
.comment
|
347
|
+
And so
|
348
|
+
is
|
349
|
+
this
|
350
|
+
.end
|
351
|
+
</pre>
|
352
|
+
</td>
|
353
|
+
<td width=50% bgcolor=lightgray valign=top>
|
354
|
+
<pre> abc 123
|
355
|
+
xyz
|
356
|
+
|
357
|
+
one
|
358
|
+
more
|
359
|
+
time
|
360
|
+
</pre>
|
361
|
+
</td>
|
362
|
+
</tr>
|
363
|
+
</table>
|
364
|
+
</center>
|
365
|
+
|
366
|
+
<b>Test: <tt>006\_def\_method</tt></b><br>
|
367
|
+
<center>
|
368
|
+
<table width=80% cellpadding=4>
|
369
|
+
<tr>
|
370
|
+
<td width=50%><b>Input</b></td>
|
371
|
+
<td width=50%><b>Output</b></td>
|
372
|
+
</tr>
|
373
|
+
<tr>
|
374
|
+
<td width=50% bgcolor=#fec0fe valign=top>
|
375
|
+
<pre> abc
|
376
|
+
123
|
377
|
+
.def foobar
|
378
|
+
::STDERR.puts "This is the"
|
379
|
+
::STDERR.puts "foobar method"
|
380
|
+
.end
|
381
|
+
xyz
|
382
|
+
.foobar
|
383
|
+
xyzzy
|
384
|
+
123
|
385
|
+
</pre>
|
386
|
+
</td>
|
387
|
+
<td width=50% bgcolor=lightgray valign=top>
|
388
|
+
<pre> abc
|
389
|
+
123
|
390
|
+
xyz
|
391
|
+
xyzzy
|
392
|
+
123
|
393
|
+
</pre>
|
394
|
+
</td>
|
395
|
+
</tr>
|
396
|
+
</table>
|
397
|
+
</center>
|
398
|
+
|
399
|
+
<b>Test: <tt>007\_simple\_vars</tt></b><br>
|
400
|
+
<center>
|
401
|
+
<table width=80% cellpadding=4>
|
402
|
+
<tr>
|
403
|
+
<td width=50%><b>Input</b></td>
|
404
|
+
<td width=50%><b>Output</b></td>
|
405
|
+
</tr>
|
406
|
+
<tr>
|
407
|
+
<td width=50% bgcolor=#fec0fe valign=top>
|
408
|
+
<pre> Just
|
409
|
+
some text.
|
410
|
+
.set name=GulliverFoyle,nation=Terra
|
411
|
+
Hi, there.
|
412
|
+
$name is my name, and $nation is my nation.
|
413
|
+
I'm $name, from $nation.
|
414
|
+
That's all.
|
415
|
+
</pre>
|
416
|
+
</td>
|
417
|
+
<td width=50% bgcolor=lightgray valign=top>
|
418
|
+
<pre> Just
|
419
|
+
some text.
|
420
|
+
Hi, there.
|
421
|
+
GulliverFoyle is my name, and Terra is my nation.
|
422
|
+
I'm GulliverFoyle, from Terra.
|
423
|
+
That's all.
|
424
|
+
</pre>
|
425
|
+
</td>
|
426
|
+
</tr>
|
427
|
+
</table>
|
428
|
+
</center>
|
429
|
+
|
430
|
+
<b>Test: <tt>008\_simple\_include</tt></b><br>
|
431
|
+
<center>
|
432
|
+
<table width=80% cellpadding=4>
|
433
|
+
<tr>
|
434
|
+
<td width=50%><b>Input</b></td>
|
435
|
+
<td width=50%><b>Output</b></td>
|
436
|
+
</tr>
|
437
|
+
<tr>
|
438
|
+
<td width=50% bgcolor=#fec0fe valign=top>
|
439
|
+
<pre> Here I am
|
440
|
+
trying to
|
441
|
+
include
|
442
|
+
.include simplefile.inc
|
443
|
+
I hope that
|
444
|
+
worked.
|
445
|
+
</pre>
|
446
|
+
</td>
|
447
|
+
<td width=50% bgcolor=lightgray valign=top>
|
448
|
+
<pre> Here I am
|
449
|
+
trying to
|
450
|
+
include
|
451
|
+
a simple
|
452
|
+
include file.
|
453
|
+
I hope that
|
454
|
+
worked.
|
455
|
+
</pre>
|
456
|
+
</td>
|
457
|
+
</tr>
|
458
|
+
</table>
|
459
|
+
</center>
|
460
|
+
|
461
|
+
<b>Test: <tt>009\_simple\_mixin</tt></b><br>
|
462
|
+
<center>
|
463
|
+
<table width=80% cellpadding=4>
|
464
|
+
<tr>
|
465
|
+
<td width=50%><b>Input</b></td>
|
466
|
+
<td width=50%><b>Output</b></td>
|
467
|
+
</tr>
|
468
|
+
<tr>
|
469
|
+
<td width=50% bgcolor=#fec0fe valign=top>
|
470
|
+
<pre> Here I am
|
471
|
+
testing a simple mixin
|
472
|
+
.mixin simple\_mixin
|
473
|
+
Now call it:
|
474
|
+
.hello\_world
|
475
|
+
That's all.
|
476
|
+
</pre>
|
477
|
+
</td>
|
478
|
+
<td width=50% bgcolor=lightgray valign=top>
|
479
|
+
<pre> Here I am
|
480
|
+
testing a simple mixin
|
481
|
+
Now call it:
|
482
|
+
Hello, world.
|
483
|
+
That's all.
|
484
|
+
</pre>
|
485
|
+
</td>
|
486
|
+
</tr>
|
487
|
+
</table>
|
488
|
+
</center>
|
489
|
+
|
490
|
+
<b>Test: <tt>010\_simple\_copy</tt></b><br>
|
491
|
+
<center>
|
492
|
+
<table width=80% cellpadding=4>
|
493
|
+
<tr>
|
494
|
+
<td width=50%><b>Input</b></td>
|
495
|
+
<td width=50%><b>Output</b></td>
|
496
|
+
</tr>
|
497
|
+
<tr>
|
498
|
+
<td width=50% bgcolor=#fec0fe valign=top>
|
499
|
+
<pre> The copy command
|
500
|
+
copies any file
|
501
|
+
without interpretation,
|
502
|
+
such as:
|
503
|
+
.copy simplefile.inc
|
504
|
+
That is all.
|
505
|
+
</pre>
|
506
|
+
</td>
|
507
|
+
<td width=50% bgcolor=lightgray valign=top>
|
508
|
+
<pre> The copy command
|
509
|
+
copies any file
|
510
|
+
without interpretation,
|
511
|
+
such as:
|
512
|
+
a simple
|
513
|
+
include file.
|
514
|
+
That is all.
|
515
|
+
</pre>
|
516
|
+
</td>
|
517
|
+
</tr>
|
518
|
+
</table>
|
519
|
+
</center>
|
520
|
+
|
521
|
+
<b>Test: <tt>011\_copy\_is\_raw</tt></b><br>
|
522
|
+
<center>
|
523
|
+
<table width=80% cellpadding=4>
|
524
|
+
<tr>
|
525
|
+
<td width=50%><b>Input</b></td>
|
526
|
+
<td width=50%><b>Output</b></td>
|
527
|
+
</tr>
|
528
|
+
<tr>
|
529
|
+
<td width=50% bgcolor=#fec0fe valign=top>
|
530
|
+
<pre> A copy command
|
531
|
+
does not interpret its input:
|
532
|
+
.copy rawtext.inc
|
533
|
+
That's all.
|
534
|
+
</pre>
|
535
|
+
</td>
|
536
|
+
<td width=50% bgcolor=lightgray valign=top>
|
537
|
+
<pre> A copy command
|
538
|
+
does not interpret its input:
|
539
|
+
This is not a comment:
|
540
|
+
.comment woohoo!
|
541
|
+
This is not a method:
|
542
|
+
.no\_such\_method
|
543
|
+
That's all.
|
544
|
+
</pre>
|
545
|
+
</td>
|
546
|
+
</tr>
|
547
|
+
</table>
|
548
|
+
</center>
|
549
|
+
|
550
|
+
<b>Test: <tt>012\_raw\_text\_block</tt></b><br>
|
551
|
+
<center>
|
552
|
+
<table width=80% cellpadding=4>
|
553
|
+
<tr>
|
554
|
+
<td width=50%><b>Input</b></td>
|
555
|
+
<td width=50%><b>Output</b></td>
|
556
|
+
</tr>
|
557
|
+
<tr>
|
558
|
+
<td width=50% bgcolor=#fec0fe valign=top>
|
559
|
+
<pre> This text block will be passed thru
|
560
|
+
with no interpretation or processing:
|
561
|
+
.raw
|
562
|
+
.comment
|
563
|
+
This isn't a
|
564
|
+
real comment.
|
565
|
+
.end This isn't picked up.
|
566
|
+
|
567
|
+
.not\_a\_method
|
568
|
+
|
569
|
+
And this stuff won't be munged: `alpha \_beta *gamma
|
570
|
+
Or this: `(alpha male) \_(beta max) *(gamma rays)
|
571
|
+
\_\_EOF\_\_
|
572
|
+
|
573
|
+
I hope that worked.
|
574
|
+
</pre>
|
575
|
+
</td>
|
576
|
+
<td width=50% bgcolor=lightgray valign=top>
|
577
|
+
<pre> This text block will be passed thru
|
578
|
+
with no interpretation or processing:
|
579
|
+
.comment
|
580
|
+
This isn't a
|
581
|
+
real comment.
|
582
|
+
.end This isn't picked up.
|
583
|
+
|
584
|
+
.not\_a\_method
|
585
|
+
|
586
|
+
And this stuff won't be munged: `alpha \_beta *gamma
|
587
|
+
Or this: `(alpha male) \_(beta max) *(gamma rays)
|
588
|
+
|
589
|
+
I hope that worked.
|
590
|
+
</pre>
|
591
|
+
</td>
|
592
|
+
</tr>
|
593
|
+
</table>
|
594
|
+
</center>
|
595
|
+
|
596
|
+
<br><br><b><font size=+1>Writing custom methods</font></b><br>
|
597
|
+
|
598
|
+
Suppose you wanted to write a method called <tt>chapter</tt> that would simply
|
599
|
+
output a chapter number and title with certain heading tags and a
|
600
|
+
horizontal rule following. There is more than one way to do this.
|
601
|
+
|
602
|
+
The simplest way is just to define a method inline with the rest of
|
603
|
+
the text. Here's an example.
|
604
|
+
|
605
|
+
<pre>
|
606
|
+
.comment
|
607
|
+
This example shows how to define
|
608
|
+
a simple method "chapter" inline
|
609
|
+
.end
|
610
|
+
|
611
|
+
. This is also a comment, by the way.
|
612
|
+
.def chapter
|
613
|
+
params = _args
|
614
|
+
raise "chapter: expecting at least two args" unless params.size > 1
|
615
|
+
num, *title = params # Chapter number + title
|
616
|
+
title = title.join(" ") # Join all words into one string
|
617
|
+
text = <<-HTML
|
618
|
+
<h3>Chapter #{num}</h3>
|
619
|
+
<h2>#{title}</h2>
|
620
|
+
<hr>
|
621
|
+
HTML
|
622
|
+
_puts text
|
623
|
+
.end
|
624
|
+
. Now let's invoke it...
|
625
|
+
.chapter 1 Why I Went to the Woods
|
626
|
+
It was the best of times, and you can call me Ishmael. The clocks
|
627
|
+
were striking thirteen.
|
628
|
+
</pre>
|
629
|
+
|
630
|
+
What can we see from this example? First of all, notice that the part
|
631
|
+
between <tt>.def</tt> and <tt>.end</tt> (the body of the method) really is just Ruby
|
632
|
+
code. The method takes no parameters because parameter passing is
|
633
|
+
handled inside the Livetext engine and the instance variable <tt>@_args</tt> is
|
634
|
+
initialized to the contents of this array. We usually refer to the
|
635
|
+
<tt>@_args</tt> array only through the method <tt>_args</tt> which returns it.
|
636
|
+
|
637
|
+
The <tt>_args</tt> method is also an iterator. If a block is attached, that block
|
638
|
+
will be called for every argument.
|
639
|
+
|
640
|
+
We then create a string using these parameters and call it using the
|
641
|
+
<tt>_puts</tt> method. This really does do a <tt>puts</tt> call, but it applies it to
|
642
|
+
wherever the output is currently being sent (defaulting to STDOUT).
|
643
|
+
|
644
|
+
All the "helper" methods start with an underscore so as to avoid name
|
645
|
+
collisions. These are all stored in the <tt>Livetext::Helpers</tt> module
|
646
|
+
(which also has some methods you will never use).
|
647
|
+
|
648
|
+
Here is the HTML output of the previous example:
|
649
|
+
|
650
|
+
<pre>
|
651
|
+
<h3>Chapter 1</h3>
|
652
|
+
<h2>Why I Went to the Woods</h2>
|
653
|
+
<hr>
|
654
|
+
It was the best of times, and you can call me Ishmael. The clocks
|
655
|
+
were striking thirteen.
|
656
|
+
</pre>
|
657
|
+
|
658
|
+
What are some other helper methods? Here's a list.
|
659
|
+
|
660
|
+
<table>
|
661
|
+
<tr>
|
662
|
+
<td width=3%><td width=10%><tt>_args</tt> </td><td> Returns an array of arguments for the method (or an enumerator for that array)
|
663
|
+
</td>
|
664
|
+
</tr>
|
665
|
+
<tr>
|
666
|
+
<td width=3%><td width=10%><tt>_data</tt> </td><td> A single "unsplit" string of all arguments in raw form
|
667
|
+
</td>
|
668
|
+
</tr>
|
669
|
+
<tr>
|
670
|
+
<td width=3%><td width=10%><tt>_body</tt> </td><td> Returns a string (or enumerator) giving access to the text block (preceding <tt>.end</tt>)
|
671
|
+
</td>
|
672
|
+
</tr>
|
673
|
+
<tr>
|
674
|
+
<td width=3%><td width=10%><tt>_puts</tt> </td><td> Write a line to output (STDOUT or wherever)
|
675
|
+
</td>
|
676
|
+
</tr>
|
677
|
+
<tr>
|
678
|
+
<td width=3%><td width=10%><tt>_print</tt> </td><td> Write a line to output (STDOUT or wherever) without a newline
|
679
|
+
</td>
|
680
|
+
</tr>
|
681
|
+
<tr>
|
682
|
+
<td width=3%><td width=10%><tt>_formatting</tt> </td><td> A function transforming boldface, italics, and monospace (Livetext conventions)
|
683
|
+
</td>
|
684
|
+
</tr>
|
685
|
+
<tr>
|
686
|
+
<td width=3%><td width=10%><tt>_var_substitution</tt> </td><td> Substitute variables into a string
|
687
|
+
</td>
|
688
|
+
</tr>
|
689
|
+
<tr>
|
690
|
+
<td width=3%><td width=10%><tt>_passthru</tt> </td><td> Feed a line directly into output after transforming and substituting
|
691
|
+
</td>
|
692
|
+
</tr>
|
693
|
+
</table>
|
694
|
+
|
695
|
+
Note that the last three methods are typically <i>not</i> called in your own code. They could be,
|
696
|
+
but it remains to be seen whether something that advanced is useful.
|
697
|
+
|
698
|
+
<br><br><b><font size=+1>More examples</font></b><br>
|
699
|
+
|
700
|
+
Suppose you wanted to take a list of words, more than one per line, and alphabetize them.
|
701
|
+
Let's write a method called <tt>alpha</tt> for that. This exercise and the next one are implemented
|
702
|
+
in the test suite.
|
703
|
+
|
704
|
+
|
705
|
+
<b>Test: <tt>013\_example\_alpha</tt></b><br>
|
706
|
+
<center>
|
707
|
+
<table width=80% cellpadding=4>
|
708
|
+
<tr>
|
709
|
+
<td width=50%><b>Input</b></td>
|
710
|
+
<td width=50%><b>Output</b></td>
|
711
|
+
</tr>
|
712
|
+
<tr>
|
713
|
+
<td width=50% bgcolor=#fec0fe valign=top>
|
714
|
+
<pre> .def alpha
|
715
|
+
text = \_body.join
|
716
|
+
text.gsub!(/\n/, " ")
|
717
|
+
words = text.split.sort
|
718
|
+
words.each {|w| \_puts " #{w}" }
|
719
|
+
.end
|
720
|
+
Here is an alphabetized list:
|
721
|
+
|
722
|
+
.alpha
|
723
|
+
fishmonger anarchist aardvark glyph gryphon
|
724
|
+
halcyon zymurgy mataeotechny zootrope
|
725
|
+
pareidolia manicotti quark bellicose anamorphic
|
726
|
+
cytology fusillade ectomorph
|
727
|
+
.end
|
728
|
+
|
729
|
+
I hope that worked.
|
730
|
+
</pre>
|
731
|
+
</td>
|
732
|
+
<td width=50% bgcolor=lightgray valign=top>
|
733
|
+
<pre> Here is an alphabetized list:
|
734
|
+
|
735
|
+
aardvark
|
736
|
+
anamorphic
|
737
|
+
anarchist
|
738
|
+
bellicose
|
739
|
+
cytology
|
740
|
+
ectomorph
|
741
|
+
fishmonger
|
742
|
+
fusillade
|
743
|
+
glyph
|
744
|
+
gryphon
|
745
|
+
halcyon
|
746
|
+
manicotti
|
747
|
+
mataeotechny
|
748
|
+
pareidolia
|
749
|
+
quark
|
750
|
+
zootrope
|
751
|
+
zymurgy
|
752
|
+
|
753
|
+
I hope that worked.
|
754
|
+
</pre>
|
755
|
+
</td>
|
756
|
+
</tr>
|
757
|
+
</table>
|
758
|
+
</center>
|
759
|
+
|
760
|
+
I'll let that code stand on its own. Now suppose you wanted to allow columnar output. Let's
|
761
|
+
have the user specify a number of columns (from 1 to 5, defaulting to 1).
|
762
|
+
|
763
|
+
|
764
|
+
<b>Test: <tt>014\_example\_alpha2</tt></b><br>
|
765
|
+
<center>
|
766
|
+
<table width=80% cellpadding=4>
|
767
|
+
<tr>
|
768
|
+
<td width=50%><b>Input</b></td>
|
769
|
+
<td width=50%><b>Output</b></td>
|
770
|
+
</tr>
|
771
|
+
<tr>
|
772
|
+
<td width=50% bgcolor=#fec0fe valign=top>
|
773
|
+
<pre> .def alpha
|
774
|
+
cols = \_args.first
|
775
|
+
cols = "1" if cols == ""
|
776
|
+
cols = cols.to\_i
|
777
|
+
raise "Columns must be 1-5" unless cols.between?(1,5)
|
778
|
+
text = \_body.join
|
779
|
+
text.gsub!(/\n/, " ")
|
780
|
+
words = text.split.sort
|
781
|
+
words.each\_slice(cols) do |row|
|
782
|
+
row.each {|w| \_print '%-15s' % w }
|
783
|
+
\_puts
|
784
|
+
end
|
785
|
+
.end
|
786
|
+
Here is an alphabetized list:
|
787
|
+
|
788
|
+
.alpha 3
|
789
|
+
fishmonger anarchist aardvark glyph gryphon
|
790
|
+
halcyon zymurgy mataeotechny zootrope
|
791
|
+
pareidolia manicotti quark bellicose anamorphic
|
792
|
+
cytology fusillade ectomorph
|
793
|
+
.end
|
794
|
+
|
795
|
+
I hope that worked a second time.
|
796
|
+
</pre>
|
797
|
+
</td>
|
798
|
+
<td width=50% bgcolor=lightgray valign=top>
|
799
|
+
<pre> Here is an alphabetized list:
|
800
|
+
|
801
|
+
aardvark anamorphic anarchist
|
802
|
+
bellicose cytology ectomorph
|
803
|
+
fishmonger fusillade glyph
|
804
|
+
gryphon halcyon manicotti
|
805
|
+
mataeotechny pareidolia quark
|
806
|
+
zootrope zymurgy
|
807
|
+
|
808
|
+
I hope that worked a second time.
|
809
|
+
</pre>
|
810
|
+
</td>
|
811
|
+
</tr>
|
812
|
+
</table>
|
813
|
+
</center>
|
814
|
+
|
815
|
+
What if we wanted to store the code outside the text file? There is more than one way to
|
816
|
+
do this.
|
817
|
+
|
818
|
+
Let's assume we have a file called <tt>mylib.rb</tt> in the same directory as the file we're processing.
|
819
|
+
(Issues such as paths and security have not been addressed yet.) We'll stick the actual Ruby code
|
820
|
+
in here (and nothing else).
|
821
|
+
|
822
|
+
<pre>
|
823
|
+
# File: mylib.rb
|
824
|
+
|
825
|
+
def alpha
|
826
|
+
cols = _args.first
|
827
|
+
cols = "1" if cols == ""
|
828
|
+
cols = cols.to_i
|
829
|
+
raise "Columns must be 1-5" unless cols.between?(1,5)
|
830
|
+
text = _body.join
|
831
|
+
text.gsub!(/\n/, " ")
|
832
|
+
words = text.split.sort
|
833
|
+
words.each_slice(cols) do |row|
|
834
|
+
row.each {|w| _print '%-15s' % w }
|
835
|
+
_puts
|
836
|
+
end
|
837
|
+
end
|
838
|
+
</pre>
|
839
|
+
|
840
|
+
Now the <tt>.lt</tt> file can be written this way:
|
841
|
+
|
842
|
+
<pre>
|
843
|
+
.mixin mylib
|
844
|
+
Here is an alphabetized list:
|
845
|
+
|
846
|
+
.alpha 3
|
847
|
+
fishmonger anarchist aardvark glyph gryphon
|
848
|
+
halcyon zymurgy mataeotechny zootrope
|
849
|
+
pareidolia manicotti quark bellicose anamorphic
|
850
|
+
cytology fusillade ectomorph
|
851
|
+
.end
|
852
|
+
|
853
|
+
I hope that worked a second time.
|
854
|
+
</pre>
|
855
|
+
|
856
|
+
The output, of course, is the same.
|
857
|
+
|
858
|
+
There is an important feature that has not yet been implemented (the
|
859
|
+
<tt>require</tt> method). Like Ruby's <tt>require</tt>, it will grab Ruby code and
|
860
|
+
load it; however, unlike <tt>mixin</tt>, it will load it into a customized
|
861
|
+
object and associate a new sigil with it. So for example, the command
|
862
|
+
<tt>.foobar</tt> would refer to a method in the <tt>Livetext::Standard</tt> class
|
863
|
+
(whether predefined or user-defined). If we did a <tt>require</tt> on a file
|
864
|
+
and associated the sigil <tt>#</tt> with it, then <tt>#foobar</tt> would be a method
|
865
|
+
on that new custom object. I will implement this soon.
|
866
|
+
|
867
|
+
<br><br><b><font size=+1>Issues, open questions, and to-do items</font></b><br>
|
868
|
+
|
869
|
+
This list is not prioritized yet.
|
870
|
+
|
871
|
+
<ol>
|
872
|
+
<li>Add versioning information
|
873
|
+
</li>
|
874
|
+
<li>Clean up code structure
|
875
|
+
</li>
|
876
|
+
<li>Add RDoc
|
877
|
+
</li>
|
878
|
+
<li>Think about command line executable
|
879
|
+
</li>
|
880
|
+
<li>Write as pure library in addition to executable
|
881
|
+
</li>
|
882
|
+
<li>Package as gem
|
883
|
+
</li>
|
884
|
+
<li>Document: <tt>require</tt> `include <tt>copy</tt> `mixin <tt>errout</tt> and others
|
885
|
+
</li>
|
886
|
+
<li>Need much better error checking and corresponding tests
|
887
|
+
</li>
|
888
|
+
<li>Worry about nesting of elements (probably mostly disallow)
|
889
|
+
</li>
|
890
|
+
<li>Think about UTF-8
|
891
|
+
</li>
|
892
|
+
<li>Document API fully
|
893
|
+
</li>
|
894
|
+
<li>Add <tt>_raw_args</tt> and let <tt>_args</tt> honor quotes
|
895
|
+
</li>
|
896
|
+
<li>Support quotes in <tt>.set</tt> values
|
897
|
+
</li>
|
898
|
+
<li>Support "namespaced" variables (`(.set code.font="whatever"))
|
899
|
+
</li>
|
900
|
+
<li>Support functions (`($$func)) including namespacing
|
901
|
+
</li>
|
902
|
+
<li>Create predefined variables and functions (e.g., <tt>$_source_file</tt>, <tt>$(_line),</tt> <tt>$$_today</tt>)
|
903
|
+
</li>
|
904
|
+
<li>Support markdown-style bold/italics? (`_markdown replaces <tt>_formatting</tt> method)
|
905
|
+
</li>
|
906
|
+
<li>Allow turning on/off: formatting, variable interpolation, function interpolation?
|
907
|
+
</li>
|
908
|
+
<li><tt>.require</tt> with file and sigil parameters
|
909
|
+
</li>
|
910
|
+
<li>Comments passed through (e.g. as HTML comments)
|
911
|
+
</li>
|
912
|
+
<li><tt>.run</tt> to execute arbitrary Ruby code inline?
|
913
|
+
</li>
|
914
|
+
<li>Concept of <tt>.proc</tt> (guaranteed to return no value, produce no output)?
|
915
|
+
</li>
|
916
|
+
<li>Exceptions??
|
917
|
+
</li>
|
918
|
+
<li>Ruby <tt>$SAFE</tt> levels?
|
919
|
+
</li>
|
920
|
+
<li>Warn when overriding existing names?
|
921
|
+
</li>
|
922
|
+
<li>Think about passing data in (erb replacement)
|
923
|
+
</li>
|
924
|
+
<li>Allow custom ending tag on <tt>raw</tt> method
|
925
|
+
</li>
|
926
|
+
<li>Ignore first blank line after <tt>.end</tt>? (and after raw-tag?)
|
927
|
+
</li>
|
928
|
+
<li>Allow/encourage custom <tt>passthru</tt> method?
|
929
|
+
</li>
|
930
|
+
<li>Must have sane support for CSS
|
931
|
+
</li>
|
932
|
+
<li>Support for Pygments and/or other code processors
|
933
|
+
</li>
|
934
|
+
<li>Support for gists? arbitrary links? other remote resouces?
|
935
|
+
</li>
|
936
|
+
<li>Small libraries for special purposes (books? special Softcover support? blogs? PDF? RMagick?)
|
937
|
+
</li>
|
938
|
+
<li>Experiment with idea of special libraries having pluggable output formats (via Ruby mixin?)
|
939
|
+
</li>
|
940
|
+
<li>Imagining a lib that can run/test code fragments as part of document generation
|
941
|
+
</li>
|
942
|
+
<li>Create vim (emacs?) syntax files
|
943
|
+
</li>
|
944
|
+
<li>Someday: Support other languages (Elixir, Python, ...)
|
945
|
+
</li>
|
946
|
+
<li><tt>.pry</tt> method?
|
947
|
+
</li>
|
948
|
+
<li><tt>.irb</tt> method?
|
949
|
+
</li>
|
950
|
+
<li>Other debugging features
|
951
|
+
</li>
|
952
|
+
<li>Feature to "break" to EOF?
|
953
|
+
</li>
|
954
|
+
<li><tt>.meth?</tt> method ending in <tt>?</tt> takes a block that may be processed or thrown away (`(.else) perhaps?)
|
955
|
+
</li>
|
956
|
+
<li><tt>.dump</tt> to dump all variables and their values
|
957
|
+
</li>
|
958
|
+
<li><tt>.if</tt> and <tt>.else</tt>?
|
959
|
+
</li>
|
960
|
+
<li>Make any/all delimiters configurable
|
961
|
+
</li>
|
962
|
+
<li>HTML helper? (in their own library?)
|
963
|
+
</li>
|
964
|
+
</ol>
|
965
|
+
|