chunker 0.1.53
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/LICENSE +29 -0
- data/README +59 -0
- data/Rakefile +156 -0
- data/lib/chunker.rb +135 -0
- data/spec/chunker_spec.rb +117 -0
- metadata +57 -0
data/LICENSE
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
Copyright (c) 2008, Mahlon E. Smith
|
|
2
|
+
|
|
3
|
+
All rights reserved.
|
|
4
|
+
|
|
5
|
+
Redistribution and use in source and binary forms, with or without modification, are
|
|
6
|
+
permitted provided that the following conditions are met:
|
|
7
|
+
|
|
8
|
+
* Redistributions of source code must retain the above copyright notice, this
|
|
9
|
+
list of conditions and the following disclaimer.
|
|
10
|
+
|
|
11
|
+
* Redistributions in binary form must reproduce the above copyright notice, this
|
|
12
|
+
list of conditions and the following disclaimer in the documentation and/or
|
|
13
|
+
other materials provided with the distribution.
|
|
14
|
+
|
|
15
|
+
* Neither the name of the author, nor the names of contributors may be used to
|
|
16
|
+
endorse or promote products derived from this software without specific prior
|
|
17
|
+
written permission.
|
|
18
|
+
|
|
19
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
20
|
+
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
21
|
+
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
22
|
+
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
|
23
|
+
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
24
|
+
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
25
|
+
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
26
|
+
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
|
27
|
+
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
28
|
+
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
29
|
+
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
data/README
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
|
|
2
|
+
Preface:
|
|
3
|
+
|
|
4
|
+
Ruby provides an automatic constant called DATA, which is an IO object
|
|
5
|
+
that references all text in the current file under an __END__ token.
|
|
6
|
+
|
|
7
|
+
I find it convenient to use the __END__ area to store all sorts of
|
|
8
|
+
stuff, rather than have to worry about distributing separate files.
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
The problem:
|
|
12
|
+
|
|
13
|
+
The DATA constant is determined from whatever ruby believes $0 to be.
|
|
14
|
+
It doesn't work inside of other required libraries, so you'll see stuff
|
|
15
|
+
like this all the time:
|
|
16
|
+
|
|
17
|
+
END = File.open( __FILE__ ).read.split( /^__END__/, 2 ).last
|
|
18
|
+
|
|
19
|
+
It works, but it's more work than I want to do.
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
A workaround:
|
|
23
|
+
|
|
24
|
+
Chunker solves this by parsing __END__ tokens for you, and making it
|
|
25
|
+
available in the form of a 'DATA_END' constant. It installs this
|
|
26
|
+
constant into the class that includes Chunker, so you can use it again
|
|
27
|
+
and again, assuming you use a different file for each class.
|
|
28
|
+
|
|
29
|
+
It also automatically parses out other things that look like tokens, so
|
|
30
|
+
you can easily have multiple, distinct documents all embedded into the
|
|
31
|
+
__END__ block.
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
Usage:
|
|
35
|
+
|
|
36
|
+
There is no direct interface to Chunker. Just include it from a
|
|
37
|
+
class to have that file's __END__ data blocks magically become DATA_*
|
|
38
|
+
IO constants within that class.
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
Example:
|
|
42
|
+
|
|
43
|
+
This produces the string "Yep.\n".
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
require 'chunker'
|
|
47
|
+
class Foom
|
|
48
|
+
include Chunker
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
puts Foom.new.class.const_get( :DATA_WICKED ).read
|
|
52
|
+
|
|
53
|
+
__END__
|
|
54
|
+
Stuff in the END block!
|
|
55
|
+
__WOW__
|
|
56
|
+
Ultimate success!
|
|
57
|
+
__WICKED__
|
|
58
|
+
Yep.
|
|
59
|
+
|
data/Rakefile
ADDED
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
#!/usr/bin/env rake
|
|
2
|
+
#
|
|
3
|
+
# Chunker Rakefile
|
|
4
|
+
#
|
|
5
|
+
|
|
6
|
+
require 'rubygems'
|
|
7
|
+
require 'pathname'
|
|
8
|
+
|
|
9
|
+
require 'rake'
|
|
10
|
+
require 'rake/packagetask'
|
|
11
|
+
require 'rake/gempackagetask'
|
|
12
|
+
require 'spec/rake/spectask'
|
|
13
|
+
require 'rubygems/installer'
|
|
14
|
+
require 'rubygems/uninstaller'
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
######################################################################
|
|
18
|
+
### P A T H S A N D F I L E S
|
|
19
|
+
######################################################################
|
|
20
|
+
|
|
21
|
+
BASEDIR = Pathname.new( __FILE__ ).expand_path.dirname.relative_path_from( Pathname.getwd )
|
|
22
|
+
|
|
23
|
+
TEXT_FILES = %w{ Rakefile README LICENSE }.collect {|f| BASEDIR + f }
|
|
24
|
+
|
|
25
|
+
SPECDIR = BASEDIR + 'spec'
|
|
26
|
+
SPEC_FILES = Pathname.glob( SPECDIR + '**/*_spec.rb' ).reject {|f| f =~ /^\.svn/ }
|
|
27
|
+
|
|
28
|
+
LIBDIR = BASEDIR + 'lib'
|
|
29
|
+
LIB_FILES = Pathname.glob( LIBDIR + '**/*.rb').reject {|i| i =~ /\.svn/ }
|
|
30
|
+
|
|
31
|
+
RELEASE_FILES = TEXT_FILES + LIB_FILES + SPEC_FILES
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
######################################################################
|
|
35
|
+
### H E L P E R S
|
|
36
|
+
######################################################################
|
|
37
|
+
|
|
38
|
+
### Given a +file+ path, find the first captured match of +pattern+,
|
|
39
|
+
### or the string 'UNKNOWN' if not found. (easy to notice something is wrong.)
|
|
40
|
+
###
|
|
41
|
+
def find_pattern( file, pattern )
|
|
42
|
+
ver = nil
|
|
43
|
+
File.open( file ) do |f|
|
|
44
|
+
ver = f.each do |line|
|
|
45
|
+
break $1 if line =~ pattern
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
return ver.is_a?( String ) ? ver : 'UNKNOWN'
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
######################################################################
|
|
53
|
+
### P A C K A G E C O N S T A N T S
|
|
54
|
+
######################################################################
|
|
55
|
+
|
|
56
|
+
PKG_NAME = 'chunker'
|
|
57
|
+
PKG_VERSION = find_pattern( LIBDIR + 'chunker.rb', /VERSION = ['"](\d\.\d(?:\/\d)?)['"]/ )
|
|
58
|
+
PKG_REVISION = find_pattern( LIBDIR + 'chunker.rb', /SVNRev = .+Rev: (\d+)/ )
|
|
59
|
+
PKG_FILE_NAME = "#{PKG_NAME}-#{PKG_VERSION}.#{PKG_REVISION}"
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
######################################################################
|
|
63
|
+
### T A S K S
|
|
64
|
+
######################################################################
|
|
65
|
+
|
|
66
|
+
task :default => [ :test, :package ]
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
### Task: run rspec tests
|
|
70
|
+
###
|
|
71
|
+
desc "Run tests"
|
|
72
|
+
Spec::Rake::SpecTask.new('test') do |task|
|
|
73
|
+
task.spec_files = SPEC_FILES
|
|
74
|
+
task.spec_opts = %w{ -c -fs }
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
### Task: generate ctags
|
|
79
|
+
### This assumes exuberant ctags, since ctags 'native' doesn't support ruby anyway.
|
|
80
|
+
###
|
|
81
|
+
desc "Generate a ctags 'tags' file from Chunker source"
|
|
82
|
+
task :ctags do
|
|
83
|
+
sh "ctags -R #{LIBDIR}"
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
### Task: Create gem from source
|
|
88
|
+
###
|
|
89
|
+
gem = Gem::Specification.new do |gem|
|
|
90
|
+
pkg_build = PKG_REVISION || 0
|
|
91
|
+
|
|
92
|
+
gem.summary = "A convenience library for parsing __END__ tokens consistently."
|
|
93
|
+
gem.name = PKG_NAME
|
|
94
|
+
gem.version = "%s.%s" % [ PKG_VERSION, pkg_build ]
|
|
95
|
+
gem.author = 'Mahlon E. Smith'
|
|
96
|
+
gem.email = 'mahlon@martini.nu'
|
|
97
|
+
gem.homepage = 'http://projects.martini.nu/ruby-modules/wiki/Chunker'
|
|
98
|
+
gem.rubyforge_project = 'mahlon'
|
|
99
|
+
gem.has_rdoc = true
|
|
100
|
+
|
|
101
|
+
gem.files = RELEASE_FILES.
|
|
102
|
+
collect {|f| f.relative_path_from(BASEDIR).to_s }
|
|
103
|
+
gem.test_files = SPEC_FILES.
|
|
104
|
+
collect {|f| f.relative_path_from(BASEDIR).to_s }
|
|
105
|
+
|
|
106
|
+
gem.description = <<-EOF
|
|
107
|
+
Ruby provides an automatic constant called DATA, which is an IO object
|
|
108
|
+
that references all text in the current file under an __END__ token.
|
|
109
|
+
|
|
110
|
+
I find it convenient to use the __END__ area to store all sorts of
|
|
111
|
+
stuff, rather than have to worry about distributing separate files.
|
|
112
|
+
|
|
113
|
+
The DATA constant is determined from whatever ruby believes $0 to be.
|
|
114
|
+
It doesn't work inside of other required libraries, so you'll see stuff
|
|
115
|
+
like this all the time:
|
|
116
|
+
|
|
117
|
+
END = File.open( __FILE__ ).read.split( /^__END__/, 2 ).last
|
|
118
|
+
|
|
119
|
+
It works, but it's more work than I want to do.
|
|
120
|
+
|
|
121
|
+
Chunker solves this by parsing __END__ tokens for you, and making it
|
|
122
|
+
available in the form of a 'DATA_END' constant. It installs this
|
|
123
|
+
constant into the class that includes Chunker, so you can use it again
|
|
124
|
+
and again, assuming you use a different file for each class.
|
|
125
|
+
|
|
126
|
+
It also automatically parses out other things that look like tokens, so
|
|
127
|
+
you can easily have multiple, distinct documents all embedded into the
|
|
128
|
+
__END__ block.
|
|
129
|
+
EOF
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
Rake::GemPackageTask.new( gem ) do |pkg|
|
|
133
|
+
pkg.need_zip = true
|
|
134
|
+
pkg.need_tar = true
|
|
135
|
+
pkg.need_tar_bz2 = true
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
### Task: install
|
|
140
|
+
###
|
|
141
|
+
task :install_gem => [ :package ] do
|
|
142
|
+
$stderr.puts
|
|
143
|
+
installer = Gem::Installer.new( "pkg/#{PKG_FILE_NAME}.gem" )
|
|
144
|
+
installer.install
|
|
145
|
+
end
|
|
146
|
+
task :install => [ :install_gem ]
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
### Task: uninstall
|
|
150
|
+
###
|
|
151
|
+
task :uninstall_gem do
|
|
152
|
+
uninstaller = Gem::Uninstaller.new( PKG_NAME )
|
|
153
|
+
uninstaller.uninstall
|
|
154
|
+
end
|
|
155
|
+
task :uninstall => [ :uninstall_gem ]
|
|
156
|
+
|
data/lib/chunker.rb
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
#!/usr/bin/ruby
|
|
2
|
+
#
|
|
3
|
+
# Chunker: A convenience library for parsing __END__ tokens consistently.
|
|
4
|
+
#
|
|
5
|
+
# == Version
|
|
6
|
+
#
|
|
7
|
+
# $Id: chunker.rb 53 2008-11-09 00:27:36Z mahlon $
|
|
8
|
+
#
|
|
9
|
+
# == Author
|
|
10
|
+
#
|
|
11
|
+
# * Mahlon E. Smith <mahlon@martini.nu>
|
|
12
|
+
#
|
|
13
|
+
# :include: LICENSE
|
|
14
|
+
#
|
|
15
|
+
|
|
16
|
+
### Namespace for the datablock parser.
|
|
17
|
+
###
|
|
18
|
+
module Chunker
|
|
19
|
+
|
|
20
|
+
require 'strscan'
|
|
21
|
+
require 'stringio'
|
|
22
|
+
|
|
23
|
+
# SVN Revision
|
|
24
|
+
#
|
|
25
|
+
SVNRev = %q$Rev: 53 $
|
|
26
|
+
|
|
27
|
+
# SVN Id
|
|
28
|
+
#
|
|
29
|
+
SVNId = %q$Id: chunker.rb 53 2008-11-09 00:27:36Z mahlon $
|
|
30
|
+
|
|
31
|
+
# Package version
|
|
32
|
+
#
|
|
33
|
+
VERSION = '0.1'
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
### Parser class for __END__ data blocks.
|
|
37
|
+
### Find each __TOKEN__ within the __END__, and put each into a
|
|
38
|
+
### DATA_TOKEN constant within the namespace that included us.
|
|
39
|
+
###
|
|
40
|
+
class DataParser
|
|
41
|
+
|
|
42
|
+
# The mark for a DATA block.
|
|
43
|
+
#
|
|
44
|
+
END_TOKEN = /^__END__\r?\n/
|
|
45
|
+
|
|
46
|
+
# The mark for a 'sub' block.
|
|
47
|
+
#
|
|
48
|
+
CHUNK_TOKEN = /^__([A-Z\_0-9]+)__\r?\n/
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
### Constructor: Given a +klass+ and an +io+ to the class file,
|
|
52
|
+
### extract the data blocks and install constants.
|
|
53
|
+
###
|
|
54
|
+
def initialize( klass, io )
|
|
55
|
+
io.open if io.closed?
|
|
56
|
+
end_string = io.read.split( END_TOKEN, 2 ).last
|
|
57
|
+
|
|
58
|
+
@klass = klass
|
|
59
|
+
@scanner = StringScanner.new( end_string )
|
|
60
|
+
io.close
|
|
61
|
+
|
|
62
|
+
if @scanner.check_until( CHUNK_TOKEN )
|
|
63
|
+
# put each chunk into its own constant
|
|
64
|
+
self.extract_blocks
|
|
65
|
+
else
|
|
66
|
+
# no sub blocks, put the whole mess into DATA_END
|
|
67
|
+
@klass.const_set( :DATA_END, StringIO.new( end_string ) )
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
#########
|
|
73
|
+
protected
|
|
74
|
+
#########
|
|
75
|
+
|
|
76
|
+
### Parse the current +io+ for data blocks, set contents to
|
|
77
|
+
### IO constants in the including class.
|
|
78
|
+
###
|
|
79
|
+
def extract_blocks
|
|
80
|
+
label = nil
|
|
81
|
+
|
|
82
|
+
while @scanner.scan_until( CHUNK_TOKEN ) and ! @scanner.eos?
|
|
83
|
+
data = ''
|
|
84
|
+
|
|
85
|
+
# First pass, __END__ contents (until next token, instead
|
|
86
|
+
# of entire data block.)
|
|
87
|
+
#
|
|
88
|
+
if label.nil?
|
|
89
|
+
label = 'END'
|
|
90
|
+
data = @scanner.pre_match
|
|
91
|
+
|
|
92
|
+
@scanner.pos = self.next_position
|
|
93
|
+
else
|
|
94
|
+
label = @scanner[1]
|
|
95
|
+
|
|
96
|
+
if data = @scanner.scan_until( CHUNK_TOKEN )
|
|
97
|
+
# Pull the next token text out of the data, set up the next pass
|
|
98
|
+
#
|
|
99
|
+
data = data[ 0, data.length - @scanner[0].length ]
|
|
100
|
+
@scanner.pos = self.next_position
|
|
101
|
+
else
|
|
102
|
+
# No additional blocks
|
|
103
|
+
#
|
|
104
|
+
data = @scanner.rest
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
# Add the IO constant to the class that included me.
|
|
109
|
+
#
|
|
110
|
+
@klass.const_set( "DATA_#{label}".to_sym, StringIO.new( data ) )
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
### Return the next scanner position for searching.
|
|
116
|
+
###
|
|
117
|
+
def next_position
|
|
118
|
+
return @scanner.pos - @scanner[0].length
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
### Hook included: Find the file path for how we arrived here, and open
|
|
124
|
+
### it as an IO object. Parse the IO for data block tokens.
|
|
125
|
+
###
|
|
126
|
+
def self.included( klass )
|
|
127
|
+
# klass.instance_eval{ __FILE__ } awww, nope.
|
|
128
|
+
# __FILE__ won't work here, so we find the filename via caller().
|
|
129
|
+
#
|
|
130
|
+
io = File.open( caller(1).last.sub(/:.*?$/, ''), 'r' )
|
|
131
|
+
|
|
132
|
+
DataParser.new( klass, io )
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
BEGIN {
|
|
4
|
+
require 'pathname'
|
|
5
|
+
basedir = Pathname.new( __FILE__ ).dirname.parent
|
|
6
|
+
libdir = basedir + "lib"
|
|
7
|
+
|
|
8
|
+
$LOAD_PATH.unshift( libdir ) unless $LOAD_PATH.include?( libdir )
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
require 'chunker'
|
|
12
|
+
require 'rubygems'
|
|
13
|
+
require 'spec'
|
|
14
|
+
|
|
15
|
+
ENDSTUFF = <<ENDSTUFF
|
|
16
|
+
Stuff within the end block.
|
|
17
|
+
|
|
18
|
+
Content of the END block
|
|
19
|
+
Content of the END block
|
|
20
|
+
Content of the END block
|
|
21
|
+
Content of the END block
|
|
22
|
+
ENDSTUFF
|
|
23
|
+
|
|
24
|
+
HURGADURGA = <<HURGADURGA
|
|
25
|
+
|
|
26
|
+
Content of the HURGADURGA block
|
|
27
|
+
Content of the HURGADURGA block
|
|
28
|
+
Content of the HURGADURGA block
|
|
29
|
+
Content of the HURGADURGA block
|
|
30
|
+
|
|
31
|
+
HURGADURGA
|
|
32
|
+
|
|
33
|
+
HURRRRG = <<HURRRRG
|
|
34
|
+
123123123 123123123 123123123
|
|
35
|
+
123123123 123123123 123123123
|
|
36
|
+
123123123 123123123 123123123
|
|
37
|
+
HURRRRG
|
|
38
|
+
|
|
39
|
+
POOP = <<POOP
|
|
40
|
+
Content of the POOP block
|
|
41
|
+
POOP
|
|
42
|
+
|
|
43
|
+
FILE_TEXT = <<EO_FILE_TEXT
|
|
44
|
+
|
|
45
|
+
This is stuff we shouldn't see or care about.
|
|
46
|
+
You know, stuff like code, presumably.
|
|
47
|
+
|
|
48
|
+
__END__
|
|
49
|
+
#{ENDSTUFF}
|
|
50
|
+
EO_FILE_TEXT
|
|
51
|
+
|
|
52
|
+
FILE_TEXT_MULTIPLE = <<EO_FILE_TEXT
|
|
53
|
+
|
|
54
|
+
This is stuff we shouldn't see or care about.
|
|
55
|
+
You know, stuff like code, presumably.
|
|
56
|
+
|
|
57
|
+
__END__
|
|
58
|
+
#{ENDSTUFF}
|
|
59
|
+
__POOP__
|
|
60
|
+
#{POOP}
|
|
61
|
+
__HURRRRG__
|
|
62
|
+
#{HURRRRG}
|
|
63
|
+
__HURGADURGA__
|
|
64
|
+
#{HURGADURGA}
|
|
65
|
+
EO_FILE_TEXT
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
describe Chunker::DataParser do
|
|
69
|
+
|
|
70
|
+
it "doesn't include content above the __END__ token" do
|
|
71
|
+
klass = Class.new
|
|
72
|
+
dp = Chunker::DataParser.new( klass, StringIO.new( FILE_TEXT_MULTIPLE ))
|
|
73
|
+
dp.instance_variable_get( :@scanner ).string.
|
|
74
|
+
should_not =~ /This is stuff we shouldn't see/
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
it "doesn't contain the __END__ token itself" do
|
|
78
|
+
klass = Class.new
|
|
79
|
+
dp = Chunker::DataParser.new( klass, StringIO.new( FILE_TEXT ))
|
|
80
|
+
dp.instance_variable_get( :@scanner ).string.should_not =~ /^__END__/
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
describe 'A class that includes Chunker' do
|
|
86
|
+
|
|
87
|
+
it "has all content in DATA_END if there are no sub blocks" do
|
|
88
|
+
File.stub!( :open ).and_return( StringIO.new( FILE_TEXT ))
|
|
89
|
+
klass = Class.new { include Chunker }
|
|
90
|
+
|
|
91
|
+
klass.constants.should_not include( 'DATA_POOP' )
|
|
92
|
+
klass.constants.should_not include( 'DATA_HURRRRG' )
|
|
93
|
+
klass.constants.should_not include( 'DATA_HURGADURGA' )
|
|
94
|
+
klass.constants.should include( 'DATA_END' )
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
it "separates data sub blocks into individual constants" do
|
|
98
|
+
File.stub!( :open ).and_return( StringIO.new( FILE_TEXT_MULTIPLE ))
|
|
99
|
+
klass = Class.new { include Chunker }
|
|
100
|
+
|
|
101
|
+
klass.constants.should include( 'DATA_END' )
|
|
102
|
+
klass.constants.should include( 'DATA_POOP' )
|
|
103
|
+
klass.constants.should include( 'DATA_HURRRRG' )
|
|
104
|
+
klass.constants.should include( 'DATA_HURGADURGA' )
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
it "has IO constants that contain the data block contents" do
|
|
108
|
+
File.stub!( :open ).and_return( StringIO.new( FILE_TEXT_MULTIPLE ))
|
|
109
|
+
klass = Class.new { include Chunker }
|
|
110
|
+
|
|
111
|
+
klass.const_get( :DATA_END ).read.chomp.should == ENDSTUFF
|
|
112
|
+
klass.const_get( :DATA_POOP ).read.chomp.should == POOP
|
|
113
|
+
klass.const_get( :DATA_HURRRRG ).read.chomp.should == HURRRRG
|
|
114
|
+
klass.const_get( :DATA_HURGADURGA ).read.chomp.should == HURGADURGA
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
|
metadata
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: chunker
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.53
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Mahlon E. Smith
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
|
|
12
|
+
date: 2008-11-10 00:00:00 -08:00
|
|
13
|
+
default_executable:
|
|
14
|
+
dependencies: []
|
|
15
|
+
|
|
16
|
+
description: "Ruby provides an automatic constant called DATA, which is an IO object that references all text in the current file under an __END__ token. I find it convenient to use the __END__ area to store all sorts of stuff, rather than have to worry about distributing separate files. The DATA constant is determined from whatever ruby believes $0 to be. It doesn't work inside of other required libraries, so you'll see stuff like this all the time: END = File.open( __FILE__ ).read.split( /^__END__/, 2 ).last It works, but it's more work than I want to do. Chunker solves this by parsing __END__ tokens for you, and making it available in the form of a 'DATA_END' constant. It installs this constant into the class that includes Chunker, so you can use it again and again, assuming you use a different file for each class. It also automatically parses out other things that look like tokens, so you can easily have multiple, distinct documents all embedded into the __END__ block."
|
|
17
|
+
email: mahlon@martini.nu
|
|
18
|
+
executables: []
|
|
19
|
+
|
|
20
|
+
extensions: []
|
|
21
|
+
|
|
22
|
+
extra_rdoc_files: []
|
|
23
|
+
|
|
24
|
+
files:
|
|
25
|
+
- Rakefile
|
|
26
|
+
- README
|
|
27
|
+
- LICENSE
|
|
28
|
+
- lib/chunker.rb
|
|
29
|
+
- spec/chunker_spec.rb
|
|
30
|
+
has_rdoc: true
|
|
31
|
+
homepage: http://projects.martini.nu/ruby-modules/wiki/Chunker
|
|
32
|
+
post_install_message:
|
|
33
|
+
rdoc_options: []
|
|
34
|
+
|
|
35
|
+
require_paths:
|
|
36
|
+
- lib
|
|
37
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
38
|
+
requirements:
|
|
39
|
+
- - ">="
|
|
40
|
+
- !ruby/object:Gem::Version
|
|
41
|
+
version: "0"
|
|
42
|
+
version:
|
|
43
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - ">="
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: "0"
|
|
48
|
+
version:
|
|
49
|
+
requirements: []
|
|
50
|
+
|
|
51
|
+
rubyforge_project: mahlon
|
|
52
|
+
rubygems_version: 1.3.1
|
|
53
|
+
signing_key:
|
|
54
|
+
specification_version: 2
|
|
55
|
+
summary: A convenience library for parsing __END__ tokens consistently.
|
|
56
|
+
test_files:
|
|
57
|
+
- spec/chunker_spec.rb
|