#!/usr/bin/ruby -w # # Generates a project scaffold using the given information. # # Existing files are backed up and NOT overwritten. It is your # responsibility to merge changes between the existing files and # the newly generated files. See the --merge option for details. # # This tool announces its progress as it runs, using these indicators: # # create: A file is being created because it does not exist. # # skip: A file is being skipped because it is already up to date. # # update: A file will be updated because it is out of date. A text # merging tool (see the "--merger" option) will be launched to # transfer content from the old file (*.old) and the new file # (*.new) to the out of date file. If a text merging tool is # not specified, then you will have to do the merging by hand. # # Usage: # # inochi [Options] ProjectName [ProgramName] # # # ProjectName: Name of your project, which will be normalized # into the naame of a Ruby module that will serve # as a namespace for all code in your project. # # ProgramName: (Optional) Name of the main project executable, # which also serves as the name of the generated # project directory and the main project library. # # # Options: # # command line require File.join(File.dirname(__FILE__), '..', 'lib', 'inochi') @options = Inochi.main :Inochi do opt :merger, 'A command that invokes a text merging tool with three arguments: (1) old file, (2) new file, (3) output file. The command should write the result of merging the old file and the new file to the output file. The command may only modify the output file; it must NOT modify the old file or the new file.', :type => :string end # utility logic require 'fileutils' require 'digest/sha1' # Notify the user about some action being performed. def notify *args # :nodoc: printf "%8s %s\n", *args end # Writes the given contents to the file at the given path. If the given path # already exists, then a backup is created before invoking the merging tool. def create path, body, merger = @options[:merger] # remove leading space body = body.to_s data = body.strip.gsub(/^#{body[/^[ \t]*(?=\S)/]}/, '') << "\n" if File.exist? path old_digest = Digest::SHA1.digest(File.read(path)) new_digest = Digest::SHA1.digest(data) if old_digest == new_digest notify :skip, path else notify :update, path cur, old, new = path, "#{path}.old", "#{path}.new" FileUtils.cp cur, old, :preserve => true File.write new, data system merger, old, new, cur if merger end else notify :create, path FileUtils.mkdir_p File.dirname(path) File.write path, data end end # program body project_name, program_name = ARGV unless project_name raise ArgumentError, "ProjectName must be given. Run `#{$0} -h` for help." end project_symbol = Inochi.calc_project_symbol(project_name) program_name ||= Inochi.calc_program_name(project_symbol) project_version = '0.0.0' project_release = Time.now.strftime('%F') inochi_preamble = %{ require 'rubygems' gem '#{Inochi::PROGRAM}', '#{Inochi::VERSION.requirement}' require '#{Inochi::PROGRAM}' }.strip create "#{program_name}/LICENSE", %{ Copyright #{Time.now.year} Your Name Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. } create "#{program_name}/Rakefile", %{ #{inochi_preamble} Inochi.rake #{project_symbol.inspect} do |gem| # TODO: additional gem configuration. # NOTE: this is completely optional! # # gem.extensions = ['foo.so'] # gem.files += ['other', 'files'] end } bin_file = "#{program_name}/bin/#{program_name}" create bin_file, %{ #!/usr/bin/ruby -w # # TODO: Explain the command-line usage of this program here. # # # Usage: # # #{program_name} [Options] Param1 Param2 Param3... # # # Param1: Description for the first parameter. # # Param2: Description for the second parameter. # # Param3: Description for the third parameter. # # # Options: # #{inochi_preamble} options = Inochi.main #{project_symbol.inspect} do # TODO: define command-line options here. # see http://trollop.rubyforge.org/ # # NOTE: this is completely optional! end # TODO: add the body of your program here puts "Command-line options: \#{options.inspect}" puts "Command-line arguments: \#{ARGV.inspect}" } FileUtils.chmod 0755, bin_file create "#{program_name}/lib/#{program_name}.rb", %{ #{inochi_preamble} Inochi.init #{project_symbol.inspect}, :project => '#{project_name}', :version => '#{project_version}', :release => '#{project_release}', :website => 'http://#{program_name}.rubyforge.org', :tagline => 'TODO: put a single line description of your project here.', :require => { # TODO: list gems required by your project here. # NOTE: this is completely optional! # # example: if your project needs version 9.9.9 of the 'foo' gem: # 'foo' => '9.9.9', # # example: if any version of a gem is acceptable then: # 'foo' => nil, } } create "#{program_name}/test/#{program_name}.rb", %{ describe #{project_symbol} do it 'has inochi' do assert #{project_symbol}.const_defined? :INOCHI #{project_symbol}::INOCHI.each do |param, value| const = param.to_s.upcase assert #{project_symbol}.const_defined? const #{project_symbol}.const_get(const).must_equal value end end end } create "#{program_name}/doc/index.erb", %{ <% Inochi.book #{project_symbol.inspect}, self %> <%# include intro.erb #%> <%# include setup.erb #%> <%# include theory.erb #%> <%# include usage.erb #%> <%# include history.erb #%> } create "#{program_name}/doc/intro.erb", %{ <% chapter "Introduction" do %> <% project_summary do %> > TODO: explain the purpose of your project **<%= $project %>** is a __________ that __________. <% end %> > TODO: explain why your project is important **<%= $project %>** is exciting because: * It lets you __________. * Its core contains less than __________ lines of code. * It __________. > TODO: explain why your project is better than its competitors These features distinguish **<%= $project %>** from the competition: * [competitor 1](http://) * [competitor 2](http://) * [competitor 3](http://) <% paragraph "Etymology" do %> > TODO: explain the meaning of the name of your project <% end %> <% section "Logistics" do %> * <%= xref "History", "Release notes" %> --- history of project releases. * [Source code](http://github.com/#{ENV['USER']}/<%= $program %>) --- obtain via [Git](http://git.or.cz) or browse online. * [API reference](api/index.html) --- documentation for source code. To get help or provide feedback, simply <%= xref "License", "contact the author(s)" %>. <% paragraph "Version numbers" do %> **<%= $project %>** releases are numbered in *major.minor.patch* form according to the [RubyGems rational versioning policy](http://www.rubygems.org/read/chapter/7), which can be summarized thus:
What increased in the version number? The increase indicates that the release:
Is backward compatible? Has new features? Has bug fixes?
major No Yes Yes
minor Yes Yes Yes
patch Yes No Yes
<% end %> <% end %> <% section "License" do %> <%# include ../LICENSE #%> <% end %> <% section "Credits" do %> > TODO: give attribution to your predecessors and contributors <% end %> <% end %> } create "#{program_name}/doc/setup.erb", %{ <% chapter "Setup" do %> <% section "Requirements" do %> Your system needs the following software to run **<%= $project %>**. | Software | Description | Notes | | -------- | ----------- | ----- | | [Ruby](http://ruby-lang.org) | Ruby language interpreter | Version #{RUBY_VERSION} is required. | | [RubyGems](http://rubygems.org) | Ruby packaging system | Version #{Gem::RubyGemsVersion} is required. | <% end %> <% section "Installation" do %> You can install **<%= $project %>** by running this command: gem install <%= $program %> To check whether the installation was sucessful, run this command: <%= $program %> --version If the installation was successful, you will see output like this:
<%= verbatim `ruby bin/\#{$program} --version` %>
If you do not see such output, you may <%= xref "License", "ask the author(s)" %> for help. <% end %> <% section "Manifest" do %> You will see the following items inside **<%= $project %>**'s installation directory, whose path you can determine by running this command: <%= $program %> --version > TODO: list important files your project provides here * bin/ * <%= $program %> --- the main **<%= $project %>** executable. * lib/ * <%= $program %>.rb --- the main **<%= $project %>** library. * <%= $program %>/ > TODO: list sub-libraries your project provides here * doc/ * api/ --- API reference documentation. * index.erb --- source of this user manual. * LICENSE --- copyright notice and legal conditions. <% end %> <% end %> } create "#{program_name}/doc/theory.erb", %{ <% chapter "Theory of operation" do %> > TODO: explain how your project does what it does <% end %> } create "#{program_name}/doc/usage.erb", %{ <% chapter "Usage" do %> <% section "Command-line interface" do %> When you run this command: <%= $program %> --help You will see this output:
<%= verbatim `ruby bin/\#{$program_name} --help` %>
> TODO: explain the command-line arguments <% end %> <% section "Ruby library interface" do %> > TODO: explain how to use your project's Ruby library > from inside another Ruby program or library <% end %> <% section "Tutorial" do %> This tutorial shows how **<%= $project %>** is used to __________. > TODO: give examples for doing common tasks <% end %> > TODO: explain how to do more (advanced) things <% end %> } create "#{program_name}/doc/history.erb", %{ <% chapter "History" do %> > TODO: put a brief history about your project here <% project_history do %> > TODO: put release notes for your project > here -- newest first, oldest last. <% section "Version #{project_version} (#{project_release})" do %> > TODO: write a short summary of the changes in this release This release changes __________, adds __________, and fixes __________. <% paragraph "Contributor kudos" do %> > TODO: list everyone who contributed to this > release and what their contribution was * __________ contributed __________ which __________. * __________ fixed __________ which __________. * __________ added __________ which __________. <% end %> <% paragraph "Incompatible changes" do %> > TODO: list all backward-incompatible changes in this release * __________ has been __________ to __________. * __________. * __________. <% end %> <% paragraph "New features" do %> > TODO: list new features added in this release * __________. * __________. * __________. <% end %> <% paragraph "Bug fixes" do %> > TODO: describe all bugs that are fixed in this release * __________ was __________. * __________ were __________. * __________ did __________. <% end %> <% paragraph "Housekeeping" do %> > TODO: list the refactorings, clean ups, and other > improvements that were done for this release * __________. * __________. * __________. <% end %> <% end %> <% end %> <% end %> }