diff --git a/.cmake-format.py b/.cmake-format.py new file mode 100644 index 0000000..68f0f78 --- /dev/null +++ b/.cmake-format.py @@ -0,0 +1,7 @@ +additional_commands = { + "pkg_find": { + "kwargs": { + "PKG": "*" + } + } +} \ No newline at end of file diff --git a/cmake/codestyle.cmake b/cmake/codestyle.cmake index 0ba3840..984ae4f 100644 --- a/cmake/codestyle.cmake +++ b/cmake/codestyle.cmake @@ -3,16 +3,19 @@ # Create format and lint rules for module files # # usage: +# ~~~ # format_and_lint(module # bar.h bar.cc # CMAKE CMakeLists.txt test/CMakeLists.txt # CC foo.h foo.cc # PY foo.py) -# +# ~~~ + # Will create rules `${module}_lint` and `${module}_format` using the standard # code formatters and lint checkers for the appropriate language. These # tools are: # +# ~~~ # CMAKE: # formatter: cmake-format # @@ -23,7 +26,7 @@ # PYTHON: # formatter: autopep8 # linter: pylint -# +# ~~~ function(format_and_lint module) set(cmake_files_) set(cc_files_) diff --git a/cmake_format/.sub/LICENSE b/cmake_format/.sub/LICENSE new file mode 100644 index 0000000..9cecc1d --- /dev/null +++ b/cmake_format/.sub/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + 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 . + +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: + + {project} Copyright (C) {year} {fullname} + 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 +. + + 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 +. diff --git a/cmake_format/.sub/requirements.txt b/cmake_format/.sub/requirements.txt new file mode 100644 index 0000000..2373925 --- /dev/null +++ b/cmake_format/.sub/requirements.txt @@ -0,0 +1,8 @@ +autopep8==1.3.5; python_version < '3.0' +autopep8==1.4.3; python_version >= '3.0' +flake8==3.6.0; python_version < '3.0' +flake8==3.7.7; python_version >= '3.0' +jinja2==2.10.1 +pylint==1.9.1; python_version < '3.0' +pylint==2.2.2; python_version >= '3.0' +pyyaml==4.2b1 diff --git a/cmake_format/.sub/sparse-checkout b/cmake_format/.sub/sparse-checkout new file mode 100644 index 0000000..a1279a5 --- /dev/null +++ b/cmake_format/.sub/sparse-checkout @@ -0,0 +1,10 @@ +/.cmake-format.py +/.gitignore +/.flake8 +/.pep8 +/cmake/*.cmake +/cmake_format +/CMakeLists.txt +/doc/conf.py +/Makefile +/pylintrc diff --git a/cmake_format/.sub/travis.yml b/cmake_format/.sub/travis.yml new file mode 100644 index 0000000..9f28740 --- /dev/null +++ b/cmake_format/.sub/travis.yml @@ -0,0 +1,13 @@ +dist: xenial +language: python +python: + - "2.7" + - "3.5" + - "3.6" + +install: + - pip install -r requirements.txt + +script: + - make test + - make lint diff --git a/cmake_format/CMakeLists.txt b/cmake_format/CMakeLists.txt index 7f2f98a..c9c48a6 100644 --- a/cmake_format/CMakeLists.txt +++ b/cmake_format/CMakeLists.txt @@ -1,18 +1,38 @@ format_and_lint(cmake_format + # cmake-format: sort __init__.py __main__.py + annotate.py commands.py + command_tests/add_custom_command_tests.py + command_tests/add_executable_tests.py + command_tests/add_library_tests.py + command_tests/conditional_tests.py + command_tests/export_tests.py + command_tests/file_tests.py + command_tests/__init__.py + command_tests/install_tests.py + command_tests/set_tests.py common.py configuration.py - format_tests.py + doc/update_readme.py formatter.py + format_tests.py invocation_tests.py - lexer_tests.py + layout_tests.py lexer.py - markup_tests.py + lexer_tests.py markup.py - parser_tests.py + markup_tests.py + parse_funs/add_xxx.py + parse_funs/external_project.py + parse_funs/fetch_content.py + parse_funs/file.py + parse_funs/__init__.py parser.py + parser_tests.py + pypi/setup.py + render.py tests.py) add_test(NAME cmake_format-format_tests @@ -56,3 +76,4 @@ if(NOT IS_TRAVIS_CI) endif() add_subdirectory(doc) +add_subdirectory(command_tests) diff --git a/cmake_format/__init__.py b/cmake_format/__init__.py index f2495d5..beb6781 100644 --- a/cmake_format/__init__.py +++ b/cmake_format/__init__.py @@ -3,4 +3,4 @@ """ from __future__ import unicode_literals -VERSION = '0.5.0' +VERSION = '0.5.1' diff --git a/cmake_format/command_tests/CMakeLists.txt b/cmake_format/command_tests/CMakeLists.txt new file mode 100644 index 0000000..1c2ceb2 --- /dev/null +++ b/cmake_format/command_tests/CMakeLists.txt @@ -0,0 +1,53 @@ +set(MODPREFIX cmake_format.command_tests) + +add_test(NAME cmake_format-add_custom_command_tests + COMMAND python -m ${MODPREFIX}.add_custom_command_tests + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) +add_test(NAME cmake_format-add_executable_tests + COMMAND python -m ${MODPREFIX}.add_executable_tests + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) +add_test(NAME cmake_format-add_library_tests + COMMAND python -m ${MODPREFIX}.add_library_tests + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) +add_test(NAME cmake_format-conditional_tests + COMMAND python -m ${MODPREFIX}.conditional_tests + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) +add_test(NAME cmake_format-export_tests + COMMAND python -m ${MODPREFIX}.export_tests + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) +add_test(NAME cmake_format-file_tests + COMMAND python -m ${MODPREFIX}.file_tests + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) +add_test(NAME cmake_format-install_tests + COMMAND python -m ${MODPREFIX}.install_tests + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) +add_test(NAME cmake_format-set_tests + COMMAND python -m ${MODPREFIX}.set_tests + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) + +if(NOT IS_TRAVIS_CI) + add_test(NAME cmake_format-add_custom_command_tests_py3 + COMMAND python3 -m ${MODPREFIX}.add_custom_command_tests + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) + add_test(NAME cmake_format-add_executable_tests_py3 + COMMAND python3 -m ${MODPREFIX}.add_executable_tests + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) + add_test(NAME cmake_format-add_library_tests_py3 + COMMAND python3 -m ${MODPREFIX}.add_library_tests + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) + add_test(NAME cmake_format-conditional_tests_py3 + COMMAND python3 -m ${MODPREFIX}.conditional_tests + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) + add_test(NAME cmake_format-export_tests_py3 + COMMAND python3 -m ${MODPREFIX}.export_tests + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) + add_test(NAME cmake_format-file_tests_py3 + COMMAND python3 -m ${MODPREFIX}.file_tests + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) + add_test(NAME cmake_format-install_tests_py3 + COMMAND python3 -m ${MODPREFIX}.install_tests + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) + add_test(NAME cmake_format-set_tests_py3 + COMMAND python3 -m ${MODPREFIX}.set_tests + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) +endif() diff --git a/cmake_format/command_tests/__init__.py b/cmake_format/command_tests/__init__.py index 97a3949..45f6e9f 100644 --- a/cmake_format/command_tests/__init__.py +++ b/cmake_format/command_tests/__init__.py @@ -257,15 +257,29 @@ def setUp(self): setattr(self, name, WrapTestWithRunFun(self, value)) def assertExpectations(self): - if self.expect_lex is not None: - with self.subTest(phase="lex"): + # Empty source_str is shorthand for "assertInvariant" + if self.source_str is None: + self.source_str = self.expect_format + + if sys.version_info < (3, 0, 0): + if self.expect_lex is not None: assert_lex(self, self.source_str, self.expect_lex) - if self.expect_parse is not None: - with self.subTest(phase="parse"): + if self.expect_parse is not None: assert_parse(self, self.source_str, self.expect_parse) - if self.expect_layout is not None: - with self.subTest(phase="layout"): + if self.expect_layout is not None: assert_layout(self, self.source_str, self.expect_layout) - if self.expect_format is not None: - with self.subTest(phase="format"): + if self.expect_format is not None: assert_format(self, self.source_str, self.expect_format) + else: + if self.expect_lex is not None: + with self.subTest(phase="lex"): # pylint: disable=no-member + assert_lex(self, self.source_str, self.expect_lex) + if self.expect_parse is not None: + with self.subTest(phase="parse"): # pylint: disable=no-member + assert_parse(self, self.source_str, self.expect_parse) + if self.expect_layout is not None: + with self.subTest(phase="layout"): # pylint: disable=no-member + assert_layout(self, self.source_str, self.expect_layout) + if self.expect_format is not None: + with self.subTest(phase="format"): # pylint: disable=no-member + assert_format(self, self.source_str, self.expect_format) diff --git a/cmake_format/command_tests/add_custom_command_tests.py b/cmake_format/command_tests/add_custom_command_tests.py index 4dae485..da21f10 100644 --- a/cmake_format/command_tests/add_custom_command_tests.py +++ b/cmake_format/command_tests/add_custom_command_tests.py @@ -1,4 +1,5 @@ # pylint: disable=bad-continuation +from __future__ import unicode_literals import unittest from cmake_format.command_tests import TestBase @@ -86,5 +87,6 @@ def test_single_argument(self): WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) """ + if __name__ == '__main__': unittest.main() diff --git a/cmake_format/command_tests/add_executable_tests.py b/cmake_format/command_tests/add_executable_tests.py index dea2f19..70a219c 100644 --- a/cmake_format/command_tests/add_executable_tests.py +++ b/cmake_format/command_tests/add_executable_tests.py @@ -1,4 +1,5 @@ # pylint: disable=bad-continuation +from __future__ import unicode_literals import unittest from cmake_format.command_tests import TestBase diff --git a/cmake_format/command_tests/add_library_tests.py b/cmake_format/command_tests/add_library_tests.py index 8995047..a6a920d 100644 --- a/cmake_format/command_tests/add_library_tests.py +++ b/cmake_format/command_tests/add_library_tests.py @@ -1,4 +1,5 @@ # pylint: disable=bad-continuation +from __future__ import unicode_literals import unittest from cmake_format.command_tests import TestBase diff --git a/cmake_format/command_tests/conditional_tests.py b/cmake_format/command_tests/conditional_tests.py index 46c63e8..674e9f5 100644 --- a/cmake_format/command_tests/conditional_tests.py +++ b/cmake_format/command_tests/conditional_tests.py @@ -1,4 +1,5 @@ # pylint: disable=bad-continuation +from __future__ import unicode_literals import unittest from cmake_format.command_tests import TestBase @@ -11,22 +12,6 @@ class TestConditionalCommands(TestBase): def test_complicated_boolean(self): self.config.max_subargs_per_line = 10 - self.source_str = """\ -set(matchme - "_DATA_\\|_CMAKE_\\|INTRA_PRED\\|_COMPILED\\|_HOSTING\\|_PERF_\\|CODER_") -if (("${var}" MATCHES "_TEST_" AND NOT - "${var}" MATCHES - "${matchme}") - OR (CONFIG_AV1_ENCODER AND CONFIG_ENCODE_PERF_TESTS AND - "${var}" MATCHES "_ENCODE_PERF_TEST_") - OR (CONFIG_AV1_DECODER AND CONFIG_DECODE_PERF_TESTS AND - "${var}" MATCHES "_DECODE_PERF_TEST_") - OR (CONFIG_AV1_ENCODER AND "${var}" MATCHES "_TEST_ENCODER_") - OR (CONFIG_AV1_DECODER AND "${var}" MATCHES "_TEST_DECODER_")) - list(APPEND aom_test_source_vars ${var}) -endif () -""" - self.expect_format = """\ set(matchme "_DATA_\\|_CMAKE_\\|INTRA_PRED\\|_COMPILED\\|_HOSTING\\|_PERF_\\|CODER_") if(("${var}" MATCHES "_TEST_" AND NOT "${var}" MATCHES "${matchme}") @@ -43,20 +28,27 @@ def test_complicated_boolean(self): """ def test_nested_parens(self): - self.source_str = """\ + self.expect_format = """\ if((NOT HELLO) OR (NOT EXISTS ${WORLD})) message(WARNING "something is wrong") set(foobar FALSE) endif() """ + def test_negated_single_nested_parens(self): self.expect_format = """\ -if((NOT HELLO) OR (NOT EXISTS ${WORLD})) - message(WARNING "something is wrong") - set(foobar FALSE) +if(NOT ("" STREQUALS "")) + # pass endif() """ + def test_conditional_in_if_and_endif(self): + self.expect_format = """\ +if(SOMETHING AND (NOT SOMETHING_ELSE STREQUAL "")) + # pass +endif(SOMETHING AND (NOT SOMETHING_ELSE STREQUAL "")) +""" + if __name__ == '__main__': unittest.main() diff --git a/cmake_format/command_tests/export_tests.py b/cmake_format/command_tests/export_tests.py new file mode 100644 index 0000000..b5f4388 --- /dev/null +++ b/cmake_format/command_tests/export_tests.py @@ -0,0 +1,20 @@ +# pylint: disable=bad-continuation +from __future__ import unicode_literals +import unittest + +from cmake_format.command_tests import TestBase + + +class TestExportCommand(TestBase): + """ + Test various examples of export() + """ + + def test_empty_parg_group(self): + self.expect_format = """\ +export(TARGETS FILE ${CMAKE_BINARY_DIR}/${CMAKE_PROJECT_NAME}Targets.cmake) +""" + + +if __name__ == '__main__': + unittest.main() diff --git a/cmake_format/command_tests/file_tests.py b/cmake_format/command_tests/file_tests.py index 9d2f408..530738c 100644 --- a/cmake_format/command_tests/file_tests.py +++ b/cmake_format/command_tests/file_tests.py @@ -1,4 +1,5 @@ # pylint: disable=bad-continuation +from __future__ import unicode_literals import unittest from cmake_format.command_tests import TestBase @@ -10,16 +11,68 @@ class TestFileCommands(TestBase): Test various examples of the file command """ + def test_file_read(self): + self.expect_format = """\ +file(READ foobar.baz foobar_content) +""" + + def test_file_strings(self): + self.expect_format = """\ +file(STRINGS foobar.baz foorbar_content REGEX hello) +""" + + def test_file_hash(self): + self.expect_format = """\ +file(SHA1 foobar.baz foobar_digest) +""" + + def test_file_timestamp(self): + self.expect_format = """\ +file(TIMESTAMP foobar.baz foobar_timestamp) +""" + def test_file_write(self): - self.source_str = r""" -file(WRITE ${CMAKE_BINARY_DIR}/${CMAKE_PROJECT_NAME}Config.cmake - "include(CMakeFindDependencyMacro)\n" - "include(\${X}/${CMAKE_PROJECT_NAME}Targets.cmake)\n") + self.expect_format = """\ +file(WRITE foobar.baz + "first line of the output file long enough to force a wrap" + "second line of the output file long enough to force a wrap") """ + def test_file_append(self): + self.expect_format = """\ +file(APPEND foobar.baz + "first line of the output file long enough to force a wrap" + "second line of the output file long enough to force a wrap") +""" + + def test_file_generate_output(self): + self.expect_format = """\ +file(GENERATE + OUTPUT foobar.baz + CONTENT "file content line one" # + "file content line two" + "file content line three" + CONDITION (FOO AND BAR) OR BAZ) +""" + + def test_file_glob(self): + self.expect_format = """\ +file(GLOB globout RELATIVE foo/bar/baz "*.py" "*.txt") +""" + + def test_file_copy(self): + self.expect_format = r""" +file(COPY foo bar baz + DESTINATION foobar + FILE_PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE + FILES_MATCHING + PATTERN "*.h" + REGEX ".*\\.cc") +"""[1:] + + def test_file_write_a(self): self.expect_parse = [ (NodeType.BODY, [ - (NodeType.WHITESPACE, []), (NodeType.STATEMENT, [ (NodeType.FUNNAME, []), (NodeType.LPAREN, []), @@ -46,6 +99,5 @@ def test_file_write(self): """[1:] - if __name__ == '__main__': unittest.main() diff --git a/cmake_format/command_tests/install_tests.py b/cmake_format/command_tests/install_tests.py index ae90ab8..016a487 100644 --- a/cmake_format/command_tests/install_tests.py +++ b/cmake_format/command_tests/install_tests.py @@ -1,4 +1,5 @@ # pylint: disable=bad-continuation +from __future__ import unicode_literals import unittest from cmake_format.command_tests import TestBase @@ -112,5 +113,6 @@ def test_kwarg_match_consumes(self): RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT runtime) """ + if __name__ == '__main__': unittest.main() diff --git a/cmake_format/command_tests/set_tests.py b/cmake_format/command_tests/set_tests.py index 871cb61..c66bdf6 100644 --- a/cmake_format/command_tests/set_tests.py +++ b/cmake_format/command_tests/set_tests.py @@ -1,9 +1,11 @@ # pylint: disable=bad-continuation +from __future__ import unicode_literals import unittest from cmake_format.command_tests import TestBase from cmake_format.parser import NodeType + class TestSetCommand(TestBase): """ Test various examples of the set() function @@ -114,5 +116,6 @@ def test_lots_of_args_command_split(self): source_g.cc) """ + if __name__ == '__main__': unittest.main() diff --git a/cmake_format/doc/README.rst b/cmake_format/doc/README.rst index aee7879..80fceb1 100644 --- a/cmake_format/doc/README.rst +++ b/cmake_format/doc/README.rst @@ -6,7 +6,7 @@ cmake format :target: https://travis-ci.com/cheshirekow/cmake_format .. image:: https://readthedocs.org/projects/cmake-format/badge/?version=latest - :target: https://cmake_format.readthedocs.io + :target: https://cmake-format.readthedocs.io ``cmake-format`` can format your listfiles nicely so that they don't look like crap. @@ -17,11 +17,17 @@ Installation Install from ``pypi`` using ``pip``:: - pip install --user cmake_format + pip install cmake_format -or:: +------------ +Integrations +------------ + +* There is an official `vscode extension`__ +* Someone also created a `sublime plugin`__ - sudo pip install cmake_format +.. __: https://marketplace.visualstudio.com/items?itemName=cheshirekow.cmake-format +.. __: https://packagecontrol.io/packages/CMakeFormat ----- Usage @@ -141,16 +147,6 @@ Usage .. tag: usage-end ------------- -Integrations ------------- - -* There is an official `vscode extension`__ -* Someone also created a `sublime plugin`__ - -.. __: https://marketplace.visualstudio.com/items?itemName=cheshirekow.cmake-format -.. __: https://packagecontrol.io/packages/CMakeFormat - ------------- Configuration ------------- @@ -215,7 +211,7 @@ pleasant way. # If true, the argument lists which are known to be sortable will be sorted # lexicographicall - autosort = False + autosort = True # enable comment markup parsing and reflow enable_markup = True @@ -276,6 +272,8 @@ by dumping out the default configuration in your preferred format. You can run ``cmake-format --dump-config [yaml|json|python]`` to print the default configuration ``stdout`` and use that as a starting point. +.. tag: features-begin + ------- Markup ------- @@ -360,8 +358,9 @@ comments ``# cmake-format: off`` and ``# cmake-format: on``. Sort Argument Lists ------------------- -``cmake-format`` can sort your argument lists for you. If the configuration -includes ``autosort=True`` (the default), it will replace:: +Starting with version `0.5.0`, ``cmake-format`` can sort your argument lists +for you. If the configuration includes ``autosort=True`` (the default), it +will replace:: add_library(foobar STATIC EXCLUDE_FROM_ALL sourcefile_06.cc @@ -426,9 +425,11 @@ Note that this is only needed if your configuration has enabled ``autosort``, and you can globally disable sorting by making setting this configuration to ``False``. ------- -Issues ------- +.. tag: features-end + +--------------------------------- +Reporting Issues and Getting Help +--------------------------------- If you encounter any bugs or regressions or if ``cmake-format`` doesn't behave in the way that you expect, please post an issue on the @@ -437,6 +438,11 @@ listfile snippets that demonstrate any issues you encounter. .. _`github issue tracker`: https://github.com/cheshirekow/cmake_format/issues +You can also join the ``#cmake-format`` channel on our discord server. + +.. _`discord server`: https://discord.gg/NgjwyPy + + ---------- Developers ---------- @@ -650,10 +656,10 @@ into this: if(sbar) # This comment is in-scope. add_library(foo_bar_baz - foo.cc bar.cc # this is a comment for arg2 this is more comment for # arg2, it should be joined with the first. - baz.cc) # This comment is part of add_library + baz.cc + foo.cc) # This comment is part of add_library other_command(some_long_argument some_long_argument) # this comment is very # long and gets split diff --git a/cmake_format/doc/changelog.rst b/cmake_format/doc/changelog.rst index ad76b0a..542cd90 100644 --- a/cmake_format/doc/changelog.rst +++ b/cmake_format/doc/changelog.rst @@ -6,8 +6,38 @@ Changelog v0.5 series ----------- -v0.5.0 -- in progress ---------------------- +v0.5.1 +------ + +* Fix empty kwarg can yield a parg group node with only whitespace + children +* Fix ``file(READ ...)`` and ``file(STRINGS ...)`` parser kwargs using set + syntax instead of dict syntax +* Fix agressive positional parser within conditional parser +* Fix missing endif, endwhile in parsemap +* Split parse functions out into separate modules for better organization +* Add more sanity tests for ``file(...)``. +* Remove README from online docs, replace with expanded documentation for + each README section +* Restore ability to accept paren-group in arbitrary parg-group +* Fix missing tests on travis +* Fix new tests using unicode literals (affects python2) +* Fix command parser after -- + +* Closes `#104`_: Extra space for export targets +* Closes `#106`_: Formatting of ``file(READ)`` fails +* Closes `#107`_: multiline cmake commands +* Closes `#108`_: Formatting of ``file(STRING)`` fails +* Closes `#110`_: Formatting of Nested Expressions Fails + +.. _#104: https://github.com/cheshirekow/cmake_format/issues/104 +.. _#106: https://github.com/cheshirekow/cmake_format/issues/106 +.. _#107: https://github.com/cheshirekow/cmake_format/issues/107 +.. _#108: https://github.com/cheshirekow/cmake_format/issues/108 +.. _#110: https://github.com/cheshirekow/cmake_format/issues/110 + +v0.5.0 +------ * Implement canonical command case * Canonicalize capitalization of keys in cmdspec diff --git a/cmake_format/doc/example.rst b/cmake_format/doc/example.rst new file mode 100644 index 0000000..0ebd85f --- /dev/null +++ b/cmake_format/doc/example.rst @@ -0,0 +1,240 @@ +------- +Example +------- + +Will turn this: + +.. tag: example-in-begin + +.. code:: cmake + + # The following multiple newlines should be collapsed into a single newline + + + + + cmake_minimum_required(VERSION 2.8.11) + project(cmake_format_test) + + # This multiline-comment should be reflowed + # into a single comment + # on one line + + # This comment should remain right before the command call. + # Furthermore, the command call should be formatted + # to a single line. + add_subdirectories(foo bar baz + foo2 bar2 baz2) + + # This very long command should be split to multiple lines + set(HEADERS very_long_header_name_a.h very_long_header_name_b.h very_long_header_name_c.h) + + # This command should be split into one line per entry because it has a long + # argument list. + set(SOURCES source_a.cc source_b.cc source_d.cc source_e.cc source_f.cc source_g.cc) + + # The string in this command should not be split + set_target_properties(foo bar baz PROPERTIES COMPILE_FLAGS "-std=c++11 -Wall -Wextra") + + # This command has a very long argument and can't be aligned with the command + # end, so it should be moved to a new line with block indent + 1. + some_long_command_name("Some very long argument that really needs to be on the next line.") + + # This situation is similar but the argument to a KWARG needs to be on a + # newline instead. + set(CMAKE_CXX_FLAGS "-std=c++11 -Wall -Wno-sign-compare -Wno-unused-parameter -xx") + + set(HEADERS header_a.h header_b.h # This comment should + # be preserved, moreover it should be split + # across two lines. + header_c.h header_d.h) + + + # This part of the comment should + # be formatted + # but... + # cmake-format: off + # This bunny should remain untouched: + # .   _ ∩ + #   レヘヽ| | + #     (・x・) + #    c( uu} + # cmake-format: on + # while this part should + # be formatted again + + # This is a paragraph + # + # This is a second paragraph + # + # This is a third paragraph + + # This is a comment + # that should be joined but + # TODO(josh): This todo should not be joined with the previous line. + # NOTE(josh): Also this should not be joined with the todo. + + if(foo) + if(sbar) + # This comment is in-scope. + add_library(foo_bar_baz foo.cc bar.cc # this is a comment for arg2 + # this is more comment for arg2, it should be joined with the first. + baz.cc) # This comment is part of add_library + + other_command(some_long_argument some_long_argument) # this comment is very long and gets split across some lines + + other_command(some_long_argument some_long_argument some_long_argument) # this comment is even longer and wouldn't make sense to pack at the end of the command so it gets it's own lines + endif() + endif() + + + # This very long command should be broken up along keyword arguments + foo(nonkwarg_a nonkwarg_b HEADERS a.h b.h c.h d.h e.h f.h SOURCES a.cc b.cc d.cc DEPENDS foo bar baz) + + # This command uses a string with escaped quote chars + foo(some_arg some_arg "This is a \"string\" within a string") + + # This command uses an empty string + foo(some_arg some_arg "") + + # This command uses a multiline string + foo(some_arg some_arg " + This string is on multiple lines + ") + + # No, I really want this to look ugly + # cmake-format: off + add_library(a b.cc + c.cc d.cc + e.cc) + # cmake-format: on + +.. tag: example-in-end + +into this: + +.. tag: example-out-begin + +.. code:: cmake + + # The following multiple newlines should be collapsed into a single newline + + cmake_minimum_required(VERSION 2.8.11) + project(cmake_format_test) + + # This multiline-comment should be reflowed into a single comment on one line + + # This comment should remain right before the command call. Furthermore, the + # command call should be formatted to a single line. + add_subdirectories(foo + bar + baz + foo2 + bar2 + baz2) + + # This very long command should be split to multiple lines + set(HEADERS very_long_header_name_a.h very_long_header_name_b.h + very_long_header_name_c.h) + + # This command should be split into one line per entry because it has a long + # argument list. + set(SOURCES + source_a.cc + source_b.cc + source_d.cc + source_e.cc + source_f.cc + source_g.cc) + + # The string in this command should not be split + set_target_properties(foo bar baz + PROPERTIES COMPILE_FLAGS "-std=c++11 -Wall -Wextra") + + # This command has a very long argument and can't be aligned with the command + # end, so it should be moved to a new line with block indent + 1. + some_long_command_name( + "Some very long argument that really needs to be on the next line.") + + # This situation is similar but the argument to a KWARG needs to be on a newline + # instead. + set(CMAKE_CXX_FLAGS + "-std=c++11 -Wall -Wno-sign-compare -Wno-unused-parameter -xx") + + set(HEADERS + header_a.h + header_b.h # This comment should be preserved, moreover it should be split + # across two lines. + header_c.h + header_d.h) + + # This part of the comment should be formatted but... + # cmake-format: off + # This bunny should remain untouched: + # .   _ ∩ + #   レヘヽ| | + #     (・x・) + #    c( uu} + # cmake-format: on + # while this part should be formatted again + + # This is a paragraph + # + # This is a second paragraph + # + # This is a third paragraph + + # This is a comment that should be joined but + # TODO(josh): This todo should not be joined with the previous line. + # NOTE(josh): Also this should not be joined with the todo. + + if(foo) + if(sbar) + # This comment is in-scope. + add_library(foo_bar_baz + bar.cc # this is a comment for arg2 this is more comment for + # arg2, it should be joined with the first. + baz.cc + foo.cc) # This comment is part of add_library + + other_command(some_long_argument some_long_argument) # this comment is very + # long and gets split + # across some lines + + other_command(some_long_argument some_long_argument some_long_argument) + # this comment is even longer and wouldn't make sense to pack at the end of + # the command so it gets it's own lines + endif() + endif() + + # This very long command should be broken up along keyword arguments + foo(nonkwarg_a nonkwarg_b + HEADERS a.h + b.h + c.h + d.h + e.h + f.h + SOURCES a.cc b.cc d.cc + DEPENDS foo + bar baz) + + # This command uses a string with escaped quote chars + foo(some_arg some_arg "This is a \"string\" within a string") + + # This command uses an empty string + foo(some_arg some_arg "") + + # This command uses a multiline string + foo(some_arg some_arg " + This string is on multiple lines + ") + + # No, I really want this to look ugly + # cmake-format: off + add_library(a b.cc + c.cc d.cc + e.cc) + # cmake-format: on + +.. tag: example-out-end diff --git a/cmake_format/doc/features.rst b/cmake_format/doc/features.rst new file mode 100644 index 0000000..fbd0dec --- /dev/null +++ b/cmake_format/doc/features.rst @@ -0,0 +1,154 @@ +======== +Features +======== + +------- +Markup +------- + +``cmake-format`` is for the exceptionally lazy. It will even format your +comments for you. It will reflow your comment text to within the configured +line width. It also understands a very limited markup format for a couple of +common bits. + +**rulers**: A ruler is a line which starts with and ends with three or more +non-alphanum or space characters:: + + # ---- This is a Ruler ---- + # cmake-format will know to keep the ruler separated from the + # paragraphs around it. So it wont try to reflow this text as + # a single paragraph. + # ---- This is also a Ruler --- + + +**list**: A list is started on the first encountered list item, which starts +with a bullet character (``*``) followed by a space followed by some text. +Subsequent lines will be included in the list item until the next list item +is encountered (the bullet must be at the same indentation level). The list +must be surrounded by a pair of empty lines. Nested lists will be formatted in +nested text:: + + # here are some lists: + # + # * item 1 + # * item 2 + # + # * subitem 1 + # * subitem 2 + # + # * second list item 1 + # * second list item 2 + +**enumerations**: An enumeration is similar to a list but the bullet character +is some integers followed by a period. New enumeration items are detected as +long as either the first digit or the punctuation lines up in the same column +as the previous item. ``cmake-format`` will renumber your items and align their +labels for you:: + + # This is an enumeration + # + # 1. item + # 2. item + # 3. item + +**fences**: If you have any text which you do not want to be formatted you can +guard it with a pair of fences. Fences are three or more tilde characters:: + + # ~~~ + # This comment is fenced + # and will not be formatted + # ~~~ + +Note that comment fences guard reflow of *comment text*, and not cmake code. +If you wish to prevent formatting of cmake, code, see below. In addition to +fenced-literals, there are three other ways to preserve comment text from +markup and/or reflow processing: + +* The ``--first-comment-is-literal`` configuration option will exactly preserve + the first comment in the file. This is intended to preserve copyright or + other formatted header comments. +* The ``--literal-comment-pattern`` configuration option allows for a more + generic way to identify comments which should be preserved literally. This + configuration takes a regular expression pattern. +* The ``--enable-markup`` configuration option globally enables comment markup + processing. It defaults to true so set it to false if you wish to globally + disable comment markup processing. Note that trailing whitespace is still + chomped from comments. + +-------------------------- +Disable Formatting Locally +-------------------------- + +You can locally disable and enable code formatting by using the special +comments ``# cmake-format: off`` and ``# cmake-format: on``. + +------------------- +Sort Argument Lists +------------------- + +Starting with version `0.5.0`, ``cmake-format`` can sort your argument lists +for you. If the configuration includes ``autosort=True`` (the default), it +will replace:: + + add_library(foobar STATIC EXCLUDE_FROM_ALL + sourcefile_06.cc + sourcefile_03.cc + sourcefile_02.cc + sourcefile_04.cc + sourcefile_07.cc + sourcefile_01.cc + sourcefile_05.cc) + +with:: + + add_library(foobar STATIC EXCLUDE_FROM_ALL + sourcefile_01.cc + sourcefile_02.cc + sourcefile_03.cc + sourcefile_04.cc + sourcefile_05.cc + sourcefile_06.cc + sourcefile_07.cc) + +This is implemented for any argument lists which the parser knows are +inherently sortable. This includes the following cmake commands: + +* ``add_library`` +* ``add_executable`` + +For most other cmake commands, you can use an annotation comment to hint to +``cmake-format`` that the argument list is sortable. For instance:: + + set(SOURCES + # cmake-format: sortable + bar.cc + baz.cc + foo.cc) + +Annotations can be given in a line-comment or a bracket comment. There is a +long-form and a short-form for each. The acceptable formats are: + ++-----------------+-------+------------------------------+ +| Line Comment | long | ``# cmake-format: `` | ++-----------------+-------+------------------------------+ +| Line Comment | short | ``# cmf: `` | ++-----------------+-------+------------------------------+ +| Bracket Comment | long | ``#[[cmake-format: ]]`` | ++-----------------+-------+------------------------------+ +| Bracket Comment | short | ``#[[cmf: ]]`` | ++-----------------+-------+------------------------------+ + +In order to annotate a positional argument list as sortable, the acceptable +tags are: ``sortable`` or ``sort``. For the commands listed above where +the positinal argument lists are inherently sortable, you can locally disable +sorting by annotating them with ``unsortable`` or ``unsort``. For example:: + + add_library(foobar STATIC + # cmake-format: unsort + sourcefile_03.cc + sourcefile_01.cc + sourcefile_02.cc) + +Note that this is only needed if your configuration has enabled ``autosort``, +and you can globally disable sorting by making setting this configuration to +``False``. diff --git a/cmake_format/doc/index.rst b/cmake_format/doc/index.rst index 54bbfda..bc69bd2 100644 --- a/cmake_format/doc/index.rst +++ b/cmake_format/doc/index.rst @@ -15,10 +15,13 @@ like crap. :maxdepth: 2 :caption: Contents: - README - render_html + installation + features + usage + example parse_tree format_algorithm + render_html release_notes changelog diff --git a/cmake_format/doc/installation.rst b/cmake_format/doc/installation.rst new file mode 100644 index 0000000..d6cd1f3 --- /dev/null +++ b/cmake_format/doc/installation.rst @@ -0,0 +1,72 @@ +============ +Installation +============ + +Install with pip +================ + +The easiest way to install ``cmake-format`` is from `pypi.org`_ +using `pip`_. For example:: + + pip install cmake_format + +If you're on a linux-type system (such as ubuntu) the above command might not +work if it would install into a system-wide location. If that's what you +really want you might need to use :code:`sudo`, e.g.:: + + sudo pip install cmake_format + +In general though I wouldn't really recommend doing that though since things +can get pretty messy between your system python distributions and your +:code:`pip` managed directories. Alternatively you can install it for your user +with:: + + pip install --user cmake_format + +which I would probably recommend for most users. + +.. note:: + + If you wish to use a configuration file in YAML format you'll want to + install with the optional ``YAML`` feature, e.g.:: + + pip install cmake_format[YAML] + +.. _`pypi.org`: https://pypi.org/project/cmake-format/ +.. _pip: https://pip.pypa.io/en/stable/ + +Install from source +=================== + +You can also install from source with pip. You can download a release_ package +from github and then install it directly with pip. For example:: + + pip install v0.5.0.tar.gz + +.. _release: https://github.com/cheshirekow/cmake_format/releases + +Note that the release packages are automatically generated from git tags which +are the same commit used to generate the corresponding version package on +``pypi.org``. So whether you install a particular version from github or +pypi shouldn't matter. + +Pip can also install directly from github. For example:: + + pip install git+https://github.com/cheshirekow/cmake_format.git + +If you wish to test a pre-release or dev package from a branch called +``foobar`` you can install it with:: + + pip install "git+https://github.com/cheshirekow/cmake_format.git@foobar" + +IDE Integrations +================ + +* There is an official `vscode extension`__ +* Someone also created a `sublime plugin`__ + +.. __: https://marketplace.visualstudio.com/items?itemName=cheshirekow.cmake-format +.. __: https://packagecontrol.io/packages/CMakeFormat + +Note that for both plugins ``cmake-format`` itself must be installed +separately. diff --git a/cmake_format/doc/release_notes.rst b/cmake_format/doc/release_notes.rst index c2682c5..5b4af9d 100644 --- a/cmake_format/doc/release_notes.rst +++ b/cmake_format/doc/release_notes.rst @@ -8,6 +8,20 @@ some high level notes and highlights from each release. v0.5 series =========== +------ +v0.5.1 +------ + +The 0.5.0 release involved some pretty big changes to the parsing engine and +introduced a new format algorithm. These two things combined unfortunately +lead to a lot of new bugs. The full battery of pre-release tests wasn't run +and so a lot of those issues popped up after release. Hopefully most of those +are squashed in this release. + +* Fixed lots of bugs introduced in 0.5.0 +* ``cmake-format`` has a channel on discord now. Come chat about it at + https://discord.gg/NgjwyPy + ------ v0.5.0 ------ diff --git a/cmake_format/doc/todo.rst b/cmake_format/doc/todo.rst index 10f5405..02c7a4d 100644 --- a/cmake_format/doc/todo.rst +++ b/cmake_format/doc/todo.rst @@ -106,6 +106,8 @@ Parser Refactor we've implemented. * Add a config option for users to specify custom commands using custom parse functions, rather than just the legacy dictionary specification. +* Split parse_funs into modules to better organize custom parsers +* Implement custom parser for the different forms of ``list()`` Documentation ============= @@ -116,3 +118,11 @@ Documentation reuse snippets, possibly through some python scripting to generate the README page, but the README should probably contain a more compressed subset of the information on the documentation pages. + +Current Issues +============== + +* Need some kind of fallback for commands like `file()` when the descriminator + argument is a variable dereference. For instance `file(${descr})`. What + should we do in that case? Should we infer based on remaining arguments, + fallback to a standard parser with a large set of kwargs and flags? diff --git a/cmake_format/doc/update_readme.py b/cmake_format/doc/update_readme.py index 20b319f..4dcbb44 100644 --- a/cmake_format/doc/update_readme.py +++ b/cmake_format/doc/update_readme.py @@ -11,6 +11,7 @@ import subprocess import sys + def format_directive(content, codetag): outlines = [".. code:: {}".format(codetag), ""] for line in content.split("\n"): @@ -18,6 +19,38 @@ def format_directive(content, codetag): outlines.append("") return "\n".join(outlines) + +def process_file(filepath, dynamic_text): + """ + Create a copy of the file replacing any dynamic sections with updated + text. Then replace the original with the updated copy. + """ + tag_pattern = re.compile("^.. tag: (.*)-(begin|end)$") + active_section = None + + nextpath = filepath + ".next" + with open(filepath, "r") as infile: + with open(nextpath, "w") as outfile: + for line in infile: + match = tag_pattern.match(line.strip()) + if active_section is None: + outfile.write(line) + + if match: + if match.group(2) == "begin": + active_section = match.group(1) + elif match.group(2) == "end": + assert active_section == match.group(1), "Unexpected end tag" + outfile.write("\n") + outfile.write(dynamic_text[active_section]) + active_section = None + outfile.write(line) + else: + raise RuntimeError("Unexpected tag") + + os.rename(nextpath, filepath) + + def main(): docdir = os.path.dirname(os.path.realpath(__file__)) projectdir = os.path.dirname(docdir) @@ -29,41 +62,31 @@ def main(): dynamic_text["usage"] = format_directive( subprocess.check_output( [sys.executable, "-Bm", "cmake_format", "--help"], env=env - ).decode("utf-8"), + ).decode("utf-8"), "text") dynamic_text["configuration"] = format_directive( subprocess.check_output( [sys.executable, "-Bm", "cmake_format", "--dump-config"], env=env - ).decode("utf-8"), + ).decode("utf-8"), "text") + with open(os.path.join(docdir, "features.rst")) as infile: + copylines = [] + for idx, line in enumerate(infile): + if idx > 3: + copylines.append(line) + copylines.append("\n") + dynamic_text["features"] = "".join(copylines) + with open("test/test_in.cmake") as infile: dynamic_text["example-in"] = format_directive(infile.read(), "cmake") with open("test/test_out.cmake") as infile: dynamic_text["example-out"] = format_directive(infile.read(), "cmake") - tag_pattern = re.compile("^.. tag: (.*)-(begin|end)$") - active_section = None - with open("doc/README.rst", "r") as infile: - with open("doc/README.rst.next", "w") as outfile: - for line in infile: - match = tag_pattern.match(line.strip()) - if active_section is None: - outfile.write(line) - - if match: - if match.group(2) == "begin": - active_section = match.group(1) - elif match.group(2) == "end": - assert active_section == match.group(1), "Unexpected end tag" - outfile.write("\n") - outfile.write(dynamic_text[active_section]) - active_section = None - outfile.write(line) - else: - raise RuntimeError("Unexpected tag") + process_file("doc/README.rst", dynamic_text) + process_file("doc/usage.rst", dynamic_text) + process_file("doc/example.rst", dynamic_text) - os.rename("doc/README.rst.next", "doc/README.rst") if __name__ == "__main__": main() diff --git a/cmake_format/doc/usage.rst b/cmake_format/doc/usage.rst new file mode 100644 index 0000000..4edc9b5 --- /dev/null +++ b/cmake_format/doc/usage.rst @@ -0,0 +1,257 @@ +======================= +Configuration and Usage +======================= + +------------- +Configuration +------------- + +``cmake-format`` accepts configuration files in yaml, json, or python format. + +.. note:: + + ``cmake-format`` requires the ``pyyaml`` python package in order to + consume yaml as the configuration file. This dependency is not enforced + by default during installation since this is an optional feature. It can + be enabled by installing with a command like + ``pip install cmake_format[YAML]`` + +An example configuration file is given here. Additional flags and additional +kwargs will help ``cmake-format`` to break up your custom commands in a +pleasant way. + +.. tag: configuration-begin + +.. code:: text + + # How wide to allow formatted cmake files + line_width = 80 + + # How many spaces to tab for indent + tab_size = 2 + + # If arglists are longer than this, break them always + max_subargs_per_line = 3 + + # If true, separate flow control names from their parentheses with a space + separate_ctrl_name_with_space = False + + # If true, separate function names from parentheses with a space + separate_fn_name_with_space = False + + # If a statement is wrapped to more than one line, than dangle the closing + # parenthesis on it's own line + dangle_parens = False + + # What character to use for bulleted lists + bullet_char = '*' + + # What character to use as punctuation after numerals in an enumerated list + enum_char = '.' + + # What style line endings to use in the output. + line_ending = 'unix' + + # Format command names consistently as 'lower' or 'upper' case + command_case = 'canonical' + + # Format keywords consistently as 'lower' or 'upper' case + keyword_case = 'unchanged' + + # Specify structure for custom cmake functions + additional_commands = { + "pkg_find": { + "kwargs": { + "PKG": "*" + } + } + } + + # A list of command names which should always be wrapped + always_wrap = [] + + # Specify the order of wrapping algorithms during successive reflow attempts + algorithm_order = [0, 1, 2, 3, 4] + + # If true, the argument lists which are known to be sortable will be sorted + # lexicographicall + autosort = True + + # enable comment markup parsing and reflow + enable_markup = True + + # If comment markup is enabled, don't reflow the first comment block in + # eachlistfile. Use this to preserve formatting of your + # copyright/licensestatements. + first_comment_is_literal = False + + # If comment markup is enabled, don't reflow any comment block which matchesthis + # (regex) pattern. Default is `None` (disabled). + literal_comment_pattern = None + + # Regular expression to match preformat fences in comments + # default=r'^\s*([`~]{3}[`~]*)(.*)$' + fence_pattern = '^\\s*([`~]{3}[`~]*)(.*)$' + + # Regular expression to match rulers in comments + # default=r'^\s*[^\w\s]{3}.*[^\w\s]{3}$' + ruler_pattern = '^\\s*[^\\w\\s]{3}.*[^\\w\\s]{3}$' + + # If true, emit the unicode byte-order mark (BOM) at the start of the file + emit_byteorder_mark = False + + # If a comment line starts with at least this many consecutive hash characters, + # then don't lstrip() them off. This allows for lazy hash rulers where the first + # hash char is not separated by space + hashruler_min_length = 10 + + # If true, then insert a space between the first hash char and remaining hash + # chars in a hash ruler, and normalize it's length to fill the column + canonicalize_hashrulers = True + + # Specify the encoding of the input file. Defaults to utf-8. + input_encoding = 'utf-8' + + # Specify the encoding of the output file. Defaults to utf-8. Note that cmake + # only claims to support utf-8 so be careful when using anything else + output_encoding = 'utf-8' + + # A dictionary containing any per-command configuration overrides. Currently + # only `command_case` is supported. + per_command = {} + + +.. tag: configuration-end + +You may specify a path to a configuration file with the ``--config-file`` +command line option. Otherwise, ``cmake-format`` will search the ancestry +of each ``infilepath`` looking for a configuration file to use. If no +configuration file is found it will use sensible defaults. + +A automatically detected configuration files may have any name that matches +``\.?cmake-format(.yaml|.json|.py)``. + +If you'd like to create a new configuration file, ``cmake-format`` can help +by dumping out the default configuration in your preferred format. You can run +``cmake-format --dump-config [yaml|json|python]`` to print the default +configuration ``stdout`` and use that as a starting point. + + +----- +Usage +----- + + +.. tag: usage-begin + +.. code:: text + + usage: + cmake-format [-h] + [--dump-config {yaml,json,python} | -i | -o OUTFILE_PATH] + [-c CONFIG_FILE] + infilepath [infilepath ...] + + Parse cmake listfiles and format them nicely. + + Formatting is configurable by providing a configuration file. The configuration + file can be in json, yaml, or python format. If no configuration file is + specified on the command line, cmake-format will attempt to find a suitable + configuration for each ``inputpath`` by checking recursively checking it's + parent directory up to the root of the filesystem. It will return the first + file it finds with a filename that matches '\.?cmake-format(.yaml|.json|.py)'. + + cmake-format can spit out the default configuration for you as starting point + for customization. Run with `--dump-config [yaml|json|python]`. + + positional arguments: + infilepaths + + optional arguments: + -h, --help show this help message and exit + -v, --version show program's version number and exit + --dump-config [{yaml,json,python}] + If specified, print the default configuration to + stdout and exit + --dump {lex,parse,layout,markup} + -i, --in-place + -o OUTFILE_PATH, --outfile-path OUTFILE_PATH + Where to write the formatted file. Default is stdout. + -c CONFIG_FILE, --config-file CONFIG_FILE + path to configuration file + + Formatter Configuration: + Override configfile options + + --line-width LINE_WIDTH + How wide to allow formatted cmake files + --tab-size TAB_SIZE How many spaces to tab for indent + --max-subargs-per-line MAX_SUBARGS_PER_LINE + If arglists are longer than this, break them always + --separate-ctrl-name-with-space [SEPARATE_CTRL_NAME_WITH_SPACE] + If true, separate flow control names from their + parentheses with a space + --separate-fn-name-with-space [SEPARATE_FN_NAME_WITH_SPACE] + If true, separate function names from parentheses with + a space + --dangle-parens [DANGLE_PARENS] + If a statement is wrapped to more than one line, than + dangle the closing parenthesis on it's own line + --bullet-char BULLET_CHAR + What character to use for bulleted lists + --enum-char ENUM_CHAR + What character to use as punctuation after numerals in + an enumerated list + --line-ending {windows,unix,auto} + What style line endings to use in the output. + --command-case {lower,upper,canonical,unchanged} + Format command names consistently as 'lower' or + 'upper' case + --keyword-case {lower,upper,unchanged} + Format keywords consistently as 'lower' or 'upper' + case + --always-wrap [ALWAYS_WRAP [ALWAYS_WRAP ...]] + A list of command names which should always be wrapped + --algorithm-order [ALGORITHM_ORDER [ALGORITHM_ORDER ...]] + Specify the order of wrapping algorithms during + successive reflow attempts + --autosort [AUTOSORT] + If true, the argument lists which are known to be + sortable will be sorted lexicographicall + --enable-markup [ENABLE_MARKUP] + enable comment markup parsing and reflow + --first-comment-is-literal [FIRST_COMMENT_IS_LITERAL] + If comment markup is enabled, don't reflow the first + comment block in eachlistfile. Use this to preserve + formatting of your copyright/licensestatements. + --literal-comment-pattern LITERAL_COMMENT_PATTERN + If comment markup is enabled, don't reflow any comment + block which matchesthis (regex) pattern. Default is + `None` (disabled). + --fence-pattern FENCE_PATTERN + Regular expression to match preformat fences in + comments default=r'^\s*([`~]{3}[`~]*)(.*)$' + --ruler-pattern RULER_PATTERN + Regular expression to match rulers in comments + default=r'^\s*[^\w\s]{3}.*[^\w\s]{3}$' + --emit-byteorder-mark [EMIT_BYTEORDER_MARK] + If true, emit the unicode byte-order mark (BOM) at the + start of the file + --hashruler-min-length HASHRULER_MIN_LENGTH + If a comment line starts with at least this many + consecutive hash characters, then don't lstrip() them + off. This allows for lazy hash rulers where the first + hash char is not separated by space + --canonicalize-hashrulers [CANONICALIZE_HASHRULERS] + If true, then insert a space between the first hash + char and remaining hash chars in a hash ruler, and + normalize it's length to fill the column + --input-encoding INPUT_ENCODING + Specify the encoding of the input file. Defaults to + utf-8. + --output-encoding OUTPUT_ENCODING + Specify the encoding of the output file. Defaults to + utf-8. Note that cmake only claims to support utf-8 so + be careful when using anything else + +.. tag: usage-end diff --git a/cmake_format/formatter.py b/cmake_format/formatter.py index 2a7e9ce..b025367 100644 --- a/cmake_format/formatter.py +++ b/cmake_format/formatter.py @@ -1489,7 +1489,7 @@ def dump_tree_for_test(nodes, outfile=None, indent=None, increment=None): indent = '' if increment is None: - increment = ' ' + increment = ' ' if outfile is None: outfile = sys.stdout @@ -1509,9 +1509,9 @@ def dump_tree_for_test(nodes, outfile=None, indent=None, increment=None): def test_string(nodes, indent=None, increment=None): if indent is None: - indent = ' ' * 10 + indent = ' ' * 0 if increment is None: - increment = ' ' * 4 + increment = ' ' * 2 outfile = io.StringIO() dump_tree_for_test(nodes, outfile, indent, increment) diff --git a/cmake_format/layout_tests.py b/cmake_format/layout_tests.py index daaf352..57770fd 100644 --- a/cmake_format/layout_tests.py +++ b/cmake_format/layout_tests.py @@ -269,85 +269,78 @@ def test_complex_nested_stuff(self): endif() """, [ # pylint: disable=bad-continuation +# noqa: E122 (NodeType.BODY, WrapAlgo.HPACK, 0, 0, 79, [ - (NodeType.FLOW_CONTROL, WrapAlgo.HPACK, 0, 0, 79, [ - (NodeType.STATEMENT, WrapAlgo.HPACK, 0, 0, 7, [ - (NodeType.FUNNAME, WrapAlgo.HPACK, 0, 0, 2, []), - (NodeType.LPAREN, WrapAlgo.HPACK, 0, 2, 3, []), - (NodeType.PARGGROUP, WrapAlgo.HPACK, 0, 3, 6, [ - (NodeType.ARGUMENT, WrapAlgo.HPACK, 0, 3, 6, []), - ]), - (NodeType.RPAREN, WrapAlgo.HPACK, 0, 6, 7, []), + (NodeType.FLOW_CONTROL, WrapAlgo.HPACK, 0, 0, 79, [ + (NodeType.STATEMENT, WrapAlgo.HPACK, 0, 0, 7, [ + (NodeType.FUNNAME, WrapAlgo.HPACK, 0, 0, 2, []), + (NodeType.LPAREN, WrapAlgo.HPACK, 0, 2, 3, []), + (NodeType.ARGUMENT, WrapAlgo.HPACK, 0, 3, 6, []), + (NodeType.RPAREN, WrapAlgo.HPACK, 0, 6, 7, []), + ]), + (NodeType.BODY, WrapAlgo.HPACK, 1, 2, 79, [ + (NodeType.FLOW_CONTROL, WrapAlgo.HPACK, 1, 2, 79, [ + (NodeType.STATEMENT, WrapAlgo.HPACK, 1, 2, 10, [ + (NodeType.FUNNAME, WrapAlgo.HPACK, 1, 2, 4, []), + (NodeType.LPAREN, WrapAlgo.HPACK, 1, 4, 5, []), + (NodeType.ARGUMENT, WrapAlgo.HPACK, 1, 5, 9, []), + (NodeType.RPAREN, WrapAlgo.HPACK, 1, 9, 10, []), ]), - (NodeType.BODY, WrapAlgo.HPACK, 1, 2, 79, [ - (NodeType.FLOW_CONTROL, WrapAlgo.HPACK, 1, 2, 79, [ - (NodeType.STATEMENT, WrapAlgo.HPACK, 1, 2, 10, [ - (NodeType.FUNNAME, WrapAlgo.HPACK, 1, 2, 4, []), - (NodeType.LPAREN, WrapAlgo.HPACK, 1, 4, 5, []), - (NodeType.PARGGROUP, WrapAlgo.HPACK, 1, 5, 9, [ - (NodeType.ARGUMENT, WrapAlgo.HPACK, 1, 5, 9, []), - ]), - (NodeType.RPAREN, WrapAlgo.HPACK, 1, 9, 10, []), - ]), - (NodeType.BODY, WrapAlgo.HPACK, 2, 4, 79, [ - (NodeType.COMMENT, WrapAlgo.HPACK, 2, 4, 31, []), - (NodeType.STATEMENT, WrapAlgo.VPACK, 3, 4, 76, [ - (NodeType.FUNNAME, WrapAlgo.HPACK, 3, 4, 15, []), - (NodeType.LPAREN, WrapAlgo.HPACK, 3, 15, 16, []), - (NodeType.PARGGROUP, WrapAlgo.HPACK, 3, 16, 27, [ - (NodeType.ARGUMENT, WrapAlgo.HPACK, 3, 16, 27, []), - ]), - - (NodeType.PARGGROUP, WrapAlgo.VPACK, 4, 16, 76, [ - (NodeType.ARGUMENT, WrapAlgo.HPACK, 4, 16, 22, []), - (NodeType.ARGUMENT, WrapAlgo.VPACK, 5, 16, 76, [ - (NodeType.COMMENT, WrapAlgo.HPACK, 5, 23, 76, []), - ]), - (NodeType.ARGUMENT, WrapAlgo.HPACK, 7, 16, 22, []), - ]), - (NodeType.RPAREN, WrapAlgo.HPACK, 7, 22, 23, []), - (NodeType.COMMENT, WrapAlgo.HPACK, 7, 24, 61, []), - - ]), - (NodeType.WHITESPACE, WrapAlgo.HPACK, 8, 4, 0, []), - (NodeType.STATEMENT, WrapAlgo.HPACK, 9, 4, 79, [ - (NodeType.FUNNAME, WrapAlgo.HPACK, 9, 4, 17, []), - (NodeType.LPAREN, WrapAlgo.HPACK, 9, 17, 18, []), - (NodeType.PARGGROUP, WrapAlgo.HPACK, 9, 18, 55, [ - (NodeType.ARGUMENT, WrapAlgo.HPACK, 9, 18, 36, []), - (NodeType.ARGUMENT, WrapAlgo.HPACK, 9, 37, 55, []), - ]), - (NodeType.RPAREN, WrapAlgo.HPACK, 9, 55, 56, []), - (NodeType.COMMENT, WrapAlgo.HPACK, 9, 57, 79, []), - ]), - (NodeType.WHITESPACE, WrapAlgo.HPACK, 12, 4, 0, []), - (NodeType.STATEMENT, WrapAlgo.VPACK, 13, 4, 79, [ - (NodeType.FUNNAME, WrapAlgo.HPACK, 13, 4, 17, []), - (NodeType.LPAREN, WrapAlgo.HPACK, 13, 17, 18, []), - (NodeType.PARGGROUP, WrapAlgo.HPACK, 13, 18, 74, [ - (NodeType.ARGUMENT, WrapAlgo.HPACK, 13, 18, 36, []), - (NodeType.ARGUMENT, WrapAlgo.HPACK, 13, 37, 55, []), - (NodeType.ARGUMENT, WrapAlgo.HPACK, 13, 56, 74, []), - ]), - (NodeType.RPAREN, WrapAlgo.HPACK, 13, 74, 75, []), - (NodeType.COMMENT, WrapAlgo.HPACK, 14, 4, 79, []), - ]), - ]), - (NodeType.STATEMENT, WrapAlgo.HPACK, 16, 2, 9, [ - (NodeType.FUNNAME, WrapAlgo.HPACK, 16, 2, 7, []), - (NodeType.LPAREN, WrapAlgo.HPACK, 16, 7, 8, []), - (NodeType.PARGGROUP, WrapAlgo.HPACK, 16, 8, 8, []), - (NodeType.RPAREN, WrapAlgo.HPACK, 16, 8, 9, []), - ]), + (NodeType.BODY, WrapAlgo.HPACK, 2, 4, 79, [ + (NodeType.COMMENT, WrapAlgo.HPACK, 2, 4, 31, []), + (NodeType.STATEMENT, WrapAlgo.VPACK, 3, 4, 76, [ + (NodeType.FUNNAME, WrapAlgo.HPACK, 3, 4, 15, []), + (NodeType.LPAREN, WrapAlgo.HPACK, 3, 15, 16, []), + (NodeType.PARGGROUP, WrapAlgo.HPACK, 3, 16, 27, [ + (NodeType.ARGUMENT, WrapAlgo.HPACK, 3, 16, 27, []), ]), + (NodeType.PARGGROUP, WrapAlgo.VPACK, 4, 16, 76, [ + (NodeType.ARGUMENT, WrapAlgo.HPACK, 4, 16, 22, []), + (NodeType.ARGUMENT, WrapAlgo.VPACK, 5, 16, 76, [ + (NodeType.COMMENT, WrapAlgo.HPACK, 5, 23, 76, []), + ]), + (NodeType.ARGUMENT, WrapAlgo.HPACK, 7, 16, 22, []), + ]), + (NodeType.RPAREN, WrapAlgo.HPACK, 7, 22, 23, []), + (NodeType.COMMENT, WrapAlgo.HPACK, 7, 24, 61, []), + ]), + (NodeType.WHITESPACE, WrapAlgo.HPACK, 8, 4, 0, []), + (NodeType.STATEMENT, WrapAlgo.HPACK, 9, 4, 79, [ + (NodeType.FUNNAME, WrapAlgo.HPACK, 9, 4, 17, []), + (NodeType.LPAREN, WrapAlgo.HPACK, 9, 17, 18, []), + (NodeType.PARGGROUP, WrapAlgo.HPACK, 9, 18, 55, [ + (NodeType.ARGUMENT, WrapAlgo.HPACK, 9, 18, 36, []), + (NodeType.ARGUMENT, WrapAlgo.HPACK, 9, 37, 55, []), + ]), + (NodeType.RPAREN, WrapAlgo.HPACK, 9, 55, 56, []), + (NodeType.COMMENT, WrapAlgo.HPACK, 9, 57, 79, []), + ]), + (NodeType.WHITESPACE, WrapAlgo.HPACK, 12, 4, 0, []), + (NodeType.STATEMENT, WrapAlgo.VPACK, 13, 4, 79, [ + (NodeType.FUNNAME, WrapAlgo.HPACK, 13, 4, 17, []), + (NodeType.LPAREN, WrapAlgo.HPACK, 13, 17, 18, []), + (NodeType.PARGGROUP, WrapAlgo.HPACK, 13, 18, 74, [ + (NodeType.ARGUMENT, WrapAlgo.HPACK, 13, 18, 36, []), + (NodeType.ARGUMENT, WrapAlgo.HPACK, 13, 37, 55, []), + (NodeType.ARGUMENT, WrapAlgo.HPACK, 13, 56, 74, []), + ]), + (NodeType.RPAREN, WrapAlgo.HPACK, 13, 74, 75, []), + (NodeType.COMMENT, WrapAlgo.HPACK, 14, 4, 79, []), + ]), ]), - (NodeType.STATEMENT, WrapAlgo.HPACK, 17, 0, 7, [ - (NodeType.FUNNAME, WrapAlgo.HPACK, 17, 0, 5, []), - (NodeType.LPAREN, WrapAlgo.HPACK, 17, 5, 6, []), - (NodeType.PARGGROUP, WrapAlgo.HPACK, 17, 6, 6, []), - (NodeType.RPAREN, WrapAlgo.HPACK, 17, 6, 7, []), + (NodeType.STATEMENT, WrapAlgo.HPACK, 16, 2, 9, [ + (NodeType.FUNNAME, WrapAlgo.HPACK, 16, 2, 7, []), + (NodeType.LPAREN, WrapAlgo.HPACK, 16, 7, 8, []), + (NodeType.RPAREN, WrapAlgo.HPACK, 16, 8, 9, []), ]), + ]), + ]), + (NodeType.STATEMENT, WrapAlgo.HPACK, 17, 0, 7, [ + (NodeType.FUNNAME, WrapAlgo.HPACK, 17, 0, 5, []), + (NodeType.LPAREN, WrapAlgo.HPACK, 17, 5, 6, []), + (NodeType.RPAREN, WrapAlgo.HPACK, 17, 6, 7, []), ]), + ]), ]), ]) @@ -427,72 +420,66 @@ def test_nested_parens(self): endif() """, [ # pylint: disable=bad-continuation +# noqa: E122 (NodeType.BODY, WrapAlgo.HPACK, 0, 0, 40, [ - (NodeType.FLOW_CONTROL, WrapAlgo.HPACK, 0, 0, 40, [ - (NodeType.STATEMENT, WrapAlgo.HPACK, 0, 0, 40, [ - (NodeType.FUNNAME, WrapAlgo.HPACK, 0, 0, 2, []), - (NodeType.LPAREN, WrapAlgo.HPACK, 0, 2, 3, []), - (NodeType.PARENGROUP, WrapAlgo.HPACK, 0, 3, 14, [ - (NodeType.LPAREN, WrapAlgo.HPACK, 0, 3, 4, []), - (NodeType.ARGGROUP, WrapAlgo.HPACK, 0, 4, 13, [ - (NodeType.PARGGROUP, WrapAlgo.HPACK, 0, 4, 13, [ - (NodeType.FLAG, WrapAlgo.HPACK, 0, 4, 7, []), - (NodeType.ARGUMENT, WrapAlgo.HPACK, 0, 8, 13, []), - ]), - ]), - (NodeType.RPAREN, WrapAlgo.HPACK, 0, 13, 14, []), - ]), - (NodeType.KWARGGROUP, WrapAlgo.HPACK, 0, 15, 39, [ - (NodeType.KEYWORD, WrapAlgo.HPACK, 0, 15, 17, []), - (NodeType.ARGGROUP, WrapAlgo.HPACK, 0, 18, 39, [ - (NodeType.PARENGROUP, WrapAlgo.HPACK, 0, 18, 39, [ - (NodeType.LPAREN, WrapAlgo.HPACK, 0, 18, 19, []), - (NodeType.ARGGROUP, WrapAlgo.HPACK, 0, 19, 38, [ - (NodeType.PARGGROUP, WrapAlgo.HPACK, 0, 19, 38, [ - -(NodeType.FLAG, WrapAlgo.HPACK, 0, 19, 22, []), -(NodeType.FLAG, WrapAlgo.HPACK, 0, 23, 29, []), -(NodeType.ARGUMENT, WrapAlgo.HPACK, 0, 30, 38, []), - - ]), - ]), - (NodeType.RPAREN, WrapAlgo.HPACK, 0, 38, 39, []), - ]), - ]), - ]), - (NodeType.RPAREN, WrapAlgo.HPACK, 0, 39, 40, []), + (NodeType.FLOW_CONTROL, WrapAlgo.HPACK, 0, 0, 40, [ + (NodeType.STATEMENT, WrapAlgo.HPACK, 0, 0, 40, [ + (NodeType.FUNNAME, WrapAlgo.HPACK, 0, 0, 2, []), + (NodeType.LPAREN, WrapAlgo.HPACK, 0, 2, 3, []), + (NodeType.PARENGROUP, WrapAlgo.HPACK, 0, 3, 14, [ + (NodeType.LPAREN, WrapAlgo.HPACK, 0, 3, 4, []), + (NodeType.ARGGROUP, WrapAlgo.HPACK, 0, 4, 13, [ + (NodeType.FLAG, WrapAlgo.HPACK, 0, 4, 7, []), + (NodeType.ARGUMENT, WrapAlgo.HPACK, 0, 8, 13, []), ]), - (NodeType.BODY, WrapAlgo.HPACK, 1, 2, 39, [ - (NodeType.STATEMENT, WrapAlgo.HPACK, 1, 2, 39, [ - (NodeType.FUNNAME, WrapAlgo.HPACK, 1, 2, 9, []), - (NodeType.LPAREN, WrapAlgo.HPACK, 1, 9, 10, []), - (NodeType.KWARGGROUP, WrapAlgo.HPACK, 1, 10, 38, [ - (NodeType.KEYWORD, WrapAlgo.HPACK, 1, 10, 17, []), - (NodeType.PARGGROUP, WrapAlgo.HPACK, 1, 18, 38, [ - (NodeType.ARGUMENT, WrapAlgo.HPACK, 1, 18, 38, []), - ]), - ]), - (NodeType.RPAREN, WrapAlgo.HPACK, 1, 38, 39, []), - ]), - (NodeType.STATEMENT, WrapAlgo.HPACK, 2, 2, 19, [ - (NodeType.FUNNAME, WrapAlgo.HPACK, 2, 2, 5, []), - (NodeType.LPAREN, WrapAlgo.HPACK, 2, 5, 6, []), - (NodeType.PARGGROUP, WrapAlgo.HPACK, 2, 6, 12, [ - (NodeType.ARGUMENT, WrapAlgo.HPACK, 2, 6, 12, []), - ]), - (NodeType.PARGGROUP, WrapAlgo.HPACK, 2, 13, 18, [ - (NodeType.ARGUMENT, WrapAlgo.HPACK, 2, 13, 18, []), - ]), - (NodeType.RPAREN, WrapAlgo.HPACK, 2, 18, 19, []), + (NodeType.RPAREN, WrapAlgo.HPACK, 0, 13, 14, []), + ]), + (NodeType.KWARGGROUP, WrapAlgo.HPACK, 0, 15, 39, [ + (NodeType.KEYWORD, WrapAlgo.HPACK, 0, 15, 17, []), + (NodeType.ARGGROUP, WrapAlgo.HPACK, 0, 18, 39, [ + (NodeType.PARENGROUP, WrapAlgo.HPACK, 0, 18, 39, [ + (NodeType.LPAREN, WrapAlgo.HPACK, 0, 18, 19, []), + (NodeType.ARGGROUP, WrapAlgo.HPACK, 0, 19, 38, [ + (NodeType.FLAG, WrapAlgo.HPACK, 0, 19, 22, []), + (NodeType.FLAG, WrapAlgo.HPACK, 0, 23, 29, []), + (NodeType.ARGUMENT, WrapAlgo.HPACK, 0, 30, 38, []), ]), + (NodeType.RPAREN, WrapAlgo.HPACK, 0, 38, 39, []), + ]), ]), - (NodeType.STATEMENT, WrapAlgo.HPACK, 3, 0, 7, [ - (NodeType.FUNNAME, WrapAlgo.HPACK, 3, 0, 5, []), - (NodeType.LPAREN, WrapAlgo.HPACK, 3, 5, 6, []), - (NodeType.PARGGROUP, WrapAlgo.HPACK, 3, 6, 6, []), - (NodeType.RPAREN, WrapAlgo.HPACK, 3, 6, 7, []), + ]), + (NodeType.RPAREN, WrapAlgo.HPACK, 0, 39, 40, []), + ]), + (NodeType.BODY, WrapAlgo.HPACK, 1, 2, 39, [ + (NodeType.STATEMENT, WrapAlgo.HPACK, 1, 2, 39, [ + (NodeType.FUNNAME, WrapAlgo.HPACK, 1, 2, 9, []), + (NodeType.LPAREN, WrapAlgo.HPACK, 1, 9, 10, []), + (NodeType.KWARGGROUP, WrapAlgo.HPACK, 1, 10, 38, [ + (NodeType.KEYWORD, WrapAlgo.HPACK, 1, 10, 17, []), + (NodeType.PARGGROUP, WrapAlgo.HPACK, 1, 18, 38, [ + (NodeType.ARGUMENT, WrapAlgo.HPACK, 1, 18, 38, []), + ]), ]), + (NodeType.RPAREN, WrapAlgo.HPACK, 1, 38, 39, []), + ]), + (NodeType.STATEMENT, WrapAlgo.HPACK, 2, 2, 19, [ + (NodeType.FUNNAME, WrapAlgo.HPACK, 2, 2, 5, []), + (NodeType.LPAREN, WrapAlgo.HPACK, 2, 5, 6, []), + (NodeType.PARGGROUP, WrapAlgo.HPACK, 2, 6, 12, [ + (NodeType.ARGUMENT, WrapAlgo.HPACK, 2, 6, 12, []), + ]), + (NodeType.PARGGROUP, WrapAlgo.HPACK, 2, 13, 18, [ + (NodeType.ARGUMENT, WrapAlgo.HPACK, 2, 13, 18, []), + ]), + (NodeType.RPAREN, WrapAlgo.HPACK, 2, 18, 19, []), + ]), + ]), + (NodeType.STATEMENT, WrapAlgo.HPACK, 3, 0, 7, [ + (NodeType.FUNNAME, WrapAlgo.HPACK, 3, 0, 5, []), + (NodeType.LPAREN, WrapAlgo.HPACK, 3, 5, 6, []), + (NodeType.RPAREN, WrapAlgo.HPACK, 3, 6, 7, []), ]), + ]), ]), ]) @@ -621,37 +608,35 @@ def test_while(self): endwhile() """, [ # pylint: disable=bad-continuation -(NodeType.BODY, WrapAlgo.HPACK, 0, 0, 29, [ - (NodeType.FLOW_CONTROL, WrapAlgo.HPACK, 0, 0, 29, [ - (NodeType.STATEMENT, WrapAlgo.VPACK, 0, 0, 15, [ - (NodeType.FUNNAME, WrapAlgo.HPACK, 0, 0, 5, []), - (NodeType.LPAREN, WrapAlgo.HPACK, 0, 5, 6, []), - (NodeType.PARGGROUP, WrapAlgo.VPACK, 0, 6, 15, [ - (NodeType.ARGUMENT, WrapAlgo.HPACK, 0, 6, 15, []), - (NodeType.ARGUMENT, WrapAlgo.HPACK, 1, 6, 10, []), - (NodeType.ARGUMENT, WrapAlgo.HPACK, 2, 6, 11, []), - (NodeType.ARGUMENT, WrapAlgo.HPACK, 3, 6, 10, []), - ]), - (NodeType.RPAREN, WrapAlgo.HPACK, 3, 10, 11, []), - ]), - (NodeType.BODY, WrapAlgo.HPACK, 4, 2, 29, [ - (NodeType.STATEMENT, WrapAlgo.HPACK, 4, 2, 29, [ - (NodeType.FUNNAME, WrapAlgo.HPACK, 4, 2, 9, []), - (NodeType.LPAREN, WrapAlgo.HPACK, 4, 9, 10, []), - (NodeType.PARGGROUP, WrapAlgo.HPACK, 4, 10, 28, [ - (NodeType.ARGUMENT, WrapAlgo.HPACK, 4, 10, 15, []), - (NodeType.ARGUMENT, WrapAlgo.HPACK, 4, 16, 28, []), - ]), - (NodeType.RPAREN, WrapAlgo.HPACK, 4, 28, 29, []), - ]), - ]), - (NodeType.STATEMENT, WrapAlgo.HPACK, 5, 0, 10, [ - (NodeType.FUNNAME, WrapAlgo.HPACK, 5, 0, 8, []), - (NodeType.LPAREN, WrapAlgo.HPACK, 5, 8, 9, []), - (NodeType.PARGGROUP, WrapAlgo.HPACK, 5, 9, 9, []), - (NodeType.RPAREN, WrapAlgo.HPACK, 5, 9, 10, []), +# noqa: E122 +(NodeType.BODY, WrapAlgo.HPACK, 0, 0, 32, [ + (NodeType.FLOW_CONTROL, WrapAlgo.HPACK, 0, 0, 32, [ + (NodeType.STATEMENT, WrapAlgo.HPACK, 0, 0, 32, [ + (NodeType.FUNNAME, WrapAlgo.HPACK, 0, 0, 5, []), + (NodeType.LPAREN, WrapAlgo.HPACK, 0, 5, 6, []), + (NodeType.ARGUMENT, WrapAlgo.HPACK, 0, 6, 15, []), + (NodeType.ARGUMENT, WrapAlgo.HPACK, 0, 16, 20, []), + (NodeType.ARGUMENT, WrapAlgo.HPACK, 0, 21, 26, []), + (NodeType.ARGUMENT, WrapAlgo.HPACK, 0, 27, 31, []), + (NodeType.RPAREN, WrapAlgo.HPACK, 0, 31, 32, []), + ]), + (NodeType.BODY, WrapAlgo.HPACK, 1, 2, 29, [ + (NodeType.STATEMENT, WrapAlgo.HPACK, 1, 2, 29, [ + (NodeType.FUNNAME, WrapAlgo.HPACK, 1, 2, 9, []), + (NodeType.LPAREN, WrapAlgo.HPACK, 1, 9, 10, []), + (NodeType.PARGGROUP, WrapAlgo.HPACK, 1, 10, 28, [ + (NodeType.ARGUMENT, WrapAlgo.HPACK, 1, 10, 15, []), + (NodeType.ARGUMENT, WrapAlgo.HPACK, 1, 16, 28, []), ]), + (NodeType.RPAREN, WrapAlgo.HPACK, 1, 28, 29, []), + ]), + ]), + (NodeType.STATEMENT, WrapAlgo.HPACK, 2, 0, 10, [ + (NodeType.FUNNAME, WrapAlgo.HPACK, 2, 0, 8, []), + (NodeType.LPAREN, WrapAlgo.HPACK, 2, 8, 9, []), + (NodeType.RPAREN, WrapAlgo.HPACK, 2, 9, 10, []), ]), + ]), ]), ]) diff --git a/cmake_format/parse_funs.py b/cmake_format/parse_funs.py deleted file mode 100644 index fd1520c..0000000 --- a/cmake_format/parse_funs.py +++ /dev/null @@ -1,1371 +0,0 @@ -# pylint: disable=too-many-lines -""" -Statement parser functions -""" - -import logging - -from cmake_format import commands -from cmake_format import lexer -from cmake_format import parser -from cmake_format.parser import ( - consume_trailing_comment, - get_normalized_kwarg, - get_tag, - KwargBreaker, - NodeType, - parse_conditional, - parse_kwarg, - parse_positionals, - parse_shell_command, - parse_standard, - PositionalParser, - should_break, - StandardParser, - TreeNode, - WHITESPACE_TOKENS, -) - -logger = logging.getLogger("cmake_format") - - -def split_legacy_spec(cmdspec): - """ - Split a legacy specification object into pargs, kwargs, and flags - """ - kwargs = {} - for kwarg, subspec in cmdspec.items(): - if kwarg in cmdspec.flags: - continue - if kwarg in ("if", "elseif", "while"): - subparser = parser.parse_conditional - elif kwarg == "COMMAND": - subparser = parser.parse_shell_command - elif isinstance(subspec, parser.IMPLICIT_PARG_TYPES): - subparser = parser.PositionalParser(subspec, []) - elif isinstance(subspec, (commands.CommandSpec)): - subparser = get_legacy_parse(subspec) - else: - raise ValueError("Unexpected kwarg spec of type {}" - .format(type(subspec))) - kwargs[kwarg] = subparser - - return cmdspec.pargs, kwargs, cmdspec.flags - - -def get_legacy_parse(cmdspec): - """ - Construct a parse tree from a legacy command specification - """ - pargs, kwargs, flags = split_legacy_spec(cmdspec) - return parser.StandardParser(pargs, kwargs, flags) - - -def only_comments_and_whitespace_remain(tokens, breakstack): - skip_tokens = (lexer.TokenType.WHITESPACE, - lexer.TokenType.NEWLINE, - lexer.TokenType.COMMENT, - lexer.TokenType.BRACKET_COMMENT) - - for token in tokens: - if token.type in skip_tokens: - continue - elif should_break(token, breakstack): - return True - else: - return False - return True - - -def consume_whitespace_and_comments(tokens, tree): - """ - Consume any whitespace or comments that occur at the current depth - """ - # If it is a whitespace token then put it directly in the parse tree at - # the current depth - while tokens: - # If it is a whitespace token then put it directly in the parse tree at - # the current depth - if tokens[0].type in WHITESPACE_TOKENS: - tree.children.append(tokens.pop(0)) - continue - - # If it's a comment token not associated with an argument, then put it - # directly into the parse tree at the current depth - if tokens[0].type in (lexer.TokenType.COMMENT, - lexer.TokenType.BRACKET_COMMENT): - child = TreeNode(NodeType.COMMENT) - tree.children.append(child) - child.children.append(tokens.pop(0)) - continue - break - - -def parse_add_library(tokens, breakstack): - """ - :: - - add_library( [STATIC | SHARED | MODULE] - [EXCLUDE_FROM_ALL] - source1 [source2 ...]) - - :see: https://cmake.org/cmake/help/v3.0/command/add_library.html - """ - # pylint: disable=too-many-statements - - parsing_name = 1 - parsing_type = 2 - parsing_flag = 3 - parsing_sources = 4 - - tree = TreeNode(NodeType.ARGGROUP) - - # If it is a whitespace token then put it directly in the parse tree at - # the current depth - while tokens and tokens[0].type in WHITESPACE_TOKENS: - tree.children.append(tokens.pop(0)) - continue - - sortable = True - state_ = parsing_name - parg_group = None - src_group = None - active_depth = tree - - while tokens: - # This parse function breakson the first right paren, since parenthetical - # groups are not allowed. A parenthesis might exist in a filename, but - # if so that filename should be quoted so it wont show up as a RIGHT_PAREN - # token. - if tokens[0].type is lexer.TokenType.RIGHT_PAREN: - break - - # If it is a whitespace token then put it directly in the parse tree at - # the current depth - if tokens[0].type in WHITESPACE_TOKENS: - active_depth.children.append(tokens.pop(0)) - continue - - # If it's a comment token not associated with an argument, then put it - # directly into the parse tree at the current depth - if tokens[0].type in (lexer.TokenType.COMMENT, - lexer.TokenType.BRACKET_COMMENT): - if (state_ > parsing_name and - get_tag(tokens[0]) in ("unsort", "unsortable")): - sortable = False - child = TreeNode(NodeType.COMMENT) - active_depth.children.append(child) - child.children.append(tokens.pop(0)) - continue - - if state_ is parsing_name: - token = tokens.pop(0) - parg_group = TreeNode(NodeType.PARGGROUP) - active_depth = parg_group - tree.children.append(parg_group) - child = TreeNode(NodeType.ARGUMENT) - child.children.append(token) - consume_trailing_comment(child, tokens) - parg_group.children.append(child) - state_ += 1 - elif state_ is parsing_type: - if get_normalized_kwarg(tokens[0]) in ("STATIC", "SHARED", "MODULE"): - token = tokens.pop(0) - child = TreeNode(NodeType.FLAG) - child.children.append(token) - consume_trailing_comment(child, tokens) - parg_group.children.append(child) - state_ += 1 - elif state_ is parsing_flag: - if get_normalized_kwarg(tokens[0]) == "EXCLUDE_FROM_ALL": - token = tokens.pop(0) - child = TreeNode(NodeType.FLAG) - child.children.append(token) - consume_trailing_comment(child, tokens) - parg_group.children.append(child) - state_ += 1 - src_group = TreeNode(NodeType.PARGGROUP, sortable=sortable) - active_depth = src_group - tree.children.append(src_group) - elif state_ is parsing_sources: - token = tokens.pop(0) - child = TreeNode(NodeType.ARGUMENT) - child.children.append(token) - consume_trailing_comment(child, tokens) - src_group.children.append(child) - - if only_comments_and_whitespace_remain(tokens, breakstack): - active_depth = tree - - return tree - - - -def parse_add_executable(tokens, breakstack): - """ - :: - - add_executable( [WIN32] [MACOSX_BUNDLE] - [EXCLUDE_FROM_ALL] - [source1] [source2 ...]) - - :see: https://cmake.org/cmake/help/latest/command/add_executable.html#command:add_executable - """ - # pylint: disable=too-many-statements - - parsing_name = 1 - parsing_flags = 2 - parsing_sources = 3 - - tree = TreeNode(NodeType.ARGGROUP) - - # If it is a whitespace token then put it directly in the parse tree at - # the current depth - while tokens and tokens[0].type in WHITESPACE_TOKENS: - tree.children.append(tokens.pop(0)) - continue - - sortable = True - state_ = parsing_name - parg_group = None - src_group = None - active_depth = tree - - while tokens: - # This parse function breaks on the first right paren, since parenthetical - # groups are not allowed. A parenthesis might exist in a filename, but - # if so that filename should be quoted so it wont show up as a RIGHT_PAREN - # token. - if tokens[0].type is lexer.TokenType.RIGHT_PAREN: - break - - # If it is a whitespace token then put it directly in the parse tree at - # the current depth - if tokens[0].type in WHITESPACE_TOKENS: - active_depth.children.append(tokens.pop(0)) - continue - - # If it's a comment token not associated with an argument, then put it - # directly into the parse tree at the current depth - if tokens[0].type in (lexer.TokenType.COMMENT, - lexer.TokenType.BRACKET_COMMENT): - if (state_ > parsing_name and - get_tag(tokens[0]) in ("unsort", "unsortable")): - sortable = False - child = TreeNode(NodeType.COMMENT) - active_depth.children.append(child) - child.children.append(tokens.pop(0)) - continue - - if state_ is parsing_name: - token = tokens.pop(0) - parg_group = TreeNode(NodeType.PARGGROUP) - active_depth = parg_group - tree.children.append(parg_group) - child = TreeNode(NodeType.ARGUMENT) - child.children.append(token) - consume_trailing_comment(child, tokens) - parg_group.children.append(child) - state_ += 1 - elif state_ is parsing_flags: - if get_normalized_kwarg(tokens[0]) in ( - "WIN32", "MACOSX_BUNDLE", "EXCLUDE_FROM_ALL"): - token = tokens.pop(0) - child = TreeNode(NodeType.FLAG) - child.children.append(token) - consume_trailing_comment(child, tokens) - parg_group.children.append(child) - else: - state_ += 1 - src_group = TreeNode(NodeType.PARGGROUP, sortable=sortable) - active_depth = src_group - tree.children.append(src_group) - elif state_ is parsing_sources: - token = tokens.pop(0) - child = TreeNode(NodeType.ARGUMENT) - child.children.append(token) - consume_trailing_comment(child, tokens) - src_group.children.append(child) - - if only_comments_and_whitespace_remain(tokens, breakstack): - active_depth = tree - - return tree - - -def parse_install_targets_sub(tokens, breakstack): - """ - Parse the inner kwargs of an ``install(TARGETS)`` command. This is common - logic for ARCHIVE, LIBRARY, RUNTIME, etc. - :see: https://cmake.org/cmake/help/v3.14/command/install.html#targets - """ - return parse_standard( - tokens, - npargs='*', - kwargs={ - "DESTINATION": PositionalParser(1), - "PERMISSIONS": PositionalParser('+'), - "CONFIGURATIONS": PositionalParser('+'), - "COMPONENT": PositionalParser(1), - "NAMELINK_COMPONENT": PositionalParser(1), - }, - flags=[ - "OPTIONAL", - "EXCLUDE_FROM_ALL", - "NAMELINK_ONLY", - "NAMELINK_SKIP" - ], - breakstack=breakstack) - - -def parse_install_targets(tokens, breakstack): - """ - :: - - install(TARGETS targets... [EXPORT ] - [[ARCHIVE|LIBRARY|RUNTIME|OBJECTS|FRAMEWORK|BUNDLE| - PRIVATE_HEADER|PUBLIC_HEADER|RESOURCE] - [DESTINATION ] - [PERMISSIONS permissions...] - [CONFIGURATIONS [Debug|Release|...]] - [COMPONENT ] - [NAMELINK_COMPONENT ] - [OPTIONAL] [EXCLUDE_FROM_ALL] - [NAMELINK_ONLY|NAMELINK_SKIP] - ] [...] - [INCLUDES DESTINATION [ ...]] - ) - - :see: https://cmake.org/cmake/help/v3.14/command/install.html#targets - """ - kwargs = { - "TARGETS": PositionalParser('+'), - "EXPORT": PositionalParser(1), - "INCLUDES": PositionalParser('+', flags=["DESTINATION"]) - } - for subkey in ("ARCHIVE", "LIBRARY", "RUNTIME", "OBJECTS", "FRAMEWORK", - "BUNDLE", "PRIVATE_HEADER", "PUBLIC_HEADER", "RESOURCE"): - kwargs[subkey] = parse_install_targets_sub - - return parse_standard( - tokens, - npargs='*', - kwargs=kwargs, - flags=[], - breakstack=breakstack) - - -def parse_install_files(tokens, breakstack): - """ - :: - install( files... - TYPE | DESTINATION - [PERMISSIONS permissions...] - [CONFIGURATIONS [Debug|Release|...]] - [COMPONENT ] - [RENAME ] [OPTIONAL] [EXCLUDE_FROM_ALL]) - - :see: https://cmake.org/cmake/help/v3.14/command/install.html#files - """ - return parse_standard( - tokens, - npargs='*', - kwargs={ - "FILES": PositionalParser('+'), - "PROGRAMS": PositionalParser('+'), - "TYPE": PositionalParser(1), - "DESTINATION": PositionalParser(1), - "PERMISSIONS": PositionalParser('+'), - "CONFIGURATIONS": PositionalParser('+'), - "COMPONENT": PositionalParser(1), - "RENAME": PositionalParser(1), - }, - flags=[ - "OPTIONAL", - "EXCLUDE_FROM_ALL", - ], - breakstack=breakstack) - - -def parse_install_directory(tokens, breakstack): - """ - :: - - install(DIRECTORY dirs... - TYPE | DESTINATION - [FILE_PERMISSIONS permissions...] - [DIRECTORY_PERMISSIONS permissions...] - [USE_SOURCE_PERMISSIONS] [OPTIONAL] [MESSAGE_NEVER] - [CONFIGURATIONS [Debug|Release|...]] - [COMPONENT ] [EXCLUDE_FROM_ALL] - [FILES_MATCHING] - [[PATTERN | REGEX ] - [EXCLUDE] [PERMISSIONS permissions...]] [...]) - - :see: https://cmake.org/cmake/help/v3.14/command/install.html#directory - """ - return parse_standard( - tokens, - npargs='*', - kwargs={ - "DIRECTORY": PositionalParser('+'), - "TYPE": PositionalParser(1), - "DESTINATION": PositionalParser(1), - "FILE_PERMISSIONS": PositionalParser('+'), - "DIRECTORY_PERMISSIONS": PositionalParser('+'), - "CONFIGURATIONS": PositionalParser('+'), - "COMPONENT": PositionalParser(1), - "RENAME": PositionalParser(1), - "PATTERN": parse_pattern, - "REGEX": parse_pattern, - }, - flags=[ - "USER_SOURCE_PERMISSIONS", - "OPTIONAL", - "MESSAGE_NEVER", - "FILES_MATCHING", - ], - breakstack=breakstack) - - -def parse_install_script(tokens, breakstack): - """ - :: - - install([[SCRIPT ] [CODE ]] - [COMPONENT ] [EXCLUDE_FROM_ALL] [...]) - - :see: https://cmake.org/cmake/help/v3.14/command/install.html#custom-installation-logic - """ - return parse_standard( - tokens, - npargs='*', - kwargs={ - "SCRIPT": PositionalParser(1), - "CODE": PositionalParser(1), - "COMPONENT": PositionalParser(1), - }, - flags=[ - "EXCLUDE_FROM_ALL" - ], - breakstack=breakstack) - - -def parse_install_export(tokens, breakstack): - """ - :: - - install(EXPORT DESTINATION - [NAMESPACE ] [[FILE .cmake]| - [PERMISSIONS permissions...] - [CONFIGURATIONS [Debug|Release|...]] - [EXPORT_LINK_INTERFACE_LIBRARIES] - [COMPONENT ] - [EXCLUDE_FROM_ALL]) - - :see: https://cmake.org/cmake/help/v3.14/command/install.html#installing-exports - """ - return parse_standard( - tokens, - npargs='*', - kwargs={ - "EXPORT": PositionalParser(1), - "DESTINATION": PositionalParser(1), - "NAMESPACE": PositionalParser(1), - "FILE": PositionalParser(1), - "PERMISSIONS": PositionalParser('+'), - "CONFIGURATIONS": PositionalParser('+'), - "COMPONENT": PositionalParser(1), - }, - flags=[ - "EXCLUDE_FROM_ALL" - ], - breakstack=breakstack) - - -def get_first_semantic_token(tokens): - """ - Return the first token with semantic meaning - """ - skip_tokens = (lexer.TokenType.WHITESPACE, - lexer.TokenType.NEWLINE, - lexer.TokenType.COMMENT, - lexer.TokenType.BRACKET_COMMENT) - - for token in tokens: - if token.type in skip_tokens: - continue - return token - return None - - -def parse_install(tokens, breakstack): - """ - The ``install()`` command has multiple different forms, implemented - by different functions. The forms are indicated by the first token - and are: - - * TARGETS - * FILES - * DIRECTORY - * SCRIPT - * CODE - * EXPORT - - :see: https://cmake.org/cmake/help/v3.0/command/install.html - """ - - descriminator_token = get_first_semantic_token(tokens) - if descriminator_token is None: - logger.warning("Invalid install() command at %s", tokens[0].get_location()) - return parse_standard(tokens, npargs='*', kwargs={}, flags=[], - breakstack=breakstack) - - descriminator = descriminator_token.spelling.upper() - parsemap = { - "TARGETS": parse_install_targets, - "FILES": parse_install_files, - "PROGRAMS": parse_install_files, - "DIRECTORY": parse_install_directory, - "SCRIPT": parse_install_script, - "CODE": parse_install_script, - "EXPORT": parse_install_export - } - if not descriminator in parsemap: - logger.warning("Invalid install form \"%s\" at %s", descriminator, - tokens[0].location()) - return parse_standard(tokens, npargs='*', kwargs={}, flags=[], - breakstack=breakstack) - - return parsemap[descriminator](tokens, breakstack) - - -def parse_file_read(tokens, breakstack): - """ - :: - - file(READ - [OFFSET ] [LIMIT ] [HEX]) - - :see: https://cmake.org/cmake/help/v3.14/command/file.html#read - """ - - return parse_standard( - tokens, - npargs='*', - kwargs={ - "OFFSET", PositionalParser(1), - "LIMIT", PositionalParser(1), - }, - flags=[ - "READ", - "HEX" - ], - breakstack=breakstack) - - -def parse_file_strings(tokens, breakstack): - """ - :: - - file(STRINGS [...]) - - :see: https://cmake.org/cmake/help/v3.14/command/file.html#read - """ - - return parse_standard( - tokens, - npargs='*', - kwargs={ - "LENGTH_MAXIMUM", PositionalParser(1), - "LENGTH_MINIMUM", PositionalParser(1), - "LIMIT_COUNT", PositionalParser(1), - "LIMIT_INPUT", PositionalParser(1), - "LIMIT_OUTPUT", PositionalParser(1), - "REGEX", PositionalParser(1), - "ENCODING", PositionalParser(1, flags=[ - "UTF-8", "UTF-16LE", "UTF-16BE", "UTF-32LE", "UTF-32BE" - ]), - }, - flags=[ - "STRINGS", - "NEWLINE_CONSUME", - "NO_HEX_CONVERSION", - - ], - breakstack=breakstack) - - -HASH_STRINGS = [ - "MD5", - "SHA1", - "SHA224", - "SHA256", - "SHA384", - "SHA512", - "SHA3_224", - "SHA3_256", - "SHA3_384", - "SHA3_512", -] - - -def parse_file_hash(tokens, breakstack): - """ - :: - - file( ) - - :see: https://cmake.org/cmake/help/v3.14/command/file.html#strings - """ - - return parse_standard( - tokens, - npargs=3, - kwargs={}, - flags=HASH_STRINGS, - breakstack=breakstack) - - -def parse_file_timestamp(tokens, breakstack): - """ - :: - - file(TIMESTAMP [] [UTC]) - - :see: https://cmake.org/cmake/help/v3.14/command/file.html#strings - """ - - return parse_standard( - tokens, - npargs='+', - kwargs={}, - flags=["TIMESTAMP", "UTC"], - breakstack=breakstack) - - -def parse_file_write(tokens, breakstack): - """ - :: - - file(WRITE ...) - file(APPEND ...) - - :see: https://cmake.org/cmake/help/v3.14/command/file.html#writing - """ - tree = TreeNode(NodeType.ARGGROUP) - consume_whitespace_and_comments(tokens, tree) - tree.children.append( - parse_positionals(tokens, 2, ["WRITE", "APPEND"], breakstack)) - consume_whitespace_and_comments(tokens, tree) - tree.children.append( - parse_positionals(tokens, '+', [], breakstack)) - - return tree - - -def parse_file_generate_output(tokens, breakstack): - """ - :: - - file(GENERATE OUTPUT output-file - - [CONDITION expression]) - - :see: https://cmake.org/cmake/help/v3.14/command/file.html#writing - """ - - return parse_standard( - tokens, - npargs='1', - kwargs={ - "OUTPUT": PositionalParser(1), - "INPUT": PositionalParser(1), - "CONTENT": PositionalParser('+'), - "CONDITION": parse_conditional, - }, - flags=["GENERATE"], - breakstack=breakstack) - - -def parse_file_glob(tokens, breakstack): - """ - :: - - file(GLOB - [LIST_DIRECTORIES true|false] [RELATIVE ] [CONFIGURE_DEPENDS] - [...]) - file(GLOB_RECURSE [FOLLOW_SYMLINKS] - [LIST_DIRECTORIES true|false] [RELATIVE ] [CONFIGURE_DEPENDS] - [...]) - :see: https://cmake.org/cmake/help/v3.14/command/file.html#filesystem - """ - - return parse_standard( - tokens, - npargs='+', - kwargs={ - "LIST_DIRECTORIES": PositionalParser(1), - "RELATIVE": PositionalParser(1) - }, - flags=[ - "GLOB", - "GLOB_RECURSE", - "CONFIGURE_DEPENDS", - "FOLLOW_SYMLINKS"], - breakstack=breakstack) - - -def parse_pattern(tokens, breakstack): - """ - :: - - [PATTERN | REGEX ] - [EXCLUDE] [PERMISSIONS ...] - """ - return parse_standard( - tokens, - npargs='+', - kwargs={"PERMISSIONS": PositionalParser('+'), }, - flags=["EXCLUDE"], - breakstack=breakstack - ) - - -def parse_file_copy(tokens, breakstack): - """ - :: - - file( ... DESTINATION - [FILE_PERMISSIONS ...] - [DIRECTORY_PERMISSIONS ...] - [NO_SOURCE_PERMISSIONS] [USE_SOURCE_PERMISSIONS] - [FILES_MATCHING] - [[PATTERN | REGEX ] - [EXCLUDE] [PERMISSIONS ...]] [...]) - - :see: https://cmake.org/cmake/help/v3.14/command/file.html#filesystem - """ - - return parse_standard( - tokens, - npargs='+', - kwargs={ - "DESTINATION": PositionalParser(1), - "FILE_PERMISSIONS": PositionalParser('+'), - "DIRECTORY_PERMISSIONS": PositionalParser('+'), - "PATTERN": parse_pattern, - "REGEX": parse_pattern, - }, - flags=[ - "COPY", - "INSTALL", - "NO_SOURCE_PERMISSIONS", - "USE_SOURCE_PERMISSIONS", - "FILES_MATCHING", - ], - breakstack=breakstack) - - -def parse_file_create_link(tokens, breakstack): - """ - :: - - file(CREATE_LINK - [RESULT ] [COPY_ON_ERROR] [SYMBOLIC]) - - :see: https://cmake.org/cmake/help/v3.14/command/file.html#filesystem - """ - - return parse_standard( - tokens, - npargs='+', - kwargs={ - "RESULT": PositionalParser(1), - }, - flags=[ - "COPY_ON_ERROR", - "SYMBOLIC", - ], - breakstack=breakstack) - - -def parse_file_xfer(tokens, breakstack): - """ - :: - - file(DOWNLOAD [...]) - file(UPLOAD [...]) - - :see: https://cmake.org/cmake/help/v3.14/command/file.html#transfer - """ - - return parse_standard( - tokens, - npargs='3', - kwargs={ - "INACTIVITY_TIMEOUT": PositionalParser(1), - "LOG": PositionalParser(1), - "STATUS": PositionalParser(1), - "TIMEOUT": PositionalParser(1), - "USERPWD": PositionalParser(1), - "HTTPHEADER": PositionalParser(1), - "NETRC": PositionalParser( - 1, flags=["CMAKE_NETRC", "IGNORED", "OPTIONAL", "REQUIRED"]), - "NETRC_FILE": PositionalParser(1), - "EXPECTED_HASH": PositionalParser(1), - "EXPECTED_MD5": PositionalParser(1), - "TLS_VERIFY": PositionalParser(1), - "TLS_CAINFO": PositionalParser(1), - }, - flags=[ - "DOWNLOAD", - "UPLOAD", - "SHOW_PROGRESS", - - ], - breakstack=breakstack) - - -def parse_file_lock(tokens, breakstack): - """ - :: - - file(LOCK [DIRECTORY] [RELEASE] - [GUARD ] - [RESULT_VARIABLE ] - [TIMEOUT ]) - - :see: https://cmake.org/cmake/help/v3.14/command/file.html#locking - """ - - return parse_standard( - tokens, - npargs='+', - kwargs={ - "GUARD": PositionalParser(1, flags=["FUNCTION", "FILE", "PROCESS"]), - "RESULT_VARIABLE": PositionalParser(1), - "TIMEOUT": PositionalParser(1) - }, - flags=[ - "LOCK", - "DIRECTORY", - "RELEASE", - ], - breakstack=breakstack) - - -def parse_file(tokens, breakstack): - """ - The ``file()`` command has a lot of different forms, depending on the first - argument. This function just dispatches the correct parse implementation for - the given form:: - - Reading - file(READ [...]) - file(STRINGS [...]) - file( ) - file(TIMESTAMP [...]) - - Writing - file({WRITE | APPEND} ...) - file({TOUCH | TOUCH_NOCREATE} [...]) - file(GENERATE OUTPUT [...]) - - Filesystem - file({GLOB | GLOB_RECURSE} [...] [...]) - file(RENAME ) - file({REMOVE | REMOVE_RECURSE } [...]) - file(MAKE_DIRECTORY [...]) - file({COPY | INSTALL} ... DESTINATION [...]) - file(SIZE ) - file(READ_SYMLINK ) - file(CREATE_LINK [...]) - - Path Conversion - file(RELATIVE_PATH ) - file({TO_CMAKE_PATH | TO_NATIVE_PATH} ) - - Transfer - file(DOWNLOAD [...]) - file(UPLOAD [...]) - - Locking - file(LOCK [...]) - - :see: https://cmake.org/cmake/help/v3.14/command/file.html - """ - - descriminator_token = get_first_semantic_token(tokens) - if descriminator_token is None: - logger.warning("Invalid empty file() command at %s", - tokens[0].get_location()) - return parse_standard(tokens, npargs='*', kwargs={}, flags=[], - breakstack=breakstack) - - descriminator = descriminator_token.spelling.upper() - parsemap = { - "READ": parse_file_read, - "STRINGS": parse_file_strings, - "TIMESTAMP": parse_file_timestamp, - "WRITE": parse_file_write, - "APPEND": parse_file_write, - "TOUCH": PositionalParser('+', ["TOUCH"]), - "TOUCH_NO_CREATE": PositionalParser('+', ["TOUCH_NO_CREATE"]), - "GLOB": parse_file_glob, - "GLOB_RECURSE": parse_file_glob, - "RENAME": PositionalParser(3, ["RENAME"]), - "REMOVE": PositionalParser('+', ["REMOVE"]), - "REMOVE_RECURSE": PositionalParser('+', ["REMOVE_RECURSE"]), - "MAKE_DIRECTORY": PositionalParser('+', ["MAKE_DIRECTORY"]), - "COPY": parse_file_copy, - "INSTALL": parse_file_copy, - "SIZE": PositionalParser(3, ["SIZE"]), - "READ_SYMLINK": PositionalParser(3, ["READ_SYMLINK"]), - "CREATE_LINK": parse_file_create_link, - "RELATIVE_PATH": PositionalParser(4, ["RELATIVE_PATH"]), - "TO_CMAKE_PATH": PositionalParser(3, ["TO_CMAKE_PATH"]), - "TO_NATIVE_PATH": PositionalParser(3, ["TO_NATIVE_PATH"]), - "DOWNLOAD": parse_file_xfer, - "UPLOAD": parse_file_xfer, - "LOCK": parse_file_lock - } - for hashname in HASH_STRINGS: - parsemap[hashname] = parse_file_hash - - if not descriminator in parsemap: - logger.warning("Invalid file() form \"%s\" at %s", descriminator, - tokens[0].location()) - return parse_standard(tokens, npargs='*', kwargs={}, flags=[], - breakstack=breakstack) - - return parsemap[descriminator](tokens, breakstack) - - -def parse_external_project_add(tokens, breakstack): - """ - :: - - ExternalProject_Add( [