ahoward-tagz 5.1.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.
data/gen_readme.rb ADDED
@@ -0,0 +1,34 @@
1
+ #! /usr/bin/env ruby
2
+
3
+ require 'pathname'
4
+
5
+ $VERBOSE=nil
6
+
7
+ def indent s, n = 2
8
+ ws = ' ' * n
9
+ s.gsub %r/^/, ws
10
+ end
11
+
12
+ template = IO::read 'README.tmpl'
13
+
14
+ samples = ''
15
+ prompt = '~ > '
16
+
17
+ Dir['sample*/*'].sort.each do |sample|
18
+ samples << "\n" << " <========< #{ sample } >========>" << "\n\n"
19
+
20
+ cmd = "cat #{ sample }"
21
+ samples << indent(prompt + cmd, 2) << "\n\n"
22
+ samples << indent(`#{ cmd }`, 4) << "\n"
23
+
24
+ cmd = "ruby #{ sample }"
25
+ samples << indent(prompt + cmd, 2) << "\n\n"
26
+
27
+ cmd = "ruby -Ilib #{ sample }"
28
+ samples << indent(`#{ cmd } 2>&1`, 4) << "\n"
29
+ end
30
+
31
+ #samples.gsub! %r/^/, ' '
32
+
33
+ readme = template.gsub %r/^\s*@samples\s*$/, samples
34
+ print readme
data/install.rb ADDED
@@ -0,0 +1,214 @@
1
+ #!/usr/bin/env ruby
2
+ require 'rbconfig'
3
+ require 'find'
4
+ require 'ftools'
5
+ require 'tempfile'
6
+ include Config
7
+
8
+ LIBDIR = "lib"
9
+ LIBDIR_MODE = 0644
10
+
11
+ BINDIR = "bin"
12
+ BINDIR_MODE = 0755
13
+
14
+
15
+ $srcdir = CONFIG["srcdir"]
16
+ $version = CONFIG["MAJOR"]+"."+CONFIG["MINOR"]
17
+ $libdir = File.join(CONFIG["libdir"], "ruby", $version)
18
+ $archdir = File.join($libdir, CONFIG["arch"])
19
+ $site_libdir = $:.find {|x| x =~ /site_ruby$/}
20
+ $bindir = CONFIG["bindir"] || CONFIG['BINDIR']
21
+ $ruby_install_name = CONFIG['ruby_install_name'] || CONFIG['RUBY_INSTALL_NAME'] || 'ruby'
22
+ $ruby_ext = CONFIG['EXEEXT'] || ''
23
+ $ruby = File.join($bindir, ($ruby_install_name + $ruby_ext))
24
+
25
+ if !$site_libdir
26
+ $site_libdir = File.join($libdir, "site_ruby")
27
+ elsif $site_libdir !~ %r/#{Regexp.quote($version)}/
28
+ $site_libdir = File.join($site_libdir, $version)
29
+ end
30
+
31
+ def install_rb(srcdir=nil, destdir=nil, mode=nil, bin=nil)
32
+ #{{{
33
+ path = []
34
+ dir = []
35
+ Find.find(srcdir) do |f|
36
+ next unless FileTest.file?(f)
37
+ next if (f = f[srcdir.length+1..-1]) == nil
38
+ next if (/CVS$/ =~ File.dirname(f))
39
+ next if (/\.svn/ =~ File.dirname(f))
40
+ next if f =~ %r/\.lnk/
41
+ next if f =~ %r/\.svn/
42
+ next if f =~ %r/\.swp/
43
+ next if f =~ %r/\.svn/
44
+ path.push f
45
+ dir |= [File.dirname(f)]
46
+ end
47
+ for f in dir
48
+ next if f == "."
49
+ next if f == "CVS"
50
+ File::makedirs(File.join(destdir, f))
51
+ end
52
+ for f in path
53
+ next if (/\~$/ =~ f)
54
+ next if (/^\./ =~ File.basename(f))
55
+ unless bin
56
+ File::install(File.join(srcdir, f), File.join(destdir, f), mode, true)
57
+ else
58
+ from = File.join(srcdir, f)
59
+ to = File.join(destdir, f)
60
+ shebangify(from) do |sf|
61
+ $deferr.print from, " -> ", File::catname(from, to), "\n"
62
+ $deferr.printf "chmod %04o %s\n", mode, to
63
+ File::install(sf, to, mode, false)
64
+ end
65
+ end
66
+ end
67
+ #}}}
68
+ end
69
+ def shebangify f
70
+ #{{{
71
+ open(f) do |fd|
72
+ buf = fd.read 42
73
+ if buf =~ %r/^\s*#\s*!.*ruby/o
74
+ ftmp = Tempfile::new("#{ $$ }_#{ File::basename(f) }")
75
+ begin
76
+ fd.rewind
77
+ ftmp.puts "#!#{ $ruby }"
78
+ while((buf = fd.read(8192)))
79
+ ftmp.write buf
80
+ end
81
+ ftmp.close
82
+ yield ftmp.path
83
+ ensure
84
+ ftmp.close!
85
+ end
86
+ else
87
+ yield f
88
+ end
89
+ end
90
+ #}}}
91
+ end
92
+ def ARGV.switch
93
+ #{{{
94
+ return nil if self.empty?
95
+ arg = self.shift
96
+ return nil if arg == '--'
97
+ if arg =~ /^-(.)(.*)/
98
+ return arg if $1 == '-'
99
+ raise 'unknown switch "-"' if $2.index('-')
100
+ self.unshift "-#{$2}" if $2.size > 0
101
+ "-#{$1}"
102
+ else
103
+ self.unshift arg
104
+ nil
105
+ end
106
+ #}}}
107
+ end
108
+ def ARGV.req_arg
109
+ #{{{
110
+ self.shift || raise('missing argument')
111
+ #}}}
112
+ end
113
+ def linkify d, linked = []
114
+ #--{{{
115
+ if test ?d, d
116
+ versioned = Dir[ File::join(d, "*-[0-9].[0-9].[0-9].rb") ]
117
+ versioned.each do |v|
118
+ src, dst = v, v.gsub(%r/\-[\d\.]+\.rb$/, '.rb')
119
+ lnk = nil
120
+ begin
121
+ if test ?l, dst
122
+ lnk = "#{ dst }.lnk"
123
+ puts "#{ dst } -> #{ lnk }"
124
+ File::rename dst, lnk
125
+ end
126
+ unless test ?e, dst
127
+ puts "#{ src } -> #{ dst }"
128
+ File::copy src, dst
129
+ linked << dst
130
+ end
131
+ ensure
132
+ if lnk
133
+ at_exit do
134
+ puts "#{ lnk } -> #{ dst }"
135
+ File::rename lnk, dst
136
+ end
137
+ end
138
+ end
139
+ end
140
+ end
141
+ linked
142
+ #--}}}
143
+ end
144
+
145
+
146
+ #
147
+ # main program
148
+ #
149
+
150
+ libdir = $site_libdir
151
+ bindir = $bindir
152
+ no_linkify = false
153
+ linked = nil
154
+ help = false
155
+
156
+ usage = <<-usage
157
+ #{ File::basename $0 }
158
+ -d, --destdir <destdir>
159
+ -l, --libdir <libdir>
160
+ -b, --bindir <bindir>
161
+ -r, --ruby <ruby>
162
+ -n, --no_linkify
163
+ -s, --sudo
164
+ -h, --help
165
+ usage
166
+
167
+ begin
168
+ while switch = ARGV.switch
169
+ case switch
170
+ when '-d', '--destdir'
171
+ libdir = ARGV.req_arg
172
+ when '-l', '--libdir'
173
+ libdir = ARGV.req_arg
174
+ when '-b', '--bindir'
175
+ bindir = ARGV.req_arg
176
+ when '-r', '--ruby'
177
+ $ruby = ARGV.req_arg
178
+ when '-n', '--no_linkify'
179
+ no_linkify = true
180
+ when '-s', '--sudo'
181
+ sudo = 'sudo'
182
+ when '-h', '--help'
183
+ help = true
184
+ else
185
+ raise "unknown switch #{switch.dump}"
186
+ end
187
+ end
188
+ rescue
189
+ STDERR.puts $!.to_s
190
+ STDERR.puts usage
191
+ exit 1
192
+ end
193
+
194
+ if help
195
+ STDOUT.puts usage
196
+ exit
197
+ end
198
+
199
+ system "#{ sudo } #{ $ruby } pre-install.rb" if test(?s, 'pre-install.rb')
200
+
201
+ unless no_linkify
202
+ linked = linkify('lib') + linkify('bin')
203
+ end
204
+
205
+ system "#{ $ruby } extconf.rb && make && #{ sudo } make install" if test(?s, 'extconf.rb')
206
+
207
+ install_rb(LIBDIR, libdir, LIBDIR_MODE)
208
+ install_rb(BINDIR, bindir, BINDIR_MODE, bin=true)
209
+
210
+ if linked
211
+ linked.each{|path| File::rm_f path}
212
+ end
213
+
214
+ system "#{ sudo } #{ $ruby } post-install.rb" if test(?s, 'post-install.rb')
data/lib/tagz.rb ADDED
@@ -0,0 +1,402 @@
1
+ unless defined? Tagz
2
+
3
+ module Tagz
4
+ unless defined?(Tagz::VERSION)
5
+ Tagz::VERSION = [
6
+ Tagz::VERSION_MAJOR = 5,
7
+ Tagz::VERSION_MINOR = 1,
8
+ Tagz::VERSION_TEENY = 0
9
+ ].join('.')
10
+ def Tagz.version() Tagz::VERSION end
11
+ end
12
+
13
+ private
14
+
15
+ # open_tag
16
+ #
17
+ def tagz__ name, *argv, &block
18
+ options = argv.last.is_a?(Hash) ? argv.pop : {}
19
+ content = argv
20
+
21
+ unless options.empty?
22
+ attributes = ' ' <<
23
+ options.map do |key, value|
24
+ key = Tagz.escape_attribute(key)
25
+ value = Tagz.escape_attribute(value)
26
+ if value =~ %r/"/
27
+ raise ArgumentError, value if value =~ %r/'/
28
+ value = "'#{ value }'"
29
+ else
30
+ raise ArgumentError, value if value =~ %r/"/
31
+ value = "\"#{ value }\""
32
+ end
33
+ [key, value].join('=')
34
+ end.join(' ')
35
+ else
36
+ attributes = ''
37
+ end
38
+
39
+ tagz.push "<#{ name }#{ attributes }>"
40
+
41
+ if content.empty?
42
+ if block
43
+ size = tagz.size
44
+ value = block.call(tagz)
45
+
46
+ if value.nil?
47
+ unless(tagz.size > size)
48
+ tagz[-1] = "/>"
49
+ else
50
+ tagz.push "</#{ name }>"
51
+ end
52
+ else
53
+ tagz << value.to_s unless(tagz.size > size)
54
+ tagz.push "</#{ name }>"
55
+ end
56
+
57
+ end
58
+ else
59
+ tagz << content.join
60
+ if block
61
+ size = tagz.size
62
+ value = block.call(tagz)
63
+ tagz << value.to_s unless(tagz.size > size)
64
+ end
65
+ tagz.push "</#{ name }>"
66
+ end
67
+
68
+ tagz
69
+ end
70
+
71
+ # close_tag
72
+ #
73
+ def __tagz tag, *a, &b
74
+ tagz.push "</#{ tag }>"
75
+ end
76
+
77
+ # access tagz doc and enclose tagz operations
78
+ #
79
+ def tagz document = nil, &block
80
+ @tagz ||= nil ## shut wornings up
81
+ previous = @tagz
82
+
83
+ if block
84
+ @tagz ||= (Document.for(document) || Document.new)
85
+ begin
86
+ size = @tagz.size
87
+ value = instance_eval(&block)
88
+ @tagz << value unless(@tagz.size > size)
89
+ @tagz
90
+ ensure
91
+ @tagz = previous
92
+ end
93
+ else
94
+ document ? Document.for(document) : @tagz
95
+ end
96
+ end
97
+
98
+ # catch special tagz methods
99
+ #
100
+ def method_missing m, *a, &b
101
+ strategy =
102
+ case m.to_s
103
+ when %r/^(.*[^_])_(!)?$/o
104
+ :open_tag
105
+ when %r/^_([^_].*)$/o
106
+ :close_tag
107
+ when 'e'
108
+ :element
109
+ when '__', '___'
110
+ :puts
111
+ else
112
+ nil
113
+ end
114
+
115
+ if(strategy.nil? or (tagz.nil? and not Globally===self))
116
+ begin
117
+ super
118
+ ensure
119
+ $!.set_backtrace caller(skip=1) if $!
120
+ end
121
+ end
122
+
123
+ case strategy
124
+ when :open_tag
125
+ m, bang = $1, $2
126
+ b ||= lambda{} if bang
127
+ tagz{ tagz__(m, *a, &b) }
128
+ when :close_tag
129
+ m = $1
130
+ tagz{ __tagz(m, *a, &b) }
131
+ when :element
132
+ Element.new(*a, &b)
133
+ when :puts
134
+ tagz do
135
+ tagz.push("\n")
136
+ unless a.empty?
137
+ tagz.push(a.join)
138
+ tagz.push("\n")
139
+ end
140
+ end
141
+ end
142
+ end
143
+
144
+ class Document < ::String
145
+ def Document.for other
146
+ Document === other ? other : Document.new(other.to_s)
147
+ end
148
+
149
+ def element
150
+ Element.new(*a, &b)
151
+ end
152
+ alias_method 'e', 'element'
153
+
154
+ alias_method 'write', 'concat'
155
+ alias_method 'push', 'concat'
156
+
157
+ def << string
158
+ case string
159
+ when Document
160
+ super string.to_s
161
+ else
162
+ super Tagz.escape_content(string)
163
+ end
164
+ self
165
+ end
166
+ def concat string
167
+ self << string
168
+ end
169
+ #alias_method 'concat', '<<'
170
+
171
+ def escape(*strings)
172
+ XChar.escape(strings.join)
173
+ end
174
+ alias_method 'h', 'escape'
175
+
176
+ def puts string
177
+ write "#{ string }\n"
178
+ end
179
+
180
+ def document
181
+ self
182
+ end
183
+ alias_method 'doc', 'document'
184
+
185
+ def + other
186
+ self.dup << other
187
+ end
188
+
189
+ def to_s
190
+ self
191
+ end
192
+
193
+ def to_str
194
+ self
195
+ end
196
+ end
197
+
198
+ class Element < ::String
199
+ def Element.attributes options
200
+ unless options.empty?
201
+ ' ' <<
202
+ options.map do |key, value|
203
+ key = Tagz.escape_attribute(key)
204
+ value = Tagz.escape_attribute(value)
205
+ if value =~ %r/"/
206
+ raise ArgumentError, value if value =~ %r/'/
207
+ value = "'#{ value }'"
208
+ else
209
+ raise ArgumentError, value if value =~ %r/"/
210
+ value = "\"#{ value }\""
211
+ end
212
+ [key, value].join('=')
213
+ end.join(' ')
214
+ else
215
+ ''
216
+ end
217
+ end
218
+
219
+ attr 'name'
220
+
221
+ def initialize name, *argv, &block
222
+ options = {}
223
+ content = []
224
+
225
+ argv.each do |arg|
226
+ case arg
227
+ when Hash
228
+ options.update arg
229
+ else
230
+ content.push arg
231
+ end
232
+ end
233
+
234
+ content.push block.call if block
235
+ content.compact!
236
+
237
+ @name = name.to_s
238
+
239
+ if content.empty?
240
+ replace "<#{ @name }#{ Element.attributes options }>"
241
+ else
242
+ replace "<#{ @name }#{ Element.attributes options }>#{ content.join }</#{ name }>"
243
+ end
244
+ end
245
+ end
246
+
247
+ module XChar
248
+ # http://intertwingly.net/stories/2004/04/14/i18n.html#CleaningWindows
249
+ #
250
+ CP1252 = {
251
+ 128 => 8364, # euro sign
252
+ 130 => 8218, # single low-9 quotation mark
253
+ 131 => 402, # latin small letter f with hook
254
+ 132 => 8222, # double low-9 quotation mark
255
+ 133 => 8230, # horizontal ellipsis
256
+ 134 => 8224, # dagger
257
+ 135 => 8225, # double dagger
258
+ 136 => 710, # modifier letter circumflex accent
259
+ 137 => 8240, # per mille sign
260
+ 138 => 352, # latin capital letter s with caron
261
+ 139 => 8249, # single left-pointing angle quotation mark
262
+ 140 => 338, # latin capital ligature oe
263
+ 142 => 381, # latin capital letter z with caron
264
+ 145 => 8216, # left single quotation mark
265
+ 146 => 8217, # right single quotation mark
266
+ 147 => 8220, # left double quotation mark
267
+ 148 => 8221, # right double quotation mark
268
+ 149 => 8226, # bullet
269
+ 150 => 8211, # en dash
270
+ 151 => 8212, # em dash
271
+ 152 => 732, # small tilde
272
+ 153 => 8482, # trade mark sign
273
+ 154 => 353, # latin small letter s with caron
274
+ 155 => 8250, # single right-pointing angle quotation mark
275
+ 156 => 339, # latin small ligature oe
276
+ 158 => 382, # latin small letter z with caron
277
+ 159 => 376} # latin capital letter y with diaeresis
278
+
279
+ # http://www.w3.org/TR/REC-xml/#dt-chardata
280
+ #
281
+ PREDEFINED = {
282
+ 38 => '&amp;', # ampersand
283
+ 60 => '&lt;', # left angle bracket
284
+ 62 => '&gt;'} # right angle bracket
285
+
286
+ # http://www.w3.org/TR/REC-xml/#charsets
287
+ #
288
+ VALID = [[0x9, 0xA, 0xD], (0x20..0xD7FF), (0xE000..0xFFFD), (0x10000..0x10FFFF)]
289
+
290
+ def XChar.escape(string)
291
+ string.unpack('U*').map{|n| xchr(n)}.join # ASCII, UTF-8
292
+ rescue
293
+ string.unpack('C*').map{|n| xchr(n)}.join # ISO-8859-1, WIN-1252
294
+ end
295
+
296
+ def XChar.xchr(n)
297
+ (@xchr ||= {})[n] ||= ((
298
+ n = XChar::CP1252[n] || n
299
+ n = 42 unless XChar::VALID.find{|range| range.include? n}
300
+ XChar::PREDEFINED[n] or (n<128 ? n.chr : "&##{n};")
301
+ ))
302
+ end
303
+ end
304
+
305
+ def Tagz.escapeHTML(*strings)
306
+ XChar.escape(strings.join)
307
+ end
308
+ def Tagz.escape(*strings)
309
+ XChar.escape(strings.join)
310
+ end
311
+
312
+ NoEscape = lambda{|v|v}
313
+
314
+ # support for configuring attribute escaping
315
+ #
316
+ def Tagz.escape_attribute!(*args, &block)
317
+ previous = @escape_attribute if defined?(@escape_attribute)
318
+ unless args.empty? and block.nil?
319
+ value = block ? block : args.shift
320
+ @escape_attribute = value ? value.to_proc : NoEscape
321
+ return previous
322
+ end
323
+ @escape_attribute
324
+ end
325
+
326
+ def Tagz.escape_attributes!(*args, &block)
327
+ Tagz.escape_attribute!(*args, &block)
328
+ end
329
+
330
+ def Tagz.escape_attribute(value)
331
+ @escape_attribute.call(value.to_s)
332
+ end
333
+
334
+ # default escape
335
+ #
336
+ escape_attribute!{|value| XChar.escape(value)}
337
+
338
+ # support for configuring content escaping
339
+ #
340
+ def Tagz.escape_content!(*args, &block)
341
+ previous = @escape_content if defined?(@escape_content)
342
+ unless args.empty? and block.nil?
343
+ value = block ? block : args.shift
344
+ @escape_content = value ? value.to_proc : NoEscape
345
+ return previous
346
+ end
347
+ @escape_content
348
+ end
349
+
350
+ def Tagz.escape_contents!(*args, &block)
351
+ Tagz.escape_content!(*args, &block)
352
+ end
353
+
354
+ def Tagz.escape_content(value)
355
+ @escape_content.call(value.to_s)
356
+ end
357
+
358
+ # default escape
359
+ #
360
+ escape_content!{|value| XChar.escape(value)}
361
+
362
+ # make tagz escape nothing
363
+ #
364
+ def Tagz.i_know_what_the_hell_i_am_doing!
365
+ Tagz.escape_attributes! false
366
+ Tagz.escape_content! false
367
+ end
368
+
369
+ # make tagz escape everything
370
+ #
371
+ def Tagz.i_do_not_know_what_the_hell_i_am_doing!
372
+ escape_attribute!{|value| XChar.escape(value)}
373
+ escape_content!{|value| XChar.escape(value)}
374
+ end
375
+
376
+ module Globally; include Tagz; end
377
+ def Tagz.globally
378
+ Globally
379
+ end
380
+
381
+ module Privately; include Tagz; end
382
+ def Tagz.privately
383
+ Privately
384
+ end
385
+
386
+ %w( tagz tagz__ __tagz method_missing ).each{|m| module_function(m)}
387
+ end
388
+
389
+ def Tagz *argv, &block
390
+ if argv.empty? and block.nil?
391
+ ::Tagz
392
+ else
393
+ Tagz.tagz(*argv, &block)
394
+ end
395
+ end
396
+
397
+ if defined?(Rails)
398
+ ActionView::Base.send(:include, Tagz.globally)
399
+ ActionController::Base.send(:include, Tagz)
400
+ end
401
+
402
+ end