rweb 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/COPYING +316 -0
- data/Changes.rdoc +5 -0
- data/README.rdoc +132 -0
- data/Rakefile +249 -0
- data/TODO.rdoc +4 -0
- data/bin/rtangle +115 -0
- data/bin/rweave +115 -0
- data/docs/rtangle.txt +90 -0
- data/docs/rweave.txt +90 -0
- data/lib/rweb.rb +233 -0
- data/tests/tc_rweb.rb +57 -0
- metadata +62 -0
data/Rakefile
ADDED
@@ -0,0 +1,249 @@
|
|
1
|
+
# Rakefile
|
2
|
+
require "rake/testtask"
|
3
|
+
require "rake/clean"
|
4
|
+
require "rake/rdoctask"
|
5
|
+
require "rake/gempackagetask"
|
6
|
+
#---
|
7
|
+
# The name of your project
|
8
|
+
PROJECT = "RWEB"
|
9
|
+
|
10
|
+
# Your name, used in packaging.
|
11
|
+
MY_NAME = "Michael T. Richter"
|
12
|
+
|
13
|
+
# Your email address, used in packaging.
|
14
|
+
MY_EMAIL = "ttmrichter@gmail.com"
|
15
|
+
|
16
|
+
# Short summary of your project, used in packaging.
|
17
|
+
PROJECT_SUMMARY = "Self-executing WEB-like literate programming for Ruby."
|
18
|
+
|
19
|
+
# The project's package name (as opposed to its display name). Used for
|
20
|
+
# RubyForge connectivity and packaging.
|
21
|
+
UNIX_NAME = "rweb"
|
22
|
+
|
23
|
+
# Your RubyForge user name.
|
24
|
+
RUBYFORGE_USER = ENV["RUBYFORGE_USER"] || "mtr1966"
|
25
|
+
|
26
|
+
# Directory on RubyForge where your website's files should be uploaded.
|
27
|
+
WEBSITE_DIR = "rweb"
|
28
|
+
|
29
|
+
# Output directory for the rdoc html files.
|
30
|
+
# If you don't have a custom homepage, and want to use the RDoc
|
31
|
+
# index.html as homepage, just set it to WEBSITE_DIR.
|
32
|
+
RDOC_HTML_DIR = "#{WEBSITE_DIR}/rdoc"
|
33
|
+
#---
|
34
|
+
# Variable settings for extension support.
|
35
|
+
EXT_DIR = "ext"
|
36
|
+
HAVE_EXT = File.directory?(EXT_DIR)
|
37
|
+
EXTCONF_FILES = FileList["#{EXT_DIR}/**/extconf.rb"]
|
38
|
+
EXT_SOURCES = FileList["#{EXT_DIR}/**/*.{c,h}"]
|
39
|
+
# Eventually add other files from EXT_DIR, like "MANIFEST"
|
40
|
+
EXT_DIST_FILES = EXT_SOURCES + EXTCONF_FILES
|
41
|
+
#---
|
42
|
+
REQUIRE_PATHS = ["lib"]
|
43
|
+
REQUIRE_PATHS << EXT_DIR if HAVE_EXT
|
44
|
+
$LOAD_PATH.concat(REQUIRE_PATHS)
|
45
|
+
# This library file defines the MyProject::VERSION constant.
|
46
|
+
require "#{UNIX_NAME}"
|
47
|
+
PROJECT_VERSION = eval("#{PROJECT}::VERSION") # e.g. "1.0.2"
|
48
|
+
#---
|
49
|
+
# Clobber object files and Makefiles generated by extconf.rb.
|
50
|
+
CLOBBER.include("#{EXT_DIR}/**/*.{so,dll,o}", "#{EXT_DIR}/**/Makefile")
|
51
|
+
# Clobber .config generated by setup.rb.
|
52
|
+
CLOBBER.include(".config")
|
53
|
+
#---
|
54
|
+
# Options common to RDocTask AND Gem::Specification.
|
55
|
+
# The --main argument specifies which file appears on the index.html page
|
56
|
+
GENERAL_RDOC_OPTS = {
|
57
|
+
"--title" => "#{PROJECT} API documentation",
|
58
|
+
"--main" => "README.rdoc"
|
59
|
+
}
|
60
|
+
|
61
|
+
# Additional RDoc formatted files, besides the Ruby source files.
|
62
|
+
RDOC_FILES = FileList["README.rdoc", "Changes.rdoc", "TODO.rdoc"]
|
63
|
+
# Remove the following line if you don't want to extract RDoc from
|
64
|
+
# the extension C sources.
|
65
|
+
RDOC_FILES.include(EXT_SOURCES)
|
66
|
+
|
67
|
+
# Ruby library code.
|
68
|
+
LIB_FILES = FileList["lib/**/*.rb"]
|
69
|
+
|
70
|
+
# Filelist with Test::Unit test cases.
|
71
|
+
TEST_FILES = FileList["tests/**/tc_*.rb"]
|
72
|
+
|
73
|
+
# Executable scripts, all non-garbage files under bin/.
|
74
|
+
BIN_FILES = FileList["bin/*"]
|
75
|
+
|
76
|
+
# This filelist is used to create source packages.
|
77
|
+
# Include all Ruby and RDoc files.
|
78
|
+
DIST_FILES = FileList["**/*.rb", "**/*.rdoc"]
|
79
|
+
DIST_FILES.include("Rakefile", "COPYING")
|
80
|
+
DIST_FILES.include(BIN_FILES)
|
81
|
+
DIST_FILES.include("data/**/*", "test/data/**/*")
|
82
|
+
DIST_FILES.include("#{WEBSITE_DIR}/**/*.{html,css}", "man/*.[0-9]")
|
83
|
+
# Don't package files which are autogenerated by RDocTask
|
84
|
+
DIST_FILES.exclude(/^(\.\/)?#{RDOC_HTML_DIR}(\/|$)/)
|
85
|
+
# Include extension source files.
|
86
|
+
DIST_FILES.include(EXT_DIST_FILES)
|
87
|
+
# Don't package temporary files, perhaps created by tests.
|
88
|
+
DIST_FILES.exclude("**/temp_*", "**/*.tmp")
|
89
|
+
# Don't get into recursion...
|
90
|
+
DIST_FILES.exclude(/^(\.\/)?pkg(\/|$)/)
|
91
|
+
# Don't bring in our DARCS tree.
|
92
|
+
DIST_FILES.exclude(/^(\.\/)?_darcs(\/|$)/)
|
93
|
+
# Include our documentation/sample files.
|
94
|
+
DIST_FILES.include("docs/**/*")
|
95
|
+
#---
|
96
|
+
# Run the tests if rake is invoked without arguments.
|
97
|
+
task "default" => ["test"]
|
98
|
+
|
99
|
+
test_task_name = HAVE_EXT ? "run-tests" : "test"
|
100
|
+
Rake::TestTask.new(test_task_name) do |t|
|
101
|
+
t.test_files = TEST_FILES
|
102
|
+
t.libs = REQUIRE_PATHS
|
103
|
+
end
|
104
|
+
#---
|
105
|
+
# Set an environment variable with any configuration options you want to
|
106
|
+
# be passed through to "setup.rb config".
|
107
|
+
CONFIG_OPTS = ENV["CONFIG"]
|
108
|
+
if HAVE_EXT
|
109
|
+
file_create ".config" do
|
110
|
+
ruby "setup.rb config #{CONFIG_OPTS}"
|
111
|
+
end
|
112
|
+
|
113
|
+
desc "Configure and make extension. " +
|
114
|
+
"The CONFIG variable is passed to `setup.rb config'"
|
115
|
+
task "make-ext" => ".config" do
|
116
|
+
# The -q option suppresses messages from setup.rb.
|
117
|
+
ruby "setup.rb -q setup"
|
118
|
+
end
|
119
|
+
|
120
|
+
desc "Run tests after making the extension."
|
121
|
+
task "test" do
|
122
|
+
Rake::Task["make-ext"].invoke
|
123
|
+
Rake::Task["run-tests"].invoke
|
124
|
+
end
|
125
|
+
end
|
126
|
+
#---
|
127
|
+
# The "rdoc" task generates API documentation.
|
128
|
+
Rake::RDocTask.new("rdoc") do |t|
|
129
|
+
t.rdoc_files = RDOC_FILES + LIB_FILES
|
130
|
+
t.title = GENERAL_RDOC_OPTS["--title"]
|
131
|
+
t.main = GENERAL_RDOC_OPTS["--main"]
|
132
|
+
t.rdoc_dir = RDOC_HTML_DIR
|
133
|
+
end
|
134
|
+
#---
|
135
|
+
GEM_SPEC = Gem::Specification.new do |s|
|
136
|
+
s.name = UNIX_NAME
|
137
|
+
s.version = PROJECT_VERSION
|
138
|
+
s.summary = PROJECT_SUMMARY
|
139
|
+
s.rubyforge_project = UNIX_NAME
|
140
|
+
s.homepage = "http://#{UNIX_NAME}.rubyforge.org/"
|
141
|
+
s.author = MY_NAME
|
142
|
+
s.email = MY_EMAIL
|
143
|
+
s.files = DIST_FILES
|
144
|
+
s.test_files = TEST_FILES
|
145
|
+
s.executables = BIN_FILES.map { |fn| File.basename(fn) }
|
146
|
+
s.has_rdoc = true
|
147
|
+
s.extra_rdoc_files = RDOC_FILES
|
148
|
+
s.rdoc_options = GENERAL_RDOC_OPTS.to_a.flatten
|
149
|
+
if HAVE_EXT
|
150
|
+
s.extensions = EXTCONF_FILES
|
151
|
+
s.require_paths << EXT_DIR
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
# Now we can generate the package-related tasks.
|
156
|
+
Rake::GemPackageTask.new(GEM_SPEC) do |pkg|
|
157
|
+
pkg.need_zip = true
|
158
|
+
pkg.need_tar = true
|
159
|
+
end
|
160
|
+
#---
|
161
|
+
desc "Upload website to RubyForge. " +
|
162
|
+
"scp will prompt for your RubyForge password."
|
163
|
+
task "publish-website" => ["rdoc"] do
|
164
|
+
rubyforge_path = "/var/www/gforge-projects/#{UNIX_NAME}/"
|
165
|
+
sh "scp -r #{WEBSITE_DIR}/* " +
|
166
|
+
"#{RUBYFORGE_USER}@rubyforge.org:#{rubyforge_path}",
|
167
|
+
:verbose => true
|
168
|
+
end
|
169
|
+
#---
|
170
|
+
task "rubyforge-setup" do
|
171
|
+
unless File.exist?(File.join(ENV["HOME"], ".rubyforge"))
|
172
|
+
puts "rubyforge will ask you to edit its config.yml now."
|
173
|
+
puts "Please set the `username' and `password' entries"
|
174
|
+
puts "to your RubyForge username and RubyForge password!"
|
175
|
+
puts "Press ENTER to continue."
|
176
|
+
$stdin.gets
|
177
|
+
sh "rubyforge setup", :verbose => true
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
task "rubyforge-login" => ["rubyforge-setup"] do
|
182
|
+
# Note: We assume that username and password were set in
|
183
|
+
# rubyforge's config.yml.
|
184
|
+
sh "rubyforge login", :verbose => true
|
185
|
+
end
|
186
|
+
|
187
|
+
task "publish-packages" => ["package", "rubyforge-login"] do
|
188
|
+
# Upload packages under pkg/ to RubyForge
|
189
|
+
# This task makes some assumptions:
|
190
|
+
# * You have already created a package on the "Files" tab on the
|
191
|
+
# RubyForge project page. See pkg_name variable below.
|
192
|
+
# * You made entries under package_ids and group_ids for this
|
193
|
+
# project in rubyforge's config.yml. If not, eventually read
|
194
|
+
# "rubyforge --help" and then run "rubyforge setup".
|
195
|
+
pkg_name = ENV["PKG_NAME"] || UNIX_NAME
|
196
|
+
cmd = "rubyforge add_release #{UNIX_NAME} #{pkg_name} " +
|
197
|
+
"#{PROJECT_VERSION} #{UNIX_NAME}-#{PROJECT_VERSION}"
|
198
|
+
cd "pkg" do
|
199
|
+
sh(cmd + ".gem", :verbose => true)
|
200
|
+
sh(cmd + ".tgz", :verbose => true)
|
201
|
+
sh(cmd + ".zip", :verbose => true)
|
202
|
+
end
|
203
|
+
end
|
204
|
+
#---
|
205
|
+
# The "prepare-release" task makes sure your tests run, and then generates
|
206
|
+
# files for a new release.
|
207
|
+
desc "Run tests, generate RDoc and create packages."
|
208
|
+
task "prepare-release" => ["clobber"] do
|
209
|
+
puts "Preparing release of #{PROJECT} version #{VERSION}"
|
210
|
+
Rake::Task["test"].invoke
|
211
|
+
Rake::Task["rdoc"].invoke
|
212
|
+
Rake::Task["package"].invoke
|
213
|
+
end
|
214
|
+
|
215
|
+
# The "publish" task is the overarching task for the whole project. It
|
216
|
+
# builds a release and then publishes it to RubyForge.
|
217
|
+
desc "Publish new release of #{PROJECT}"
|
218
|
+
task "publish" => ["prepare-release"] do
|
219
|
+
puts "Uploading documentation..."
|
220
|
+
Rake::Task["publish-website"].invoke
|
221
|
+
puts "Checking for rubyforge command..."
|
222
|
+
`rubyforge --help`
|
223
|
+
if $? == 0
|
224
|
+
puts "Uploading packages..."
|
225
|
+
Rake::Task["publish-packages"].invoke
|
226
|
+
puts "Release done!"
|
227
|
+
else
|
228
|
+
puts "Can't invoke rubyforge command."
|
229
|
+
puts "Either install rubyforge with 'gem install rubyforge'"
|
230
|
+
puts "and retry or upload the package files manually!"
|
231
|
+
end
|
232
|
+
end
|
233
|
+
=begin
|
234
|
+
#---
|
235
|
+
$ rake -T
|
236
|
+
rake clean # Remove any temporary products.
|
237
|
+
rake clobber # Remove any generated file.
|
238
|
+
rake clobber_package # Remove package products
|
239
|
+
rake clobber_rdoc # Remove rdoc products
|
240
|
+
rake package # Build all the packages
|
241
|
+
rake prepare-release # Run tests, generate RDoc and create packages.
|
242
|
+
rake publish # Publish new release of MyProject
|
243
|
+
rake publish-website # Upload website to RubyForge. scp will prompt for your RubyForge password.
|
244
|
+
rake rdoc # Build the rdoc HTML Files
|
245
|
+
rake repackage # Force a rebuild of the package files
|
246
|
+
rake rerdoc # Force a rebuild of the RDOC files
|
247
|
+
rake test # Run tests for test
|
248
|
+
#---
|
249
|
+
=end
|
data/TODO.rdoc
ADDED
data/bin/rtangle
ADDED
@@ -0,0 +1,115 @@
|
|
1
|
+
#! /usr/bin/ruby -w
|
2
|
+
|
3
|
+
# RTANGLE -- External tangling tool for literate Ruby.
|
4
|
+
# Copyright (C) 2007 Michael T. Richter <ttmrichter@gmail.com>
|
5
|
+
#
|
6
|
+
# This program is free software; you can redistribute it and/or modify
|
7
|
+
# it under the terms of the GNU General Public License as published by
|
8
|
+
# the Free Software Foundation; Version 2, June 1991 (and no other).
|
9
|
+
#
|
10
|
+
# This program is distributed in the hope that it will be useful,
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
# GNU General Public License for more details.
|
14
|
+
#
|
15
|
+
# You should have received a copy of the GNU General Public License
|
16
|
+
# along with this program (in the file COPYING); if not, write to the Free
|
17
|
+
# Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
|
18
|
+
# USA
|
19
|
+
|
20
|
+
require 'rubygems'
|
21
|
+
require 'rweb'
|
22
|
+
|
23
|
+
eval RWEB.tangle(DATA)
|
24
|
+
|
25
|
+
__END__
|
26
|
+
{title => RTANGLE}
|
27
|
+
|
28
|
+
This is a simple utility that acts as a wrapper around RWEB's tangle and,
|
29
|
+
instead of executing the resulting code, either prints it to stdout or saves it
|
30
|
+
to a given file. Note that RTangle is itself written in RWEB's executable format
|
31
|
+
with the boilerplate before the __END__ statement and the actual program
|
32
|
+
document afterwards.
|
33
|
+
|
34
|
+
The mainline code is quite simple:
|
35
|
+
|
36
|
+
<< {
|
37
|
+
{<<global requires>>}
|
38
|
+
|
39
|
+
{<<command line processing>>}
|
40
|
+
|
41
|
+
{<<tangling>>}
|
42
|
+
|
43
|
+
{<<main>>}
|
44
|
+
}>>
|
45
|
+
|
46
|
+
The only require we need to introduce is to require RWEB itself. This is not, of
|
47
|
+
course, necessary if we execute the RWEB document directly. Since, however, it
|
48
|
+
is highly likely that we may at some point wish to tangle the RTangle utility
|
49
|
+
itself into a Ruby source file, we should, pro forma, require the library
|
50
|
+
anyway.
|
51
|
+
|
52
|
+
<< global requires {
|
53
|
+
require 'rweb'
|
54
|
+
}>>
|
55
|
+
|
56
|
+
The tangling stage itself is a very simple function which takes any kind of IO
|
57
|
+
object for input, tangles it, then places the resulting string into the output,
|
58
|
+
itself an IO object of any kind. It also doesn't care in the slightest exactly
|
59
|
+
what kind of IO object is being used, thus suited to application as a filter in
|
60
|
+
a potentially longer chain of tools.
|
61
|
+
|
62
|
+
<< tangling {
|
63
|
+
def rtangle(io_in, io_out)
|
64
|
+
io_out << RWEB.tangle(io_in)
|
65
|
+
end
|
66
|
+
}>>
|
67
|
+
|
68
|
+
As can be seen, the true heavy lifting is done inside of the RWEB module. This
|
69
|
+
utility is a hyper-simple shell around it by comparison.
|
70
|
+
|
71
|
+
The mainline function is pretty simple as well. It just takes the arguments from
|
72
|
+
the command line and passes them to the command line processor blindly,
|
73
|
+
accepting in return a pair of IO objects -- one for input, the other for output.
|
74
|
+
It then calls tangle with these objects, wrapping in a begin/ensure clause to
|
75
|
+
make sure the IO objects are closed before exiting. The only additional step it
|
76
|
+
takes is a call to the function find_block_begin which shadows the IO object
|
77
|
+
used for input and silently sweeps away the stuff before __END__ in a document
|
78
|
+
if it exists in the first 20 lines.
|
79
|
+
|
80
|
+
<< main {
|
81
|
+
io_in, io_out = process_argv ARGV
|
82
|
+
begin
|
83
|
+
rtangle(io_in, io_out)
|
84
|
+
ensure
|
85
|
+
io_in.close
|
86
|
+
io_out.close
|
87
|
+
end
|
88
|
+
}>>
|
89
|
+
|
90
|
+
All that's left is the command line processor.
|
91
|
+
|
92
|
+
<< command line processing {
|
93
|
+
def process_argv args
|
94
|
+
io_in = STDIN
|
95
|
+
io_out = STDOUT
|
96
|
+
if args.length > 2
|
97
|
+
{<<display usage>>}
|
98
|
+
end
|
99
|
+
arg = args.shift
|
100
|
+
io_in = File.open(arg, "r") if arg
|
101
|
+
arg = args.shift
|
102
|
+
io_out = File.open(arg, "w") if arg
|
103
|
+
return io_in, io_out
|
104
|
+
end
|
105
|
+
}>>
|
106
|
+
|
107
|
+
The usage message is straightforward and broken out only to reduce code clutter.
|
108
|
+
|
109
|
+
<< display usage {
|
110
|
+
puts "Incorrect command line."
|
111
|
+
puts "Usage:"
|
112
|
+
puts " rtangle [input_file [output_file]]"
|
113
|
+
puts
|
114
|
+
puts "Files default to stdin and stdout respectively."
|
115
|
+
}>>
|
data/bin/rweave
ADDED
@@ -0,0 +1,115 @@
|
|
1
|
+
#! /usr/bin/ruby -w
|
2
|
+
|
3
|
+
# RWEAVE -- External weaving tool for literate Ruby.
|
4
|
+
# Copyright (C) 2007 Michael T. Richter <ttmrichter@gmail.com>
|
5
|
+
#
|
6
|
+
# This program is free software; you can redistribute it and/or modify
|
7
|
+
# it under the terms of the GNU General Public License as published by
|
8
|
+
# the Free Software Foundation; Version 2, June 1991 (and no other).
|
9
|
+
#
|
10
|
+
# This program is distributed in the hope that it will be useful,
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
# GNU General Public License for more details.
|
14
|
+
#
|
15
|
+
# You should have received a copy of the GNU General Public License
|
16
|
+
# along with this program (in the file COPYING.txt); if not, write to the Free
|
17
|
+
# Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
|
18
|
+
# USA
|
19
|
+
|
20
|
+
require 'rubygems'
|
21
|
+
require 'rweb'
|
22
|
+
|
23
|
+
eval RWEB.tangle(DATA)
|
24
|
+
|
25
|
+
__END__
|
26
|
+
{title => RWEAVE}
|
27
|
+
|
28
|
+
This is a simple utility that acts as a wrapper around RWEB's weave and, instead
|
29
|
+
of executing the resulting code, either prints it to stdout or saves it to a
|
30
|
+
given file. Note that RWeave is itself written in RWEB's executable format with
|
31
|
+
the boilerplate before the __END__ statement and the actual program document
|
32
|
+
afterwards.
|
33
|
+
|
34
|
+
The mainline code is quite simple:
|
35
|
+
|
36
|
+
<< {
|
37
|
+
{<<global requires>>}
|
38
|
+
|
39
|
+
{<<command line processing>>}
|
40
|
+
|
41
|
+
{<<weaving>>}
|
42
|
+
|
43
|
+
{<<main>>}
|
44
|
+
}>>
|
45
|
+
|
46
|
+
The only require we need to introduce is to require RWEB itself. This is not, of
|
47
|
+
course, necessary if we execute the RWEB document directly. Since, however, it
|
48
|
+
is highly likely that we may at some point wish to weave the RWeave utility
|
49
|
+
itself into a Ruby source file, we should, pro forma, require the library
|
50
|
+
anyway.
|
51
|
+
|
52
|
+
<< global requires {
|
53
|
+
require 'rweb'
|
54
|
+
}>>
|
55
|
+
|
56
|
+
The weaving stage itself is a very simple function which takes any kind of IO
|
57
|
+
object for input, weaves it, then places the resulting string into the output,
|
58
|
+
itself an IO object of any kind. It also doesn't care in the slightest exactly
|
59
|
+
what kind of IO object is being used, thus suited to application as a filter in
|
60
|
+
a potentially longer chain of tools.
|
61
|
+
|
62
|
+
<< weaving {
|
63
|
+
def rweave(io_in, io_out)
|
64
|
+
io_out << RWEB.weave(io_in)
|
65
|
+
end
|
66
|
+
}>>
|
67
|
+
|
68
|
+
As can be seen, the true heavy lifting is done inside of the RWEB module. This
|
69
|
+
utility is a hyper-simple shell around it by comparison.
|
70
|
+
|
71
|
+
The mainline function is pretty simple as well. It just takes the arguments from
|
72
|
+
the command line and passes them to the command line processor blindly,
|
73
|
+
accepting in return a pair of IO objects -- one for input, the other for output.
|
74
|
+
It then calls weave with these objects, wrapping in a begin/ensure clause to
|
75
|
+
make sure the IO objects are closed before exiting. The only additional step it
|
76
|
+
takes is a call to the function find_block_begin which shadows the IO object
|
77
|
+
used for input and silently sweeps away the stuff before __END__ in a document
|
78
|
+
if it exists in the first 20 lines.
|
79
|
+
|
80
|
+
<< main {
|
81
|
+
io_in, io_out = process_argv ARGV
|
82
|
+
begin
|
83
|
+
rweave(io_in, io_out)
|
84
|
+
ensure
|
85
|
+
io_in.close
|
86
|
+
io_out.close
|
87
|
+
end
|
88
|
+
}>>
|
89
|
+
|
90
|
+
All that's left is the command line processor.
|
91
|
+
|
92
|
+
<< command line processing {
|
93
|
+
def process_argv args
|
94
|
+
io_in = STDIN
|
95
|
+
io_out = STDOUT
|
96
|
+
if args.length > 2
|
97
|
+
{<<display usage>>}
|
98
|
+
end
|
99
|
+
arg = args.shift
|
100
|
+
io_in = File.open(arg, "r") if arg
|
101
|
+
arg = args.shift
|
102
|
+
io_out = File.open(arg, "w") if arg
|
103
|
+
return io_in, io_out
|
104
|
+
end
|
105
|
+
}>>
|
106
|
+
|
107
|
+
The usage message is straightforward and broken out only to reduce code clutter.
|
108
|
+
|
109
|
+
<< display usage {
|
110
|
+
puts "Incorrect command line."
|
111
|
+
puts "Usage:"
|
112
|
+
puts " rweave [input_file [output_file]]"
|
113
|
+
puts
|
114
|
+
puts "Files default to stdin and stdout respectively."
|
115
|
+
}>>
|