ahoward-tagz 5.1.0

Sign up to get free protection for your applications and to get access to all the features.
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