rweb 0.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/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
|
+
}>>
|