folio 0.3.0 → 0.4.0

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.
@@ -0,0 +1,129 @@
1
+ <?xml version="1.0"?>
2
+ <log>
3
+ <entry>
4
+ <date>Tue Sep 16 13:18:40 -0400 2008</date>
5
+ <author> trans <transfire@gmail.com></author>
6
+ <revison>77b1389e5bccf8b5052152a8d75cc0c00b1d1b52</revison>
7
+ <type></type>
8
+ <message>added more spec fictures</message>
9
+ </entry>
10
+ <entry>
11
+ <date>Tue Sep 16 13:18:06 -0400 2008</date>
12
+ <author> trans <transfire@gmail.com></author>
13
+ <revison>8a2eb973587d99ef4978191eececf6d0f588b90a</revison>
14
+ <type></type>
15
+ <message>improved error messages</message>
16
+ </entry>
17
+ <entry>
18
+ <date>Tue Sep 16 13:16:36 -0400 2008</date>
19
+ <author> trans <transfire@gmail.com></author>
20
+ <revison>7e0c67bf84574d0343ce78330959f5bf5335247f</revison>
21
+ <type></type>
22
+ <message>added LinkNotFound error</message>
23
+ </entry>
24
+ <entry>
25
+ <date>Tue Sep 16 13:16:03 -0400 2008</date>
26
+ <author> trans <transfire@gmail.com></author>
27
+ <revison>8b72d67261db24f2b40597c34827a35441d76c30</revison>
28
+ <type></type>
29
+ <message>remarked out Folio shortcut #[] method for time being</message>
30
+ </entry>
31
+ <entry>
32
+ <date>Tue Sep 16 11:53:43 -0400 2008</date>
33
+ <author> trans <transfire@gmail.com></author>
34
+ <revison>b1ed5ded2ec3798397461004186bb7b59b9d1ef9</revison>
35
+ <type></type>
36
+ <message>added spec for link.rb</message>
37
+ </entry>
38
+ <entry>
39
+ <date>Tue Sep 16 11:42:22 -0400 2008</date>
40
+ <author> trans <transfire@gmail.com></author>
41
+ <revison>5d2f4d23c060c92d5e7e843079379f43e4d881e0</revison>
42
+ <type></type>
43
+ <message>removed relpath</message>
44
+ </entry>
45
+ <entry>
46
+ <date>Tue Sep 16 11:41:04 -0400 2008</date>
47
+ <author> trans <transfire@gmail.com></author>
48
+ <revison>b9a38c5a8370aa7e4cf57bba80bdafbc39cdb674</revison>
49
+ <type></type>
50
+ <message>renamed spec_prompt.rb to spec_shell.rb</message>
51
+ </entry>
52
+ <entry>
53
+ <date>Tue Sep 16 11:30:40 -0400 2008</date>
54
+ <author> trans <transfire@gmail.com></author>
55
+ <revison>da2eb57bccd4400e0b272836ad9cf23ce23d6b19</revison>
56
+ <type>major</type>
57
+ <message>Renamed Prompt to Shell. </message>
58
+ </entry>
59
+ <entry>
60
+ <date>Thu Sep 11 12:50:59 -0400 2008</date>
61
+ <author> trans <transfire@gmail.com></author>
62
+ <revison>e8dadfff85bbf3dc5cf8cced5be17b0789b04650</revison>
63
+ <type></type>
64
+ <message>moved test directory to spec directory</message>
65
+ </entry>
66
+ <entry>
67
+ <date>Thu Sep 11 12:44:48 -0400 2008</date>
68
+ <author> trans <transfire@gmail.com></author>
69
+ <revison>94d3c4989d012173606ddbc37ddf0a8bc702b661</revison>
70
+ <type></type>
71
+ <message>turned tests into specs</message>
72
+ </entry>
73
+ <entry>
74
+ <date>Thu Sep 11 12:44:07 -0400 2008</date>
75
+ <author> trans <transfire@gmail.com></author>
76
+ <revison>2454fe9d762aee096db7143dacc398582269690e</revison>
77
+ <type></type>
78
+ <message>fixed tests by adding #== to FileObject class</message>
79
+ </entry>
80
+ <entry>
81
+ <date>Wed Sep 10 16:30:28 -0400 2008</date>
82
+ <author> trans <transfire@gmail.com></author>
83
+ <revison>c07c7bd87c0109db8019cac1be89b217855397b5</revison>
84
+ <type></type>
85
+ <message>custom rdoc-template</message>
86
+ </entry>
87
+ <entry>
88
+ <date>Wed Sep 10 15:10:48 -0400 2008</date>
89
+ <author> trans <transfire@gmail.com></author>
90
+ <revison>b4cb8082c81719d5fa0788f0566fe28656f1533d</revison>
91
+ <type></type>
92
+ <message>added TODO and VERSION files</message>
93
+ </entry>
94
+ <entry>
95
+ <date>Wed Sep 10 15:06:56 -0400 2008</date>
96
+ <author> trans <transfire@gmail.com></author>
97
+ <revison>9a926a12a0b061c3ec9bfbd23f5387e65c1e7201</revison>
98
+ <type>major</type>
99
+ <message>Added XDG methods to Prompt class. </message>
100
+ </entry>
101
+ <entry>
102
+ <date>Wed Sep 10 14:16:35 -0400 2008</date>
103
+ <author> trans <transfire@gmail.com></author>
104
+ <revison>474f3f77720a102e47bcd699ae5700b7a40e741b</revison>
105
+ <type></type>
106
+ <message>moved METADATA to meta/</message>
107
+ </entry>
108
+ <entry>
109
+ <date>Sat Sep 06 12:59:40 -0400 2008</date>
110
+ <author> trans <transfire@gmail.com></author>
111
+ <revison>9714d9df4d409a4013acb6530ea3e3ce7b53acb5</revison>
112
+ <type></type>
113
+ <message>added .gitignore file</message>
114
+ </entry>
115
+ <entry>
116
+ <date>Sat Sep 06 12:58:25 -0400 2008</date>
117
+ <author> trans <transfire@gmail.com></author>
118
+ <revison>168a1faaf6148677bfdeec36793d4d141cf2a6d8</revison>
119
+ <type></type>
120
+ <message>reorganized project for reap changes</message>
121
+ </entry>
122
+ <entry>
123
+ <date>Thu Sep 04 17:03:44 -0400 2008</date>
124
+ <author> trans <transfire@gmail.com></author>
125
+ <revison>20c00238d1401c2b4385f0a6109c2c001b922008</revison>
126
+ <type>major</type>
127
+ <message>Started Repository. </message>
128
+ </entry>
129
+ </log>
@@ -0,0 +1,33 @@
1
+ <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
2
+
3
+ <xsl:output cdata-section-elements="script"/>
4
+
5
+ <xsl:template match="/">
6
+ <html>
7
+ <head>
8
+ <title>Changelog</title>
9
+ <link REL='SHORTCUT ICON' HREF="../img/ruby-sm.png" />
10
+ <style>
11
+ td { font-family: sans-serif; padding: 0px 10px; }
12
+ </style>
13
+ </head>
14
+ <body>
15
+ <div class="container">
16
+ <h1>Changelog</h1>
17
+ <table style="width: 100%;">
18
+ <xsl:apply-templates />
19
+ </table>
20
+ </div>
21
+ </body>
22
+ </html>
23
+ </xsl:template>
24
+
25
+ <xsl:template match="entry">
26
+ <tr>
27
+ <td><b><pre><xsl:value-of select="msg"/></pre></b></td>
28
+ <td><xsl:value-of select="author"/></td>
29
+ <td><xsl:value-of select="date"/></td>
30
+ </tr>
31
+ </xsl:template>
32
+
33
+ </xsl:stylesheet>
@@ -0,0 +1,35 @@
1
+ <notes>
2
+ <set label="FIXME">
3
+ <file src="lib/folio/minitar.rb">
4
+ <note line="421" type="FIXME">FIXME: what if an exception is raised in the block?</note>
5
+ <note line="458" type="FIXME">FIXME: what if an exception is raised in the block?</note>
6
+ </file>
7
+ </set>
8
+ <set label="TODO">
9
+ <file src="lib/folio/fileutils.rb">
10
+ <note line="10" type="TODO">TODO: Rename to linkstage or something less likely to name clash?</note>
11
+ <note line="22" type="TODO">TODO: dryrun test here or before folder creation?</note>
12
+ </file>
13
+ <file src="lib/folio/filetest.rb">
14
+ <note line="33" type="TODO">TODO: Make more robust. Probably needs to be fixed for Windows.</note>
15
+ <note line="52" type="TODO">TODO: Make more robust.</note>
16
+ </file>
17
+ <file src="lib/folio/fileobject.rb">
18
+ <note line="204" type="TODO">TODO: I don&apos;t like the name of this.</note>
19
+ </file>
20
+ <file src="lib/folio/document.rb">
21
+ <note line="40" type="TODO">TODO: how to handle unkinking (b/c file no longer exists)</note>
22
+ </file>
23
+ <file src="lib/folio/ziputils.rb">
24
+ <note line="7" type="TODO">TODO: Much of this shells out. It would be best to internalize.</note>
25
+ <note line="29" type="TODO">TODO: support gzip and bzip2 as well.</note>
26
+ <note line="141" type="TODO">TODO: Write unified untar_gzip function.</note>
27
+ </file>
28
+ <file src="lib/folio/shell.rb">
29
+ <note line="66" type="TODO">TODO: Should there be methods like this for each
30
+ type, and raise an error if not the right type?</note>
31
+ <note line="131" type="TODO">TODO: Ultimately merge #glob and #multiglob.</note>
32
+ <note line="196" type="TODO">TODO: Is #out_of_date? this the same as #uptodate?</note>
33
+ </file>
34
+ </set>
35
+ </notes>
@@ -7,5 +7,5 @@ This is the third release since the initial idea.
7
7
  Techincally this is still "alpha" code as it needs
