rubigen 1.0.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.
Files changed (120) hide show
  1. data/History.txt +3 -0
  2. data/License.txt +17 -0
  3. data/Manifest.txt +119 -0
  4. data/README.txt +204 -0
  5. data/Rakefile +142 -0
  6. data/bin/ruby_app +12 -0
  7. data/examples/rails_generators/applications/app/USAGE +16 -0
  8. data/examples/rails_generators/applications/app/app_generator.rb +177 -0
  9. data/examples/rails_generators/components/controller/USAGE +29 -0
  10. data/examples/rails_generators/components/controller/controller_generator.rb +37 -0
  11. data/examples/rails_generators/components/controller/templates/controller.rb +10 -0
  12. data/examples/rails_generators/components/controller/templates/functional_test.rb +18 -0
  13. data/examples/rails_generators/components/controller/templates/helper.rb +2 -0
  14. data/examples/rails_generators/components/controller/templates/view.html.erb +2 -0
  15. data/examples/rails_generators/components/integration_test/USAGE +8 -0
  16. data/examples/rails_generators/components/integration_test/integration_test_generator.rb +16 -0
  17. data/examples/rails_generators/components/integration_test/templates/integration_test.rb +10 -0
  18. data/examples/rails_generators/components/mailer/USAGE +16 -0
  19. data/examples/rails_generators/components/mailer/mailer_generator.rb +34 -0
  20. data/examples/rails_generators/components/mailer/templates/fixture.erb +3 -0
  21. data/examples/rails_generators/components/mailer/templates/fixture.rhtml +0 -0
  22. data/examples/rails_generators/components/mailer/templates/mailer.rb +13 -0
  23. data/examples/rails_generators/components/mailer/templates/unit_test.rb +37 -0
  24. data/examples/rails_generators/components/mailer/templates/view.erb +3 -0
  25. data/examples/rails_generators/components/mailer/templates/view.rhtml +0 -0
  26. data/examples/rails_generators/components/migration/USAGE +24 -0
  27. data/examples/rails_generators/components/migration/migration_generator.rb +20 -0
  28. data/examples/rails_generators/components/migration/templates/migration.rb +7 -0
  29. data/examples/rails_generators/components/model/USAGE +27 -0
  30. data/examples/rails_generators/components/model/model_generator.rb +38 -0
  31. data/examples/rails_generators/components/model/templates/fixtures.yml +15 -0
  32. data/examples/rails_generators/components/model/templates/migration.rb +14 -0
  33. data/examples/rails_generators/components/model/templates/model.rb +2 -0
  34. data/examples/rails_generators/components/model/templates/unit_test.rb +10 -0
  35. data/examples/rails_generators/components/observer/USAGE +13 -0
  36. data/examples/rails_generators/components/observer/observer_generator.rb +16 -0
  37. data/examples/rails_generators/components/observer/templates/observer.rb +2 -0
  38. data/examples/rails_generators/components/observer/templates/unit_test.rb +10 -0
  39. data/examples/rails_generators/components/plugin/USAGE +25 -0
  40. data/examples/rails_generators/components/plugin/plugin_generator.rb +39 -0
  41. data/examples/rails_generators/components/plugin/templates/MIT-LICENSE +20 -0
  42. data/examples/rails_generators/components/plugin/templates/README +13 -0
  43. data/examples/rails_generators/components/plugin/templates/Rakefile +22 -0
  44. data/examples/rails_generators/components/plugin/templates/USAGE +8 -0
  45. data/examples/rails_generators/components/plugin/templates/generator.rb +8 -0
  46. data/examples/rails_generators/components/plugin/templates/init.rb +1 -0
  47. data/examples/rails_generators/components/plugin/templates/install.rb +1 -0
  48. data/examples/rails_generators/components/plugin/templates/plugin.rb +1 -0
  49. data/examples/rails_generators/components/plugin/templates/tasks.rake +4 -0
  50. data/examples/rails_generators/components/plugin/templates/uninstall.rb +1 -0
  51. data/examples/rails_generators/components/plugin/templates/unit_test.rb +8 -0
  52. data/examples/rails_generators/components/resource/USAGE +23 -0
  53. data/examples/rails_generators/components/resource/resource_generator.rb +72 -0
  54. data/examples/rails_generators/components/resource/templates/USAGE +18 -0
  55. data/examples/rails_generators/components/resource/templates/controller.rb +2 -0
  56. data/examples/rails_generators/components/resource/templates/fixtures.yml +0 -0
  57. data/examples/rails_generators/components/resource/templates/functional_test.rb +20 -0
  58. data/examples/rails_generators/components/resource/templates/helper.rb +2 -0
  59. data/examples/rails_generators/components/scaffold/USAGE +25 -0
  60. data/examples/rails_generators/components/scaffold/scaffold_generator.rb +90 -0
  61. data/examples/rails_generators/components/scaffold/templates/controller.rb +85 -0
  62. data/examples/rails_generators/components/scaffold/templates/functional_test.rb +57 -0
  63. data/examples/rails_generators/components/scaffold/templates/helper.rb +2 -0
  64. data/examples/rails_generators/components/scaffold/templates/layout.html.erb +17 -0
  65. data/examples/rails_generators/components/scaffold/templates/style.css +74 -0
  66. data/examples/rails_generators/components/scaffold/templates/view_edit.html.erb +19 -0
  67. data/examples/rails_generators/components/scaffold/templates/view_index.html.erb +24 -0
  68. data/examples/rails_generators/components/scaffold/templates/view_new.html.erb +18 -0
  69. data/examples/rails_generators/components/scaffold/templates/view_show.html.erb +10 -0
  70. data/examples/rails_generators/components/session_migration/USAGE +10 -0
  71. data/examples/rails_generators/components/session_migration/session_migration_generator.rb +18 -0
  72. data/examples/rails_generators/components/session_migration/templates/migration.rb +16 -0
  73. data/examples/rails_generators/components/web_service/USAGE +24 -0
  74. data/examples/rails_generators/components/web_service/templates/api_definition.rb +5 -0
  75. data/examples/rails_generators/components/web_service/templates/controller.rb +8 -0
  76. data/examples/rails_generators/components/web_service/templates/functional_test.rb +19 -0
  77. data/examples/rails_generators/components/web_service/web_service_generator.rb +29 -0
  78. data/lib/rubigen/base.rb +168 -0
  79. data/lib/rubigen/commands.rb +632 -0
  80. data/lib/rubigen/generated_attribute.rb +40 -0
  81. data/lib/rubigen/generators/applications/ruby_app/USAGE +10 -0
  82. data/lib/rubigen/generators/applications/ruby_app/ruby_app_generator.rb +78 -0
  83. data/lib/rubigen/generators/applications/ruby_app/templates/README.txt +1 -0
  84. data/lib/rubigen/generators/applications/ruby_app/templates/configs/empty.log +0 -0
  85. data/lib/rubigen/generators/applications/ruby_app/templates/fresh_rakefile +10 -0
  86. data/lib/rubigen/generators/applications/ruby_app/templates/module.rb +5 -0
  87. data/lib/rubigen/generators/applications/ruby_app/templates/script/generate +13 -0
  88. data/lib/rubigen/generators/applications/ruby_app/templates/test_helper.rb +2 -0
  89. data/lib/rubigen/generators/components/test_unit/USAGE +14 -0
  90. data/lib/rubigen/generators/components/test_unit/templates/test +14 -0
  91. data/lib/rubigen/generators/components/test_unit/test_unit_generator.rb +26 -0
  92. data/lib/rubigen/helpers/generator_test_helper.rb +133 -0
  93. data/lib/rubigen/lookup.rb +296 -0
  94. data/lib/rubigen/manifest.rb +51 -0
  95. data/lib/rubigen/options.rb +136 -0
  96. data/lib/rubigen/scripts/destroy.rb +27 -0
  97. data/lib/rubigen/scripts/generate.rb +7 -0
  98. data/lib/rubigen/scripts/update.rb +12 -0
  99. data/lib/rubigen/scripts.rb +69 -0
  100. data/lib/rubigen/simple_logger.rb +44 -0
  101. data/lib/rubigen/spec.rb +42 -0
  102. data/lib/rubigen/version.rb +9 -0
  103. data/lib/rubigen.rb +44 -0
  104. data/script/destroy +9 -0
  105. data/script/generate +9 -0
  106. data/script/txt2html +65 -0
  107. data/setup.rb +1585 -0
  108. data/test/examples_from_rails/generator_test_helper.rb +195 -0
  109. data/test/examples_from_rails/test_rails_resource_generator.rb +106 -0
  110. data/test/examples_from_rails/test_rails_scaffold_generator.rb +185 -0
  111. data/test/test_generate_builtin_application.rb +24 -0
  112. data/test/test_generate_builtin_test_unit.rb +22 -0
  113. data/test/test_helper.rb +33 -0
  114. data/test/test_lookup.rb +103 -0
  115. data/website/index.html +352 -0
  116. data/website/index.txt +252 -0
  117. data/website/javascripts/rounded_corners_lite.inc.js +285 -0
  118. data/website/stylesheets/screen.css +138 -0
  119. data/website/template.rhtml +44 -0
  120. metadata +183 -0
