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.
@@ -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
@@ -0,0 +1,4 @@
1
+ = TODO
2
+ 1. Supply formal unit tests.
3
+ 2. Provide XHTML weaving support.
4
+ 3. Design generic weaving framework.
@@ -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
+ }>>
@@ -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
+ }>>