bluecloth 2.0.6.pre120-x86-mswin32

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.
Files changed (112) hide show
  1. data/ChangeLog +363 -0
  2. data/LICENSE +27 -0
  3. data/LICENSE.discount +47 -0
  4. data/README +81 -0
  5. data/Rakefile +349 -0
  6. data/Rakefile.local +43 -0
  7. data/bin/bluecloth +84 -0
  8. data/ext/Csio.c +61 -0
  9. data/ext/VERSION +1 -0
  10. data/ext/amalloc.h +29 -0
  11. data/ext/bluecloth.c +391 -0
  12. data/ext/bluecloth.h +19 -0
  13. data/ext/config.h +55 -0
  14. data/ext/css.c +76 -0
  15. data/ext/cstring.h +75 -0
  16. data/ext/docheader.c +43 -0
  17. data/ext/extconf.rb +52 -0
  18. data/ext/generate.c +1602 -0
  19. data/ext/markdown.c +1078 -0
  20. data/ext/markdown.h +146 -0
  21. data/ext/mkdio.c +303 -0
  22. data/ext/mkdio.h +79 -0
  23. data/ext/resource.c +155 -0
  24. data/ext/version.c +28 -0
  25. data/ext/xml.c +82 -0
  26. data/ext/xmlpage.c +48 -0
  27. data/lib/1.8/bluecloth_ext.so +0 -0
  28. data/lib/1.9/bluecloth_ext.so +0 -0
  29. data/lib/bluecloth.rb +164 -0
  30. data/rake/191_compat.rb +26 -0
  31. data/rake/dependencies.rb +76 -0
  32. data/rake/helpers.rb +434 -0
  33. data/rake/hg.rb +273 -0
  34. data/rake/manual.rb +782 -0
  35. data/rake/packaging.rb +126 -0
  36. data/rake/publishing.rb +269 -0
  37. data/rake/rdoc.rb +30 -0
  38. data/rake/style.rb +62 -0
  39. data/rake/svn.rb +668 -0
  40. data/rake/testing.rb +187 -0
  41. data/rake/verifytask.rb +64 -0
  42. data/rake/win32.rb +190 -0
  43. data/spec/bluecloth/101_changes_spec.rb +141 -0
  44. data/spec/bluecloth/autolinks_spec.rb +49 -0
  45. data/spec/bluecloth/blockquotes_spec.rb +145 -0
  46. data/spec/bluecloth/code_spans_spec.rb +164 -0
  47. data/spec/bluecloth/emphasis_spec.rb +164 -0
  48. data/spec/bluecloth/entities_spec.rb +65 -0
  49. data/spec/bluecloth/hrules_spec.rb +90 -0
  50. data/spec/bluecloth/images_spec.rb +92 -0
  51. data/spec/bluecloth/inline_html_spec.rb +238 -0
  52. data/spec/bluecloth/links_spec.rb +171 -0
  53. data/spec/bluecloth/lists_spec.rb +294 -0
  54. data/spec/bluecloth/paragraphs_spec.rb +75 -0
  55. data/spec/bluecloth/titles_spec.rb +305 -0
  56. data/spec/bluecloth_spec.rb +281 -0
  57. data/spec/bugfix_spec.rb +172 -0
  58. data/spec/contributions_spec.rb +85 -0
  59. data/spec/data/antsugar.txt +34 -0
  60. data/spec/data/markdowntest/Amps and angle encoding.html +17 -0
  61. data/spec/data/markdowntest/Amps and angle encoding.text +21 -0
  62. data/spec/data/markdowntest/Auto links.html +18 -0
  63. data/spec/data/markdowntest/Auto links.text +13 -0
  64. data/spec/data/markdowntest/Backslash escapes.html +118 -0
  65. data/spec/data/markdowntest/Backslash escapes.text +120 -0
  66. data/spec/data/markdowntest/Blockquotes with code blocks.html +15 -0
  67. data/spec/data/markdowntest/Blockquotes with code blocks.text +11 -0
  68. data/spec/data/markdowntest/Code Blocks.html +18 -0
  69. data/spec/data/markdowntest/Code Blocks.text +14 -0
  70. data/spec/data/markdowntest/Code Spans.html +5 -0
  71. data/spec/data/markdowntest/Code Spans.text +5 -0
  72. data/spec/data/markdowntest/Hard-wrapped paragraphs with list-like lines.html +8 -0
  73. data/spec/data/markdowntest/Hard-wrapped paragraphs with list-like lines.text +8 -0
  74. data/spec/data/markdowntest/Horizontal rules.html +71 -0
  75. data/spec/data/markdowntest/Horizontal rules.text +67 -0
  76. data/spec/data/markdowntest/Inline HTML (Advanced).html +15 -0
  77. data/spec/data/markdowntest/Inline HTML (Advanced).text +15 -0
  78. data/spec/data/markdowntest/Inline HTML (Simple).html +72 -0
  79. data/spec/data/markdowntest/Inline HTML (Simple).text +69 -0
  80. data/spec/data/markdowntest/Inline HTML comments.html +13 -0
  81. data/spec/data/markdowntest/Inline HTML comments.text +13 -0
  82. data/spec/data/markdowntest/Links, inline style.html +11 -0
  83. data/spec/data/markdowntest/Links, inline style.text +12 -0
  84. data/spec/data/markdowntest/Links, reference style.html +52 -0
  85. data/spec/data/markdowntest/Links, reference style.text +71 -0
  86. data/spec/data/markdowntest/Links, shortcut references.html +9 -0
  87. data/spec/data/markdowntest/Links, shortcut references.text +20 -0
  88. data/spec/data/markdowntest/Literal quotes in titles.html +3 -0
  89. data/spec/data/markdowntest/Literal quotes in titles.text +7 -0
  90. data/spec/data/markdowntest/Markdown Documentation - Basics.html +314 -0
  91. data/spec/data/markdowntest/Markdown Documentation - Basics.text +306 -0
  92. data/spec/data/markdowntest/Markdown Documentation - Syntax.html +942 -0
  93. data/spec/data/markdowntest/Markdown Documentation - Syntax.text +888 -0
  94. data/spec/data/markdowntest/Nested blockquotes.html +9 -0
  95. data/spec/data/markdowntest/Nested blockquotes.text +5 -0
  96. data/spec/data/markdowntest/Ordered and unordered lists.html +148 -0
  97. data/spec/data/markdowntest/Ordered and unordered lists.text +131 -0
  98. data/spec/data/markdowntest/Strong and em together.html +7 -0
  99. data/spec/data/markdowntest/Strong and em together.text +7 -0
  100. data/spec/data/markdowntest/Tabs.html +25 -0
  101. data/spec/data/markdowntest/Tabs.text +21 -0
  102. data/spec/data/markdowntest/Tidyness.html +8 -0
  103. data/spec/data/markdowntest/Tidyness.text +5 -0
  104. data/spec/data/ml-announce.txt +17 -0
  105. data/spec/data/re-overflow.txt +67 -0
  106. data/spec/data/re-overflow2.txt +281 -0
  107. data/spec/discount_spec.rb +184 -0
  108. data/spec/lib/constants.rb +5 -0
  109. data/spec/lib/helpers.rb +137 -0
  110. data/spec/lib/matchers.rb +235 -0
  111. data/spec/markdowntest_spec.rb +79 -0
  112. metadata +205 -0