8
8
  many more tests. Nontheless, the library is a rather
9
9
  strightforward wrapper around Ruby internals, so it
10
- already fairly usable.
10
+ is already very usable.
11
11
 
@@ -0,0 +1,552 @@
1
+ <html>
2
+ <head>
3
+ <title>Specifications</title>
4
+
5
+ <style>
6
+ #container{ margin: 0 auto; width: 800px; }
7
+ /* Debug borders */
8
+ p, li, dt, dd, div, pre, h1, h2, h3, h4, h5, h6 {
9
+ /*
10
+ border: 1px solid red;
11
+ */
12
+ }
13
+ body { font-size: 0.9em; margin: 1em 5% 1em 5%; }
14
+ a { color: blue; text-decoration: underline; }
15
+ a:visited { color: fuchsia; }
16
+ em { font-style: italic; }
17
+ strong { font-weight: bold; }
18
+ tt { color: navy; }
19
+ h1, h2, h3, h4, h5, h6 {
20
+ color: #527bbd;
21
+ font-family: sans-serif;
22
+ margin-top: 1.2em;
23
+ margin-bottom: 0.5em;
24
+ line-height: 1.3;
25
+ }
26
+ h1 { border-bottom: 2px solid silver; }
27
+ h2 { border-bottom: 2px solid silver; padding-top: 0.5em; }
28
+ hr { border: 1px solid silver; }
29
+ p { color: #555;
30
+ text-align: justify;
31
+ margin-top: 0.5em;
32
+ margin-bottom: 0.5em;
33
+ line-height: 1.4em;
34
+ }
35
+ pre { padding: 10; margin: 0; }
36
+
37
+ span#author {
38
+ color: #527bbd;
39
+ font-family: sans-serif;
40
+ font-weight: bold;
41
+ font-size: 1.1em;
42
+ }
43
+ span#email {
44
+ }
45
+ span#revision {
46
+ font-family: sans-serif;
47
+ }
48
+
49
+ div#footer {
50
+ font-family: sans-serif;
51
+ font-size: small;
52
+ border-top: 2px solid silver;
53
+ padding-top: 0.5em;
54
+ margin-top: 4.0em;
55
+ }
56
+
57
+ div#footer-text {
58
+ float: left;
59
+ padding-bottom: 0.5em;
60
+ }
61
+
62
+ div#footer-badges {
63
+ float: right;
64
+ padding-bottom: 0.5em;
65
+ }
66
+
67
+ div.content { /* Block element content. */
68
+ padding: 0;
69
+ }
70
+
71
+ /* Block element titles. */
72
+ h1.title {
73
+ font-family: sans-serif;
74
+ font-weight: bold;
75
+ text-align: left;
76
+ font-size: 3em;
77
+ margin-top: 1.0em;
78
+ margin-bottom: 0.5em;
79
+ }
80
+
81
+ /* Block element titles. */
82
+ div.title, caption.title {
83
+ font-family: sans-serif;
84
+ font-weight: bold;
85
+ text-align: left;
86
+ margin-top: 1.0em;
87
+ margin-bottom: 0.5em;
88
+ }
89
+ div.title + * {
90
+ margin-top: 0;
91
+ }
92
+
93
+ td div.title:first-child {
94
+ margin-top: 0.0em;
95
+ }
96
+ div.content div.title:first-child {
97
+ margin-top: 0.0em;
98
+ }
99
+ div.content + div.title {
100
+ margin-top: 0.0em;
101
+ }
102
+
103
+ div.sidebarblock > div.content {
104
+ background: #ffffee;
105
+ border: 1px solid silver;
106
+ padding: 0.5em;
107
+ }
108
+
109
+ img { border-style: none; }
110
+
111
+ dl { margin-top: 0.8em; margin-bottom: 0.8em; }
112
+ dt { margin-top: 0.5em; margin-bottom: 0; font-style: italic; }
113
+ dd > *:first-child { margin-top: 0; }
114
+ ul, ol { list-style-position: outside; }
115
+
116
+ thead { font-family: sans-serif; font-weight: bold; }
117
+ tfoot { font-weight: bold; }
118
+ </style>
119
+
120
+ <!-- JQuery is needed -->
121
+ <script src="../assets/scripts/jquery.js" type="text/javascript" language="javascript"></script>
122
+
123
+
124
+
125
+ <link href="../assets/styles/spec.css" type="text/css" rel="stylesheet">
126
+ </head>
127
+
128
+ <body>
129
+
130
+ <!-- Side Table of Contents -->
131
+ <div id="sidebar" style="position: fixed; top: 10; right: 10; background: white;">
132
+ <a href="javascript: toc_toggle();">
133
+ <img src="img/icon/book.jpg" height="30px;" style="border: none;" alt="TOC" align="right"/>
134
+ </a>
135
+
136
+ <div id="toc_side" class="toc">
137
+ </div>
138
+ </div>
139
+
140
+ <div id="container">
141
+ <div id="header">
142
+ <img src="img/icon/book.jpg" align="left" style="padding-right: 10px;" alt=""/>
143
+
144
+ <h1 class="title">Specifications</h1>
145
+
146
+ <h1>Table of Contents</h1>
147
+
148
+ <div class="toc">
149
+ </div>
150
+ </div>
151
+
152
+ <div id="content">
153
+ <h1>Document Unit Testing</h1>
154
+ <p>
155
+ Load the Folio library.
156
+ </p>
157
+ <pre>
158
+ require 'folio'
159
+ </pre>
160
+ <p>
161
+ Instantiate document object.
162
+ </p>
163
+ <pre>
164
+ @foo = Folio.file('fixtures/foo.txt')
165
+ </pre>
166
+ <p>
167
+ Confirm it is a a document.
168
+ </p>
169
+ <pre>
170
+ @foo.assert.document?
171
+ </pre>
172
+ <p>
173
+ Confirm it is equal to another document initialized identically.
174
+ </p>
175
+ <pre>
176
+ @foo.assert == Folio.file('fixtures/foo.txt')
177
+ </pre>
178
+ <p>
179
+ Confirm it is equal to the same file initialized from a different working
180
+ directory.
181
+ </p>
182
+ <pre>
183
+ f = nil
184
+ Dir.chdir('fixtures') do
185
+ f = Folio.file('foo.txt')
186
+ end
187
+ @foo.assert == f
188
+ </pre>
189
+ <p>
190
+ Document can be read.
191
+ </p>
192
+ <pre>
193
+ @foo.read.assert == &quot;THIS IS FOO!\n&quot;
194
+ </pre>
195
+ <p>
196
+ The #readlines methods read the document into an array of lines.
197
+ </p>
198
+ <pre>
199
+ @foo.readlines.assert == [&quot;THIS IS FOO!\n&quot;]
200
+ </pre>
201
+ <p>
202
+ We can also open the document for reading using the more traditional open()
203
+ method.
204
+ </p>
205
+ <pre>
206
+ t = nil
207
+ @foo.open('r'){ |f| t = f.read }
208
+ t.assert == &quot;THIS IS FOO!\n&quot;
209
+ </pre>
210
+ <p>
211
+ The #parent method return the Directory object in which the document is
212
+ contained.
213
+ </p>
214
+ <pre>
215
+ @foo.parent.assert == Folio.file('fixtures')
216
+ </pre>
217
+ <p>
218
+ A document can be written to as well using the #write method.
219
+ </p>
220
+ <pre>
221
+ out = Folio.doc('fixtures/out.txt')
222
+ out.write('Hello')
223
+ File.read(out.to_s).assert == 'Hello'
224
+ </pre>
225
+
226
+
227
+
228
+
229
+
230
+ <h1>General Usage of Folio Link Object</h1>
231
+ <p>
232
+ Require the Folio library.
233
+ </p>
234
+ <pre>
235
+ require 'folio'
236
+ </pre>
237
+ <p>
238
+ Instantiate a soft link.
239
+ </p>
240
+ <pre>
241
+ @foo = Folio.file('fixtures/foo_softlink.txt')
242
+ </pre>
243
+ <p>
244
+ It is a link.
245
+ </p>
246
+ <pre>
247
+ @foo.link?.assert == true
248
+ </pre>
249
+ <p>
250
+ It is equal to a link defined identically.
251
+ </p>
252
+ <pre>
253
+ @foo.assert == Folio.file('fixtures/foo_softlink.txt')
254
+ </pre>
255
+ <p>
256
+ The link is not equal to the target document.
257
+ </p>
258
+ <pre>
259
+ @foo.assert! == Folio.file('fixtures/foo.txt')
260
+ </pre>
261
+ <p>
262
+ But it is equal to a same link instantiated from a differnt working
263
+ directory.
264
+ </p>
265
+ <pre>
266
+ f = nil
267
+ Dir.chdir('fixtures') do
268
+ f = Folio.file('foo_softlink.txt')
269
+ end
270
+ @foo.assert == f
271
+ </pre>
272
+ <p>
273
+ Reads the linked document correctly.
274
+ </p>
275
+ <pre>
276
+ @foo.read == &quot;THIS IS FOO!&quot;
277
+ </pre>
278
+ <p>
279
+ Opens the linked document for reading.
280
+ </p>
281
+ <pre>
282
+ t = nil
283
+ @foo.open('r'){ |f| t = f.read }
284
+ t.assert == &quot;THIS IS FOO!\n&quot;
285
+ </pre>
286
+ <p>
287
+ It provides the parent directory object.
288
+ </p>
289
+ <pre>
290
+ @foo.parent.assert == Folio.dir('fixtures')
291
+ </pre>
292
+
293
+
294
+
295
+
296
+ <h1>General Usage of the Folio Shell</h1>
297
+ <p>
298
+ Require the Folio library.
299
+ </p>
300
+ <pre>
301
+ require 'folio'
302
+ </pre>
303
+ <p>
304
+ Open a new Folio::Shell object.
305
+ </p>
306
+ <pre>
307
+ @c = Folio.shell('fixtures')
308
+ </pre>
309
+ <p>
310
+ Method #work returns current working directory.
311
+ </p>
312
+ <pre>
313
+ @c.work.assert == Folio.dir('fixtures')
314
+ </pre>
315
+ <p>
316
+ Method #to_s returns current working dirname.
317
+ </p>
318
+ <pre>
319
+ @c.to_s.assert == File.join(Dir.pwd, 'fixtures')
320
+ </pre>
321
+ <p>
322
+ Method #entries returns a list of names of the current directory content.
323
+ </p>
324
+ <pre>
325
+ @c.entries.sort.assert == ['foo.txt', 'foo_softlink.txt', 'out.txt']
326
+ </pre>
327
+ <p>
328
+ Method #files returns an array of file objects in the current directory.
329
+ </p>
330
+ <pre>
331
+ f = @c.files.to_a
332
+ f.size.assert == 3
333
+ f.assert.include?(Folio.file('fixtures/foo_softlink.txt'))
334
+ f.assert.include?(Folio.file('fixtures/foo.txt'))
335
+ </pre>
336
+
337
+ <h1>Problem Scenerios</h1>
338
+ <h2>Non-existant paths</h2>
339
+ <p>
340
+ If a path does not exist, how do we know if it is intended to be a file, or
341
+ directory, or what?
342
+ </p>
343
+ <pre>
344
+ d1 = dir('home/trans')
345
+ d2 = d1 / 'images'
346
+ </pre>
347
+ <p>
348
+ Optons for resolution include:
349
+ </p>
350
+ <ul>
351
+ <li>Do not support ambiguitous methods.
352
+
353
+ </li>
354
+ <li>Raise an error if non-existant.
355
+
356
+ </li>
357
+ <li>Default to a directory when ambiguious.
358
+
359
+ </li>
360
+ <li>Use a delegator.
361
+
362
+ </li>
363
+ </ul>
364
+ <p>
365
+ The first solution is the most straightforward. The second is reasonably
366
+ viable as well, but at least it provides some understanble use for such
367
+ methods.
368
+ </p>
369
+ <p>
370
+ The return value of the third feels to quirky. And the last is a complex
371
+ solution that effectively only leaves us with some sort of non-disk
372
+ Pathname object; a solution almost a quirky.
373
+ </p>
374
+ <h2>Removal of file-io object</h2>
375
+ <p>
376
+ If we delete a file object, then the object looses it&#8217;s reference.
377
+ This is especially problematic if we do not allow file objects to have
378
+ non-existant paths.
379
+ </p>
380
+ <pre>
381
+ d2 = d1.dir('images')
382
+ d2.rm_r
383
+ </pre>
384
+ <p>
385
+ Options for resolution:
386
+ </p>
387
+ <ul>
388
+ <li>Do not support removal methods.
389
+
390
+ </li>
391
+ <li>Allow non-existant paths.
392
+
393
+ </li>
394
+ <li>Use delegator.
395
+
396
+ </li>
397
+ </ul>
398
+ <p>
399
+ The first solution would mean using a parent directory object to delete
400
+ anything.
401
+ </p>
402
+ <pre>
403
+ f1 = file('/home/trans/.bashrc')
404
+ f1.rm # not allowed
405
+ f1.parent.rm(f1) # instead
406
+ </pre>
407
+ <p>
408
+ I do not like this option becuase it means a directory object would behave
409
+ substantially differnt from other file objects. That might not be so bad is
410
+ Shell and Directory could be one and the same, but methods like #ctime
411
+ would still clash.
412
+ </p>
413
+ <p>
414
+ The second option is the simplist. The file object simply takes on a
415
+ &quot;virtual&quot; state. This could lead to errors being thrown, but it
416
+ is not unacceptable.
417
+ </p>
418
+ <pre>
419
+ f1 = file('/home/trans/.bashrc')
420
+ f1.rm
421
+ f1.ctime # error
422
+ </pre>
423
+ <p>
424
+ The last solution creates an indirection for all file objects. Removing a
425
+ file would redelegate to a virtual pathname object. This is a more
426
+ complicated solution and is really no better than the previous solutution
427
+ &#8212;MethodMissing would be the error. A delegtor solution is a bit more
428
+ interesting when we consider virtual file objects that can mimic a file
429
+ system. However that could be a rather misleading redelgation.
430
+ </p>
431
+ <h2>Looking at the Lager Picture</h2>
432
+ <p>
433
+ Do we really need these objects? Isn&#8217;t the core idea the Folio Shell?
434
+ For the first issue, what is wrong with:
435
+ </p>
436
+ <pre>
437
+ s1 = shell('home/trans')
438
+ s2 = s1 / 'images'
439
+ </pre>
440
+ <p>
441
+ Which would clearly raise an error if it were not existant.
442
+ </p>
443
+ <p>
444
+ As for the second. While it might not be quite as concise, it fits the
445
+ shell prompt pattern:
446
+ </p>
447
+ <pre>
448
+ s1 = shell('/home/trans')
449
+ s1.rm('.bashrc')
450
+ </pre>
451
+ <p>
452
+ Yea, ok. However, while we could pass around shell objects as a form of
453
+ directory object, this would leave us no way to pass file objects.
454
+ </p>
455
+ <h2>Conclusion</h2>
456
+ <p>
457
+ It is fairly clear that the second solution to the second issue is the
458
+ clearest choice. And that Directory and Shell should in fact stay separate
459
+ objects. The &quot;Larger Picture&quot; should be the general pattern for
460
+ theses cases, however this ought not prevent the use of the file objects as
461
+ well.
462
+ </p>
463
+ <p>
464
+ As for the first issue, the first or second options the better choices. I
465
+ will probably raise the error.
466
+ </p>
467
+
468
+
469
+ </div>
470
+ </div>
471
+
472
+ </body>
473
+
474
+ </html>
475
+
476
+ <script src="../assets/scripts/spec.js" type="text/javascript" language="javascript"></script>
477
+
478
+ <script type="text/javascript" language="javascript">
479
+ /*****************************************************************
480
+ * $.toc()
481
+ * by rebecca murphey
482
+ * rmurphey gmail com
483
+ *
484
+ * This function is called on its own and takes as an argument
485
+ * a list of selectors with which it will build a table of
486
+ * contents.
487
+ *
488
+ * The first selector will make up the top level of the TOC;
489
+ * the second selector will make up the second level of the TOC;
490
+ * etc.
491
+ *
492
+ * This function returns a div containing nested unordered lists;
493
+ * each list item is linked to an anchor tag added before the item
494
+ * on the page.
495
+ *
496
+ * usage: $.toc('h1,h2,h3').prependTo('body');
497
+ ************************************************************************/
498
+ (function($) {
499
+ $.toc = function(tocList) {
500
+ $(tocList).addClass('jquery-toc');
501
+ var tocListArray = tocList.split(',');
502
+ $.each(tocListArray, function(i,v) { tocListArray[i] = $.trim(v); });
503
+ var $elements = $('.jquery-toc');
504
+ $('body').append('<div></div>');
505
+ var $toc = $('body div:last');
506
+ var lastLevel = 1;
507
+ $toc.append('<ul class="jquery-toc-1"></ul>');
508
+ $elements.each(function() {
509
+ var $e = $(this);
510
+ var text = $e.text();
511
+ var anchor = text.replace(/ /g,'-');
512
+ $e.before('<a name="' + anchor + '"></a>');
513
+ var level;
514
+ $.each(tocListArray, function(i,v) {
515
+ if (v.match(' ')) {
516
+ var vArray = v.split(' ');
517
+ var e = vArray[vArray.length - 1];
518
+ } else { e = v; }
519
+ if ($e.is(e)) { level = i+1; }
520
+ });
521
+ var className = 'jquery-toc-' + level;
522
+ var li = '<li><a href="#' + anchor + '">' + text + '</a></li>';
523
+ if (level == lastLevel) {
524
+ $('ul.' + className + ':last',$toc).append(li);
525
+ } else if (level > lastLevel) {
526
+ var parentLevel = level - 1;
527
+ var parentClassName = 'jquery-toc-' + parentLevel;
528
+ $('ul.' + parentClassName + ':last',$toc).
529
+ append('<ul class="' + className + '"></ul>');
530
+ $('ul.' + className + ':last',$toc).append(li);
531
+ } else if (level < lastLevel) {
532
+ $('ul.' + className + ':last',$toc).append(li);
533
+ }
534
+ lastLevel = level;
535
+ });
536
+ var $toc_ul = $('ul.jquery-toc-1',$toc);
537
+ $toc.remove();
538
+ return($toc_ul);
539
+ }
540
+ })(jQuery);
541
+ </script>
542
+
543
+ <script>
544
+ function toc_toggle() {
545
+ $('#toc_side').toggle();
546
+ };
547
+
548
+ $.toc('#content h1,h2,h3,h4').appendTo('.toc');
549
+
550
+ toc_toggle();
551
+ </script>
552
+