@@ -0,0 +1,136 @@
1
+ require 'optparse'
2
+
3
+ module RubiGen
4
+ module Options
5
+ def self.included(base)
6
+ base.extend(ClassMethods)
7
+ class << base
8
+ if respond_to?(:inherited)
9
+ alias_method :inherited_without_options, :inherited
10
+ end
11
+ alias_method :inherited, :inherited_with_options
12
+ end
13
+ end
14
+
15
+ module ClassMethods
16
+ def inherited_with_options(sub)
17
+ inherited_without_options(sub) if respond_to?(:inherited_without_options)
18
+ sub.extend(RubiGen::Options::ClassMethods)
19
+ end
20
+
21
+ def mandatory_options(options = nil)
22
+ if options
23
+ write_inheritable_attribute(:mandatory_options, options)
24
+ else
25
+ read_inheritable_attribute(:mandatory_options) or write_inheritable_attribute(:mandatory_options, {})
26
+ end
27
+ end
28
+
29
+ def default_options(options = nil)
30
+ if options
31
+ write_inheritable_attribute(:default_options, options)
32
+ else
33
+ read_inheritable_attribute(:default_options) or write_inheritable_attribute(:default_options, {})
34
+ end
35
+ end
36
+
37
+ # Merge together our class options. In increasing precedence:
38
+ # default_options (class default options)
39
+ # runtime_options (provided as argument)
40
+ # mandatory_options (class mandatory options)
41
+ def full_options(runtime_options = {})
42
+ default_options.merge(runtime_options).merge(mandatory_options)
43
+ end
44
+
45
+ end
46
+
47
+ # Each instance has an options hash that's populated by #parse.
48
+ def options
49
+ @options ||= {}
50
+ end
51
+ attr_writer :options
52
+
53
+ protected
54
+ # Convenient access to class mandatory options.
55
+ def mandatory_options
56
+ self.class.mandatory_options
57
+ end
58
+
59
+ # Convenient access to class default options.
60
+ def default_options
61
+ self.class.default_options
62
+ end
63
+
64
+ # Merge together our instance options. In increasing precedence:
65
+ # default_options (class default options)
66
+ # options (instance options)
67
+ # runtime_options (provided as argument)
68
+ # mandatory_options (class mandatory options)
69
+ def full_options(runtime_options = {})
70
+ self.class.full_options(options.merge(runtime_options))
71
+ end
72
+
73
+ # Parse arguments into the options hash. Classes may customize
74
+ # parsing behavior by overriding these methods:
75
+ # #banner Usage: ./script/generate [options]
76
+ # #add_options! Options:
77
+ # some options..
78
+ # #add_general_options! General Options:
79
+ # general options..
80
+ def parse!(args, runtime_options = {})
81
+ self.options = {}
82
+
83
+ @option_parser = OptionParser.new do |opt|
84
+ opt.banner = banner
85
+ add_options!(opt)
86
+ add_general_options!(opt)
87
+ opt.parse!(args)
88
+ end
89
+
90
+ return args
91
+ ensure
92
+ self.options = full_options(runtime_options)
93
+ end
94
+
95
+ # Raise a usage error. Override usage_message to provide a blurb
96
+ # after the option parser summary.
97
+ def usage(message = usage_message)
98
+ raise UsageError, "#{@option_parser}\n#{message}"
99
+ end
100
+
101
+ def usage_message
102
+ ''
103
+ end
104
+
105
+ # Override with your own usage banner.
106
+ def banner
107
+ "Usage: #{$0} [options]"
108
+ end
109
+
110
+ # Override to add your options to the parser:
111
+ # def add_options!(opt)
112
+ # opt.on('-v', '--verbose') { |value| options[:verbose] = value }
113
+ # end
114
+ def add_options!(opt)
115
+ end
116
+
117
+ # Adds general options like -h and --quiet. Usually don't override.
118
+ def add_general_options!(opt)
119
+ opt.separator 'General Options:'
120
+
121
+ opt.on('-h', '--help', 'Show this help message and quit.') { |v| options[:help] = v }
122
+ opt.on('-p', '--pretend', 'Run but do not make any changes.') { |v| options[:pretend] = v }
123
+ opt.on('-f', '--force', 'Overwrite files that already exist.') { options[:collision] = :force }
124
+ opt.on('-s', '--skip', 'Skip files that already exist.') { options[:collision] = :skip }
125
+ opt.on('-q', '--quiet', 'Suppress normal output.') { |v| options[:quiet] = v }
126
+ opt.on('-t', '--backtrace', 'Debugging: show backtrace on errors.') { |v| options[:backtrace] = v }
127
+ opt.on('-c', '--svn', 'Modify files with subversion. (Note: svn must be in path)') do
128
+ options[:svn] = `svn status`.inject({}) do |opt, e|
129
+ opt[e.chomp[7..-1]] = true
130
+ opt
131
+ end
132
+ end
133
+ end
134
+
135
+ end
136
+ end
@@ -0,0 +1,27 @@
1
+ require File.dirname(__FILE__) + '/../scripts'
2
+
3
+ module RubiGen::Scripts
4
+ class Destroy < Base
5
+ mandatory_options :command => :destroy
6
+
7
+ protected
8
+ def usage_message
9
+ usage = "\nInstalled Generators\n"
10
+ RubiGen::Base.sources.each do |source|
11
+ label = source.label.to_s.capitalize
12
+ names = source.names
13
+ usage << " #{label}: #{names.join(', ')}\n" unless names.empty?
14
+ end
15
+
16
+ usage << <<-end_blurb
17
+
18
+ This script will destroy all files created by the corresponding
19
+ script/generate command. For instance, script/destroy test_unit create_post
20
+ will delete the appropriate test_create_post.rb file in /test.
21
+
22
+ For instructions on finding new generators, run script/generate
23
+ end_blurb
24
+ return usage
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,7 @@
1
+ require File.dirname(__FILE__) + '/../scripts'
2
+
3
+ module RubiGen::Scripts
4
+ class Generate < Base
5
+ mandatory_options :command => :create
6
+ end
7
+ end
@@ -0,0 +1,12 @@
1
+ require File.dirname(__FILE__) + '/../scripts'
2
+
3
+ module RubiGen::Scripts
4
+ class Update < Base
5
+ mandatory_options :command => :update
6
+
7
+ protected
8
+ def banner
9
+ "Usage: #{$0} [options] scaffold"
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,69 @@
1
+ require File.dirname(__FILE__) + '/options'
2
+
3
+ module RubiGen
4
+ module Scripts
5
+
6
+ # Generator scripts handle command-line invocation. Each script
7
+ # responds to an invoke! class method which handles option parsing
8
+ # and generator invocation.
9
+ class Base
10
+ include Options
11
+ default_options :collision => :ask, :quiet => false
12
+
13
+ # Run the generator script. Takes an array of unparsed arguments
14
+ # and a hash of parsed arguments, takes the generator as an option
15
+ # or first remaining argument, and invokes the requested command.
16
+ def run(args = [], runtime_options = {})
17
+ begin
18
+ parse!(args.dup, runtime_options)
19
+ rescue OptionParser::InvalidOption => e
20
+ # Don't cry, script. Generators want what you think is invalid.
21
+ end
22
+
23
+ # Generator name is the only required option.
24
+ unless options[:generator]
25
+ usage if args.empty?
26
+ options[:generator] ||= args.shift
27
+ end
28
+
29
+ # Look up generator instance and invoke command on it.
30
+ RubiGen::Base.instance(options[:generator], args, options).command(options[:command]).invoke!
31
+ rescue => e
32
+ puts e
33
+ puts " #{e.backtrace.join("\n ")}\n" if options[:backtrace]
34
+ raise SystemExit
35
+ end
36
+
37
+ protected
38
+ # Override with your own script usage banner.
39
+ def banner
40
+ "Usage: #{$0} generator [options] [args]"
41
+ end
42
+
43
+ def usage_message
44
+ usage = "\nInstalled Generators\n"
45
+ RubiGen::Base.sources.inject({}) do |mem, source|
46
+ label = source.label.to_s.capitalize
47
+ mem[label] ||= []
48
+ mem[label] |= source.names
49
+ mem
50
+ end.each_pair do |label, names|
51
+ usage << " #{label}: #{names.join(', ')}\n" unless names.empty?
52
+ end
53
+
54
+ usage << <<-end_blurb
55
+
56
+ More are available at http://rubigen.rubyforge.org/
57
+ end_blurb
58
+
59
+ usage << <<-end_blurb
60
+ Run generate with no arguments for usage information
61
+ #{$0} test_unit
62
+
63
+ end_blurb
64
+ return usage
65
+ end
66
+ end # Base
67
+
68
+ end
69
+ end
@@ -0,0 +1,44 @@
1
+ module RubiGen
2
+ class SimpleLogger # :nodoc:
3
+ attr_reader :out
4
+ attr_accessor :quiet
5
+
6
+ def initialize(out = $stdout)
7
+ @out = out
8
+ @quiet = false
9
+ @level = 0
10
+ end
11
+
12
+ def log(status, message, &block)
13
+ @out.print("%12s %s%s\n" % [status, ' ' * @level, message]) unless quiet
14
+ indent(&block) if block_given?
15
+ end
16
+
17
+ def indent(&block)
18
+ @level += 1
19
+ if block_given?
20
+ begin
21
+ block.call
22
+ ensure
23
+ outdent
24
+ end
25
+ end
26
+ end
27
+
28
+ def outdent
29
+ @level -= 1
30
+ if block_given?
31
+ begin
32
+ block.call
33
+ ensure
34
+ indent
35
+ end
36
+ end
37
+ end
38
+
39
+ private
40
+ def method_missing(method, *args, &block)
41
+ log(method.to_s, args.first, &block)
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,42 @@
1
+ module RubiGen
2
+ # A spec knows where a generator was found and how to instantiate it.
3
+ # Metadata include the generator's name, its base path, and the source
4
+ # which yielded it (PathSource, GemPathSource, etc.)
5
+ class Spec
6
+ attr_reader :name, :path, :source
7
+
8
+ def initialize(name, path, source)
9
+ @name, @path, @source = name, path, source
10
+ end
11
+
12
+ # Look up the generator class. Require its class file, find the class
13
+ # in ObjectSpace, tag it with this spec, and return.
14
+ def klass
15
+ unless @klass
16
+ require class_file
17
+ @klass = lookup_class
18
+ @klass.spec = self
19
+ end
20
+ @klass
21
+ end
22
+
23
+ def class_file
24
+ "#{path}/#{name}_generator.rb"
25
+ end
26
+
27
+ def class_name
28
+ "#{name.camelize}Generator"
29
+ end
30
+
31
+ private
32
+ # Search for the first Class descending from RubiGen::Base
33
+ # whose name matches the requested class name.
34
+ def lookup_class
35
+ ObjectSpace.each_object(Class) do |obj|
36
+ return obj if obj.ancestors.include?(RubiGen::Base) and
37
+ obj.name.split('::').last == class_name
38
+ end
39
+ raise NameError, "Missing #{class_name} class in #{class_file}"
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,9 @@
1
+ module Rubigen #:nodoc:
2
+ module VERSION #:nodoc:
3
+ MAJOR = 1
4
+ MINOR = 0
5
+ TINY = 0
6
+
7
+ STRING = [MAJOR, MINOR, TINY].join('.')
8
+ end
9
+ end
data/lib/rubigen.rb ADDED
@@ -0,0 +1,44 @@
1
+ #--
2
+ # Copyright (c) 2004 Jeremy Kemper
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ #++
23
+
24
+ $:.unshift(File.dirname(__FILE__))
25
+
26
+ begin
27
+ require 'active_support'
28
+ rescue LoadError
29
+ require 'rubygems'
30
+ gem 'activesupport'
31
+ require 'active_support'
32
+ end
33
+
34
+ require 'rubigen/base'
35
+ require 'rubigen/lookup'
36
+ require 'rubigen/commands'
37
+
38
+ RubiGen::Base.send(:include, RubiGen::Lookup)
39
+ RubiGen::Base.send(:include, RubiGen::Commands)
40
+
41
+ # Set up a default logger for convenience.
42
+ require 'rubigen/simple_logger'
43
+ RubiGen::Base.logger = RubiGen::SimpleLogger.new(STDOUT)
44
+
data/script/destroy ADDED
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env ruby
2
+ APP_ROOT = File.join(File.dirname(__FILE__), '..')
3
+
4
+ require File.join(File.dirname(__FILE__), %w[.. lib rubigen])
5
+ require 'rubigen/scripts/destroy'
6
+
7
+ ARGV.shift if ['--help', '-h'].include?(ARGV[0])
8
+ RubiGen::Base.use_component_sources! :rubygems, :newgem
9
+ RubiGen::Scripts::Destroy.new.run(ARGV)
data/script/generate ADDED
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env ruby
2
+ APP_ROOT = File.join(File.dirname(__FILE__), '..')
3
+
4
+ require File.join(File.dirname(__FILE__), %w[.. lib rubigen])
5
+ require 'rubigen/scripts/generate'
6
+
7
+ ARGV.shift if ['--help', '-h'].include?(ARGV[0])
8
+ RubiGen::Base.use_component_sources! :rubygems, :newgem
9
+ RubiGen::Scripts::Generate.new.run(ARGV)
data/script/txt2html ADDED
@@ -0,0 +1,65 @@
1
+ #!/usr/bin/env ruby
2
+ require 'rubygems'
3
+ begin
4
+ require 'newgem'
5
+ rescue LoadError
6
+ puts "\n\nGenerating the website requires the newgem RubyGem"
7
+ puts "Install: gem install newgem\n\n"
8
+ exit(1)
9
+ end
10
+ require 'redcloth'
11
+ require 'syntax/convertors/html'
12
+ require 'erb'
13
+ require File.dirname(__FILE__) + '/../lib/rubigen/version.rb'
14
+ version = Rubigen::VERSION::STRING
15
+ download = 'http://rubyforge.org/projects/rubigen'
16
+ class Fixnum
17
+ def ordinal
18
+ # teens
19
+ return 'th' if (10..19).include?(self % 100)
20
+ # others
21
+ case self % 10
22
+ when 1: return 'st'
23
+ when 2: return 'nd'
24
+ when 3: return 'rd'
25
+ else return 'th'
26
+ end
27
+ end
28
+ end
29
+ class Time
30
+ def pretty
31
+ return "#{mday}#{mday.ordinal} #{strftime('%B')} #{year}"
32
+ end
33
+ end
34
+ def convert_syntax(syntax, source)
35
+ return Syntax::Convertors::HTML.for_syntax(syntax).convert(source).gsub(%r!^<pre>|</pre>$!,'')
36
+ end
37
+ if ARGV.length >= 1
38
+ src, template = ARGV
39
+ template ||= File.join(File.dirname(__FILE__), '/../website/template.rhtml')
40
+
41
+ else
42
+ puts("Usage: #{File.split($0).last} source.txt [template.rhtml] > output.html")
43
+ exit!
44
+ end
45
+ template = ERB.new(File.open(template).read)
46
+ title = nil
47
+ body = nil
48
+ File.open(src) do |fsrc|
49
+ title_text = fsrc.readline
50
+ body_text = fsrc.read
51
+ syntax_items = []
52
+ body_text.gsub!(%r!<(pre|code)[^>]*?syntax=['"]([^'"]+)[^>]*>(.*?)</\1>!m){
53
+ ident = syntax_items.length
54
+ element, syntax, source = $1, $2, $3
55
+ syntax_items << "<#{element} class='syntax'>#{convert_syntax(syntax, source)}</#{element}>"
56
+ "syntax-temp-#{ident}"
57
+ }
58
+ title = RedCloth.new(title_text).to_html.gsub(%r!<.*?>!,'').strip
59
+ body = RedCloth.new(body_text).to_html
60
+ body.gsub!(%r!(?:<pre><code>)?syntax-temp-(\d+)(?:</code></pre>)?!){ syntax_items[$1.to_i] }
61
+ end
62
+ stat = File.stat(src)
63
+ created = stat.ctime
64
+ modified = stat.mtime
65
+ $stdout << template.result(binding)