summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAntonio Terceiro <terceiro@debian.org>2011-08-29 18:03:57 -0700
committergit-ubuntu importer <ubuntu-devel-discuss@lists.ubuntu.com>2011-09-01 09:28:30 +0000
commit96fbf829bff6815b6fd68fa42773c969edea2606 (patch)
tree53cc129e018c8b7bb87113149b932827c494ef0f
Imported using git-ubuntu import.
Notes
Notes:
-rw-r--r--COPYING674
-rw-r--r--COPYING.LESSER165
-rw-r--r--ChangeLog0
-rw-r--r--README55
-rw-r--r--Rakefile205
-rw-r--r--TODO10
-rw-r--r--VERSION1
-rw-r--r--debian/changelog74
-rw-r--r--debian/compat1
-rw-r--r--debian/control49
-rw-r--r--debian/copyright26
-rw-r--r--debian/ruby-cmdparse.docs6
-rw-r--r--debian/ruby-cmdparse.examples1
-rw-r--r--debian/ruby-cmdparse.links1
-rw-r--r--debian/ruby-tests.rb7
-rwxr-xr-xdebian/rules15
-rw-r--r--debian/source/format1
-rw-r--r--debian/source/lintian-overrides2
-rw-r--r--debian/watch2
-rw-r--r--doc/config.yaml2
-rw-r--r--doc/plugin/extract.rb29
-rw-r--r--doc/src/about.page28
-rw-r--r--doc/src/default.css151
-rw-r--r--doc/src/default.template43
-rw-r--r--doc/src/download.page34
-rw-r--r--doc/src/features.page11
-rw-r--r--doc/src/index.page80
-rw-r--r--doc/src/logo.pngbin0 -> 12456 bytes
-rw-r--r--doc/src/meta.info5
-rw-r--r--doc/src/tutorial.page177
-rw-r--r--lib/cmdparse.rb450
-rw-r--r--lib/cmdparse/wrappers/optparse.rb63
-rw-r--r--metadata.yml87
-rw-r--r--net.rb88
-rw-r--r--setup.rb1331
35 files changed, 3874 insertions, 0 deletions
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..94a9ed0
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ <program> Copyright (C) <year> <name of author>
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
diff --git a/COPYING.LESSER b/COPYING.LESSER
new file mode 100644
index 0000000..65c5ca8
--- /dev/null
+++ b/COPYING.LESSER
@@ -0,0 +1,165 @@
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+
+ This version of the GNU Lesser General Public License incorporates
+the terms and conditions of version 3 of the GNU General Public
+License, supplemented by the additional permissions listed below.
+
+ 0. Additional Definitions.
+
+ As used herein, "this License" refers to version 3 of the GNU Lesser
+General Public License, and the "GNU GPL" refers to version 3 of the GNU
+General Public License.
+
+ "The Library" refers to a covered work governed by this License,
+other than an Application or a Combined Work as defined below.
+
+ An "Application" is any work that makes use of an interface provided
+by the Library, but which is not otherwise based on the Library.
+Defining a subclass of a class defined by the Library is deemed a mode
+of using an interface provided by the Library.
+
+ A "Combined Work" is a work produced by combining or linking an
+Application with the Library. The particular version of the Library
+with which the Combined Work was made is also called the "Linked
+Version".
+
+ The "Minimal Corresponding Source" for a Combined Work means the
+Corresponding Source for the Combined Work, excluding any source code
+for portions of the Combined Work that, considered in isolation, are
+based on the Application, and not on the Linked Version.
+
+ The "Corresponding Application Code" for a Combined Work means the
+object code and/or source code for the Application, including any data
+and utility programs needed for reproducing the Combined Work from the
+Application, but excluding the System Libraries of the Combined Work.
+
+ 1. Exception to Section 3 of the GNU GPL.
+
+ You may convey a covered work under sections 3 and 4 of this License
+without being bound by section 3 of the GNU GPL.
+
+ 2. Conveying Modified Versions.
+
+ If you modify a copy of the Library, and, in your modifications, a
+facility refers to a function or data to be supplied by an Application
+that uses the facility (other than as an argument passed when the
+facility is invoked), then you may convey a copy of the modified
+version:
+
+ a) under this License, provided that you make a good faith effort to
+ ensure that, in the event an Application does not supply the
+ function or data, the facility still operates, and performs
+ whatever part of its purpose remains meaningful, or
+
+ b) under the GNU GPL, with none of the additional permissions of
+ this License applicable to that copy.
+
+ 3. Object Code Incorporating Material from Library Header Files.
+
+ The object code form of an Application may incorporate material from
+a header file that is part of the Library. You may convey such object
+code under terms of your choice, provided that, if the incorporated
+material is not limited to numerical parameters, data structure
+layouts and accessors, or small macros, inline functions and templates
+(ten or fewer lines in length), you do both of the following:
+
+ a) Give prominent notice with each copy of the object code that the
+ Library is used in it and that the Library and its use are
+ covered by this License.
+
+ b) Accompany the object code with a copy of the GNU GPL and this license
+ document.
+
+ 4. Combined Works.
+
+ You may convey a Combined Work under terms of your choice that,
+taken together, effectively do not restrict modification of the
+portions of the Library contained in the Combined Work and reverse
+engineering for debugging such modifications, if you also do each of
+the following:
+
+ a) Give prominent notice with each copy of the Combined Work that
+ the Library is used in it and that the Library and its use are
+ covered by this License.
+
+ b) Accompany the Combined Work with a copy of the GNU GPL and this license
+ document.
+
+ c) For a Combined Work that displays copyright notices during
+ execution, include the copyright notice for the Library among
+ these notices, as well as a reference directing the user to the
+ copies of the GNU GPL and this license document.
+
+ d) Do one of the following:
+
+ 0) Convey the Minimal Corresponding Source under the terms of this
+ License, and the Corresponding Application Code in a form
+ suitable for, and under terms that permit, the user to
+ recombine or relink the Application with a modified version of
+ the Linked Version to produce a modified Combined Work, in the
+ manner specified by section 6 of the GNU GPL for conveying
+ Corresponding Source.
+
+ 1) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (a) uses at run time
+ a copy of the Library already present on the user's computer
+ system, and (b) will operate properly with a modified version
+ of the Library that is interface-compatible with the Linked
+ Version.
+
+ e) Provide Installation Information, but only if you would otherwise
+ be required to provide such information under section 6 of the
+ GNU GPL, and only to the extent that such information is
+ necessary to install and execute a modified version of the
+ Combined Work produced by recombining or relinking the
+ Application with a modified version of the Linked Version. (If
+ you use option 4d0, the Installation Information must accompany
+ the Minimal Corresponding Source and Corresponding Application
+ Code. If you use option 4d1, you must provide the Installation
+ Information in the manner specified by section 6 of the GNU GPL
+ for conveying Corresponding Source.)
+
+ 5. Combined Libraries.
+
+ You may place library facilities that are a work based on the
+Library side by side in a single library together with other library
+facilities that are not Applications and are not covered by this
+License, and convey such a combined library under terms of your
+choice, if you do both of the following:
+
+ a) Accompany the combined library with a copy of the same work based
+ on the Library, uncombined with any other library facilities,
+ conveyed under the terms of this License.
+
+ b) Give prominent notice with the combined library that part of it
+ is a work based on the Library, and explaining where to find the
+ accompanying uncombined form of the same work.
+
+ 6. Revised Versions of the GNU Lesser General Public License.
+
+ The Free Software Foundation may publish revised and/or new versions
+of the GNU Lesser General Public License from time to time. Such new
+versions will be similar in spirit to the present version, but may
+differ in detail to address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Library as you received it specifies that a certain numbered version
+of the GNU Lesser General Public License "or any later version"
+applies to it, you have the option of following the terms and
+conditions either of that published version or of any later version
+published by the Free Software Foundation. If the Library as you
+received it does not specify a version number of the GNU Lesser
+General Public License, you may choose any version of the GNU Lesser
+General Public License ever published by the Free Software Foundation.
+
+ If the Library as you received it specifies that a proxy can decide
+whether future versions of the GNU Lesser General Public License shall
+apply, that proxy's public statement of acceptance of any version is
+permanent authorization for you to choose that version for the
+Library.
diff --git a/ChangeLog b/ChangeLog
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/ChangeLog
diff --git a/README b/README
new file mode 100644
index 0000000..959b368
--- /dev/null
+++ b/README
@@ -0,0 +1,55 @@
+cmdparse - an advanced command line parser using optparse which has support for commands
+
+Copyright (C) 2004-2010 Thomas Leitner
+
+= Description
+
+Some new programs use a "command style" command line. Examples for such programs are the "svn"
+program from Subversion and the "gem" program from Rubygems. The standard Ruby distribution has no
+library to create programs that use such a command line interface.
+
+This library, cmdparse, can be used to create such a command line interface. Internally it uses
+optparse or any other option parser library to parse options and it provides a nice API for
+specifying commands.
+
+= License
+
+GNU LGPLv3 - see COPYING.LESSER for the LGPL and COPYING for the GPL
+
+= Dependencies
+
+ none
+
+= Installation
+
+The preferred way of installing cmdparse is via RubyGems:
+ $ gem install cmdparse
+
+If you do not have RubyGems installed, but Rake, you can use the following command:
+ $ rake install
+
+If you have neither RubyGems nor Rake, use these commands:
+ $ ruby setup.rb config
+ $ ruby setup.rb setup
+ $ ruby setup.rb install
+
+= Documentation
+
+You can build the documentation by invoking
+ $ rake doc
+
+This builds the API and the additional documentation. The additional documentation needs webgen
+>=0.3.5 (webgen.rubyforge.org) for building.
+
+
+= Example
+
+There is an example of how to use cmdparse in the +net.rb+ file.
+
+
+= Contact
+
+Author: Thomas Leitner
+* Web: http://cmdparse.rubyforge.org
+* e-Mail: t_leitner@gmx.at
+* GPG Key-Id: 0xD942E7F6
diff --git a/Rakefile b/Rakefile
new file mode 100644
index 0000000..4f5f5ca
--- /dev/null
+++ b/Rakefile
@@ -0,0 +1,205 @@
+# -*- ruby -*-
+#
+#--
+# cmdparse: advanced command line parser supporting commands
+# Copyright (C) 2004-2010 Thomas Leitner
+#
+# This file is part of cmdparse.
+#
+# cmdparse is free software: you can redistribute it and/or modify it under the terms of the GNU
+# Lesser General Public License as published by the Free Software Foundation, either version 3 of
+# the License, or (at your option) any later version.
+#
+# cmdparse is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+# the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+# General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License along with cmdparse. If
+# not, see <http://www.gnu.org/licenses/>.
+#
+#++
+
+
+begin
+ require 'rubygems'
+ require 'rake/gempackagetask'
+rescue Exception
+ nil
+end
+
+require 'rake/clean'
+require 'rake/packagetask'
+require 'rake/rdoctask'
+require 'rake/testtask'
+
+# General actions ##############################################################
+
+$:.unshift 'lib'
+require 'cmdparse'
+
+PKG_NAME = "cmdparse"
+PKG_VERSION = CmdParse::VERSION.join( '.' )
+PKG_FULLNAME = PKG_NAME + "-" + PKG_VERSION
+
+SRC_RB = FileList['lib/**/*.rb']
+
+# The default task is run if rake is given no explicit arguments.
+
+desc "Default Task"
+task :default => :test
+
+
+# End user tasks ################################################################
+
+desc "Prepares for installation"
+task :prepare do
+ ruby "setup.rb config"
+ ruby "setup.rb setup"
+end
+
+
+desc "Installs the package #{PKG_NAME}"
+task :install => [:prepare]
+task :install do
+ ruby "setup.rb install"
+end
+
+
+task :clean do
+ ruby "setup.rb clean"
+end
+
+task :test do
+ ruby "-Ilib test/tc_commandhash.rb"
+end
+
+CLOBBER << "doc/output"
+desc "Builds the documentation"
+task :doc => [:rdoc] do
+ chdir "doc" do
+ sh "webgen"
+ end
+end
+
+rd = Rake::RDocTask.new do |rdoc|
+ rdoc.rdoc_dir = 'doc/output/rdoc'
+ rdoc.title = PKG_NAME
+ rdoc.options << '--line-numbers' << '--inline-source' << '-m CmdParse::CommandParser'
+ rdoc.rdoc_files.include( 'lib/**/*.rb' )
+end
+
+
+# Developer tasks ##############################################################
+
+
+PKG_FILES = FileList.new( [
+ 'setup.rb',
+ 'TODO',
+ 'COPYING',
+ 'COPYING.LESSER',
+ 'README',
+ 'Rakefile',
+ 'ChangeLog',
+ 'net.rb',
+ 'VERSION',
+ 'lib/**/*.rb',
+ 'doc/**/*'
+ ]) do |fl|
+ fl.exclude( /\bsvn\b/ )
+ fl.exclude( 'doc/output' )
+end
+
+if !defined? Gem
+ puts "Package Target requires RubyGEMs"
+else
+ spec = Gem::Specification.new do |s|
+
+ #### Basic information
+
+ s.name = PKG_NAME
+ s.version = PKG_VERSION
+ s.summary = "Advanced command line parser supporting commands"
+ s.description = <<-EOF
+ cmdparse provides classes for parsing commands on the command line; command line options
+ are parsed using optparse or any other option parser implementation. Programs that use
+ such command line interfaces are, for example, subversion's 'svn' or Rubygem's 'gem' program.
+ EOF
+
+ #### Dependencies, requirements and files
+
+ s.files = PKG_FILES.to_a
+
+ s.require_path = 'lib'
+ s.autorequire = 'cmdparse'
+
+ #### Documentation
+
+ s.has_rdoc = true
+ s.extra_rdoc_files = rd.rdoc_files.reject do |fn| fn =~ /\.rb$/ end.to_a
+ s.rdoc_options = ['--line-numbers', '-m', 'CmdParse::CommandParser']
+
+ #### Author and project details
+
+ s.author = "Thomas Leitner"
+ s.email = "t_leitner@gmx.at"
+ s.homepage = "http://cmdparse.rubyforge.org"
+ s.rubyforge_project = "cmdparse"
+ end
+
+ task :package => [:generateFiles]
+ task :generateFiles do |t|
+ File.open('VERSION', 'w+') do |file| file.write( PKG_VERSION + "\n" ) end
+ end
+
+ CLOBBER << "ChangeLog" << "VERSION"
+
+ Rake::GemPackageTask.new( spec ) do |pkg|
+ pkg.need_zip = true
+ pkg.need_tar = true
+ end
+
+end
+
+desc "Upload documentation to homepage"
+task :uploaddoc => [:doc] do
+ Dir.chdir('doc/output')
+ sh "scp -r * gettalong@rubyforge.org:/var/www/gforge-projects/cmdparse/"
+end
+
+
+# Misc tasks ###################################################################
+
+
+def count_lines( filename )
+ lines = 0
+ codelines = 0
+ open( filename ) do |f|
+ f.each do |line|
+ lines += 1
+ next if line =~ /^\s*$/
+ next if line =~ /^\s*#/
+ codelines += 1
+ end
+ end
+ [lines, codelines]
+end
+
+
+def show_line( msg, lines, loc )
+ printf "%6s %6s %s\n", lines.to_s, loc.to_s, msg
+end
+
+
+desc "Show statistics"
+task :statistics do
+ total_lines = 0
+ total_code = 0
+ show_line( "File Name", "Lines", "LOC" )
+ SRC_RB.each do |fn|
+ lines, codelines = count_lines fn
+ show_line( fn, lines, codelines )
+ total_lines += lines
+ total_code += codelines
+ end
+ show_line( "Total", total_lines, total_code )
+end
diff --git a/TODO b/TODO
new file mode 100644
index 0000000..7f06207
--- /dev/null
+++ b/TODO
@@ -0,0 +1,10 @@
+* see mail from Markus Werner concerning class methods for defining methods as sub commands
+
+---- DONE ----
+
+* define banner in a common way (like option parser), maybe use the one from option parser
+* raise NoCommandGivenError when no command was given
+* ability to specify default command (used when no command was given)
+* add order,order!,... methods to mimic optparse
+* optionally capture error messages and provide friendlier output
+* if command has subcommands, use order! method, if has arguments use permute! (=POSIXLY_CORRECT); same with getoptlong \ No newline at end of file
diff --git a/VERSION b/VERSION
new file mode 100644
index 0000000..50ffc5a
--- /dev/null
+++ b/VERSION
@@ -0,0 +1 @@
+2.0.3
diff --git a/debian/changelog b/debian/changelog
new file mode 100644
index 0000000..6cc208d
--- /dev/null
+++ b/debian/changelog
@@ -0,0 +1,74 @@
+ruby-cmdparse (2.0.3-1) unstable; urgency=low
+
+ * New upstream release
+ * Adapt package to the new Ruby policy: rename source and binary packages and
+ migrate to gem2deb.
+
+ -- Antonio Terceiro <terceiro@debian.org> Mon, 29 Aug 2011 18:03:57 -0700
+
+libcmdparse2-ruby (2.0.2-2) unstable; urgency=low
+
+ [ Arnaud Cornet ]
+ * Do not use the Uploaders rule anymore.
+
+ [ Lucas Nussbaum ]
+ * Bumped debhelper build-depend to >= 5 (fixes linda error).
+
+ -- Arnaud Cornet <arnaud.cornet@gmail.com> Sun, 15 Apr 2007 11:01:04 +0200
+
+libcmdparse2-ruby (2.0.2-1) unstable; urgency=low
+
+ [ Arnaud Cornet ]
+ * Move cdbs, debhelper, ruby and ruby-pkg-tools to build-depends.
+ * New upstream version.
+
+ [ Paul van Tilburg ]
+ * Bumped standards-version to 3.7.2; no changes required.
+
+ -- Paul van Tilburg <paulvt@debian.org> Thu, 27 Jul 2006 22:00:52 +0200
+
+libcmdparse2-ruby (2.0.0-3) unstable; urgency=low
+
+ [ Arnaud Cornet ]
+ * libcmdparse2-ruby1.8 now replaces libcmdparse2-ruby (<= 2.0.0-1) to make it
+ upgradable.
+
+ -- Paul van Tilburg <paulvt@debian.org> Fri, 14 Apr 2006 16:29:26 +0200
+
+libcmdparse2-ruby (2.0.0-2) unstable; urgency=low
+
+ [ Lucas Nussbaum ]
+ * Added debian/watch file.
+
+ [ Arnaud Cornet ]
+ * Take ownership of the package.
+ * debian/control.in now uses @RUBY_EXTRAS_TEAM@ instead of the
+ deprecated @RUBY_TEAM@, and build-depends on ruby-pkg-tools >= 0.8.
+ * Split the package in two (libcmdparse2-ruby and
+ libcmdparse2-ruby1.8).
+
+ [ Paul van Tilburg ]
+ * Added new build-depends that are needed because the package now uses the
+ ruby-setup-rb class from the ruby-pkg-tools.
+
+ -- Paul van Tilburg <paulvt@debian.org> Thu, 30 Mar 2006 13:41:40 +0200
+
+libcmdparse2-ruby (2.0.0-1) unstable; urgency=low
+
+ [ Arnaud Cornet ]
+ * New upstream release.
+ * Added setup.rb licence to debian/copyright.
+ * libcmdparse2-ruby is maintained by the Debian/Ruby Extras team.
+
+ [ Paul van Tilburg ]
+ * Prepared control.in to have a template Uploaders field.
+ * Adapted debian/rules to update this Uploaders field.
+
+ -- Paul van Tilburg <paulvt@debian.org> Wed, 28 Dec 2005 22:12:00 +0000
+
+libcmdparse-ruby (1.0.5-1) unstable; urgency=low
+
+ * Initial Release.
+
+ -- Arnaud Cornet <arnaud.cornet@gmail.com> Wed, 10 Aug 2005 11:38:10 +0200
+
diff --git a/debian/compat b/debian/compat
new file mode 100644
index 0000000..7f8f011
--- /dev/null
+++ b/debian/compat
@@ -0,0 +1 @@
+7
diff --git a/debian/control b/debian/control
new file mode 100644
index 0000000..255610d
--- /dev/null
+++ b/debian/control
@@ -0,0 +1,49 @@
+Source: ruby-cmdparse
+Section: ruby
+Priority: optional
+Maintainer: Debian Ruby Extras Maintainers <pkg-ruby-extras-maintainers@lists.alioth.debian.org>
+Uploaders: Antonio Terceiro <terceiro@debian.org>, Arnaud Cornet <acornet@debian.org>, Paul van Tilburg <paulvt@debian.org>
+DM-Upload-Allowed: yes
+Build-Depends: debhelper (>= 7.0.50~), gem2deb (>= 0.2.7~)
+Standards-Version: 3.9.2
+Vcs-Git: git://git.debian.org/pkg-ruby-extras/ruby-cmdparse.git
+Vcs-Browser: http://git.debian.org/?p=pkg-ruby-extras/ruby-cmdparse.git;a=summary
+Homepage: http://cmdparse.rubyforge.org
+XS-Ruby-Versions: all
+
+Package: ruby-cmdparse
+Architecture: all
+XB-Ruby-Versions: ${ruby:Versions}
+Depends: ${shlibs:Depends}, ${misc:Depends}, ruby | ruby-interpreter
+Replaces: libcmdparse2-ruby (<< 2.0.3-1~), libcmdparse2-ruby1.8 (<< 2.0.3-1~), libcmdparse-ruby (<< 2.0.3-1~)
+Breaks: libcmdparse2-ruby (<< 2.0.3-1~), libcmdparse2-ruby1.8 (<< 2.0.3-1~), libcmdparse-ruby (<< 2.0.3-1~)
+Provides: libcmdparse2-ruby, libcmdparse2-ruby1.8, libcmdparse-ruby
+Description: Advanced command line parsing module supporting sub-commands
+ Flexible library simplifying creation of shell commands using sub-commands,
+ ie a la apt-get.
+ Uses optparse, part of ruby standard library
+
+# Transitional packages
+Package: libcmdparse2-ruby
+Section: oldlibs
+Architecture: all
+Depends: ${misc:Depends}, ruby-cmdparse
+Description: Transitional package for ruby-cmdparse
+ This is a transitional package to ease upgrades to the ruby-cmdparse
+ package. It can safely be removed.
+
+Package: libcmdparse2-ruby1.8
+Section: oldlibs
+Architecture: all
+Depends: ${misc:Depends}, ruby-cmdparse
+Description: Transitional package for ruby-cmdparse
+ This is a transitional package to ease upgrades to the ruby-cmdparse
+ package. It can safely be removed.
+
+Package: libcmdparse-ruby
+Section: oldlibs
+Architecture: all
+Depends: ${misc:Depends}, ruby-cmdparse
+Description: Transitional package for ruby-cmdparse
+ This is a transitional package to ease upgrades to the ruby-cmdparse
+ package. It can safely be removed.
diff --git a/debian/copyright b/debian/copyright
new file mode 100644
index 0000000..e05a8e3
--- /dev/null
+++ b/debian/copyright
@@ -0,0 +1,26 @@
+Format: http://svn.debian.org/wsvn/dep/web/deps/dep5.mdwn?op=file&rev=173
+Upstream-Name: cmdparse
+Source: http://cmdparse.rubyforge.org/
+
+Files: *
+Copyright: Copyright (C) 2004-2010 Thomas Leitner
+License: LGPL-3
+Comment:
+ On Debian systems, the complete text of the GNU Lesser General Public Library
+ 3 can be found in `/usr/share/common-licenses/LGPL-3`.
+
+Files: setup.rb
+Copyright: Copyright (c) 2000-2004 Minero Aoki
+License:
+ This program is free software.
+ You can distribute/modify this program under the terms of
+ the GNU Lesser General Public License version 2.1.
+Comment:
+ On Debian systems, the complete text of the GNU Lesser General Public
+ License 2.1 can be found in `/usr/share/common-licenses/LGPL-2.1'.
+
+Files: debian/*
+Copyright: © 2001 Antonio Terceiro <terceiro@debian.org>
+License:
+ The Debian packaging is licensed under the same terms as the original package.
+
diff --git a/debian/ruby-cmdparse.docs b/debian/ruby-cmdparse.docs
new file mode 100644
index 0000000..d0b0785
--- /dev/null
+++ b/debian/ruby-cmdparse.docs
@@ -0,0 +1,6 @@
+# FIXME: doc/ dir found in source. Consider installing the docs.
+# Examples:
+# doc/manual.html
+# doc/site/*
+# FIXME: READMEs found
+# README
diff --git a/debian/ruby-cmdparse.examples b/debian/ruby-cmdparse.examples
new file mode 100644
index 0000000..a455abf
--- /dev/null
+++ b/debian/ruby-cmdparse.examples
@@ -0,0 +1 @@
+net.rb
diff --git a/debian/ruby-cmdparse.links b/debian/ruby-cmdparse.links
new file mode 100644
index 0000000..95441b3
--- /dev/null
+++ b/debian/ruby-cmdparse.links
@@ -0,0 +1 @@
+/usr/lib/ruby/vendor_ruby/cmdparse.rb /usr/lib/ruby/vendor_ruby/cmdparse2.rb
diff --git a/debian/ruby-tests.rb b/debian/ruby-tests.rb
new file mode 100644
index 0000000..bcf4faf
--- /dev/null
+++ b/debian/ruby-tests.rb
@@ -0,0 +1,7 @@
+# a VERY BASIC test case, just to be sure that the code is installed.
+require 'test/unit'
+class CmdParseTest < Test::Unit::TestCase
+ def test_require
+ require 'cmdparse'
+ end
+end
diff --git a/debian/rules b/debian/rules
new file mode 100755
index 0000000..a5e7dc8
--- /dev/null
+++ b/debian/rules
@@ -0,0 +1,15 @@
+#!/usr/bin/make -f
+#export DH_VERBOSE=1
+#
+# Uncomment to ignore all test failures (but the tests will run anyway)
+#export DH_RUBY_IGNORE_TESTS=all
+#
+# Uncomment to ignore some test failures (but the tests will run anyway).
+# Valid values:
+#export DH_RUBY_IGNORE_TESTS=ruby1.8 ruby1.9.1 require-rubygems
+#
+# If you need to specify the .gemspec (eg there is more than one)
+#export DH_RUBY_GEMSPEC=gem.gemspec
+
+%:
+ dh $@ --buildsystem=ruby --with ruby
diff --git a/debian/source/format b/debian/source/format
new file mode 100644
index 0000000..163aaf8
--- /dev/null
+++ b/debian/source/format
@@ -0,0 +1 @@
+3.0 (quilt)
diff --git a/debian/source/lintian-overrides b/debian/source/lintian-overrides
new file mode 100644
index 0000000..f2af7cd
--- /dev/null
+++ b/debian/source/lintian-overrides
@@ -0,0 +1,2 @@
+ruby-cmdparse source: duplicate-short-description libcmdparse2-ruby libcmdparse2-ruby1.8 libcmdparse-ruby
+ruby-cmdparse source: duplicate-long-description libcmdparse2-ruby libcmdparse2-ruby1.8 libcmdparse-ruby
diff --git a/debian/watch b/debian/watch
new file mode 100644
index 0000000..f6266fa
--- /dev/null
+++ b/debian/watch
@@ -0,0 +1,2 @@
+version=3
+http://pkg-ruby-extras.alioth.debian.org/cgi-bin/gemwatch/cmdparse .*/cmdparse-(.*).tar.gz
diff --git a/doc/config.yaml b/doc/config.yaml
new file mode 100644
index 0000000..b1b80e5
--- /dev/null
+++ b/doc/config.yaml
@@ -0,0 +1,2 @@
+PageHandler:
+ validator: xmllint
diff --git a/doc/plugin/extract.rb b/doc/plugin/extract.rb
new file mode 100644
index 0000000..6353b2a
--- /dev/null
+++ b/doc/plugin/extract.rb
@@ -0,0 +1,29 @@
+module CmdparsePlugins
+
+ class ExtractTag < Tags::DefaultTag
+
+ summary "Extracts lines from a file"
+ depends_on 'Tags'
+ add_param 'file', nil, 'the file from which to read the lines'
+ add_param 'lines', nil, 'the lines which should be read (Range)'
+ set_mandatory 'file'
+ set_mandatory 'lines'
+
+ def initialize
+ super
+ @processOutput = false
+ register_tag( 'extract' )
+ end
+
+ def process_tag( tag, node, refNode )
+ data = File.readlines( get_param( 'file' ) ).unshift( 'empty null line' )[get_param( 'lines' )]
+ out = '<table class="cmdparse-example"><tr>'
+ out << '<td><pre>' << get_param( 'lines' ).collect {|n| "#{n}<br />" }.to_s << '</pre></td>'
+ out << '<td><pre>' << data.collect {|line| "#{CGI::escapeHTML(line)}" }.to_s << '</pre></td>'
+ out << '</tr></table>'
+ out
+ end
+
+ end
+
+end
diff --git a/doc/src/about.page b/doc/src/about.page
new file mode 100644
index 0000000..a8c6fd4
--- /dev/null
+++ b/doc/src/about.page
@@ -0,0 +1,28 @@
+---
+title: About
+inMenu: true
+orderInfo: 2
+---
+h2. About @cmdparse@
+
+Some new programs use a "command style" command line. Examples for such programs are the "svn"
+program from Subversion and the "gem" program from Rubygems. The standard Ruby distribution has no
+library to create programs that use such a command line interface.
+
+This library, cmdparse, can be used to create such a command line interface. Internally it uses
+optparse or any other option parser library to parse options and it provides a nice API for
+specifying commands and subcommands.
+
+A typical command line for a program which uses commands looks like this:
+
+<pre>
+ $ net --verbose ipaddr add 192.168.0.1 193.150.0.1
+</pre>
+
+
+h2. Author
+
+* *Thomas Leitner*
+* Web: "http://cmdparse.rubyforge.org":http://cmdparse.rubyforge.org
+* e-Mail: "t_leitner@gmx.at":mailto:t_leitner@gmx.at
+* GPG Key-Id: 0xD942E7F6
diff --git a/doc/src/default.css b/doc/src/default.css
new file mode 100644
index 0000000..1fdd03c
--- /dev/null
+++ b/doc/src/default.css
@@ -0,0 +1,151 @@
+/*
+#5CB85C -> background
+#408040 -> headings
+#CFE6CF -> code
+#30BF30 -> other
+ */
+
+ body {
+ margin: 0px 2em;
+ font-size: 12px;
+ font-family: Verdana, Arial, Helvetica;
+ border: 1px solid black;
+ color: black;
+ }
+
+ h1, h2, h3, h4, h5 { color: #408040}
+
+ a:visited { color: #408040; }
+ a { color: #5CB85C; }
+ .bar a { color: white }
+ .bar a:visited { color: white }
+
+ #all { background-color: #CFE6CF; }
+
+ #header {
+ border-bottom: 1px solid black;
+ padding: 1ex;
+ background-color: #5CB85C;
+ }
+ #header img {
+ padding-right: 5em;
+ }
+ #header h1 {
+ margin: 0ex;
+ font-size: 300%;
+ font-style: italic;
+ font-weight: normal;
+ color: white;
+ }
+
+, #headerbar { border-bottom: 1px solid black; }
+ #footer { border-top: 1px solid black; }
+
+ #body {
+ margin-left: 250px;
+ margin-right: 20px;
+ padding: 10px;
+ }
+
+ #menu {
+ float: left;
+ width: 230px;
+ padding: 20px 0px 0px 2px;
+ }
+
+ .bar {
+ clear: both;
+ padding: 3px;
+ text-align: center;
+ font-size: 90%;
+ background-color: #30BF30;
+ }
+
+ .left, .right {
+ padding: 0px 1em;
+ }
+
+ .left {
+ float: left;
+ text-align: left;
+ }
+
+ .right {
+ float: right;
+ text-align: right;
+ }
+
+ /* styling the menu */
+
+ #menu a {
+ text-decoration: none;
+ font-weight: bold;
+ font-size: 130%;
+ }
+
+ #menu a:hover {
+ text-decoration: underline;
+ }
+
+ #menu .webgen-menuitem-selected {
+ border-left: 3px solid #408040;
+ }
+
+ #menu ul {
+ list-style-type: none;
+ padding: 0px;
+ margin-left: 10px;
+ }
+
+ #menu li > ul {
+ font-size: 95%;
+ }
+
+ #menu li {
+ margin: 0.0em 0px;
+ padding: 2px 0px;
+ padding-left: 5px;
+ border-left: 3px solid #CCCCCC;
+ }
+
+ /* styling the content */
+
+ h2 {
+ padding: 0px;
+ letter-spacing: 0.2em;
+ font-size: 150%;
+ font-weight: bold;
+ border-bottom: 1px solid #408040;
+ }
+
+ .webgen-file {
+ padding-left: 10px;
+ margin: 0px 10px;
+ border-left: 3px solid #5CB85C;
+ }
+
+ .webgen-picture {
+ text-align: center;
+ }
+
+ .webgen-picture img {
+ border: 1px solid black;
+ }
+
+ .webgen-gallery {
+ text-align: center;
+ }
+
+ .webgen-gallery table {
+ width: 100%;
+ }
+
+ .webgen-gallery table td{
+ text-align: center;
+ border: 1px solid black;
+ }
+
+ table.cmdparse-example td {
+ border: 1px solid #408040;
+ background-color: white;
+ }
diff --git a/doc/src/default.template b/doc/src/default.template
new file mode 100644
index 0000000..306d8ef
--- /dev/null
+++ b/doc/src/default.template
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="{lang:}">
+ <head>
+ <title>cmdparse: {title:}</title>
+ <link href="{relocatable: default.css}" rel="stylesheet" />
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+ </head>
+ <body>
+ <div id="all">
+
+ <div id="header">
+ <table>
+ <tr>
+ <td><img src="{relocatable: logo.png}" alt="Logo" title="Logo" /></td>
+ <td><h1>cmdparse<span style="font-size: 60%"> - advanced command line parser supporting commands</span></h1>
+ </td>
+ </tr>
+ </table>
+ </div>
+
+ <div id="headerbar" class="bar">
+ <span class="left">Navbar: {breadcrumbTrail: }</span>
+ <span class="right">Language: {langbar: }</span>
+ <div style="clear:both"></div>
+ </div>
+
+ <div id="menu">
+ {menu:}
+ </div>
+
+ <div id="body">
+ {content:}
+ </div>
+
+ <div id="footer" class="bar">
+ <a href="http://validator.w3.org/check?uri=referer"><img src="{resource: w3c-valid-xhtml11}" alt="Valid XHTML 1.1!" height="31" width="88" /></a>
+ <a href="http://jigsaw.w3.org/css-validator/check/referer"><img src="{resource: w3c-valid-css}" alt="Valid CSS!" height="31" width="88" /></a>
+ <a href="http://webgen.rubyforge.org"><img src="{resource: webgen-generated}" alt="Generated by webgen" height="31" width="88"/></a> on <b>{date: }</b>
+ </div>
+ </div>
+ </body>
+</html>
diff --git a/doc/src/download.page b/doc/src/download.page
new file mode 100644
index 0000000..5a08494
--- /dev/null
+++ b/doc/src/download.page
@@ -0,0 +1,34 @@
+---
+title: Download &amp; Installation
+inMenu: true
+orderInfo: 4
+---
+h2. Download
+
+The newest version of cmdparse can be downloaded from Rubyforge.
+
+Homepage: "cmdparse.rubyforge.org":http://cmdparse.rubyforge.org <br />
+Download: "rubyforge.org/frs/?group_id=396":http://rubyforge.org/frs/?group_id=396
+
+h2. Dependencies
+
+none
+
+h2. Installation
+
+The preferred way of installing cmdparse is via RubyGems:
+<pre>
+ $ gem install cmdparse
+</pre>
+
+If you do not have RubyGems installed, but Rake, you can use the following command:
+<pre>
+ $ rake install
+</pre>
+
+If you have neither RubyGems nor Rake, use these commands:
+<pre>
+ $ ruby setup.rb config
+ $ ruby setup.rb setup
+ $ ruby setup.rb install
+</pre>
diff --git a/doc/src/features.page b/doc/src/features.page
new file mode 100644
index 0000000..5fcb929
--- /dev/null
+++ b/doc/src/features.page
@@ -0,0 +1,11 @@
+---
+title: Features
+inMenu: true
+orderInfo: 3
+---
+h2. Feature list
+
+* Commands can have subcommands
+* Default commands for showing help and the version of the program
+* Option parsing library of choice can be used (after writing wrapper), default is @optparse@
+* Easy to use
diff --git a/doc/src/index.page b/doc/src/index.page
new file mode 100644
index 0000000..f7e46c6
--- /dev/null
+++ b/doc/src/index.page
@@ -0,0 +1,80 @@
+---
+title: HomePage
+inMenu: true
+directoryName: cmdparse
+menuOrder: 1
+---
+h2. Welcome
+
+... to the homepage of _*cmdparse*_, an advanced command line parser supporting commands.
+
+Have a look around the site!
+
+h2. News
+
+<b>2006-06-17 cmdparse 2.0.2 released!!!</b>
+
+Changes:
+
+* Included two patches from Assaph Mehr:
+ * partial command matching can now be used (see <a href="{relocatable: tutorial.page}">tutorial page</a>)
+ * now a banner for the help and version commands can be specified
+
+<b>2006-04-05 cmdparse 2.0.1 released!!!</b>
+
+Changes:
+
+* Just a bug fix release for those using cmdparse with Rubygems. By issuing the command
+ @require_gem 'cmdparse'@ the cmdparse library gets automagically loaded.
+* Minor documentation updates
+
+<b>2005-08-16 cmdparse 2.0.0 released!!!</b>
+
+This version is not compatible to previous versions of cmdparse as there have been major changes in
+the API. However, updating your code to use the new API is very easy!
+
+Changes:
+
+* Commands can now have subcommands which can have subcommands which can have subcommands...
+* No need to implement a whole new class for simple commands anymore
+* Default option parser library is @optparse@, however, any option parser library can be used after writing a small wrapper
+
+<b>2005-07-05 cmdparse 1.0.5 released!!!</b>
+
+Changes:
+
+* added possibility to parse global options, command and local options separately
+
+
+<b>2005-06-16 cmdparse 1.0.4 released!!!</b>
+
+Changes:
+
+* fix for older ruby versions
+* fixed bug where exception was not caught
+
+
+<b>2005-06-09 cmdparse 1.0.3 released!!!</b>
+
+Changes:
+
+* added optional graceful exception handling
+
+
+<b>2005-04-21 cmdparse 1.0.2 released!!!</b>
+
+Changes:
+
+* splitted parsing of the arguments and executing the command into two methods
+
+<b>2005-04-13 cmdparse 1.0.1 released!!!</b>
+
+Changes:
+
+* Improved HelpCommand: the global options -h and --help take an optional command name now
+* Possibility to define a default command which is used when no command was specified
+* A @NoCommandGivenError@ is thrown when no command on the CLI and no default command was specified
+
+h2. And so
+
+... have fun!
diff --git a/doc/src/logo.png b/doc/src/logo.png
new file mode 100644
index 0000000..298626e
--- /dev/null
+++ b/doc/src/logo.png
Binary files differ
diff --git a/doc/src/meta.info b/doc/src/meta.info
new file mode 100644
index 0000000..88ff88a
--- /dev/null
+++ b/doc/src/meta.info
@@ -0,0 +1,5 @@
+api.html:
+ dest: rdoc/index.html
+ title: API Reference
+ orderInfo: 7
+ inMenu: true
diff --git a/doc/src/tutorial.page b/doc/src/tutorial.page
new file mode 100644
index 0000000..6591e44
--- /dev/null
+++ b/doc/src/tutorial.page
@@ -0,0 +1,177 @@
+---
+title: Tutorial
+inMenu: true
+orderInfo: 6
+---
+h2. Quickstart
+
+Here are some short code fragments which show how to use cmdparse. A complete example app can be
+found later in the "tutorial section":#tutorial.
+
+Defining commands using classes:
+<pre>
+class TestCmd < CmdParse::Command
+ def initialize
+ super('test', true)
+ self.add_command(TestSubCmd.new)
+ end
+end
+
+class TestSubCmd < CmdParse::Command
+ def initialize
+ super('sub',false)
+ end
+
+ def execute (args)
+ puts "Hallo #{args}"
+ end
+end
+
+cmd = CmdParse::CommandParser.new( true )
+cmd.add_command(TestCmd.new)
+</pre>
+
+Defining command using the basic @CmdParse::Command@ class:
+<pre>
+cmd = CmdParse::CommandParser.new( true )
+testcmd = CmdParse::Command.new( 'test', true )
+testcmd.short_desc = "Short desc"
+cmd.add_command( testcmd )
+
+sub = CmdParse::Command.new( 'sub', false )
+sub.short_desc = "Add an IP address"
+sub.set_execution_block do |args|
+ puts "Hallo #{args}"
+end
+testcmd.add_command( sub )
+</pre>
+
+h2(#tutorial). Tutorial
+
+<b>The complete code for this example can be found in the file @net.rb@ of the @cmdparse@
+package!</b>
+
+This tutorial produces a small @net@ application which can add, delete and list IP adresses and show
+'network statistics'. The shown code fragments do not include the whole program. So, instead of
+writing all the code yourself, just look at the code fragments first and then use the include
+@net.rb@ file for running the program.
+
+h3. Require statements
+
+Create a new new file and write the necessary @require@ statements.
+
+<notextile>{extract: {file: ../net.rb, lines: !ruby/range 5..5}}</notextile>
+
+h3. The @CommandParser@ class
+
+Next we will define our basic @CommandParser@ by defining the name of the program, its version and
+the global options. The first boolean argument to the constructor of the @CommandParser@ class
+defines whether exceptions should be handled gracefully, i.e. by showing an appropriate error
+message and the help screen. The second boolean argument defines whether the top level commands
+should use partial command matching instead of full command matching. If partial command matching is
+used, then the shortest unambiguous part of a command name can be used instead of always specifing
+the full command name.
+
+<notextile>{extract: {file: ../net.rb, lines: !ruby/range 30..36}}</notextile>
+
+The options are defined using an option parser wrapper. Currently, the only option parser library
+supported is @optparse@ from the Ruby Standard Library. If you want to use another option parser
+library, you need to write a wrapper for it so that @cmdparse@ can use it.
+
+Now we only have to tell the program to use our newly defined class to process the command line
+arguments.
+
+<notextile>{extract: {file: ../net.rb, lines: !ruby/range 86..86}}</notextile>
+
+The @parse@ method of our @CommandParser@ instance parses the given array of options (or @ARGV@ if
+no argument is specified). All the command line options are parsed and the given command executed.
+
+The program can be executed now but won't be useful as we did not specify any commands.
+
+h3. Defining commands
+
+So, as we have defined our @CommandParser@ object, we need to add some commands to it. First, we
+will add two predefined commands, namely the @help@ and the @version@ command.
+
+<notextile>{extract: {file: ../net.rb, lines: !ruby/range 37..38}}</notextile>
+
+That was easy! Now you can execute the program and specify the commands @help@ or @version@.
+However, we want the program to do something "useful". Therefore we define a new command.
+
+<notextile>{extract: {file: ../net.rb, lines: !ruby/range 41..44}}</notextile>
+
+This command is defined by using the default @Command@ class. First an instance is created assigning
+a name to the command and defining whether this command takes subcommands and uses partial command
+matching. Next we add a short description so that the @help@ command can produce something useful.
+And at last, we add this command to our @CommandParser@ instance.
+
+We specified that our @ipaddr@ command takes subcommands. So we have to define them, too:
+
+<notextile>{extract: {file: ../net.rb, lines: !ruby/range 46..78}}</notextile>
+
+We add three subcommands to the @ipaddr@ command: @add@, @del@ and @list@.
+
+The @add@ command is similar to the @ipaddr@ command. However, as the @add@ command does not take
+other commands, we have to define an execution block.
+
+The @del@ command is similar to the @add@ command. As we want to be able to delete all IP addresses
+by issuing only one command, we add an option for this.
+
+By providing @true@ as second argument when we add the @list@ command to the @ipaddr@ command, we
+specifiy that this command should be the default command which gets invoked when no command name is
+specified on the command line. Only one command can be specified as default command!
+
+Till now we only used the basic @Command@ class to specify commands. However, new commands can also
+be created by subclassing the @Command@ class, as shown with this last command:
+
+<notextile>{extract: {file: ../net.rb, lines: !ruby/range 9..28}}</notextile>
+<notextile>{extract: {file: ../net.rb, lines: !ruby/range 39..39}}</notextile>
+
+h3. Running the program
+
+That's all! You can run the program now and have a look at the output which differs depending on
+which arguments you choose.
+
+So, a typical invocation of this program looks like this:
+
+<pre>
+ $ ruby net.rb --verbose ipaddr add 192.168.0.1 193.150.0.1
+</pre>
+
+* <notextile><tt>--verbose</tt></notextile> is a global option
+* @ipaddr@ is the first command name (which has no options)
+* @add@ is the second command name (which also has no options)
+* <tt>192.168.0.1 193.150.0.1</tt> are additional arguments
+
+You should notice that if you type
+<pre>
+ $ ruby net.rb
+</pre>
+
+you get an error because you did not specify any command.
+
+However, when you type
+<pre>
+ $ ruby net.rb ipaddr
+</pre>
+
+you do not get an error!
+
+Why? As the @ipaddr@ command takes subcommands there should be an additional command name (e.g.
+@list@) on the command line. However, as the @list@ command is the default command for @ipaddr@ you
+do not need to type it.
+
+*By the way:* You get the same output if you type
+<pre>
+ $ ruby net.rb ip
+</pre>
+
+Why? As partial command matching is used for the top level commands, the shortest unambiguous name
+for a command can be used. As there is no other command starting with @ip@ (or even with the letter
+@i@), it is sufficient to write the above to select the @ipaddr@ command.
+
+*Notice:* The options of a command which does not take subcommands do not need to be at the front;
+they can be anywhere, like this
+<pre>
+ $ ruby test.rb --verbose mycommand file1 file2 --recursive file3
+</pre>
diff --git a/lib/cmdparse.rb b/lib/cmdparse.rb
new file mode 100644
index 0000000..423da44
--- /dev/null
+++ b/lib/cmdparse.rb
@@ -0,0 +1,450 @@
+#
+#--
+# cmdparse: advanced command line parser supporting commands
+# Copyright (C) 2004-2010 Thomas Leitner
+#
+# This file is part of cmdparse.
+#
+# cmdparse is free software: you can redistribute it and/or modify it under the terms of the GNU
+# Lesser General Public License as published by the Free Software Foundation, either version 3 of
+# the License, or (at your option) any later version.
+#
+# cmdparse is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+# the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+# General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License along with cmdparse. If
+# not, see <http://www.gnu.org/licenses/>.
+#
+#++
+#
+
+# Namespace module for cmdparse.
+module CmdParse
+
+ # The version of this cmdparse implemention
+ VERSION = [2, 0, 3]
+
+
+ # Base class for all cmdparse errors.
+ class ParseError < RuntimeError
+
+ # Sets the reason for a subclass.
+ def self.reason( reason, has_arguments = true )
+ (@@reason ||= {})[self] = [reason, has_arguments]
+ end
+
+ # Returns the reason plus the message.
+ def message
+ data = @@reason[self.class] || ['Unknown error', true]
+ data[0] + (data[1] ? ": " + super : '')
+ end
+
+ end
+
+ # This error is thrown when an invalid command is encountered.
+ class InvalidCommandError < ParseError
+ reason 'Invalid command'
+ end
+
+ # This error is thrown when an invalid argument is encountered.
+ class InvalidArgumentError < ParseError
+ reason 'Invalid argument'
+ end
+
+ # This error is thrown when an invalid option is encountered.
+ class InvalidOptionError < ParseError
+ reason 'Invalid option'
+ end
+
+ # This error is thrown when no command was given and no default command was specified.
+ class NoCommandGivenError < ParseError
+ reason 'No command given', false
+ end
+
+ # This error is thrown when a command is added to another command which does not support commands.
+ class TakesNoCommandError < ParseError
+ reason 'This command takes no other commands', false
+ end
+
+
+ # Base class for all parser wrappers.
+ class ParserWrapper
+
+ # Returns the parser instance for the object and, if a block is a given, yields the instance.
+ def instance
+ yield @instance if block_given?
+ @instance
+ end
+
+ # Parses the arguments in order, i.e. stops at the first non-option argument, and returns all
+ # remaining arguments.
+ def order( args )
+ raise InvalidOptionError.new( args[0] ) if args[0] =~ /^-/
+ args
+ end
+
+ # Permutes the arguments so that all options anywhere on the command line are parsed and the
+ # remaining non-options are returned.
+ def permute( args )
+ raise InvalidOptionError.new( args[0] ) if args.any? {|a| a =~ /^-/}
+ args
+ end
+
+ # Returns a summary string of the options.
+ def summarize
+ ""
+ end
+
+ end
+
+ # Require default option parser wrapper
+ require 'cmdparse/wrappers/optparse'
+
+ # Command Hash - will return partial key matches as well if there is a single
+ # non-ambigous matching key
+ class CommandHash < Hash
+
+ def []( cmd_name )
+ super or begin
+ possible = keys.select {|key| key =~ /^#{cmd_name}.*/ }
+ fetch( possible[0] ) if possible.size == 1
+ end
+ end
+
+ end
+
+ # Base class for the commands. This class implements all needed methods so that it can be used by
+ # the +CommandParser+ class.
+ class Command
+
+ # The name of the command
+ attr_reader :name
+
+ # A short description of the command.
+ attr_accessor :short_desc
+
+ # A detailed description of the command
+ attr_accessor :description
+
+ # The wrapper for parsing the command line options.
+ attr_accessor :options
+
+ # Returns the name of the default command.
+ attr_reader :default_command
+
+ # Sets or returns the super command of this command. The super command is either a +Command+
+ # instance for normal commands or a +CommandParser+ instance for the root command.
+ attr_accessor :super_command
+
+ # Returns the list of commands for this command.
+ attr_reader :commands
+
+ # Initializes the command called +name+. The parameter +has_commands+ specifies if this command
+ # takes other commands as argument. The optional argument +partial_commands+ specifies, if
+ # partial command matching should be used.
+ def initialize( name, has_commands, partial_commands = false )
+ @name = name
+ @options = ParserWrapper.new
+ @has_commands = has_commands
+ @commands = Hash.new
+ @default_command = nil
+ use_partial_commands( partial_commands )
+ end
+
+ def use_partial_commands( use_partial )
+ temp = ( use_partial ? CommandHash.new : Hash.new )
+ temp.update( @commands )
+ @commands = temp
+ end
+
+ # Returns +true+ if this command supports sub commands.
+ def has_commands?
+ @has_commands
+ end
+
+ # Adds a command to the command list if this command takes other commands as argument. If the
+ # optional parameter +default+ is true, then this command is used when no command is specified
+ # on the command line.
+ def add_command( command, default = false )
+ raise TakesNoCommandError.new( @name ) if !has_commands?
+ @commands[command.name] = command
+ @default_command = command.name if default
+ command.super_command = self
+ command.init
+ end
+
+ # For sorting commands by name.
+ def <=>( other )
+ @name <=> other.name
+ end
+
+ # Returns the +CommandParser+ instance for this command or +nil+ if this command was not
+ # assigned to a +CommandParser+ instance.
+ def commandparser
+ cmd = super_command
+ cmd = cmd.super_command while !cmd.nil? && !cmd.kind_of?( CommandParser )
+ cmd
+ end
+
+ # Returns a list of super commands, ie.:
+ # [command, super_command, super_super_command, ...]
+ def super_commands
+ cmds = []
+ cmd = self
+ while !cmd.nil? && !cmd.super_command.kind_of?( CommandParser )
+ cmds << cmd
+ cmd = cmd.super_command
+ end
+ cmds
+ end
+
+ # This method is called when the command is added to a +Command+ instance.
+ def init; end
+
+ # Set the given +block+ as execution block. See also: +execute+.
+ def set_execution_block( &block )
+ @exec_block = block
+ end
+
+ # Invokes the block set by +set_execution_block+. This method is called by the +CommandParser+
+ # instance if this command was specified on the command line.
+ def execute( args )
+ @exec_block.call( args )
+ end
+
+ # Defines the usage line for the command.
+ def usage
+ tmp = "Usage: #{commandparser.program_name}"
+ tmp << " [options] " if !commandparser.options.instance_of?( ParserWrapper )
+ tmp << super_commands.reverse.collect do |c|
+ t = c.name
+ t << " [options]" if !c.options.instance_of?( ParserWrapper )
+ t
+ end.join(' ')
+ tmp << (has_commands? ? " COMMAND [options] [ARGS]" : " [ARGS]")
+ end
+
+ # Default method for showing the help for the command.
+ def show_help
+ puts "#{@name}: #{short_desc}"
+ puts description if description
+ puts
+ puts usage
+ puts
+ if has_commands?
+ list_commands
+ puts
+ end
+ unless (summary = options.summarize).empty?
+ puts summary
+ puts
+ end
+ end
+
+ #######
+ private
+ #######
+
+ def list_commands( level = 1, command = self )
+ puts "Available commands:" if level == 1
+ command.commands.sort.each do |name, cmd|
+ print " "*level + name.ljust( 15 ) + cmd.short_desc.to_s
+ print " (=default command)" if name == command.default_command
+ print "\n"
+ list_commands( level + 1, cmd ) if cmd.has_commands?
+ end
+ end
+
+ end
+
+ # The default help command. It adds the options "-h" and "--help" to the global options of the
+ # associated +CommandParser+. When the command is specified on the command line, it can show the
+ # main help or individual command help.
+ class HelpCommand < Command
+
+ def initialize
+ super( 'help', false )
+ self.short_desc = 'Provide help for individual commands'
+ self.description = 'This command prints the program help if no arguments are given. ' \
+ 'If one or more command names are given as arguments, these arguments are interpreted ' \
+ 'as a hierachy of commands and the help for the right most command is show.'
+ end
+
+ def init
+ case commandparser.main_command.options
+ when OptionParserWrapper
+ commandparser.main_command.options.instance do |opt|
+ opt.on_tail( "-h", "--help", "Show help" ) do
+ execute( [] )
+ end
+ end
+ end
+ end
+
+ def usage
+ "Usage: #{commandparser.program_name} help [COMMAND SUBCOMMAND ...]"
+ end
+
+ def execute( args )
+ if args.length > 0
+ cmd = commandparser.main_command
+ arg = args.shift
+ while !arg.nil? && cmd.commands[ arg ]
+ cmd = cmd.commands[arg]
+ arg = args.shift
+ end
+ if arg.nil?
+ cmd.show_help
+ else
+ raise InvalidArgumentError, args.unshift( arg ).join(' ')
+ end
+ else
+ show_program_help
+ end
+ exit
+ end
+
+ #######
+ private
+ #######
+
+ def show_program_help
+ puts commandparser.banner + "\n" if commandparser.banner
+ puts "Usage: #{commandparser.program_name} [options] COMMAND [options] [COMMAND [options] ...] [args]"
+ puts ""
+ list_commands( 1, commandparser.main_command )
+ puts ""
+ puts commandparser.main_command.options.summarize
+ puts
+ end
+
+ end
+
+
+ # The default version command. It adds the options "-v" and "--version" to the global options of
+ # the associated +CommandParser+. When specified on the command line, it shows the version of the
+ # program.
+ class VersionCommand < Command
+
+ def initialize
+ super( 'version', false )
+ self.short_desc = "Show the version of the program"
+ end
+
+ def init
+ case commandparser.main_command.options
+ when OptionParserWrapper
+ commandparser.main_command.options.instance do |opt|
+ opt.on_tail( "--version", "-v", "Show the version of the program" ) do
+ execute( [] )
+ end
+ end
+ end
+ end
+
+ def usage
+ "Usage: #{commandparser.program_name} version"
+ end
+
+ def execute( args )
+ version = commandparser.program_version
+ version = version.join( '.' ) if version.instance_of?( Array )
+ puts commandparser.banner + "\n" if commandparser.banner
+ puts version
+ exit
+ end
+
+ end
+
+
+ # The main class for creating a command based CLI program.
+ class CommandParser
+
+ # A standard banner for help & version screens
+ attr_accessor :banner
+
+ # The top level command representing the program itself.
+ attr_reader :main_command
+
+ # The name of the program.
+ attr_accessor :program_name
+
+ # The version of the program.
+ attr_accessor :program_version
+
+ # Are Exceptions be handled gracefully? I.e. by printing error message and the help screen?
+ attr_reader :handle_exceptions
+
+ # Create a new CommandParser object. The optional argument +handleExceptions+ specifies if the
+ # object should handle exceptions gracefully. Set +partial_commands+ to +true+, if you want
+ # partial command matching for the top level commands.
+ def initialize( handleExceptions = false, partial_commands = false )
+ @main_command = Command.new( 'mainCommand', true )
+ @main_command.super_command = self
+ @main_command.use_partial_commands( partial_commands )
+ @program_name = $0
+ @program_version = "0.0.0"
+ @handle_exceptions = handleExceptions
+ end
+
+ # Returns the wrapper for parsing the global options.
+ def options
+ @main_command.options
+ end
+
+ # Sets the wrapper for parsing the global options.
+ def options=( wrapper )
+ @main_command.options = wrapper
+ end
+
+ # Adds a top level command.
+ def add_command( *args )
+ @main_command.add_command( *args )
+ end
+
+ # Parses the command line arguments. If a block is specified, the current hierarchy level and
+ # the name of the current command is yielded after the options for the level have been parsed.
+ def parse( argv = ARGV ) # :yields: level, commandName
+ level = 0
+ command = @main_command
+
+ while !command.nil?
+ argv = if command.has_commands? || ENV.include?( 'POSIXLY_CORRECT' )
+ command.options.order( argv )
+ else
+ command.options.permute( argv )
+ end
+ yield( level, command.name ) if block_given?
+
+ if command.has_commands?
+ cmdName, argv = argv[0], argv[1..-1] || []
+
+ if cmdName.nil?
+ if command.default_command.nil?
+ raise NoCommandGivenError
+ else
+ cmdName = command.default_command
+ end
+ else
+ raise InvalidCommandError.new( cmdName ) unless command.commands[ cmdName ]
+ end
+
+ command = command.commands[cmdName]
+ level += 1
+ else
+ command.execute( argv )
+ command = nil
+ end
+ end
+ rescue ParseError, OptionParser::ParseError => e
+ raise if !@handle_exceptions
+ puts "Error while parsing command line:\n " + e.message
+ puts
+ @main_command.commands['help'].execute( command.super_commands.reverse.collect {|c| c.name} ) if @main_command.commands['help']
+ exit
+ end
+
+ end
+
+end
diff --git a/lib/cmdparse/wrappers/optparse.rb b/lib/cmdparse/wrappers/optparse.rb
new file mode 100644
index 0000000..7e5c3bc
--- /dev/null
+++ b/lib/cmdparse/wrappers/optparse.rb
@@ -0,0 +1,63 @@
+#
+#--
+# cmdparse: advanced command line parser supporting commands
+# Copyright (C) 2004-2010 Thomas Leitner
+#
+# This file is part of cmdparse.
+#
+# cmdparse is free software: you can redistribute it and/or modify it under the terms of the GNU
+# Lesser General Public License as published by the Free Software Foundation, either version 3 of
+# the License, or (at your option) any later version.
+#
+# cmdparse is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+# the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+# General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License along with cmdparse. If
+# not, see <http://www.gnu.org/licenses/>.
+#
+#++
+#
+
+require 'optparse'
+
+# Some extension to the standard option parser class
+class OptionParser
+
+ if const_defined?( 'Officious' )
+ Officious.delete( 'version' )
+ Officious.delete( 'help' )
+ else
+ DefaultList.long.delete( 'version' )
+ DefaultList.long.delete( 'help' )
+ end
+
+end
+
+module CmdParse
+
+ # Parser wrapper for OptionParser (included in Ruby Standard Library).
+ class OptionParserWrapper < ParserWrapper
+
+ # Initializes the wrapper with a default OptionParser instance or the +parser+ parameter and
+ # yields this instance.
+ def initialize( parser = OptionParser.new, &block )
+ @instance = parser
+ self.instance( &block )
+ end
+
+ def order( args )
+ @instance.order( args )
+ end
+
+ def permute( args )
+ @instance.permute( args )
+ end
+
+ def summarize
+ @instance.summarize
+ end
+
+ end
+
+end
diff --git a/metadata.yml b/metadata.yml
new file mode 100644
index 0000000..bfc0a95
--- /dev/null
+++ b/metadata.yml
@@ -0,0 +1,87 @@
+--- !ruby/object:Gem::Specification
+name: cmdparse
+version: !ruby/object:Gem::Version
+ prerelease: false
+ segments:
+ - 2
+ - 0
+ - 3
+ version: 2.0.3
+platform: ruby
+authors:
+- Thomas Leitner
+autorequire: cmdparse
+bindir: bin
+cert_chain: []
+
+date: 2011-01-05 00:00:00 +01:00
+default_executable:
+dependencies: []
+
+description: " cmdparse provides classes for parsing commands on the command line; command line options\n are parsed using optparse or any other option parser implementation. Programs that use\n such command line interfaces are, for example, subversion's 'svn' or Rubygem's 'gem' program.\n"
+email: t_leitner@gmx.at
+executables: []
+
+extensions: []
+
+extra_rdoc_files: []
+
+files:
+- setup.rb
+- TODO
+- COPYING
+- COPYING.LESSER
+- README
+- Rakefile
+- ChangeLog
+- net.rb
+- VERSION
+- lib/cmdparse/wrappers/optparse.rb
+- lib/cmdparse.rb
+- doc/plugin/extract.rb
+- doc/config.yaml
+- doc/src/features.page
+- doc/src/logo.png
+- doc/src/tutorial.page
+- doc/src/default.css
+- doc/src/index.page
+- doc/src/meta.info
+- doc/src/download.page
+- doc/src/default.template
+- doc/src/about.page
+has_rdoc: true
+homepage: http://cmdparse.rubyforge.org
+licenses: []
+
+post_install_message:
+rdoc_options:
+- --line-numbers
+- -m
+- CmdParse::CommandParser
+require_paths:
+- lib
+required_ruby_version: !ruby/object:Gem::Requirement
+ none: false
+ requirements:
+ - - ">="
+ - !ruby/object:Gem::Version
+ segments:
+ - 0
+ version: "0"
+required_rubygems_version: !ruby/object:Gem::Requirement
+ none: false
+ requirements:
+ - - ">="
+ - !ruby/object:Gem::Version
+ segments:
+ - 0
+ version: "0"
+requirements: []
+
+rubyforge_project: cmdparse
+rubygems_version: 1.3.7
+signing_key:
+specification_version: 3
+summary: Advanced command line parser supporting commands
+test_files: []
+
diff --git a/net.rb b/net.rb
new file mode 100644
index 0000000..d885a5e
--- /dev/null
+++ b/net.rb
@@ -0,0 +1,88 @@
+#!/usr/bin/env ruby
+# if something is changed here -> change line numbers in doc/src/documentation.page
+
+$:.unshift "lib"
+require 'cmdparse'
+require 'ostruct'
+require 'yaml'
+
+class NetStatCommand < CmdParse::Command
+
+ def initialize
+ super( 'stat', false )
+ self.short_desc = "Show network statistics"
+ self.description = "This command shows very useful network statistics - eye catching!!!"
+ end
+
+ def execute( args )
+ puts "Showing network statistics" if $verbose
+ puts
+ puts "Yeah, I will do something now..."
+ puts
+ 1.upto(10) do |row|
+ puts " "*(20-row) + "#"*(row*2 - 1)
+ end
+ puts
+ end
+
+end
+
+cmd = CmdParse::CommandParser.new( true, true )
+cmd.program_name = "net"
+cmd.program_version = [0, 1, 1]
+cmd.options = CmdParse::OptionParserWrapper.new do |opt|
+ opt.separator "Global options:"
+ opt.on("--verbose", "Be verbose when outputting info") {|t| $verbose = true }
+end
+cmd.add_command( CmdParse::HelpCommand.new )
+cmd.add_command( CmdParse::VersionCommand.new )
+cmd.add_command( NetStatCommand.new )
+
+# ipaddr
+ipaddr = CmdParse::Command.new( 'ipaddr', true, true )
+ipaddr.short_desc = "Manage IP addresses"
+cmd.add_command( ipaddr )
+
+# ipaddr add
+add = CmdParse::Command.new( 'add', false )
+add.short_desc = "Add an IP address"
+add.set_execution_block do |args|
+ puts "Adding ip addresses: #{args.join(', ')}" if $verbose
+ $ipaddrs += args
+end
+ipaddr.add_command( add )
+
+# ipaddr del
+del = CmdParse::Command.new( 'del', false )
+del.short_desc = "Delete an IP address"
+del.options = CmdParse::OptionParserWrapper.new do |opt|
+ opt.on( '-a', '--all', 'Delete all IP addresses' ) { $deleteAll = true }
+end
+del.set_execution_block do |args|
+ if $deleteAll
+ $ipaddrs = []
+ else
+ puts "Deleting ip addresses: #{args.join(', ')}" if $verbose
+ args.each {|ip| $ipaddrs.delete( ip ) }
+ end
+end
+ipaddr.add_command( del )
+
+# ipaddr list
+list = CmdParse::Command.new( 'list', false )
+list.short_desc = "Lists all IP addresses"
+list.set_execution_block do |args|
+ puts "Listing ip addresses:" if $verbose
+ puts $ipaddrs.to_yaml
+end
+ipaddr.add_command( list, true )
+
+if File.exists?( 'dumpnet' )
+ $ipaddrs = Marshal.load( File.read( 'dumpnet' ) )
+else
+ $ipaddrs = []
+end
+
+cmd.parse
+
+File.open( 'dumpnet', 'w+' ) {|f| f.write( Marshal.dump( $ipaddrs ) ) }
diff --git a/setup.rb b/setup.rb
new file mode 100644
index 0000000..f1c9d9a
--- /dev/null
+++ b/setup.rb
@@ -0,0 +1,1331 @@
+#
+# setup.rb
+#
+# Copyright (c) 2000-2004 Minero Aoki
+#
+# This program is free software.
+# You can distribute/modify this program under the terms of
+# the GNU Lesser General Public License version 2.1.
+#
+
+#
+# For backward compatibility
+#
+
+unless Enumerable.method_defined?(:map)
+ module Enumerable
+ alias map collect
+ end
+end
+
+unless Enumerable.method_defined?(:detect)
+ module Enumerable
+ alias detect find
+ end
+end
+
+unless Enumerable.method_defined?(:select)
+ module Enumerable
+ alias select find_all
+ end
+end
+
+unless Enumerable.method_defined?(:reject)
+ module Enumerable
+ def reject
+ result = []
+ each do |i|
+ result.push i unless yield(i)
+ end
+ result
+ end
+ end
+end
+
+unless Enumerable.method_defined?(:inject)
+ module Enumerable
+ def inject(result)
+ each do |i|
+ result = yield(result, i)
+ end
+ result
+ end
+ end
+end
+
+unless Enumerable.method_defined?(:any?)
+ module Enumerable
+ def any?
+ each do |i|
+ return true if yield(i)
+ end
+ false
+ end
+ end
+end
+
+unless File.respond_to?(:read)
+ def File.read(fname)
+ open(fname) {|f|
+ return f.read
+ }
+ end
+end
+
+#
+# Application independent utilities
+#
+
+def File.binread(fname)
+ open(fname, 'rb') {|f|
+ return f.read
+ }
+end
+
+# for corrupted windows stat(2)
+def File.dir?(path)
+ File.directory?((path[-1,1] == '/') ? path : path + '/')
+end
+
+#
+# Config
+#
+
+if arg = ARGV.detect{|arg| /\A--rbconfig=/ =~ arg }
+ ARGV.delete(arg)
+ require arg.split(/=/, 2)[1]
+ $".push 'rbconfig.rb'
+else
+ require 'rbconfig'
+end
+
+def multipackage_install?
+ FileTest.directory?(File.dirname($0) + '/packages')
+end
+
+
+class ConfigTable
+
+ c = ::Config::CONFIG
+
+ rubypath = c['bindir'] + '/' + c['ruby_install_name']
+
+ major = c['MAJOR'].to_i
+ minor = c['MINOR'].to_i
+ teeny = c['TEENY'].to_i
+ version = "#{major}.#{minor}"
+
+ # ruby ver. >= 1.4.4?
+ newpath_p = ((major >= 2) or
+ ((major == 1) and
+ ((minor >= 5) or
+ ((minor == 4) and (teeny >= 4)))))
+
+ subprefix = lambda {|path|
+ path.sub(/\A#{Regexp.quote(c['prefix'])}/o, '$prefix')
+ }
+
+ if c['rubylibdir']
+ # V < 1.6.3
+ stdruby = subprefix.call(c['rubylibdir'])
+ siteruby = subprefix.call(c['sitedir'])
+ versite = subprefix.call(c['sitelibdir'])
+ sodir = subprefix.call(c['sitearchdir'])
+ elsif newpath_p
+ # 1.4.4 <= V <= 1.6.3
+ stdruby = "$prefix/lib/ruby/#{version}"
+ siteruby = subprefix.call(c['sitedir'])
+ versite = siteruby + '/' + version
+ sodir = "$site-ruby/#{c['arch']}"
+ else
+ # V < 1.4.4
+ stdruby = "$prefix/lib/ruby/#{version}"
+ siteruby = "$prefix/lib/ruby/#{version}/site_ruby"
+ versite = siteruby
+ sodir = "$site-ruby/#{c['arch']}"
+ end
+
+ if arg = c['configure_args'].split.detect {|arg| /--with-make-prog=/ =~ arg }
+ makeprog = arg.sub(/'/, '').split(/=/, 2)[1]
+ else
+ makeprog = 'make'
+ end
+
+ common_descripters = [
+ [ 'prefix', [ c['prefix'],
+ 'path',
+ 'path prefix of target environment' ] ],
+ [ 'std-ruby', [ stdruby,
+ 'path',
+ 'the directory for standard ruby libraries' ] ],
+ [ 'site-ruby-common', [ siteruby,
+ 'path',
+ 'the directory for version-independent non-standard ruby libraries' ] ],
+ [ 'site-ruby', [ versite,
+ 'path',
+ 'the directory for non-standard ruby libraries' ] ],
+ [ 'bin-dir', [ '$prefix/bin',
+ 'path',
+ 'the directory for commands' ] ],
+ [ 'rb-dir', [ '$site-ruby',
+ 'path',
+ 'the directory for ruby scripts' ] ],
+ [ 'so-dir', [ sodir,
+ 'path',
+ 'the directory for ruby extentions' ] ],
+ [ 'data-dir', [ '$prefix/share',
+ 'path',
+ 'the directory for shared data' ] ],
+ [ 'ruby-path', [ rubypath,
+ 'path',
+ 'path to set to #! line' ] ],
+ [ 'ruby-prog', [ rubypath,
+ 'name',
+ 'the ruby program using for installation' ] ],
+ [ 'make-prog', [ makeprog,
+ 'name',
+ 'the make program to compile ruby extentions' ] ],
+ [ 'without-ext', [ 'no',
+ 'yes/no',
+ 'does not compile/install ruby extentions' ] ]
+ ]
+ multipackage_descripters = [
+ [ 'with', [ '',
+ 'name,name...',
+ 'package names that you want to install',
+ 'ALL' ] ],
+ [ 'without', [ '',
+ 'name,name...',
+ 'package names that you do not want to install',
+ 'NONE' ] ]
+ ]
+ if multipackage_install?
+ DESCRIPTER = common_descripters + multipackage_descripters
+ else
+ DESCRIPTER = common_descripters
+ end
+
+ SAVE_FILE = 'config.save'
+
+ def ConfigTable.each_name(&block)
+ keys().each(&block)
+ end
+
+ def ConfigTable.keys
+ DESCRIPTER.map {|name, *dummy| name }
+ end
+
+ def ConfigTable.each_definition(&block)
+ DESCRIPTER.each(&block)
+ end
+
+ def ConfigTable.get_entry(name)
+ name, ent = DESCRIPTER.assoc(name)
+ ent
+ end
+
+ def ConfigTable.get_entry!(name)
+ get_entry(name) or raise ArgumentError, "no such config: #{name}"
+ end
+
+ def ConfigTable.add_entry(name, vals)
+ ConfigTable::DESCRIPTER.push [name,vals]
+ end
+
+ def ConfigTable.remove_entry(name)
+ get_entry(name) or raise ArgumentError, "no such config: #{name}"
+ DESCRIPTER.delete_if {|n, arr| n == name }
+ end
+
+ def ConfigTable.config_key?(name)
+ get_entry(name) ? true : false
+ end
+
+ def ConfigTable.bool_config?(name)
+ ent = get_entry(name) or return false
+ ent[1] == 'yes/no'
+ end
+
+ def ConfigTable.value_config?(name)
+ ent = get_entry(name) or return false
+ ent[1] != 'yes/no'
+ end
+
+ def ConfigTable.path_config?(name)
+ ent = get_entry(name) or return false
+ ent[1] == 'path'
+ end
+
+
+ class << self
+ alias newobj new
+ end
+
+ def ConfigTable.new
+ c = newobj()
+ c.initialize_from_table
+ c
+ end
+
+ def ConfigTable.load
+ c = newobj()
+ c.initialize_from_file
+ c
+ end
+
+ def initialize_from_table
+ @table = {}
+ DESCRIPTER.each do |k, (default, vname, desc, default2)|
+ @table[k] = default
+ end
+ end
+
+ def initialize_from_file
+ raise InstallError, "#{File.basename $0} config first"\
+ unless File.file?(SAVE_FILE)
+ @table = {}
+ File.foreach(SAVE_FILE) do |line|
+ k, v = line.split(/=/, 2)
+ @table[k] = v.strip
+ end
+ end
+
+ def save
+ File.open(SAVE_FILE, 'w') {|f|
+ @table.each do |k, v|
+ f.printf "%s=%s\n", k, v if v
+ end
+ }
+ end
+
+ def []=(k, v)
+ raise InstallError, "unknown config option #{k}"\
+ unless ConfigTable.config_key?(k)
+ @table[k] = v
+ end
+
+ def [](key)
+ return nil unless @table[key]
+ @table[key].gsub(%r<\$([^/]+)>) { self[$1] }
+ end
+
+ def set_raw(key, val)
+ @table[key] = val
+ end
+
+ def get_raw(key)
+ @table[key]
+ end
+
+end
+
+
+module MetaConfigAPI
+
+ def eval_file_ifexist(fname)
+ instance_eval File.read(fname), fname, 1 if File.file?(fname)
+ end
+
+ def config_names
+ ConfigTable.keys
+ end
+
+ def config?(name)
+ ConfigTable.config_key?(name)
+ end
+
+ def bool_config?(name)
+ ConfigTable.bool_config?(name)
+ end
+
+ def value_config?(name)
+ ConfigTable.value_config?(name)
+ end
+
+ def path_config?(name)
+ ConfigTable.path_config?(name)
+ end
+
+ def add_config(name, argname, default, desc)
+ ConfigTable.add_entry name,[default,argname,desc]
+ end
+
+ def add_path_config(name, default, desc)
+ add_config name, 'path', default, desc
+ end
+
+ def add_bool_config(name, default, desc)
+ add_config name, 'yes/no', default ? 'yes' : 'no', desc
+ end
+
+ def set_config_default(name, default)
+ if bool_config?(name)
+ ConfigTable.get_entry!(name)[0] = (default ? 'yes' : 'no')
+ else
+ ConfigTable.get_entry!(name)[0] = default
+ end
+ end
+
+ def remove_config(name)
+ ent = ConfigTable.get_entry(name)
+ ConfigTable.remove_entry name
+ ent
+ end
+
+end
+
+#
+# File Operations
+#
+
+module FileOperations
+
+ def mkdir_p(dirname, prefix = nil)
+ dirname = prefix + dirname if prefix
+ $stderr.puts "mkdir -p #{dirname}" if verbose?
+ return if no_harm?
+
+ # does not check '/'... it's too abnormal case
+ dirs = dirname.split(%r<(?=/)>)
+ if /\A[a-z]:\z/i =~ dirs[0]
+ disk = dirs.shift
+ dirs[0] = disk + dirs[0]
+ end
+ dirs.each_index do |idx|
+ path = dirs[0..idx].join('')
+ Dir.mkdir path unless File.dir?(path)
+ end
+ end
+
+ def rm_f(fname)
+ $stderr.puts "rm -f #{fname}" if verbose?
+ return if no_harm?
+
+ if File.exist?(fname) or File.symlink?(fname)
+ File.chmod 0777, fname
+ File.unlink fname
+ end
+ end
+
+ def rm_rf(dn)
+ $stderr.puts "rm -rf #{dn}" if verbose?
+ return if no_harm?
+
+ Dir.chdir dn
+ Dir.foreach('.') do |fn|
+ next if fn == '.'
+ next if fn == '..'
+ if File.dir?(fn)
+ verbose_off {
+ rm_rf fn
+ }
+ else
+ verbose_off {
+ rm_f fn
+ }
+ end
+ end
+ Dir.chdir '..'
+ Dir.rmdir dn
+ end
+
+ def move_file(src, dest)
+ File.unlink dest if File.exist?(dest)
+ begin
+ File.rename src, dest
+ rescue
+ File.open(dest, 'wb') {|f| f.write File.binread(src) }
+ File.chmod File.stat(src).mode, dest
+ File.unlink src
+ end
+ end
+
+ def install(from, dest, mode, prefix = nil)
+ $stderr.puts "install #{from} #{dest}" if verbose?
+ return if no_harm?
+
+ realdest = prefix + dest if prefix
+ realdest = File.join(realdest, File.basename(from)) if File.dir?(realdest)
+ str = File.binread(from)
+ if diff?(str, realdest)
+ verbose_off {
+ rm_f realdest if File.exist?(realdest)
+ }
+ File.open(realdest, 'wb') {|f|
+ f.write str
+ }
+ File.chmod mode, realdest
+
+ File.open("#{objdir_root()}/InstalledFiles", 'a') {|f|
+ if prefix
+ f.puts realdest.sub(prefix, '')
+ else
+ f.puts realdest
+ end
+ }
+ end
+ end
+
+ def diff?(new_content, path)
+ return true unless File.exist?(path)
+ new_content != File.binread(path)
+ end
+
+ def command(str)
+ $stderr.puts str if verbose?
+ system str or raise RuntimeError, "'system #{str}' failed"
+ end
+
+ def ruby(str)
+ command config('ruby-prog') + ' ' + str
+ end
+
+ def make(task = '')
+ command config('make-prog') + ' ' + task
+ end
+
+ def extdir?(dir)
+ File.exist?(dir + '/MANIFEST')
+ end
+
+ def all_files_in(dirname)
+ Dir.open(dirname) {|d|
+ return d.select {|ent| File.file?("#{dirname}/#{ent}") }
+ }
+ end
+
+ REJECT_DIRS = %w(
+ CVS SCCS RCS CVS.adm
+ )
+
+ def all_dirs_in(dirname)
+ Dir.open(dirname) {|d|
+ return d.select {|n| File.dir?("#{dirname}/#{n}") } - %w(. ..) - REJECT_DIRS
+ }
+ end
+
+end
+
+#
+# Main Installer
+#
+
+class InstallError < StandardError; end
+
+
+module HookUtils
+
+ def run_hook(name)
+ try_run_hook "#{curr_srcdir()}/#{name}" or
+ try_run_hook "#{curr_srcdir()}/#{name}.rb"
+ end
+
+ def try_run_hook(fname)
+ return false unless File.file?(fname)
+ begin
+ instance_eval File.read(fname), fname, 1
+ rescue
+ raise InstallError, "hook #{fname} failed:\n" + $!.message
+ end
+ true
+ end
+
+end
+
+
+module HookScriptAPI
+
+ def get_config(key)
+ @config[key]
+ end
+
+ alias config get_config
+
+ def set_config(key, val)
+ @config[key] = val
+ end
+
+ #
+ # srcdir/objdir (works only in the package directory)
+ #
+
+ #abstract srcdir_root
+ #abstract objdir_root
+ #abstract relpath
+
+ def curr_srcdir
+ "#{srcdir_root()}/#{relpath()}"
+ end
+
+ def curr_objdir
+ "#{objdir_root()}/#{relpath()}"
+ end
+
+ def srcfile(path)
+ "#{curr_srcdir()}/#{path}"
+ end
+
+ def srcexist?(path)
+ File.exist?(srcfile(path))
+ end
+
+ def srcdirectory?(path)
+ File.dir?(srcfile(path))
+ end
+
+ def srcfile?(path)
+ File.file? srcfile(path)
+ end
+
+ def srcentries(path = '.')
+ Dir.open("#{curr_srcdir()}/#{path}") {|d|
+ return d.to_a - %w(. ..)
+ }
+ end
+
+ def srcfiles(path = '.')
+ srcentries(path).select {|fname|
+ File.file?(File.join(curr_srcdir(), path, fname))
+ }
+ end
+
+ def srcdirectories(path = '.')
+ srcentries(path).select {|fname|
+ File.dir?(File.join(curr_srcdir(), path, fname))
+ }
+ end
+
+end
+
+
+class ToplevelInstaller
+
+ Version = '3.2.4'
+ Copyright = 'Copyright (c) 2000-2004 Minero Aoki'
+
+ TASKS = [
+ [ 'config', 'saves your configurations' ],
+ [ 'show', 'shows current configuration' ],
+ [ 'setup', 'compiles ruby extentions and others' ],
+ [ 'install', 'installs files' ],
+ [ 'clean', "does `make clean' for each extention" ],
+ [ 'distclean',"does `make distclean' for each extention" ]
+ ]
+
+ def ToplevelInstaller.invoke
+ instance().invoke
+ end
+
+ @singleton = nil
+
+ def ToplevelInstaller.instance
+ @singleton ||= new(File.dirname($0))
+ @singleton
+ end
+
+ include MetaConfigAPI
+
+ def initialize(ardir_root)
+ @config = nil
+ @options = { 'verbose' => true }
+ @ardir = File.expand_path(ardir_root)
+ end
+
+ def inspect
+ "#<#{self.class} #{__id__()}>"
+ end
+
+ def invoke
+ run_metaconfigs
+ task = parsearg_global()
+ @config = load_config(task)
+ __send__ "parsearg_#{task}"
+ init_installers
+ __send__ "exec_#{task}"
+ end
+
+ def run_metaconfigs
+ eval_file_ifexist "#{@ardir}/metaconfig"
+ end
+
+ def load_config(task)
+ case task
+ when 'config'
+ ConfigTable.new
+ when 'clean', 'distclean'
+ if File.exist?('config.save')
+ then ConfigTable.load
+ else ConfigTable.new
+ end
+ else
+ ConfigTable.load
+ end
+ end
+
+ def init_installers
+ @installer = Installer.new(@config, @options, @ardir, File.expand_path('.'))
+ end
+
+ #
+ # Hook Script API bases
+ #
+
+ def srcdir_root
+ @ardir
+ end
+
+ def objdir_root
+ '.'
+ end
+
+ def relpath
+ '.'
+ end
+
+ #
+ # Option Parsing
+ #
+
+ def parsearg_global
+ valid_task = /\A(?:#{TASKS.map {|task,desc| task }.join '|'})\z/
+
+ while arg = ARGV.shift
+ case arg
+ when /\A\w+\z/
+ raise InstallError, "invalid task: #{arg}" unless valid_task =~ arg
+ return arg
+
+ when '-q', '--quiet'
+ @options['verbose'] = false
+
+ when '--verbose'
+ @options['verbose'] = true
+
+ when '-h', '--help'
+ print_usage $stdout
+ exit 0
+
+ when '-v', '--version'
+ puts "#{File.basename($0)} version #{Version}"
+ exit 0
+
+ when '--copyright'
+ puts Copyright
+ exit 0
+
+ else
+ raise InstallError, "unknown global option '#{arg}'"
+ end
+ end
+
+ raise InstallError, <<EOS
+No task or global option given.
+Typical installation procedure is:
+ $ ruby #{File.basename($0)} config
+ $ ruby #{File.basename($0)} setup
+ # ruby #{File.basename($0)} install (may require root privilege)
+EOS
+ end
+
+
+ def parsearg_no_options
+ raise InstallError, "#{task}: unknown options: #{ARGV.join ' '}"\
+ unless ARGV.empty?
+ end
+
+ alias parsearg_show parsearg_no_options
+ alias parsearg_setup parsearg_no_options
+ alias parsearg_clean parsearg_no_options
+ alias parsearg_distclean parsearg_no_options
+
+ def parsearg_config
+ re = /\A--(#{ConfigTable.keys.join '|'})(?:=(.*))?\z/
+ @options['config-opt'] = []
+
+ while i = ARGV.shift
+ if /\A--?\z/ =~ i
+ @options['config-opt'] = ARGV.dup
+ break
+ end
+ m = re.match(i) or raise InstallError, "config: unknown option #{i}"
+ name, value = m.to_a[1,2]
+ if value
+ if ConfigTable.bool_config?(name)
+ raise InstallError, "config: --#{name} allows only yes/no for argument"\
+ unless /\A(y(es)?|n(o)?|t(rue)?|f(alse))\z/i =~ value
+ value = (/\Ay(es)?|\At(rue)/i =~ value) ? 'yes' : 'no'
+ end
+ else
+ raise InstallError, "config: --#{name} requires argument"\
+ unless ConfigTable.bool_config?(name)
+ value = 'yes'
+ end
+ @config[name] = value
+ end
+ end
+
+ def parsearg_install
+ @options['no-harm'] = false
+ @options['install-prefix'] = ''
+ while a = ARGV.shift
+ case a
+ when /\A--no-harm\z/
+ @options['no-harm'] = true
+ when /\A--prefix=(.*)\z/
+ path = $1
+ path = File.expand_path(path) unless path[0,1] == '/'
+ @options['install-prefix'] = path
+ else
+ raise InstallError, "install: unknown option #{a}"
+ end
+ end
+ end
+
+ def print_usage(out)
+ out.puts 'Typical Installation Procedure:'
+ out.puts " $ ruby #{File.basename $0} config"
+ out.puts " $ ruby #{File.basename $0} setup"
+ out.puts " # ruby #{File.basename $0} install (may require root privilege)"
+ out.puts
+ out.puts 'Detailed Usage:'
+ out.puts " ruby #{File.basename $0} <global option>"
+ out.puts " ruby #{File.basename $0} [<global options>] <task> [<task options>]"
+
+ fmt = " %-20s %s\n"
+ out.puts
+ out.puts 'Global options:'
+ out.printf fmt, '-q,--quiet', 'suppress message outputs'
+ out.printf fmt, ' --verbose', 'output messages verbosely'
+ out.printf fmt, '-h,--help', 'print this message'
+ out.printf fmt, '-v,--version', 'print version and quit'
+ out.printf fmt, ' --copyright', 'print copyright and quit'
+
+ out.puts
+ out.puts 'Tasks:'
+ TASKS.each do |name, desc|
+ out.printf " %-10s %s\n", name, desc
+ end
+
+ out.puts
+ out.puts 'Options for config:'
+ ConfigTable.each_definition do |name, (default, arg, desc, default2)|
+ out.printf " %-20s %s [%s]\n",
+ '--'+ name + (ConfigTable.bool_config?(name) ? '' : '='+arg),
+ desc,
+ default2 || default
+ end
+ out.printf " %-20s %s [%s]\n",
+ '--rbconfig=path', 'your rbconfig.rb to load', "running ruby's"
+
+ out.puts
+ out.puts 'Options for install:'
+ out.printf " %-20s %s [%s]\n",
+ '--no-harm', 'only display what to do if given', 'off'
+ out.printf " %-20s %s [%s]\n",
+ '--prefix', 'install path prefix', '$prefix'
+
+ out.puts
+ end
+
+ #
+ # Task Handlers
+ #
+
+ def exec_config
+ @installer.exec_config
+ @config.save # must be final
+ end
+
+ def exec_setup
+ @installer.exec_setup
+ end
+
+ def exec_install
+ @installer.exec_install
+ end
+
+ def exec_show
+ ConfigTable.each_name do |k|
+ v = @config.get_raw(k)
+ if not v or v.empty?
+ v = '(not specified)'
+ end
+ printf "%-10s %s\n", k, v
+ end
+ end
+
+ def exec_clean
+ @installer.exec_clean
+ end
+
+ def exec_distclean
+ @installer.exec_distclean
+ end
+
+end
+
+
+class ToplevelInstallerMulti < ToplevelInstaller
+
+ include HookUtils
+ include HookScriptAPI
+ include FileOperations
+
+ def initialize(ardir)
+ super
+ @packages = all_dirs_in("#{@ardir}/packages")
+ raise 'no package exists' if @packages.empty?
+ end
+
+ def run_metaconfigs
+ eval_file_ifexist "#{@ardir}/metaconfig"
+ @packages.each do |name|
+ eval_file_ifexist "#{@ardir}/packages/#{name}/metaconfig"
+ end
+ end
+
+ def init_installers
+ @installers = {}
+ @packages.each do |pack|
+ @installers[pack] = Installer.new(@config, @options,
+ "#{@ardir}/packages/#{pack}",
+ "packages/#{pack}")
+ end
+
+ with = extract_selection(config('with'))
+ without = extract_selection(config('without'))
+ @selected = @installers.keys.select {|name|
+ (with.empty? or with.include?(name)) \
+ and not without.include?(name)
+ }
+ end
+
+ def extract_selection(list)
+ a = list.split(/,/)
+ a.each do |name|
+ raise InstallError, "no such package: #{name}" \
+ unless @installers.key?(name)
+ end
+ a
+ end
+
+ def print_usage(f)
+ super
+ f.puts 'Inluded packages:'
+ f.puts ' ' + @packages.sort.join(' ')
+ f.puts
+ end
+
+ #
+ # multi-package metaconfig API
+ #
+
+ attr_reader :packages
+
+ def declare_packages(list)
+ raise 'package list is empty' if list.empty?
+ list.each do |name|
+ raise "directory packages/#{name} does not exist"\
+ unless File.dir?("#{@ardir}/packages/#{name}")
+ end
+ @packages = list
+ end
+
+ #
+ # Task Handlers
+ #
+
+ def exec_config
+ run_hook 'pre-config'
+ each_selected_installers {|inst| inst.exec_config }
+ run_hook 'post-config'
+ @config.save # must be final
+ end
+
+ def exec_setup
+ run_hook 'pre-setup'
+ each_selected_installers {|inst| inst.exec_setup }
+ run_hook 'post-setup'
+ end
+
+ def exec_install
+ run_hook 'pre-install'
+ each_selected_installers {|inst| inst.exec_install }
+ run_hook 'post-install'
+ end
+
+ def exec_clean
+ rm_f 'config.save'
+ run_hook 'pre-clean'
+ each_selected_installers {|inst| inst.exec_clean }
+ run_hook 'post-clean'
+ end
+
+ def exec_distclean
+ rm_f 'config.save'
+ run_hook 'pre-distclean'
+ each_selected_installers {|inst| inst.exec_distclean }
+ run_hook 'post-distclean'
+ end
+
+ #
+ # lib
+ #
+
+ def each_selected_installers
+ Dir.mkdir 'packages' unless File.dir?('packages')
+ @selected.each do |pack|
+ $stderr.puts "Processing the package `#{pack}' ..." if @options['verbose']
+ Dir.mkdir "packages/#{pack}" unless File.dir?("packages/#{pack}")
+ Dir.chdir "packages/#{pack}"
+ yield @installers[pack]
+ Dir.chdir '../..'
+ end
+ end
+
+ def verbose?
+ @options['verbose']
+ end
+
+ def no_harm?
+ @options['no-harm']
+ end
+
+end
+
+
+class Installer
+
+ FILETYPES = %w( bin lib ext data )
+
+ include HookScriptAPI
+ include HookUtils
+ include FileOperations
+
+ def initialize(config, opt, srcroot, objroot)
+ @config = config
+ @options = opt
+ @srcdir = File.expand_path(srcroot)
+ @objdir = File.expand_path(objroot)
+ @currdir = '.'
+ end
+
+ def inspect
+ "#<#{self.class} #{File.basename(@srcdir)}>"
+ end
+
+ #
+ # Hook Script API bases
+ #
+
+ def srcdir_root
+ @srcdir
+ end
+
+ def objdir_root
+ @objdir
+ end
+
+ def relpath
+ @currdir
+ end
+
+ #
+ # configs/options
+ #
+
+ def no_harm?
+ @options['no-harm']
+ end
+
+ def verbose?
+ @options['verbose']
+ end
+
+ def verbose_off
+ begin
+ save, @options['verbose'] = @options['verbose'], false
+ yield
+ ensure
+ @options['verbose'] = save
+ end
+ end
+
+ #
+ # TASK config
+ #
+
+ def exec_config
+ exec_task_traverse 'config'
+ end
+
+ def config_dir_bin(rel)
+ end
+
+ def config_dir_lib(rel)
+ end
+
+ def config_dir_ext(rel)
+ extconf if extdir?(curr_srcdir())
+ end
+
+ def extconf
+ opt = @options['config-opt'].join(' ')
+ command "#{config('ruby-prog')} #{curr_srcdir()}/extconf.rb #{opt}"
+ end
+
+ def config_dir_data(rel)
+ end
+
+ #
+ # TASK setup
+ #
+
+ def exec_setup
+ exec_task_traverse 'setup'
+ end
+
+ def setup_dir_bin(rel)
+ all_files_in(curr_srcdir()).each do |fname|
+ adjust_shebang "#{curr_srcdir()}/#{fname}"
+ end
+ end
+
+ # modify: #!/usr/bin/ruby
+ # modify: #! /usr/bin/ruby
+ # modify: #!ruby
+ # not modify: #!/usr/bin/env ruby
+ SHEBANG_RE = /\A\#!\s*\S*ruby\S*/
+
+ def adjust_shebang(path)
+ return if no_harm?
+
+ tmpfile = File.basename(path) + '.tmp'
+ begin
+ File.open(path, 'rb') {|r|
+ File.open(tmpfile, 'wb') {|w|
+ first = r.gets
+ return unless SHEBANG_RE =~ first
+
+ $stderr.puts "adjusting shebang: #{File.basename path}" if verbose?
+ w.print first.sub(SHEBANG_RE, '#!' + config('ruby-path'))
+ w.write r.read
+ }
+ }
+ move_file tmpfile, File.basename(path)
+ ensure
+ File.unlink tmpfile if File.exist?(tmpfile)
+ end
+ end
+
+ def setup_dir_lib(rel)
+ end
+
+ def setup_dir_ext(rel)
+ make if extdir?(curr_srcdir())
+ end
+
+ def setup_dir_data(rel)
+ end
+
+ #
+ # TASK install
+ #
+
+ def exec_install
+ exec_task_traverse 'install'
+ end
+
+ def install_dir_bin(rel)
+ install_files collect_filenames_auto(), "#{config('bin-dir')}/#{rel}", 0755
+ end
+
+ def install_dir_lib(rel)
+ install_files ruby_scripts(), "#{config('rb-dir')}/#{rel}", 0644
+ end
+
+ def install_dir_ext(rel)
+ return unless extdir?(curr_srcdir())
+ install_files ruby_extentions('.'),
+ "#{config('so-dir')}/#{File.dirname(rel)}",
+ 0555
+ end
+
+ def install_dir_data(rel)
+ install_files collect_filenames_auto(), "#{config('data-dir')}/#{rel}", 0644
+ end
+
+ def install_files(list, dest, mode)
+ mkdir_p dest, @options['install-prefix']
+ list.each do |fname|
+ install fname, dest, mode, @options['install-prefix']
+ end
+ end
+
+ def ruby_scripts
+ collect_filenames_auto().select {|n| /\.rb\z/ =~ n }
+ end
+
+ # picked up many entries from cvs-1.11.1/src/ignore.c
+ reject_patterns = %w(
+ core RCSLOG tags TAGS .make.state
+ .nse_depinfo #* .#* cvslog.* ,* .del-* *.olb
+ *~ *.old *.bak *.BAK *.orig *.rej _$* *$
+
+ *.org *.in .*
+ )
+ mapping = {
+ '.' => '\.',
+ '$' => '\$',
+ '#' => '\#',
+ '*' => '.*'
+ }
+ REJECT_PATTERNS = Regexp.new('\A(?:' +
+ reject_patterns.map {|pat|
+ pat.gsub(/[\.\$\#\*]/) {|ch| mapping[ch] }
+ }.join('|') +
+ ')\z')
+
+ def collect_filenames_auto
+ mapdir((existfiles() - hookfiles()).reject {|fname|
+ REJECT_PATTERNS =~ fname
+ })
+ end
+
+ def existfiles
+ all_files_in(curr_srcdir()) | all_files_in('.')
+ end
+
+ def hookfiles
+ %w( pre-%s post-%s pre-%s.rb post-%s.rb ).map {|fmt|
+ %w( config setup install clean ).map {|t| sprintf(fmt, t) }
+ }.flatten
+ end
+
+ def mapdir(filelist)
+ filelist.map {|fname|
+ if File.exist?(fname) # objdir
+ fname
+ else # srcdir
+ File.join(curr_srcdir(), fname)
+ end
+ }
+ end
+
+ def ruby_extentions(dir)
+ _ruby_extentions(dir) or
+ raise InstallError, "no ruby extention exists: 'ruby #{$0} setup' first"
+ end
+
+ DLEXT = /\.#{ ::Config::CONFIG['DLEXT'] }\z/
+
+ def _ruby_extentions(dir)
+ Dir.open(dir) {|d|
+ return d.select {|fname| DLEXT =~ fname }
+ }
+ end
+
+ #
+ # TASK clean
+ #
+
+ def exec_clean
+ exec_task_traverse 'clean'
+ rm_f 'config.save'
+ rm_f 'InstalledFiles'
+ end
+
+ def clean_dir_bin(rel)
+ end
+
+ def clean_dir_lib(rel)
+ end
+
+ def clean_dir_ext(rel)
+ return unless extdir?(curr_srcdir())
+ make 'clean' if File.file?('Makefile')
+ end
+
+ def clean_dir_data(rel)
+ end
+
+ #
+ # TASK distclean
+ #
+
+ def exec_distclean
+ exec_task_traverse 'distclean'
+ rm_f 'config.save'
+ rm_f 'InstalledFiles'
+ end
+
+ def distclean_dir_bin(rel)
+ end
+
+ def distclean_dir_lib(rel)
+ end
+
+ def distclean_dir_ext(rel)
+ return unless extdir?(curr_srcdir())
+ make 'distclean' if File.file?('Makefile')
+ end
+
+ #
+ # lib
+ #
+
+ def exec_task_traverse(task)
+ run_hook "pre-#{task}"
+ FILETYPES.each do |type|
+ if config('without-ext') == 'yes' and type == 'ext'
+ $stderr.puts 'skipping ext/* by user option' if verbose?
+ next
+ end
+ traverse task, type, "#{task}_dir_#{type}"
+ end
+ run_hook "post-#{task}"
+ end
+
+ def traverse(task, rel, mid)
+ dive_into(rel) {
+ run_hook "pre-#{task}"
+ __send__ mid, rel.sub(%r[\A.*?(?:/|\z)], '')
+ all_dirs_in(curr_srcdir()).each do |d|
+ traverse task, "#{rel}/#{d}", mid
+ end
+ run_hook "post-#{task}"
+ }
+ end
+
+ def dive_into(rel)
+ return unless File.dir?("#{@srcdir}/#{rel}")
+
+ dir = File.basename(rel)
+ Dir.mkdir dir unless File.dir?(dir)
+ prevdir = Dir.pwd
+ Dir.chdir dir
+ $stderr.puts '---> ' + rel if verbose?
+ @currdir = rel
+ yield
+ Dir.chdir prevdir
+ $stderr.puts '<--- ' + rel if verbose?
+ @currdir = File.dirname(rel)
+ end
+
+end
+
+
+if $0 == __FILE__
+ begin
+ if multipackage_install?
+ ToplevelInstallerMulti.invoke
+ else
+ ToplevelInstaller.invoke
+ end
+ rescue
+ raise if $DEBUG
+ $stderr.puts $!.message
+ $stderr.puts "Try 'ruby #{$0} --help' for detailed usage."
+ exit 1
+ end
+end