@@ -0,0 +1,26 @@
1
+ # 1.9.1 fixes
2
+
3
+
4
+ # Make Pathname compatible with 1.8.7 Pathname.
5
+ unless Pathname.instance_methods.include?( :=~ )
6
+ class Pathname
7
+ def self::glob( *args ) # :yield: p
8
+ args = args.collect {|p| p.to_s }
9
+ if block_given?
10
+ Dir.glob(*args) {|f| yield self.new(f) }
11
+ else
12
+ Dir.glob(*args).map {|f| self.new(f) }
13
+ end
14
+ end
15
+
16
+ def =~( other )
17
+ self.to_s =~ other
18
+ end
19
+
20
+ def to_str
21
+ self.to_s
22
+ end
23
+ end
24
+ end
25
+
26
+
@@ -0,0 +1,76 @@
1
+ #
2
+ # Dependency-checking and Installation Rake Tasks
3
+
4
+ #
5
+
6
+ require 'rubygems/dependency_installer'
7
+ require 'rubygems/source_index'
8
+ require 'rubygems/requirement'
9
+ require 'rubygems/doc_manager'
10
+
11
+ ### Install the specified +gems+ if they aren't already installed.
12
+ def install_gems( gems )
13
+
14
+ defaults = Gem::DependencyInstaller::DEFAULT_OPTIONS.merge({
15
+ :generate_rdoc => true,
16
+ :generate_ri => true,
17
+ :install_dir => Gem.dir,
18
+ :format_executable => false,
19
+ :test => false,
20
+ :version => Gem::Requirement.default,
21
+ })
22
+
23
+ # Check for root
24
+ if Process.euid != 0
25
+ $stderr.puts "This probably won't work, as you aren't root, but I'll try anyway"
26
+ end
27
+
28
+ gemindex = Gem::SourceIndex.from_installed_gems
29
+
30
+ gems.each do |gemname, reqstring|
31
+ requirement = Gem::Requirement.new( reqstring )
32
+ trace "requirement is: %p" % [ requirement ]
33
+
34
+ trace "Searching for an installed #{gemname}..."
35
+ specs = gemindex.find_name( gemname )
36
+ trace "...found %d specs: %s" %
37
+ [ specs.length, specs.collect {|s| "%s %s" % [s.name, s.version] }.join(', ') ]
38
+
39
+ if spec = specs.find {|spec| requirement.satisfied_by?(spec.version) }
40
+ log "Version %s of %s is already installed (needs %s); skipping..." %
41
+ [ spec.version, spec.name, requirement ]
42
+ next
43
+ end
44
+
45
+ rgv = Gem::Version.new( Gem::RubyGemsVersion )
46
+ installer = nil
47
+
48
+ log "Trying to install #{gemname.inspect} #{requirement}..."
49
+ if rgv >= Gem::Version.new( '1.1.1' )
50
+ installer = Gem::DependencyInstaller.new
51
+ installer.install( gemname, requirement )
52
+ else
53
+ installer = Gem::DependencyInstaller.new( gemname )
54
+ installer.install
55
+ end
56
+
57
+ installer.installed_gems.each do |spec|
58
+ log "Installed: %s" % [ spec.full_name ]
59
+ end
60
+
61
+ end
62
+ end
63
+
64
+
65
+ ### Task: install runtime dependencies
66
+ desc "Install runtime dependencies as gems"
67
+ task :install_dependencies do
68
+ install_gems( DEPENDENCIES )
69
+ end
70
+
71
+ ### Task: install gems for development tasks
72
+ desc "Install development dependencies as gems"
73
+ task :install_dev_dependencies do
74
+ install_gems( DEVELOPMENT_DEPENDENCIES )
75
+ end
76
+
data/rake/helpers.rb ADDED
@@ -0,0 +1,434 @@
1
+ # encoding: utf-8
2
+ #####################################################################
3
+ ### G L O B A L H E L P E R F U N C T I O N S
4
+ #####################################################################
5
+
6
+
7
+ require 'pathname'
8
+ require 'uri'
9
+ require 'open3'
10
+
11
+ begin
12
+ require 'readline'
13
+ include Readline
14
+ rescue LoadError
15
+ # Fall back to a plain prompt
16
+ def readline( text )
17
+ $stderr.print( text.chomp )
18
+ return $stdin.gets
19
+ end
20
+ end
21
+
22
+ # Set some ANSI escape code constants (Shamelessly stolen from Perl's
23
+ # Term::ANSIColor by Russ Allbery <rra@stanford.edu> and Zenin <zenin@best.com>
24
+ ANSI_ATTRIBUTES = {
25
+ 'clear' => 0,
26
+ 'reset' => 0,
27
+ 'bold' => 1,
28
+ 'dark' => 2,
29
+ 'underline' => 4,
30
+ 'underscore' => 4,
31
+ 'blink' => 5,
32
+ 'reverse' => 7,
33
+ 'concealed' => 8,
34
+
35
+ 'black' => 30, 'on_black' => 40,
36
+ 'red' => 31, 'on_red' => 41,
37
+ 'green' => 32, 'on_green' => 42,
38
+ 'yellow' => 33, 'on_yellow' => 43,
39
+ 'blue' => 34, 'on_blue' => 44,
40
+ 'magenta' => 35, 'on_magenta' => 45,
41
+ 'cyan' => 36, 'on_cyan' => 46,
42
+ 'white' => 37, 'on_white' => 47
43
+ }
44
+
45
+
46
+ MULTILINE_PROMPT = <<-'EOF'
47
+ Enter one or more values for '%s'.
48
+ A blank line finishes input.
49
+ EOF
50
+
51
+
52
+ CLEAR_TO_EOL = "\e[K"
53
+ CLEAR_CURRENT_LINE = "\e[2K"
54
+
55
+
56
+ ### Output a logging message
57
+ def log( *msg )
58
+ output = colorize( msg.flatten.join(' '), 'cyan' )
59
+ $stderr.puts( output )
60
+ end
61
+
62
+
63
+ ### Output a logging message if tracing is on
64
+ def trace( *msg )
65
+ return unless $trace
66
+ output = colorize( msg.flatten.join(' '), 'yellow' )
67
+ $stderr.puts( output )
68
+ end
69
+
70
+
71
+ ### Return the specified args as a string, quoting any that have a space.
72
+ def quotelist( *args )
73
+ return args.flatten.collect {|part| part =~ /\s/ ? part.inspect : part}
74
+ end
75
+
76
+
77
+ ### Run the specified command +cmd+ with system(), failing if the execution
78
+ ### fails.
79
+ def run( *cmd )
80
+ cmd.flatten!
81
+
82
+ if cmd.length > 1
83
+ trace( quotelist(*cmd) )
84
+ else
85
+ trace( cmd )
86
+ end
87
+
88
+ if $dryrun
89
+ $stderr.puts "(dry run mode)"
90
+ else
91
+ system( *cmd )
92
+ unless $?.success?
93
+ fail "Command failed: [%s]" % [cmd.join(' ')]
94
+ end
95
+ end
96
+ end
97
+
98
+
99
+ ### Run the given +cmd+ with the specified +args+ without interpolation by the shell and
100
+ ### return anything written to its STDOUT.
101
+ def read_command_output( cmd, *args )
102
+ trace "Reading output from: %s" % [ cmd, quotelist(cmd, *args) ]
103
+ output = IO.read( '|-' ) or exec cmd, *args
104
+ return output
105
+ end
106
+
107
+
108
+ ### Run a subordinate Rake process with the same options and the specified +targets+.
109
+ def rake( *targets )
110
+ opts = ARGV.select {|arg| arg[0,1] == '-' }
111
+ args = opts + targets.map {|t| t.to_s }
112
+ run 'rake', '-N', *args
113
+ end
114
+
115
+
116
+ ### Open a pipe to a process running the given +cmd+ and call the given block with it.
117
+ def pipeto( *cmd )
118
+ $DEBUG = true
119
+
120
+ cmd.flatten!
121
+ log( "Opening a pipe to: ", cmd.collect {|part| part =~ /\s/ ? part.inspect : part} )
122
+ if $dryrun
123
+ $stderr.puts "(dry run mode)"
124
+ else
125
+ open( '|-', 'w+' ) do |io|
126
+
127
+ # Parent
128
+ if io
129
+ yield( io )
130
+
131
+ # Child
132
+ else
133
+ exec( *cmd )
134
+ fail "Command failed: [%s]" % [cmd.join(' ')]
135
+ end
136
+ end
137
+ end
138
+ end
139
+
140
+
141
+ ### Download the file at +sourceuri+ via HTTP and write it to +targetfile+.
142
+ def download( sourceuri, targetfile=nil )
143
+ oldsync = $stdout.sync
144
+ $stdout.sync = true
145
+ require 'open-uri'
146
+
147
+ targetpath = Pathname.new( targetfile )
148
+
149
+ log "Downloading %s to %s" % [sourceuri, targetfile]
150
+ trace " connecting..."
151
+ ifh = open( sourceuri ) do |ifh|
152
+ trace " connected..."
153
+ targetpath.open( File::WRONLY|File::TRUNC|File::CREAT, 0644 ) do |ofh|
154
+ log "Downloading..."
155
+ buf = ''
156
+
157
+ while ifh.read( 16384, buf )
158
+ until buf.empty?
159
+ bytes = ofh.write( buf )
160
+ buf.slice!( 0, bytes )
161
+ end
162
+ end
163
+
164
+ log "Done."
165
+ end
166
+
167
+ end
168
+
169
+ return targetpath
170
+ ensure
171
+ $stdout.sync = oldsync
172
+ end
173
+
174
+
175
+ ### Return the fully-qualified path to the specified +program+ in the PATH.
176
+ def which( program )
177
+ ENV['PATH'].split(/:/).
178
+ collect {|dir| Pathname.new(dir) + program }.
179
+ find {|path| path.exist? && path.executable? }
180
+ end
181
+
182
+
183
+ ### Create a string that contains the ANSI codes specified and return it
184
+ def ansi_code( *attributes )
185
+ attributes.flatten!
186
+ attributes.collect! {|at| at.to_s }
187
+ # $stderr.puts "Returning ansicode for TERM = %p: %p" %
188
+ # [ ENV['TERM'], attributes ]
189
+ return '' unless /(?:vt10[03]|xterm(?:-color)?|linux|screen)/i =~ ENV['TERM']
190
+ attributes = ANSI_ATTRIBUTES.values_at( *attributes ).compact.join(';')
191
+
192
+ # $stderr.puts " attr is: %p" % [attributes]
193
+ if attributes.empty?
194
+ return ''
195
+ else
196
+ return "\e[%sm" % attributes
197
+ end
198
+ end
199
+
200
+
201
+ ### Colorize the given +string+ with the specified +attributes+ and return it, handling
202
+ ### line-endings, color reset, etc.
203
+ def colorize( *args )
204
+ string = ''
205
+
206
+ if block_given?
207
+ string = yield
208
+ else
209
+ string = args.shift
210
+ end
211
+
212
+ ending = string[/(\s)$/] || ''
213
+ string = string.rstrip
214
+
215
+ return ansi_code( args.flatten ) + string + ansi_code( 'reset' ) + ending
216
+ end
217
+
218
+
219
+ ### Output the specified <tt>msg</tt> as an ANSI-colored error message
220
+ ### (white on red).
221
+ def error_message( msg, details='' )
222
+ $stderr.puts colorize( 'bold', 'white', 'on_red' ) { msg } + details
223
+ end
224
+ alias :error :error_message
225
+
226
+
227
+ ### Highlight and embed a prompt control character in the given +string+ and return it.
228
+ def make_prompt_string( string )
229
+ return CLEAR_CURRENT_LINE + colorize( 'bold', 'green' ) { string + ' ' }
230
+ end
231
+
232
+
233
+ ### Output the specified <tt>prompt_string</tt> as a prompt (in green) and
234
+ ### return the user's input with leading and trailing spaces removed. If a
235
+ ### test is provided, the prompt will repeat until the test returns true.
236
+ ### An optional failure message can also be passed in.
237
+ def prompt( prompt_string, failure_msg="Try again." ) # :yields: response
238
+ prompt_string.chomp!
239
+ prompt_string << ":" unless /\W$/.match( prompt_string )
240
+ response = nil
241
+
242
+ begin
243
+ prompt = make_prompt_string( prompt_string )
244
+ response = readline( prompt ) || ''
245
+ response.strip!
246
+ if block_given? && ! yield( response )
247
+ error_message( failure_msg + "\n\n" )
248
+ response = nil
249
+ end
250
+ end while response.nil?
251
+
252
+ return response
253
+ end
254
+
255
+
256
+ ### Prompt the user with the given <tt>prompt_string</tt> via #prompt,
257
+ ### substituting the given <tt>default</tt> if the user doesn't input
258
+ ### anything. If a test is provided, the prompt will repeat until the test
259
+ ### returns true. An optional failure message can also be passed in.
260
+ def prompt_with_default( prompt_string, default, failure_msg="Try again." )
261
+ response = nil
262
+
263
+ begin
264
+ default ||= '~'
265
+ response = prompt( "%s [%s]" % [ prompt_string, default ] )
266
+ response = default.to_s if !response.nil? && response.empty?
267
+
268
+ trace "Validating response %p" % [ response ]
269
+
270
+ # the block is a validator. We need to make sure that the user didn't
271
+ # enter '~', because if they did, it's nil and we should move on. If
272
+ # they didn't, then call the block.
273
+ if block_given? && response != '~' && ! yield( response )
274
+ error_message( failure_msg + "\n\n" )
275
+ response = nil
276
+ end
277
+ end while response.nil?
278
+
279
+ return nil if response == '~'
280
+ return response
281
+ end
282
+
283
+
284
+ ### Prompt for an array of values
285
+ def prompt_for_multiple_values( label, default=nil )
286
+ $stderr.puts( MULTILINE_PROMPT % [label] )
287
+ if default
288
+ $stderr.puts "Enter a single blank line to keep the default:\n %p" % [ default ]
289
+ end
290
+
291
+ results = []
292
+ result = nil
293
+
294
+ begin
295
+ result = readline( make_prompt_string("> ") )
296
+ if result.nil? || result.empty?
297
+ results << default if default && results.empty?
298
+ else
299
+ results << result
300
+ end
301
+ end until result.nil? || result.empty?
302
+
303
+ return results.flatten
304
+ end
305
+
306
+
307
+ ### Turn echo and masking of input on/off.
308
+ def noecho( masked=false )
309
+ require 'termios'
310
+
311
+ rval = nil
312
+ term = Termios.getattr( $stdin )
313
+
314
+ begin
315
+ newt = term.dup
316
+ newt.c_lflag &= ~Termios::ECHO
317
+ newt.c_lflag &= ~Termios::ICANON if masked
318
+
319
+ Termios.tcsetattr( $stdin, Termios::TCSANOW, newt )
320
+
321
+ rval = yield
322
+ ensure
323
+ Termios.tcsetattr( $stdin, Termios::TCSANOW, term )
324
+ end
325
+
326
+ return rval
327
+ end
328
+
329
+
330
+ ### Prompt the user for her password, turning off echo if the 'termios' module is
331
+ ### available.
332
+ def prompt_for_password( prompt="Password: " )
333
+ return noecho( true ) do
334
+ $stderr.print( prompt )
335
+ ($stdin.gets || '').chomp
336
+ end
337
+ end
338
+
339
+
340
+ ### Display a description of a potentially-dangerous task, and prompt
341
+ ### for confirmation. If the user answers with anything that begins
342
+ ### with 'y', yield to the block. If +abort_on_decline+ is +true+,
343
+ ### any non-'y' answer will fail with an error message.
344
+ def ask_for_confirmation( description, abort_on_decline=true )
345
+ puts description
346
+
347
+ answer = prompt_with_default( "Continue?", 'n' ) do |input|
348
+ input =~ /^[yn]/i
349
+ end
350
+
351
+ if answer =~ /^y/i
352
+ return yield
353
+ elsif abort_on_decline
354
+ error "Aborted."
355
+ fail
356
+ end
357
+
358
+ return false
359
+ end
360
+ alias :prompt_for_confirmation :ask_for_confirmation
361
+
362
+
363
+ ### Search line-by-line in the specified +file+ for the given +regexp+, returning the
364
+ ### first match, or nil if no match was found. If the +regexp+ has any capture groups,
365
+ ### those will be returned in an Array, else the whole matching line is returned.
366
+ def find_pattern_in_file( regexp, file )
367
+ rval = nil
368
+
369
+ File.open( file, 'r' ).each do |line|
370
+ if (( match = regexp.match(line) ))
371
+ rval = match.captures.empty? ? match[0] : match.captures
372
+ break
373
+ end
374
+ end
375
+
376
+ return rval
377
+ end
378
+
379
+
380
+ ### Search line-by-line in the output of the specified +cmd+ for the given +regexp+,
381
+ ### returning the first match, or nil if no match was found. If the +regexp+ has any
382
+ ### capture groups, those will be returned in an Array, else the whole matching line
383
+ ### is returned.
384
+ def find_pattern_in_pipe( regexp, *cmd )
385
+ output = []
386
+
387
+ log( cmd.collect {|part| part =~ /\s/ ? part.inspect : part} )
388
+ Open3.popen3( *cmd ) do |stdin, stdout, stderr|
389
+ stdin.close
390
+
391
+ output << stdout.gets until stdout.eof?
392
+ output << stderr.gets until stderr.eof?
393
+ end
394
+
395
+ result = output.find { |line| regexp.match(line) }
396
+ return $1 || result
397
+ end
398
+
399
+
400
+ ### Invoke the user's editor on the given +filename+ and return the exit code
401
+ ### from doing so.
402
+ def edit( filename )
403
+ editor = ENV['EDITOR'] || ENV['VISUAL'] || DEFAULT_EDITOR
404
+ system editor, filename
405
+ unless $?.success? || editor =~ /vim/i
406
+ fail "Editor exited uncleanly."
407
+ end
408
+ end
409
+
410
+
411
+ ### Extract all the non Rake-target arguments from ARGV and return them.
412
+ def get_target_args
413
+ args = ARGV.reject {|arg| arg =~ /^-/ || Rake::Task.task_defined?(arg) }
414
+ return args
415
+ end
416
+
417
+
418
+ ### Log a subdirectory change, execute a block, and exit the subdirectory
419
+ def in_subdirectory( subdir )
420
+ block = Proc.new
421
+
422
+ log "Entering #{subdir}"
423
+ Dir.chdir( subdir, &block )
424
+ log "Leaving #{subdir}"
425
+ end
426
+
427
+
428
+ ### Make an easily-comparable version vector out of +ver+ and return it.
429
+ def vvec( ver )
430
+ return ver.split('.').collect {|char| char.to_i }.pack('N*')
431
+ end
432
+
433
+
434
+