#!/usr/bin/env ruby # # Generates a project scaffold using the given information. # # Existing files are backed up and NOT overwritten. It is your # responsibility to merge changes (see the --merger option) # between the existing files and the newly generated files. # # 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 is being 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 name 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: # #-- # Copyright protects this work. # See LICENSE file for details. #++ # 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 direct the result of merging the old file and the new file to the output file. In addition, the command *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}/CREDITS", %{ * Contributor name * [Contributor name with hyperlink](http://the.contributor's.url) * Another contributor * Yet another contributor } create "#{program_name}/LICENSE", %{ (the ISC 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/env ruby # # 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 => 'put a single line description of your project here', :require => { # TODO: list gems required by your project during runtime 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, }, :develop => { # TODO: list gems required by your project during development 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", %{ unless #{project_symbol}.const_defined? :INOCHI fail "#{project_symbol} must be established by Inochi" end #{project_symbol}::INOCHI.each do |param, value| const = param.to_s.upcase unless #{project_symbol}.const_defined? const fail "#{project_symbol}::\#{const} must be established by Inochi" end unless #{project_symbol}.const_get(const) == value fail "#{project_symbol}::\#{const} is not what Inochi established" end end puts "Inochi establishment tests passed!" } create "#{program_name}/doc/index.erb", %{ % Inochi.book #{project_symbol.inspect}, self %+ "intro.erb" %+ "setup.erb" %+ "theory.erb" %+ "usage.erb" %+ "history.erb" } create "#{program_name}/doc/intro.erb", %{ % api_url = './api/index.html' % src_url = "http://github.com/__________/\#{$program}" % src_scm = '[Git](http://git-scm.com)' %|chapter "Introduction" %|project > TODO: explain the purpose of your project <%= $project %> is a __________ that __________. * <%= xref "History", "What's new?" %> --- history of project releases. * [Source code](<%= src_url %>) --- obtain via <%= src_scm %> or browse online. * [API reference](<%= api_url %>) --- documentation for source code. * [Project home](<%= $website %>) --- the <%= $project %> project home page. To get help or provide feedback, simply %= xref "License", "contact the author(s)." %|section "Features" > TODO: explain why your project is important <%= $project %> is exciting because: * It lets you __________. * Its core contains less than __________ lines of code. * It __________. %|section "Etymology" > TODO: explain the meaning of the name of your project %|section "License" %< "../LICENSE" %|section "Credits" > TODO: give attribution to your predecessors and contributors %= $project is made possible by %= xref "History", "contributions" from users like you: %< "../CREDITS" %|section "Related works" > TODO: list other projects which are similar to yours * [project 1](http://) * [project 2](http://) * [project 3](http://) } create "#{program_name}/doc/setup.erb", %{ %|chapter "Setup" %|section "Requirements" Your system needs the following software to run <%= $project %>. | Software | Description | Notes | | -------- | ----------- | ----- | | [Ruby](http://ruby-lang.org) | Ruby language interpreter | Version #{RUBY_VERSION} has been tested successfully. | | [RubyGems](http://rubygems.org) | Ruby packaging system | Version #{Gem::RubyGemsVersion} or newer is required. | %|section "Installation" 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. %|section "Package contents" 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. * lang/ --- translations of language phrases. * LICENSE --- copyright notice and legal conditions. * CREDITS --- attribution of project contributors. %|section "Version numbers" <%= $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 as follows:
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
} create "#{program_name}/doc/theory.erb", %{ %|chapter "Theory of operation" > TODO: explain how your project does what it does } create "#{program_name}/doc/usage.erb", %{ %|chapter "Usage" %|section "Command-line interface" When you run this command: <%= $program %> --help You will see this output:
<%= verbatim `ruby bin/\#{$program} --help` %>
> TODO: explain the command-line arguments %|section "Ruby library interface" > TODO: explain how to use your project's Ruby library > from inside another Ruby program or library %|section "General walkthrough" This tutorial walks you through the typical usage of <%= $project %>. > TODO: give examples for doing common tasks %|section "Specific topics" > TODO: explain how to do more advanced / specific things } create "#{program_name}/doc/history.erb", %{ %|chapter "History" > TODO: put a brief history about your project here %|history > TODO: put release notes for your project > here -- newest first, oldest last. %|section "Version #{project_version} (#{project_release})" > TODO: write a short summary of the changes in this release This release changes __________, adds __________, and fixes __________. %|paragraph "Thank you" > TODO: list everyone who contributed to this release * __________ contributed __________ * __________ suggested __________ * __________ helped to __________ %|paragraph "Incompatible changes" > TODO: list all backward-incompatible changes in this release * __________ has been __________ to __________ ---contributor name * __________ ---contributor name * __________ ---contributor name %|paragraph "New features" > TODO: list new features added in this release * __________ ---contributor name * __________ ---contributor name * __________ ---contributor name %|paragraph "Bug fixes" > TODO: describe all bugs that are fixed in this release * __________ was __________ ---contributor name * __________ were __________ ---contributor name * __________ did __________ ---contributor name %|paragraph "Housekeeping" > TODO: list the refactorings, clean ups, and other > improvements that were done for this release * __________ ---contributor name * __________ ---contributor name * __________ ---contributor name }